/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
// This file is available under and governed by the GNU General Public
// License version 2 only, as published by the Free Software Foundation.
// However, the following notice accompanied the original version of this
// file:
//
//---------------------------------------------------------------------------------
//
// Little Color Management System
// Copyright (c) 1998-2011 Marti Maria Saguer
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
// THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
//---------------------------------------------------------------------------------
//
#include "lcms2_internal.h"
//----------------------------------------------------------------------------------
// Optimization for 8 bits, Shaper-CLUT (3 inputs only)
typedef struct {
const cmsInterpParams* p; // Tetrahedrical interpolation parameters. This is a not-owned pointer.
} Prelin8Data;
// Generic optimization for 16 bits Shaper-CLUT-Shaper (any inputs)
typedef struct {
// Number of channels
int nInputs;
int nOutputs;
// Since there is no limitation of the output number of channels, this buffer holding the connexion CLUT-shaper
// has to be dynamically allocated. This is not the case of first step shaper-CLUT, which is limited to max inputs
_cmsInterpFn16 EvalCurveIn16[MAX_INPUT_DIMENSIONS]; // The maximum number of input channels is known in advance
_cmsInterpFn16* EvalCurveOut16; // Points to an array of curve evaluators in 16 bits (not-owned pointer)
cmsInterpParams** ParamsCurveOut16; // Points to an array of references to interpolation params (not-owned pointer)
} Prelin16Data;
// Optimization for matrix-shaper in 8 bits. Numbers are operated in n.14 signed, tables are stored in 1.14 fixed
typedef struct {
// Curves, optimization is shared between 8 and 16 bits
typedef struct {
} Curves16Data;
// Simple optimizations ----------------------------------------------------------------------------------------------------------
// Remove an element in linked chain
static
{
}
// Remove all identities in chain. Note that pt actually is a double pointer to the element that holds the pointer.
static
{
}
else
}
return AnyOpt;
}
// Same, but only if two adjacent elements are found
static
{
}
else
}
return AnyOpt;
}
// Preoptimize just gets rif of no-ops coming paired. Conversion from v2 to v4 followed
// by a v4 to v2 and vice-versa. The elements are then discarded.
static
{
do {
// Remove all identities
// Remove XYZ2Lab followed by Lab2XYZ
// Remove Lab2XYZ followed by XYZ2Lab
// Remove V4 to V2 followed by V2 to V4
// Remove V2 to V4 followed by V4 to V2
// Remove float pcs Lab conversions
// Remove float pcs Lab conversions
} while (Opt);
return AnyOpt;
}
static
register cmsUInt16Number Output[],
register const struct _cms_interp_struc* p)
{
}
static
register cmsUInt16Number Output[],
register const void* D)
{
int i;
}
}
}
static
{
}
static
{
Duped ->EvalCurveOut16 = _cmsDupMem(ContextID, p16 ->EvalCurveOut16, p16 ->nOutputs * sizeof(_cmsInterpFn16));
Duped ->ParamsCurveOut16 = _cmsDupMem(ContextID, p16 ->ParamsCurveOut16, p16 ->nOutputs * sizeof(cmsInterpParams* ));
return Duped;
}
static
const cmsInterpParams* ColorMap,
{
int i;
for (i=0; i < nInputs; i++) {
}
else {
}
}
p16 -> ParamsCurveOut16 = (cmsInterpParams**) _cmsCalloc(ContextID, nOutputs, sizeof(cmsInterpParams* ));
for (i=0; i < nOutputs; i++) {
}
else {
}
}
return p16;
}
// Resampling ---------------------------------------------------------------------------------
// Sampler implemented by another LUT. This is a clean way to precalculate the devicelink 3D CLUT for
// almost any transform. We use floating point precision and then convert from floating point to 16 bits.
static
int XFormSampler16(register const cmsUInt16Number In[], register cmsUInt16Number Out[], register void* Cargo)
{
// From 16 bit to floating point
for (i=0; i < Lut ->InputChannels; i++)
// Evaluate in floating point
// Back to 16 bits representation
for (i=0; i < Lut ->OutputChannels; i++)
// Always succeed
return TRUE;
}
// Try to see if the curves of a given MPE are linear
static
{
cmsUInt32Number i, n;
n = cmsStageOutputChannels(mpe);
for (i=0; i < n; i++) {
}
return TRUE;
}
// This function replaces a specific node placed in "At" by the "Value" numbers. Its purpose
// is to fix scum dot on broken profiles/transforms. Works on 1, 3 and 4 channels
static
int nChannelsOut, int nChannelsIn)
{
int i, index;
cmsSignalError(CLUT->ContextID, cmsERROR_INTERNAL, "(internal) Attempt to PatchLUT on non-lut MPE");
return FALSE;
}
if (nChannelsIn == 4) {
}
else
if (nChannelsIn == 3) {
}
else
if (nChannelsIn == 1) {
}
else {
cmsSignalError(CLUT->ContextID, cmsERROR_INTERNAL, "(internal) %d Channels are not supported on PatchLUT", nChannelsIn);
return FALSE;
}
for (i=0; i < nChannelsOut; i++)
return TRUE;
}
// Auxiliar, to see if two values are equal or very different
static
{
int i;
for (i=0; i < n; i++) {
if (abs(White1[i] - White2[i]) > 0xf000) return TRUE; // Values are so extremly different that the fixup should be avoided
}
return TRUE;
}
// Locate the node for the white point and fix it to pure white in order to avoid scum dot.
static
cmsBool FixWhiteMisalignment(cmsPipeline* Lut, cmsColorSpaceSignature EntryColorSpace, cmsColorSpaceSignature ExitColorSpace)
{
// It needs to be fixed?
// Check if the LUT comes as Prelin, CLUT or Postlin. We allow all combinations
if (!cmsPipelineCheckAndRetreiveStages(Lut, 3, cmsSigCurveSetElemType, cmsSigCLutElemType, cmsSigCurveSetElemType, &PreLin, &CLUT, &PostLin))
if (!cmsPipelineCheckAndRetreiveStages(Lut, 2, cmsSigCurveSetElemType, cmsSigCLutElemType, &PreLin, &CLUT))
if (!cmsPipelineCheckAndRetreiveStages(Lut, 2, cmsSigCLutElemType, cmsSigCurveSetElemType, &CLUT, &PostLin))
return FALSE;
// We need to interpolate white points of both, pre and post curves
if (PreLin) {
for (i=0; i < nIns; i++) {
}
}
else {
for (i=0; i < nIns; i++)
WhiteIn[i] = WhitePointIn[i];
}
// If any post-linearization, we need to find how is represented white before the curve, do
// a reverse interpolation in this case.
if (PostLin) {
for (i=0; i < nOuts; i++) {
}
}
else {
for (i=0; i < nOuts; i++)
WhiteOut[i] = WhitePointOut[i];
}
// Ok, proceed with patching. May fail and we don't care if it fails
return TRUE;
}
// -----------------------------------------------------------------------------------------------------------------------------------------------
// This function creates simple LUT from complex ones. The generated LUT has an optional set of
// prelinearization curves, a CLUT of nGridPoints and optional postlinearization tables.
// These curves have to exist in the original LUT in order to be used in the simplified output.
// Caller may also use the flags to allow this feature.
// LUTS with all curves will be simplified to a single curve. Parametric curves are lost.
// This function should be used on 16-bits LUTS only, as floating point losses precision when simplified
// -----------------------------------------------------------------------------------------------------------------------------------------------
static
cmsBool OptimizeByResampling(cmsPipeline** Lut, cmsUInt32Number Intent, cmsUInt32Number* InputFormat, cmsUInt32Number* OutputFormat, cmsUInt32Number* dwFlags)
{
int nGridPoints;
// This is a loosy optimization! does not apply in floating-point cases
// For empty LUTs, 2 points are enough
if (cmsPipelineStageCount(*Lut) == 0)
nGridPoints = 2;
// Named color pipelines cannot be optimized either
}
// Allocate an empty LUT
// Prelinearization tables are kept unless indicated by flags
if (*dwFlags & cmsFLAGS_CLUT_PRE_LINEARIZATION) {
// Get a pointer to the prelinearization element
// Check if suitable
// Maybe this is a linear tram, so we can avoid the whole stuff
if (!AllCurvesAreLinear(PreLin)) {
// All seems ok, proceed.
// Remove prelinearization. Since we have duplicated the curve
// in destination LUT, the sampling shoud be applied after this stage.
}
}
}
// Allocate the CLUT
CLUT = cmsStageAllocCLut16bit(Src ->ContextID, nGridPoints, Src ->InputChannels, Src->OutputChannels, NULL);
// Add the CLUT to the destination LUT
// Postlinearization tables are kept unless indicated by flags
if (*dwFlags & cmsFLAGS_CLUT_POST_LINEARIZATION) {
// Get a pointer to the postlinearization if present
// Check if suitable
// Maybe this is a linear tram, so we can avoid the whole stuff
if (!AllCurvesAreLinear(PostLin)) {
// All seems ok, proceed.
// In destination LUT, the sampling shoud be applied after this stage.
}
}
}
// Ops, something went wrong, Restore stages
return FALSE;
}
// Done.
_cmsPipelineSetOptimizationParameters(Dest, (_cmsOPTeval16Fn) DataCLUT->Params->Interpolation.Lerp16, DataCLUT->Params, NULL, NULL);
}
else {
_cmsPipelineSetOptimizationParameters(Dest, PrelinEval16, (void*) p16, PrelinOpt16free, Prelin16dup);
}
// Don't fix white on absolute colorimetric
if (Intent == INTENT_ABSOLUTE_COLORIMETRIC)
if (!(*dwFlags & cmsFLAGS_NOWHITEONWHITEFIXUP)) {
}
return TRUE;
}
// -----------------------------------------------------------------------------------------------------------------------------------------------
// Fixes the gamma balancing of transform. This is described in my paper "Prelinearization Stages on
// Color-Management Application-Specific Integrated Circuits (ASICs)" presented at NIP24. It only works
// for RGB transforms. See the paper for more details
// -----------------------------------------------------------------------------------------------------------------------------------------------
// Normalize endpoints by slope limiting max and min. This assures endpoints as well.
// Descending curves are handled as well.
static
{
int i;
if (cmsIsToneCurveDescending(g)) {
}
else {
}
// Compute slope and offset for begin of curve
for (i=0; i < AtBegin; i++)
// Compute slope and offset for the end
}
// Precomputes tables for 8-bit on input devicelink.
static
{
int i;
// Since this only works for 8 bit input, values comes always as x * 257,
// we can safely take msb byte (x << 8 + x)
for (i=0; i < 256; i++) {
if (G != NULL) {
// Get 16-bit representation
}
else {
Input[0] = FROM_8_TO_16(i);
}
// Move to 0..1.0 in fixed domain
// Store the precalculated table of nodes
// Store the precalculated table of offsets
}
p8 ->p = p;
return p8;
}
static
{
}
static
{
}
// A optimized interpolation for 8-bit input.
static
register cmsUInt16Number Output[],
register const void* D)
{
cmsUInt8Number r, g, b;
int OutChan;
register const cmsInterpParams* p = p8 ->p;
r = Input[0] >> 8;
// These are the 6 Tetrahedral
{
}
else
{
}
else
{
}
else
{
}
else
{
}
else
{
}
else {
}
}
}
// Curves that contain wide empty areas are not optimizeable
static
{
for (i=0; i < nEntries; i++) {
}
return FALSE;
}
// --------------------------------------------------------------------------------------------------------------
// We need xput over here
static
cmsBool OptimizeByComputingLinearization(cmsPipeline** Lut, cmsUInt32Number Intent, cmsUInt32Number* InputFormat, cmsUInt32Number* OutputFormat, cmsUInt32Number* dwFlags)
{
int nGridPoints;
cmsUInt32Number t, i;
// This is a loosy optimization! does not apply in floating-point cases
// Only on RGB
// On 16 bits, user has to specify the feature
if (!_cmsFormatterIs8bit(*InputFormat)) {
}
OriginalLut = *Lut;
// Named color pipelines cannot be optimized either
}
// Empty gamma containers
for (t = 0; t < OriginalLut ->InputChannels; t++) {
}
// Populate the curves
for (i=0; i < PRELINEARIZATION_POINTS; i++) {
// Feed input with a gray ramp
for (t=0; t < OriginalLut ->InputChannels; t++)
In[t] = v;
// Evaluate the gray value
// Store result in curve
for (t=0; t < OriginalLut ->InputChannels; t++)
}
// Slope-limit the obtained curves
for (t = 0; t < OriginalLut ->InputChannels; t++)
SlopeLimiting(Trans[t]);
// Check for validity
lIsSuitable = TRUE;
// Exclude if already linear
if (!cmsIsToneCurveLinear(Trans[t]))
// Exclude if non-monotonic
if (!cmsIsToneCurveMonotonic(Trans[t]))
lIsSuitable = FALSE;
if (IsDegenerated(Trans[t]))
lIsSuitable = FALSE;
}
// If it is not suitable, just quit
if (!lIsSuitable) goto Error;
// Invert curves if possible
for (t = 0; t < OriginalLut ->InputChannels; t++) {
}
// Now inset the reversed curves at the begin of transform
cmsPipelineInsertStage(LutPlusCurves, cmsAT_BEGIN, cmsStageAllocToneCurves(OriginalLut ->ContextID, OriginalLut ->InputChannels, TransReverse));
// Create the result LUT
OptimizedLUT = cmsPipelineAlloc(OriginalLut ->ContextID, OriginalLut ->InputChannels, OriginalLut ->OutputChannels);
OptimizedPrelinMpe = cmsStageAllocToneCurves(OriginalLut ->ContextID, OriginalLut ->InputChannels, Trans);
// Create and insert the curves at the beginning
// Allocate the CLUT for result
OptimizedCLUTmpe = cmsStageAllocCLut16bit(OriginalLut ->ContextID, nGridPoints, OriginalLut ->InputChannels, OriginalLut ->OutputChannels, NULL);
// Add the CLUT to the destination LUT
// Resample the LUT
if (!cmsStageSampleCLut16bit(OptimizedCLUTmpe, XFormSampler16, (void*) LutPlusCurves, 0)) goto Error;
// Free resources
for (t = 0; t < OriginalLut ->InputChannels; t++) {
}
// Set the evaluator if 8-bit
if (_cmsFormatterIs8bit(*InputFormat)) {
_cmsPipelineSetOptimizationParameters(OptimizedLUT, PrelinEval8, (void*) p8, Prelin8free, Prelin8dup);
}
else
{
_cmsPipelineSetOptimizationParameters(OptimizedLUT, PrelinEval16, (void*) p16, PrelinOpt16free, Prelin16dup);
}
// Don't fix white on absolute colorimetric
if (Intent == INTENT_ABSOLUTE_COLORIMETRIC)
if (!(*dwFlags & cmsFLAGS_NOWHITEONWHITEFIXUP)) {
return FALSE;
}
}
// And return the obtained LUT
*Lut = OptimizedLUT;
return TRUE;
for (t = 0; t < OriginalLut ->InputChannels; t++) {
}
return FALSE;
}
// Curves optimizer ------------------------------------------------------------------------------------------------------------------
static
{
int i;
}
}
static
{
int i;
Data ->Curves[i] = _cmsDupMem(ContextID, Data ->Curves[i], Data -> nElements * sizeof(cmsUInt16Number));
}
return (void*) Data;
}
// Precomputes tables for 8-bit on input devicelink.
static
{
int i, j;
for (i=0; i < nCurves; i++) {
for (j=0; j < i; j++) {
}
return NULL;
}
if (nElements == 256) {
for (j=0; j < nElements; j++) {
}
}
else {
for (j=0; j < nElements; j++) {
}
}
}
return c16;
}
static
register cmsUInt16Number Out[],
register const void* D)
{
int i;
x = (In[i] >> 8);
}
}
static
register cmsUInt16Number Out[],
register const void* D)
{
int i;
}
}
static
register cmsUInt16Number Out[],
register const void* D)
{
for (i=0; i < Lut ->InputChannels; i++) {
}
}
// If the target LUT holds only curves, the optimization procedure is to join all those
// curves together. That only works on curves and does not work on matrices.
static
cmsBool OptimizeByJoiningCurves(cmsPipeline** Lut, cmsUInt32Number Intent, cmsUInt32Number* InputFormat, cmsUInt32Number* OutputFormat, cmsUInt32Number* dwFlags)
{
cmsUInt32Number i, j;
// This is a loosy optimization! does not apply in floating-point cases
// Only curves in this LUT?
}
// Allocate an empty LUT
// Create target curves
GammaTables = (cmsToneCurve**) _cmsCalloc(Src ->ContextID, Src ->InputChannels, sizeof(cmsToneCurve*));
for (i=0; i < Src ->InputChannels; i++) {
}
// Compute 16 bit result by using floating point
for (i=0; i < PRELINEARIZATION_POINTS; i++) {
for (j=0; j < Src ->InputChannels; j++)
for (j=0; j < Src ->InputChannels; j++)
}
for (i=0; i < Src ->InputChannels; i++) {
GammaTables[i] = NULL;
}
// Maybe the curves are linear at the end
if (!AllCurvesAreLinear(ObtainedCurves)) {
// If the curves are to be applied in 8 bits, we can save memory
if (_cmsFormatterIs8bit(*InputFormat)) {
*dwFlags |= cmsFLAGS_NOCACHE;
}
else {
*dwFlags |= cmsFLAGS_NOCACHE;
}
}
else {
// LUT optimizes to nothing. Set the identity LUT
cmsPipelineInsertStage(Dest, cmsAT_BEGIN, cmsStageAllocIdentity(Dest ->ContextID, Src ->InputChannels));
*dwFlags |= cmsFLAGS_NOCACHE;
}
// We are done.
return TRUE;
if (GammaTables != NULL) {
for (i=0; i < Src ->InputChannels; i++) {
}
}
return FALSE;
}
// -------------------------------------------------------------------------------------------------------------------------------------
// LUT is Shaper - Matrix - Matrix - Shaper, which is very frequent when combining two matrix-shaper profiles
static
{
}
static
{
}
// A fast matrix-shaper evaluator for 8 bits. This is a bit ticky since I'm using 1.14 signed fixed point
// to accomplish some performance. Actually it takes 256x3 16 bits tables and 16385 x 3 tables of 8 bits,
// in total about 50K, and the performance boost is huge!
static
register cmsUInt16Number Out[],
register const void* D)
{
MatShaper8Data* p = (MatShaper8Data*) D;
// In this case (and only in this case!) we can use this simplification since
// In[] is assured to come from a 8 bit number. (a << 8 | a)
// Across first shaper, which also converts to 1.14 fixed point
// Evaluate the matrix in 1.14 fixed point
// Now we have to clip to 0..1.0 range
// And across second shaper,
}
// This table converts from 8 bits to 1.14 after applying the curve
static
{
int i;
cmsFloat32Number R, y;
for (i=0; i < 256; i++) {
R = (cmsFloat32Number) (i / 255.0);
y = cmsEvalToneCurveFloat(Curve, R);
Table[i] = DOUBLE_TO_1FIXED14(y);
}
}
// This table converts form 1.14 (being 0x4000 the last entry) to 8 bits after applying the curve
static
{
int i;
for (i=0; i < 16385; i++) {
R = (cmsFloat32Number) (i / 16384.0);
if (Is8BitsOutput) {
// If 8 bits output, we can optimize further by computing the / 257 part.
// first we compute the resulting byte and then we store the byte times
// 257. This quantization allows to round very quick by doing a >> 8, but
// since the low byte is always equal to msb, we can do a & 0xff and this works!
cmsUInt8Number b = FROM_16_TO_8(w);
Table[i] = FROM_8_TO_16(b);
}
}
}
// Compute the matrix-shaper structure
static
cmsBool SetMatShaper(cmsPipeline* Dest, cmsToneCurve* Curve1[3], cmsMAT3* Mat, cmsVEC3* Off, cmsToneCurve* Curve2[3], cmsUInt32Number* OutputFormat)
{
MatShaper8Data* p;
int i, j;
// Allocate a big chuck of memory to store precomputed tables
// Precompute tables
// Convert matrix to nFixed14. Note that those values may take more than 16 bits as
for (i=0; i < 3; i++) {
for (j=0; j < 3; j++) {
}
}
for (i=0; i < 3; i++) {
p ->Off[i] = 0;
}
else {
}
}
// Mark as optimized for faster formatter
if (Is8Bits)
// Fill function pointers
_cmsPipelineSetOptimizationParameters(Dest, MatShaperEval16, (void*) p, FreeMatShaper, DupMatShaper);
return TRUE;
}
// 8 bits on input allows matrix-shaper boot up to 25 Mpixels per second on RGB. That's fast!
// TODO: Allow a third matrix for abs. colorimetric
static
cmsBool OptimizeMatrixShaper(cmsPipeline** Lut, cmsUInt32Number Intent, cmsUInt32Number* InputFormat, cmsUInt32Number* OutputFormat, cmsUInt32Number* dwFlags)
{
// Only works on RGB to RGB
// Only works on 8 bit input
// Seems suitable, proceed
// Check for shaper-matrix-matrix-shaper structure, that is what this optimizer stands for
// Get both matrices
// Input offset should be zero
// Multiply both matrices to get the result
// Now the result is in res + Data2 -> Offset. Maybe is a plain identity?
IdentityMat = FALSE;
// We can get rid of full matrix
IdentityMat = TRUE;
}
// Allocate an empty LUT
// Assamble the new LUT
if (!IdentityMat)
cmsPipelineInsertStage(Dest, cmsAT_END, cmsStageAllocMatrix(Dest ->ContextID, 3, 3, (const cmsFloat64Number*) &res, Data2 ->Offset));
// If identity on matrix, we can further optimize the curves, so call the join curves routine
if (IdentityMat) {
}
else {
// In this particular optimization, cach� does not help as it takes more time to deal with
// the cach� that with the pixel handling
*dwFlags |= cmsFLAGS_NOCACHE;
// Setup the optimizarion routines
SetMatShaper(Dest, mpeC1 ->TheCurves, &res, (cmsVEC3*) Data2 ->Offset, mpeC2->TheCurves, OutputFormat);
}
return TRUE;
}
// -------------------------------------------------------------------------------------------------------------------------------------
// Optimization plug-ins
// List of optimizations
typedef struct _cmsOptimizationCollection_st {
// The built-in list. We currently implement 4 types of optimizations. Joining of curves, matrix-shaper, linearization and resampling
{ OptimizeByResampling, NULL }
};
// The linked list head
// Register new ways to optimize
{
return TRUE;
}
// Optimizer callback is required
// Copy the parameters
// Keep linked list
// All is ok
return TRUE;
}
// The entry point for LUT optimization
int Intent,
{
// A CLUT is being asked, so force this specific optimization
if (*dwFlags & cmsFLAGS_FORCE_CLUT) {
}
// Anything to optimize?
return TRUE;
}
// Try to get rid of identities and trivial conversions.
// After removal do we end with an identity?
return TRUE;
}
// Do not optimize, keep all precision
if (*dwFlags & cmsFLAGS_NOOPTIMIZE)
return FALSE;
// Try built-in optimizations and plug-in
for (Opts = OptimizationCollection;
// If one schema succeeded, we are done
return TRUE; // Optimized!
}
}
// Only simple optimizations succeeded
return AnySuccess;
}