< prev index next >

src/java.desktop/share/native/liblcms/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-2017 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 //---------------------------------------------------------------------------------


 183         cmsPipelineFree(p -> GamutCheck);
 184 
 185     if (p -> Lut)
 186         cmsPipelineFree(p -> Lut);
 187 
 188     if (p ->InputColorant)
 189         cmsFreeNamedColorList(p ->InputColorant);
 190 
 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 


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


 400                   accum = p->FromInput(p, wIn, accum, Stride->BytesPerPlaneIn);
 401                   output = p->ToOutput(p, wIn, output, Stride->BytesPerPlaneOut);
 402     }
 403 
 404            strideIn += Stride->BytesPerLineIn;
 405            strideOut += Stride->BytesPerLineOut;
 406     }
 407 
 408 }
 409 
 410 
 411 // No gamut check, no cache, 16 bits
 412 static
 413 void PrecalculatedXFORM(_cmsTRANSFORM* p,
 414                         const void* in,
 415                         void* out,
 416                         cmsUInt32Number PixelsPerLine,
 417                         cmsUInt32Number LineCount,
 418                         const cmsStride* Stride)
 419 {
 420     register cmsUInt8Number* accum;
 421     register cmsUInt8Number* output;
 422     cmsUInt16Number wIn[cmsMAXCHANNELS], wOut[cmsMAXCHANNELS];
 423     cmsUInt32Number i, j, strideIn, strideOut;
 424 
 425     _cmsHandleExtraChannels(p, in, out, PixelsPerLine, LineCount, Stride);
 426 
 427     strideIn = 0;
 428     strideOut = 0;
 429     memset(wIn, 0, sizeof(wIn));
 430     memset(wOut, 0, sizeof(wOut));
 431 
 432     for (i = 0; i < LineCount; i++) {
 433 
 434         accum = (cmsUInt8Number*)in + strideIn;
 435         output = (cmsUInt8Number*)out + strideOut;
 436 
 437         for (j = 0; j < PixelsPerLine; j++) {
 438 
 439             accum = p->FromInput(p, wIn, accum, Stride->BytesPerPlaneIn);
 440             p->Lut->Eval16Fn(wIn, wOut, p->Lut->Data);
 441             output = p->ToOutput(p, wOut, output, Stride->BytesPerPlaneOut);


 454                                      const cmsUInt16Number wIn[],
 455                                      cmsUInt16Number wOut[])
 456 {
 457     cmsUInt16Number wOutOfGamut;
 458 
 459     p ->GamutCheck ->Eval16Fn(wIn, &wOutOfGamut, p ->GamutCheck ->Data);
 460     if (wOutOfGamut >= 1) {
 461 
 462         cmsUInt16Number i;
 463         _cmsAlarmCodesChunkType* ContextAlarmCodes = (_cmsAlarmCodesChunkType*) _cmsContextGetClientChunk(p->ContextID, AlarmCodesContext);
 464 
 465         for (i=0; i < p ->Lut->OutputChannels; i++) {
 466 
 467             wOut[i] = ContextAlarmCodes ->AlarmCodes[i];
 468         }
 469     }
 470     else
 471         p ->Lut ->Eval16Fn(wIn, wOut, p -> Lut->Data);
 472 }
 473 
 474 // Gamut check, No caché, 16 bits.
 475 static
 476 void PrecalculatedXFORMGamutCheck(_cmsTRANSFORM* p,
 477                                   const void* in,
 478                                   void* out,
 479                                   cmsUInt32Number PixelsPerLine,
 480                                   cmsUInt32Number LineCount,
 481                                   const cmsStride* Stride)
 482 {
 483     cmsUInt8Number* accum;
 484     cmsUInt8Number* output;
 485     cmsUInt16Number wIn[cmsMAXCHANNELS], wOut[cmsMAXCHANNELS];
 486     cmsUInt32Number i, j, strideIn, strideOut;
 487 
 488     _cmsHandleExtraChannels(p, in, out, PixelsPerLine, LineCount, Stride);
 489 
 490     strideIn = 0;
 491     strideOut = 0;
 492     memset(wIn, 0, sizeof(wIn));
 493     memset(wOut, 0, sizeof(wOut));
 494 
 495     for (i = 0; i < LineCount; i++) {
 496 
 497            accum = (cmsUInt8Number*)in + strideIn;
 498            output = (cmsUInt8Number*)out + strideOut;
 499 
 500            for (j = 0; j < PixelsPerLine; j++) {
 501 
 502                   accum = p->FromInput(p, wIn, accum, Stride->BytesPerPlaneIn);
 503                   TransformOnePixelWithGamutCheck(p, wIn, wOut);
 504                   output = p->ToOutput(p, wOut, output, Stride->BytesPerPlaneOut);
 505            }
 506 
 507            strideIn += Stride->BytesPerLineIn;
 508            strideOut += Stride->BytesPerLineOut;
 509     }
 510 }
 511 
 512 
 513 // No gamut check, Caché, 16 bits,
 514 static
 515 void CachedXFORM(_cmsTRANSFORM* p,
 516                  const void* in,
 517                  void* out,
 518                  cmsUInt32Number PixelsPerLine,
 519                  cmsUInt32Number LineCount,
 520                  const cmsStride* Stride)
 521 {
 522     cmsUInt8Number* accum;
 523     cmsUInt8Number* output;
 524     cmsUInt16Number wIn[cmsMAXCHANNELS], wOut[cmsMAXCHANNELS];
 525     _cmsCACHE Cache;
 526     cmsUInt32Number i, j, strideIn, strideOut;
 527 
 528     _cmsHandleExtraChannels(p, in, out, PixelsPerLine, LineCount, Stride);
 529 
 530     // Empty buffers for quick memcmp
 531     memset(wIn, 0, sizeof(wIn));
 532     memset(wOut, 0, sizeof(wOut));
 533 


 792 static
 793 _cmsTRANSFORM* AllocEmptyTransform(cmsContext ContextID, cmsPipeline* lut,
 794                                                cmsUInt32Number Intent, cmsUInt32Number* InputFormat, cmsUInt32Number* OutputFormat, cmsUInt32Number* dwFlags)
 795 {
 796      _cmsTransformPluginChunkType* ctx = ( _cmsTransformPluginChunkType*) _cmsContextGetClientChunk(ContextID, TransformPlugin);
 797      _cmsTransformCollection* Plugin;
 798 
 799        // Allocate needed memory
 800        _cmsTRANSFORM* p = (_cmsTRANSFORM*)_cmsMallocZero(ContextID, sizeof(_cmsTRANSFORM));
 801        if (!p) {
 802               cmsPipelineFree(lut);
 803               return NULL;
 804        }
 805 
 806        // Store the proposed pipeline
 807        p->Lut = lut;
 808 
 809        // Let's see if any plug-in want to do the transform by itself
 810        if (p->Lut != NULL) {
 811 


 812               for (Plugin = ctx->TransformCollection;
 813                      Plugin != NULL;
 814                      Plugin = Plugin->Next) {
 815 
 816                      if (Plugin->Factory(&p->xform, &p->UserData, &p->FreeUserData, &p->Lut, InputFormat, OutputFormat, dwFlags)) {
 817 
 818                             // Last plugin in the declaration order takes control. We just keep
 819                             // the original parameters as a logging.
 820                             // Note that cmsFLAGS_CAN_CHANGE_FORMATTER is not set, so by default
 821                             // an optimized transform is not reusable. The plug-in can, however, change
 822                             // the flags and make it suitable.
 823 
 824                             p->ContextID = ContextID;
 825                             p->InputFormat = *InputFormat;
 826                             p->OutputFormat = *OutputFormat;
 827                             p->dwOriginalFlags = *dwFlags;
 828 
 829                             // Fill the formatters just in case the optimized routine is interested.
 830                             // No error is thrown if the formatter doesn't exist. It is up to the optimization
 831                             // factory to decide what to do in those cases.
 832                             p->FromInput = _cmsGetFormatter(ContextID, *InputFormat, cmsFormatterInput, CMS_PACK_FLAGS_16BITS).Fmt16;
 833                             p->ToOutput = _cmsGetFormatter(ContextID, *OutputFormat, cmsFormatterOutput, CMS_PACK_FLAGS_16BITS).Fmt16;
 834                             p->FromInputFloat = _cmsGetFormatter(ContextID, *InputFormat, cmsFormatterInput, CMS_PACK_FLAGS_FLOAT).FmtFloat;
 835                             p->ToOutputFloat = _cmsGetFormatter(ContextID, *OutputFormat, cmsFormatterOutput, CMS_PACK_FLAGS_FLOAT).FmtFloat;
 836 
 837                             // Save the day? (Ignore the warning)
 838                             if (Plugin->OldXform) {
 839                                    p->OldXform = (_cmsTransformFn)(void*) p->xform;
 840                                    p->xform = _cmsTransform2toTransformAdaptor;
 841                             }
 842 
 843                             return p;
 844                      }
 845               }

 846 
 847               // Not suitable for the transform plug-in, let's check  the pipeline plug-in
 848               _cmsOptimizePipeline(ContextID, &p->Lut, Intent, InputFormat, OutputFormat, dwFlags);
 849        }
 850 
 851     // Check whatever this is a true floating point transform
 852     if (_cmsFormatterIsFloat(*InputFormat) && _cmsFormatterIsFloat(*OutputFormat)) {
 853 
 854         // Get formatter function always return a valid union, but the contents of this union may be NULL.
 855         p ->FromInputFloat = _cmsGetFormatter(ContextID, *InputFormat,  cmsFormatterInput, CMS_PACK_FLAGS_FLOAT).FmtFloat;
 856         p ->ToOutputFloat  = _cmsGetFormatter(ContextID, *OutputFormat, cmsFormatterOutput, CMS_PACK_FLAGS_FLOAT).FmtFloat;
 857         *dwFlags |= cmsFLAGS_CAN_CHANGE_FORMATTER;
 858 
 859         if (p ->FromInputFloat == NULL || p ->ToOutputFloat == NULL) {
 860 
 861             cmsSignalError(ContextID, cmsERROR_UNKNOWN_EXTENSION, "Unsupported raster format");
 862             cmsDeleteTransform(p);
 863             return NULL;
 864         }
 865 
 866         if (*dwFlags & cmsFLAGS_NULLTRANSFORM) {
 867 
 868             p ->xform = NullFloatXFORM;
 869         }
 870         else {
 871             // Float transforms don't use caché, always are non-NULL
 872             p ->xform = FloatXFORM;
 873         }
 874 
 875     }
 876     else {
 877 
 878         if (*InputFormat == 0 && *OutputFormat == 0) {
 879             p ->FromInput = p ->ToOutput = NULL;
 880             *dwFlags |= cmsFLAGS_CAN_CHANGE_FORMATTER;
 881         }
 882         else {
 883 
 884             cmsUInt32Number BytesPerPixelInput;
 885 
 886             p ->FromInput = _cmsGetFormatter(ContextID, *InputFormat,  cmsFormatterInput, CMS_PACK_FLAGS_16BITS).Fmt16;
 887             p ->ToOutput  = _cmsGetFormatter(ContextID, *OutputFormat, cmsFormatterOutput, CMS_PACK_FLAGS_16BITS).Fmt16;
 888 
 889             if (p ->FromInput == NULL || p ->ToOutput == NULL) {
 890 
 891                 cmsSignalError(ContextID, cmsERROR_UNKNOWN_EXTENSION, "Unsupported raster format");
 892                 cmsDeleteTransform(p);
 893                 return NULL;
 894             }
 895 
 896             BytesPerPixelInput = T_BYTES(p ->InputFormat);
 897             if (BytesPerPixelInput == 0 || BytesPerPixelInput >= 2)
 898                    *dwFlags |= cmsFLAGS_CAN_CHANGE_FORMATTER;
 899 
 900         }
 901 
 902         if (*dwFlags & cmsFLAGS_NULLTRANSFORM) {
 903 
 904             p ->xform = NullXFORM;
 905         }
 906         else {
 907             if (*dwFlags & cmsFLAGS_NOCACHE) {
 908 
 909                 if (*dwFlags & cmsFLAGS_GAMUTCHECK)
 910                     p ->xform = PrecalculatedXFORMGamutCheck;  // Gamut check, no caché
 911                 else
 912                     p ->xform = PrecalculatedXFORM;  // No caché, no gamut check
 913             }
 914             else {
 915 
 916                 if (*dwFlags & cmsFLAGS_GAMUTCHECK)
 917                     p ->xform = CachedXFORMGamutCheck;    // Gamut check, caché
 918                 else
 919                     p ->xform = CachedXFORM;  // No gamut check, caché
 920 
 921             }
 922         }
 923     }
 924 
 925     p ->InputFormat     = *InputFormat;
 926     p ->OutputFormat    = *OutputFormat;
 927     p ->dwOriginalFlags = *dwFlags;
 928     p ->ContextID       = ContextID;
 929     p ->UserData        = NULL;
 930     return p;
 931 }
 932 
 933 static
 934 cmsBool GetXFormColorSpaces(cmsUInt32Number nProfiles, cmsHPROFILE hProfiles[], cmsColorSpaceSignature* Input, cmsColorSpaceSignature* Output)
 935 {
 936     cmsColorSpaceSignature ColorSpaceIn, ColorSpaceOut;
 937     cmsColorSpaceSignature PostColorSpace;
 938     cmsUInt32Number i;
 939 




  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-2020 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 //---------------------------------------------------------------------------------


 183         cmsPipelineFree(p -> GamutCheck);
 184 
 185     if (p -> Lut)
 186         cmsPipelineFree(p -> Lut);
 187 
 188     if (p ->InputColorant)
 189         cmsFreeNamedColorList(p ->InputColorant);
 190 
 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 
 204 static
 205 cmsUInt32Number PixelSize(cmsUInt32Number Format)
 206 {
 207     cmsUInt32Number fmt_bytes = T_BYTES(Format);
 208 
 209     // For double, the T_BYTES field is zero
 210     if (fmt_bytes == 0)
 211         return sizeof(cmsUInt64Number);
 212 
 213     // Otherwise, it is already correct for all formats
 214     return fmt_bytes;
 215 }
 216 
 217 
 218 
 219 
 220 // Apply transform.
 221 void CMSEXPORT cmsDoTransform(cmsHTRANSFORM  Transform,
 222                               const void* InputBuffer,
 223                               void* OutputBuffer,
 224                               cmsUInt32Number Size)
 225 
 226 {
 227     _cmsTRANSFORM* p = (_cmsTRANSFORM*) Transform;
 228     cmsStride stride;
 229 
 230     stride.BytesPerLineIn = 0;  // Not used
 231     stride.BytesPerLineOut = 0;
 232     stride.BytesPerPlaneIn = Size * PixelSize(p->InputFormat);
 233     stride.BytesPerPlaneOut = Size * PixelSize(p->OutputFormat);
 234 
 235     p -> xform(p, InputBuffer, OutputBuffer, Size, 1, &stride);
 236 }
 237 
 238 
 239 // This is a legacy stride for planar
 240 void CMSEXPORT cmsDoTransformStride(cmsHTRANSFORM  Transform,
 241                               const void* InputBuffer,
 242                               void* OutputBuffer,
 243                               cmsUInt32Number Size, cmsUInt32Number Stride)
 244 
 245 {
 246     _cmsTRANSFORM* p = (_cmsTRANSFORM*) Transform;
 247     cmsStride stride;
 248 
 249     stride.BytesPerLineIn = 0;
 250     stride.BytesPerLineOut = 0;
 251     stride.BytesPerPlaneIn = Stride;
 252     stride.BytesPerPlaneOut = Stride;
 253 


 370     memset(fIn, 0, sizeof(fIn));
 371 
 372     for (i = 0; i < LineCount; i++) {
 373 
 374            accum = (cmsUInt8Number*) in + strideIn;
 375            output = (cmsUInt8Number*) out + strideOut;
 376 
 377            for (j = 0; j < PixelsPerLine; j++) {
 378 
 379                   accum = p->FromInputFloat(p, fIn, accum, Stride ->BytesPerPlaneIn);
 380                   output = p->ToOutputFloat(p, fIn, output, Stride->BytesPerPlaneOut);
 381            }
 382 
 383            strideIn += Stride->BytesPerLineIn;
 384            strideOut += Stride->BytesPerLineOut;
 385     }
 386 }
 387 
 388 // 16 bit precision -----------------------------------------------------------------------------------------------------------
 389 
 390 // Null transformation, only applies formatters. No cache
 391 static
 392 void NullXFORM(_cmsTRANSFORM* p,
 393                const void* in,
 394                void* out,
 395                cmsUInt32Number PixelsPerLine,
 396                cmsUInt32Number LineCount,
 397                const cmsStride* Stride)
 398 {
 399     cmsUInt8Number* accum;
 400     cmsUInt8Number* output;
 401     cmsUInt16Number wIn[cmsMAXCHANNELS];
 402     cmsUInt32Number i, j, strideIn, strideOut;
 403 
 404     _cmsHandleExtraChannels(p, in, out, PixelsPerLine, LineCount, Stride);
 405 
 406     strideIn = 0;
 407     strideOut = 0;
 408     memset(wIn, 0, sizeof(wIn));
 409 
 410     for (i = 0; i < LineCount; i++) {


 417                   accum = p->FromInput(p, wIn, accum, Stride->BytesPerPlaneIn);
 418                   output = p->ToOutput(p, wIn, output, Stride->BytesPerPlaneOut);
 419     }
 420 
 421            strideIn += Stride->BytesPerLineIn;
 422            strideOut += Stride->BytesPerLineOut;
 423     }
 424 
 425 }
 426 
 427 
 428 // No gamut check, no cache, 16 bits
 429 static
 430 void PrecalculatedXFORM(_cmsTRANSFORM* p,
 431                         const void* in,
 432                         void* out,
 433                         cmsUInt32Number PixelsPerLine,
 434                         cmsUInt32Number LineCount,
 435                         const cmsStride* Stride)
 436 {
 437     CMSREGISTER cmsUInt8Number* accum;
 438     CMSREGISTER cmsUInt8Number* output;
 439     cmsUInt16Number wIn[cmsMAXCHANNELS], wOut[cmsMAXCHANNELS];
 440     cmsUInt32Number i, j, strideIn, strideOut;
 441 
 442     _cmsHandleExtraChannels(p, in, out, PixelsPerLine, LineCount, Stride);
 443 
 444     strideIn = 0;
 445     strideOut = 0;
 446     memset(wIn, 0, sizeof(wIn));
 447     memset(wOut, 0, sizeof(wOut));
 448 
 449     for (i = 0; i < LineCount; i++) {
 450 
 451         accum = (cmsUInt8Number*)in + strideIn;
 452         output = (cmsUInt8Number*)out + strideOut;
 453 
 454         for (j = 0; j < PixelsPerLine; j++) {
 455 
 456             accum = p->FromInput(p, wIn, accum, Stride->BytesPerPlaneIn);
 457             p->Lut->Eval16Fn(wIn, wOut, p->Lut->Data);
 458             output = p->ToOutput(p, wOut, output, Stride->BytesPerPlaneOut);


 471                                      const cmsUInt16Number wIn[],
 472                                      cmsUInt16Number wOut[])
 473 {
 474     cmsUInt16Number wOutOfGamut;
 475 
 476     p ->GamutCheck ->Eval16Fn(wIn, &wOutOfGamut, p ->GamutCheck ->Data);
 477     if (wOutOfGamut >= 1) {
 478 
 479         cmsUInt16Number i;
 480         _cmsAlarmCodesChunkType* ContextAlarmCodes = (_cmsAlarmCodesChunkType*) _cmsContextGetClientChunk(p->ContextID, AlarmCodesContext);
 481 
 482         for (i=0; i < p ->Lut->OutputChannels; i++) {
 483 
 484             wOut[i] = ContextAlarmCodes ->AlarmCodes[i];
 485         }
 486     }
 487     else
 488         p ->Lut ->Eval16Fn(wIn, wOut, p -> Lut->Data);
 489 }
 490 
 491 // Gamut check, No cache, 16 bits.
 492 static
 493 void PrecalculatedXFORMGamutCheck(_cmsTRANSFORM* p,
 494                                   const void* in,
 495                                   void* out,
 496                                   cmsUInt32Number PixelsPerLine,
 497                                   cmsUInt32Number LineCount,
 498                                   const cmsStride* Stride)
 499 {
 500     cmsUInt8Number* accum;
 501     cmsUInt8Number* output;
 502     cmsUInt16Number wIn[cmsMAXCHANNELS], wOut[cmsMAXCHANNELS];
 503     cmsUInt32Number i, j, strideIn, strideOut;
 504 
 505     _cmsHandleExtraChannels(p, in, out, PixelsPerLine, LineCount, Stride);
 506 
 507     strideIn = 0;
 508     strideOut = 0;
 509     memset(wIn, 0, sizeof(wIn));
 510     memset(wOut, 0, sizeof(wOut));
 511 
 512     for (i = 0; i < LineCount; i++) {
 513 
 514            accum = (cmsUInt8Number*)in + strideIn;
 515            output = (cmsUInt8Number*)out + strideOut;
 516 
 517            for (j = 0; j < PixelsPerLine; j++) {
 518 
 519                   accum = p->FromInput(p, wIn, accum, Stride->BytesPerPlaneIn);
 520                   TransformOnePixelWithGamutCheck(p, wIn, wOut);
 521                   output = p->ToOutput(p, wOut, output, Stride->BytesPerPlaneOut);
 522            }
 523 
 524            strideIn += Stride->BytesPerLineIn;
 525            strideOut += Stride->BytesPerLineOut;
 526     }
 527 }
 528 
 529 
 530 // No gamut check, Cache, 16 bits,
 531 static
 532 void CachedXFORM(_cmsTRANSFORM* p,
 533                  const void* in,
 534                  void* out,
 535                  cmsUInt32Number PixelsPerLine,
 536                  cmsUInt32Number LineCount,
 537                  const cmsStride* Stride)
 538 {
 539     cmsUInt8Number* accum;
 540     cmsUInt8Number* output;
 541     cmsUInt16Number wIn[cmsMAXCHANNELS], wOut[cmsMAXCHANNELS];
 542     _cmsCACHE Cache;
 543     cmsUInt32Number i, j, strideIn, strideOut;
 544 
 545     _cmsHandleExtraChannels(p, in, out, PixelsPerLine, LineCount, Stride);
 546 
 547     // Empty buffers for quick memcmp
 548     memset(wIn, 0, sizeof(wIn));
 549     memset(wOut, 0, sizeof(wOut));
 550 


 809 static
 810 _cmsTRANSFORM* AllocEmptyTransform(cmsContext ContextID, cmsPipeline* lut,
 811                                                cmsUInt32Number Intent, cmsUInt32Number* InputFormat, cmsUInt32Number* OutputFormat, cmsUInt32Number* dwFlags)
 812 {
 813      _cmsTransformPluginChunkType* ctx = ( _cmsTransformPluginChunkType*) _cmsContextGetClientChunk(ContextID, TransformPlugin);
 814      _cmsTransformCollection* Plugin;
 815 
 816        // Allocate needed memory
 817        _cmsTRANSFORM* p = (_cmsTRANSFORM*)_cmsMallocZero(ContextID, sizeof(_cmsTRANSFORM));
 818        if (!p) {
 819               cmsPipelineFree(lut);
 820               return NULL;
 821        }
 822 
 823        // Store the proposed pipeline
 824        p->Lut = lut;
 825 
 826        // Let's see if any plug-in want to do the transform by itself
 827        if (p->Lut != NULL) {
 828 
 829            if (!(*dwFlags & cmsFLAGS_NOOPTIMIZE))
 830            {
 831                for (Plugin = ctx->TransformCollection;
 832                    Plugin != NULL;
 833                    Plugin = Plugin->Next) {
 834 
 835                    if (Plugin->Factory(&p->xform, &p->UserData, &p->FreeUserData, &p->Lut, InputFormat, OutputFormat, dwFlags)) {
 836 
 837                        // Last plugin in the declaration order takes control. We just keep
 838                        // the original parameters as a logging.
 839                        // Note that cmsFLAGS_CAN_CHANGE_FORMATTER is not set, so by default
 840                        // an optimized transform is not reusable. The plug-in can, however, change
 841                        // the flags and make it suitable.
 842 
 843                        p->ContextID = ContextID;
 844                        p->InputFormat = *InputFormat;
 845                        p->OutputFormat = *OutputFormat;
 846                        p->dwOriginalFlags = *dwFlags;
 847 
 848                        // Fill the formatters just in case the optimized routine is interested.
 849                        // No error is thrown if the formatter doesn't exist. It is up to the optimization
 850                        // factory to decide what to do in those cases.
 851                        p->FromInput = _cmsGetFormatter(ContextID, *InputFormat, cmsFormatterInput, CMS_PACK_FLAGS_16BITS).Fmt16;
 852                        p->ToOutput = _cmsGetFormatter(ContextID, *OutputFormat, cmsFormatterOutput, CMS_PACK_FLAGS_16BITS).Fmt16;
 853                        p->FromInputFloat = _cmsGetFormatter(ContextID, *InputFormat, cmsFormatterInput, CMS_PACK_FLAGS_FLOAT).FmtFloat;
 854                        p->ToOutputFloat = _cmsGetFormatter(ContextID, *OutputFormat, cmsFormatterOutput, CMS_PACK_FLAGS_FLOAT).FmtFloat;
 855 
 856                        // Save the day? (Ignore the warning)
 857                        if (Plugin->OldXform) {
 858                            p->OldXform = (_cmsTransformFn)(void*)p->xform;
 859                            p->xform = _cmsTransform2toTransformAdaptor;
 860                        }
 861 
 862                        return p;
 863                    }
 864                }
 865            }
 866 
 867            // Not suitable for the transform plug-in, let's check  the pipeline plug-in
 868            _cmsOptimizePipeline(ContextID, &p->Lut, Intent, InputFormat, OutputFormat, dwFlags);
 869        }
 870 
 871     // Check whatever this is a true floating point transform
 872     if (_cmsFormatterIsFloat(*InputFormat) && _cmsFormatterIsFloat(*OutputFormat)) {
 873 
 874         // Get formatter function always return a valid union, but the contents of this union may be NULL.
 875         p ->FromInputFloat = _cmsGetFormatter(ContextID, *InputFormat,  cmsFormatterInput, CMS_PACK_FLAGS_FLOAT).FmtFloat;
 876         p ->ToOutputFloat  = _cmsGetFormatter(ContextID, *OutputFormat, cmsFormatterOutput, CMS_PACK_FLAGS_FLOAT).FmtFloat;
 877         *dwFlags |= cmsFLAGS_CAN_CHANGE_FORMATTER;
 878 
 879         if (p ->FromInputFloat == NULL || p ->ToOutputFloat == NULL) {
 880 
 881             cmsSignalError(ContextID, cmsERROR_UNKNOWN_EXTENSION, "Unsupported raster format");
 882             cmsDeleteTransform(p);
 883             return NULL;
 884         }
 885 
 886         if (*dwFlags & cmsFLAGS_NULLTRANSFORM) {
 887 
 888             p ->xform = NullFloatXFORM;
 889         }
 890         else {
 891             // Float transforms don't use cache, always are non-NULL
 892             p ->xform = FloatXFORM;
 893         }
 894 
 895     }
 896     else {
 897 
 898         if (*InputFormat == 0 && *OutputFormat == 0) {
 899             p ->FromInput = p ->ToOutput = NULL;
 900             *dwFlags |= cmsFLAGS_CAN_CHANGE_FORMATTER;
 901         }
 902         else {
 903 
 904             cmsUInt32Number BytesPerPixelInput;
 905 
 906             p ->FromInput = _cmsGetFormatter(ContextID, *InputFormat,  cmsFormatterInput, CMS_PACK_FLAGS_16BITS).Fmt16;
 907             p ->ToOutput  = _cmsGetFormatter(ContextID, *OutputFormat, cmsFormatterOutput, CMS_PACK_FLAGS_16BITS).Fmt16;
 908 
 909             if (p ->FromInput == NULL || p ->ToOutput == NULL) {
 910 
 911                 cmsSignalError(ContextID, cmsERROR_UNKNOWN_EXTENSION, "Unsupported raster format");
 912                 cmsDeleteTransform(p);
 913                 return NULL;
 914             }
 915 
 916             BytesPerPixelInput = T_BYTES(p ->InputFormat);
 917             if (BytesPerPixelInput == 0 || BytesPerPixelInput >= 2)
 918                    *dwFlags |= cmsFLAGS_CAN_CHANGE_FORMATTER;
 919 
 920         }
 921 
 922         if (*dwFlags & cmsFLAGS_NULLTRANSFORM) {
 923 
 924             p ->xform = NullXFORM;
 925         }
 926         else {
 927             if (*dwFlags & cmsFLAGS_NOCACHE) {
 928 
 929                 if (*dwFlags & cmsFLAGS_GAMUTCHECK)
 930                     p ->xform = PrecalculatedXFORMGamutCheck;  // Gamut check, no cache
 931                 else
 932                     p ->xform = PrecalculatedXFORM;  // No cache, no gamut check
 933             }
 934             else {
 935 
 936                 if (*dwFlags & cmsFLAGS_GAMUTCHECK)
 937                     p ->xform = CachedXFORMGamutCheck;    // Gamut check, cache
 938                 else
 939                     p ->xform = CachedXFORM;  // No gamut check, cache
 940 
 941             }
 942         }
 943     }
 944 
 945     p ->InputFormat     = *InputFormat;
 946     p ->OutputFormat    = *OutputFormat;
 947     p ->dwOriginalFlags = *dwFlags;
 948     p ->ContextID       = ContextID;
 949     p ->UserData        = NULL;
 950     return p;
 951 }
 952 
 953 static
 954 cmsBool GetXFormColorSpaces(cmsUInt32Number nProfiles, cmsHPROFILE hProfiles[], cmsColorSpaceSignature* Input, cmsColorSpaceSignature* Output)
 955 {
 956     cmsColorSpaceSignature ColorSpaceIn, ColorSpaceOut;
 957     cmsColorSpaceSignature PostColorSpace;
 958     cmsUInt32Number i;
 959 


< prev index next >