< prev index next >

src/java.desktop/share/native/liblcms/cmsopt.c

Print this page

 195 static
 196 cmsBool CloseEnoughFloat(cmsFloat64Number a, cmsFloat64Number b)
 197 {
 198        return fabs(b - a) < 0.00001f;
 199 }
 200 
 201 static
 202 cmsBool  isFloatMatrixIdentity(const cmsMAT3* a)
 203 {
 204        cmsMAT3 Identity;
 205        int i, j;
 206 
 207        _cmsMAT3identity(&Identity);
 208 
 209        for (i = 0; i < 3; i++)
 210               for (j = 0; j < 3; j++)
 211                      if (!CloseEnoughFloat(a->v[i].n[j], Identity.v[i].n[j])) return FALSE;
 212 
 213        return TRUE;
 214 }

 215 // if two adjacent matrices are found, multiply them.
 216 static
 217 cmsBool _MultiplyMatrix(cmsPipeline* Lut)
 218 {
 219        cmsStage** pt1;
 220        cmsStage** pt2;
 221        cmsStage*  chain;
 222        cmsBool AnyOpt = FALSE;
 223 
 224        pt1 = &Lut->Elements;
 225        if (*pt1 == NULL) return AnyOpt;
 226 
 227        while (*pt1 != NULL) {
 228 
 229               pt2 = &((*pt1)->Next);
 230               if (*pt2 == NULL) return AnyOpt;
 231 
 232               if ((*pt1)->Implements == cmsSigMatrixElemType && (*pt2)->Implements == cmsSigMatrixElemType) {
 233 
 234                      // Get both matrices

1125 
1126     for (t = 0; t < OriginalLut ->InputChannels; t++) {
1127         Trans[t] = cmsBuildTabulatedToneCurve16(OriginalLut ->ContextID, PRELINEARIZATION_POINTS, NULL);
1128         if (Trans[t] == NULL) goto Error;
1129     }
1130 
1131     // Populate the curves
1132     for (i=0; i < PRELINEARIZATION_POINTS; i++) {
1133 
1134         v = (cmsFloat32Number) ((cmsFloat64Number) i / (PRELINEARIZATION_POINTS - 1));
1135 
1136         // Feed input with a gray ramp
1137         for (t=0; t < OriginalLut ->InputChannels; t++)
1138             In[t] = v;
1139 
1140         // Evaluate the gray value
1141         cmsPipelineEvalFloat(In, Out, OriginalLut);
1142 
1143         // Store result in curve
1144         for (t=0; t < OriginalLut ->InputChannels; t++)
1145             Trans[t] ->Table16[i] = _cmsQuickSaturateWord(Out[t] * 65535.0);



1146     }
1147 
1148     // Slope-limit the obtained curves
1149     for (t = 0; t < OriginalLut ->InputChannels; t++)
1150         SlopeLimiting(Trans[t]);
1151 
1152     // Check for validity
1153     lIsSuitable = TRUE;
1154     lIsLinear   = TRUE;
1155     for (t=0; (lIsSuitable && (t < OriginalLut ->InputChannels)); t++) {
1156 
1157         // Exclude if already linear
1158         if (!cmsIsToneCurveLinear(Trans[t]))
1159             lIsLinear = FALSE;
1160 
1161         // Exclude if non-monotonic
1162         if (!cmsIsToneCurveMonotonic(Trans[t]))
1163             lIsSuitable = FALSE;
1164 
1165         if (IsDegenerated(Trans[t]))
1166             lIsSuitable = FALSE;
1167     }
1168 
1169     // If it is not suitable, just quit
1170     if (!lIsSuitable) goto Error;
1171 
1172     // Invert curves if possible

1736 
1737               // Only 2nd matrix has offset, or it is zero
1738               Offset = Data2->Offset;
1739 
1740               // Now the result is in res + Data2 -> Offset. Maybe is a plain identity?
1741               if (_cmsMAT3isIdentity(&res) && Offset == NULL) {
1742 
1743                      // We can get rid of full matrix
1744                      IdentityMat = TRUE;
1745               }
1746 
1747        }
1748        else {
1749 
1750               if (cmsPipelineCheckAndRetreiveStages(Src, 3,
1751                      cmsSigCurveSetElemType, cmsSigMatrixElemType, cmsSigCurveSetElemType,
1752                      &Curve1, &Matrix1, &Curve2)) {
1753 
1754                      _cmsStageMatrixData* Data = (_cmsStageMatrixData*)cmsStageData(Matrix1);
1755 


1756                      // Copy the matrix to our result
1757                      memcpy(&res, Data->Double, sizeof(res));
1758 
1759                      // Preserve the Odffset (may be NULL as a zero offset)
1760                      Offset = Data->Offset;
1761 
1762                      if (_cmsMAT3isIdentity(&res) && Offset == NULL) {
1763 
1764                             // We can get rid of full matrix
1765                             IdentityMat = TRUE;
1766                      }
1767               }
1768               else
1769                      return FALSE; // Not optimizeable this time
1770 
1771        }
1772 
1773       // Allocate an empty LUT
1774     Dest =  cmsPipelineAlloc(Src ->ContextID, Src ->InputChannels, Src ->OutputChannels);
1775     if (!Dest) return FALSE;

1780 
1781     if (!IdentityMat) {
1782 
1783            if (!cmsPipelineInsertStage(Dest, cmsAT_END, cmsStageAllocMatrix(Dest->ContextID, 3, 3, (const cmsFloat64Number*)&res, Offset)))
1784                   goto Error;
1785     }
1786 
1787     if (!cmsPipelineInsertStage(Dest, cmsAT_END, cmsStageDup(Curve2)))
1788         goto Error;
1789 
1790     // If identity on matrix, we can further optimize the curves, so call the join curves routine
1791     if (IdentityMat) {
1792 
1793         OptimizeByJoiningCurves(&Dest, Intent, InputFormat, OutputFormat, dwFlags);
1794     }
1795     else {
1796         _cmsStageToneCurvesData* mpeC1 = (_cmsStageToneCurvesData*) cmsStageData(Curve1);
1797         _cmsStageToneCurvesData* mpeC2 = (_cmsStageToneCurvesData*) cmsStageData(Curve2);
1798 
1799         // In this particular optimization, cache does not help as it takes more time to deal with
1800         // the cache that with the pixel handling
1801         *dwFlags |= cmsFLAGS_NOCACHE;
1802 
1803         // Setup the optimizarion routines
1804         SetMatShaper(Dest, mpeC1 ->TheCurves, &res, (cmsVEC3*) Offset, mpeC2->TheCurves, OutputFormat);
1805     }
1806 
1807     cmsPipelineFree(Src);
1808     *Lut = Dest;
1809     return TRUE;
1810 Error:
1811     // Leave Src unchanged
1812     cmsPipelineFree(Dest);
1813     return FALSE;
1814 }
1815 
1816 
1817 // -------------------------------------------------------------------------------------------------------------------------------------
1818 // Optimization plug-ins
1819 
1820 // List of optimizations

1937     cmsBool AnySuccess = FALSE;
1938     cmsStage* mpe;
1939 
1940     // A CLUT is being asked, so force this specific optimization
1941     if (*dwFlags & cmsFLAGS_FORCE_CLUT) {
1942 
1943         PreOptimize(*PtrLut);
1944         return OptimizeByResampling(PtrLut, Intent, InputFormat, OutputFormat, dwFlags);
1945     }
1946 
1947     // Anything to optimize?
1948     if ((*PtrLut) ->Elements == NULL) {
1949         _cmsPipelineSetOptimizationParameters(*PtrLut, FastIdentity16, (void*) *PtrLut, NULL, NULL);
1950         return TRUE;
1951     }
1952 
1953     // Named color pipelines cannot be optimized
1954     for (mpe = cmsPipelineGetPtrToFirstStage(*PtrLut);
1955         mpe != NULL;
1956         mpe = cmsStageNext(mpe)) {
1957         if (cmsStageType(mpe) == cmsSigNamedColorElemType) return FALSE;
1958     }
1959 
1960     // Try to get rid of identities and trivial conversions.
1961     AnySuccess = PreOptimize(*PtrLut);
1962 
1963     // After removal do we end with an identity?
1964     if ((*PtrLut) ->Elements == NULL) {
1965         _cmsPipelineSetOptimizationParameters(*PtrLut, FastIdentity16, (void*) *PtrLut, NULL, NULL);
1966         return TRUE;
1967     }
1968 
1969     // Do not optimize, keep all precision
1970     if (*dwFlags & cmsFLAGS_NOOPTIMIZE)
1971         return FALSE;
1972 
1973     // Try plug-in optimizations
1974     for (Opts = ctx->OptimizationCollection;
1975          Opts != NULL;
1976          Opts = Opts ->Next) {
1977 

 195 static
 196 cmsBool CloseEnoughFloat(cmsFloat64Number a, cmsFloat64Number b)
 197 {
 198        return fabs(b - a) < 0.00001f;
 199 }
 200 
 201 static
 202 cmsBool  isFloatMatrixIdentity(const cmsMAT3* a)
 203 {
 204        cmsMAT3 Identity;
 205        int i, j;
 206 
 207        _cmsMAT3identity(&Identity);
 208 
 209        for (i = 0; i < 3; i++)
 210               for (j = 0; j < 3; j++)
 211                      if (!CloseEnoughFloat(a->v[i].n[j], Identity.v[i].n[j])) return FALSE;
 212 
 213        return TRUE;
 214 }
 215 
 216 // if two adjacent matrices are found, multiply them.
 217 static
 218 cmsBool _MultiplyMatrix(cmsPipeline* Lut)
 219 {
 220        cmsStage** pt1;
 221        cmsStage** pt2;
 222        cmsStage*  chain;
 223        cmsBool AnyOpt = FALSE;
 224 
 225        pt1 = &Lut->Elements;
 226        if (*pt1 == NULL) return AnyOpt;
 227 
 228        while (*pt1 != NULL) {
 229 
 230               pt2 = &((*pt1)->Next);
 231               if (*pt2 == NULL) return AnyOpt;
 232 
 233               if ((*pt1)->Implements == cmsSigMatrixElemType && (*pt2)->Implements == cmsSigMatrixElemType) {
 234 
 235                      // Get both matrices

1126 
1127     for (t = 0; t < OriginalLut ->InputChannels; t++) {
1128         Trans[t] = cmsBuildTabulatedToneCurve16(OriginalLut ->ContextID, PRELINEARIZATION_POINTS, NULL);
1129         if (Trans[t] == NULL) goto Error;
1130     }
1131 
1132     // Populate the curves
1133     for (i=0; i < PRELINEARIZATION_POINTS; i++) {
1134 
1135         v = (cmsFloat32Number) ((cmsFloat64Number) i / (PRELINEARIZATION_POINTS - 1));
1136 
1137         // Feed input with a gray ramp
1138         for (t=0; t < OriginalLut ->InputChannels; t++)
1139             In[t] = v;
1140 
1141         // Evaluate the gray value
1142         cmsPipelineEvalFloat(In, Out, OriginalLut);
1143 
1144         // Store result in curve
1145         for (t=0; t < OriginalLut ->InputChannels; t++)
1146         {
1147             if (Trans[t]->Table16 != NULL)
1148                 Trans[t] ->Table16[i] = _cmsQuickSaturateWord(Out[t] * 65535.0);
1149         }
1150     }
1151 
1152     // Slope-limit the obtained curves
1153     for (t = 0; t < OriginalLut ->InputChannels; t++)
1154         SlopeLimiting(Trans[t]);
1155 
1156     // Check for validity. lIsLinear is here for debug purposes
1157     lIsSuitable = TRUE;
1158     lIsLinear   = TRUE;
1159     for (t=0; (lIsSuitable && (t < OriginalLut ->InputChannels)); t++) {
1160 
1161         // Exclude if already linear
1162         if (!cmsIsToneCurveLinear(Trans[t]))
1163             lIsLinear = FALSE;
1164 
1165         // Exclude if non-monotonic
1166         if (!cmsIsToneCurveMonotonic(Trans[t]))
1167             lIsSuitable = FALSE;
1168 
1169         if (IsDegenerated(Trans[t]))
1170             lIsSuitable = FALSE;
1171     }
1172 
1173     // If it is not suitable, just quit
1174     if (!lIsSuitable) goto Error;
1175 
1176     // Invert curves if possible

1740 
1741               // Only 2nd matrix has offset, or it is zero
1742               Offset = Data2->Offset;
1743 
1744               // Now the result is in res + Data2 -> Offset. Maybe is a plain identity?
1745               if (_cmsMAT3isIdentity(&res) && Offset == NULL) {
1746 
1747                      // We can get rid of full matrix
1748                      IdentityMat = TRUE;
1749               }
1750 
1751        }
1752        else {
1753 
1754               if (cmsPipelineCheckAndRetreiveStages(Src, 3,
1755                      cmsSigCurveSetElemType, cmsSigMatrixElemType, cmsSigCurveSetElemType,
1756                      &Curve1, &Matrix1, &Curve2)) {
1757 
1758                      _cmsStageMatrixData* Data = (_cmsStageMatrixData*)cmsStageData(Matrix1);
1759 
1760                      if (Matrix1->InputChannels != 3 || Matrix1->OutputChannels != 3) return FALSE;
1761 
1762                      // Copy the matrix to our result
1763                      memcpy(&res, Data->Double, sizeof(res));
1764 
1765                      // Preserve the Odffset (may be NULL as a zero offset)
1766                      Offset = Data->Offset;
1767 
1768                      if (_cmsMAT3isIdentity(&res) && Offset == NULL) {
1769 
1770                             // We can get rid of full matrix
1771                             IdentityMat = TRUE;
1772                      }
1773               }
1774               else
1775                      return FALSE; // Not optimizeable this time
1776 
1777        }
1778 
1779       // Allocate an empty LUT
1780     Dest =  cmsPipelineAlloc(Src ->ContextID, Src ->InputChannels, Src ->OutputChannels);
1781     if (!Dest) return FALSE;

1786 
1787     if (!IdentityMat) {
1788 
1789            if (!cmsPipelineInsertStage(Dest, cmsAT_END, cmsStageAllocMatrix(Dest->ContextID, 3, 3, (const cmsFloat64Number*)&res, Offset)))
1790                   goto Error;
1791     }
1792 
1793     if (!cmsPipelineInsertStage(Dest, cmsAT_END, cmsStageDup(Curve2)))
1794         goto Error;
1795 
1796     // If identity on matrix, we can further optimize the curves, so call the join curves routine
1797     if (IdentityMat) {
1798 
1799         OptimizeByJoiningCurves(&Dest, Intent, InputFormat, OutputFormat, dwFlags);
1800     }
1801     else {
1802         _cmsStageToneCurvesData* mpeC1 = (_cmsStageToneCurvesData*) cmsStageData(Curve1);
1803         _cmsStageToneCurvesData* mpeC2 = (_cmsStageToneCurvesData*) cmsStageData(Curve2);
1804 
1805         // In this particular optimization, cache does not help as it takes more time to deal with
1806         // the cache than with the pixel handling
1807         *dwFlags |= cmsFLAGS_NOCACHE;
1808 
1809         // Setup the optimizarion routines
1810         SetMatShaper(Dest, mpeC1 ->TheCurves, &res, (cmsVEC3*) Offset, mpeC2->TheCurves, OutputFormat);
1811     }
1812 
1813     cmsPipelineFree(Src);
1814     *Lut = Dest;
1815     return TRUE;
1816 Error:
1817     // Leave Src unchanged
1818     cmsPipelineFree(Dest);
1819     return FALSE;
1820 }
1821 
1822 
1823 // -------------------------------------------------------------------------------------------------------------------------------------
1824 // Optimization plug-ins
1825 
1826 // List of optimizations

1943     cmsBool AnySuccess = FALSE;
1944     cmsStage* mpe;
1945 
1946     // A CLUT is being asked, so force this specific optimization
1947     if (*dwFlags & cmsFLAGS_FORCE_CLUT) {
1948 
1949         PreOptimize(*PtrLut);
1950         return OptimizeByResampling(PtrLut, Intent, InputFormat, OutputFormat, dwFlags);
1951     }
1952 
1953     // Anything to optimize?
1954     if ((*PtrLut) ->Elements == NULL) {
1955         _cmsPipelineSetOptimizationParameters(*PtrLut, FastIdentity16, (void*) *PtrLut, NULL, NULL);
1956         return TRUE;
1957     }
1958 
1959     // Named color pipelines cannot be optimized
1960     for (mpe = cmsPipelineGetPtrToFirstStage(*PtrLut);
1961         mpe != NULL;
1962         mpe = cmsStageNext(mpe)) {
1963             if (cmsStageType(mpe) == cmsSigNamedColorElemType) return FALSE;
1964     }
1965 
1966     // Try to get rid of identities and trivial conversions.
1967     AnySuccess = PreOptimize(*PtrLut);
1968 
1969     // After removal do we end with an identity?
1970     if ((*PtrLut) ->Elements == NULL) {
1971         _cmsPipelineSetOptimizationParameters(*PtrLut, FastIdentity16, (void*) *PtrLut, NULL, NULL);
1972         return TRUE;
1973     }
1974 
1975     // Do not optimize, keep all precision
1976     if (*dwFlags & cmsFLAGS_NOOPTIMIZE)
1977         return FALSE;
1978 
1979     // Try plug-in optimizations
1980     for (Opts = ctx->OptimizationCollection;
1981          Opts != NULL;
1982          Opts = Opts ->Next) {
1983 
< prev index next >