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