< prev index next >

src/share/native/sun/java2d/cmm/lcms/cmsxform.c

Print this page




  13  * version 2 for more details (a copy is included in the LICENSE file that
  14  * accompanied this code).
  15  *
  16  * You should have received a copy of the GNU General Public License version
  17  * 2 along with this work; if not, write to the Free Software Foundation,
  18  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  19  *
  20  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  21  * or visit www.oracle.com if you need additional information or have any
  22  * questions.
  23  */
  24 
  25 // This file is available under and governed by the GNU General Public
  26 // License version 2 only, as published by the Free Software Foundation.
  27 // However, the following notice accompanied the original version of this
  28 // file:
  29 //
  30 //---------------------------------------------------------------------------------
  31 //
  32 //  Little Color Management System
  33 //  Copyright (c) 1998-2014 Marti Maria Saguer
  34 //
  35 // Permission is hereby granted, free of charge, to any person obtaining
  36 // a copy of this software and associated documentation files (the "Software"),
  37 // to deal in the Software without restriction, including without limitation
  38 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
  39 // and/or sell copies of the Software, and to permit persons to whom the Software
  40 // is furnished to do so, subject to the following conditions:
  41 //
  42 // The above copyright notice and this permission notice shall be included in
  43 // all copies or substantial portions of the Software.
  44 //
  45 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  46 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
  47 // THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  48 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  49 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  50 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  51 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  52 //
  53 //---------------------------------------------------------------------------------


 191     if (p -> OutputColorant)
 192         cmsFreeNamedColorList(p ->OutputColorant);
 193 
 194     if (p ->Sequence)
 195         cmsFreeProfileSequenceDescription(p ->Sequence);
 196 
 197     if (p ->UserData)
 198         p ->FreeUserData(p ->ContextID, p ->UserData);
 199 
 200     _cmsFree(p ->ContextID, (void *) p);
 201 }
 202 
 203 // Apply transform.
 204 void CMSEXPORT cmsDoTransform(cmsHTRANSFORM  Transform,
 205                               const void* InputBuffer,
 206                               void* OutputBuffer,
 207                               cmsUInt32Number Size)
 208 
 209 {
 210     _cmsTRANSFORM* p = (_cmsTRANSFORM*) Transform;

 211 
 212     p -> xform(p, InputBuffer, OutputBuffer, Size, Size);





 213 }
 214 
 215 
 216 // Apply transform.
 217 void CMSEXPORT cmsDoTransformStride(cmsHTRANSFORM  Transform,
 218                               const void* InputBuffer,
 219                               void* OutputBuffer,
 220                               cmsUInt32Number Size, cmsUInt32Number Stride)
 221 
 222 {
 223     _cmsTRANSFORM* p = (_cmsTRANSFORM*) Transform;





























 224 
 225     p -> xform(p, InputBuffer, OutputBuffer, Size, Stride);
 226 }
 227 
 228 

 229 // Transform routines ----------------------------------------------------------------------------------------------------------
 230 
 231 // Float xform converts floats. Since there are no performance issues, one routine does all job, including gamut check.
 232 // Note that because extended range, we can use a -1.0 value for out of gamut in this case.
 233 static
 234 void FloatXFORM(_cmsTRANSFORM* p,
 235                 const void* in,
 236                 void* out, cmsUInt32Number Size, cmsUInt32Number Stride)



 237 {
 238     cmsUInt8Number* accum;
 239     cmsUInt8Number* output;
 240     cmsFloat32Number fIn[cmsMAXCHANNELS], fOut[cmsMAXCHANNELS];
 241     cmsFloat32Number OutOfGamut;
 242     cmsUInt32Number i, j;


 243 
 244     accum  = (cmsUInt8Number*)  in;
 245     output = (cmsUInt8Number*)  out;
 246 
 247     for (i=0; i < Size; i++) {
 248 
 249         accum = p -> FromInputFloat(p, fIn, accum, Stride);





 250 
 251         // Any gamut chack to do?
 252         if (p ->GamutCheck != NULL) {
 253 
 254             // Evaluate gamut marker.
 255             cmsPipelineEvalFloat( fIn, &OutOfGamut, p ->GamutCheck);
 256 
 257             // Is current color out of gamut?
 258             if (OutOfGamut > 0.0) {
 259 
 260                 // Certainly, out of gamut
 261                 for (j=0; j < cmsMAXCHANNELS; j++)
 262                     fOut[j] = -1.0;
 263 
 264             }
 265             else {
 266                 // No, proceed normally
 267                 cmsPipelineEvalFloat(fIn, fOut, p -> Lut);
 268             }
 269         }
 270         else {
 271 
 272             // No gamut check at all
 273             cmsPipelineEvalFloat(fIn, fOut, p -> Lut);




 274         }
 275 
 276         // Back to asked representation
 277         output = p -> ToOutputFloat(p, fOut, output, Stride);
 278     }

 279 }
 280 
 281 
 282 static
 283 void NullFloatXFORM(_cmsTRANSFORM* p,
 284                     const void* in,
 285                     void* out,
 286                     cmsUInt32Number Size,
 287                     cmsUInt32Number Stride)


 288 {
 289     cmsUInt8Number* accum;
 290     cmsUInt8Number* output;
 291     cmsFloat32Number fIn[cmsMAXCHANNELS];
 292     cmsUInt32Number i, n;





 293 
 294     accum  = (cmsUInt8Number*)  in;
 295     output = (cmsUInt8Number*)  out;
 296     n = Size;
 297 
 298     for (i=0; i < n; i++) {

 299 
 300         accum  = p -> FromInputFloat(p, fIn, accum, Stride);
 301         output = p -> ToOutputFloat(p, fIn, output, Stride);






 302     }
 303 }
 304 
 305 // 16 bit precision -----------------------------------------------------------------------------------------------------------
 306 
 307 // Null transformation, only applies formatters. No caché
 308 static
 309 void NullXFORM(_cmsTRANSFORM* p,
 310                const void* in,
 311                void* out, cmsUInt32Number Size,
 312                cmsUInt32Number Stride)


 313 {
 314     cmsUInt8Number* accum;
 315     cmsUInt8Number* output;
 316     cmsUInt16Number wIn[cmsMAXCHANNELS];
 317     cmsUInt32Number i, n;





 318 
 319     accum  = (cmsUInt8Number*)  in;
 320     output = (cmsUInt8Number*)  out;
 321     n = Size;                    // Buffer len
 322 
 323     for (i=0; i < n; i++) {

 324 
 325         accum  = p -> FromInput(p, wIn, accum, Stride);
 326         output = p -> ToOutput(p, wIn, output, Stride);






 327     }

 328 }
 329 
 330 
 331 // No gamut check, no cache, 16 bits
 332 static
 333 void PrecalculatedXFORM(_cmsTRANSFORM* p,
 334                         const void* in,
 335                         void* out, cmsUInt32Number Size, cmsUInt32Number Stride)



 336 {
 337     register cmsUInt8Number* accum;
 338     register cmsUInt8Number* output;
 339     cmsUInt16Number wIn[cmsMAXCHANNELS], wOut[cmsMAXCHANNELS];
 340     cmsUInt32Number i, n;
 341 
 342     accum  = (cmsUInt8Number*)  in;
 343     output = (cmsUInt8Number*)  out;
 344     n = Size;
 345 
 346     for (i=0; i < n; i++) {

 347 
 348         accum = p -> FromInput(p, wIn, accum, Stride);
 349         p ->Lut ->Eval16Fn(wIn, wOut, p -> Lut->Data);
 350         output = p -> ToOutput(p, wOut, output, Stride);







 351     }





 352 }
 353 
 354 
 355 // Auxiliar: Handle precalculated gamut check. The retrieval of context may be alittle bit slow, but this function is not critical.
 356 static
 357 void TransformOnePixelWithGamutCheck(_cmsTRANSFORM* p,
 358                                      const cmsUInt16Number wIn[],
 359                                      cmsUInt16Number wOut[])
 360 {
 361     cmsUInt16Number wOutOfGamut;
 362 
 363     p ->GamutCheck ->Eval16Fn(wIn, &wOutOfGamut, p ->GamutCheck ->Data);
 364     if (wOutOfGamut >= 1) {
 365 
 366         cmsUInt16Number i;
 367         _cmsAlarmCodesChunkType* ContextAlarmCodes = (_cmsAlarmCodesChunkType*) _cmsContextGetClientChunk(p->ContextID, AlarmCodesContext);
 368 
 369         for (i=0; i < p ->Lut->OutputChannels; i++) {
 370 
 371             wOut[i] = ContextAlarmCodes ->AlarmCodes[i];
 372         }
 373     }
 374     else
 375         p ->Lut ->Eval16Fn(wIn, wOut, p -> Lut->Data);
 376 }
 377 
 378 // Gamut check, No caché, 16 bits.
 379 static
 380 void PrecalculatedXFORMGamutCheck(_cmsTRANSFORM* p,
 381                                   const void* in,
 382                                   void* out, cmsUInt32Number Size, cmsUInt32Number Stride)



 383 {
 384     cmsUInt8Number* accum;
 385     cmsUInt8Number* output;
 386     cmsUInt16Number wIn[cmsMAXCHANNELS], wOut[cmsMAXCHANNELS];
 387     cmsUInt32Number i, n;





 388 
 389     accum  = (cmsUInt8Number*)  in;
 390     output = (cmsUInt8Number*)  out;
 391     n = Size;                    // Buffer len
 392 
 393     for (i=0; i < n; i++) {

 394 
 395         accum = p -> FromInput(p, wIn, accum, Stride);


 396         TransformOnePixelWithGamutCheck(p, wIn, wOut);
 397         output = p -> ToOutput(p, wOut, output, Stride);




 398     }
 399 }
 400 
 401 
 402 // No gamut check, Caché, 16 bits,
 403 static
 404 void CachedXFORM(_cmsTRANSFORM* p,
 405                  const void* in,
 406                  void* out, cmsUInt32Number Size, cmsUInt32Number Stride)



 407 {
 408     cmsUInt8Number* accum;
 409     cmsUInt8Number* output;
 410     cmsUInt16Number wIn[cmsMAXCHANNELS], wOut[cmsMAXCHANNELS];
 411     cmsUInt32Number i, n;
 412     _cmsCACHE Cache;

 413 
 414     accum  = (cmsUInt8Number*)  in;
 415     output = (cmsUInt8Number*)  out;
 416     n = Size;                    // Buffer len
 417 
 418     // Empty buffers for quick memcmp
 419     memset(wIn,  0, sizeof(wIn));
 420     memset(wOut, 0, sizeof(wOut));
 421 
 422     // Get copy of zero cache
 423     memcpy(&Cache, &p ->Cache, sizeof(Cache));



 424 
 425     for (i=0; i < n; i++) {
 426 
 427         accum = p -> FromInput(p, wIn, accum, Stride);





 428 
 429         if (memcmp(wIn, Cache.CacheIn, sizeof(Cache.CacheIn)) == 0) {
 430 
 431             memcpy(wOut, Cache.CacheOut, sizeof(Cache.CacheOut));
 432         }
 433         else {
 434 
 435             p ->Lut ->Eval16Fn(wIn, wOut, p -> Lut->Data);
 436 
 437             memcpy(Cache.CacheIn,  wIn,  sizeof(Cache.CacheIn));
 438             memcpy(Cache.CacheOut, wOut, sizeof(Cache.CacheOut));
 439         }
 440 
 441         output = p -> ToOutput(p, wOut, output, Stride);
 442     }
 443 



 444 }
 445 
 446 
 447 // All those nice features together
 448 static
 449 void CachedXFORMGamutCheck(_cmsTRANSFORM* p,
 450                            const void* in,
 451                            void* out, cmsUInt32Number Size, cmsUInt32Number Stride)



 452 {
 453        cmsUInt8Number* accum;
 454        cmsUInt8Number* output;
 455        cmsUInt16Number wIn[cmsMAXCHANNELS], wOut[cmsMAXCHANNELS];
 456        cmsUInt32Number i, n;
 457        _cmsCACHE Cache;

 458 
 459        accum  = (cmsUInt8Number*)  in;
 460        output = (cmsUInt8Number*)  out;
 461        n = Size;                    // Buffer len
 462 
 463        // Empty buffers for quick memcmp
 464        memset(wIn,  0, sizeof(cmsUInt16Number) * cmsMAXCHANNELS);
 465        memset(wOut, 0, sizeof(cmsUInt16Number) * cmsMAXCHANNELS);
 466 
 467        // Get copy of zero cache
 468        memcpy(&Cache, &p ->Cache, sizeof(Cache));
 469 
 470        for (i=0; i < n; i++) {

 471 
 472             accum = p -> FromInput(p, wIn, accum, Stride);







 473 
 474             if (memcmp(wIn, Cache.CacheIn, sizeof(Cache.CacheIn)) == 0) {

 475                     memcpy(wOut, Cache.CacheOut, sizeof(Cache.CacheOut));
 476             }
 477             else {
 478                     TransformOnePixelWithGamutCheck(p, wIn, wOut);

 479                     memcpy(Cache.CacheIn, wIn, sizeof(Cache.CacheIn));
 480                     memcpy(Cache.CacheOut, wOut, sizeof(Cache.CacheOut));
 481             }
 482 
 483             output = p -> ToOutput(p, wOut, output, Stride);
 484        }
 485 



 486 }
 487 
 488 // -------------------------------------------------------------------------------------------------------------
 489 
 490 // List of used-defined transform factories
 491 typedef struct _cmsTransformCollection_st {
 492 
 493     _cmsTransformFactory  Factory;


 494     struct _cmsTransformCollection_st *Next;
 495 
 496 } _cmsTransformCollection;
 497 
 498 // The linked list head
 499 _cmsTransformPluginChunkType _cmsTransformPluginChunk = { NULL };
 500 
 501 
 502 // Duplicates the zone of memory used by the plug-in in the new context
 503 static
 504 void DupPluginTransformList(struct _cmsContext_struct* ctx,
 505                                                const struct _cmsContext_struct* src)
 506 {
 507    _cmsTransformPluginChunkType newHead = { NULL };
 508    _cmsTransformCollection*  entry;
 509    _cmsTransformCollection*  Anterior = NULL;
 510    _cmsTransformPluginChunkType* head = (_cmsTransformPluginChunkType*) src->chunks[TransformPlugin];
 511 
 512     // Walk the list copying all nodes
 513    for (entry = head->TransformCollection;


 516 
 517             _cmsTransformCollection *newEntry = ( _cmsTransformCollection *) _cmsSubAllocDup(ctx ->MemPool, entry, sizeof(_cmsTransformCollection));
 518 
 519             if (newEntry == NULL)
 520                 return;
 521 
 522             // We want to keep the linked list order, so this is a little bit tricky
 523             newEntry -> Next = NULL;
 524             if (Anterior)
 525                 Anterior -> Next = newEntry;
 526 
 527             Anterior = newEntry;
 528 
 529             if (newHead.TransformCollection == NULL)
 530                 newHead.TransformCollection = newEntry;
 531     }
 532 
 533   ctx ->chunks[TransformPlugin] = _cmsSubAllocDup(ctx->MemPool, &newHead, sizeof(_cmsTransformPluginChunkType));
 534 }
 535 

 536 void _cmsAllocTransformPluginChunk(struct _cmsContext_struct* ctx,
 537                                         const struct _cmsContext_struct* src)
 538 {
 539     if (src != NULL) {
 540 
 541         // Copy all linked list
 542         DupPluginTransformList(ctx, src);
 543     }
 544     else {
 545         static _cmsTransformPluginChunkType TransformPluginChunkType = { NULL };
 546         ctx ->chunks[TransformPlugin] = _cmsSubAllocDup(ctx ->MemPool, &TransformPluginChunkType, sizeof(_cmsTransformPluginChunkType));
 547     }
 548 }
 549 





























 550 
 551 
 552 // Register new ways to transform
 553 cmsBool  _cmsRegisterTransformPlugin(cmsContext ContextID, cmsPluginBase* Data)
 554 {
 555     cmsPluginTransform* Plugin = (cmsPluginTransform*) Data;
 556     _cmsTransformCollection* fl;
 557     _cmsTransformPluginChunkType* ctx = ( _cmsTransformPluginChunkType*) _cmsContextGetClientChunk(ContextID,TransformPlugin);
 558 
 559     if (Data == NULL) {
 560 
 561         // Free the chain. Memory is safely freed at exit
 562         ctx->TransformCollection = NULL;
 563         return TRUE;
 564     }
 565 
 566     // Factory callback is required
 567     if (Plugin ->Factory == NULL) return FALSE;
 568 
 569 
 570     fl = (_cmsTransformCollection*) _cmsPluginMalloc(ContextID, sizeof(_cmsTransformCollection));
 571     if (fl == NULL) return FALSE;
 572 








 573     // Copy the parameters
 574     fl ->Factory = Plugin ->Factory;
 575 
 576     // Keep linked list
 577     fl ->Next = ctx->TransformCollection;
 578     ctx->TransformCollection = fl;
 579 
 580     // All is ok
 581     return TRUE;
 582 }
 583 
 584 
 585 void CMSEXPORT _cmsSetTransformUserData(struct _cmstransform_struct *CMMcargo, void* ptr, _cmsFreeUserDataFn FreePrivateDataFn)
 586 {
 587     _cmsAssert(CMMcargo != NULL);
 588     CMMcargo ->UserData = ptr;
 589     CMMcargo ->FreeUserData = FreePrivateDataFn;
 590 }
 591 
 592 // returns the pointer defined by the plug-in to store private data
 593 void * CMSEXPORT _cmsGetTransformUserData(struct _cmstransform_struct *CMMcargo)
 594 {


 639 
 640                             // Last plugin in the declaration order takes control. We just keep
 641                             // the original parameters as a logging.
 642                             // Note that cmsFLAGS_CAN_CHANGE_FORMATTER is not set, so by default
 643                             // an optimized transform is not reusable. The plug-in can, however, change
 644                             // the flags and make it suitable.
 645 
 646                             p->ContextID = ContextID;
 647                             p->InputFormat = *InputFormat;
 648                             p->OutputFormat = *OutputFormat;
 649                             p->dwOriginalFlags = *dwFlags;
 650 
 651                             // Fill the formatters just in case the optimized routine is interested.
 652                             // No error is thrown if the formatter doesn't exist. It is up to the optimization
 653                             // factory to decide what to do in those cases.
 654                             p->FromInput = _cmsGetFormatter(ContextID, *InputFormat, cmsFormatterInput, CMS_PACK_FLAGS_16BITS).Fmt16;
 655                             p->ToOutput = _cmsGetFormatter(ContextID, *OutputFormat, cmsFormatterOutput, CMS_PACK_FLAGS_16BITS).Fmt16;
 656                             p->FromInputFloat = _cmsGetFormatter(ContextID, *InputFormat, cmsFormatterInput, CMS_PACK_FLAGS_FLOAT).FmtFloat;
 657                             p->ToOutputFloat = _cmsGetFormatter(ContextID, *OutputFormat, cmsFormatterOutput, CMS_PACK_FLAGS_FLOAT).FmtFloat;
 658 






 659                             return p;
 660                      }
 661               }
 662 
 663               // Not suitable for the transform plug-in, let's check  the pipeline plug-in
 664               _cmsOptimizePipeline(ContextID, &p->Lut, Intent, InputFormat, OutputFormat, dwFlags);
 665        }
 666 
 667     // Check whatever this is a true floating point transform
 668     if (_cmsFormatterIsFloat(*InputFormat) && _cmsFormatterIsFloat(*OutputFormat)) {
 669 
 670         // Get formatter function always return a valid union, but the contents of this union may be NULL.
 671         p ->FromInputFloat = _cmsGetFormatter(ContextID, *InputFormat,  cmsFormatterInput, CMS_PACK_FLAGS_FLOAT).FmtFloat;
 672         p ->ToOutputFloat  = _cmsGetFormatter(ContextID, *OutputFormat, cmsFormatterOutput, CMS_PACK_FLAGS_FLOAT).FmtFloat;
 673         *dwFlags |= cmsFLAGS_CAN_CHANGE_FORMATTER;
 674 
 675         if (p ->FromInputFloat == NULL || p ->ToOutputFloat == NULL) {
 676 
 677             cmsSignalError(ContextID, cmsERROR_UNKNOWN_EXTENSION, "Unsupported raster format");
 678             _cmsFree(ContextID, p);


 799 }
 800 
 801 // Check colorspace
 802 static
 803 cmsBool  IsProperColorSpace(cmsColorSpaceSignature Check, cmsUInt32Number dwFormat)
 804 {
 805     int Space1 = T_COLORSPACE(dwFormat);
 806     int Space2 = _cmsLCMScolorSpace(Check);
 807 
 808     if (Space1 == PT_ANY) return TRUE;
 809     if (Space1 == Space2) return TRUE;
 810 
 811     if (Space1 == PT_LabV2 && Space2 == PT_Lab) return TRUE;
 812     if (Space1 == PT_Lab   && Space2 == PT_LabV2) return TRUE;
 813 
 814     return FALSE;
 815 }
 816 
 817 // ----------------------------------------------------------------------------------------------------------------
 818 
















 819 static
 820 void SetWhitePoint(cmsCIEXYZ* wtPt, const cmsCIEXYZ* src)
 821 {
 822     if (src == NULL) {
 823         wtPt ->X = cmsD50X;
 824         wtPt ->Y = cmsD50Y;
 825         wtPt ->Z = cmsD50Z;
 826     }
 827     else {
 828         wtPt ->X = src->X;
 829         wtPt ->Y = src->Y;
 830         wtPt ->Z = src->Z;


 831     }
 832 
 833 }
 834 
 835 // New to lcms 2.0 -- have all parameters available.
 836 cmsHTRANSFORM CMSEXPORT cmsCreateExtendedTransform(cmsContext ContextID,
 837                                                    cmsUInt32Number nProfiles, cmsHPROFILE hProfiles[],
 838                                                    cmsBool  BPC[],
 839                                                    cmsUInt32Number Intents[],
 840                                                    cmsFloat64Number AdaptationStates[],
 841                                                    cmsHPROFILE hGamutProfile,
 842                                                    cmsUInt32Number nGamutPCSposition,
 843                                                    cmsUInt32Number InputFormat,
 844                                                    cmsUInt32Number OutputFormat,
 845                                                    cmsUInt32Number dwFlags)
 846 {
 847     _cmsTRANSFORM* xform;
 848     cmsColorSpaceSignature EntryColorSpace;
 849     cmsColorSpaceSignature ExitColorSpace;
 850     cmsPipeline* Lut;


1121 {
1122     _cmsTRANSFORM* xform = (_cmsTRANSFORM*) hTransform;
1123 
1124     if (xform == NULL) return 0;
1125     return xform->InputFormat;
1126 }
1127 
1128 cmsUInt32Number CMSEXPORT cmsGetTransformOutputFormat(cmsHTRANSFORM hTransform)
1129 {
1130     _cmsTRANSFORM* xform = (_cmsTRANSFORM*) hTransform;
1131 
1132     if (xform == NULL) return 0;
1133     return xform->OutputFormat;
1134 }
1135 
1136 // For backwards compatibility
1137 cmsBool CMSEXPORT cmsChangeBuffersFormat(cmsHTRANSFORM hTransform,
1138                                          cmsUInt32Number InputFormat,
1139                                          cmsUInt32Number OutputFormat)
1140 {
1141 
1142     _cmsTRANSFORM* xform = (_cmsTRANSFORM*) hTransform;
1143     cmsFormatter16 FromInput, ToOutput;
1144 
1145 
1146     // We only can afford to change formatters if previous transform is at least 16 bits
1147     if (!(xform ->dwOriginalFlags & cmsFLAGS_CAN_CHANGE_FORMATTER)) {
1148 
1149         cmsSignalError(xform ->ContextID, cmsERROR_NOT_SUITABLE, "cmsChangeBuffersFormat works only on transforms created originally with at least 16 bits of precision");
1150         return FALSE;
1151     }
1152 
1153     FromInput = _cmsGetFormatter(xform->ContextID, InputFormat,  cmsFormatterInput, CMS_PACK_FLAGS_16BITS).Fmt16;
1154     ToOutput  = _cmsGetFormatter(xform->ContextID, OutputFormat, cmsFormatterOutput, CMS_PACK_FLAGS_16BITS).Fmt16;
1155 
1156     if (FromInput == NULL || ToOutput == NULL) {
1157 
1158         cmsSignalError(xform -> ContextID, cmsERROR_UNKNOWN_EXTENSION, "Unsupported raster format");
1159         return FALSE;
1160     }
1161 


  13  * version 2 for more details (a copy is included in the LICENSE file that
  14  * accompanied this code).
  15  *
  16  * You should have received a copy of the GNU General Public License version
  17  * 2 along with this work; if not, write to the Free Software Foundation,
  18  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  19  *
  20  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  21  * or visit www.oracle.com if you need additional information or have any
  22  * questions.
  23  */
  24 
  25 // This file is available under and governed by the GNU General Public
  26 // License version 2 only, as published by the Free Software Foundation.
  27 // However, the following notice accompanied the original version of this
  28 // file:
  29 //
  30 //---------------------------------------------------------------------------------
  31 //
  32 //  Little Color Management System
  33 //  Copyright (c) 1998-2016 Marti Maria Saguer
  34 //
  35 // Permission is hereby granted, free of charge, to any person obtaining
  36 // a copy of this software and associated documentation files (the "Software"),
  37 // to deal in the Software without restriction, including without limitation
  38 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
  39 // and/or sell copies of the Software, and to permit persons to whom the Software
  40 // is furnished to do so, subject to the following conditions:
  41 //
  42 // The above copyright notice and this permission notice shall be included in
  43 // all copies or substantial portions of the Software.
  44 //
  45 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  46 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
  47 // THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  48 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  49 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  50 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  51 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  52 //
  53 //---------------------------------------------------------------------------------


 191     if (p -> OutputColorant)
 192         cmsFreeNamedColorList(p ->OutputColorant);
 193 
 194     if (p ->Sequence)
 195         cmsFreeProfileSequenceDescription(p ->Sequence);
 196 
 197     if (p ->UserData)
 198         p ->FreeUserData(p ->ContextID, p ->UserData);
 199 
 200     _cmsFree(p ->ContextID, (void *) p);
 201 }
 202 
 203 // Apply transform.
 204 void CMSEXPORT cmsDoTransform(cmsHTRANSFORM  Transform,
 205                               const void* InputBuffer,
 206                               void* OutputBuffer,
 207                               cmsUInt32Number Size)
 208 
 209 {
 210     _cmsTRANSFORM* p = (_cmsTRANSFORM*) Transform;
 211     cmsStride stride;
 212 
 213     stride.BytesPerLineIn = 0;  // Not used
 214     stride.BytesPerLineOut = 0;
 215     stride.BytesPerPlaneIn = Size;
 216     stride.BytesPerPlaneOut = Size;
 217 
 218     p -> xform(p, InputBuffer, OutputBuffer, Size, 1, &stride);
 219 }
 220 
 221 
 222 // This is a legacy stride for planar
 223 void CMSEXPORT cmsDoTransformStride(cmsHTRANSFORM  Transform,
 224                               const void* InputBuffer,
 225                               void* OutputBuffer,
 226                               cmsUInt32Number Size, cmsUInt32Number Stride)
 227 
 228 {
 229     _cmsTRANSFORM* p = (_cmsTRANSFORM*) Transform;
 230     cmsStride stride;
 231 
 232     stride.BytesPerLineIn = 0;
 233     stride.BytesPerLineOut = 0;
 234     stride.BytesPerPlaneIn = Stride;
 235     stride.BytesPerPlaneOut = Stride;
 236 
 237     p -> xform(p, InputBuffer, OutputBuffer, Size, 1, &stride);
 238 }
 239 
 240 // This is the "fast" function for plugins
 241 void CMSEXPORT cmsDoTransformLineStride(cmsHTRANSFORM  Transform,
 242                               const void* InputBuffer,
 243                               void* OutputBuffer,
 244                               cmsUInt32Number PixelsPerLine,
 245                               cmsUInt32Number LineCount,
 246                               cmsUInt32Number BytesPerLineIn,
 247                               cmsUInt32Number BytesPerLineOut,
 248                               cmsUInt32Number BytesPerPlaneIn,
 249                               cmsUInt32Number BytesPerPlaneOut)
 250 
 251 {
 252     _cmsTRANSFORM* p = (_cmsTRANSFORM*) Transform;
 253     cmsStride stride;
 254 
 255     stride.BytesPerLineIn = BytesPerLineIn;
 256     stride.BytesPerLineOut = BytesPerLineOut;
 257     stride.BytesPerPlaneIn = BytesPerPlaneIn;
 258     stride.BytesPerPlaneOut = BytesPerPlaneOut;
 259 
 260     p->xform(p, InputBuffer, OutputBuffer, PixelsPerLine, LineCount, &stride);
 261 }
 262 
 263 
 264 
 265 // Transform routines ----------------------------------------------------------------------------------------------------------
 266 
 267 // Float xform converts floats. Since there are no performance issues, one routine does all job, including gamut check.
 268 // Note that because extended range, we can use a -1.0 value for out of gamut in this case.
 269 static
 270 void FloatXFORM(_cmsTRANSFORM* p,
 271                 const void* in,
 272                 void* out,
 273                 cmsUInt32Number PixelsPerLine,
 274                 cmsUInt32Number LineCount,
 275                 const cmsStride* Stride)
 276 {
 277     cmsUInt8Number* accum;
 278     cmsUInt8Number* output;
 279     cmsFloat32Number fIn[cmsMAXCHANNELS], fOut[cmsMAXCHANNELS];
 280     cmsFloat32Number OutOfGamut;
 281     cmsUInt32Number i, j, c, strideIn, strideOut;
 282 
 283     _cmsHandleExtraChannels(p, in, out, PixelsPerLine, LineCount, Stride);
 284 
 285     strideIn = 0;
 286     strideOut = 0;
 287 
 288     for (i = 0; i < LineCount; i++) {
 289 
 290         accum = (cmsUInt8Number*)in + strideIn;
 291         output = (cmsUInt8Number*)out + strideOut;
 292 
 293         for (j = 0; j < PixelsPerLine; j++) {
 294 
 295             accum = p->FromInputFloat(p, fIn, accum, Stride->BytesPerPlaneIn);
 296 
 297             // Any gamut chack to do?
 298             if (p->GamutCheck != NULL) {
 299 
 300                 // Evaluate gamut marker.
 301                 cmsPipelineEvalFloat(fIn, &OutOfGamut, p->GamutCheck);
 302 
 303                 // Is current color out of gamut?
 304                 if (OutOfGamut > 0.0) {
 305 
 306                     // Certainly, out of gamut
 307                     for (c = 0; c < cmsMAXCHANNELS; c++)
 308                         fOut[c] = -1.0;
 309 
 310                 }
 311                 else {
 312                     // No, proceed normally
 313                     cmsPipelineEvalFloat(fIn, fOut, p->Lut);
 314                 }
 315             }
 316             else {
 317 
 318                 // No gamut check at all
 319                 cmsPipelineEvalFloat(fIn, fOut, p->Lut);
 320             }
 321 
 322 
 323             output = p->ToOutputFloat(p, fOut, output, Stride->BytesPerPlaneOut);
 324         }
 325 
 326         strideIn += Stride->BytesPerLineIn;
 327         strideOut += Stride->BytesPerLineOut;
 328     }
 329 
 330 }
 331 
 332 
 333 static
 334 void NullFloatXFORM(_cmsTRANSFORM* p,
 335                     const void* in,
 336                     void* out,
 337                     cmsUInt32Number PixelsPerLine,
 338                     cmsUInt32Number LineCount,
 339                     const cmsStride* Stride)
 340 
 341 {
 342     cmsUInt8Number* accum;
 343     cmsUInt8Number* output;
 344     cmsFloat32Number fIn[cmsMAXCHANNELS];
 345     cmsUInt32Number i, j, strideIn, strideOut;
 346 
 347     _cmsHandleExtraChannels(p, in, out, PixelsPerLine, LineCount, Stride);
 348 
 349     strideIn = 0;
 350     strideOut = 0;
 351 
 352     for (i = 0; i < LineCount; i++) {


 353 
 354            accum = (cmsUInt8Number*) in + strideIn;
 355            output = (cmsUInt8Number*) out + strideOut;
 356 
 357            for (j = 0; j < PixelsPerLine; j++) {
 358 
 359                   accum = p->FromInputFloat(p, fIn, accum, Stride ->BytesPerPlaneIn);
 360                   output = p->ToOutputFloat(p, fIn, output, Stride->BytesPerPlaneOut);
 361            }
 362 
 363            strideIn += Stride->BytesPerLineIn;
 364            strideOut += Stride->BytesPerLineOut;
 365     }
 366 }
 367 
 368 // 16 bit precision -----------------------------------------------------------------------------------------------------------
 369 
 370 // Null transformation, only applies formatters. No caché
 371 static
 372 void NullXFORM(_cmsTRANSFORM* p,
 373                const void* in,
 374                void* out,
 375                cmsUInt32Number PixelsPerLine,
 376                cmsUInt32Number LineCount,
 377                const cmsStride* Stride)
 378 {
 379     cmsUInt8Number* accum;
 380     cmsUInt8Number* output;
 381     cmsUInt16Number wIn[cmsMAXCHANNELS];
 382     cmsUInt32Number i, j, strideIn, strideOut;
 383 
 384     _cmsHandleExtraChannels(p, in, out, PixelsPerLine, LineCount, Stride);
 385 
 386     strideIn = 0;
 387     strideOut = 0;
 388 
 389     for (i = 0; i < LineCount; i++) {


 390 
 391            accum = (cmsUInt8Number*)in + strideIn;
 392            output = (cmsUInt8Number*)out + strideOut;
 393 
 394            for (j = 0; j < PixelsPerLine; j++) {
 395 
 396                   accum = p->FromInput(p, wIn, accum, Stride->BytesPerPlaneIn);
 397                   output = p->ToOutput(p, wIn, output, Stride->BytesPerPlaneOut);
 398     }
 399 
 400            strideIn += Stride->BytesPerLineIn;
 401            strideOut += Stride->BytesPerLineOut;
 402     }
 403 
 404 }
 405 
 406 
 407 // No gamut check, no cache, 16 bits
 408 static
 409 void PrecalculatedXFORM(_cmsTRANSFORM* p,
 410                         const void* in,
 411                         void* out,
 412                         cmsUInt32Number PixelsPerLine,
 413                         cmsUInt32Number LineCount,
 414                         const cmsStride* Stride)
 415 {
 416     register cmsUInt8Number* accum;
 417     register cmsUInt8Number* output;
 418     cmsUInt16Number wIn[cmsMAXCHANNELS], wOut[cmsMAXCHANNELS];
 419     cmsUInt32Number i, j, strideIn, strideOut;
 420 
 421     _cmsHandleExtraChannels(p, in, out, PixelsPerLine, LineCount, Stride);


 422 
 423     strideIn = 0;
 424     strideOut = 0;
 425 
 426     for (i = 0; i < LineCount; i++) {
 427 
 428         accum = (cmsUInt8Number*)in + strideIn;
 429         output = (cmsUInt8Number*)out + strideOut;
 430 
 431         for (j = 0; j < PixelsPerLine; j++) {
 432 
 433             accum = p->FromInput(p, wIn, accum, Stride->BytesPerPlaneIn);
 434             p->Lut->Eval16Fn(wIn, wOut, p->Lut->Data);
 435             output = p->ToOutput(p, wOut, output, Stride->BytesPerPlaneOut);
 436         }
 437 
 438         strideIn += Stride->BytesPerLineIn;
 439         strideOut += Stride->BytesPerLineOut;
 440     }
 441 
 442 }
 443 
 444 
 445 // Auxiliary: Handle precalculated gamut check. The retrieval of context may be alittle bit slow, but this function is not critical.
 446 static
 447 void TransformOnePixelWithGamutCheck(_cmsTRANSFORM* p,
 448                                      const cmsUInt16Number wIn[],
 449                                      cmsUInt16Number wOut[])
 450 {
 451     cmsUInt16Number wOutOfGamut;
 452 
 453     p ->GamutCheck ->Eval16Fn(wIn, &wOutOfGamut, p ->GamutCheck ->Data);
 454     if (wOutOfGamut >= 1) {
 455 
 456         cmsUInt16Number i;
 457         _cmsAlarmCodesChunkType* ContextAlarmCodes = (_cmsAlarmCodesChunkType*) _cmsContextGetClientChunk(p->ContextID, AlarmCodesContext);
 458 
 459         for (i=0; i < p ->Lut->OutputChannels; i++) {
 460 
 461             wOut[i] = ContextAlarmCodes ->AlarmCodes[i];
 462         }
 463     }
 464     else
 465         p ->Lut ->Eval16Fn(wIn, wOut, p -> Lut->Data);
 466 }
 467 
 468 // Gamut check, No caché, 16 bits.
 469 static
 470 void PrecalculatedXFORMGamutCheck(_cmsTRANSFORM* p,
 471                                   const void* in,
 472                                   void* out,
 473                                   cmsUInt32Number PixelsPerLine,
 474                                   cmsUInt32Number LineCount,
 475                                   const cmsStride* Stride)
 476 {
 477     cmsUInt8Number* accum;
 478     cmsUInt8Number* output;
 479     cmsUInt16Number wIn[cmsMAXCHANNELS], wOut[cmsMAXCHANNELS];
 480     cmsUInt32Number i, j, strideIn, strideOut;
 481 
 482     _cmsHandleExtraChannels(p, in, out, PixelsPerLine, LineCount, Stride);
 483 
 484     strideIn = 0;
 485     strideOut = 0;
 486 
 487     for (i = 0; i < LineCount; i++) {


 488 
 489            accum = (cmsUInt8Number*)in + strideIn;
 490            output = (cmsUInt8Number*)out + strideOut;
 491 
 492            for (j = 0; j < PixelsPerLine; j++) {
 493 
 494                   accum = p->FromInput(p, wIn, accum, Stride->BytesPerPlaneIn);
 495                   TransformOnePixelWithGamutCheck(p, wIn, wOut);
 496                   output = p->ToOutput(p, wOut, output, Stride->BytesPerPlaneOut);
 497            }
 498 
 499            strideIn += Stride->BytesPerLineIn;
 500            strideOut += Stride->BytesPerLineOut;
 501     }
 502 }
 503 
 504 
 505 // No gamut check, Caché, 16 bits,
 506 static
 507 void CachedXFORM(_cmsTRANSFORM* p,
 508                  const void* in,
 509                  void* out,
 510                  cmsUInt32Number PixelsPerLine,
 511                  cmsUInt32Number LineCount,
 512                  const cmsStride* Stride)
 513 {
 514     cmsUInt8Number* accum;
 515     cmsUInt8Number* output;
 516     cmsUInt16Number wIn[cmsMAXCHANNELS], wOut[cmsMAXCHANNELS];

 517     _cmsCACHE Cache;
 518     cmsUInt32Number i, j, strideIn, strideOut;
 519 
 520     _cmsHandleExtraChannels(p, in, out, PixelsPerLine, LineCount, Stride);


 521 
 522     // Empty buffers for quick memcmp
 523     memset(wIn, 0, sizeof(wIn));
 524     memset(wOut, 0, sizeof(wOut));
 525 
 526     // Get copy of zero cache
 527     memcpy(&Cache, &p->Cache, sizeof(Cache));
 528 
 529     strideIn = 0;
 530     strideOut = 0;
 531 
 532     for (i = 0; i < LineCount; i++) {
 533 
 534         accum = (cmsUInt8Number*)in + strideIn;
 535         output = (cmsUInt8Number*)out + strideOut;
 536 
 537         for (j = 0; j < PixelsPerLine; j++) {
 538 
 539             accum = p->FromInput(p, wIn, accum, Stride->BytesPerPlaneIn);
 540 
 541             if (memcmp(wIn, Cache.CacheIn, sizeof(Cache.CacheIn)) == 0) {
 542 
 543                 memcpy(wOut, Cache.CacheOut, sizeof(Cache.CacheOut));
 544             }
 545             else {
 546                 p->Lut->Eval16Fn(wIn, wOut, p->Lut->Data);

 547 
 548                 memcpy(Cache.CacheIn, wIn, sizeof(Cache.CacheIn));
 549                 memcpy(Cache.CacheOut, wOut, sizeof(Cache.CacheOut));
 550             }
 551 
 552             output = p->ToOutput(p, wOut, output, Stride->BytesPerPlaneOut);
 553         }
 554 
 555         strideIn += Stride->BytesPerLineIn;
 556         strideOut += Stride->BytesPerLineOut;
 557     }
 558 }
 559 

 560 // All those nice features together
 561 static
 562 void CachedXFORMGamutCheck(_cmsTRANSFORM* p,
 563                            const void* in,
 564                            void* out,
 565                            cmsUInt32Number PixelsPerLine,
 566                            cmsUInt32Number LineCount,
 567                            const cmsStride* Stride)
 568 {
 569     cmsUInt8Number* accum;
 570     cmsUInt8Number* output;
 571     cmsUInt16Number wIn[cmsMAXCHANNELS], wOut[cmsMAXCHANNELS];

 572     _cmsCACHE Cache;
 573     cmsUInt32Number i, j, strideIn, strideOut;
 574 
 575     _cmsHandleExtraChannels(p, in, out, PixelsPerLine, LineCount, Stride);


 576 
 577     // Empty buffers for quick memcmp
 578     memset(wIn, 0, sizeof(wIn));
 579     memset(wOut, 0, sizeof(wOut));
 580 
 581     // Get copy of zero cache
 582     memcpy(&Cache, &p->Cache, sizeof(Cache));
 583 
 584     strideIn = 0;
 585     strideOut = 0;
 586 
 587     for (i = 0; i < LineCount; i++) {
 588 
 589         accum = (cmsUInt8Number*)in + strideIn;
 590         output = (cmsUInt8Number*)out + strideOut;
 591 
 592         for (j = 0; j < PixelsPerLine; j++) {
 593 
 594             accum = p->FromInput(p, wIn, accum, Stride->BytesPerPlaneIn);
 595 
 596             if (memcmp(wIn, Cache.CacheIn, sizeof(Cache.CacheIn)) == 0) {
 597 
 598                 memcpy(wOut, Cache.CacheOut, sizeof(Cache.CacheOut));
 599             }
 600             else {
 601                 TransformOnePixelWithGamutCheck(p, wIn, wOut);
 602 
 603                 memcpy(Cache.CacheIn, wIn, sizeof(Cache.CacheIn));
 604                 memcpy(Cache.CacheOut, wOut, sizeof(Cache.CacheOut));
 605             }
 606 
 607             output = p->ToOutput(p, wOut, output, Stride->BytesPerPlaneOut);
 608         }
 609 
 610         strideIn += Stride->BytesPerLineIn;
 611         strideOut += Stride->BytesPerLineOut;
 612     }
 613 }
 614 
 615 // Transform plug-ins ----------------------------------------------------------------------------------------------------
 616 
 617 // List of used-defined transform factories
 618 typedef struct _cmsTransformCollection_st {
 619 
 620     _cmsTransform2Factory  Factory;
 621     cmsBool                OldXform;   // Factory returns xform function in the old style
 622 
 623     struct _cmsTransformCollection_st *Next;
 624 
 625 } _cmsTransformCollection;
 626 
 627 // The linked list head
 628 _cmsTransformPluginChunkType _cmsTransformPluginChunk = { NULL };
 629 
 630 
 631 // Duplicates the zone of memory used by the plug-in in the new context
 632 static
 633 void DupPluginTransformList(struct _cmsContext_struct* ctx,
 634                                                const struct _cmsContext_struct* src)
 635 {
 636    _cmsTransformPluginChunkType newHead = { NULL };
 637    _cmsTransformCollection*  entry;
 638    _cmsTransformCollection*  Anterior = NULL;
 639    _cmsTransformPluginChunkType* head = (_cmsTransformPluginChunkType*) src->chunks[TransformPlugin];
 640 
 641     // Walk the list copying all nodes
 642    for (entry = head->TransformCollection;


 645 
 646             _cmsTransformCollection *newEntry = ( _cmsTransformCollection *) _cmsSubAllocDup(ctx ->MemPool, entry, sizeof(_cmsTransformCollection));
 647 
 648             if (newEntry == NULL)
 649                 return;
 650 
 651             // We want to keep the linked list order, so this is a little bit tricky
 652             newEntry -> Next = NULL;
 653             if (Anterior)
 654                 Anterior -> Next = newEntry;
 655 
 656             Anterior = newEntry;
 657 
 658             if (newHead.TransformCollection == NULL)
 659                 newHead.TransformCollection = newEntry;
 660     }
 661 
 662   ctx ->chunks[TransformPlugin] = _cmsSubAllocDup(ctx->MemPool, &newHead, sizeof(_cmsTransformPluginChunkType));
 663 }
 664 
 665 // Allocates memory for transform plugin factory
 666 void _cmsAllocTransformPluginChunk(struct _cmsContext_struct* ctx,
 667                                         const struct _cmsContext_struct* src)
 668 {
 669     if (src != NULL) {
 670 
 671         // Copy all linked list
 672         DupPluginTransformList(ctx, src);
 673     }
 674     else {
 675         static _cmsTransformPluginChunkType TransformPluginChunkType = { NULL };
 676         ctx ->chunks[TransformPlugin] = _cmsSubAllocDup(ctx ->MemPool, &TransformPluginChunkType, sizeof(_cmsTransformPluginChunkType));
 677     }
 678 }
 679 
 680 // Adaptor for old versions of plug-in
 681 static
 682 void _cmsTransform2toTransformAdaptor(struct _cmstransform_struct *CMMcargo,
 683                                       const void* InputBuffer,
 684                                       void* OutputBuffer,
 685                                       cmsUInt32Number PixelsPerLine,
 686                                       cmsUInt32Number LineCount,
 687                                       const cmsStride* Stride)
 688 {
 689 
 690        cmsUInt32Number i, strideIn, strideOut;
 691 
 692        _cmsHandleExtraChannels(CMMcargo, InputBuffer, OutputBuffer, PixelsPerLine, LineCount, Stride);
 693 
 694        strideIn = 0;
 695        strideOut = 0;
 696 
 697        for (i = 0; i < LineCount; i++) {
 698 
 699               void *accum = (cmsUInt8Number*)InputBuffer + strideIn;
 700               void *output = (cmsUInt8Number*)OutputBuffer + strideOut;
 701 
 702               CMMcargo->OldXform(CMMcargo, accum, output, PixelsPerLine, Stride->BytesPerPlaneIn);
 703 
 704               strideIn += Stride->BytesPerLineIn;
 705               strideOut += Stride->BytesPerLineOut;
 706        }
 707 }
 708 
 709 
 710 
 711 // Register new ways to transform
 712 cmsBool  _cmsRegisterTransformPlugin(cmsContext ContextID, cmsPluginBase* Data)
 713 {
 714     cmsPluginTransform* Plugin = (cmsPluginTransform*) Data;
 715     _cmsTransformCollection* fl;
 716     _cmsTransformPluginChunkType* ctx = ( _cmsTransformPluginChunkType*) _cmsContextGetClientChunk(ContextID,TransformPlugin);
 717 
 718     if (Data == NULL) {
 719 
 720         // Free the chain. Memory is safely freed at exit
 721         ctx->TransformCollection = NULL;
 722         return TRUE;
 723     }
 724 
 725     // Factory callback is required
 726     if (Plugin->factories.xform == NULL) return FALSE;
 727 
 728 
 729     fl = (_cmsTransformCollection*) _cmsPluginMalloc(ContextID, sizeof(_cmsTransformCollection));
 730     if (fl == NULL) return FALSE;
 731 
 732     // Check for full xform plug-ins previous to 2.8, we would need an adapter in that case
 733     if (Plugin->base.ExpectedVersion < 2080) {
 734 
 735            fl->OldXform = TRUE;
 736     }
 737     else
 738            fl->OldXform = FALSE;
 739 
 740     // Copy the parameters
 741     fl->Factory = Plugin->factories.xform;
 742 
 743     // Keep linked list
 744     fl ->Next = ctx->TransformCollection;
 745     ctx->TransformCollection = fl;
 746 
 747     // All is ok
 748     return TRUE;
 749 }
 750 
 751 
 752 void CMSEXPORT _cmsSetTransformUserData(struct _cmstransform_struct *CMMcargo, void* ptr, _cmsFreeUserDataFn FreePrivateDataFn)
 753 {
 754     _cmsAssert(CMMcargo != NULL);
 755     CMMcargo ->UserData = ptr;
 756     CMMcargo ->FreeUserData = FreePrivateDataFn;
 757 }
 758 
 759 // returns the pointer defined by the plug-in to store private data
 760 void * CMSEXPORT _cmsGetTransformUserData(struct _cmstransform_struct *CMMcargo)
 761 {


 806 
 807                             // Last plugin in the declaration order takes control. We just keep
 808                             // the original parameters as a logging.
 809                             // Note that cmsFLAGS_CAN_CHANGE_FORMATTER is not set, so by default
 810                             // an optimized transform is not reusable. The plug-in can, however, change
 811                             // the flags and make it suitable.
 812 
 813                             p->ContextID = ContextID;
 814                             p->InputFormat = *InputFormat;
 815                             p->OutputFormat = *OutputFormat;
 816                             p->dwOriginalFlags = *dwFlags;
 817 
 818                             // Fill the formatters just in case the optimized routine is interested.
 819                             // No error is thrown if the formatter doesn't exist. It is up to the optimization
 820                             // factory to decide what to do in those cases.
 821                             p->FromInput = _cmsGetFormatter(ContextID, *InputFormat, cmsFormatterInput, CMS_PACK_FLAGS_16BITS).Fmt16;
 822                             p->ToOutput = _cmsGetFormatter(ContextID, *OutputFormat, cmsFormatterOutput, CMS_PACK_FLAGS_16BITS).Fmt16;
 823                             p->FromInputFloat = _cmsGetFormatter(ContextID, *InputFormat, cmsFormatterInput, CMS_PACK_FLAGS_FLOAT).FmtFloat;
 824                             p->ToOutputFloat = _cmsGetFormatter(ContextID, *OutputFormat, cmsFormatterOutput, CMS_PACK_FLAGS_FLOAT).FmtFloat;
 825 
 826                             // Save the day?
 827                             if (Plugin->OldXform) {
 828                                    p->OldXform = (_cmsTransformFn) p->xform;
 829                                    p->xform = _cmsTransform2toTransformAdaptor;
 830                             }
 831 
 832                             return p;
 833                      }
 834               }
 835 
 836               // Not suitable for the transform plug-in, let's check  the pipeline plug-in
 837               _cmsOptimizePipeline(ContextID, &p->Lut, Intent, InputFormat, OutputFormat, dwFlags);
 838        }
 839 
 840     // Check whatever this is a true floating point transform
 841     if (_cmsFormatterIsFloat(*InputFormat) && _cmsFormatterIsFloat(*OutputFormat)) {
 842 
 843         // Get formatter function always return a valid union, but the contents of this union may be NULL.
 844         p ->FromInputFloat = _cmsGetFormatter(ContextID, *InputFormat,  cmsFormatterInput, CMS_PACK_FLAGS_FLOAT).FmtFloat;
 845         p ->ToOutputFloat  = _cmsGetFormatter(ContextID, *OutputFormat, cmsFormatterOutput, CMS_PACK_FLAGS_FLOAT).FmtFloat;
 846         *dwFlags |= cmsFLAGS_CAN_CHANGE_FORMATTER;
 847 
 848         if (p ->FromInputFloat == NULL || p ->ToOutputFloat == NULL) {
 849 
 850             cmsSignalError(ContextID, cmsERROR_UNKNOWN_EXTENSION, "Unsupported raster format");
 851             _cmsFree(ContextID, p);


 972 }
 973 
 974 // Check colorspace
 975 static
 976 cmsBool  IsProperColorSpace(cmsColorSpaceSignature Check, cmsUInt32Number dwFormat)
 977 {
 978     int Space1 = T_COLORSPACE(dwFormat);
 979     int Space2 = _cmsLCMScolorSpace(Check);
 980 
 981     if (Space1 == PT_ANY) return TRUE;
 982     if (Space1 == Space2) return TRUE;
 983 
 984     if (Space1 == PT_LabV2 && Space2 == PT_Lab) return TRUE;
 985     if (Space1 == PT_Lab   && Space2 == PT_LabV2) return TRUE;
 986 
 987     return FALSE;
 988 }
 989 
 990 // ----------------------------------------------------------------------------------------------------------------
 991 
 992 // Jun-21-2000: Some profiles (those that comes with W2K) comes
 993 // with the media white (media black?) x 100. Add a sanity check
 994 
 995 static
 996 void NormalizeXYZ(cmsCIEXYZ* Dest)
 997 {
 998     while (Dest -> X > 2. &&
 999            Dest -> Y > 2. &&
1000            Dest -> Z > 2.) {
1001 
1002                Dest -> X /= 10.;
1003                Dest -> Y /= 10.;
1004                Dest -> Z /= 10.;
1005        }
1006 }
1007 
1008 static
1009 void SetWhitePoint(cmsCIEXYZ* wtPt, const cmsCIEXYZ* src)
1010 {
1011     if (src == NULL) {
1012         wtPt ->X = cmsD50X;
1013         wtPt ->Y = cmsD50Y;
1014         wtPt ->Z = cmsD50Z;
1015     }
1016     else {
1017         wtPt ->X = src->X;
1018         wtPt ->Y = src->Y;
1019         wtPt ->Z = src->Z;
1020 
1021         NormalizeXYZ(wtPt);
1022     }
1023 
1024 }
1025 
1026 // New to lcms 2.0 -- have all parameters available.
1027 cmsHTRANSFORM CMSEXPORT cmsCreateExtendedTransform(cmsContext ContextID,
1028                                                    cmsUInt32Number nProfiles, cmsHPROFILE hProfiles[],
1029                                                    cmsBool  BPC[],
1030                                                    cmsUInt32Number Intents[],
1031                                                    cmsFloat64Number AdaptationStates[],
1032                                                    cmsHPROFILE hGamutProfile,
1033                                                    cmsUInt32Number nGamutPCSposition,
1034                                                    cmsUInt32Number InputFormat,
1035                                                    cmsUInt32Number OutputFormat,
1036                                                    cmsUInt32Number dwFlags)
1037 {
1038     _cmsTRANSFORM* xform;
1039     cmsColorSpaceSignature EntryColorSpace;
1040     cmsColorSpaceSignature ExitColorSpace;
1041     cmsPipeline* Lut;


1312 {
1313     _cmsTRANSFORM* xform = (_cmsTRANSFORM*) hTransform;
1314 
1315     if (xform == NULL) return 0;
1316     return xform->InputFormat;
1317 }
1318 
1319 cmsUInt32Number CMSEXPORT cmsGetTransformOutputFormat(cmsHTRANSFORM hTransform)
1320 {
1321     _cmsTRANSFORM* xform = (_cmsTRANSFORM*) hTransform;
1322 
1323     if (xform == NULL) return 0;
1324     return xform->OutputFormat;
1325 }
1326 
1327 // For backwards compatibility
1328 cmsBool CMSEXPORT cmsChangeBuffersFormat(cmsHTRANSFORM hTransform,
1329                                          cmsUInt32Number InputFormat,
1330                                          cmsUInt32Number OutputFormat)
1331 {

1332     _cmsTRANSFORM* xform = (_cmsTRANSFORM*) hTransform;
1333     cmsFormatter16 FromInput, ToOutput;
1334 
1335 
1336     // We only can afford to change formatters if previous transform is at least 16 bits
1337     if (!(xform ->dwOriginalFlags & cmsFLAGS_CAN_CHANGE_FORMATTER)) {
1338 
1339         cmsSignalError(xform ->ContextID, cmsERROR_NOT_SUITABLE, "cmsChangeBuffersFormat works only on transforms created originally with at least 16 bits of precision");
1340         return FALSE;
1341     }
1342 
1343     FromInput = _cmsGetFormatter(xform->ContextID, InputFormat,  cmsFormatterInput, CMS_PACK_FLAGS_16BITS).Fmt16;
1344     ToOutput  = _cmsGetFormatter(xform->ContextID, OutputFormat, cmsFormatterOutput, CMS_PACK_FLAGS_16BITS).Fmt16;
1345 
1346     if (FromInput == NULL || ToOutput == NULL) {
1347 
1348         cmsSignalError(xform -> ContextID, cmsERROR_UNKNOWN_EXTENSION, "Unsupported raster format");
1349         return FALSE;
1350     }
1351 
< prev index next >