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
|