MagickCore  6.9.12-67
Convert, Edit, Or Compose Bitmap Images
 All Data Structures
colorspace.c
1 /*
2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3 % %
4 % %
5 % %
6 % CCCC OOO L OOO RRRR SSSSS PPPP AAA CCCC EEEEE %
7 % C O O L O O R R SS P P A A C E %
8 % C O O L O O RRRR SSS PPPP AAAAA C EEE %
9 % C O O L O O R R SS P A A C E %
10 % CCCC OOO LLLLL OOO R R SSSSS P A A CCCC EEEEE %
11 % %
12 % %
13 % MagickCore Image Colorspace Methods %
14 % %
15 % Software Design %
16 % Cristy %
17 % July 1992 %
18 % %
19 % %
20 % Copyright 1999-2021 ImageMagick Studio LLC, a non-profit organization %
21 % dedicated to making software imaging solutions freely available. %
22 % %
23 % You may not use this file except in compliance with the License. You may %
24 % obtain a copy of the License at %
25 % %
26 % https://imagemagick.org/script/license.php %
27 % %
28 % Unless required by applicable law or agreed to in writing, software %
29 % distributed under the License is distributed on an "AS IS" BASIS, %
30 % WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %
31 % See the License for the specific language governing permissions and %
32 % limitations under the License. %
33 % %
34 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
35 %
36 %
37 */
38 
39 /*
40  Include declarations.
41 */
42 #include "magick/studio.h"
43 #include "magick/attribute.h"
44 #include "magick/cache.h"
45 #include "magick/cache-private.h"
46 #include "magick/cache-view.h"
47 #include "magick/color.h"
48 #include "magick/color-private.h"
49 #include "magick/colorspace.h"
50 #include "magick/colorspace-private.h"
51 #include "magick/exception.h"
52 #include "magick/exception-private.h"
53 #include "magick/enhance.h"
54 #include "magick/image.h"
55 #include "magick/image-private.h"
56 #include "magick/gem.h"
57 #include "magick/gem-private.h"
58 #include "magick/memory_.h"
59 #include "magick/monitor.h"
60 #include "magick/monitor-private.h"
61 #include "magick/pixel-private.h"
62 #include "magick/property.h"
63 #include "magick/quantize.h"
64 #include "magick/quantum.h"
65 #include "magick/resource_.h"
66 #include "magick/string_.h"
67 #include "magick/string-private.h"
68 #include "magick/utility.h"
69 
70 /*
71  Typedef declarations.
72 */
73 typedef struct _TransformPacket
74 {
75  MagickRealType
76  x,
77  y,
78  z;
80 
81 /*
82 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
83 % %
84 % %
85 % %
86 % G e t I m a g e C o l o r s p a c e T y p e %
87 % %
88 % %
89 % %
90 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
91 %
92 % GetImageColorspaceType() returns the potential colorspace of image:
93 % sRGBColorspaceType, RGBColorspaceType, GRAYColorspaceType, etc.
94 %
95 % To ensure the image type matches its potential, use SetImageColorspaceType():
96 %
97 % (void) SetImageColorspaceType(image,GetImageColorspaceType(image),
98 % exception);
99 %
100 % The format of the GetImageColorspaceType method is:
101 %
102 % ColorspaceType GetImageColorspaceType(const Image *image,
103 % ExceptionInfo *exception)
104 %
105 % A description of each parameter follows:
106 %
107 % o image: the image.
108 %
109 % o exception: return any errors or warnings in this structure.
110 %
111 */
112 MagickExport ColorspaceType GetImageColorspaceType(const Image *image,
113  ExceptionInfo *exception)
114 {
115  ColorspaceType
116  colorspace;
117 
118  ImageType
119  type;
120 
121  assert(image != (Image *) NULL);
122  assert(image->signature == MagickCoreSignature);
123  if (IsEventLogging() != MagickFalse)
124  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
125  colorspace=image->colorspace;
126  type=IdentifyImageType(image,exception);
127  if ((type == BilevelType) || (type == GrayscaleType) ||
128  (type == GrayscaleMatteType))
129  colorspace=GRAYColorspace;
130  return(colorspace);
131 }
132 
133 /*
134 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
135 % %
136 % %
137 % %
138 + R G B T r a n s f o r m I m a g e %
139 % %
140 % %
141 % %
142 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
143 %
144 % RGBTransformImage() converts the reference image from sRGB to an alternate
145 % colorspace. The transformation matrices are not the standard ones: the
146 % weights are rescaled to normalized the range of the transformed values to
147 % be [0..QuantumRange].
148 %
149 % The format of the RGBTransformImage method is:
150 %
151 % MagickBooleanType RGBTransformImage(Image *image,
152 % const ColorspaceType colorspace)
153 %
154 % A description of each parameter follows:
155 %
156 % o image: the image.
157 %
158 % o colorspace: the colorspace to transform the image to.
159 %
160 */
161 
162 static inline void ConvertRGBToCMY(const Quantum red,const Quantum green,
163  const Quantum blue,double *cyan,double *magenta,double *yellow)
164 {
165  *cyan=QuantumScale*(QuantumRange-red);
166  *magenta=QuantumScale*(QuantumRange-green);
167  *yellow=QuantumScale*(QuantumRange-blue);
168 }
169 
170 static void ConvertRGBToLab(const Quantum red,const Quantum green,
171  const Quantum blue,double *L,double *a,double *b)
172 {
173  double
174  X,
175  Y,
176  Z;
177 
178  ConvertRGBToXYZ(red,green,blue,&X,&Y,&Z);
179  ConvertXYZToLab(X,Y,Z,L,a,b);
180 }
181 
182 static inline void ConvertXYZToLMS(const double x,const double y,
183  const double z,double *L,double *M,double *S)
184 {
185  *L=0.7328*x+0.4296*y-0.1624*z;
186  *M=(-0.7036*x+1.6975*y+0.0061*z);
187  *S=0.0030*x+0.0136*y+0.9834*z;
188 }
189 
190 static void ConvertRGBToLMS(const Quantum red,const Quantum green,
191  const Quantum blue,double *L,double *M,double *S)
192 {
193  double
194  X,
195  Y,
196  Z;
197 
198  ConvertRGBToXYZ(red,green,blue,&X,&Y,&Z);
199  ConvertXYZToLMS(X,Y,Z,L,M,S);
200 }
201 
202 static void ConvertRGBToLuv(const Quantum red,const Quantum green,
203  const Quantum blue,double *L,double *u,double *v)
204 {
205  double
206  X,
207  Y,
208  Z;
209 
210  ConvertRGBToXYZ(red,green,blue,&X,&Y,&Z);
211  ConvertXYZToLuv(X,Y,Z,L,u,v);
212 }
213 
214 static void ConvertRGBToxyY(const Quantum red,const Quantum green,
215  const Quantum blue,double *low_x,double *low_y,double *cap_Y)
216 {
217  double
218  gamma,
219  X,
220  Y,
221  Z;
222 
223  ConvertRGBToXYZ(red,green,blue,&X,&Y,&Z);
224  gamma=PerceptibleReciprocal(X+Y+Z);
225  *low_x=gamma*X;
226  *low_y=gamma*Y;
227  *cap_Y=Y;
228 }
229 
230 static void ConvertRGBToYPbPr(const Quantum red,const Quantum green,
231  const Quantum blue,double *Y,double *Pb,double *Pr)
232 {
233  *Y=QuantumScale*(0.298839*red+0.586811*green+0.114350*blue);
234  *Pb=QuantumScale*((-0.1687367)*red-0.331264*green+0.5*blue)+0.5;
235  *Pr=QuantumScale*(0.5*red-0.418688*green-0.081312*blue)+0.5;
236 }
237 
238 static void ConvertRGBToYCbCr(const Quantum red,const Quantum green,
239  const Quantum blue,double *Y,double *Cb,double *Cr)
240 {
241  ConvertRGBToYPbPr(red,green,blue,Y,Cb,Cr);
242 }
243 
244 static void ConvertRGBToYUV(const Quantum red,const Quantum green,
245  const Quantum blue,double *Y,double *U,double *V)
246 {
247  *Y=QuantumScale*(0.298839*red+0.586811*green+0.114350*blue);
248  *U=QuantumScale*((-0.147)*red-0.289*green+0.436*blue)+0.5;
249  *V=QuantumScale*(0.615*red-0.515*green-0.100*blue)+0.5;
250 }
251 
252 static void ConvertRGBToYDbDr(const Quantum red,const Quantum green,
253  const Quantum blue,double *Y,double *Db,double *Dr)
254 {
255  *Y=QuantumScale*(0.298839*red+0.586811*green+0.114350*blue);
256  *Db=QuantumScale*(-0.450*red-0.883*green+1.333*blue)+0.5;
257  *Dr=QuantumScale*(-1.333*red+1.116*green+0.217*blue)+0.5;
258 }
259 
260 static void ConvertRGBToYIQ(const Quantum red,const Quantum green,
261  const Quantum blue,double *Y,double *I,double *Q)
262 {
263  *Y=QuantumScale*(0.298839*red+0.586811*green+0.114350*blue);
264  *I=QuantumScale*(0.595716*red-0.274453*green-0.321263*blue)+0.5;
265  *Q=QuantumScale*(0.211456*red-0.522591*green+0.311135*blue)+0.5;
266 }
267 
268 MagickExport MagickBooleanType RGBTransformImage(Image *image,
269  const ColorspaceType colorspace)
270 {
271 #define RGBTransformImageTag "RGBTransform/Image"
272 
273  CacheView
274  *image_view;
275 
277  *exception;
278 
279  MagickBooleanType
280  status;
281 
282  MagickOffsetType
283  progress;
284 
286  primary_info;
287 
288  ssize_t
289  i;
290 
291  ssize_t
292  y;
293 
295  *x_map,
296  *y_map,
297  *z_map;
298 
299  assert(image != (Image *) NULL);
300  assert(image->signature == MagickCoreSignature);
301  assert(colorspace != sRGBColorspace);
302  assert(colorspace != TransparentColorspace);
303  assert(colorspace != UndefinedColorspace);
304  if (IsEventLogging() != MagickFalse)
305  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
306  status=MagickTrue;
307  progress=0;
308  exception=(&image->exception);
309  switch (colorspace)
310  {
311  case CMYKColorspace:
312  {
314  zero;
315 
316  /*
317  Convert RGB to CMYK colorspace.
318  */
319  if (image->storage_class == PseudoClass)
320  {
321  if (SyncImage(image) == MagickFalse)
322  return(MagickFalse);
323  if (SetImageStorageClass(image,DirectClass) == MagickFalse)
324  return(MagickFalse);
325  }
326  if (SetImageColorspace(image,colorspace) == MagickFalse)
327  return(MagickFalse);
328  GetMagickPixelPacket(image,&zero);
329  image_view=AcquireAuthenticCacheView(image,exception);
330 #if defined(MAGICKCORE_OPENMP_SUPPORT)
331  #pragma omp parallel for schedule(static) shared(status) \
332  magick_number_threads(image,image,image->rows,1)
333 #endif
334  for (y=0; y < (ssize_t) image->rows; y++)
335  {
336  MagickBooleanType
337  sync;
338 
340  pixel;
341 
342  IndexPacket
343  *magick_restrict indexes;
344 
345  ssize_t
346  x;
347 
349  *magick_restrict q;
350 
351  if (status == MagickFalse)
352  continue;
353  q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
354  exception);
355  if (q == (PixelPacket *) NULL)
356  {
357  status=MagickFalse;
358  continue;
359  }
360  indexes=GetCacheViewAuthenticIndexQueue(image_view);
361  pixel=zero;
362  for (x=0; x < (ssize_t) image->columns; x++)
363  {
364  SetMagickPixelPacket(image,q,indexes+x,&pixel);
365  pixel.red=(MagickRealType) pixel.red;
366  pixel.green=(MagickRealType) pixel.green;
367  pixel.blue=(MagickRealType) pixel.blue;
368  ConvertRGBToCMYK(&pixel);
369  SetPixelPacket(image,&pixel,q,indexes+x);
370  q++;
371  }
372  sync=SyncCacheViewAuthenticPixels(image_view,exception);
373  if (sync == MagickFalse)
374  status=MagickFalse;
375  }
376  image_view=DestroyCacheView(image_view);
377  image->type=image->matte == MagickFalse ? ColorSeparationType :
378  ColorSeparationMatteType;
379  if (SetImageColorspace(image,colorspace) == MagickFalse)
380  return(MagickFalse);
381  return(status);
382  }
383  case LinearGRAYColorspace:
384  {
385  /*
386  Transform image from sRGB to GRAY.
387  */
388  if (image->storage_class == PseudoClass)
389  {
390  if (SyncImage(image) == MagickFalse)
391  return(MagickFalse);
392  if (SetImageStorageClass(image,DirectClass) == MagickFalse)
393  return(MagickFalse);
394  }
395  image_view=AcquireAuthenticCacheView(image,exception);
396 #if defined(MAGICKCORE_OPENMP_SUPPORT)
397  #pragma omp parallel for schedule(static) shared(status) \
398  magick_number_threads(image,image,image->rows,1)
399 #endif
400  for (y=0; y < (ssize_t) image->rows; y++)
401  {
402  MagickBooleanType
403  sync;
404 
405  ssize_t
406  x;
407 
409  *magick_restrict q;
410 
411  if (status == MagickFalse)
412  continue;
413  q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
414  exception);
415  if (q == (PixelPacket *) NULL)
416  {
417  status=MagickFalse;
418  continue;
419  }
420  for (x=0; x < (ssize_t) image->columns; x++)
421  {
422  MagickRealType
423  gray;
424 
425  gray=0.212656*DecodePixelGamma(GetPixelRed(q))+0.715158*
426  DecodePixelGamma(GetPixelGreen(q))+0.072186*
427  DecodePixelGamma(GetPixelBlue(q));
428  SetPixelGray(q,ClampToQuantum(gray));
429  q++;
430  }
431  sync=SyncCacheViewAuthenticPixels(image_view,exception);
432  if (sync == MagickFalse)
433  status=MagickFalse;
434  }
435  image_view=DestroyCacheView(image_view);
436  if (SetImageColorspace(image,colorspace) == MagickFalse)
437  return(MagickFalse);
438  image->type=GrayscaleType;
439  return(status);
440  }
441  case GRAYColorspace:
442  {
443  /*
444  Transform image from sRGB to GRAY.
445  */
446  if (image->storage_class == PseudoClass)
447  {
448  if (SyncImage(image) == MagickFalse)
449  return(MagickFalse);
450  if (SetImageStorageClass(image,DirectClass) == MagickFalse)
451  return(MagickFalse);
452  }
453  image_view=AcquireAuthenticCacheView(image,exception);
454 #if defined(MAGICKCORE_OPENMP_SUPPORT)
455  #pragma omp parallel for schedule(static) shared(status) \
456  magick_number_threads(image,image,image->rows,1)
457 #endif
458  for (y=0; y < (ssize_t) image->rows; y++)
459  {
460  MagickBooleanType
461  sync;
462 
463  ssize_t
464  x;
465 
467  *magick_restrict q;
468 
469  if (status == MagickFalse)
470  continue;
471  q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
472  exception);
473  if (q == (PixelPacket *) NULL)
474  {
475  status=MagickFalse;
476  continue;
477  }
478  for (x=0; x < (ssize_t) image->columns; x++)
479  {
480  MagickRealType
481  gray;
482 
483  gray=0.212656*GetPixelRed(q)+0.715158*GetPixelGreen(q)+
484  0.072186*GetPixelBlue(q);
485  SetPixelGray(q,ClampToQuantum(gray));
486  q++;
487  }
488  sync=SyncCacheViewAuthenticPixels(image_view,exception);
489  if (sync == MagickFalse)
490  status=MagickFalse;
491  }
492  image_view=DestroyCacheView(image_view);
493  if (SetImageColorspace(image,colorspace) == MagickFalse)
494  return(MagickFalse);
495  image->type=GrayscaleType;
496  return(status);
497  }
498  case CMYColorspace:
499  case HCLColorspace:
500  case HCLpColorspace:
501  case HSBColorspace:
502  case HSIColorspace:
503  case HSLColorspace:
504  case HSVColorspace:
505  case HWBColorspace:
506  case LabColorspace:
507  case LCHColorspace:
508  case LCHabColorspace:
509  case LCHuvColorspace:
510  case LMSColorspace:
511  case LuvColorspace:
512  case xyYColorspace:
513  case XYZColorspace:
514  case YCbCrColorspace:
515  case YDbDrColorspace:
516  case YIQColorspace:
517  case YPbPrColorspace:
518  case YUVColorspace:
519  {
520  /*
521  Transform image from sRGB to HSI.
522  */
523  if (image->storage_class == PseudoClass)
524  {
525  if (SyncImage(image) == MagickFalse)
526  return(MagickFalse);
527  if (SetImageStorageClass(image,DirectClass) == MagickFalse)
528  return(MagickFalse);
529  }
530  image_view=AcquireAuthenticCacheView(image,exception);
531 #if defined(MAGICKCORE_OPENMP_SUPPORT)
532  #pragma omp parallel for schedule(static) shared(status) \
533  magick_number_threads(image,image,image->rows,1)
534 #endif
535  for (y=0; y < (ssize_t) image->rows; y++)
536  {
537  MagickBooleanType
538  sync;
539 
540  ssize_t
541  x;
542 
544  *magick_restrict q;
545 
546  if (status == MagickFalse)
547  continue;
548  q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
549  exception);
550  if (q == (PixelPacket *) NULL)
551  {
552  status=MagickFalse;
553  continue;
554  }
555  for (x=0; x < (ssize_t) image->columns; x++)
556  {
557  double
558  X,
559  Y,
560  Z;
561 
562  Quantum
563  blue,
564  green,
565  red;
566 
567  red=ClampToQuantum((MagickRealType) GetPixelRed(q));
568  green=ClampToQuantum((MagickRealType) GetPixelGreen(q));
569  blue=ClampToQuantum((MagickRealType) GetPixelBlue(q));
570  switch (colorspace)
571  {
572  case CMYColorspace:
573  {
574  ConvertRGBToCMY(red,green,blue,&X,&Y,&Z);
575  break;
576  }
577  case HCLColorspace:
578  {
579  ConvertRGBToHCL(red,green,blue,&X,&Y,&Z);
580  break;
581  }
582  case HCLpColorspace:
583  {
584  ConvertRGBToHCLp(red,green,blue,&X,&Y,&Z);
585  break;
586  }
587  case HSBColorspace:
588  {
589  ConvertRGBToHSB(red,green,blue,&X,&Y,&Z);
590  break;
591  }
592  case HSIColorspace:
593  {
594  ConvertRGBToHSI(red,green,blue,&X,&Y,&Z);
595  break;
596  }
597  case HSLColorspace:
598  {
599  ConvertRGBToHSL(red,green,blue,&X,&Y,&Z);
600  break;
601  }
602  case HSVColorspace:
603  {
604  ConvertRGBToHSV(red,green,blue,&X,&Y,&Z);
605  break;
606  }
607  case HWBColorspace:
608  {
609  ConvertRGBToHWB(red,green,blue,&X,&Y,&Z);
610  break;
611  }
612  case LabColorspace:
613  {
614  ConvertRGBToLab(red,green,blue,&X,&Y,&Z);
615  break;
616  }
617  case LCHColorspace:
618  case LCHabColorspace:
619  {
620  ConvertRGBToLCHab(red,green,blue,&X,&Y,&Z);
621  break;
622  }
623  case LCHuvColorspace:
624  {
625  ConvertRGBToLCHuv(red,green,blue,&X,&Y,&Z);
626  break;
627  }
628  case LMSColorspace:
629  {
630  ConvertRGBToLMS(red,green,blue,&X,&Y,&Z);
631  break;
632  }
633  case LuvColorspace:
634  {
635  ConvertRGBToLuv(red,green,blue,&X,&Y,&Z);
636  break;
637  }
638  case xyYColorspace:
639  {
640  ConvertRGBToxyY(red,green,blue,&X,&Y,&Z);
641  break;
642  }
643  case XYZColorspace:
644  {
645  ConvertRGBToXYZ(red,green,blue,&X,&Y,&Z);
646  break;
647  }
648  case YCbCrColorspace:
649  {
650  ConvertRGBToYCbCr(red,green,blue,&X,&Y,&Z);
651  break;
652  }
653  case YDbDrColorspace:
654  {
655  ConvertRGBToYDbDr(red,green,blue,&X,&Y,&Z);
656  break;
657  }
658  case YIQColorspace:
659  {
660  ConvertRGBToYIQ(red,green,blue,&X,&Y,&Z);
661  break;
662  }
663  case YPbPrColorspace:
664  {
665  ConvertRGBToYPbPr(red,green,blue,&X,&Y,&Z);
666  break;
667  }
668  case YUVColorspace:
669  {
670  ConvertRGBToYUV(red,green,blue,&X,&Y,&Z);
671  break;
672  }
673  default:
674  {
675  X=QuantumScale*red;
676  Y=QuantumScale*green;
677  Z=QuantumScale*blue;
678  break;
679  }
680  }
681  SetPixelRed(q,ClampToQuantum((MagickRealType) QuantumRange*X));
682  SetPixelGreen(q,ClampToQuantum((MagickRealType) QuantumRange*Y));
683  SetPixelBlue(q,ClampToQuantum((MagickRealType) QuantumRange*Z));
684  q++;
685  }
686  sync=SyncCacheViewAuthenticPixels(image_view,exception);
687  if (sync == MagickFalse)
688  status=MagickFalse;
689  }
690  image_view=DestroyCacheView(image_view);
691  if (SetImageColorspace(image,colorspace) == MagickFalse)
692  return(MagickFalse);
693  return(status);
694  }
695  case LogColorspace:
696  {
697 #define DisplayGamma (1.0/1.7)
698 #define FilmGamma 0.6
699 #define ReferenceBlack 95.0
700 #define ReferenceWhite 685.0
701 
702  const char
703  *value;
704 
705  double
706  black,
707  density,
708  film_gamma,
709  gamma,
710  reference_black,
711  reference_white;
712 
713  Quantum
714  *logmap;
715 
716  /*
717  Transform RGB to Log colorspace.
718  */
719  density=DisplayGamma;
720  gamma=DisplayGamma;
721  value=GetImageProperty(image,"gamma");
722  if (value != (const char *) NULL)
723  gamma=PerceptibleReciprocal(StringToDouble(value,(char **) NULL));
724  film_gamma=FilmGamma;
725  value=GetImageProperty(image,"film-gamma");
726  if (value != (const char *) NULL)
727  film_gamma=StringToDouble(value,(char **) NULL);
728  reference_black=ReferenceBlack;
729  value=GetImageProperty(image,"reference-black");
730  if (value != (const char *) NULL)
731  reference_black=StringToDouble(value,(char **) NULL);
732  reference_white=ReferenceWhite;
733  value=GetImageProperty(image,"reference-white");
734  if (value != (const char *) NULL)
735  reference_white=StringToDouble(value,(char **) NULL);
736  logmap=(Quantum *) AcquireQuantumMemory((size_t) MaxMap+1UL,
737  sizeof(*logmap));
738  if (logmap == (Quantum *) NULL)
739  ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
740  image->filename);
741  black=pow(10.0,(reference_black-reference_white)*(gamma/density)*0.002*
742  PerceptibleReciprocal(film_gamma));
743 #if defined(MAGICKCORE_OPENMP_SUPPORT)
744  #pragma omp parallel for schedule(static)
745 #endif
746  for (i=0; i <= (ssize_t) MaxMap; i++)
747  logmap[i]=ScaleMapToQuantum((MagickRealType) (MaxMap*(reference_white+
748  log10(black+(1.0*i/MaxMap)*(1.0-black))/((gamma/density)*0.002*
749  PerceptibleReciprocal(film_gamma)))/1024.0));
750  image_view=AcquireAuthenticCacheView(image,exception);
751 #if defined(MAGICKCORE_OPENMP_SUPPORT)
752  #pragma omp parallel for schedule(static) shared(status) \
753  magick_number_threads(image,image,image->rows,1)
754 #endif
755  for (y=0; y < (ssize_t) image->rows; y++)
756  {
757  MagickBooleanType
758  sync;
759 
760  ssize_t
761  x;
762 
764  *magick_restrict q;
765 
766  if (status == MagickFalse)
767  continue;
768  q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
769  exception);
770  if (q == (PixelPacket *) NULL)
771  {
772  status=MagickFalse;
773  continue;
774  }
775  for (x=(ssize_t) image->columns; x != 0; x--)
776  {
777  Quantum
778  blue,
779  green,
780  red;
781 
782  red=ClampToQuantum(DecodePixelGamma((MagickRealType)
783  GetPixelRed(q)));
784  green=ClampToQuantum(DecodePixelGamma((MagickRealType)
785  GetPixelGreen(q)));
786  blue=ClampToQuantum(DecodePixelGamma((MagickRealType)
787  GetPixelBlue(q)));
788  SetPixelRed(q,logmap[ScaleQuantumToMap(red)]);
789  SetPixelGreen(q,logmap[ScaleQuantumToMap(green)]);
790  SetPixelBlue(q,logmap[ScaleQuantumToMap(blue)]);
791  q++;
792  }
793  sync=SyncCacheViewAuthenticPixels(image_view,exception);
794  if (sync == MagickFalse)
795  status=MagickFalse;
796  }
797  image_view=DestroyCacheView(image_view);
798  logmap=(Quantum *) RelinquishMagickMemory(logmap);
799  if (SetImageColorspace(image,colorspace) == MagickFalse)
800  return(MagickFalse);
801  return(status);
802  }
803  case RGBColorspace:
804  case scRGBColorspace:
805  {
806  /*
807  Transform image from sRGB to linear RGB.
808  */
809  if (image->storage_class == PseudoClass)
810  {
811  if (SyncImage(image) == MagickFalse)
812  return(MagickFalse);
813  if (SetImageStorageClass(image,DirectClass) == MagickFalse)
814  return(MagickFalse);
815  }
816  image_view=AcquireAuthenticCacheView(image,exception);
817 #if defined(MAGICKCORE_OPENMP_SUPPORT)
818  #pragma omp parallel for schedule(static) shared(status) \
819  magick_number_threads(image,image,image->rows,1)
820 #endif
821  for (y=0; y < (ssize_t) image->rows; y++)
822  {
823  MagickBooleanType
824  sync;
825 
826  ssize_t
827  x;
828 
830  *magick_restrict q;
831 
832  if (status == MagickFalse)
833  continue;
834  q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
835  exception);
836  if (q == (PixelPacket *) NULL)
837  {
838  status=MagickFalse;
839  continue;
840  }
841  for (x=0; x < (ssize_t) image->columns; x++)
842  {
843  Quantum
844  blue,
845  green,
846  red;
847 
848  red=ClampToQuantum(DecodePixelGamma((MagickRealType)
849  GetPixelRed(q)));
850  green=ClampToQuantum(DecodePixelGamma((MagickRealType)
851  GetPixelGreen(q)));
852  blue=ClampToQuantum(DecodePixelGamma((MagickRealType)
853  GetPixelBlue(q)));
854  SetPixelRed(q,red);
855  SetPixelGreen(q,green);
856  SetPixelBlue(q,blue);
857  q++;
858  }
859  sync=SyncCacheViewAuthenticPixels(image_view,exception);
860  if (sync == MagickFalse)
861  status=MagickFalse;
862  }
863  image_view=DestroyCacheView(image_view);
864  if (SetImageColorspace(image,colorspace) == MagickFalse)
865  return(MagickFalse);
866  return(status);
867  }
868  default:
869  break;
870  }
871  /*
872  Allocate the tables.
873  */
874  x_map=(TransformPacket *) AcquireQuantumMemory((size_t) MaxMap+1UL,
875  sizeof(*x_map));
876  y_map=(TransformPacket *) AcquireQuantumMemory((size_t) MaxMap+1UL,
877  sizeof(*y_map));
878  z_map=(TransformPacket *) AcquireQuantumMemory((size_t) MaxMap+1UL,
879  sizeof(*z_map));
880  if ((x_map == (TransformPacket *) NULL) ||
881  (y_map == (TransformPacket *) NULL) ||
882  (z_map == (TransformPacket *) NULL))
883  {
884  if (x_map != (TransformPacket *) NULL)
885  x_map=(TransformPacket *) RelinquishMagickMemory(x_map);
886  if (y_map != (TransformPacket *) NULL)
887  y_map=(TransformPacket *) RelinquishMagickMemory(y_map);
888  if (z_map != (TransformPacket *) NULL)
889  z_map=(TransformPacket *) RelinquishMagickMemory(z_map);
890  ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
891  image->filename);
892  }
893  (void) memset(&primary_info,0,sizeof(primary_info));
894  switch (colorspace)
895  {
896  case OHTAColorspace:
897  {
898  /*
899  Initialize OHTA tables:
900 
901  I1 = 0.33333*R+0.33334*G+0.33333*B
902  I2 = 0.50000*R+0.00000*G-0.50000*B
903  I3 =-0.25000*R+0.50000*G-0.25000*B
904 
905  I and Q, normally -0.5 through 0.5, are normalized to the range 0
906  through QuantumRange.
907  */
908  primary_info.y=(double) (MaxMap+1.0)/2.0;
909  primary_info.z=(double) (MaxMap+1.0)/2.0;
910 #if defined(MAGICKCORE_OPENMP_SUPPORT)
911  #pragma omp parallel for schedule(static)
912 #endif
913  for (i=0; i <= (ssize_t) MaxMap; i++)
914  {
915  x_map[i].x=(MagickRealType) (0.33333*(double) i);
916  x_map[i].y=(MagickRealType) (0.50000*(double) i);
917  x_map[i].z=(MagickRealType) (-0.25000*(double) i);
918  y_map[i].x=(MagickRealType) (0.33334*(double) i);
919  y_map[i].y=(MagickRealType) (0.00000*(double) i);
920  y_map[i].z=(MagickRealType) (0.50000*(double) i);
921  z_map[i].x=(MagickRealType) (0.33333*(double) i);
922  z_map[i].y=(MagickRealType) (-0.50000*(double) i);
923  z_map[i].z=(MagickRealType) (-0.25000*(double) i);
924  }
925  break;
926  }
927  case Rec601LumaColorspace:
928  {
929  /*
930  Initialize Rec601 luma tables:
931 
932  G = 0.298839*R+0.586811*G+0.114350*B
933  */
934 #if defined(MAGICKCORE_OPENMP_SUPPORT)
935  #pragma omp parallel for schedule(static)
936 #endif
937  for (i=0; i <= (ssize_t) MaxMap; i++)
938  {
939  x_map[i].x=(MagickRealType) (0.298839*(double) i);
940  x_map[i].y=(MagickRealType) (0.298839*(double) i);
941  x_map[i].z=(MagickRealType) (0.298839*(double) i);
942  y_map[i].x=(MagickRealType) (0.586811*(double) i);
943  y_map[i].y=(MagickRealType) (0.586811*(double) i);
944  y_map[i].z=(MagickRealType) (0.586811*(double) i);
945  z_map[i].x=(MagickRealType) (0.114350*(double) i);
946  z_map[i].y=(MagickRealType) (0.114350*(double) i);
947  z_map[i].z=(MagickRealType) (0.114350*(double) i);
948  }
949  break;
950  }
951  case Rec601YCbCrColorspace:
952  {
953  /*
954  Initialize YCbCr tables (ITU-R BT.601):
955 
956  Y = 0.2988390*R+0.5868110*G+0.1143500*B
957  Cb= -0.1687367*R-0.3312640*G+0.5000000*B
958  Cr= 0.5000000*R-0.4186880*G-0.0813120*B
959 
960  Cb and Cr, normally -0.5 through 0.5, are normalized to the range 0
961  through QuantumRange.
962  */
963  primary_info.y=(double) (MaxMap+1.0)/2.0;
964  primary_info.z=(double) (MaxMap+1.0)/2.0;
965 #if defined(MAGICKCORE_OPENMP_SUPPORT)
966  #pragma omp parallel for schedule(static)
967 #endif
968  for (i=0; i <= (ssize_t) MaxMap; i++)
969  {
970  x_map[i].x=(MagickRealType) (0.298839*(double) i);
971  x_map[i].y=(MagickRealType) (-0.1687367*(double) i);
972  x_map[i].z=(MagickRealType) (0.500000*(double) i);
973  y_map[i].x=(MagickRealType) (0.586811*(double) i);
974  y_map[i].y=(MagickRealType) (-0.331264*(double) i);
975  y_map[i].z=(MagickRealType) (-0.418688*(double) i);
976  z_map[i].x=(MagickRealType) (0.114350*(double) i);
977  z_map[i].y=(MagickRealType) (0.500000*(double) i);
978  z_map[i].z=(MagickRealType) (-0.081312*(double) i);
979  }
980  break;
981  }
982  case Rec709LumaColorspace:
983  {
984  /*
985  Initialize Rec709 luma tables:
986 
987  G = 0.212656*R+0.715158*G+0.072186*B
988  */
989 #if defined(MAGICKCORE_OPENMP_SUPPORT)
990  #pragma omp parallel for schedule(static)
991 #endif
992  for (i=0; i <= (ssize_t) MaxMap; i++)
993  {
994  x_map[i].x=(MagickRealType) (0.212656*(double) i);
995  x_map[i].y=(MagickRealType) (0.212656*(double) i);
996  x_map[i].z=(MagickRealType) (0.212656*(double) i);
997  y_map[i].x=(MagickRealType) (0.715158*(double) i);
998  y_map[i].y=(MagickRealType) (0.715158*(double) i);
999  y_map[i].z=(MagickRealType) (0.715158*(double) i);
1000  z_map[i].x=(MagickRealType) (0.072186*(double) i);
1001  z_map[i].y=(MagickRealType) (0.072186*(double) i);
1002  z_map[i].z=(MagickRealType) (0.072186*(double) i);
1003  }
1004  break;
1005  }
1006  case Rec709YCbCrColorspace:
1007  {
1008  /*
1009  Initialize YCbCr tables (ITU-R BT.709):
1010 
1011  Y = 0.212656*R+0.715158*G+0.072186*B
1012  Cb= -0.114572*R-0.385428*G+0.500000*B
1013  Cr= 0.500000*R-0.454153*G-0.045847*B
1014 
1015  Cb and Cr, normally -0.5 through 0.5, are normalized to the range 0
1016  through QuantumRange.
1017  */
1018  primary_info.y=(double) (MaxMap+1.0)/2.0;
1019  primary_info.z=(double) (MaxMap+1.0)/2.0;
1020 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1021  #pragma omp parallel for schedule(static)
1022 #endif
1023  for (i=0; i <= (ssize_t) MaxMap; i++)
1024  {
1025  x_map[i].x=(MagickRealType) (0.212656*(double) i);
1026  x_map[i].y=(MagickRealType) (-0.114572*(double) i);
1027  x_map[i].z=(MagickRealType) (0.500000*(double) i);
1028  y_map[i].x=(MagickRealType) (0.715158*(double) i);
1029  y_map[i].y=(MagickRealType) (-0.385428*(double) i);
1030  y_map[i].z=(MagickRealType) (-0.454153*(double) i);
1031  z_map[i].x=(MagickRealType) (0.072186*(double) i);
1032  z_map[i].y=(MagickRealType) (0.500000*(double) i);
1033  z_map[i].z=(MagickRealType) (-0.045847*(double) i);
1034  }
1035  break;
1036  }
1037  case YCCColorspace:
1038  {
1039  /*
1040  Initialize YCC tables:
1041 
1042  Y = 0.298839*R+0.586811*G+0.114350*B
1043  C1= -0.298839*R-0.586811*G+0.88600*B
1044  C2= 0.70100*R-0.586811*G-0.114350*B
1045 
1046  YCC is scaled by 1.3584. C1 zero is 156 and C2 is at 137.
1047  */
1048  primary_info.y=(double) ScaleQuantumToMap(ScaleCharToQuantum(156));
1049  primary_info.z=(double) ScaleQuantumToMap(ScaleCharToQuantum(137));
1050  for (i=0; i <= (ssize_t) (0.018*MaxMap); i++)
1051  {
1052  x_map[i].x=0.005382*i;
1053  x_map[i].y=(-0.003296)*i;
1054  x_map[i].z=0.009410*i;
1055  y_map[i].x=0.010566*i;
1056  y_map[i].y=(-0.006471)*i;
1057  y_map[i].z=(-0.007880)*i;
1058  z_map[i].x=0.002052*i;
1059  z_map[i].y=0.009768*i;
1060  z_map[i].z=(-0.001530)*i;
1061  }
1062  for ( ; i <= (ssize_t) MaxMap; i++)
1063  {
1064  x_map[i].x=0.298839*(1.099*i-0.099);
1065  x_map[i].y=(-0.298839)*(1.099*i-0.099);
1066  x_map[i].z=0.70100*(1.099*i-0.099);
1067  y_map[i].x=0.586811*(1.099*i-0.099);
1068  y_map[i].y=(-0.586811)*(1.099*i-0.099);
1069  y_map[i].z=(-0.586811)*(1.099*i-0.099);
1070  z_map[i].x=0.114350*(1.099*i-0.099);
1071  z_map[i].y=0.88600*(1.099*i-0.099);
1072  z_map[i].z=(-0.114350)*(1.099*i-0.099);
1073  }
1074  break;
1075  }
1076  default:
1077  {
1078  /*
1079  Linear conversion tables.
1080  */
1081 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1082  #pragma omp parallel for schedule(static)
1083 #endif
1084  for (i=0; i <= (ssize_t) MaxMap; i++)
1085  {
1086  x_map[i].x=(MagickRealType) (1.0*(double) i);
1087  y_map[i].x=(MagickRealType) 0.0;
1088  z_map[i].x=(MagickRealType) 0.0;
1089  x_map[i].y=(MagickRealType) 0.0;
1090  y_map[i].y=(MagickRealType) (1.0*(double) i);
1091  z_map[i].y=(MagickRealType) 0.0;
1092  x_map[i].z=(MagickRealType) 0.0;
1093  y_map[i].z=(MagickRealType) 0.0;
1094  z_map[i].z=(MagickRealType) (1.0*(double) i);
1095  }
1096  break;
1097  }
1098  }
1099  /*
1100  Convert from sRGB.
1101  */
1102  switch (image->storage_class)
1103  {
1104  case DirectClass:
1105  default:
1106  {
1107  /*
1108  Convert DirectClass image.
1109  */
1110  image_view=AcquireAuthenticCacheView(image,exception);
1111 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1112  #pragma omp parallel for schedule(static) shared(status) \
1113  magick_number_threads(image,image,image->rows,1)
1114 #endif
1115  for (y=0; y < (ssize_t) image->rows; y++)
1116  {
1117  MagickBooleanType
1118  sync;
1119 
1121  pixel;
1122 
1123  ssize_t
1124  x;
1125 
1126  PixelPacket
1127  *magick_restrict q;
1128 
1129  size_t
1130  blue,
1131  green,
1132  red;
1133 
1134  if (status == MagickFalse)
1135  continue;
1136  q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
1137  exception);
1138  if (q == (PixelPacket *) NULL)
1139  {
1140  status=MagickFalse;
1141  continue;
1142  }
1143  for (x=0; x < (ssize_t) image->columns; x++)
1144  {
1145  red=ScaleQuantumToMap(ClampToQuantum((MagickRealType)
1146  GetPixelRed(q)));
1147  green=ScaleQuantumToMap(ClampToQuantum((MagickRealType)
1148  GetPixelGreen(q)));
1149  blue=ScaleQuantumToMap(ClampToQuantum((MagickRealType)
1150  GetPixelBlue(q)));
1151  pixel.red=(x_map[red].x+y_map[green].x+z_map[blue].x)+
1152  (MagickRealType) primary_info.x;
1153  pixel.green=(x_map[red].y+y_map[green].y+z_map[blue].y)+
1154  (MagickRealType) primary_info.y;
1155  pixel.blue=(x_map[red].z+y_map[green].z+z_map[blue].z)+
1156  (MagickRealType) primary_info.z;
1157  SetPixelRed(q,ScaleMapToQuantum(pixel.red));
1158  SetPixelGreen(q,ScaleMapToQuantum(pixel.green));
1159  SetPixelBlue(q,ScaleMapToQuantum(pixel.blue));
1160  q++;
1161  }
1162  sync=SyncCacheViewAuthenticPixels(image_view,exception);
1163  if (sync == MagickFalse)
1164  status=MagickFalse;
1165  if (image->progress_monitor != (MagickProgressMonitor) NULL)
1166  {
1167  MagickBooleanType
1168  proceed;
1169 
1170 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1171  #pragma omp atomic
1172 #endif
1173  progress++;
1174  proceed=SetImageProgress(image,RGBTransformImageTag,progress,
1175  image->rows);
1176  if (proceed == MagickFalse)
1177  status=MagickFalse;
1178  }
1179  }
1180  image_view=DestroyCacheView(image_view);
1181  break;
1182  }
1183  case PseudoClass:
1184  {
1185  size_t
1186  blue,
1187  green,
1188  red;
1189 
1190  /*
1191  Convert PseudoClass image.
1192  */
1193  for (i=0; i < (ssize_t) image->colors; i++)
1194  {
1196  pixel;
1197 
1198  red=ScaleQuantumToMap(ClampToQuantum((MagickRealType)
1199  image->colormap[i].red));
1200  green=ScaleQuantumToMap(ClampToQuantum((MagickRealType)
1201  image->colormap[i].green));
1202  blue=ScaleQuantumToMap(ClampToQuantum((MagickRealType)
1203  image->colormap[i].blue));
1204  pixel.red=x_map[red].x+y_map[green].x+z_map[blue].x+primary_info.x;
1205  pixel.green=x_map[red].y+y_map[green].y+z_map[blue].y+primary_info.y;
1206  pixel.blue=x_map[red].z+y_map[green].z+z_map[blue].z+primary_info.z;
1207  image->colormap[i].red=ScaleMapToQuantum(pixel.red);
1208  image->colormap[i].green=ScaleMapToQuantum(pixel.green);
1209  image->colormap[i].blue=ScaleMapToQuantum(pixel.blue);
1210  }
1211  (void) SyncImage(image);
1212  break;
1213  }
1214  }
1215  /*
1216  Relinquish resources.
1217  */
1218  z_map=(TransformPacket *) RelinquishMagickMemory(z_map);
1219  y_map=(TransformPacket *) RelinquishMagickMemory(y_map);
1220  x_map=(TransformPacket *) RelinquishMagickMemory(x_map);
1221  if (SetImageColorspace(image,colorspace) == MagickFalse)
1222  return(MagickFalse);
1223  return(status);
1224 }
1225 
1226 /*
1227 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1228 % %
1229 % %
1230 % %
1231 % S e t I m a g e C o l o r s p a c e %
1232 % %
1233 % %
1234 % %
1235 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1236 %
1237 % SetImageColorspace() sets the colorspace member of the Image structure.
1238 %
1239 % The format of the SetImageColorspace method is:
1240 %
1241 % MagickBooleanType SetImageColorspace(Image *image,
1242 % const ColorspaceType colorspace)
1243 %
1244 % A description of each parameter follows:
1245 %
1246 % o image: the image.
1247 %
1248 % o colorspace: the colorspace.
1249 %
1250 */
1251 MagickExport MagickBooleanType SetImageColorspace(Image *image,
1252  const ColorspaceType colorspace)
1253 {
1254  ImageType
1255  type;
1256 
1257  MagickBooleanType
1258  status;
1259 
1260  assert(image != (Image *) NULL);
1261  assert(image->signature == MagickCoreSignature);
1262  if (IsEventLogging() != MagickFalse)
1263  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1264  if (image->colorspace == colorspace)
1265  return(MagickTrue);
1266  image->colorspace=colorspace;
1267  image->rendering_intent=UndefinedIntent;
1268  image->gamma=1.000/2.200;
1269  (void) memset(&image->chromaticity,0,sizeof(image->chromaticity));
1270  type=image->type;
1271  if (IsGrayColorspace(colorspace) != MagickFalse)
1272  {
1273  if (colorspace == LinearGRAYColorspace)
1274  image->gamma=1.0;
1275  type=GrayscaleType;
1276  }
1277  else
1278  if ((IsRGBColorspace(colorspace) != MagickFalse) ||
1279  (colorspace == XYZColorspace) || (colorspace == xyYColorspace))
1280  image->gamma=1.0;
1281  else
1282  {
1283  image->rendering_intent=PerceptualIntent;
1284  image->chromaticity.red_primary.x=0.6400;
1285  image->chromaticity.red_primary.y=0.3300;
1286  image->chromaticity.red_primary.z=0.0300;
1287  image->chromaticity.green_primary.x=0.3000;
1288  image->chromaticity.green_primary.y=0.6000;
1289  image->chromaticity.green_primary.z=0.1000;
1290  image->chromaticity.blue_primary.x=0.1500;
1291  image->chromaticity.blue_primary.y=0.0600;
1292  image->chromaticity.blue_primary.z=0.7900;
1293  image->chromaticity.white_point.x=0.3127;
1294  image->chromaticity.white_point.y=0.3290;
1295  image->chromaticity.white_point.z=0.3583;
1296  }
1297  status=SyncImagePixelCache(image,&image->exception);
1298  image->type=type;
1299  return(status);
1300 }
1301 
1302 /*
1303 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1304 % %
1305 % %
1306 % %
1307 % S e t I m a g e G r a y %
1308 % %
1309 % %
1310 % %
1311 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1312 %
1313 % SetImageGray() returns MagickTrue if all the pixels in the image have the
1314 % same red, green, and blue intensities and changes the type of the image to
1315 % bi-level or grayscale.
1316 %
1317 % The format of the SetImageGray method is:
1318 %
1319 % MagickBooleanType SetImageGray(const Image *image,
1320 % ExceptionInfo *exception)
1321 %
1322 % A description of each parameter follows:
1323 %
1324 % o image: the image.
1325 %
1326 % o exception: return any errors or warnings in this structure.
1327 %
1328 */
1329 MagickExport MagickBooleanType SetImageGray(Image *image,
1330  ExceptionInfo *exception)
1331 {
1332  const char
1333  *value;
1334 
1335  CacheView
1336  *image_view;
1337 
1338  ImageType
1339  type;
1340 
1341  const PixelPacket
1342  *p;
1343 
1344  ssize_t
1345  x;
1346 
1347  ssize_t
1348  y;
1349 
1350  assert(image != (Image *) NULL);
1351  assert(image->signature == MagickCoreSignature);
1352  if (IsEventLogging() != MagickFalse)
1353  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1354  if ((image->type == BilevelType) || (image->type == GrayscaleType) ||
1355  (image->type == GrayscaleMatteType))
1356  return(MagickTrue);
1357  if ((IsGrayColorspace(image->colorspace) == MagickFalse) &&
1358  (IssRGBCompatibleColorspace(image->colorspace) == MagickFalse))
1359  return(MagickFalse);
1360  value=GetImageProperty(image,"colorspace:auto-grayscale");
1361  if (IsStringNotFalse(value) == MagickFalse)
1362  return(MagickFalse);
1363  type=BilevelType;
1364  image_view=AcquireVirtualCacheView(image,exception);
1365  for (y=0; y < (ssize_t) image->rows; y++)
1366  {
1367  p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
1368  if (p == (const PixelPacket *) NULL)
1369  break;
1370  for (x=0; x < (ssize_t) image->columns; x++)
1371  {
1372  if (IsGrayPixel(p) == MagickFalse)
1373  {
1374  type=UndefinedType;
1375  break;
1376  }
1377  if ((type == BilevelType) && (IsMonochromePixel(p) == MagickFalse))
1378  type=GrayscaleType;
1379  p++;
1380  }
1381  if (type == UndefinedType)
1382  break;
1383  }
1384  image_view=DestroyCacheView(image_view);
1385  if (type == UndefinedType)
1386  return(MagickFalse);
1387  image->colorspace=GRAYColorspace;
1388  if (SyncImagePixelCache((Image *) image,exception) == MagickFalse)
1389  return(MagickFalse);
1390  image->type=type;
1391  if ((type == GrayscaleType) && (image->matte != MagickFalse))
1392  image->type=GrayscaleMatteType;
1393  return(MagickTrue);
1394 }
1395 
1396 /*
1397 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1398 % %
1399 % %
1400 % %
1401 % S e t I m a g e M o n o c h r o m e %
1402 % %
1403 % %
1404 % %
1405 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1406 %
1407 % SetImageMonochrome() returns MagickTrue if all the pixels in the image have
1408 % the same red, green, and blue intensities and the intensity is either
1409 % 0 or QuantumRange and changes the type of the image to bi-level.
1410 %
1411 % The format of the SetImageMonochrome method is:
1412 %
1413 % MagickBooleanType SetImageMonochrome(const Image *image,
1414 % ExceptionInfo *exception)
1415 %
1416 % A description of each parameter follows:
1417 %
1418 % o image: the image.
1419 %
1420 % o exception: return any errors or warnings in this structure.
1421 %
1422 */
1423 MagickExport MagickBooleanType SetImageMonochrome(Image *image,
1424  ExceptionInfo *exception)
1425 {
1426  const char
1427  *value;
1428 
1429  CacheView
1430  *image_view;
1431 
1432  ImageType
1433  type;
1434 
1435  ssize_t
1436  x;
1437 
1438  const PixelPacket
1439  *p;
1440 
1441  ssize_t
1442  y;
1443 
1444  assert(image != (Image *) NULL);
1445  assert(image->signature == MagickCoreSignature);
1446  if (IsEventLogging() != MagickFalse)
1447  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1448  if (IsMonochromeImage(image,&image->exception) != MagickFalse)
1449  return(MagickTrue);
1450  if ((IsGrayColorspace(image->colorspace) == MagickFalse) &&
1451  (IssRGBCompatibleColorspace(image->colorspace) == MagickFalse))
1452  return(MagickFalse);
1453  value=GetImageProperty(image,"colorspace:auto-grayscale");
1454  if (IsStringNotFalse(value) == MagickFalse)
1455  return(MagickFalse);
1456  type=BilevelType;
1457  image_view=AcquireVirtualCacheView(image,exception);
1458  for (y=0; y < (ssize_t) image->rows; y++)
1459  {
1460  p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
1461  if (p == (const PixelPacket *) NULL)
1462  break;
1463  for (x=0; x < (ssize_t) image->columns; x++)
1464  {
1465  if (IsMonochromePixel(p) == MagickFalse)
1466  {
1467  type=UndefinedType;
1468  break;
1469  }
1470  p++;
1471  }
1472  if (type == UndefinedType)
1473  break;
1474  }
1475  image_view=DestroyCacheView(image_view);
1476  if (type == UndefinedType)
1477  return(MagickFalse);
1478  image->colorspace=GRAYColorspace;
1479  if (SyncImagePixelCache((Image *) image,exception) == MagickFalse)
1480  return(MagickFalse);
1481  image->type=type;
1482  return(MagickTrue);
1483 }
1484 
1485 /*
1486 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1487 % %
1488 % %
1489 % %
1490 % T r a n s f o r m I m a g e C o l o r s p a c e %
1491 % %
1492 % %
1493 % %
1494 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1495 %
1496 % TransformImageColorspace() transforms an image colorspace.
1497 %
1498 % The format of the TransformImageColorspace method is:
1499 %
1500 % MagickBooleanType TransformImageColorspace(Image *image,
1501 % const ColorspaceType colorspace)
1502 %
1503 % A description of each parameter follows:
1504 %
1505 % o image: the image.
1506 %
1507 % o colorspace: the colorspace.
1508 %
1509 */
1510 MagickExport MagickBooleanType TransformImageColorspace(Image *image,
1511  const ColorspaceType colorspace)
1512 {
1513  MagickBooleanType
1514  status;
1515 
1516  assert(image != (Image *) NULL);
1517  assert(image->signature == MagickCoreSignature);
1518  if (IsEventLogging() != MagickFalse)
1519  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1520  if (image->colorspace == colorspace)
1521  return(MagickTrue);
1522  (void) DeleteImageProfile(image,"icc");
1523  (void) DeleteImageProfile(image,"icm");
1524  if (colorspace == UndefinedColorspace)
1525  return(SetImageColorspace(image,colorspace));
1526  /*
1527  Convert the reference image from an alternate colorspace to sRGB.
1528  */
1529  if (IssRGBColorspace(colorspace) != MagickFalse)
1530  return(TransformRGBImage(image,image->colorspace));
1531  status=MagickTrue;
1532  if (IssRGBColorspace(image->colorspace) == MagickFalse)
1533  status=TransformRGBImage(image,image->colorspace);
1534  if (status == MagickFalse)
1535  return(status);
1536  /*
1537  Convert the reference image from sRGB to an alternate colorspace.
1538  */
1539  if (RGBTransformImage(image,colorspace) == MagickFalse)
1540  status=MagickFalse;
1541  return(status);
1542 }
1543 
1544 /*
1545 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1546 % %
1547 % %
1548 % %
1549 + T r a n s f o r m R G B I m a g e %
1550 % %
1551 % %
1552 % %
1553 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1554 %
1555 % TransformRGBImage() converts the reference image from an alternate
1556 % colorspace to sRGB. The transformation matrices are not the standard ones:
1557 % the weights are rescaled to normalize the range of the transformed values to
1558 % be [0..QuantumRange].
1559 %
1560 % The format of the TransformRGBImage method is:
1561 %
1562 % MagickBooleanType TransformRGBImage(Image *image,
1563 % const ColorspaceType colorspace)
1564 %
1565 % A description of each parameter follows:
1566 %
1567 % o image: the image.
1568 %
1569 % o colorspace: the colorspace to transform the image to.
1570 %
1571 */
1572 
1573 static inline void ConvertCMYToRGB(const double cyan,const double magenta,
1574  const double yellow,Quantum *red,Quantum *green,Quantum *blue)
1575 {
1576  *red=ClampToQuantum(QuantumRange*(1.0-cyan));
1577  *green=ClampToQuantum(QuantumRange*(1.0-magenta));
1578  *blue=ClampToQuantum(QuantumRange*(1.0-yellow));
1579 }
1580 
1581 static inline void ConvertLMSToXYZ(const double L,const double M,const double S,
1582  double *X,double *Y,double *Z)
1583 {
1584  *X=1.096123820835514*L-0.278869000218287*M+0.182745179382773*S;
1585  *Y=0.454369041975359*L+0.473533154307412*M+0.072097803717229*S;
1586  *Z=(-0.009627608738429)*L-0.005698031216113*M+1.015325639954543*S;
1587 }
1588 
1589 static inline void ConvertLMSToRGB(const double L,const double M,
1590  const double S,Quantum *red,Quantum *green,Quantum *blue)
1591 {
1592  double
1593  X,
1594  Y,
1595  Z;
1596 
1597  ConvertLMSToXYZ(L,M,S,&X,&Y,&Z);
1598  ConvertXYZToRGB(X,Y,Z,red,green,blue);
1599 }
1600 
1601 static inline void ConvertLuvToRGB(const double L,const double u,
1602  const double v,Quantum *red,Quantum *green,Quantum *blue)
1603 {
1604  double
1605  X,
1606  Y,
1607  Z;
1608 
1609  ConvertLuvToXYZ(100.0*L,354.0*u-134.0,262.0*v-140.0,&X,&Y,&Z);
1610  ConvertXYZToRGB(X,Y,Z,red,green,blue);
1611 }
1612 
1613 static inline ssize_t RoundToYCC(const MagickRealType value)
1614 {
1615  if (value <= 0.0)
1616  return(0);
1617  if (value >= 1388.0)
1618  return(1388);
1619  return((ssize_t) (value+0.5));
1620 }
1621 
1622 static inline void ConvertLabToRGB(const double L,const double a,
1623  const double b,Quantum *red,Quantum *green,Quantum *blue)
1624 {
1625  double
1626  X,
1627  Y,
1628  Z;
1629 
1630  ConvertLabToXYZ(100.0*L,255.0*(a-0.5),255.0*(b-0.5),&X,&Y,&Z);
1631  ConvertXYZToRGB(X,Y,Z,red,green,blue);
1632 }
1633 
1634 static inline void ConvertxyYToRGB(const double low_x,const double low_y,
1635  const double cap_Y,Quantum *red,Quantum *green,Quantum *blue)
1636 {
1637  double
1638  gamma,
1639  X,
1640  Y,
1641  Z;
1642 
1643  gamma=PerceptibleReciprocal(low_y);
1644  X=gamma*cap_Y*low_x;
1645  Y=cap_Y;
1646  Z=gamma*cap_Y*(1.0-low_x-low_y);
1647  ConvertXYZToRGB(X,Y,Z,red,green,blue);
1648 }
1649 
1650 static void ConvertYPbPrToRGB(const double Y,const double Pb,const double Pr,
1651  Quantum *red,Quantum *green,Quantum *blue)
1652 {
1653  *red=ClampToQuantum(QuantumRange*(0.99999999999914679361*Y-
1654  1.2188941887145875e-06*(Pb-0.5)+1.4019995886561440468*(Pr-0.5)));
1655  *green=ClampToQuantum(QuantumRange*(0.99999975910502514331*Y-
1656  0.34413567816504303521*(Pb-0.5)-0.71413649331646789076*(Pr-0.5)));
1657  *blue=ClampToQuantum(QuantumRange*(1.00000124040004623180*Y+
1658  1.77200006607230409200*(Pb-0.5)+2.1453384174593273e-06*(Pr-0.5)));
1659 }
1660 
1661 static void ConvertYCbCrToRGB(const double Y,const double Cb,
1662  const double Cr,Quantum *red,Quantum *green,Quantum *blue)
1663 {
1664  ConvertYPbPrToRGB(Y,Cb,Cr,red,green,blue);
1665 }
1666 
1667 static void ConvertYDbDrToRGB(const double Y,const double Db,const double Dr,
1668  Quantum *red,Quantum *green,Quantum *blue)
1669 {
1670  *red=ClampToQuantum(QuantumRange*(Y+9.2303716147657e-05*(Db-0.5)-
1671  0.52591263066186533*(Dr-0.5)));
1672  *green=ClampToQuantum(QuantumRange*(Y-0.12913289889050927*(Db-0.5)+
1673  0.26789932820759876*(Dr-0.5)));
1674  *blue=ClampToQuantum(QuantumRange*(Y+0.66467905997895482*(Db-0.5)-
1675  7.9202543533108e-05*(Dr-0.5)));
1676 }
1677 
1678 static void ConvertYIQToRGB(const double Y,const double I,const double Q,
1679  Quantum *red,Quantum *green,Quantum *blue)
1680 {
1681  *red=ClampToQuantum(QuantumRange*(Y+0.9562957197589482261*(I-0.5)+
1682  0.6210244164652610754*(Q-0.5)));
1683  *green=ClampToQuantum(QuantumRange*(Y-0.2721220993185104464*(I-0.5)-
1684  0.6473805968256950427*(Q-0.5)));
1685  *blue=ClampToQuantum(QuantumRange*(Y-1.1069890167364901945*(I-0.5)+
1686  1.7046149983646481374*(Q-0.5)));
1687 }
1688 
1689 static void ConvertYUVToRGB(const double Y,const double U,const double V,
1690  Quantum *red,Quantum *green,Quantum *blue)
1691 {
1692  *red=ClampToQuantum(QuantumRange*(Y-3.945707070708279e-05*(U-0.5)+
1693  1.1398279671717170825*(V-0.5)));
1694  *green=ClampToQuantum(QuantumRange*(Y-0.3946101641414141437*(U-0.5)-
1695  0.5805003156565656797*(V-0.5)));
1696  *blue=ClampToQuantum(QuantumRange*(Y+2.0319996843434342537*(U-0.5)-
1697  4.813762626262513e-04*(V-0.5)));
1698 }
1699 
1700 MagickExport MagickBooleanType TransformRGBImage(Image *image,
1701  const ColorspaceType colorspace)
1702 {
1703 #define TransformRGBImageTag "Transform/Image"
1704 
1705  static const float
1706  YCCMap[1389] =
1707  {
1708  0.000000, 0.000720f, 0.001441f, 0.002161f, 0.002882f, 0.003602f,
1709  0.004323f, 0.005043f, 0.005764f, 0.006484f, 0.007205f, 0.007925f,
1710  0.008646f, 0.009366f, 0.010086f, 0.010807f, 0.011527f, 0.012248f,
1711  0.012968f, 0.013689f, 0.014409f, 0.015130f, 0.015850f, 0.016571f,
1712  0.017291f, 0.018012f, 0.018732f, 0.019452f, 0.020173f, 0.020893f,
1713  0.021614f, 0.022334f, 0.023055f, 0.023775f, 0.024496f, 0.025216f,
1714  0.025937f, 0.026657f, 0.027378f, 0.028098f, 0.028818f, 0.029539f,
1715  0.030259f, 0.030980f, 0.031700f, 0.032421f, 0.033141f, 0.033862f,
1716  0.034582f, 0.035303f, 0.036023f, 0.036744f, 0.037464f, 0.038184f,
1717  0.038905f, 0.039625f, 0.040346f, 0.041066f, 0.041787f, 0.042507f,
1718  0.043228f, 0.043948f, 0.044669f, 0.045389f, 0.046110f, 0.046830f,
1719  0.047550f, 0.048271f, 0.048991f, 0.049712f, 0.050432f, 0.051153f,
1720  0.051873f, 0.052594f, 0.053314f, 0.054035f, 0.054755f, 0.055476f,
1721  0.056196f, 0.056916f, 0.057637f, 0.058357f, 0.059078f, 0.059798f,
1722  0.060519f, 0.061239f, 0.061960f, 0.062680f, 0.063401f, 0.064121f,
1723  0.064842f, 0.065562f, 0.066282f, 0.067003f, 0.067723f, 0.068444f,
1724  0.069164f, 0.069885f, 0.070605f, 0.071326f, 0.072046f, 0.072767f,
1725  0.073487f, 0.074207f, 0.074928f, 0.075648f, 0.076369f, 0.077089f,
1726  0.077810f, 0.078530f, 0.079251f, 0.079971f, 0.080692f, 0.081412f,
1727  0.082133f, 0.082853f, 0.083573f, 0.084294f, 0.085014f, 0.085735f,
1728  0.086455f, 0.087176f, 0.087896f, 0.088617f, 0.089337f, 0.090058f,
1729  0.090778f, 0.091499f, 0.092219f, 0.092939f, 0.093660f, 0.094380f,
1730  0.095101f, 0.095821f, 0.096542f, 0.097262f, 0.097983f, 0.098703f,
1731  0.099424f, 0.100144f, 0.100865f, 0.101585f, 0.102305f, 0.103026f,
1732  0.103746f, 0.104467f, 0.105187f, 0.105908f, 0.106628f, 0.107349f,
1733  0.108069f, 0.108790f, 0.109510f, 0.110231f, 0.110951f, 0.111671f,
1734  0.112392f, 0.113112f, 0.113833f, 0.114553f, 0.115274f, 0.115994f,
1735  0.116715f, 0.117435f, 0.118156f, 0.118876f, 0.119597f, 0.120317f,
1736  0.121037f, 0.121758f, 0.122478f, 0.123199f, 0.123919f, 0.124640f,
1737  0.125360f, 0.126081f, 0.126801f, 0.127522f, 0.128242f, 0.128963f,
1738  0.129683f, 0.130403f, 0.131124f, 0.131844f, 0.132565f, 0.133285f,
1739  0.134006f, 0.134726f, 0.135447f, 0.136167f, 0.136888f, 0.137608f,
1740  0.138329f, 0.139049f, 0.139769f, 0.140490f, 0.141210f, 0.141931f,
1741  0.142651f, 0.143372f, 0.144092f, 0.144813f, 0.145533f, 0.146254f,
1742  0.146974f, 0.147695f, 0.148415f, 0.149135f, 0.149856f, 0.150576f,
1743  0.151297f, 0.152017f, 0.152738f, 0.153458f, 0.154179f, 0.154899f,
1744  0.155620f, 0.156340f, 0.157061f, 0.157781f, 0.158501f, 0.159222f,
1745  0.159942f, 0.160663f, 0.161383f, 0.162104f, 0.162824f, 0.163545f,
1746  0.164265f, 0.164986f, 0.165706f, 0.166427f, 0.167147f, 0.167867f,
1747  0.168588f, 0.169308f, 0.170029f, 0.170749f, 0.171470f, 0.172190f,
1748  0.172911f, 0.173631f, 0.174352f, 0.175072f, 0.175793f, 0.176513f,
1749  0.177233f, 0.177954f, 0.178674f, 0.179395f, 0.180115f, 0.180836f,
1750  0.181556f, 0.182277f, 0.182997f, 0.183718f, 0.184438f, 0.185159f,
1751  0.185879f, 0.186599f, 0.187320f, 0.188040f, 0.188761f, 0.189481f,
1752  0.190202f, 0.190922f, 0.191643f, 0.192363f, 0.193084f, 0.193804f,
1753  0.194524f, 0.195245f, 0.195965f, 0.196686f, 0.197406f, 0.198127f,
1754  0.198847f, 0.199568f, 0.200288f, 0.201009f, 0.201729f, 0.202450f,
1755  0.203170f, 0.203890f, 0.204611f, 0.205331f, 0.206052f, 0.206772f,
1756  0.207493f, 0.208213f, 0.208934f, 0.209654f, 0.210375f, 0.211095f,
1757  0.211816f, 0.212536f, 0.213256f, 0.213977f, 0.214697f, 0.215418f,
1758  0.216138f, 0.216859f, 0.217579f, 0.218300f, 0.219020f, 0.219741f,
1759  0.220461f, 0.221182f, 0.221902f, 0.222622f, 0.223343f, 0.224063f,
1760  0.224784f, 0.225504f, 0.226225f, 0.226945f, 0.227666f, 0.228386f,
1761  0.229107f, 0.229827f, 0.230548f, 0.231268f, 0.231988f, 0.232709f,
1762  0.233429f, 0.234150f, 0.234870f, 0.235591f, 0.236311f, 0.237032f,
1763  0.237752f, 0.238473f, 0.239193f, 0.239914f, 0.240634f, 0.241354f,
1764  0.242075f, 0.242795f, 0.243516f, 0.244236f, 0.244957f, 0.245677f,
1765  0.246398f, 0.247118f, 0.247839f, 0.248559f, 0.249280f, 0.250000f,
1766  0.250720f, 0.251441f, 0.252161f, 0.252882f, 0.253602f, 0.254323f,
1767  0.255043f, 0.255764f, 0.256484f, 0.257205f, 0.257925f, 0.258646f,
1768  0.259366f, 0.260086f, 0.260807f, 0.261527f, 0.262248f, 0.262968f,
1769  0.263689f, 0.264409f, 0.265130f, 0.265850f, 0.266571f, 0.267291f,
1770  0.268012f, 0.268732f, 0.269452f, 0.270173f, 0.270893f, 0.271614f,
1771  0.272334f, 0.273055f, 0.273775f, 0.274496f, 0.275216f, 0.275937f,
1772  0.276657f, 0.277378f, 0.278098f, 0.278818f, 0.279539f, 0.280259f,
1773  0.280980f, 0.281700f, 0.282421f, 0.283141f, 0.283862f, 0.284582f,
1774  0.285303f, 0.286023f, 0.286744f, 0.287464f, 0.288184f, 0.288905f,
1775  0.289625f, 0.290346f, 0.291066f, 0.291787f, 0.292507f, 0.293228f,
1776  0.293948f, 0.294669f, 0.295389f, 0.296109f, 0.296830f, 0.297550f,
1777  0.298271f, 0.298991f, 0.299712f, 0.300432f, 0.301153f, 0.301873f,
1778  0.302594f, 0.303314f, 0.304035f, 0.304755f, 0.305476f, 0.306196f,
1779  0.306916f, 0.307637f, 0.308357f, 0.309078f, 0.309798f, 0.310519f,
1780  0.311239f, 0.311960f, 0.312680f, 0.313401f, 0.314121f, 0.314842f,
1781  0.315562f, 0.316282f, 0.317003f, 0.317723f, 0.318444f, 0.319164f,
1782  0.319885f, 0.320605f, 0.321326f, 0.322046f, 0.322767f, 0.323487f,
1783  0.324207f, 0.324928f, 0.325648f, 0.326369f, 0.327089f, 0.327810f,
1784  0.328530f, 0.329251f, 0.329971f, 0.330692f, 0.331412f, 0.332133f,
1785  0.332853f, 0.333573f, 0.334294f, 0.335014f, 0.335735f, 0.336455f,
1786  0.337176f, 0.337896f, 0.338617f, 0.339337f, 0.340058f, 0.340778f,
1787  0.341499f, 0.342219f, 0.342939f, 0.343660f, 0.344380f, 0.345101f,
1788  0.345821f, 0.346542f, 0.347262f, 0.347983f, 0.348703f, 0.349424f,
1789  0.350144f, 0.350865f, 0.351585f, 0.352305f, 0.353026f, 0.353746f,
1790  0.354467f, 0.355187f, 0.355908f, 0.356628f, 0.357349f, 0.358069f,
1791  0.358790f, 0.359510f, 0.360231f, 0.360951f, 0.361671f, 0.362392f,
1792  0.363112f, 0.363833f, 0.364553f, 0.365274f, 0.365994f, 0.366715f,
1793  0.367435f, 0.368156f, 0.368876f, 0.369597f, 0.370317f, 0.371037f,
1794  0.371758f, 0.372478f, 0.373199f, 0.373919f, 0.374640f, 0.375360f,
1795  0.376081f, 0.376801f, 0.377522f, 0.378242f, 0.378963f, 0.379683f,
1796  0.380403f, 0.381124f, 0.381844f, 0.382565f, 0.383285f, 0.384006f,
1797  0.384726f, 0.385447f, 0.386167f, 0.386888f, 0.387608f, 0.388329f,
1798  0.389049f, 0.389769f, 0.390490f, 0.391210f, 0.391931f, 0.392651f,
1799  0.393372f, 0.394092f, 0.394813f, 0.395533f, 0.396254f, 0.396974f,
1800  0.397695f, 0.398415f, 0.399135f, 0.399856f, 0.400576f, 0.401297f,
1801  0.402017f, 0.402738f, 0.403458f, 0.404179f, 0.404899f, 0.405620f,
1802  0.406340f, 0.407061f, 0.407781f, 0.408501f, 0.409222f, 0.409942f,
1803  0.410663f, 0.411383f, 0.412104f, 0.412824f, 0.413545f, 0.414265f,
1804  0.414986f, 0.415706f, 0.416427f, 0.417147f, 0.417867f, 0.418588f,
1805  0.419308f, 0.420029f, 0.420749f, 0.421470f, 0.422190f, 0.422911f,
1806  0.423631f, 0.424352f, 0.425072f, 0.425793f, 0.426513f, 0.427233f,
1807  0.427954f, 0.428674f, 0.429395f, 0.430115f, 0.430836f, 0.431556f,
1808  0.432277f, 0.432997f, 0.433718f, 0.434438f, 0.435158f, 0.435879f,
1809  0.436599f, 0.437320f, 0.438040f, 0.438761f, 0.439481f, 0.440202f,
1810  0.440922f, 0.441643f, 0.442363f, 0.443084f, 0.443804f, 0.444524f,
1811  0.445245f, 0.445965f, 0.446686f, 0.447406f, 0.448127f, 0.448847f,
1812  0.449568f, 0.450288f, 0.451009f, 0.451729f, 0.452450f, 0.453170f,
1813  0.453891f, 0.454611f, 0.455331f, 0.456052f, 0.456772f, 0.457493f,
1814  0.458213f, 0.458934f, 0.459654f, 0.460375f, 0.461095f, 0.461816f,
1815  0.462536f, 0.463256f, 0.463977f, 0.464697f, 0.465418f, 0.466138f,
1816  0.466859f, 0.467579f, 0.468300f, 0.469020f, 0.469741f, 0.470461f,
1817  0.471182f, 0.471902f, 0.472622f, 0.473343f, 0.474063f, 0.474784f,
1818  0.475504f, 0.476225f, 0.476945f, 0.477666f, 0.478386f, 0.479107f,
1819  0.479827f, 0.480548f, 0.481268f, 0.481988f, 0.482709f, 0.483429f,
1820  0.484150f, 0.484870f, 0.485591f, 0.486311f, 0.487032f, 0.487752f,
1821  0.488473f, 0.489193f, 0.489914f, 0.490634f, 0.491354f, 0.492075f,
1822  0.492795f, 0.493516f, 0.494236f, 0.494957f, 0.495677f, 0.496398f,
1823  0.497118f, 0.497839f, 0.498559f, 0.499280f, 0.500000f, 0.500720f,
1824  0.501441f, 0.502161f, 0.502882f, 0.503602f, 0.504323f, 0.505043f,
1825  0.505764f, 0.506484f, 0.507205f, 0.507925f, 0.508646f, 0.509366f,
1826  0.510086f, 0.510807f, 0.511527f, 0.512248f, 0.512968f, 0.513689f,
1827  0.514409f, 0.515130f, 0.515850f, 0.516571f, 0.517291f, 0.518012f,
1828  0.518732f, 0.519452f, 0.520173f, 0.520893f, 0.521614f, 0.522334f,
1829  0.523055f, 0.523775f, 0.524496f, 0.525216f, 0.525937f, 0.526657f,
1830  0.527378f, 0.528098f, 0.528818f, 0.529539f, 0.530259f, 0.530980f,
1831  0.531700f, 0.532421f, 0.533141f, 0.533862f, 0.534582f, 0.535303f,
1832  0.536023f, 0.536744f, 0.537464f, 0.538184f, 0.538905f, 0.539625f,
1833  0.540346f, 0.541066f, 0.541787f, 0.542507f, 0.543228f, 0.543948f,
1834  0.544669f, 0.545389f, 0.546109f, 0.546830f, 0.547550f, 0.548271f,
1835  0.548991f, 0.549712f, 0.550432f, 0.551153f, 0.551873f, 0.552594f,
1836  0.553314f, 0.554035f, 0.554755f, 0.555476f, 0.556196f, 0.556916f,
1837  0.557637f, 0.558357f, 0.559078f, 0.559798f, 0.560519f, 0.561239f,
1838  0.561960f, 0.562680f, 0.563401f, 0.564121f, 0.564842f, 0.565562f,
1839  0.566282f, 0.567003f, 0.567723f, 0.568444f, 0.569164f, 0.569885f,
1840  0.570605f, 0.571326f, 0.572046f, 0.572767f, 0.573487f, 0.574207f,
1841  0.574928f, 0.575648f, 0.576369f, 0.577089f, 0.577810f, 0.578530f,
1842  0.579251f, 0.579971f, 0.580692f, 0.581412f, 0.582133f, 0.582853f,
1843  0.583573f, 0.584294f, 0.585014f, 0.585735f, 0.586455f, 0.587176f,
1844  0.587896f, 0.588617f, 0.589337f, 0.590058f, 0.590778f, 0.591499f,
1845  0.592219f, 0.592939f, 0.593660f, 0.594380f, 0.595101f, 0.595821f,
1846  0.596542f, 0.597262f, 0.597983f, 0.598703f, 0.599424f, 0.600144f,
1847  0.600865f, 0.601585f, 0.602305f, 0.603026f, 0.603746f, 0.604467f,
1848  0.605187f, 0.605908f, 0.606628f, 0.607349f, 0.608069f, 0.608790f,
1849  0.609510f, 0.610231f, 0.610951f, 0.611671f, 0.612392f, 0.613112f,
1850  0.613833f, 0.614553f, 0.615274f, 0.615994f, 0.616715f, 0.617435f,
1851  0.618156f, 0.618876f, 0.619597f, 0.620317f, 0.621037f, 0.621758f,
1852  0.622478f, 0.623199f, 0.623919f, 0.624640f, 0.625360f, 0.626081f,
1853  0.626801f, 0.627522f, 0.628242f, 0.628963f, 0.629683f, 0.630403f,
1854  0.631124f, 0.631844f, 0.632565f, 0.633285f, 0.634006f, 0.634726f,
1855  0.635447f, 0.636167f, 0.636888f, 0.637608f, 0.638329f, 0.639049f,
1856  0.639769f, 0.640490f, 0.641210f, 0.641931f, 0.642651f, 0.643372f,
1857  0.644092f, 0.644813f, 0.645533f, 0.646254f, 0.646974f, 0.647695f,
1858  0.648415f, 0.649135f, 0.649856f, 0.650576f, 0.651297f, 0.652017f,
1859  0.652738f, 0.653458f, 0.654179f, 0.654899f, 0.655620f, 0.656340f,
1860  0.657061f, 0.657781f, 0.658501f, 0.659222f, 0.659942f, 0.660663f,
1861  0.661383f, 0.662104f, 0.662824f, 0.663545f, 0.664265f, 0.664986f,
1862  0.665706f, 0.666427f, 0.667147f, 0.667867f, 0.668588f, 0.669308f,
1863  0.670029f, 0.670749f, 0.671470f, 0.672190f, 0.672911f, 0.673631f,
1864  0.674352f, 0.675072f, 0.675793f, 0.676513f, 0.677233f, 0.677954f,
1865  0.678674f, 0.679395f, 0.680115f, 0.680836f, 0.681556f, 0.682277f,
1866  0.682997f, 0.683718f, 0.684438f, 0.685158f, 0.685879f, 0.686599f,
1867  0.687320f, 0.688040f, 0.688761f, 0.689481f, 0.690202f, 0.690922f,
1868  0.691643f, 0.692363f, 0.693084f, 0.693804f, 0.694524f, 0.695245f,
1869  0.695965f, 0.696686f, 0.697406f, 0.698127f, 0.698847f, 0.699568f,
1870  0.700288f, 0.701009f, 0.701729f, 0.702450f, 0.703170f, 0.703891f,
1871  0.704611f, 0.705331f, 0.706052f, 0.706772f, 0.707493f, 0.708213f,
1872  0.708934f, 0.709654f, 0.710375f, 0.711095f, 0.711816f, 0.712536f,
1873  0.713256f, 0.713977f, 0.714697f, 0.715418f, 0.716138f, 0.716859f,
1874  0.717579f, 0.718300f, 0.719020f, 0.719741f, 0.720461f, 0.721182f,
1875  0.721902f, 0.722622f, 0.723343f, 0.724063f, 0.724784f, 0.725504f,
1876  0.726225f, 0.726945f, 0.727666f, 0.728386f, 0.729107f, 0.729827f,
1877  0.730548f, 0.731268f, 0.731988f, 0.732709f, 0.733429f, 0.734150f,
1878  0.734870f, 0.735591f, 0.736311f, 0.737032f, 0.737752f, 0.738473f,
1879  0.739193f, 0.739914f, 0.740634f, 0.741354f, 0.742075f, 0.742795f,
1880  0.743516f, 0.744236f, 0.744957f, 0.745677f, 0.746398f, 0.747118f,
1881  0.747839f, 0.748559f, 0.749280f, 0.750000f, 0.750720f, 0.751441f,
1882  0.752161f, 0.752882f, 0.753602f, 0.754323f, 0.755043f, 0.755764f,
1883  0.756484f, 0.757205f, 0.757925f, 0.758646f, 0.759366f, 0.760086f,
1884  0.760807f, 0.761527f, 0.762248f, 0.762968f, 0.763689f, 0.764409f,
1885  0.765130f, 0.765850f, 0.766571f, 0.767291f, 0.768012f, 0.768732f,
1886  0.769452f, 0.770173f, 0.770893f, 0.771614f, 0.772334f, 0.773055f,
1887  0.773775f, 0.774496f, 0.775216f, 0.775937f, 0.776657f, 0.777378f,
1888  0.778098f, 0.778818f, 0.779539f, 0.780259f, 0.780980f, 0.781700f,
1889  0.782421f, 0.783141f, 0.783862f, 0.784582f, 0.785303f, 0.786023f,
1890  0.786744f, 0.787464f, 0.788184f, 0.788905f, 0.789625f, 0.790346f,
1891  0.791066f, 0.791787f, 0.792507f, 0.793228f, 0.793948f, 0.794669f,
1892  0.795389f, 0.796109f, 0.796830f, 0.797550f, 0.798271f, 0.798991f,
1893  0.799712f, 0.800432f, 0.801153f, 0.801873f, 0.802594f, 0.803314f,
1894  0.804035f, 0.804755f, 0.805476f, 0.806196f, 0.806916f, 0.807637f,
1895  0.808357f, 0.809078f, 0.809798f, 0.810519f, 0.811239f, 0.811960f,
1896  0.812680f, 0.813401f, 0.814121f, 0.814842f, 0.815562f, 0.816282f,
1897  0.817003f, 0.817723f, 0.818444f, 0.819164f, 0.819885f, 0.820605f,
1898  0.821326f, 0.822046f, 0.822767f, 0.823487f, 0.824207f, 0.824928f,
1899  0.825648f, 0.826369f, 0.827089f, 0.827810f, 0.828530f, 0.829251f,
1900  0.829971f, 0.830692f, 0.831412f, 0.832133f, 0.832853f, 0.833573f,
1901  0.834294f, 0.835014f, 0.835735f, 0.836455f, 0.837176f, 0.837896f,
1902  0.838617f, 0.839337f, 0.840058f, 0.840778f, 0.841499f, 0.842219f,
1903  0.842939f, 0.843660f, 0.844380f, 0.845101f, 0.845821f, 0.846542f,
1904  0.847262f, 0.847983f, 0.848703f, 0.849424f, 0.850144f, 0.850865f,
1905  0.851585f, 0.852305f, 0.853026f, 0.853746f, 0.854467f, 0.855187f,
1906  0.855908f, 0.856628f, 0.857349f, 0.858069f, 0.858790f, 0.859510f,
1907  0.860231f, 0.860951f, 0.861671f, 0.862392f, 0.863112f, 0.863833f,
1908  0.864553f, 0.865274f, 0.865994f, 0.866715f, 0.867435f, 0.868156f,
1909  0.868876f, 0.869597f, 0.870317f, 0.871037f, 0.871758f, 0.872478f,
1910  0.873199f, 0.873919f, 0.874640f, 0.875360f, 0.876081f, 0.876801f,
1911  0.877522f, 0.878242f, 0.878963f, 0.879683f, 0.880403f, 0.881124f,
1912  0.881844f, 0.882565f, 0.883285f, 0.884006f, 0.884726f, 0.885447f,
1913  0.886167f, 0.886888f, 0.887608f, 0.888329f, 0.889049f, 0.889769f,
1914  0.890490f, 0.891210f, 0.891931f, 0.892651f, 0.893372f, 0.894092f,
1915  0.894813f, 0.895533f, 0.896254f, 0.896974f, 0.897695f, 0.898415f,
1916  0.899135f, 0.899856f, 0.900576f, 0.901297f, 0.902017f, 0.902738f,
1917  0.903458f, 0.904179f, 0.904899f, 0.905620f, 0.906340f, 0.907061f,
1918  0.907781f, 0.908501f, 0.909222f, 0.909942f, 0.910663f, 0.911383f,
1919  0.912104f, 0.912824f, 0.913545f, 0.914265f, 0.914986f, 0.915706f,
1920  0.916427f, 0.917147f, 0.917867f, 0.918588f, 0.919308f, 0.920029f,
1921  0.920749f, 0.921470f, 0.922190f, 0.922911f, 0.923631f, 0.924352f,
1922  0.925072f, 0.925793f, 0.926513f, 0.927233f, 0.927954f, 0.928674f,
1923  0.929395f, 0.930115f, 0.930836f, 0.931556f, 0.932277f, 0.932997f,
1924  0.933718f, 0.934438f, 0.935158f, 0.935879f, 0.936599f, 0.937320f,
1925  0.938040f, 0.938761f, 0.939481f, 0.940202f, 0.940922f, 0.941643f,
1926  0.942363f, 0.943084f, 0.943804f, 0.944524f, 0.945245f, 0.945965f,
1927  0.946686f, 0.947406f, 0.948127f, 0.948847f, 0.949568f, 0.950288f,
1928  0.951009f, 0.951729f, 0.952450f, 0.953170f, 0.953891f, 0.954611f,
1929  0.955331f, 0.956052f, 0.956772f, 0.957493f, 0.958213f, 0.958934f,
1930  0.959654f, 0.960375f, 0.961095f, 0.961816f, 0.962536f, 0.963256f,
1931  0.963977f, 0.964697f, 0.965418f, 0.966138f, 0.966859f, 0.967579f,
1932  0.968300f, 0.969020f, 0.969741f, 0.970461f, 0.971182f, 0.971902f,
1933  0.972622f, 0.973343f, 0.974063f, 0.974784f, 0.975504f, 0.976225f,
1934  0.976945f, 0.977666f, 0.978386f, 0.979107f, 0.979827f, 0.980548f,
1935  0.981268f, 0.981988f, 0.982709f, 0.983429f, 0.984150f, 0.984870f,
1936  0.985591f, 0.986311f, 0.987032f, 0.987752f, 0.988473f, 0.989193f,
1937  0.989914f, 0.990634f, 0.991354f, 0.992075f, 0.992795f, 0.993516f,
1938  0.994236f, 0.994957f, 0.995677f, 0.996398f, 0.997118f, 0.997839f,
1939  0.998559f, 0.999280f, 1.000000
1940  };
1941 
1942  CacheView
1943  *image_view;
1944 
1946  *exception;
1947 
1948  MagickBooleanType
1949  status;
1950 
1951  MagickOffsetType
1952  progress;
1953 
1954  ssize_t
1955  i;
1956 
1957  ssize_t
1958  y;
1959 
1961  *y_map,
1962  *x_map,
1963  *z_map;
1964 
1965  assert(image != (Image *) NULL);
1966  assert(image->signature == MagickCoreSignature);
1967  if (IsEventLogging() != MagickFalse)
1968  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1969  status=MagickTrue;
1970  progress=0;
1971  exception=(&image->exception);
1972  switch (colorspace)
1973  {
1974  case CMYKColorspace:
1975  {
1977  zero;
1978 
1979  /*
1980  Transform image from CMYK to sRGB.
1981  */
1982  if (image->storage_class == PseudoClass)
1983  {
1984  if (SyncImage(image) == MagickFalse)
1985  return(MagickFalse);
1986  if (SetImageStorageClass(image,DirectClass) == MagickFalse)
1987  return(MagickFalse);
1988  }
1989  GetMagickPixelPacket(image,&zero);
1990  image_view=AcquireAuthenticCacheView(image,exception);
1991 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1992  #pragma omp parallel for schedule(static) shared(status) \
1993  magick_number_threads(image,image,image->rows,1)
1994 #endif
1995  for (y=0; y < (ssize_t) image->rows; y++)
1996  {
1997  MagickBooleanType
1998  sync;
1999 
2001  pixel;
2002 
2003  IndexPacket
2004  *magick_restrict indexes;
2005 
2006  ssize_t
2007  x;
2008 
2009  PixelPacket
2010  *magick_restrict q;
2011 
2012  if (status == MagickFalse)
2013  continue;
2014  q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
2015  exception);
2016  if (q == (PixelPacket *) NULL)
2017  {
2018  status=MagickFalse;
2019  continue;
2020  }
2021  indexes=GetCacheViewAuthenticIndexQueue(image_view);
2022  pixel=zero;
2023  for (x=0; x < (ssize_t) image->columns; x++)
2024  {
2025  SetMagickPixelPacket(image,q,indexes+x,&pixel);
2026  ConvertCMYKToRGB(&pixel);
2027  SetPixelPacket(image,&pixel,q,indexes+x);
2028  q++;
2029  }
2030  sync=SyncCacheViewAuthenticPixels(image_view,exception);
2031  if (sync == MagickFalse)
2032  status=MagickFalse;
2033  }
2034  image_view=DestroyCacheView(image_view);
2035  if (SetImageColorspace(image,sRGBColorspace) == MagickFalse)
2036  return(MagickFalse);
2037  return(status);
2038  }
2039  case LinearGRAYColorspace:
2040  case Rec601LumaColorspace:
2041  {
2042  /*
2043  Transform linear RGB to sRGB colorspace.
2044  */
2045  if (image->storage_class == PseudoClass)
2046  {
2047  if (SyncImage(image) == MagickFalse)
2048  return(MagickFalse);
2049  if (SetImageStorageClass(image,DirectClass) == MagickFalse)
2050  return(MagickFalse);
2051  }
2052  if (SetImageColorspace(image,sRGBColorspace) == MagickFalse)
2053  return(MagickFalse);
2054  image_view=AcquireAuthenticCacheView(image,exception);
2055 #if defined(MAGICKCORE_OPENMP_SUPPORT)
2056  #pragma omp parallel for schedule(static) shared(status) \
2057  magick_number_threads(image,image,image->rows,1)
2058 #endif
2059  for (y=0; y < (ssize_t) image->rows; y++)
2060  {
2061  MagickBooleanType
2062  sync;
2063 
2064  ssize_t
2065  x;
2066 
2067  PixelPacket
2068  *magick_restrict q;
2069 
2070  if (status == MagickFalse)
2071  continue;
2072  q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
2073  exception);
2074  if (q == (PixelPacket *) NULL)
2075  {
2076  status=MagickFalse;
2077  continue;
2078  }
2079  for (x=(ssize_t) image->columns; x != 0; x--)
2080  {
2081  MagickRealType
2082  gray;
2083 
2084  gray=0.212656*EncodePixelGamma(GetPixelRed(q))+0.715158*
2085  EncodePixelGamma(GetPixelGreen(q))+0.072186*
2086  EncodePixelGamma(GetPixelBlue(q));
2087  SetPixelRed(q,ClampToQuantum(gray));
2088  SetPixelGreen(q,ClampToQuantum(gray));
2089  SetPixelBlue(q,ClampToQuantum(gray));
2090  q++;
2091  }
2092  sync=SyncCacheViewAuthenticPixels(image_view,exception);
2093  if (sync == MagickFalse)
2094  status=MagickFalse;
2095  }
2096  image_view=DestroyCacheView(image_view);
2097  if (SetImageColorspace(image,sRGBColorspace) == MagickFalse)
2098  return(MagickFalse);
2099  return(status);
2100  }
2101  case GRAYColorspace:
2102  case Rec709LumaColorspace:
2103  {
2104  /*
2105  Transform linear RGB to sRGB colorspace.
2106  */
2107  if (image->storage_class == PseudoClass)
2108  {
2109  if (SyncImage(image) == MagickFalse)
2110  return(MagickFalse);
2111  if (SetImageStorageClass(image,DirectClass) == MagickFalse)
2112  return(MagickFalse);
2113  }
2114  if (SetImageColorspace(image,sRGBColorspace) == MagickFalse)
2115  return(MagickFalse);
2116  image_view=AcquireAuthenticCacheView(image,exception);
2117 #if defined(MAGICKCORE_OPENMP_SUPPORT)
2118  #pragma omp parallel for schedule(static) shared(status) \
2119  magick_number_threads(image,image,image->rows,1)
2120 #endif
2121  for (y=0; y < (ssize_t) image->rows; y++)
2122  {
2123  MagickBooleanType
2124  sync;
2125 
2126  ssize_t
2127  x;
2128 
2129  PixelPacket
2130  *magick_restrict q;
2131 
2132  if (status == MagickFalse)
2133  continue;
2134  q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
2135  exception);
2136  if (q == (PixelPacket *) NULL)
2137  {
2138  status=MagickFalse;
2139  continue;
2140  }
2141  for (x=(ssize_t) image->columns; x != 0; x--)
2142  {
2143  MagickRealType
2144  gray;
2145 
2146  gray=0.212656*GetPixelRed(q)+0.715158*GetPixelGreen(q)+
2147  0.072186*GetPixelBlue(q);
2148  SetPixelRed(q,ClampToQuantum(gray));
2149  SetPixelGreen(q,ClampToQuantum(gray));
2150  SetPixelBlue(q,ClampToQuantum(gray));
2151  q++;
2152  }
2153  sync=SyncCacheViewAuthenticPixels(image_view,exception);
2154  if (sync == MagickFalse)
2155  status=MagickFalse;
2156  }
2157  image_view=DestroyCacheView(image_view);
2158  if (SetImageColorspace(image,sRGBColorspace) == MagickFalse)
2159  return(MagickFalse);
2160  return(status);
2161  }
2162  case CMYColorspace:
2163  case HCLColorspace:
2164  case HCLpColorspace:
2165  case HSBColorspace:
2166  case HSIColorspace:
2167  case HSLColorspace:
2168  case HSVColorspace:
2169  case HWBColorspace:
2170  case LabColorspace:
2171  case LCHColorspace:
2172  case LCHabColorspace:
2173  case LCHuvColorspace:
2174  case LMSColorspace:
2175  case LuvColorspace:
2176  case xyYColorspace:
2177  case XYZColorspace:
2178  case YCbCrColorspace:
2179  case YDbDrColorspace:
2180  case YIQColorspace:
2181  case YPbPrColorspace:
2182  case YUVColorspace:
2183  {
2184  /*
2185  Transform image from source colorspace to sRGB.
2186  */
2187  if (image->storage_class == PseudoClass)
2188  {
2189  if (SyncImage(image) == MagickFalse)
2190  return(MagickFalse);
2191  if (SetImageStorageClass(image,DirectClass) == MagickFalse)
2192  return(MagickFalse);
2193  }
2194  image_view=AcquireAuthenticCacheView(image,exception);
2195 #if defined(MAGICKCORE_OPENMP_SUPPORT)
2196  #pragma omp parallel for schedule(static) shared(status) \
2197  magick_number_threads(image,image,image->rows,1)
2198 #endif
2199  for (y=0; y < (ssize_t) image->rows; y++)
2200  {
2201  MagickBooleanType
2202  sync;
2203 
2204  ssize_t
2205  x;
2206 
2207  PixelPacket
2208  *magick_restrict q;
2209 
2210  if (status == MagickFalse)
2211  continue;
2212  q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
2213  exception);
2214  if (q == (PixelPacket *) NULL)
2215  {
2216  status=MagickFalse;
2217  continue;
2218  }
2219  for (x=0; x < (ssize_t) image->columns; x++)
2220  {
2221  double
2222  X,
2223  Y,
2224  Z;
2225 
2226  Quantum
2227  blue,
2228  green,
2229  red;
2230 
2231  X=QuantumScale*GetPixelRed(q);
2232  Y=QuantumScale*GetPixelGreen(q);
2233  Z=QuantumScale*GetPixelBlue(q);
2234  switch (colorspace)
2235  {
2236  case CMYColorspace:
2237  {
2238  ConvertCMYToRGB(X,Y,Z,&red,&green,&blue);
2239  break;
2240  }
2241  case HCLColorspace:
2242  {
2243  ConvertHCLToRGB(X,Y,Z,&red,&green,&blue);
2244  break;
2245  }
2246  case HCLpColorspace:
2247  {
2248  ConvertHCLpToRGB(X,Y,Z,&red,&green,&blue);
2249  break;
2250  }
2251  case HSBColorspace:
2252  {
2253  ConvertHSBToRGB(X,Y,Z,&red,&green,&blue);
2254  break;
2255  }
2256  case HSIColorspace:
2257  {
2258  ConvertHSIToRGB(X,Y,Z,&red,&green,&blue);
2259  break;
2260  }
2261  case HSLColorspace:
2262  {
2263  ConvertHSLToRGB(X,Y,Z,&red,&green,&blue);
2264  break;
2265  }
2266  case HSVColorspace:
2267  {
2268  ConvertHSVToRGB(X,Y,Z,&red,&green,&blue);
2269  break;
2270  }
2271  case HWBColorspace:
2272  {
2273  ConvertHWBToRGB(X,Y,Z,&red,&green,&blue);
2274  break;
2275  }
2276  case LabColorspace:
2277  {
2278  ConvertLabToRGB(X,Y,Z,&red,&green,&blue);
2279  break;
2280  }
2281  case LCHColorspace:
2282  case LCHabColorspace:
2283  {
2284  ConvertLCHabToRGB(X,Y,Z,&red,&green,&blue);
2285  break;
2286  }
2287  case LCHuvColorspace:
2288  {
2289  ConvertLCHuvToRGB(X,Y,Z,&red,&green,&blue);
2290  break;
2291  }
2292  case LMSColorspace:
2293  {
2294  ConvertLMSToRGB(X,Y,Z,&red,&green,&blue);
2295  break;
2296  }
2297  case LuvColorspace:
2298  {
2299  ConvertLuvToRGB(X,Y,Z,&red,&green,&blue);
2300  break;
2301  }
2302  case xyYColorspace:
2303  {
2304  ConvertxyYToRGB(X,Y,Z,&red,&green,&blue);
2305  break;
2306  }
2307  case XYZColorspace:
2308  {
2309  ConvertXYZToRGB(X,Y,Z,&red,&green,&blue);
2310  break;
2311  }
2312  case YCbCrColorspace:
2313  {
2314  ConvertYCbCrToRGB(X,Y,Z,&red,&green,&blue);
2315  break;
2316  }
2317  case YDbDrColorspace:
2318  {
2319  ConvertYDbDrToRGB(X,Y,Z,&red,&green,&blue);
2320  break;
2321  }
2322  case YIQColorspace:
2323  {
2324  ConvertYIQToRGB(X,Y,Z,&red,&green,&blue);
2325  break;
2326  }
2327  case YPbPrColorspace:
2328  {
2329  ConvertYPbPrToRGB(X,Y,Z,&red,&green,&blue);
2330  break;
2331  }
2332  case YUVColorspace:
2333  {
2334  ConvertYUVToRGB(X,Y,Z,&red,&green,&blue);
2335  break;
2336  }
2337  default:
2338  {
2339  red=ClampToQuantum(QuantumRange*X);
2340  green=ClampToQuantum(QuantumRange*Y);
2341  blue=ClampToQuantum(QuantumRange*Z);
2342  break;
2343  }
2344  }
2345  SetPixelRed(q,ClampToQuantum((MagickRealType) red));
2346  SetPixelGreen(q,ClampToQuantum((MagickRealType) green));
2347  SetPixelBlue(q,ClampToQuantum((MagickRealType) blue));
2348  q++;
2349  }
2350  sync=SyncCacheViewAuthenticPixels(image_view,exception);
2351  if (sync == MagickFalse)
2352  status=MagickFalse;
2353  }
2354  image_view=DestroyCacheView(image_view);
2355  if (SetImageColorspace(image,sRGBColorspace) == MagickFalse)
2356  return(MagickFalse);
2357  return(status);
2358  }
2359  case LogColorspace:
2360  {
2361  const char
2362  *value;
2363 
2364  double
2365  black,
2366  density,
2367  film_gamma,
2368  gamma,
2369  reference_black,
2370  reference_white;
2371 
2372  Quantum
2373  *logmap;
2374 
2375  /*
2376  Transform Log to sRGB colorspace.
2377  */
2378  density=DisplayGamma;
2379  gamma=DisplayGamma;
2380  value=GetImageProperty(image,"gamma");
2381  if (value != (const char *) NULL)
2382  gamma=PerceptibleReciprocal(StringToDouble(value,(char **) NULL));
2383  film_gamma=FilmGamma;
2384  value=GetImageProperty(image,"film-gamma");
2385  if (value != (const char *) NULL)
2386  film_gamma=StringToDouble(value,(char **) NULL);
2387  reference_black=ReferenceBlack;
2388  value=GetImageProperty(image,"reference-black");
2389  if (value != (const char *) NULL)
2390  reference_black=StringToDouble(value,(char **) NULL);
2391  reference_white=ReferenceWhite;
2392  value=GetImageProperty(image,"reference-white");
2393  if (value != (const char *) NULL)
2394  reference_white=StringToDouble(value,(char **) NULL);
2395  logmap=(Quantum *) AcquireQuantumMemory((size_t) MaxMap+1UL,
2396  sizeof(*logmap));
2397  if (logmap == (Quantum *) NULL)
2398  ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
2399  image->filename);
2400  black=pow(10.0,(reference_black-reference_white)*(gamma/density)*0.002*
2401  PerceptibleReciprocal(film_gamma));
2402  for (i=0; i <= (ssize_t) (reference_black*MaxMap/1024.0); i++)
2403  logmap[i]=(Quantum) 0;
2404  for ( ; i < (ssize_t) (reference_white*MaxMap/1024.0); i++)
2405  logmap[i]=ClampToQuantum((MagickRealType) QuantumRange/(1.0-black)*
2406  (pow(10.0,(1024.0*i/MaxMap-reference_white)*(gamma/density)*0.002*
2407  PerceptibleReciprocal(film_gamma))-black));
2408  for ( ; i <= (ssize_t) MaxMap; i++)
2409  logmap[i]=QuantumRange;
2410  if (image->storage_class == PseudoClass)
2411  {
2412  if (SyncImage(image) == MagickFalse)
2413  return(MagickFalse);
2414  if (SetImageStorageClass(image,DirectClass) == MagickFalse)
2415  return(MagickFalse);
2416  }
2417  image_view=AcquireAuthenticCacheView(image,exception);
2418 #if defined(MAGICKCORE_OPENMP_SUPPORT)
2419  #pragma omp parallel for schedule(static) shared(status) \
2420  magick_number_threads(image,image,image->rows,1)
2421 #endif
2422  for (y=0; y < (ssize_t) image->rows; y++)
2423  {
2424  MagickBooleanType
2425  sync;
2426 
2427  ssize_t
2428  x;
2429 
2430  PixelPacket
2431  *magick_restrict q;
2432 
2433  if (status == MagickFalse)
2434  continue;
2435  q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
2436  exception);
2437  if (q == (PixelPacket *) NULL)
2438  {
2439  status=MagickFalse;
2440  continue;
2441  }
2442  for (x=(ssize_t) image->columns; x != 0; x--)
2443  {
2444  Quantum
2445  blue,
2446  green,
2447  red;
2448 
2449  red=ClampToQuantum(EncodePixelGamma((MagickRealType)
2450  logmap[ScaleQuantumToMap(GetPixelRed(q))]));
2451  green=ClampToQuantum(EncodePixelGamma((MagickRealType)
2452  logmap[ScaleQuantumToMap(GetPixelGreen(q))]));
2453  blue=ClampToQuantum(EncodePixelGamma((MagickRealType)
2454  logmap[ScaleQuantumToMap(GetPixelBlue(q))]));
2455  SetPixelRed(q,red);
2456  SetPixelGreen(q,green);
2457  SetPixelBlue(q,blue);
2458  q++;
2459  }
2460  sync=SyncCacheViewAuthenticPixels(image_view,exception);
2461  if (sync == MagickFalse)
2462  status=MagickFalse;
2463  }
2464  image_view=DestroyCacheView(image_view);
2465  logmap=(Quantum *) RelinquishMagickMemory(logmap);
2466  if (SetImageColorspace(image,sRGBColorspace) == MagickFalse)
2467  return(MagickFalse);
2468  return(status);
2469  }
2470  case RGBColorspace:
2471  case scRGBColorspace:
2472  {
2473  /*
2474  Transform linear RGB to sRGB colorspace.
2475  */
2476  if (image->storage_class == PseudoClass)
2477  {
2478  if (SyncImage(image) == MagickFalse)
2479  return(MagickFalse);
2480  if (SetImageStorageClass(image,DirectClass) == MagickFalse)
2481  return(MagickFalse);
2482  }
2483  image_view=AcquireAuthenticCacheView(image,exception);
2484 #if defined(MAGICKCORE_OPENMP_SUPPORT)
2485  #pragma omp parallel for schedule(static) shared(status) \
2486  magick_number_threads(image,image,image->rows,1)
2487 #endif
2488  for (y=0; y < (ssize_t) image->rows; y++)
2489  {
2490  MagickBooleanType
2491  sync;
2492 
2493  ssize_t
2494  x;
2495 
2496  PixelPacket
2497  *magick_restrict q;
2498 
2499  if (status == MagickFalse)
2500  continue;
2501  q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
2502  exception);
2503  if (q == (PixelPacket *) NULL)
2504  {
2505  status=MagickFalse;
2506  continue;
2507  }
2508  for (x=(ssize_t) image->columns; x != 0; x--)
2509  {
2510  Quantum
2511  blue,
2512  green,
2513  red;
2514 
2515  red=ClampToQuantum(EncodePixelGamma((MagickRealType) GetPixelRed(q)));
2516  green=ClampToQuantum(EncodePixelGamma((MagickRealType)
2517  GetPixelGreen(q)));
2518  blue=ClampToQuantum(EncodePixelGamma((MagickRealType)
2519  GetPixelBlue(q)));
2520  SetPixelRed(q,red);
2521  SetPixelGreen(q,green);
2522  SetPixelBlue(q,blue);
2523  q++;
2524  }
2525  sync=SyncCacheViewAuthenticPixels(image_view,exception);
2526  if (sync == MagickFalse)
2527  status=MagickFalse;
2528  }
2529  image_view=DestroyCacheView(image_view);
2530  if (SetImageColorspace(image,sRGBColorspace) == MagickFalse)
2531  return(MagickFalse);
2532  return(status);
2533  }
2534  default:
2535  break;
2536  }
2537  /*
2538  Allocate the tables.
2539  */
2540  x_map=(TransformPacket *) AcquireQuantumMemory((size_t) MaxMap+1UL,
2541  sizeof(*x_map));
2542  y_map=(TransformPacket *) AcquireQuantumMemory((size_t) MaxMap+1UL,
2543  sizeof(*y_map));
2544  z_map=(TransformPacket *) AcquireQuantumMemory((size_t) MaxMap+1UL,
2545  sizeof(*z_map));
2546  if ((x_map == (TransformPacket *) NULL) ||
2547  (y_map == (TransformPacket *) NULL) ||
2548  (z_map == (TransformPacket *) NULL))
2549  {
2550  if (z_map != (TransformPacket *) NULL)
2551  z_map=(TransformPacket *) RelinquishMagickMemory(z_map);
2552  if (y_map != (TransformPacket *) NULL)
2553  y_map=(TransformPacket *) RelinquishMagickMemory(y_map);
2554  if (x_map != (TransformPacket *) NULL)
2555  x_map=(TransformPacket *) RelinquishMagickMemory(x_map);
2556  ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
2557  image->filename);
2558  }
2559  switch (colorspace)
2560  {
2561  case OHTAColorspace:
2562  {
2563  /*
2564  Initialize OHTA tables:
2565 
2566  R = I1+1.00000*I2-0.66668*I3
2567  G = I1+0.00000*I2+1.33333*I3
2568  B = I1-1.00000*I2-0.66668*I3
2569 
2570  I and Q, normally -0.5 through 0.5, must be normalized to the range 0
2571  through QuantumRange.
2572  */
2573 #if defined(MAGICKCORE_OPENMP_SUPPORT)
2574  #pragma omp parallel for schedule(static)
2575 #endif
2576  for (i=0; i <= (ssize_t) MaxMap; i++)
2577  {
2578  x_map[i].x=(1.0*(double) i);
2579  y_map[i].x=(0.5*1.00000*(2.0*(double) i-MaxMap));
2580  z_map[i].x=(-0.5*0.66668*(2.0*(double) i-MaxMap));
2581  x_map[i].y=(1.0*(double) i);
2582  y_map[i].y=(0.5*0.00000*(2.0*(double) i-MaxMap));
2583  z_map[i].y=(0.5*1.33333*(2.0*(double) i-MaxMap));
2584  x_map[i].z=(1.0*(double) i);
2585  y_map[i].z=(-0.5*1.00000*(2.0*(double) i-MaxMap));
2586  z_map[i].z=(-0.5*0.66668*(2.0*(double) i-MaxMap));
2587  }
2588  break;
2589  }
2590  case Rec601YCbCrColorspace:
2591  {
2592  /*
2593  Initialize YCbCr tables:
2594 
2595  R = Y +1.402000*Cr
2596  G = Y-0.344136*Cb-0.714136*Cr
2597  B = Y+1.772000*Cb
2598 
2599  Cb and Cr, normally -0.5 through 0.5, must be normalized to the range 0
2600  through QuantumRange.
2601  */
2602 #if defined(MAGICKCORE_OPENMP_SUPPORT)
2603  #pragma omp parallel for schedule(static)
2604 #endif
2605  for (i=0; i <= (ssize_t) MaxMap; i++)
2606  {
2607  x_map[i].x=0.99999999999914679361*(double) i;
2608  y_map[i].x=0.5*(-1.2188941887145875e-06)*(2.00*(double) i-MaxMap);
2609  z_map[i].x=0.5*1.4019995886561440468*(2.00*(double) i-MaxMap);
2610  x_map[i].y=0.99999975910502514331*(double) i;
2611  y_map[i].y=0.5*(-0.34413567816504303521)*(2.00*(double) i-MaxMap);
2612  z_map[i].y=0.5*(-0.71413649331646789076)*(2.00*(double) i-MaxMap);
2613  x_map[i].z=1.00000124040004623180*(double) i;
2614  y_map[i].z=0.5*1.77200006607230409200*(2.00*(double) i-MaxMap);
2615  z_map[i].z=0.5*2.1453384174593273e-06*(2.00*(double) i-MaxMap);
2616  }
2617  break;
2618  }
2619  case Rec709YCbCrColorspace:
2620  {
2621  /*
2622  Initialize YCbCr tables:
2623 
2624  R = Y +1.574800*Cr
2625  G = Y-0.187324*Cb-0.468124*Cr
2626  B = Y+1.855600*Cb
2627 
2628  Cb and Cr, normally -0.5 through 0.5, must be normalized to the range 0
2629  through QuantumRange.
2630  */
2631 #if defined(MAGICKCORE_OPENMP_SUPPORT)
2632  #pragma omp parallel for schedule(static)
2633 #endif
2634  for (i=0; i <= (ssize_t) MaxMap; i++)
2635  {
2636  x_map[i].x=(MagickRealType) (1.0*(double) i);
2637  y_map[i].x=(MagickRealType) (0.5*0.000000*(2.0*(double) i-MaxMap));
2638  z_map[i].x=(MagickRealType) (0.5*1.574800*(2.0*(double) i-MaxMap));
2639  x_map[i].y=(MagickRealType) (1.0*(double) i);
2640  y_map[i].y=(MagickRealType) (0.5*(-0.187324)*(2.0*(double) i-MaxMap));
2641  z_map[i].y=(MagickRealType) (0.5*(-0.468124)*(2.0*(double) i-MaxMap));
2642  x_map[i].z=(MagickRealType) (1.0*(double) i);
2643  y_map[i].z=(MagickRealType) (0.5*1.855600*(2.0*(double) i-MaxMap));
2644  z_map[i].z=(MagickRealType) (0.5*0.000000*(2.0*(double) i-MaxMap));
2645  }
2646  break;
2647  }
2648  case YCCColorspace:
2649  {
2650  /*
2651  Initialize YCC tables:
2652 
2653  R = Y +1.340762*C2
2654  G = Y-0.317038*C1-0.682243*C2
2655  B = Y+1.632639*C1
2656 
2657  YCC is scaled by 1.3584. C1 zero is 156 and C2 is at 137.
2658  */
2659 #if defined(MAGICKCORE_OPENMP_SUPPORT)
2660  #pragma omp parallel for schedule(static)
2661 #endif
2662  for (i=0; i <= (ssize_t) MaxMap; i++)
2663  {
2664  x_map[i].x=(MagickRealType) (1.3584000*(double) i);
2665  y_map[i].x=(MagickRealType) (0.0000000);
2666  z_map[i].x=(MagickRealType) (1.8215000*((double) i-(MagickRealType)
2667  ScaleQuantumToMap(ScaleCharToQuantum(137))));
2668  x_map[i].y=(MagickRealType) (1.3584000*(double) i);
2669  y_map[i].y=(MagickRealType) ((-0.4302726)*((double) i-(MagickRealType)
2670  ScaleQuantumToMap(ScaleCharToQuantum(156))));
2671  z_map[i].y=(MagickRealType) ((-0.9271435)*((double) i-(MagickRealType)
2672  ScaleQuantumToMap(ScaleCharToQuantum(137))));
2673  x_map[i].z=(MagickRealType) (1.3584000*(double) i);
2674  y_map[i].z=(MagickRealType) (2.2179000*((double) i-(MagickRealType)
2675  ScaleQuantumToMap(ScaleCharToQuantum(156))));
2676  z_map[i].z=(MagickRealType) (0.0000000);
2677  }
2678  break;
2679  }
2680  default:
2681  {
2682  /*
2683  Linear conversion tables.
2684  */
2685 #if defined(MAGICKCORE_OPENMP_SUPPORT)
2686  #pragma omp parallel for schedule(static)
2687 #endif
2688  for (i=0; i <= (ssize_t) MaxMap; i++)
2689  {
2690  x_map[i].x=(MagickRealType) (1.0*(double) i);
2691  y_map[i].x=(MagickRealType) 0.0;
2692  z_map[i].x=(MagickRealType) 0.0;
2693  x_map[i].y=(MagickRealType) 0.0;
2694  y_map[i].y=(MagickRealType) (1.0*(double) i);
2695  z_map[i].y=(MagickRealType) 0.0;
2696  x_map[i].z=(MagickRealType) 0.0;
2697  y_map[i].z=(MagickRealType) 0.0;
2698  z_map[i].z=(MagickRealType) (1.0*(double) i);
2699  }
2700  break;
2701  }
2702  }
2703  /*
2704  Convert to sRGB.
2705  */
2706  switch (image->storage_class)
2707  {
2708  case DirectClass:
2709  default:
2710  {
2711  /*
2712  Convert DirectClass image.
2713  */
2714  image_view=AcquireAuthenticCacheView(image,exception);
2715 #if defined(MAGICKCORE_OPENMP_SUPPORT)
2716  #pragma omp parallel for schedule(static) shared(status) \
2717  magick_number_threads(image,image,image->rows,1)
2718 #endif
2719  for (y=0; y < (ssize_t) image->rows; y++)
2720  {
2721  MagickBooleanType
2722  sync;
2723 
2725  pixel;
2726 
2727  ssize_t
2728  x;
2729 
2730  PixelPacket
2731  *magick_restrict q;
2732 
2733  if (status == MagickFalse)
2734  continue;
2735  q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
2736  exception);
2737  if (q == (PixelPacket *) NULL)
2738  {
2739  status=MagickFalse;
2740  continue;
2741  }
2742  for (x=0; x < (ssize_t) image->columns; x++)
2743  {
2744  size_t
2745  blue,
2746  green,
2747  red;
2748 
2749  red=ScaleQuantumToMap(GetPixelRed(q));
2750  green=ScaleQuantumToMap(GetPixelGreen(q));
2751  blue=ScaleQuantumToMap(GetPixelBlue(q));
2752  pixel.red=x_map[red].x+y_map[green].x+z_map[blue].x;
2753  pixel.green=x_map[red].y+y_map[green].y+z_map[blue].y;
2754  pixel.blue=x_map[red].z+y_map[green].z+z_map[blue].z;
2755  if (colorspace == YCCColorspace)
2756  {
2757  pixel.red=QuantumRange*YCCMap[RoundToYCC(1024.0*pixel.red/
2758  (double) MaxMap)];
2759  pixel.green=QuantumRange*YCCMap[RoundToYCC(1024.0*pixel.green/
2760  (double) MaxMap)];
2761  pixel.blue=QuantumRange*YCCMap[RoundToYCC(1024.0*pixel.blue/
2762  (double) MaxMap)];
2763  }
2764  else
2765  {
2766  pixel.red=(MagickRealType) ScaleMapToQuantum(pixel.red);
2767  pixel.green=(MagickRealType) ScaleMapToQuantum(pixel.green);
2768  pixel.blue=(MagickRealType) ScaleMapToQuantum(pixel.blue);
2769  }
2770  SetPixelRed(q,ClampToQuantum(pixel.red));
2771  SetPixelGreen(q,ClampToQuantum(pixel.green));
2772  SetPixelBlue(q,ClampToQuantum(pixel.blue));
2773  q++;
2774  }
2775  sync=SyncCacheViewAuthenticPixels(image_view,exception);
2776  if (sync == MagickFalse)
2777  status=MagickFalse;
2778  if (image->progress_monitor != (MagickProgressMonitor) NULL)
2779  {
2780  MagickBooleanType
2781  proceed;
2782 
2783 #if defined(MAGICKCORE_OPENMP_SUPPORT)
2784  #pragma omp atomic
2785 #endif
2786  progress++;
2787  proceed=SetImageProgress(image,TransformRGBImageTag,progress,
2788  image->rows);
2789  if (proceed == MagickFalse)
2790  status=MagickFalse;
2791  }
2792  }
2793  image_view=DestroyCacheView(image_view);
2794  break;
2795  }
2796  case PseudoClass:
2797  {
2798  /*
2799  Convert PseudoClass image.
2800  */
2801 #if defined(MAGICKCORE_OPENMP_SUPPORT)
2802  #pragma omp parallel for schedule(static) shared(status) \
2803  magick_number_threads(image,image,image->colors,1)
2804 #endif
2805  for (i=0; i < (ssize_t) image->colors; i++)
2806  {
2808  pixel;
2809 
2810  size_t
2811  blue,
2812  green,
2813  red;
2814 
2815  red=ScaleQuantumToMap(image->colormap[i].red);
2816  green=ScaleQuantumToMap(image->colormap[i].green);
2817  blue=ScaleQuantumToMap(image->colormap[i].blue);
2818  pixel.red=x_map[red].x+y_map[green].x+z_map[blue].x;
2819  pixel.green=x_map[red].y+y_map[green].y+z_map[blue].y;
2820  pixel.blue=x_map[red].z+y_map[green].z+z_map[blue].z;
2821  if (colorspace == YCCColorspace)
2822  {
2823  pixel.red=QuantumRange*YCCMap[RoundToYCC(1024.0*pixel.red/
2824  (double) MaxMap)];
2825  pixel.green=QuantumRange*YCCMap[RoundToYCC(1024.0*pixel.green/
2826  (double) MaxMap)];
2827  pixel.blue=QuantumRange*YCCMap[RoundToYCC(1024.0*pixel.blue/
2828  (double) MaxMap)];
2829  }
2830  else
2831  {
2832  pixel.red=(MagickRealType) ScaleMapToQuantum(pixel.red);
2833  pixel.green=(MagickRealType) ScaleMapToQuantum(pixel.green);
2834  pixel.blue=(MagickRealType) ScaleMapToQuantum(pixel.blue);
2835  }
2836  image->colormap[i].red=ClampToQuantum(pixel.red);
2837  image->colormap[i].green=ClampToQuantum(pixel.green);
2838  image->colormap[i].blue=ClampToQuantum(pixel.blue);
2839  }
2840  (void) SyncImage(image);
2841  break;
2842  }
2843  }
2844  /*
2845  Relinquish resources.
2846  */
2847  z_map=(TransformPacket *) RelinquishMagickMemory(z_map);
2848  y_map=(TransformPacket *) RelinquishMagickMemory(y_map);
2849  x_map=(TransformPacket *) RelinquishMagickMemory(x_map);
2850  if (SetImageColorspace(image,sRGBColorspace) == MagickFalse)
2851  return(MagickFalse);
2852  return(MagickTrue);
2853 }
Definition: image.h:152