• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3 %                                                                             %
4 %                                                                             %
5 %                                                                             %
6 %                      PPPP   IIIII  X   X  EEEEE  L                          %
7 %                      P   P    I     X X   E      L                          %
8 %                      PPPP     I      X    EEE    L                          %
9 %                      P        I     X X   E      L                          %
10 %                      P      IIIII  X   X  EEEEE  LLLLL                      %
11 %                                                                             %
12 %                  MagickCore Methods to Import/Export Pixels                 %
13 %                                                                             %
14 %                             Software Design                                 %
15 %                                  Cristy                                     %
16 %                               October 1998                                  %
17 %                                                                             %
18 %                                                                             %
19 %  Copyright 1999-2021 ImageMagick Studio LLC, a non-profit organization      %
20 %  dedicated to making software imaging solutions freely available.           %
21 %                                                                             %
22 %  You may not use this file except in compliance with the License.  You may  %
23 %  obtain a copy of the License at                                            %
24 %                                                                             %
25 %    https://imagemagick.org/script/license.php                               %
26 %                                                                             %
27 %  Unless required by applicable law or agreed to in writing, software        %
28 %  distributed under the License is distributed on an "AS IS" BASIS,          %
29 %  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   %
30 %  See the License for the specific language governing permissions and        %
31 %  limitations under the License.                                             %
32 %                                                                             %
33 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
34 %
35 %
36 */
37 
38 /*
39   Include declarations.
40 */
41 #include "MagickCore/studio.h"
42 #include "MagickCore/property.h"
43 #include "MagickCore/blob.h"
44 #include "MagickCore/blob-private.h"
45 #include "MagickCore/cache-private.h"
46 #include "MagickCore/color-private.h"
47 #include "MagickCore/colorspace-private.h"
48 #include "MagickCore/draw.h"
49 #include "MagickCore/exception.h"
50 #include "MagickCore/exception-private.h"
51 #include "MagickCore/cache.h"
52 #include "MagickCore/constitute.h"
53 #include "MagickCore/delegate.h"
54 #include "MagickCore/geometry.h"
55 #include "MagickCore/image-private.h"
56 #include "MagickCore/list.h"
57 #include "MagickCore/magick.h"
58 #include "MagickCore/memory_.h"
59 #include "MagickCore/memory-private.h"
60 #include "MagickCore/monitor.h"
61 #include "MagickCore/option.h"
62 #include "MagickCore/pixel.h"
63 #include "MagickCore/pixel-accessor.h"
64 #include "MagickCore/pixel-private.h"
65 #include "MagickCore/quantum.h"
66 #include "MagickCore/quantum-private.h"
67 #include "MagickCore/resource_.h"
68 #include "MagickCore/semaphore.h"
69 #include "MagickCore/statistic.h"
70 #include "MagickCore/stream.h"
71 #include "MagickCore/string_.h"
72 #include "MagickCore/transform.h"
73 #include "MagickCore/utility.h"
74 
75 /*
76 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
77 %                                                                             %
78 %                                                                             %
79 %                                                                             %
80 +   A c q u i r e P i x e l C h a n n e l M a p                               %
81 %                                                                             %
82 %                                                                             %
83 %                                                                             %
84 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
85 %
86 %  AcquirePixelChannelMap() acquires a pixel component map.
87 %
88 %  The format of the AcquirePixelChannelMap() method is:
89 %
90 %      PixelChannelMap *AcquirePixelChannelMap(void)
91 %
92 */
AcquirePixelChannelMap(void)93 MagickExport PixelChannelMap *AcquirePixelChannelMap(void)
94 {
95   PixelChannelMap
96     *channel_map;
97 
98   ssize_t
99     i;
100 
101   channel_map=(PixelChannelMap *) AcquireQuantumMemory(MaxPixelChannels,
102     sizeof(*channel_map));
103   if (channel_map == (PixelChannelMap *) NULL)
104     ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
105   (void) memset(channel_map,0,MaxPixelChannels*sizeof(*channel_map));
106   for (i=0; i < MaxPixelChannels; i++)
107     channel_map[i].channel=(PixelChannel) i;
108   return(channel_map);
109 }
110 
111 /*
112 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
113 %                                                                             %
114 %                                                                             %
115 %                                                                             %
116 +   C l o n e P i x e l C h a n n e l M a p                                   %
117 %                                                                             %
118 %                                                                             %
119 %                                                                             %
120 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
121 %
122 %  ClonePixelChannelMap() clones a pixel component map.
123 %
124 %  The format of the ClonePixelChannelMap() method is:
125 %
126 %      PixelChannelMap *ClonePixelChannelMap(PixelChannelMap *channel_map)
127 %
128 %  A description of each parameter follows:
129 %
130 %    o channel_map: the pixel component map.
131 %
132 */
ClonePixelChannelMap(PixelChannelMap * channel_map)133 MagickExport PixelChannelMap *ClonePixelChannelMap(PixelChannelMap *channel_map)
134 {
135   PixelChannelMap
136     *clone_map;
137 
138   assert(channel_map != (PixelChannelMap *) NULL);
139   clone_map=AcquirePixelChannelMap();
140   if (clone_map == (PixelChannelMap *) NULL)
141     return((PixelChannelMap *) NULL);
142   (void) memcpy(clone_map,channel_map,MaxPixelChannels*
143     sizeof(*channel_map));
144   return(clone_map);
145 }
146 
147 /*
148 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
149 %                                                                             %
150 %                                                                             %
151 %                                                                             %
152 +   C l o n e P i x e l I n f o                                               %
153 %                                                                             %
154 %                                                                             %
155 %                                                                             %
156 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
157 %
158 %  ClonePixelInfo() makes a duplicate of the given pixel info structure, or if
159 %  pixel info is NULL, a new one.
160 %
161 %  The format of the ClonePixelInfo method is:
162 %
163 %      PixelInfo *ClonePixelInfo(const PixelInfo *pixel)
164 %
165 %  A description of each parameter follows:
166 %
167 %    o pixel: the pixel info.
168 %
169 */
ClonePixelInfo(const PixelInfo * pixel)170 MagickExport PixelInfo *ClonePixelInfo(const PixelInfo *pixel)
171 {
172   PixelInfo
173     *pixel_info;
174 
175   pixel_info=(PixelInfo *) AcquireMagickMemory(sizeof(*pixel_info));
176   if (pixel_info == (PixelInfo *) NULL)
177     ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
178   *pixel_info=(*pixel);
179   return(pixel_info);
180 }
181 
182 /*
183 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
184 %                                                                             %
185 %                                                                             %
186 %                                                                             %
187 +   C o n f o r m P i x e l I n f o                                           %
188 %                                                                             %
189 %                                                                             %
190 %                                                                             %
191 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
192 %
193 %  ConformPixelInfo() ensures the pixel conforms with the colorspace and alpha
194 %  attribute of the image.
195 %
196 %  The format of the ConformPixelInfo method is:
197 %
198 %      void *ConformPixelInfo((Image *image,const PixelInfo *source,
199 %        PixelInfo *destination,ExceptionInfo *exception)
200 %
201 %  A description of each parameter follows:
202 %
203 %    o image: the image.
204 %
205 %    o source: the source pixel info.
206 %
207 %    o destination: the destination pixel info.
208 %
209 %    o exception: return any errors or warnings in this structure.
210 %
211 */
ConformPixelInfo(Image * image,const PixelInfo * source,PixelInfo * destination,ExceptionInfo * exception)212 MagickExport void ConformPixelInfo(Image *image,const PixelInfo *source,
213   PixelInfo *destination,ExceptionInfo *exception)
214 {
215   assert(image != (Image *) NULL);
216   assert(image->signature == MagickCoreSignature);
217   assert(destination != (const PixelInfo *) NULL);
218   *destination=(*source);
219   if (image->colorspace == CMYKColorspace)
220     {
221       if (IssRGBCompatibleColorspace(destination->colorspace) != MagickFalse)
222         ConvertRGBToCMYK(destination);
223     }
224   else
225     if (destination->colorspace == CMYKColorspace)
226       {
227         if (IssRGBCompatibleColorspace(image->colorspace) != MagickFalse)
228           ConvertCMYKToRGB(destination);
229       }
230   if ((IsPixelInfoGray(&image->background_color) == MagickFalse) &&
231       (IsGrayColorspace(image->colorspace) != MagickFalse))
232     (void) TransformImageColorspace(image,sRGBColorspace,exception);
233   if ((destination->alpha_trait != UndefinedPixelTrait) &&
234       (image->alpha_trait == UndefinedPixelTrait))
235     (void) SetImageAlpha(image,OpaqueAlpha,exception);
236 }
237 
238 /*
239 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
240 %                                                                             %
241 %                                                                             %
242 %                                                                             %
243 %   D e c o d e P i x e l G a m m a                                           %
244 %                                                                             %
245 %                                                                             %
246 %                                                                             %
247 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
248 %
249 %  DecodePixelGamma() applies the expansive power-law nonlinearity to the pixel.
250 %
251 %  The format of the DecodePixelGamma method is:
252 %
253 %      double DecodePixelGamma(const MagickRealType pixel)
254 %
255 %  A description of each parameter follows:
256 %
257 %    o pixel: the pixel.
258 %
259 */
260 
DecodeGamma(const double x)261 static inline double DecodeGamma(const double x)
262 {
263   div_t
264     quotient;
265 
266   double
267     p,
268     term[9];
269 
270   int
271     exponent;
272 
273   static const double coefficient[] =  /* terms for x^(7/5), x=1.5 */
274   {
275     1.7917488588043277509,
276     0.82045614371976854984,
277     0.027694100686325412819,
278     -0.00094244335181762134018,
279     0.000064355540911469709545,
280     -5.7224404636060757485e-06,
281     5.8767669437311184313e-07,
282     -6.6139920053589721168e-08,
283     7.9323242696227458163e-09
284   };
285 
286   static const double powers_of_two[] =  /* (2^x)^(7/5) */
287   {
288     1.0,
289     2.6390158215457883983,
290     6.9644045063689921093,
291     1.8379173679952558018e+01,
292     4.8502930128332728543e+01
293   };
294 
295   /*
296     Compute x^2.4 == x*x^(7/5) == pow(x,2.4).
297   */
298   term[0]=1.0;
299   term[1]=4.0*frexp(x,&exponent)-3.0;
300   term[2]=2.0*term[1]*term[1]-term[0];
301   term[3]=2.0*term[1]*term[2]-term[1];
302   term[4]=2.0*term[1]*term[3]-term[2];
303   term[5]=2.0*term[1]*term[4]-term[3];
304   term[6]=2.0*term[1]*term[5]-term[4];
305   term[7]=2.0*term[1]*term[6]-term[5];
306   term[8]=2.0*term[1]*term[7]-term[6];
307   p=coefficient[0]*term[0]+coefficient[1]*term[1]+coefficient[2]*term[2]+
308     coefficient[3]*term[3]+coefficient[4]*term[4]+coefficient[5]*term[5]+
309     coefficient[6]*term[6]+coefficient[7]*term[7]+coefficient[8]*term[8];
310   quotient=div(exponent-1,5);
311   if (quotient.rem < 0)
312     {
313       quotient.quot-=1;
314       quotient.rem+=5;
315     }
316   return(x*ldexp(powers_of_two[quotient.rem]*p,7*quotient.quot));
317 }
318 
DecodePixelGamma(const MagickRealType pixel)319 MagickExport MagickRealType DecodePixelGamma(const MagickRealType pixel)
320 {
321   if (pixel <= (0.0404482362771076*QuantumRange))
322     return(pixel/12.92f);
323   return((MagickRealType) (QuantumRange*DecodeGamma((double) (QuantumScale*
324     pixel+0.055)/1.055)));
325 }
326 
327 /*
328 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
329 %                                                                             %
330 %                                                                             %
331 %                                                                             %
332 +   D e s t r o y P i x e l C h a n n e l M a p                               %
333 %                                                                             %
334 %                                                                             %
335 %                                                                             %
336 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
337 %
338 %  DestroyPixelChannelMap() deallocates memory associated with the pixel
339 %  channel map.
340 %
341 %  The format of the DestroyPixelChannelMap() method is:
342 %
343 %      PixelChannelMap *DestroyPixelChannelMap(PixelChannelMap *channel_map)
344 %
345 %  A description of each parameter follows:
346 %
347 %    o channel_map: the pixel component map.
348 %
349 */
DestroyPixelChannelMap(PixelChannelMap * channel_map)350 MagickExport PixelChannelMap *DestroyPixelChannelMap(
351   PixelChannelMap *channel_map)
352 {
353   assert(channel_map != (PixelChannelMap *) NULL);
354   channel_map=(PixelChannelMap *) RelinquishMagickMemory(channel_map);
355   return((PixelChannelMap *) RelinquishMagickMemory(channel_map));
356 }
357 
358 /*
359 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
360 %                                                                             %
361 %                                                                             %
362 %                                                                             %
363 +   E n c o d e P i x e l G a m m a                                           %
364 %                                                                             %
365 %                                                                             %
366 %                                                                             %
367 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
368 %
369 %  EncodePixelGamma() cancels any nonlinearity in the pixel.
370 %
371 %  The format of the EncodePixelGamma method is:
372 %
373 %      MagickRealType EncodePixelGamma(const double MagickRealType)
374 %
375 %  A description of each parameter follows:
376 %
377 %    o pixel: the pixel.
378 %
379 */
380 
EncodeGamma(const double x)381 static inline double EncodeGamma(const double x)
382 {
383   div_t
384     quotient;
385 
386   double
387     p,
388     term[9];
389 
390   int
391     exponent;
392 
393   static const double coefficient[] =  /* Chebychevi poly: x^(5/12), x=1.5 */
394   {
395     1.1758200232996901923,
396     0.16665763094889061230,
397     -0.0083154894939042125035,
398     0.00075187976780420279038,
399     -0.000083240178519391795367,
400     0.000010229209410070008679,
401     -1.3400466409860246e-06,
402     1.8333422241635376682e-07,
403     -2.5878596761348859722e-08
404   };
405 
406   static const double powers_of_two[] =  /* (2^N)^(5/12) */
407   {
408     1.0,
409     1.3348398541700343678,
410     1.7817974362806785482,
411     2.3784142300054420538,
412     3.1748021039363991669,
413     4.2378523774371812394,
414     5.6568542494923805819,
415     7.5509945014535482244,
416     1.0079368399158985525e1,
417     1.3454342644059433809e1,
418     1.7959392772949968275e1,
419     2.3972913230026907883e1
420   };
421 
422   /*
423     Compute x^(1/2.4) == x^(5/12) == pow(x,1.0/2.4).
424   */
425   term[0]=1.0;
426   term[1]=4.0*frexp(x,&exponent)-3.0;
427   term[2]=2.0*term[1]*term[1]-term[0];
428   term[3]=2.0*term[1]*term[2]-term[1];
429   term[4]=2.0*term[1]*term[3]-term[2];
430   term[5]=2.0*term[1]*term[4]-term[3];
431   term[6]=2.0*term[1]*term[5]-term[4];
432   term[7]=2.0*term[1]*term[6]-term[5];
433   term[8]=2.0*term[1]*term[7]-term[6];
434   p=coefficient[0]*term[0]+coefficient[1]*term[1]+coefficient[2]*term[2]+
435     coefficient[3]*term[3]+coefficient[4]*term[4]+coefficient[5]*term[5]+
436     coefficient[6]*term[6]+coefficient[7]*term[7]+coefficient[8]*term[8];
437   quotient=div(exponent-1,12);
438   if (quotient.rem < 0)
439     {
440       quotient.quot-=1;
441       quotient.rem+=12;
442     }
443   return(ldexp(powers_of_two[quotient.rem]*p,5*quotient.quot));
444 }
445 
EncodePixelGamma(const MagickRealType pixel)446 MagickExport MagickRealType EncodePixelGamma(const MagickRealType pixel)
447 {
448   if (pixel <= (0.0031306684425005883*QuantumRange))
449     return(12.92f*pixel);
450   return((MagickRealType) QuantumRange*(1.055*EncodeGamma((double) QuantumScale*
451     pixel)-0.055));
452 }
453 
454 /*
455 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
456 %                                                                             %
457 %                                                                             %
458 %                                                                             %
459 %   E x p o r t I m a g e P i x e l s                                         %
460 %                                                                             %
461 %                                                                             %
462 %                                                                             %
463 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
464 %
465 %  ExportImagePixels() extracts pixel data from an image and returns it to you.
466 %  The method returns MagickTrue on success otherwise MagickFalse if an error is
467 %  encountered.  The data is returned as char, short int, Quantum, unsigned int,
468 %  unsigned long long, float, or double in the order specified by map.
469 %
470 %  Suppose you want to extract the first scanline of a 640x480 image as
471 %  character data in red-green-blue order:
472 %
473 %      ExportImagePixels(image,0,0,640,1,"RGB",CharPixel,pixels,exception);
474 %
475 %  The format of the ExportImagePixels method is:
476 %
477 %      MagickBooleanType ExportImagePixels(const Image *image,const ssize_t x,
478 %        const ssize_t y,const size_t width,const size_t height,
479 %        const char *map,const StorageType type,void *pixels,
480 %        ExceptionInfo *exception)
481 %
482 %  A description of each parameter follows:
483 %
484 %    o image: the image.
485 %
486 %    o x,y,width,height:  These values define the perimeter
487 %      of a region of pixels you want to extract.
488 %
489 %    o map:  This string reflects the expected ordering of the pixel array.
490 %      It can be any combination or order of R = red, G = green, B = blue,
491 %      A = alpha (0 is transparent), O = opacity (0 is opaque), C = cyan,
492 %      Y = yellow, M = magenta, K = black, I = intensity (for grayscale),
493 %      P = pad.
494 %
495 %    o type: Define the data type of the pixels.  Float and double types are
496 %      normalized to [0..1] otherwise [0..QuantumRange].  Choose from these
497 %      types: CharPixel (char *), DoublePixel (double *), FloatPixel (float *),
498 %      LongPixel (unsigned int *), LongLongPixel (unsigned long long *),
499 %      QuantumPixel (Quantum *), or ShortPixel (unsigned short *).
500 %
501 %    o pixels: This array of values contain the pixel components as defined by
502 %      map and type.  You must preallocate this array where the expected
503 %      length varies depending on the values of width, height, map, and type.
504 %
505 %    o exception: return any errors or warnings in this structure.
506 %
507 */
508 
ExportCharPixel(const Image * image,const RectangleInfo * roi,const char * magick_restrict map,const QuantumType * quantum_map,void * pixels,ExceptionInfo * exception)509 static MagickBooleanType ExportCharPixel(const Image *image,
510   const RectangleInfo *roi,const char *magick_restrict map,
511   const QuantumType *quantum_map,void *pixels,ExceptionInfo *exception)
512 {
513   const Quantum
514     *magick_restrict p;
515 
516   ssize_t
517     x;
518 
519   unsigned char
520     *magick_restrict q;
521 
522   size_t
523     length;
524 
525   ssize_t
526     y;
527 
528   q=(unsigned char *) pixels;
529   if (LocaleCompare(map,"BGR") == 0)
530     {
531       for (y=0; y < (ssize_t) roi->height; y++)
532       {
533         p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
534         if (p == (const Quantum *) NULL)
535           break;
536         for (x=0; x < (ssize_t) roi->width; x++)
537         {
538           *q++=ScaleQuantumToChar(GetPixelBlue(image,p));
539           *q++=ScaleQuantumToChar(GetPixelGreen(image,p));
540           *q++=ScaleQuantumToChar(GetPixelRed(image,p));
541           p+=GetPixelChannels(image);
542         }
543       }
544       return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
545     }
546   if (LocaleCompare(map,"BGRA") == 0)
547     {
548       for (y=0; y < (ssize_t) roi->height; y++)
549       {
550         p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
551         if (p == (const Quantum *) NULL)
552           break;
553         for (x=0; x < (ssize_t) roi->width; x++)
554         {
555           *q++=ScaleQuantumToChar(GetPixelBlue(image,p));
556           *q++=ScaleQuantumToChar(GetPixelGreen(image,p));
557           *q++=ScaleQuantumToChar(GetPixelRed(image,p));
558           *q++=ScaleQuantumToChar(GetPixelAlpha(image,p));
559           p+=GetPixelChannels(image);
560         }
561       }
562       return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
563     }
564   if (LocaleCompare(map,"BGRP") == 0)
565     {
566       for (y=0; y < (ssize_t) roi->height; y++)
567       {
568         p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
569         if (p == (const Quantum *) NULL)
570           break;
571         for (x=0; x < (ssize_t) roi->width; x++)
572         {
573           *q++=ScaleQuantumToChar(GetPixelBlue(image,p));
574           *q++=ScaleQuantumToChar(GetPixelGreen(image,p));
575           *q++=ScaleQuantumToChar(GetPixelRed(image,p));
576           *q++=ScaleQuantumToChar((Quantum) 0);
577           p+=GetPixelChannels(image);
578         }
579       }
580       return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
581     }
582   if (LocaleCompare(map,"I") == 0)
583     {
584       for (y=0; y < (ssize_t) roi->height; y++)
585       {
586         p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
587         if (p == (const Quantum *) NULL)
588           break;
589         for (x=0; x < (ssize_t) roi->width; x++)
590         {
591           *q++=ScaleQuantumToChar(ClampToQuantum(GetPixelIntensity(image,p)));
592           p+=GetPixelChannels(image);
593         }
594       }
595       return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
596     }
597   if (LocaleCompare(map,"RGB") == 0)
598     {
599       for (y=0; y < (ssize_t) roi->height; y++)
600       {
601         p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
602         if (p == (const Quantum *) NULL)
603           break;
604         for (x=0; x < (ssize_t) roi->width; x++)
605         {
606           *q++=ScaleQuantumToChar(GetPixelRed(image,p));
607           *q++=ScaleQuantumToChar(GetPixelGreen(image,p));
608           *q++=ScaleQuantumToChar(GetPixelBlue(image,p));
609           p+=GetPixelChannels(image);
610         }
611       }
612       return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
613     }
614   if (LocaleCompare(map,"RGBA") == 0)
615     {
616       for (y=0; y < (ssize_t) roi->height; y++)
617       {
618         p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
619         if (p == (const Quantum *) NULL)
620           break;
621         for (x=0; x < (ssize_t) roi->width; x++)
622         {
623           *q++=ScaleQuantumToChar(GetPixelRed(image,p));
624           *q++=ScaleQuantumToChar(GetPixelGreen(image,p));
625           *q++=ScaleQuantumToChar(GetPixelBlue(image,p));
626           *q++=ScaleQuantumToChar(GetPixelAlpha(image,p));
627           p+=GetPixelChannels(image);
628         }
629       }
630       return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
631     }
632   if (LocaleCompare(map,"RGBP") == 0)
633     {
634       for (y=0; y < (ssize_t) roi->height; y++)
635       {
636         p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
637         if (p == (const Quantum *) NULL)
638           break;
639         for (x=0; x < (ssize_t) roi->width; x++)
640         {
641           *q++=ScaleQuantumToChar(GetPixelRed(image,p));
642           *q++=ScaleQuantumToChar(GetPixelGreen(image,p));
643           *q++=ScaleQuantumToChar(GetPixelBlue(image,p));
644           *q++=ScaleQuantumToChar((Quantum) 0);
645           p+=GetPixelChannels(image);
646         }
647       }
648       return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
649     }
650   length=strlen(map);
651   for (y=0; y < (ssize_t) roi->height; y++)
652   {
653     p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
654     if (p == (const Quantum *) NULL)
655       break;
656     for (x=0; x < (ssize_t) roi->width; x++)
657     {
658       ssize_t
659         i;
660 
661       for (i=0; i < (ssize_t) length; i++)
662       {
663         *q=0;
664         switch (quantum_map[i])
665         {
666           case RedQuantum:
667           case CyanQuantum:
668           {
669             *q=ScaleQuantumToChar(GetPixelRed(image,p));
670             break;
671           }
672           case GreenQuantum:
673           case MagentaQuantum:
674           {
675             *q=ScaleQuantumToChar(GetPixelGreen(image,p));
676             break;
677           }
678           case BlueQuantum:
679           case YellowQuantum:
680           {
681             *q=ScaleQuantumToChar(GetPixelBlue(image,p));
682             break;
683           }
684           case AlphaQuantum:
685           {
686             *q=ScaleQuantumToChar(GetPixelAlpha(image,p));
687             break;
688           }
689           case OpacityQuantum:
690           {
691             *q=ScaleQuantumToChar(GetPixelAlpha(image,p));
692             break;
693           }
694           case BlackQuantum:
695           {
696             if (image->colorspace == CMYKColorspace)
697               *q=ScaleQuantumToChar(GetPixelBlack(image,p));
698             break;
699           }
700           case IndexQuantum:
701           {
702             *q=ScaleQuantumToChar(ClampToQuantum(GetPixelIntensity(image,p)));
703             break;
704           }
705           default:
706             break;
707         }
708         q++;
709       }
710       p+=GetPixelChannels(image);
711     }
712   }
713   return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
714 }
715 
ExportDoublePixel(const Image * image,const RectangleInfo * roi,const char * magick_restrict map,const QuantumType * quantum_map,void * pixels,ExceptionInfo * exception)716 static MagickBooleanType ExportDoublePixel(const Image *image,
717   const RectangleInfo *roi,const char *magick_restrict map,
718   const QuantumType *quantum_map,void *pixels,ExceptionInfo *exception)
719 {
720   const Quantum
721     *magick_restrict p;
722 
723   double
724     *magick_restrict q;
725 
726   ssize_t
727     x;
728 
729   size_t
730     length;
731 
732   ssize_t
733     y;
734 
735   q=(double *) pixels;
736   if (LocaleCompare(map,"BGR") == 0)
737     {
738       for (y=0; y < (ssize_t) roi->height; y++)
739       {
740         p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
741         if (p == (const Quantum *) NULL)
742           break;
743         for (x=0; x < (ssize_t) roi->width; x++)
744         {
745           *q++=(double) (QuantumScale*GetPixelBlue(image,p));
746           *q++=(double) (QuantumScale*GetPixelGreen(image,p));
747           *q++=(double) (QuantumScale*GetPixelRed(image,p));
748           p+=GetPixelChannels(image);
749         }
750       }
751       return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
752     }
753   if (LocaleCompare(map,"BGRA") == 0)
754     {
755       for (y=0; y < (ssize_t) roi->height; y++)
756       {
757         p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
758         if (p == (const Quantum *) NULL)
759           break;
760         for (x=0; x < (ssize_t) roi->width; x++)
761         {
762           *q++=(double) (QuantumScale*GetPixelBlue(image,p));
763           *q++=(double) (QuantumScale*GetPixelGreen(image,p));
764           *q++=(double) (QuantumScale*GetPixelRed(image,p));
765           *q++=(double) (QuantumScale*GetPixelAlpha(image,p));
766           p+=GetPixelChannels(image);
767         }
768       }
769       return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
770     }
771   if (LocaleCompare(map,"BGRP") == 0)
772     {
773       for (y=0; y < (ssize_t) roi->height; y++)
774       {
775         p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
776         if (p == (const Quantum *) NULL)
777           break;
778         for (x=0; x < (ssize_t) roi->width; x++)
779         {
780           *q++=(double) (QuantumScale*GetPixelBlue(image,p));
781           *q++=(double) (QuantumScale*GetPixelGreen(image,p));
782           *q++=(double) (QuantumScale*GetPixelRed(image,p));
783           *q++=0.0;
784           p+=GetPixelChannels(image);
785         }
786       }
787       return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
788     }
789   if (LocaleCompare(map,"I") == 0)
790     {
791       for (y=0; y < (ssize_t) roi->height; y++)
792       {
793         p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
794         if (p == (const Quantum *) NULL)
795           break;
796         for (x=0; x < (ssize_t) roi->width; x++)
797         {
798           *q++=(double) (QuantumScale*GetPixelIntensity(image,p));
799           p+=GetPixelChannels(image);
800         }
801       }
802       return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
803     }
804   if (LocaleCompare(map,"RGB") == 0)
805     {
806       for (y=0; y < (ssize_t) roi->height; y++)
807       {
808         p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
809         if (p == (const Quantum *) NULL)
810           break;
811         for (x=0; x < (ssize_t) roi->width; x++)
812         {
813           *q++=(double) (QuantumScale*GetPixelRed(image,p));
814           *q++=(double) (QuantumScale*GetPixelGreen(image,p));
815           *q++=(double) (QuantumScale*GetPixelBlue(image,p));
816           p+=GetPixelChannels(image);
817         }
818       }
819       return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
820     }
821   if (LocaleCompare(map,"RGBA") == 0)
822     {
823       for (y=0; y < (ssize_t) roi->height; y++)
824       {
825         p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
826         if (p == (const Quantum *) NULL)
827           break;
828         for (x=0; x < (ssize_t) roi->width; x++)
829         {
830           *q++=(double) (QuantumScale*GetPixelRed(image,p));
831           *q++=(double) (QuantumScale*GetPixelGreen(image,p));
832           *q++=(double) (QuantumScale*GetPixelBlue(image,p));
833           *q++=(double) (QuantumScale*GetPixelAlpha(image,p));
834           p+=GetPixelChannels(image);
835         }
836       }
837       return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
838     }
839   if (LocaleCompare(map,"RGBP") == 0)
840     {
841       for (y=0; y < (ssize_t) roi->height; y++)
842       {
843         p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
844         if (p == (const Quantum *) NULL)
845           break;
846         for (x=0; x < (ssize_t) roi->width; x++)
847         {
848           *q++=(double) (QuantumScale*GetPixelRed(image,p));
849           *q++=(double) (QuantumScale*GetPixelGreen(image,p));
850           *q++=(double) (QuantumScale*GetPixelBlue(image,p));
851           *q++=0.0;
852           p+=GetPixelChannels(image);
853         }
854       }
855       return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
856     }
857   length=strlen(map);
858   for (y=0; y < (ssize_t) roi->height; y++)
859   {
860     p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
861     if (p == (const Quantum *) NULL)
862       break;
863     for (x=0; x < (ssize_t) roi->width; x++)
864     {
865       ssize_t
866         i;
867 
868       for (i=0; i < (ssize_t) length; i++)
869       {
870         *q=0;
871         switch (quantum_map[i])
872         {
873           case RedQuantum:
874           case CyanQuantum:
875           {
876             *q=(double) (QuantumScale*GetPixelRed(image,p));
877             break;
878           }
879           case GreenQuantum:
880           case MagentaQuantum:
881           {
882             *q=(double) (QuantumScale*GetPixelGreen(image,p));
883             break;
884           }
885           case BlueQuantum:
886           case YellowQuantum:
887           {
888             *q=(double) (QuantumScale*GetPixelBlue(image,p));
889             break;
890           }
891           case AlphaQuantum:
892           {
893             *q=(double) (QuantumScale*GetPixelAlpha(image,p));
894             break;
895           }
896           case OpacityQuantum:
897           {
898             *q=(double) (QuantumScale*GetPixelAlpha(image,p));
899             break;
900           }
901           case BlackQuantum:
902           {
903             if (image->colorspace == CMYKColorspace)
904               *q=(double) (QuantumScale*
905                 GetPixelBlack(image,p));
906             break;
907           }
908           case IndexQuantum:
909           {
910             *q=(double) (QuantumScale*GetPixelIntensity(image,p));
911             break;
912           }
913           default:
914             *q=0;
915         }
916         q++;
917       }
918       p+=GetPixelChannels(image);
919     }
920   }
921   return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
922 }
923 
ExportFloatPixel(const Image * image,const RectangleInfo * roi,const char * magick_restrict map,const QuantumType * quantum_map,void * pixels,ExceptionInfo * exception)924 static MagickBooleanType ExportFloatPixel(const Image *image,
925   const RectangleInfo *roi,const char *magick_restrict map,
926   const QuantumType *quantum_map,void *pixels,ExceptionInfo *exception)
927 {
928   const Quantum
929     *magick_restrict p;
930 
931   float
932     *magick_restrict q;
933 
934   ssize_t
935     x;
936 
937   size_t
938     length;
939 
940   ssize_t
941     y;
942 
943   q=(float *) pixels;
944   if (LocaleCompare(map,"BGR") == 0)
945     {
946       for (y=0; y < (ssize_t) roi->height; y++)
947       {
948         p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
949         if (p == (const Quantum *) NULL)
950           break;
951         for (x=0; x < (ssize_t) roi->width; x++)
952         {
953           *q++=(float) (QuantumScale*GetPixelBlue(image,p));
954           *q++=(float) (QuantumScale*GetPixelGreen(image,p));
955           *q++=(float) (QuantumScale*GetPixelRed(image,p));
956           p+=GetPixelChannels(image);
957         }
958       }
959       return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
960     }
961   if (LocaleCompare(map,"BGRA") == 0)
962     {
963       for (y=0; y < (ssize_t) roi->height; y++)
964       {
965         p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
966         if (p == (const Quantum *) NULL)
967           break;
968         for (x=0; x < (ssize_t) roi->width; x++)
969         {
970           *q++=(float) (QuantumScale*GetPixelBlue(image,p));
971           *q++=(float) (QuantumScale*GetPixelGreen(image,p));
972           *q++=(float) (QuantumScale*GetPixelRed(image,p));
973           *q++=(float) (QuantumScale*GetPixelAlpha(image,p));
974           p+=GetPixelChannels(image);
975         }
976       }
977       return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
978     }
979   if (LocaleCompare(map,"BGRP") == 0)
980     {
981       for (y=0; y < (ssize_t) roi->height; y++)
982       {
983         p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
984         if (p == (const Quantum *) NULL)
985           break;
986         for (x=0; x < (ssize_t) roi->width; x++)
987         {
988           *q++=(float) (QuantumScale*GetPixelBlue(image,p));
989           *q++=(float) (QuantumScale*GetPixelGreen(image,p));
990           *q++=(float) (QuantumScale*GetPixelRed(image,p));
991           *q++=0.0;
992           p+=GetPixelChannels(image);
993         }
994       }
995       return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
996     }
997   if (LocaleCompare(map,"I") == 0)
998     {
999       for (y=0; y < (ssize_t) roi->height; y++)
1000       {
1001         p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
1002         if (p == (const Quantum *) NULL)
1003           break;
1004         for (x=0; x < (ssize_t) roi->width; x++)
1005         {
1006           *q++=(float) (QuantumScale*GetPixelIntensity(image,p));
1007           p+=GetPixelChannels(image);
1008         }
1009       }
1010       return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
1011     }
1012   if (LocaleCompare(map,"RGB") == 0)
1013     {
1014       for (y=0; y < (ssize_t) roi->height; y++)
1015       {
1016         p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
1017         if (p == (const Quantum *) NULL)
1018           break;
1019         for (x=0; x < (ssize_t) roi->width; x++)
1020         {
1021           *q++=(float) (QuantumScale*GetPixelRed(image,p));
1022           *q++=(float) (QuantumScale*GetPixelGreen(image,p));
1023           *q++=(float) (QuantumScale*GetPixelBlue(image,p));
1024           p+=GetPixelChannels(image);
1025         }
1026       }
1027       return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
1028     }
1029   if (LocaleCompare(map,"RGBA") == 0)
1030     {
1031       for (y=0; y < (ssize_t) roi->height; y++)
1032       {
1033         p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
1034         if (p == (const Quantum *) NULL)
1035           break;
1036         for (x=0; x < (ssize_t) roi->width; x++)
1037         {
1038           *q++=(float) (QuantumScale*GetPixelRed(image,p));
1039           *q++=(float) (QuantumScale*GetPixelGreen(image,p));
1040           *q++=(float) (QuantumScale*GetPixelBlue(image,p));
1041           *q++=(float) (QuantumScale*GetPixelAlpha(image,p));
1042           p+=GetPixelChannels(image);
1043         }
1044       }
1045       return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
1046     }
1047   if (LocaleCompare(map,"RGBP") == 0)
1048     {
1049       for (y=0; y < (ssize_t) roi->height; y++)
1050       {
1051         p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
1052         if (p == (const Quantum *) NULL)
1053           break;
1054         for (x=0; x < (ssize_t) roi->width; x++)
1055         {
1056           *q++=(float) (QuantumScale*GetPixelRed(image,p));
1057           *q++=(float) (QuantumScale*GetPixelGreen(image,p));
1058           *q++=(float) (QuantumScale*GetPixelBlue(image,p));
1059           *q++=0.0;
1060           p+=GetPixelChannels(image);
1061         }
1062       }
1063       return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
1064     }
1065   length=strlen(map);
1066   for (y=0; y < (ssize_t) roi->height; y++)
1067   {
1068     p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
1069     if (p == (const Quantum *) NULL)
1070       break;
1071     for (x=0; x < (ssize_t) roi->width; x++)
1072     {
1073       ssize_t
1074         i;
1075 
1076       for (i=0; i < (ssize_t) length; i++)
1077       {
1078         *q=0;
1079         switch (quantum_map[i])
1080         {
1081           case RedQuantum:
1082           case CyanQuantum:
1083           {
1084             *q=(float) (QuantumScale*GetPixelRed(image,p));
1085             break;
1086           }
1087           case GreenQuantum:
1088           case MagentaQuantum:
1089           {
1090             *q=(float) (QuantumScale*GetPixelGreen(image,p));
1091             break;
1092           }
1093           case BlueQuantum:
1094           case YellowQuantum:
1095           {
1096             *q=(float) (QuantumScale*GetPixelBlue(image,p));
1097             break;
1098           }
1099           case AlphaQuantum:
1100           {
1101             *q=(float) (QuantumScale*((Quantum) (GetPixelAlpha(image,p))));
1102             break;
1103           }
1104           case OpacityQuantum:
1105           {
1106             *q=(float) (QuantumScale*GetPixelAlpha(image,p));
1107             break;
1108           }
1109           case BlackQuantum:
1110           {
1111             if (image->colorspace == CMYKColorspace)
1112               *q=(float) (QuantumScale* GetPixelBlack(image,p));
1113             break;
1114           }
1115           case IndexQuantum:
1116           {
1117             *q=(float) (QuantumScale*GetPixelIntensity(image,p));
1118             break;
1119           }
1120           default:
1121             *q=0;
1122         }
1123         q++;
1124       }
1125       p+=GetPixelChannels(image);
1126     }
1127   }
1128   return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
1129 }
1130 
ExportLongPixel(const Image * image,const RectangleInfo * roi,const char * magick_restrict map,const QuantumType * quantum_map,void * pixels,ExceptionInfo * exception)1131 static MagickBooleanType ExportLongPixel(const Image *image,
1132   const RectangleInfo *roi,const char *magick_restrict map,
1133   const QuantumType *quantum_map,void *pixels,ExceptionInfo *exception)
1134 {
1135   const Quantum
1136     *magick_restrict p;
1137 
1138   ssize_t
1139     x;
1140 
1141   unsigned int
1142     *magick_restrict q;
1143 
1144   size_t
1145     length;
1146 
1147   ssize_t
1148     y;
1149 
1150   q=(unsigned int *) pixels;
1151   if (LocaleCompare(map,"BGR") == 0)
1152     {
1153       for (y=0; y < (ssize_t) roi->height; y++)
1154       {
1155         p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
1156         if (p == (const Quantum *) NULL)
1157           break;
1158         for (x=0; x < (ssize_t) roi->width; x++)
1159         {
1160           *q++=ScaleQuantumToLong(GetPixelBlue(image,p));
1161           *q++=ScaleQuantumToLong(GetPixelGreen(image,p));
1162           *q++=ScaleQuantumToLong(GetPixelRed(image,p));
1163           p+=GetPixelChannels(image);
1164         }
1165       }
1166       return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
1167     }
1168   if (LocaleCompare(map,"BGRA") == 0)
1169     {
1170       for (y=0; y < (ssize_t) roi->height; y++)
1171       {
1172         p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
1173         if (p == (const Quantum *) NULL)
1174           break;
1175         for (x=0; x < (ssize_t) roi->width; x++)
1176         {
1177           *q++=ScaleQuantumToLong(GetPixelBlue(image,p));
1178           *q++=ScaleQuantumToLong(GetPixelGreen(image,p));
1179           *q++=ScaleQuantumToLong(GetPixelRed(image,p));
1180           *q++=ScaleQuantumToLong(GetPixelAlpha(image,p));
1181           p+=GetPixelChannels(image);
1182         }
1183       }
1184       return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
1185     }
1186   if (LocaleCompare(map,"BGRP") == 0)
1187     {
1188       for (y=0; y < (ssize_t) roi->height; y++)
1189       {
1190         p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
1191         if (p == (const Quantum *) NULL)
1192           break;
1193         for (x=0; x < (ssize_t) roi->width; x++)
1194         {
1195           *q++=ScaleQuantumToLong(GetPixelBlue(image,p));
1196           *q++=ScaleQuantumToLong(GetPixelGreen(image,p));
1197           *q++=ScaleQuantumToLong(GetPixelRed(image,p));
1198           *q++=0;
1199           p+=GetPixelChannels(image);
1200         }
1201       }
1202       return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
1203     }
1204   if (LocaleCompare(map,"I") == 0)
1205     {
1206       for (y=0; y < (ssize_t) roi->height; y++)
1207       {
1208         p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
1209         if (p == (const Quantum *) NULL)
1210           break;
1211         for (x=0; x < (ssize_t) roi->width; x++)
1212         {
1213           *q++=ScaleQuantumToLong(ClampToQuantum(GetPixelIntensity(image,p)));
1214           p+=GetPixelChannels(image);
1215         }
1216       }
1217       return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
1218     }
1219   if (LocaleCompare(map,"RGB") == 0)
1220     {
1221       for (y=0; y < (ssize_t) roi->height; y++)
1222       {
1223         p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
1224         if (p == (const Quantum *) NULL)
1225           break;
1226         for (x=0; x < (ssize_t) roi->width; x++)
1227         {
1228           *q++=ScaleQuantumToLong(GetPixelRed(image,p));
1229           *q++=ScaleQuantumToLong(GetPixelGreen(image,p));
1230           *q++=ScaleQuantumToLong(GetPixelBlue(image,p));
1231           p+=GetPixelChannels(image);
1232         }
1233       }
1234       return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
1235     }
1236   if (LocaleCompare(map,"RGBA") == 0)
1237     {
1238       for (y=0; y < (ssize_t) roi->height; y++)
1239       {
1240         p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
1241         if (p == (const Quantum *) NULL)
1242           break;
1243         for (x=0; x < (ssize_t) roi->width; x++)
1244         {
1245           *q++=ScaleQuantumToLong(GetPixelRed(image,p));
1246           *q++=ScaleQuantumToLong(GetPixelGreen(image,p));
1247           *q++=ScaleQuantumToLong(GetPixelBlue(image,p));
1248           *q++=ScaleQuantumToLong(GetPixelAlpha(image,p));
1249           p+=GetPixelChannels(image);
1250         }
1251       }
1252       return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
1253     }
1254   if (LocaleCompare(map,"RGBP") == 0)
1255     {
1256       for (y=0; y < (ssize_t) roi->height; y++)
1257       {
1258         p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
1259         if (p == (const Quantum *) NULL)
1260           break;
1261         for (x=0; x < (ssize_t) roi->width; x++)
1262         {
1263           *q++=ScaleQuantumToLong(GetPixelRed(image,p));
1264           *q++=ScaleQuantumToLong(GetPixelGreen(image,p));
1265           *q++=ScaleQuantumToLong(GetPixelBlue(image,p));
1266           *q++=0;
1267           p+=GetPixelChannels(image);
1268         }
1269       }
1270       return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
1271     }
1272   length=strlen(map);
1273   for (y=0; y < (ssize_t) roi->height; y++)
1274   {
1275     p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
1276     if (p == (const Quantum *) NULL)
1277       break;
1278     for (x=0; x < (ssize_t) roi->width; x++)
1279     {
1280       ssize_t
1281         i;
1282 
1283       for (i=0; i < (ssize_t) length; i++)
1284       {
1285         *q=0;
1286         switch (quantum_map[i])
1287         {
1288           case RedQuantum:
1289           case CyanQuantum:
1290           {
1291             *q=ScaleQuantumToLong(GetPixelRed(image,p));
1292             break;
1293           }
1294           case GreenQuantum:
1295           case MagentaQuantum:
1296           {
1297             *q=ScaleQuantumToLong(GetPixelGreen(image,p));
1298             break;
1299           }
1300           case BlueQuantum:
1301           case YellowQuantum:
1302           {
1303             *q=ScaleQuantumToLong(GetPixelBlue(image,p));
1304             break;
1305           }
1306           case AlphaQuantum:
1307           {
1308             *q=ScaleQuantumToLong(GetPixelAlpha(image,p));
1309             break;
1310           }
1311           case OpacityQuantum:
1312           {
1313             *q=ScaleQuantumToLong(GetPixelAlpha(image,p));
1314             break;
1315           }
1316           case BlackQuantum:
1317           {
1318             if (image->colorspace == CMYKColorspace)
1319               *q=ScaleQuantumToLong(GetPixelBlack(image,p));
1320             break;
1321           }
1322           case IndexQuantum:
1323           {
1324             *q=ScaleQuantumToLong(ClampToQuantum(GetPixelIntensity(image,p)));
1325             break;
1326           }
1327           default:
1328             break;
1329         }
1330         q++;
1331       }
1332       p+=GetPixelChannels(image);
1333     }
1334   }
1335   return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
1336 }
1337 
ExportLongLongPixel(const Image * image,const RectangleInfo * roi,const char * magick_restrict map,const QuantumType * quantum_map,void * pixels,ExceptionInfo * exception)1338 static MagickBooleanType ExportLongLongPixel(const Image *image,
1339   const RectangleInfo *roi,const char *magick_restrict map,
1340   const QuantumType *quantum_map,void *pixels,ExceptionInfo *exception)
1341 {
1342   const Quantum
1343     *magick_restrict p;
1344 
1345   ssize_t
1346     x;
1347 
1348   MagickSizeType
1349     *magick_restrict q;
1350 
1351   size_t
1352     length;
1353 
1354   ssize_t
1355     y;
1356 
1357   q=(MagickSizeType *) pixels;
1358   if (LocaleCompare(map,"BGR") == 0)
1359     {
1360       for (y=0; y < (ssize_t) roi->height; y++)
1361       {
1362         p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
1363         if (p == (const Quantum *) NULL)
1364           break;
1365         for (x=0; x < (ssize_t) roi->width; x++)
1366         {
1367           *q++=ScaleQuantumToLongLong(GetPixelBlue(image,p));
1368           *q++=ScaleQuantumToLongLong(GetPixelGreen(image,p));
1369           *q++=ScaleQuantumToLongLong(GetPixelRed(image,p));
1370           p+=GetPixelChannels(image);
1371         }
1372       }
1373       return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
1374     }
1375   if (LocaleCompare(map,"BGRA") == 0)
1376     {
1377       for (y=0; y < (ssize_t) roi->height; y++)
1378       {
1379         p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
1380         if (p == (const Quantum *) NULL)
1381           break;
1382         for (x=0; x < (ssize_t) roi->width; x++)
1383         {
1384           *q++=ScaleQuantumToLongLong(GetPixelBlue(image,p));
1385           *q++=ScaleQuantumToLongLong(GetPixelGreen(image,p));
1386           *q++=ScaleQuantumToLongLong(GetPixelRed(image,p));
1387           *q++=ScaleQuantumToLongLong(GetPixelAlpha(image,p));
1388           p+=GetPixelChannels(image);
1389         }
1390       }
1391       return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
1392     }
1393   if (LocaleCompare(map,"BGRP") == 0)
1394     {
1395       for (y=0; y < (ssize_t) roi->height; y++)
1396       {
1397         p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
1398         if (p == (const Quantum *) NULL)
1399           break;
1400         for (x=0; x < (ssize_t) roi->width; x++)
1401         {
1402           *q++=ScaleQuantumToLongLong(GetPixelBlue(image,p));
1403           *q++=ScaleQuantumToLongLong(GetPixelGreen(image,p));
1404           *q++=ScaleQuantumToLongLong(GetPixelRed(image,p));
1405           *q++=0;
1406           p+=GetPixelChannels(image);
1407         }
1408       }
1409       return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
1410     }
1411   if (LocaleCompare(map,"I") == 0)
1412     {
1413       for (y=0; y < (ssize_t) roi->height; y++)
1414       {
1415         p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
1416         if (p == (const Quantum *) NULL)
1417           break;
1418         for (x=0; x < (ssize_t) roi->width; x++)
1419         {
1420           *q++=ScaleQuantumToLongLong(ClampToQuantum(
1421             GetPixelIntensity(image,p)));
1422           p+=GetPixelChannels(image);
1423         }
1424       }
1425       return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
1426     }
1427   if (LocaleCompare(map,"RGB") == 0)
1428     {
1429       for (y=0; y < (ssize_t) roi->height; y++)
1430       {
1431         p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
1432         if (p == (const Quantum *) NULL)
1433           break;
1434         for (x=0; x < (ssize_t) roi->width; x++)
1435         {
1436           *q++=ScaleQuantumToLongLong(GetPixelRed(image,p));
1437           *q++=ScaleQuantumToLongLong(GetPixelGreen(image,p));
1438           *q++=ScaleQuantumToLongLong(GetPixelBlue(image,p));
1439           p+=GetPixelChannels(image);
1440         }
1441       }
1442       return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
1443     }
1444   if (LocaleCompare(map,"RGBA") == 0)
1445     {
1446       for (y=0; y < (ssize_t) roi->height; y++)
1447       {
1448         p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
1449         if (p == (const Quantum *) NULL)
1450           break;
1451         for (x=0; x < (ssize_t) roi->width; x++)
1452         {
1453           *q++=ScaleQuantumToLongLong(GetPixelRed(image,p));
1454           *q++=ScaleQuantumToLongLong(GetPixelGreen(image,p));
1455           *q++=ScaleQuantumToLongLong(GetPixelBlue(image,p));
1456           *q++=ScaleQuantumToLongLong(GetPixelAlpha(image,p));
1457           p+=GetPixelChannels(image);
1458         }
1459       }
1460       return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
1461     }
1462   if (LocaleCompare(map,"RGBP") == 0)
1463     {
1464       for (y=0; y < (ssize_t) roi->height; y++)
1465       {
1466         p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
1467         if (p == (const Quantum *) NULL)
1468           break;
1469         for (x=0; x < (ssize_t) roi->width; x++)
1470         {
1471           *q++=ScaleQuantumToLongLong(GetPixelRed(image,p));
1472           *q++=ScaleQuantumToLongLong(GetPixelGreen(image,p));
1473           *q++=ScaleQuantumToLongLong(GetPixelBlue(image,p));
1474           *q++=0;
1475           p+=GetPixelChannels(image);
1476         }
1477       }
1478       return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
1479     }
1480   length=strlen(map);
1481   for (y=0; y < (ssize_t) roi->height; y++)
1482   {
1483     p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
1484     if (p == (const Quantum *) NULL)
1485       break;
1486     for (x=0; x < (ssize_t) roi->width; x++)
1487     {
1488       ssize_t
1489         i;
1490 
1491       for (i=0; i < (ssize_t) length; i++)
1492       {
1493         *q=0;
1494         switch (quantum_map[i])
1495         {
1496           case RedQuantum:
1497           case CyanQuantum:
1498           {
1499             *q=ScaleQuantumToLongLong(GetPixelRed(image,p));
1500             break;
1501           }
1502           case GreenQuantum:
1503           case MagentaQuantum:
1504           {
1505             *q=ScaleQuantumToLongLong(GetPixelGreen(image,p));
1506             break;
1507           }
1508           case BlueQuantum:
1509           case YellowQuantum:
1510           {
1511             *q=ScaleQuantumToLongLong(GetPixelBlue(image,p));
1512             break;
1513           }
1514           case AlphaQuantum:
1515           {
1516             *q=ScaleQuantumToLongLong(GetPixelAlpha(image,p));
1517             break;
1518           }
1519           case OpacityQuantum:
1520           {
1521             *q=ScaleQuantumToLongLong(GetPixelAlpha(image,p));
1522             break;
1523           }
1524           case BlackQuantum:
1525           {
1526             if (image->colorspace == CMYKColorspace)
1527               *q=ScaleQuantumToLongLong(GetPixelBlack(image,p));
1528             break;
1529           }
1530           case IndexQuantum:
1531           {
1532             *q=ScaleQuantumToLongLong(ClampToQuantum(
1533               GetPixelIntensity(image,p)));
1534             break;
1535           }
1536           default:
1537             break;
1538         }
1539         q++;
1540       }
1541       p+=GetPixelChannels(image);
1542     }
1543   }
1544   return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
1545 }
1546 
ExportQuantumPixel(const Image * image,const RectangleInfo * roi,const char * magick_restrict map,const QuantumType * quantum_map,void * pixels,ExceptionInfo * exception)1547 static MagickBooleanType ExportQuantumPixel(const Image *image,
1548   const RectangleInfo *roi,const char *magick_restrict map,
1549   const QuantumType *quantum_map,void *pixels,ExceptionInfo *exception)
1550 {
1551   const Quantum
1552     *magick_restrict p;
1553 
1554   Quantum
1555     *magick_restrict q;
1556 
1557   ssize_t
1558     x;
1559 
1560   size_t
1561     length;
1562 
1563   ssize_t
1564     y;
1565 
1566   q=(Quantum *) pixels;
1567   if (LocaleCompare(map,"BGR") == 0)
1568     {
1569       for (y=0; y < (ssize_t) roi->height; y++)
1570       {
1571         p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
1572         if (p == (const Quantum *) NULL)
1573           break;
1574         for (x=0; x < (ssize_t) roi->width; x++)
1575         {
1576           *q++=GetPixelBlue(image,p);
1577           *q++=GetPixelGreen(image,p);
1578           *q++=GetPixelRed(image,p);
1579           p+=GetPixelChannels(image);
1580         }
1581       }
1582       return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
1583     }
1584   if (LocaleCompare(map,"BGRA") == 0)
1585     {
1586       for (y=0; y < (ssize_t) roi->height; y++)
1587       {
1588         p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
1589         if (p == (const Quantum *) NULL)
1590           break;
1591         for (x=0; x < (ssize_t) roi->width; x++)
1592         {
1593           *q++=GetPixelBlue(image,p);
1594           *q++=GetPixelGreen(image,p);
1595           *q++=GetPixelRed(image,p);
1596           *q++=(Quantum) (GetPixelAlpha(image,p));
1597           p+=GetPixelChannels(image);
1598         }
1599       }
1600       return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
1601     }
1602   if (LocaleCompare(map,"BGRP") == 0)
1603     {
1604       for (y=0; y < (ssize_t) roi->height; y++)
1605       {
1606         p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
1607         if (p == (const Quantum *) NULL)
1608           break;
1609         for (x=0; x < (ssize_t) roi->width; x++)
1610         {
1611           *q++=GetPixelBlue(image,p);
1612           *q++=GetPixelGreen(image,p);
1613           *q++=GetPixelRed(image,p);
1614           *q++=(Quantum) 0;
1615           p+=GetPixelChannels(image);
1616         }
1617       }
1618       return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
1619     }
1620   if (LocaleCompare(map,"I") == 0)
1621     {
1622       for (y=0; y < (ssize_t) roi->height; y++)
1623       {
1624         p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
1625         if (p == (const Quantum *) NULL)
1626           break;
1627         for (x=0; x < (ssize_t) roi->width; x++)
1628         {
1629           *q++=ClampToQuantum(GetPixelIntensity(image,p));
1630           p+=GetPixelChannels(image);
1631         }
1632       }
1633       return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
1634     }
1635   if (LocaleCompare(map,"RGB") == 0)
1636     {
1637       for (y=0; y < (ssize_t) roi->height; y++)
1638       {
1639         p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
1640         if (p == (const Quantum *) NULL)
1641           break;
1642         for (x=0; x < (ssize_t) roi->width; x++)
1643         {
1644           *q++=GetPixelRed(image,p);
1645           *q++=GetPixelGreen(image,p);
1646           *q++=GetPixelBlue(image,p);
1647           p+=GetPixelChannels(image);
1648         }
1649       }
1650       return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
1651     }
1652   if (LocaleCompare(map,"RGBA") == 0)
1653     {
1654       for (y=0; y < (ssize_t) roi->height; y++)
1655       {
1656         p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
1657         if (p == (const Quantum *) NULL)
1658           break;
1659         for (x=0; x < (ssize_t) roi->width; x++)
1660         {
1661           *q++=GetPixelRed(image,p);
1662           *q++=GetPixelGreen(image,p);
1663           *q++=GetPixelBlue(image,p);
1664           *q++=(Quantum) (GetPixelAlpha(image,p));
1665           p+=GetPixelChannels(image);
1666         }
1667       }
1668       return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
1669     }
1670   if (LocaleCompare(map,"RGBP") == 0)
1671     {
1672       for (y=0; y < (ssize_t) roi->height; y++)
1673       {
1674         p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
1675         if (p == (const Quantum *) NULL)
1676           break;
1677         for (x=0; x < (ssize_t) roi->width; x++)
1678         {
1679           *q++=GetPixelRed(image,p);
1680           *q++=GetPixelGreen(image,p);
1681           *q++=GetPixelBlue(image,p);
1682           *q++=(Quantum) 0;
1683           p+=GetPixelChannels(image);
1684         }
1685       }
1686       return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
1687     }
1688   length=strlen(map);
1689   for (y=0; y < (ssize_t) roi->height; y++)
1690   {
1691     p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
1692     if (p == (const Quantum *) NULL)
1693       break;
1694     for (x=0; x < (ssize_t) roi->width; x++)
1695     {
1696       ssize_t
1697         i;
1698 
1699       for (i=0; i < (ssize_t) length; i++)
1700       {
1701         *q=(Quantum) 0;
1702         switch (quantum_map[i])
1703         {
1704           case RedQuantum:
1705           case CyanQuantum:
1706           {
1707             *q=GetPixelRed(image,p);
1708             break;
1709           }
1710           case GreenQuantum:
1711           case MagentaQuantum:
1712           {
1713             *q=GetPixelGreen(image,p);
1714             break;
1715           }
1716           case BlueQuantum:
1717           case YellowQuantum:
1718           {
1719             *q=GetPixelBlue(image,p);
1720             break;
1721           }
1722           case AlphaQuantum:
1723           {
1724             *q=GetPixelAlpha(image,p);
1725             break;
1726           }
1727           case OpacityQuantum:
1728           {
1729             *q=GetPixelAlpha(image,p);
1730             break;
1731           }
1732           case BlackQuantum:
1733           {
1734             if (image->colorspace == CMYKColorspace)
1735               *q=GetPixelBlack(image,p);
1736             break;
1737           }
1738           case IndexQuantum:
1739           {
1740             *q=ClampToQuantum(GetPixelIntensity(image,p));
1741             break;
1742           }
1743           default:
1744           {
1745             *q=(Quantum) 0;
1746             break;
1747           }
1748         }
1749         q++;
1750       }
1751       p+=GetPixelChannels(image);
1752     }
1753   }
1754   return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
1755 }
1756 
ExportShortPixel(const Image * image,const RectangleInfo * roi,const char * magick_restrict map,const QuantumType * quantum_map,void * pixels,ExceptionInfo * exception)1757 static MagickBooleanType ExportShortPixel(const Image *image,
1758   const RectangleInfo *roi,const char *magick_restrict map,
1759   const QuantumType *quantum_map,void *pixels,ExceptionInfo *exception)
1760 {
1761   const Quantum
1762     *magick_restrict p;
1763 
1764   ssize_t
1765     x;
1766 
1767   unsigned short
1768     *magick_restrict q;
1769 
1770   size_t
1771     length;
1772 
1773   ssize_t
1774     y;
1775 
1776   q=(unsigned short *) pixels;
1777   if (LocaleCompare(map,"BGR") == 0)
1778     {
1779       for (y=0; y < (ssize_t) roi->height; y++)
1780       {
1781         p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
1782         if (p == (const Quantum *) NULL)
1783           break;
1784         for (x=0; x < (ssize_t) roi->width; x++)
1785         {
1786           *q++=ScaleQuantumToShort(GetPixelBlue(image,p));
1787           *q++=ScaleQuantumToShort(GetPixelGreen(image,p));
1788           *q++=ScaleQuantumToShort(GetPixelRed(image,p));
1789           p+=GetPixelChannels(image);
1790         }
1791       }
1792       return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
1793     }
1794   if (LocaleCompare(map,"BGRA") == 0)
1795     {
1796       for (y=0; y < (ssize_t) roi->height; y++)
1797       {
1798         p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
1799         if (p == (const Quantum *) NULL)
1800           break;
1801         for (x=0; x < (ssize_t) roi->width; x++)
1802         {
1803           *q++=ScaleQuantumToShort(GetPixelBlue(image,p));
1804           *q++=ScaleQuantumToShort(GetPixelGreen(image,p));
1805           *q++=ScaleQuantumToShort(GetPixelRed(image,p));
1806           *q++=ScaleQuantumToShort(GetPixelAlpha(image,p));
1807           p+=GetPixelChannels(image);
1808         }
1809       }
1810       return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
1811     }
1812   if (LocaleCompare(map,"BGRP") == 0)
1813     {
1814       for (y=0; y < (ssize_t) roi->height; y++)
1815       {
1816         p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
1817         if (p == (const Quantum *) NULL)
1818           break;
1819         for (x=0; x < (ssize_t) roi->width; x++)
1820         {
1821           *q++=ScaleQuantumToShort(GetPixelBlue(image,p));
1822           *q++=ScaleQuantumToShort(GetPixelGreen(image,p));
1823           *q++=ScaleQuantumToShort(GetPixelRed(image,p));
1824           *q++=0;
1825           p+=GetPixelChannels(image);
1826         }
1827       }
1828       return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
1829     }
1830   if (LocaleCompare(map,"I") == 0)
1831     {
1832       for (y=0; y < (ssize_t) roi->height; y++)
1833       {
1834         p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
1835         if (p == (const Quantum *) NULL)
1836           break;
1837         for (x=0; x < (ssize_t) roi->width; x++)
1838         {
1839           *q++=ScaleQuantumToShort(ClampToQuantum(GetPixelIntensity(image,p)));
1840           p+=GetPixelChannels(image);
1841         }
1842       }
1843       return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
1844     }
1845   if (LocaleCompare(map,"RGB") == 0)
1846     {
1847       for (y=0; y < (ssize_t) roi->height; y++)
1848       {
1849         p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
1850         if (p == (const Quantum *) NULL)
1851           break;
1852         for (x=0; x < (ssize_t) roi->width; x++)
1853         {
1854           *q++=ScaleQuantumToShort(GetPixelRed(image,p));
1855           *q++=ScaleQuantumToShort(GetPixelGreen(image,p));
1856           *q++=ScaleQuantumToShort(GetPixelBlue(image,p));
1857           p+=GetPixelChannels(image);
1858         }
1859       }
1860       return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
1861     }
1862   if (LocaleCompare(map,"RGBA") == 0)
1863     {
1864       for (y=0; y < (ssize_t) roi->height; y++)
1865       {
1866         p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
1867         if (p == (const Quantum *) NULL)
1868           break;
1869         for (x=0; x < (ssize_t) roi->width; x++)
1870         {
1871           *q++=ScaleQuantumToShort(GetPixelRed(image,p));
1872           *q++=ScaleQuantumToShort(GetPixelGreen(image,p));
1873           *q++=ScaleQuantumToShort(GetPixelBlue(image,p));
1874           *q++=ScaleQuantumToShort(GetPixelAlpha(image,p));
1875           p+=GetPixelChannels(image);
1876         }
1877       }
1878       return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
1879     }
1880   if (LocaleCompare(map,"RGBP") == 0)
1881     {
1882       for (y=0; y < (ssize_t) roi->height; y++)
1883       {
1884         p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
1885         if (p == (const Quantum *) NULL)
1886           break;
1887         for (x=0; x < (ssize_t) roi->width; x++)
1888         {
1889           *q++=ScaleQuantumToShort(GetPixelRed(image,p));
1890           *q++=ScaleQuantumToShort(GetPixelGreen(image,p));
1891           *q++=ScaleQuantumToShort(GetPixelBlue(image,p));
1892           *q++=0;
1893           p+=GetPixelChannels(image);
1894         }
1895       }
1896       return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
1897     }
1898   length=strlen(map);
1899   for (y=0; y < (ssize_t) roi->height; y++)
1900   {
1901     p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
1902     if (p == (const Quantum *) NULL)
1903       break;
1904     for (x=0; x < (ssize_t) roi->width; x++)
1905     {
1906       ssize_t
1907         i;
1908 
1909       for (i=0; i < (ssize_t) length; i++)
1910       {
1911         *q=0;
1912         switch (quantum_map[i])
1913         {
1914           case RedQuantum:
1915           case CyanQuantum:
1916           {
1917             *q=ScaleQuantumToShort(GetPixelRed(image,p));
1918             break;
1919           }
1920           case GreenQuantum:
1921           case MagentaQuantum:
1922           {
1923             *q=ScaleQuantumToShort(GetPixelGreen(image,p));
1924             break;
1925           }
1926           case BlueQuantum:
1927           case YellowQuantum:
1928           {
1929             *q=ScaleQuantumToShort(GetPixelBlue(image,p));
1930             break;
1931           }
1932           case AlphaQuantum:
1933           {
1934             *q=ScaleQuantumToShort(GetPixelAlpha(image,p));
1935             break;
1936           }
1937           case OpacityQuantum:
1938           {
1939             *q=ScaleQuantumToShort(GetPixelAlpha(image,p));
1940             break;
1941           }
1942           case BlackQuantum:
1943           {
1944             if (image->colorspace == CMYKColorspace)
1945               *q=ScaleQuantumToShort(GetPixelBlack(image,p));
1946             break;
1947           }
1948           case IndexQuantum:
1949           {
1950             *q=ScaleQuantumToShort(ClampToQuantum(GetPixelIntensity(image,p)));
1951             break;
1952           }
1953           default:
1954             break;
1955         }
1956         q++;
1957       }
1958       p+=GetPixelChannels(image);
1959     }
1960   }
1961   return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
1962 }
1963 
ExportImagePixels(const Image * image,const ssize_t x,const ssize_t y,const size_t width,const size_t height,const char * map,const StorageType type,void * pixels,ExceptionInfo * exception)1964 MagickExport MagickBooleanType ExportImagePixels(const Image *image,
1965   const ssize_t x,const ssize_t y,const size_t width,const size_t height,
1966   const char *map,const StorageType type,void *pixels,ExceptionInfo *exception)
1967 {
1968   MagickBooleanType
1969     status;
1970 
1971   QuantumType
1972     *quantum_map;
1973 
1974   RectangleInfo
1975     roi;
1976 
1977   ssize_t
1978     i;
1979 
1980   size_t
1981     length;
1982 
1983   assert(image != (Image *) NULL);
1984   assert(image->signature == MagickCoreSignature);
1985   if (image->debug != MagickFalse)
1986     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1987   length=strlen(map);
1988   quantum_map=(QuantumType *) AcquireQuantumMemory(length,sizeof(*quantum_map));
1989   if (quantum_map == (QuantumType *) NULL)
1990     {
1991       (void) ThrowMagickException(exception,GetMagickModule(),
1992         ResourceLimitError,"MemoryAllocationFailed","`%s'",image->filename);
1993       return(MagickFalse);
1994     }
1995   for (i=0; i < (ssize_t) length; i++)
1996   {
1997     switch (map[i])
1998     {
1999       case 'A':
2000       case 'a':
2001       {
2002         quantum_map[i]=AlphaQuantum;
2003         break;
2004       }
2005       case 'B':
2006       case 'b':
2007       {
2008         quantum_map[i]=BlueQuantum;
2009         break;
2010       }
2011       case 'C':
2012       case 'c':
2013       {
2014         quantum_map[i]=CyanQuantum;
2015         if (image->colorspace == CMYKColorspace)
2016           break;
2017         quantum_map=(QuantumType *) RelinquishMagickMemory(quantum_map);
2018         (void) ThrowMagickException(exception,GetMagickModule(),ImageError,
2019           "ColorSeparatedImageRequired","`%s'",map);
2020         return(MagickFalse);
2021       }
2022       case 'g':
2023       case 'G':
2024       {
2025         quantum_map[i]=GreenQuantum;
2026         break;
2027       }
2028       case 'I':
2029       case 'i':
2030       {
2031         quantum_map[i]=IndexQuantum;
2032         break;
2033       }
2034       case 'K':
2035       case 'k':
2036       {
2037         quantum_map[i]=BlackQuantum;
2038         if (image->colorspace == CMYKColorspace)
2039           break;
2040         quantum_map=(QuantumType *) RelinquishMagickMemory(quantum_map);
2041         (void) ThrowMagickException(exception,GetMagickModule(),ImageError,
2042           "ColorSeparatedImageRequired","`%s'",map);
2043         return(MagickFalse);
2044       }
2045       case 'M':
2046       case 'm':
2047       {
2048         quantum_map[i]=MagentaQuantum;
2049         if (image->colorspace == CMYKColorspace)
2050           break;
2051         quantum_map=(QuantumType *) RelinquishMagickMemory(quantum_map);
2052         (void) ThrowMagickException(exception,GetMagickModule(),ImageError,
2053           "ColorSeparatedImageRequired","`%s'",map);
2054         return(MagickFalse);
2055       }
2056       case 'o':
2057       case 'O':
2058       {
2059         quantum_map[i]=OpacityQuantum;
2060         break;
2061       }
2062       case 'P':
2063       case 'p':
2064       {
2065         quantum_map[i]=UndefinedQuantum;
2066         break;
2067       }
2068       case 'R':
2069       case 'r':
2070       {
2071         quantum_map[i]=RedQuantum;
2072         break;
2073       }
2074       case 'Y':
2075       case 'y':
2076       {
2077         quantum_map[i]=YellowQuantum;
2078         if (image->colorspace == CMYKColorspace)
2079           break;
2080         quantum_map=(QuantumType *) RelinquishMagickMemory(quantum_map);
2081         (void) ThrowMagickException(exception,GetMagickModule(),ImageError,
2082           "ColorSeparatedImageRequired","`%s'",map);
2083         return(MagickFalse);
2084       }
2085       default:
2086       {
2087         quantum_map=(QuantumType *) RelinquishMagickMemory(quantum_map);
2088         (void) ThrowMagickException(exception,GetMagickModule(),OptionError,
2089           "UnrecognizedPixelMap","`%s'",map);
2090         return(MagickFalse);
2091       }
2092     }
2093   }
2094   roi.width=width;
2095   roi.height=height;
2096   roi.x=x;
2097   roi.y=y;
2098   switch (type)
2099   {
2100     case CharPixel:
2101     {
2102       status=ExportCharPixel(image,&roi,map,quantum_map,pixels,exception);
2103       break;
2104     }
2105     case DoublePixel:
2106     {
2107       status=ExportDoublePixel(image,&roi,map,quantum_map,pixels,exception);
2108       break;
2109     }
2110     case FloatPixel:
2111     {
2112       status=ExportFloatPixel(image,&roi,map,quantum_map,pixels,exception);
2113       break;
2114     }
2115     case LongPixel:
2116     {
2117       status=ExportLongPixel(image,&roi,map,quantum_map,pixels,exception);
2118       break;
2119     }
2120     case LongLongPixel:
2121     {
2122       status=ExportLongLongPixel(image,&roi,map,quantum_map,pixels,exception);
2123       break;
2124     }
2125     case QuantumPixel:
2126     {
2127       status=ExportQuantumPixel(image,&roi,map,quantum_map,pixels,exception);
2128       break;
2129     }
2130     case ShortPixel:
2131     {
2132       status=ExportShortPixel(image,&roi,map,quantum_map,pixels,exception);
2133       break;
2134     }
2135     default:
2136     {
2137       (void) ThrowMagickException(exception,GetMagickModule(),OptionError,
2138         "UnrecognizedPixelMap","`%s'",map);
2139       status=MagickFalse;
2140     }
2141   }
2142   quantum_map=(QuantumType *) RelinquishMagickMemory(quantum_map);
2143   return(status);
2144 }
2145 
2146 /*
2147 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2148 %                                                                             %
2149 %                                                                             %
2150 %                                                                             %
2151 %   G e t P i x e l I n f o                                                   %
2152 %                                                                             %
2153 %                                                                             %
2154 %                                                                             %
2155 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2156 %
2157 %  GetPixelInfo() initializes the PixelInfo structure.
2158 %
2159 %  The format of the GetPixelInfo method is:
2160 %
2161 %      GetPixelInfo(const Image *image,PixelInfo *pixel)
2162 %
2163 %  A description of each parameter follows:
2164 %
2165 %    o image: the image. (optional - may be NULL)
2166 %
2167 %    o pixel: Specifies a pointer to a PixelInfo structure.
2168 %
2169 */
GetPixelInfo(const Image * image,PixelInfo * pixel)2170 MagickExport void GetPixelInfo(const Image *image,PixelInfo *pixel)
2171 {
2172   (void) memset(pixel,0,sizeof(*pixel));
2173   pixel->storage_class=DirectClass;
2174   pixel->colorspace=sRGBColorspace;
2175   pixel->depth=MAGICKCORE_QUANTUM_DEPTH;
2176   pixel->alpha_trait=UndefinedPixelTrait;
2177   pixel->alpha=(double) OpaqueAlpha;
2178   if (image == (const Image *) NULL)
2179     return;
2180   pixel->storage_class=image->storage_class;
2181   pixel->colorspace=image->colorspace;
2182   pixel->alpha_trait=image->alpha_trait;
2183   pixel->depth=image->depth;
2184   pixel->fuzz=image->fuzz;
2185 }
2186 
2187 /*
2188 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2189 %                                                                             %
2190 %                                                                             %
2191 %                                                                             %
2192 %   G e t P i x e l I n d o I n t e n s i t y                                 %
2193 %                                                                             %
2194 %                                                                             %
2195 %                                                                             %
2196 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2197 %
2198 %  GetPixelInfoIntensity() returns a single sample intensity value from the red,
2199 %  green, and blue components of a pixel based on the selected method:
2200 %
2201 %    Rec601Luma       0.298839R' + 0.586811G' + 0.114350B'
2202 %    Rec601Luminance  0.298839R + 0.586811G + 0.114350B
2203 %    Rec709Luma       0.212656R' + 0.715158G' + 0.072186B'
2204 %    Rec709Luminance  0.212656R + 0.715158G + 0.072186B
2205 %    Brightness       max(R', G', B')
2206 %    Lightness        (min(R', G', B') + max(R', G', B')) / 2.0
2207 %
2208 %    MS               (R^2 + G^2 + B^2) / 3.0
2209 %    RMS              sqrt((R^2 + G^2 + B^2) / 3.0
2210 %    Average          (R + G + B') / 3.0
2211 %
2212 %  The format of the GetPixelInfoIntensity method is:
2213 %
2214 %      MagickRealType GetPixelInfoIntensity(const Image *image,
2215 %        const Quantum *pixel)
2216 %
2217 %  A description of each parameter follows:
2218 %
2219 %    o image: the image.
2220 %
2221 %    o pixel: Specifies a pointer to a Quantum structure.
2222 %
2223 */
GetPixelInfoIntensity(const Image * magick_restrict image,const PixelInfo * magick_restrict pixel)2224 MagickExport MagickRealType GetPixelInfoIntensity(
2225   const Image *magick_restrict image,const PixelInfo *magick_restrict pixel)
2226 {
2227   MagickRealType
2228     blue,
2229     green,
2230     red,
2231     intensity;
2232 
2233   PixelIntensityMethod
2234     method;
2235 
2236   method=Rec709LumaPixelIntensityMethod;
2237   if (image != (const Image *) NULL)
2238     method=image->intensity;
2239   red=pixel->red;
2240   green=pixel->green;
2241   blue=pixel->blue;
2242   switch (method)
2243   {
2244     case AveragePixelIntensityMethod:
2245     {
2246       intensity=(red+green+blue)/3.0;
2247       break;
2248     }
2249     case BrightnessPixelIntensityMethod:
2250     {
2251       intensity=MagickMax(MagickMax(red,green),blue);
2252       break;
2253     }
2254     case LightnessPixelIntensityMethod:
2255     {
2256       intensity=(MagickMin(MagickMin(red,green),blue)+
2257         MagickMax(MagickMax(red,green),blue))/2.0;
2258       break;
2259     }
2260     case MSPixelIntensityMethod:
2261     {
2262       intensity=(MagickRealType) (((double) red*red+green*green+blue*blue)/
2263         (3.0*QuantumRange));
2264       break;
2265     }
2266     case Rec601LumaPixelIntensityMethod:
2267     {
2268       if (pixel->colorspace == RGBColorspace)
2269         {
2270           red=EncodePixelGamma(red);
2271           green=EncodePixelGamma(green);
2272           blue=EncodePixelGamma(blue);
2273         }
2274       intensity=0.298839*red+0.586811*green+0.114350*blue;
2275       break;
2276     }
2277     case Rec601LuminancePixelIntensityMethod:
2278     {
2279       if (pixel->colorspace == sRGBColorspace)
2280         {
2281           red=DecodePixelGamma(red);
2282           green=DecodePixelGamma(green);
2283           blue=DecodePixelGamma(blue);
2284         }
2285       intensity=0.298839*red+0.586811*green+0.114350*blue;
2286       break;
2287     }
2288     case Rec709LumaPixelIntensityMethod:
2289     default:
2290     {
2291       if (pixel->colorspace == RGBColorspace)
2292         {
2293           red=EncodePixelGamma(red);
2294           green=EncodePixelGamma(green);
2295           blue=EncodePixelGamma(blue);
2296         }
2297       intensity=0.212656*red+0.715158*green+0.072186*blue;
2298       break;
2299     }
2300     case Rec709LuminancePixelIntensityMethod:
2301     {
2302       if (pixel->colorspace == sRGBColorspace)
2303         {
2304           red=DecodePixelGamma(red);
2305           green=DecodePixelGamma(green);
2306           blue=DecodePixelGamma(blue);
2307         }
2308       intensity=0.212656*red+0.715158*green+0.072186*blue;
2309       break;
2310     }
2311     case RMSPixelIntensityMethod:
2312     {
2313       intensity=(MagickRealType) (sqrt((double) red*red+green*green+blue*blue)/
2314         sqrt(3.0));
2315       break;
2316     }
2317   }
2318   return(intensity);
2319 }
2320 
2321 /*
2322 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2323 %                                                                             %
2324 %                                                                             %
2325 %                                                                             %
2326 %   G e t P i x e l I n t e n s i t y                                         %
2327 %                                                                             %
2328 %                                                                             %
2329 %                                                                             %
2330 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2331 %
2332 %  GetPixelIntensity() returns a single sample intensity value from the red,
2333 %  green, and blue components of a pixel based on the selected method:
2334 %
2335 %    Rec601Luma       0.298839R' + 0.586811G' + 0.114350B'
2336 %    Rec601Luminance  0.298839R + 0.586811G + 0.114350B
2337 %    Rec709Luma       0.212656R' + 0.715158G' + 0.072186B'
2338 %    Rec709Luminance  0.212656R + 0.715158G + 0.072186B
2339 %    Brightness       max(R', G', B')
2340 %    Lightness        (min(R', G', B') + max(R', G', B')) / 2.0
2341 %
2342 %    MS               (R^2 + G^2 + B^2) / 3.0
2343 %    RMS              sqrt((R^2 + G^2 + B^2) / 3.0
2344 %    Average          (R + G + B') / 3.0
2345 %
2346 %  The format of the GetPixelIntensity method is:
2347 %
2348 %      MagickRealType GetPixelIntensity(const Image *image,
2349 %        const Quantum *pixel)
2350 %
2351 %  A description of each parameter follows:
2352 %
2353 %    o image: the image.
2354 %
2355 %    o pixel: Specifies a pointer to a Quantum structure.
2356 %
2357 */
GetPixelIntensity(const Image * magick_restrict image,const Quantum * magick_restrict pixel)2358 MagickExport MagickRealType GetPixelIntensity(
2359   const Image *magick_restrict image,const Quantum *magick_restrict pixel)
2360 {
2361   MagickRealType
2362     blue,
2363     green,
2364     red,
2365     intensity;
2366 
2367   red=(MagickRealType) GetPixelRed(image,pixel);
2368   if (image->number_channels == 1)
2369     return(red);
2370   green=(MagickRealType) GetPixelGreen(image,pixel);
2371   blue=(MagickRealType) GetPixelBlue(image,pixel);
2372   switch (image->intensity)
2373   {
2374     case AveragePixelIntensityMethod:
2375     {
2376       intensity=(red+green+blue)/3.0;
2377       break;
2378     }
2379     case BrightnessPixelIntensityMethod:
2380     {
2381       intensity=MagickMax(MagickMax(red,green),blue);
2382       break;
2383     }
2384     case LightnessPixelIntensityMethod:
2385     {
2386       intensity=(MagickMin(MagickMin(red,green),blue)+
2387         MagickMax(MagickMax(red,green),blue))/2.0;
2388       break;
2389     }
2390     case MSPixelIntensityMethod:
2391     {
2392       intensity=(MagickRealType) (((double) red*red+green*green+blue*blue)/
2393         (3.0*QuantumRange));
2394       break;
2395     }
2396     case Rec601LumaPixelIntensityMethod:
2397     {
2398       if ((image->colorspace == RGBColorspace) ||
2399           (image->colorspace == LinearGRAYColorspace))
2400         {
2401           red=EncodePixelGamma(red);
2402           green=EncodePixelGamma(green);
2403           blue=EncodePixelGamma(blue);
2404         }
2405       intensity=0.298839*red+0.586811*green+0.114350*blue;
2406       break;
2407     }
2408     case Rec601LuminancePixelIntensityMethod:
2409     {
2410       if ((image->colorspace == sRGBColorspace) ||
2411           (image->colorspace == GRAYColorspace))
2412         {
2413           red=DecodePixelGamma(red);
2414           green=DecodePixelGamma(green);
2415           blue=DecodePixelGamma(blue);
2416         }
2417       intensity=0.298839*red+0.586811*green+0.114350*blue;
2418       break;
2419     }
2420     case Rec709LumaPixelIntensityMethod:
2421     default:
2422     {
2423       if ((image->colorspace == RGBColorspace) ||
2424           (image->colorspace == LinearGRAYColorspace))
2425         {
2426           red=EncodePixelGamma(red);
2427           green=EncodePixelGamma(green);
2428           blue=EncodePixelGamma(blue);
2429         }
2430       intensity=0.212656*red+0.715158*green+0.072186*blue;
2431       break;
2432     }
2433     case Rec709LuminancePixelIntensityMethod:
2434     {
2435       if ((image->colorspace == sRGBColorspace) ||
2436           (image->colorspace == GRAYColorspace))
2437         {
2438           red=DecodePixelGamma(red);
2439           green=DecodePixelGamma(green);
2440           blue=DecodePixelGamma(blue);
2441         }
2442       intensity=0.212656*red+0.715158*green+0.072186*blue;
2443       break;
2444     }
2445     case RMSPixelIntensityMethod:
2446     {
2447       intensity=(MagickRealType) (sqrt((double) red*red+green*green+blue*blue)/
2448         sqrt(3.0));
2449       break;
2450     }
2451   }
2452   return(intensity);
2453 }
2454 
2455 /*
2456 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2457 %                                                                             %
2458 %                                                                             %
2459 %                                                                             %
2460 %   I m p o r t I m a g e P i x e l s                                         %
2461 %                                                                             %
2462 %                                                                             %
2463 %                                                                             %
2464 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2465 %
2466 %  ImportImagePixels() accepts pixel data and stores in the image at the
2467 %  location you specify.  The method returns MagickTrue on success otherwise
2468 %  MagickFalse if an error is encountered.  The pixel data can be either char,
2469 %  Quantum, short int, unsigned int, unsigned long long, float, or double in
2470 %  the order specified by map.
2471 %
2472 %  Suppose your want to upload the first scanline of a 640x480 image from
2473 %  character data in red-green-blue order:
2474 %
2475 %      ImportImagePixels(image,0,0,640,1,"RGB",CharPixel,pixels);
2476 %
2477 %  The format of the ImportImagePixels method is:
2478 %
2479 %      MagickBooleanType ImportImagePixels(Image *image,const ssize_t x,
2480 %        const ssize_t y,const size_t width,const size_t height,
2481 %        const char *map,const StorageType type,const void *pixels,
2482 %        ExceptionInfo *exception)
2483 %
2484 %  A description of each parameter follows:
2485 %
2486 %    o image: the image.
2487 %
2488 %    o x,y,width,height:  These values define the perimeter
2489 %      of a region of pixels you want to define.
2490 %
2491 %    o map:  This string reflects the expected ordering of the pixel array.
2492 %      It can be any combination or order of R = red, G = green, B = blue,
2493 %      A = alpha (0 is transparent), O = opacity (0 is opaque), C = cyan,
2494 %      Y = yellow, M = magenta, K = black, I = intensity (for grayscale),
2495 %      P = pad.
2496 %
2497 %    o type: Define the data type of the pixels.  Float and double types are
2498 %      normalized to [0..1] otherwise [0..QuantumRange].  Choose from these
2499 %      types: CharPixel (char *), DoublePixel (double *), FloatPixel (float *),
2500 %      LongPixel (unsigned int *), LongLongPixel (unsigned long long *),
2501 %      QuantumPixel (Quantum *), or ShortPixel (unsigned short *).
2502 %
2503 %    o pixels: This array of values contain the pixel components as defined by
2504 %      map and type.  You must preallocate this array where the expected
2505 %      length varies depending on the values of width, height, map, and type.
2506 %
2507 %    o exception: return any errors or warnings in this structure.
2508 %
2509 */
2510 
ImportCharPixel(Image * image,const RectangleInfo * roi,const char * magick_restrict map,const QuantumType * quantum_map,const void * pixels,ExceptionInfo * exception)2511 static MagickBooleanType ImportCharPixel(Image *image,const RectangleInfo *roi,
2512   const char *magick_restrict map,const QuantumType *quantum_map,
2513   const void *pixels,ExceptionInfo *exception)
2514 {
2515   const unsigned char
2516     *magick_restrict p;
2517 
2518   Quantum
2519     *magick_restrict q;
2520 
2521   ssize_t
2522     x;
2523 
2524   size_t
2525     length;
2526 
2527   ssize_t
2528     y;
2529 
2530   p=(const unsigned char *) pixels;
2531   if (LocaleCompare(map,"BGR") == 0)
2532     {
2533       for (y=0; y < (ssize_t) roi->height; y++)
2534       {
2535         q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
2536         if (q == (Quantum *) NULL)
2537           break;
2538         for (x=0; x < (ssize_t) roi->width; x++)
2539         {
2540           SetPixelBlue(image,ScaleCharToQuantum(*p++),q);
2541           SetPixelGreen(image,ScaleCharToQuantum(*p++),q);
2542           SetPixelRed(image,ScaleCharToQuantum(*p++),q);
2543           q+=GetPixelChannels(image);
2544         }
2545         if (SyncAuthenticPixels(image,exception) == MagickFalse)
2546           break;
2547       }
2548       return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
2549     }
2550   if (LocaleCompare(map,"BGRA") == 0)
2551     {
2552       for (y=0; y < (ssize_t) roi->height; y++)
2553       {
2554         q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
2555         if (q == (Quantum *) NULL)
2556           break;
2557         for (x=0; x < (ssize_t) roi->width; x++)
2558         {
2559           SetPixelBlue(image,ScaleCharToQuantum(*p++),q);
2560           SetPixelGreen(image,ScaleCharToQuantum(*p++),q);
2561           SetPixelRed(image,ScaleCharToQuantum(*p++),q);
2562           SetPixelAlpha(image,ScaleCharToQuantum(*p++),q);
2563           q+=GetPixelChannels(image);
2564         }
2565         if (SyncAuthenticPixels(image,exception) == MagickFalse)
2566           break;
2567       }
2568       return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
2569     }
2570   if (LocaleCompare(map,"BGRO") == 0)
2571     {
2572       for (y=0; y < (ssize_t) roi->height; y++)
2573       {
2574         q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
2575         if (q == (Quantum *) NULL)
2576           break;
2577         for (x=0; x < (ssize_t) roi->width; x++)
2578         {
2579           SetPixelBlue(image,ScaleCharToQuantum(*p++),q);
2580           SetPixelGreen(image,ScaleCharToQuantum(*p++),q);
2581           SetPixelRed(image,ScaleCharToQuantum(*p++),q);
2582           SetPixelAlpha(image,ScaleCharToQuantum(*p++),q);
2583           q+=GetPixelChannels(image);
2584         }
2585         if (SyncAuthenticPixels(image,exception) == MagickFalse)
2586           break;
2587       }
2588       return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
2589     }
2590   if (LocaleCompare(map,"BGRP") == 0)
2591     {
2592       for (y=0; y < (ssize_t) roi->height; y++)
2593       {
2594         q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
2595         if (q == (Quantum *) NULL)
2596           break;
2597         for (x=0; x < (ssize_t) roi->width; x++)
2598         {
2599           SetPixelBlue(image,ScaleCharToQuantum(*p++),q);
2600           SetPixelGreen(image,ScaleCharToQuantum(*p++),q);
2601           SetPixelRed(image,ScaleCharToQuantum(*p++),q);
2602           p++;
2603           q+=GetPixelChannels(image);
2604         }
2605         if (SyncAuthenticPixels(image,exception) == MagickFalse)
2606           break;
2607       }
2608       return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
2609     }
2610   if (LocaleCompare(map,"I") == 0)
2611     {
2612       for (y=0; y < (ssize_t) roi->height; y++)
2613       {
2614         q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
2615         if (q == (Quantum *) NULL)
2616           break;
2617         for (x=0; x < (ssize_t) roi->width; x++)
2618         {
2619           SetPixelGray(image,ScaleCharToQuantum(*p++),q);
2620           q+=GetPixelChannels(image);
2621         }
2622         if (SyncAuthenticPixels(image,exception) == MagickFalse)
2623           break;
2624       }
2625       return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
2626     }
2627   if (LocaleCompare(map,"RGB") == 0)
2628     {
2629       for (y=0; y < (ssize_t) roi->height; y++)
2630       {
2631         q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
2632         if (q == (Quantum *) NULL)
2633           break;
2634         for (x=0; x < (ssize_t) roi->width; x++)
2635         {
2636           SetPixelRed(image,ScaleCharToQuantum(*p++),q);
2637           SetPixelGreen(image,ScaleCharToQuantum(*p++),q);
2638           SetPixelBlue(image,ScaleCharToQuantum(*p++),q);
2639           q+=GetPixelChannels(image);
2640         }
2641         if (SyncAuthenticPixels(image,exception) == MagickFalse)
2642           break;
2643       }
2644       return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
2645     }
2646   if (LocaleCompare(map,"RGBA") == 0)
2647     {
2648       for (y=0; y < (ssize_t) roi->height; y++)
2649       {
2650         q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
2651         if (q == (Quantum *) NULL)
2652           break;
2653         for (x=0; x < (ssize_t) roi->width; x++)
2654         {
2655           SetPixelRed(image,ScaleCharToQuantum(*p++),q);
2656           SetPixelGreen(image,ScaleCharToQuantum(*p++),q);
2657           SetPixelBlue(image,ScaleCharToQuantum(*p++),q);
2658           SetPixelAlpha(image,ScaleCharToQuantum(*p++),q);
2659           q+=GetPixelChannels(image);
2660         }
2661         if (SyncAuthenticPixels(image,exception) == MagickFalse)
2662           break;
2663       }
2664       return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
2665     }
2666   if (LocaleCompare(map,"RGBO") == 0)
2667     {
2668       for (y=0; y < (ssize_t) roi->height; y++)
2669       {
2670         q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
2671         if (q == (Quantum *) NULL)
2672           break;
2673         for (x=0; x < (ssize_t) roi->width; x++)
2674         {
2675           SetPixelRed(image,ScaleCharToQuantum(*p++),q);
2676           SetPixelGreen(image,ScaleCharToQuantum(*p++),q);
2677           SetPixelBlue(image,ScaleCharToQuantum(*p++),q);
2678           SetPixelAlpha(image,ScaleCharToQuantum(*p++),q);
2679           q+=GetPixelChannels(image);
2680         }
2681         if (SyncAuthenticPixels(image,exception) == MagickFalse)
2682           break;
2683       }
2684       return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
2685     }
2686   if (LocaleCompare(map,"RGBP") == 0)
2687     {
2688       for (y=0; y < (ssize_t) roi->height; y++)
2689       {
2690         q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
2691         if (q == (Quantum *) NULL)
2692           break;
2693         for (x=0; x < (ssize_t) roi->width; x++)
2694         {
2695           SetPixelRed(image,ScaleCharToQuantum(*p++),q);
2696           SetPixelGreen(image,ScaleCharToQuantum(*p++),q);
2697           SetPixelBlue(image,ScaleCharToQuantum(*p++),q);
2698           p++;
2699           q+=GetPixelChannels(image);
2700         }
2701         if (SyncAuthenticPixels(image,exception) == MagickFalse)
2702           break;
2703       }
2704       return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
2705     }
2706   length=strlen(map);
2707   for (y=0; y < (ssize_t) roi->height; y++)
2708   {
2709     q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
2710     if (q == (Quantum *) NULL)
2711       break;
2712     for (x=0; x < (ssize_t) roi->width; x++)
2713     {
2714       ssize_t
2715         i;
2716 
2717       for (i=0; i < (ssize_t) length; i++)
2718       {
2719         switch (quantum_map[i])
2720         {
2721           case RedQuantum:
2722           case CyanQuantum:
2723           {
2724             SetPixelRed(image,ScaleCharToQuantum(*p),q);
2725             break;
2726           }
2727           case GreenQuantum:
2728           case MagentaQuantum:
2729           {
2730             SetPixelGreen(image,ScaleCharToQuantum(*p),q);
2731             break;
2732           }
2733           case BlueQuantum:
2734           case YellowQuantum:
2735           {
2736             SetPixelBlue(image,ScaleCharToQuantum(*p),q);
2737             break;
2738           }
2739           case AlphaQuantum:
2740           {
2741             SetPixelAlpha(image,ScaleCharToQuantum(*p),q);
2742             break;
2743           }
2744           case OpacityQuantum:
2745           {
2746             SetPixelAlpha(image,ScaleCharToQuantum(*p),q);
2747             break;
2748           }
2749           case BlackQuantum:
2750           {
2751             SetPixelBlack(image,ScaleCharToQuantum(*p),q);
2752             break;
2753           }
2754           case IndexQuantum:
2755           {
2756             SetPixelGray(image,ScaleCharToQuantum(*p),q);
2757             break;
2758           }
2759           default:
2760             break;
2761         }
2762         p++;
2763       }
2764       q+=GetPixelChannels(image);
2765     }
2766     if (SyncAuthenticPixels(image,exception) == MagickFalse)
2767       break;
2768   }
2769   return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
2770 }
2771 
ImportDoublePixel(Image * image,const RectangleInfo * roi,const char * magick_restrict map,const QuantumType * quantum_map,const void * pixels,ExceptionInfo * exception)2772 static MagickBooleanType ImportDoublePixel(Image *image,
2773   const RectangleInfo *roi,const char *magick_restrict map,
2774   const QuantumType *quantum_map,const void *pixels,ExceptionInfo *exception)
2775 {
2776   const double
2777     *magick_restrict p;
2778 
2779   Quantum
2780     *magick_restrict q;
2781 
2782   ssize_t
2783     x;
2784 
2785   size_t
2786     length;
2787 
2788   ssize_t
2789     y;
2790 
2791   p=(const double *) pixels;
2792   if (LocaleCompare(map,"BGR") == 0)
2793     {
2794       for (y=0; y < (ssize_t) roi->height; y++)
2795       {
2796         q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
2797         if (q == (Quantum *) NULL)
2798           break;
2799         for (x=0; x < (ssize_t) roi->width; x++)
2800         {
2801           SetPixelBlue(image,ClampToQuantum(QuantumRange*(*p)),q);
2802           p++;
2803           SetPixelGreen(image,ClampToQuantum(QuantumRange*(*p)),q);
2804           p++;
2805           SetPixelRed(image,ClampToQuantum(QuantumRange*(*p)),q);
2806           p++;
2807           q+=GetPixelChannels(image);
2808         }
2809         if (SyncAuthenticPixels(image,exception) == MagickFalse)
2810           break;
2811       }
2812       return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
2813     }
2814   if (LocaleCompare(map,"BGRA") == 0)
2815     {
2816       for (y=0; y < (ssize_t) roi->height; y++)
2817       {
2818         q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
2819         if (q == (Quantum *) NULL)
2820           break;
2821         for (x=0; x < (ssize_t) roi->width; x++)
2822         {
2823           SetPixelBlue(image,ClampToQuantum(QuantumRange*(*p)),q);
2824           p++;
2825           SetPixelGreen(image,ClampToQuantum(QuantumRange*(*p)),q);
2826           p++;
2827           SetPixelRed(image,ClampToQuantum(QuantumRange*(*p)),q);
2828           p++;
2829           SetPixelAlpha(image,ClampToQuantum(QuantumRange*(*p)),q);
2830           p++;
2831           q+=GetPixelChannels(image);
2832         }
2833         if (SyncAuthenticPixels(image,exception) == MagickFalse)
2834           break;
2835       }
2836       return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
2837     }
2838   if (LocaleCompare(map,"BGRP") == 0)
2839     {
2840       for (y=0; y < (ssize_t) roi->height; y++)
2841       {
2842         q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
2843         if (q == (Quantum *) NULL)
2844           break;
2845         for (x=0; x < (ssize_t) roi->width; x++)
2846         {
2847           SetPixelBlue(image,ClampToQuantum(QuantumRange*(*p)),q);
2848           p++;
2849           SetPixelGreen(image,ClampToQuantum(QuantumRange*(*p)),q);
2850           p++;
2851           SetPixelRed(image,ClampToQuantum(QuantumRange*(*p)),q);
2852           p++;
2853           p++;
2854           q+=GetPixelChannels(image);
2855         }
2856         if (SyncAuthenticPixels(image,exception) == MagickFalse)
2857           break;
2858       }
2859       return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
2860     }
2861   if (LocaleCompare(map,"I") == 0)
2862     {
2863       for (y=0; y < (ssize_t) roi->height; y++)
2864       {
2865         q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
2866         if (q == (Quantum *) NULL)
2867           break;
2868         for (x=0; x < (ssize_t) roi->width; x++)
2869         {
2870           SetPixelGray(image,ClampToQuantum(QuantumRange*(*p)),q);
2871           p++;
2872           q+=GetPixelChannels(image);
2873         }
2874         if (SyncAuthenticPixels(image,exception) == MagickFalse)
2875           break;
2876       }
2877       return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
2878     }
2879   if (LocaleCompare(map,"RGB") == 0)
2880     {
2881       for (y=0; y < (ssize_t) roi->height; y++)
2882       {
2883         q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
2884         if (q == (Quantum *) NULL)
2885           break;
2886         for (x=0; x < (ssize_t) roi->width; x++)
2887         {
2888           SetPixelRed(image,ClampToQuantum(QuantumRange*(*p)),q);
2889           p++;
2890           SetPixelGreen(image,ClampToQuantum(QuantumRange*(*p)),q);
2891           p++;
2892           SetPixelBlue(image,ClampToQuantum(QuantumRange*(*p)),q);
2893           p++;
2894           q+=GetPixelChannels(image);
2895         }
2896         if (SyncAuthenticPixels(image,exception) == MagickFalse)
2897           break;
2898       }
2899       return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
2900     }
2901   if (LocaleCompare(map,"RGBA") == 0)
2902     {
2903       for (y=0; y < (ssize_t) roi->height; y++)
2904       {
2905         q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
2906         if (q == (Quantum *) NULL)
2907           break;
2908         for (x=0; x < (ssize_t) roi->width; x++)
2909         {
2910           SetPixelRed(image,ClampToQuantum(QuantumRange*(*p)),q);
2911           p++;
2912           SetPixelGreen(image,ClampToQuantum(QuantumRange*(*p)),q);
2913           p++;
2914           SetPixelBlue(image,ClampToQuantum(QuantumRange*(*p)),q);
2915           p++;
2916           SetPixelAlpha(image,ClampToQuantum(QuantumRange*(*p)),q);
2917           p++;
2918           q+=GetPixelChannels(image);
2919         }
2920         if (SyncAuthenticPixels(image,exception) == MagickFalse)
2921           break;
2922       }
2923       return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
2924     }
2925   if (LocaleCompare(map,"RGBP") == 0)
2926     {
2927       for (y=0; y < (ssize_t) roi->height; y++)
2928       {
2929         q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
2930         if (q == (Quantum *) NULL)
2931           break;
2932         for (x=0; x < (ssize_t) roi->width; x++)
2933         {
2934           SetPixelRed(image,ClampToQuantum(QuantumRange*(*p)),q);
2935           p++;
2936           SetPixelGreen(image,ClampToQuantum(QuantumRange*(*p)),q);
2937           p++;
2938           SetPixelBlue(image,ClampToQuantum(QuantumRange*(*p)),q);
2939           p++;
2940           q+=GetPixelChannels(image);
2941         }
2942         if (SyncAuthenticPixels(image,exception) == MagickFalse)
2943           break;
2944       }
2945       return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
2946     }
2947    length=strlen(map);
2948   for (y=0; y < (ssize_t) roi->height; y++)
2949   {
2950     q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
2951     if (q == (Quantum *) NULL)
2952       break;
2953     for (x=0; x < (ssize_t) roi->width; x++)
2954     {
2955       ssize_t
2956         i;
2957 
2958       for (i=0; i < (ssize_t) length; i++)
2959       {
2960         switch (quantum_map[i])
2961         {
2962           case RedQuantum:
2963           case CyanQuantum:
2964           {
2965             SetPixelRed(image,ClampToQuantum(QuantumRange*(*p)),q);
2966             break;
2967           }
2968           case GreenQuantum:
2969           case MagentaQuantum:
2970           {
2971             SetPixelGreen(image,ClampToQuantum(QuantumRange*(*p)),q);
2972             break;
2973           }
2974           case BlueQuantum:
2975           case YellowQuantum:
2976           {
2977             SetPixelBlue(image,ClampToQuantum(QuantumRange*(*p)),q);
2978             break;
2979           }
2980           case AlphaQuantum:
2981           {
2982             SetPixelAlpha(image,ClampToQuantum(QuantumRange*(*p)),q);
2983             break;
2984           }
2985           case OpacityQuantum:
2986           {
2987             SetPixelAlpha(image,ClampToQuantum(QuantumRange*(*p)),q);
2988             break;
2989           }
2990           case BlackQuantum:
2991           {
2992             SetPixelBlack(image,ClampToQuantum(QuantumRange*(*p)),q);
2993             break;
2994           }
2995           case IndexQuantum:
2996           {
2997             SetPixelGray(image,ClampToQuantum(QuantumRange*(*p)),q);
2998             break;
2999           }
3000           default:
3001             break;
3002         }
3003         p++;
3004       }
3005       q+=GetPixelChannels(image);
3006     }
3007     if (SyncAuthenticPixels(image,exception) == MagickFalse)
3008       break;
3009   }
3010   return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
3011 }
3012 
ImportFloatPixel(Image * image,const RectangleInfo * roi,const char * magick_restrict map,const QuantumType * quantum_map,const void * pixels,ExceptionInfo * exception)3013 static MagickBooleanType ImportFloatPixel(Image *image,const RectangleInfo *roi,
3014   const char *magick_restrict map,const QuantumType *quantum_map,
3015   const void *pixels,ExceptionInfo *exception)
3016 {
3017   const float
3018     *magick_restrict p;
3019 
3020   Quantum
3021     *magick_restrict q;
3022 
3023   ssize_t
3024     x;
3025 
3026   size_t
3027     length;
3028 
3029   ssize_t
3030     y;
3031 
3032   p=(const float *) pixels;
3033   if (LocaleCompare(map,"BGR") == 0)
3034     {
3035       for (y=0; y < (ssize_t) roi->height; y++)
3036       {
3037         q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
3038         if (q == (Quantum *) NULL)
3039           break;
3040         for (x=0; x < (ssize_t) roi->width; x++)
3041         {
3042           SetPixelBlue(image,ClampToQuantum(QuantumRange*(*p)),q);
3043           p++;
3044           SetPixelGreen(image,ClampToQuantum(QuantumRange*(*p)),q);
3045           p++;
3046           SetPixelRed(image,ClampToQuantum(QuantumRange*(*p)),q);
3047           p++;
3048           q+=GetPixelChannels(image);
3049         }
3050         if (SyncAuthenticPixels(image,exception) == MagickFalse)
3051           break;
3052       }
3053       return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
3054     }
3055   if (LocaleCompare(map,"BGRA") == 0)
3056     {
3057       for (y=0; y < (ssize_t) roi->height; y++)
3058       {
3059         q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
3060         if (q == (Quantum *) NULL)
3061           break;
3062         for (x=0; x < (ssize_t) roi->width; x++)
3063         {
3064           SetPixelBlue(image,ClampToQuantum(QuantumRange*(*p)),q);
3065           p++;
3066           SetPixelGreen(image,ClampToQuantum(QuantumRange*(*p)),q);
3067           p++;
3068           SetPixelRed(image,ClampToQuantum(QuantumRange*(*p)),q);
3069           p++;
3070           SetPixelAlpha(image,ClampToQuantum(QuantumRange*(*p)),q);
3071           p++;
3072           q+=GetPixelChannels(image);
3073         }
3074         if (SyncAuthenticPixels(image,exception) == MagickFalse)
3075           break;
3076       }
3077       return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
3078     }
3079   if (LocaleCompare(map,"BGRP") == 0)
3080     {
3081       for (y=0; y < (ssize_t) roi->height; y++)
3082       {
3083         q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
3084         if (q == (Quantum *) NULL)
3085           break;
3086         for (x=0; x < (ssize_t) roi->width; x++)
3087         {
3088           SetPixelBlue(image,ClampToQuantum(QuantumRange*(*p)),q);
3089           p++;
3090           SetPixelGreen(image,ClampToQuantum(QuantumRange*(*p)),q);
3091           p++;
3092           SetPixelRed(image,ClampToQuantum(QuantumRange*(*p)),q);
3093           p++;
3094           p++;
3095           q+=GetPixelChannels(image);
3096         }
3097         if (SyncAuthenticPixels(image,exception) == MagickFalse)
3098           break;
3099       }
3100       return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
3101     }
3102   if (LocaleCompare(map,"I") == 0)
3103     {
3104       for (y=0; y < (ssize_t) roi->height; y++)
3105       {
3106         q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
3107         if (q == (Quantum *) NULL)
3108           break;
3109         for (x=0; x < (ssize_t) roi->width; x++)
3110         {
3111           SetPixelGray(image,ClampToQuantum(QuantumRange*(*p)),q);
3112           p++;
3113           q+=GetPixelChannels(image);
3114         }
3115         if (SyncAuthenticPixels(image,exception) == MagickFalse)
3116           break;
3117       }
3118       return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
3119     }
3120   if (LocaleCompare(map,"RGB") == 0)
3121     {
3122       for (y=0; y < (ssize_t) roi->height; y++)
3123       {
3124         q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
3125         if (q == (Quantum *) NULL)
3126           break;
3127         for (x=0; x < (ssize_t) roi->width; x++)
3128         {
3129           SetPixelRed(image,ClampToQuantum(QuantumRange*(*p)),q);
3130           p++;
3131           SetPixelGreen(image,ClampToQuantum(QuantumRange*(*p)),q);
3132           p++;
3133           SetPixelBlue(image,ClampToQuantum(QuantumRange*(*p)),q);
3134           p++;
3135           q+=GetPixelChannels(image);
3136         }
3137         if (SyncAuthenticPixels(image,exception) == MagickFalse)
3138           break;
3139       }
3140       return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
3141     }
3142   if (LocaleCompare(map,"RGBA") == 0)
3143     {
3144       for (y=0; y < (ssize_t) roi->height; y++)
3145       {
3146         q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
3147         if (q == (Quantum *) NULL)
3148           break;
3149         for (x=0; x < (ssize_t) roi->width; x++)
3150         {
3151           SetPixelRed(image,ClampToQuantum(QuantumRange*(*p)),q);
3152           p++;
3153           SetPixelGreen(image,ClampToQuantum(QuantumRange*(*p)),q);
3154           p++;
3155           SetPixelBlue(image,ClampToQuantum(QuantumRange*(*p)),q);
3156           p++;
3157           SetPixelAlpha(image,ClampToQuantum(QuantumRange*(*p)),q);
3158           p++;
3159           q+=GetPixelChannels(image);
3160         }
3161         if (SyncAuthenticPixels(image,exception) == MagickFalse)
3162           break;
3163       }
3164       return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
3165     }
3166   if (LocaleCompare(map,"RGBP") == 0)
3167     {
3168       for (y=0; y < (ssize_t) roi->height; y++)
3169       {
3170         q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
3171         if (q == (Quantum *) NULL)
3172           break;
3173         for (x=0; x < (ssize_t) roi->width; x++)
3174         {
3175           SetPixelRed(image,ClampToQuantum(QuantumRange*(*p)),q);
3176           p++;
3177           SetPixelGreen(image,ClampToQuantum(QuantumRange*(*p)),q);
3178           p++;
3179           SetPixelBlue(image,ClampToQuantum(QuantumRange*(*p)),q);
3180           p++;
3181           q+=GetPixelChannels(image);
3182         }
3183         if (SyncAuthenticPixels(image,exception) == MagickFalse)
3184           break;
3185       }
3186       return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
3187     }
3188   length=strlen(map);
3189   for (y=0; y < (ssize_t) roi->height; y++)
3190   {
3191     q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
3192     if (q == (Quantum *) NULL)
3193       break;
3194     for (x=0; x < (ssize_t) roi->width; x++)
3195     {
3196       ssize_t
3197         i;
3198 
3199       for (i=0; i < (ssize_t) length; i++)
3200       {
3201         switch (quantum_map[i])
3202         {
3203           case RedQuantum:
3204           case CyanQuantum:
3205           {
3206             SetPixelRed(image,ClampToQuantum(QuantumRange*(*p)),q);
3207             break;
3208           }
3209           case GreenQuantum:
3210           case MagentaQuantum:
3211           {
3212             SetPixelGreen(image,ClampToQuantum(QuantumRange*(*p)),q);
3213             break;
3214           }
3215           case BlueQuantum:
3216           case YellowQuantum:
3217           {
3218             SetPixelBlue(image,ClampToQuantum(QuantumRange*(*p)),q);
3219             break;
3220           }
3221           case AlphaQuantum:
3222           {
3223             SetPixelAlpha(image,ClampToQuantum(QuantumRange*(*p)),q);
3224             break;
3225           }
3226           case OpacityQuantum:
3227           {
3228             SetPixelAlpha(image,ClampToQuantum(QuantumRange*(*p)),q);
3229             break;
3230           }
3231           case BlackQuantum:
3232           {
3233             SetPixelBlack(image,ClampToQuantum(QuantumRange*(*p)),q);
3234             break;
3235           }
3236           case IndexQuantum:
3237           {
3238             SetPixelGray(image,ClampToQuantum(QuantumRange*(*p)),q);
3239             break;
3240           }
3241           default:
3242             break;
3243         }
3244         p++;
3245       }
3246       q+=GetPixelChannels(image);
3247     }
3248     if (SyncAuthenticPixels(image,exception) == MagickFalse)
3249       break;
3250   }
3251   return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
3252 }
3253 
ImportLongPixel(Image * image,const RectangleInfo * roi,const char * magick_restrict map,const QuantumType * quantum_map,const void * pixels,ExceptionInfo * exception)3254 static MagickBooleanType ImportLongPixel(Image *image,const RectangleInfo *roi,
3255   const char *magick_restrict map,const QuantumType *quantum_map,
3256   const void *pixels,ExceptionInfo *exception)
3257 {
3258   const unsigned int
3259     *magick_restrict p;
3260 
3261   Quantum
3262     *magick_restrict q;
3263 
3264   ssize_t
3265     x;
3266 
3267   size_t
3268     length;
3269 
3270   ssize_t
3271     y;
3272 
3273   p=(const unsigned int *) pixels;
3274   if (LocaleCompare(map,"BGR") == 0)
3275     {
3276       for (y=0; y < (ssize_t) roi->height; y++)
3277       {
3278         q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
3279         if (q == (Quantum *) NULL)
3280           break;
3281         for (x=0; x < (ssize_t) roi->width; x++)
3282         {
3283           SetPixelBlue(image,ScaleLongToQuantum(*p++),q);
3284           SetPixelGreen(image,ScaleLongToQuantum(*p++),q);
3285           SetPixelRed(image,ScaleLongToQuantum(*p++),q);
3286           q+=GetPixelChannels(image);
3287         }
3288         if (SyncAuthenticPixels(image,exception) == MagickFalse)
3289           break;
3290       }
3291       return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
3292     }
3293   if (LocaleCompare(map,"BGRA") == 0)
3294     {
3295       for (y=0; y < (ssize_t) roi->height; y++)
3296       {
3297         q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
3298         if (q == (Quantum *) NULL)
3299           break;
3300         for (x=0; x < (ssize_t) roi->width; x++)
3301         {
3302           SetPixelBlue(image,ScaleLongToQuantum(*p++),q);
3303           SetPixelGreen(image,ScaleLongToQuantum(*p++),q);
3304           SetPixelRed(image,ScaleLongToQuantum(*p++),q);
3305           SetPixelAlpha(image,ScaleLongToQuantum(*p++),q);
3306           q+=GetPixelChannels(image);
3307         }
3308         if (SyncAuthenticPixels(image,exception) == MagickFalse)
3309           break;
3310       }
3311       return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
3312     }
3313   if (LocaleCompare(map,"BGRP") == 0)
3314     {
3315       for (y=0; y < (ssize_t) roi->height; y++)
3316       {
3317         q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
3318         if (q == (Quantum *) NULL)
3319           break;
3320         for (x=0; x < (ssize_t) roi->width; x++)
3321         {
3322           SetPixelBlue(image,ScaleLongToQuantum(*p++),q);
3323           SetPixelGreen(image,ScaleLongToQuantum(*p++),q);
3324           SetPixelRed(image,ScaleLongToQuantum(*p++),q);
3325           p++;
3326           q+=GetPixelChannels(image);
3327         }
3328         if (SyncAuthenticPixels(image,exception) == MagickFalse)
3329           break;
3330       }
3331       return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
3332     }
3333   if (LocaleCompare(map,"I") == 0)
3334     {
3335       for (y=0; y < (ssize_t) roi->height; y++)
3336       {
3337         q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
3338         if (q == (Quantum *) NULL)
3339           break;
3340         for (x=0; x < (ssize_t) roi->width; x++)
3341         {
3342           SetPixelGray(image,ScaleLongToQuantum(*p++),q);
3343           q+=GetPixelChannels(image);
3344         }
3345         if (SyncAuthenticPixels(image,exception) == MagickFalse)
3346           break;
3347       }
3348       return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
3349     }
3350   if (LocaleCompare(map,"RGB") == 0)
3351     {
3352       for (y=0; y < (ssize_t) roi->height; y++)
3353       {
3354         q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
3355         if (q == (Quantum *) NULL)
3356           break;
3357         for (x=0; x < (ssize_t) roi->width; x++)
3358         {
3359           SetPixelRed(image,ScaleLongToQuantum(*p++),q);
3360           SetPixelGreen(image,ScaleLongToQuantum(*p++),q);
3361           SetPixelBlue(image,ScaleLongToQuantum(*p++),q);
3362           q+=GetPixelChannels(image);
3363         }
3364         if (SyncAuthenticPixels(image,exception) == MagickFalse)
3365           break;
3366       }
3367       return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
3368     }
3369   if (LocaleCompare(map,"RGBA") == 0)
3370     {
3371       for (y=0; y < (ssize_t) roi->height; y++)
3372       {
3373         q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
3374         if (q == (Quantum *) NULL)
3375           break;
3376         for (x=0; x < (ssize_t) roi->width; x++)
3377         {
3378           SetPixelRed(image,ScaleLongToQuantum(*p++),q);
3379           SetPixelGreen(image,ScaleLongToQuantum(*p++),q);
3380           SetPixelBlue(image,ScaleLongToQuantum(*p++),q);
3381           SetPixelAlpha(image,ScaleLongToQuantum(*p++),q);
3382           q+=GetPixelChannels(image);
3383         }
3384         if (SyncAuthenticPixels(image,exception) == MagickFalse)
3385           break;
3386       }
3387       return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
3388     }
3389   if (LocaleCompare(map,"RGBP") == 0)
3390     {
3391       for (y=0; y < (ssize_t) roi->height; y++)
3392       {
3393         q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
3394         if (q == (Quantum *) NULL)
3395           break;
3396         for (x=0; x < (ssize_t) roi->width; x++)
3397         {
3398           SetPixelRed(image,ScaleLongToQuantum(*p++),q);
3399           SetPixelGreen(image,ScaleLongToQuantum(*p++),q);
3400           SetPixelBlue(image,ScaleLongToQuantum(*p++),q);
3401           p++;
3402           q+=GetPixelChannels(image);
3403         }
3404         if (SyncAuthenticPixels(image,exception) == MagickFalse)
3405           break;
3406       }
3407       return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
3408     }
3409   length=strlen(map);
3410   for (y=0; y < (ssize_t) roi->height; y++)
3411   {
3412     q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
3413     if (q == (Quantum *) NULL)
3414       break;
3415     for (x=0; x < (ssize_t) roi->width; x++)
3416     {
3417       ssize_t
3418         i;
3419 
3420       for (i=0; i < (ssize_t) length; i++)
3421       {
3422         switch (quantum_map[i])
3423         {
3424           case RedQuantum:
3425           case CyanQuantum:
3426           {
3427             SetPixelRed(image,ScaleLongToQuantum(*p),q);
3428             break;
3429           }
3430           case GreenQuantum:
3431           case MagentaQuantum:
3432           {
3433             SetPixelGreen(image,ScaleLongToQuantum(*p),q);
3434             break;
3435           }
3436           case BlueQuantum:
3437           case YellowQuantum:
3438           {
3439             SetPixelBlue(image,ScaleLongToQuantum(*p),q);
3440             break;
3441           }
3442           case AlphaQuantum:
3443           {
3444             SetPixelAlpha(image,ScaleLongToQuantum(*p),q);
3445             break;
3446           }
3447           case OpacityQuantum:
3448           {
3449             SetPixelAlpha(image,ScaleLongToQuantum(*p),q);
3450             break;
3451           }
3452           case BlackQuantum:
3453           {
3454             SetPixelBlack(image,ScaleLongToQuantum(*p),q);
3455             break;
3456           }
3457           case IndexQuantum:
3458           {
3459             SetPixelGray(image,ScaleLongToQuantum(*p),q);
3460             break;
3461           }
3462           default:
3463             break;
3464         }
3465         p++;
3466       }
3467       q+=GetPixelChannels(image);
3468     }
3469     if (SyncAuthenticPixels(image,exception) == MagickFalse)
3470       break;
3471   }
3472   return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
3473 }
3474 
ImportLongLongPixel(Image * image,const RectangleInfo * roi,const char * magick_restrict map,const QuantumType * quantum_map,const void * pixels,ExceptionInfo * exception)3475 static MagickBooleanType ImportLongLongPixel(Image *image,
3476   const RectangleInfo *roi,const char *magick_restrict map,
3477   const QuantumType *quantum_map,const void *pixels,ExceptionInfo *exception)
3478 {
3479   const MagickSizeType
3480     *magick_restrict p;
3481 
3482   Quantum
3483     *magick_restrict q;
3484 
3485   ssize_t
3486     x;
3487 
3488   size_t
3489     length;
3490 
3491   ssize_t
3492     y;
3493 
3494   p=(const MagickSizeType *) pixels;
3495   if (LocaleCompare(map,"BGR") == 0)
3496     {
3497       for (y=0; y < (ssize_t) roi->height; y++)
3498       {
3499         q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
3500         if (q == (Quantum *) NULL)
3501           break;
3502         for (x=0; x < (ssize_t) roi->width; x++)
3503         {
3504           SetPixelBlue(image,ScaleLongLongToQuantum(*p++),q);
3505           SetPixelGreen(image,ScaleLongLongToQuantum(*p++),q);
3506           SetPixelRed(image,ScaleLongLongToQuantum(*p++),q);
3507           q+=GetPixelChannels(image);
3508         }
3509         if (SyncAuthenticPixels(image,exception) == MagickFalse)
3510           break;
3511       }
3512       return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
3513     }
3514   if (LocaleCompare(map,"BGRA") == 0)
3515     {
3516       for (y=0; y < (ssize_t) roi->height; y++)
3517       {
3518         q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
3519         if (q == (Quantum *) NULL)
3520           break;
3521         for (x=0; x < (ssize_t) roi->width; x++)
3522         {
3523           SetPixelBlue(image,ScaleLongLongToQuantum(*p++),q);
3524           SetPixelGreen(image,ScaleLongLongToQuantum(*p++),q);
3525           SetPixelRed(image,ScaleLongLongToQuantum(*p++),q);
3526           SetPixelAlpha(image,ScaleLongLongToQuantum(*p++),q);
3527           q+=GetPixelChannels(image);
3528         }
3529         if (SyncAuthenticPixels(image,exception) == MagickFalse)
3530           break;
3531       }
3532       return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
3533     }
3534   if (LocaleCompare(map,"BGRP") == 0)
3535     {
3536       for (y=0; y < (ssize_t) roi->height; y++)
3537       {
3538         q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
3539         if (q == (Quantum *) NULL)
3540           break;
3541         for (x=0; x < (ssize_t) roi->width; x++)
3542         {
3543           SetPixelBlue(image,ScaleLongLongToQuantum(*p++),q);
3544           SetPixelGreen(image,ScaleLongLongToQuantum(*p++),q);
3545           SetPixelRed(image,ScaleLongLongToQuantum(*p++),q);
3546           p++;
3547           q+=GetPixelChannels(image);
3548         }
3549         if (SyncAuthenticPixels(image,exception) == MagickFalse)
3550           break;
3551       }
3552       return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
3553     }
3554   if (LocaleCompare(map,"I") == 0)
3555     {
3556       for (y=0; y < (ssize_t) roi->height; y++)
3557       {
3558         q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
3559         if (q == (Quantum *) NULL)
3560           break;
3561         for (x=0; x < (ssize_t) roi->width; x++)
3562         {
3563           SetPixelGray(image,ScaleLongLongToQuantum(*p++),q);
3564           q+=GetPixelChannels(image);
3565         }
3566         if (SyncAuthenticPixels(image,exception) == MagickFalse)
3567           break;
3568       }
3569       return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
3570     }
3571   if (LocaleCompare(map,"RGB") == 0)
3572     {
3573       for (y=0; y < (ssize_t) roi->height; y++)
3574       {
3575         q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
3576         if (q == (Quantum *) NULL)
3577           break;
3578         for (x=0; x < (ssize_t) roi->width; x++)
3579         {
3580           SetPixelRed(image,ScaleLongLongToQuantum(*p++),q);
3581           SetPixelGreen(image,ScaleLongLongToQuantum(*p++),q);
3582           SetPixelBlue(image,ScaleLongLongToQuantum(*p++),q);
3583           q+=GetPixelChannels(image);
3584         }
3585         if (SyncAuthenticPixels(image,exception) == MagickFalse)
3586           break;
3587       }
3588       return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
3589     }
3590   if (LocaleCompare(map,"RGBA") == 0)
3591     {
3592       for (y=0; y < (ssize_t) roi->height; y++)
3593       {
3594         q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
3595         if (q == (Quantum *) NULL)
3596           break;
3597         for (x=0; x < (ssize_t) roi->width; x++)
3598         {
3599           SetPixelRed(image,ScaleLongLongToQuantum(*p++),q);
3600           SetPixelGreen(image,ScaleLongLongToQuantum(*p++),q);
3601           SetPixelBlue(image,ScaleLongLongToQuantum(*p++),q);
3602           SetPixelAlpha(image,ScaleLongLongToQuantum(*p++),q);
3603           q+=GetPixelChannels(image);
3604         }
3605         if (SyncAuthenticPixels(image,exception) == MagickFalse)
3606           break;
3607       }
3608       return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
3609     }
3610   if (LocaleCompare(map,"RGBP") == 0)
3611     {
3612       for (y=0; y < (ssize_t) roi->height; y++)
3613       {
3614         q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
3615         if (q == (Quantum *) NULL)
3616           break;
3617         for (x=0; x < (ssize_t) roi->width; x++)
3618         {
3619           SetPixelRed(image,ScaleLongLongToQuantum(*p++),q);
3620           SetPixelGreen(image,ScaleLongLongToQuantum(*p++),q);
3621           SetPixelBlue(image,ScaleLongLongToQuantum(*p++),q);
3622           p++;
3623           q+=GetPixelChannels(image);
3624         }
3625         if (SyncAuthenticPixels(image,exception) == MagickFalse)
3626           break;
3627       }
3628       return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
3629     }
3630   length=strlen(map);
3631   for (y=0; y < (ssize_t) roi->height; y++)
3632   {
3633     q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
3634     if (q == (Quantum *) NULL)
3635       break;
3636     for (x=0; x < (ssize_t) roi->width; x++)
3637     {
3638       ssize_t
3639         i;
3640 
3641       for (i=0; i < (ssize_t) length; i++)
3642       {
3643         switch (quantum_map[i])
3644         {
3645           case RedQuantum:
3646           case CyanQuantum:
3647           {
3648             SetPixelRed(image,ScaleLongLongToQuantum(*p),q);
3649             break;
3650           }
3651           case GreenQuantum:
3652           case MagentaQuantum:
3653           {
3654             SetPixelGreen(image,ScaleLongLongToQuantum(*p),q);
3655             break;
3656           }
3657           case BlueQuantum:
3658           case YellowQuantum:
3659           {
3660             SetPixelBlue(image,ScaleLongLongToQuantum(*p),q);
3661             break;
3662           }
3663           case AlphaQuantum:
3664           {
3665             SetPixelAlpha(image,ScaleLongLongToQuantum(*p),q);
3666             break;
3667           }
3668           case OpacityQuantum:
3669           {
3670             SetPixelAlpha(image,ScaleLongLongToQuantum(*p),q);
3671             break;
3672           }
3673           case BlackQuantum:
3674           {
3675             SetPixelBlack(image,ScaleLongLongToQuantum(*p),q);
3676             break;
3677           }
3678           case IndexQuantum:
3679           {
3680             SetPixelGray(image,ScaleLongLongToQuantum(*p),q);
3681             break;
3682           }
3683           default:
3684             break;
3685         }
3686         p++;
3687       }
3688       q+=GetPixelChannels(image);
3689     }
3690     if (SyncAuthenticPixels(image,exception) == MagickFalse)
3691       break;
3692   }
3693   return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
3694 }
3695 
ImportQuantumPixel(Image * image,const RectangleInfo * roi,const char * magick_restrict map,const QuantumType * quantum_map,const void * pixels,ExceptionInfo * exception)3696 static MagickBooleanType ImportQuantumPixel(Image *image,
3697   const RectangleInfo *roi,const char *magick_restrict map,
3698   const QuantumType *quantum_map,const void *pixels,ExceptionInfo *exception)
3699 {
3700   const Quantum
3701     *magick_restrict p;
3702 
3703   Quantum
3704     *magick_restrict q;
3705 
3706   ssize_t
3707     x;
3708 
3709   size_t
3710     length;
3711 
3712   ssize_t
3713     y;
3714 
3715   p=(const Quantum *) pixels;
3716   if (LocaleCompare(map,"BGR") == 0)
3717     {
3718       for (y=0; y < (ssize_t) roi->height; y++)
3719       {
3720         q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
3721         if (q == (Quantum *) NULL)
3722           break;
3723         for (x=0; x < (ssize_t) roi->width; x++)
3724         {
3725           SetPixelBlue(image,*p++,q);
3726           SetPixelGreen(image,*p++,q);
3727           SetPixelRed(image,*p++,q);
3728           q+=GetPixelChannels(image);
3729         }
3730         if (SyncAuthenticPixels(image,exception) == MagickFalse)
3731           break;
3732       }
3733       return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
3734     }
3735   if (LocaleCompare(map,"BGRA") == 0)
3736     {
3737       for (y=0; y < (ssize_t) roi->height; y++)
3738       {
3739         q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
3740         if (q == (Quantum *) NULL)
3741           break;
3742         for (x=0; x < (ssize_t) roi->width; x++)
3743         {
3744           SetPixelBlue(image,*p++,q);
3745           SetPixelGreen(image,*p++,q);
3746           SetPixelRed(image,*p++,q);
3747           SetPixelAlpha(image,*p++,q);
3748           q+=GetPixelChannels(image);
3749         }
3750         if (SyncAuthenticPixels(image,exception) == MagickFalse)
3751           break;
3752       }
3753       return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
3754     }
3755   if (LocaleCompare(map,"BGRP") == 0)
3756     {
3757       for (y=0; y < (ssize_t) roi->height; y++)
3758       {
3759         q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
3760         if (q == (Quantum *) NULL)
3761           break;
3762         for (x=0; x < (ssize_t) roi->width; x++)
3763         {
3764           SetPixelBlue(image,*p++,q);
3765           SetPixelGreen(image,*p++,q);
3766           SetPixelRed(image,*p++,q);
3767           p++;
3768           q+=GetPixelChannels(image);
3769         }
3770         if (SyncAuthenticPixels(image,exception) == MagickFalse)
3771           break;
3772       }
3773       return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
3774     }
3775   if (LocaleCompare(map,"I") == 0)
3776     {
3777       for (y=0; y < (ssize_t) roi->height; y++)
3778       {
3779         q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
3780         if (q == (Quantum *) NULL)
3781           break;
3782         for (x=0; x < (ssize_t) roi->width; x++)
3783         {
3784           SetPixelGray(image,*p++,q);
3785           q+=GetPixelChannels(image);
3786         }
3787         if (SyncAuthenticPixels(image,exception) == MagickFalse)
3788           break;
3789       }
3790       return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
3791     }
3792   if (LocaleCompare(map,"RGB") == 0)
3793     {
3794       for (y=0; y < (ssize_t) roi->height; y++)
3795       {
3796         q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
3797         if (q == (Quantum *) NULL)
3798           break;
3799         for (x=0; x < (ssize_t) roi->width; x++)
3800         {
3801           SetPixelRed(image,*p++,q);
3802           SetPixelGreen(image,*p++,q);
3803           SetPixelBlue(image,*p++,q);
3804           q+=GetPixelChannels(image);
3805         }
3806         if (SyncAuthenticPixels(image,exception) == MagickFalse)
3807           break;
3808       }
3809       return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
3810     }
3811   if (LocaleCompare(map,"RGBA") == 0)
3812     {
3813       for (y=0; y < (ssize_t) roi->height; y++)
3814       {
3815         q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
3816         if (q == (Quantum *) NULL)
3817           break;
3818         for (x=0; x < (ssize_t) roi->width; x++)
3819         {
3820           SetPixelRed(image,*p++,q);
3821           SetPixelGreen(image,*p++,q);
3822           SetPixelBlue(image,*p++,q);
3823           SetPixelAlpha(image,*p++,q);
3824           q+=GetPixelChannels(image);
3825         }
3826         if (SyncAuthenticPixels(image,exception) == MagickFalse)
3827           break;
3828       }
3829       return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
3830     }
3831   if (LocaleCompare(map,"RGBP") == 0)
3832     {
3833       for (y=0; y < (ssize_t) roi->height; y++)
3834       {
3835         q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
3836         if (q == (Quantum *) NULL)
3837           break;
3838         for (x=0; x < (ssize_t) roi->width; x++)
3839         {
3840           SetPixelRed(image,*p++,q);
3841           SetPixelGreen(image,*p++,q);
3842           SetPixelBlue(image,*p++,q);
3843           p++;
3844           q+=GetPixelChannels(image);
3845         }
3846         if (SyncAuthenticPixels(image,exception) == MagickFalse)
3847           break;
3848       }
3849       return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
3850     }
3851   length=strlen(map);
3852   for (y=0; y < (ssize_t) roi->height; y++)
3853   {
3854     q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
3855     if (q == (Quantum *) NULL)
3856       break;
3857     for (x=0; x < (ssize_t) roi->width; x++)
3858     {
3859       ssize_t
3860         i;
3861 
3862       for (i=0; i < (ssize_t) length; i++)
3863       {
3864         switch (quantum_map[i])
3865         {
3866           case RedQuantum:
3867           case CyanQuantum:
3868           {
3869             SetPixelRed(image,*p,q);
3870             break;
3871           }
3872           case GreenQuantum:
3873           case MagentaQuantum:
3874           {
3875             SetPixelGreen(image,*p,q);
3876             break;
3877           }
3878           case BlueQuantum:
3879           case YellowQuantum:
3880           {
3881             SetPixelBlue(image,*p,q);
3882             break;
3883           }
3884           case AlphaQuantum:
3885           {
3886             SetPixelAlpha(image,*p,q);
3887             break;
3888           }
3889           case OpacityQuantum:
3890           {
3891             SetPixelAlpha(image,*p,q);
3892             break;
3893           }
3894           case BlackQuantum:
3895           {
3896             SetPixelBlack(image,*p,q);
3897             break;
3898           }
3899           case IndexQuantum:
3900           {
3901             SetPixelGray(image,*p,q);
3902             break;
3903           }
3904           default:
3905             break;
3906         }
3907         p++;
3908       }
3909       q+=GetPixelChannels(image);
3910     }
3911     if (SyncAuthenticPixels(image,exception) == MagickFalse)
3912       break;
3913   }
3914   return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
3915 }
3916 
ImportShortPixel(Image * image,const RectangleInfo * roi,const char * magick_restrict map,const QuantumType * quantum_map,const void * pixels,ExceptionInfo * exception)3917 static MagickBooleanType ImportShortPixel(Image *image,const RectangleInfo *roi,
3918   const char *magick_restrict map,const QuantumType *quantum_map,
3919   const void *pixels,ExceptionInfo *exception)
3920 {
3921   const unsigned short
3922     *magick_restrict p;
3923 
3924   Quantum
3925     *magick_restrict q;
3926 
3927   ssize_t
3928     x;
3929 
3930   size_t
3931     length;
3932 
3933   ssize_t
3934     y;
3935 
3936   p=(const unsigned short *) pixels;
3937   if (LocaleCompare(map,"BGR") == 0)
3938     {
3939       for (y=0; y < (ssize_t) roi->height; y++)
3940       {
3941         q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
3942         if (q == (Quantum *) NULL)
3943           break;
3944         for (x=0; x < (ssize_t) roi->width; x++)
3945         {
3946           SetPixelBlue(image,ScaleShortToQuantum(*p++),q);
3947           SetPixelGreen(image,ScaleShortToQuantum(*p++),q);
3948           SetPixelRed(image,ScaleShortToQuantum(*p++),q);
3949           q+=GetPixelChannels(image);
3950         }
3951         if (SyncAuthenticPixels(image,exception) == MagickFalse)
3952           break;
3953       }
3954       return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
3955     }
3956   if (LocaleCompare(map,"BGRA") == 0)
3957     {
3958       for (y=0; y < (ssize_t) roi->height; y++)
3959       {
3960         q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
3961         if (q == (Quantum *) NULL)
3962           break;
3963         for (x=0; x < (ssize_t) roi->width; x++)
3964         {
3965           SetPixelBlue(image,ScaleShortToQuantum(*p++),q);
3966           SetPixelGreen(image,ScaleShortToQuantum(*p++),q);
3967           SetPixelRed(image,ScaleShortToQuantum(*p++),q);
3968           SetPixelAlpha(image,ScaleShortToQuantum(*p++),q);
3969           q+=GetPixelChannels(image);
3970         }
3971         if (SyncAuthenticPixels(image,exception) == MagickFalse)
3972           break;
3973       }
3974       return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
3975     }
3976   if (LocaleCompare(map,"BGRP") == 0)
3977     {
3978       for (y=0; y < (ssize_t) roi->height; y++)
3979       {
3980         q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
3981         if (q == (Quantum *) NULL)
3982           break;
3983         for (x=0; x < (ssize_t) roi->width; x++)
3984         {
3985           SetPixelBlue(image,ScaleShortToQuantum(*p++),q);
3986           SetPixelGreen(image,ScaleShortToQuantum(*p++),q);
3987           SetPixelRed(image,ScaleShortToQuantum(*p++),q);
3988           p++;
3989           q+=GetPixelChannels(image);
3990         }
3991         if (SyncAuthenticPixels(image,exception) == MagickFalse)
3992           break;
3993       }
3994       return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
3995     }
3996   if (LocaleCompare(map,"I") == 0)
3997     {
3998       for (y=0; y < (ssize_t) roi->height; y++)
3999       {
4000         q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
4001         if (q == (Quantum *) NULL)
4002           break;
4003         for (x=0; x < (ssize_t) roi->width; x++)
4004         {
4005           SetPixelGray(image,ScaleShortToQuantum(*p++),q);
4006           q+=GetPixelChannels(image);
4007         }
4008         if (SyncAuthenticPixels(image,exception) == MagickFalse)
4009           break;
4010       }
4011       return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
4012     }
4013   if (LocaleCompare(map,"RGB") == 0)
4014     {
4015       for (y=0; y < (ssize_t) roi->height; y++)
4016       {
4017         q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
4018         if (q == (Quantum *) NULL)
4019           break;
4020         for (x=0; x < (ssize_t) roi->width; x++)
4021         {
4022           SetPixelRed(image,ScaleShortToQuantum(*p++),q);
4023           SetPixelGreen(image,ScaleShortToQuantum(*p++),q);
4024           SetPixelBlue(image,ScaleShortToQuantum(*p++),q);
4025           q+=GetPixelChannels(image);
4026         }
4027         if (SyncAuthenticPixels(image,exception) == MagickFalse)
4028           break;
4029       }
4030       return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
4031     }
4032   if (LocaleCompare(map,"RGBA") == 0)
4033     {
4034       for (y=0; y < (ssize_t) roi->height; y++)
4035       {
4036         q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
4037         if (q == (Quantum *) NULL)
4038           break;
4039         for (x=0; x < (ssize_t) roi->width; x++)
4040         {
4041           SetPixelRed(image,ScaleShortToQuantum(*p++),q);
4042           SetPixelGreen(image,ScaleShortToQuantum(*p++),q);
4043           SetPixelBlue(image,ScaleShortToQuantum(*p++),q);
4044           SetPixelAlpha(image,ScaleShortToQuantum(*p++),q);
4045           q+=GetPixelChannels(image);
4046         }
4047         if (SyncAuthenticPixels(image,exception) == MagickFalse)
4048           break;
4049       }
4050       return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
4051     }
4052   if (LocaleCompare(map,"RGBP") == 0)
4053     {
4054       for (y=0; y < (ssize_t) roi->height; y++)
4055       {
4056         q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
4057         if (q == (Quantum *) NULL)
4058           break;
4059         for (x=0; x < (ssize_t) roi->width; x++)
4060         {
4061           SetPixelRed(image,ScaleShortToQuantum(*p++),q);
4062           SetPixelGreen(image,ScaleShortToQuantum(*p++),q);
4063           SetPixelBlue(image,ScaleShortToQuantum(*p++),q);
4064           p++;
4065           q+=GetPixelChannels(image);
4066         }
4067         if (SyncAuthenticPixels(image,exception) == MagickFalse)
4068           break;
4069       }
4070       return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
4071     }
4072   length=strlen(map);
4073   for (y=0; y < (ssize_t) roi->height; y++)
4074   {
4075     q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
4076     if (q == (Quantum *) NULL)
4077       break;
4078     for (x=0; x < (ssize_t) roi->width; x++)
4079     {
4080       ssize_t
4081         i;
4082 
4083       for (i=0; i < (ssize_t) length; i++)
4084       {
4085         switch (quantum_map[i])
4086         {
4087           case RedQuantum:
4088           case CyanQuantum:
4089           {
4090             SetPixelRed(image,ScaleShortToQuantum(*p),q);
4091             break;
4092           }
4093           case GreenQuantum:
4094           case MagentaQuantum:
4095           {
4096             SetPixelGreen(image,ScaleShortToQuantum(*p),q);
4097             break;
4098           }
4099           case BlueQuantum:
4100           case YellowQuantum:
4101           {
4102             SetPixelBlue(image,ScaleShortToQuantum(*p),q);
4103             break;
4104           }
4105           case AlphaQuantum:
4106           {
4107             SetPixelAlpha(image,ScaleShortToQuantum(*p),q);
4108             break;
4109           }
4110           case OpacityQuantum:
4111           {
4112             SetPixelAlpha(image,ScaleShortToQuantum(*p),q);
4113             break;
4114           }
4115           case BlackQuantum:
4116           {
4117             SetPixelBlack(image,ScaleShortToQuantum(*p),q);
4118             break;
4119           }
4120           case IndexQuantum:
4121           {
4122             SetPixelGray(image,ScaleShortToQuantum(*p),q);
4123             break;
4124           }
4125           default:
4126             break;
4127         }
4128         p++;
4129       }
4130       q+=GetPixelChannels(image);
4131     }
4132     if (SyncAuthenticPixels(image,exception) == MagickFalse)
4133       break;
4134   }
4135   return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
4136 }
4137 
ImportImagePixels(Image * image,const ssize_t x,const ssize_t y,const size_t width,const size_t height,const char * map,const StorageType type,const void * pixels,ExceptionInfo * exception)4138 MagickExport MagickBooleanType ImportImagePixels(Image *image,const ssize_t x,
4139   const ssize_t y,const size_t width,const size_t height,const char *map,
4140   const StorageType type,const void *pixels,ExceptionInfo *exception)
4141 {
4142   MagickBooleanType
4143     status;
4144 
4145   QuantumType
4146     *quantum_map;
4147 
4148   RectangleInfo
4149     roi;
4150 
4151   ssize_t
4152     i;
4153 
4154   size_t
4155     length;
4156 
4157   /*
4158     Allocate image structure.
4159   */
4160   assert(image != (Image *) NULL);
4161   assert(image->signature == MagickCoreSignature);
4162   if (image->debug != MagickFalse)
4163     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
4164   length=strlen(map);
4165   quantum_map=(QuantumType *) AcquireQuantumMemory(length,sizeof(*quantum_map));
4166   if (quantum_map == (QuantumType *) NULL)
4167     ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
4168       image->filename);
4169   for (i=0; i < (ssize_t) length; i++)
4170   {
4171     switch (map[i])
4172     {
4173       case 'a':
4174       case 'A':
4175       {
4176         quantum_map[i]=AlphaQuantum;
4177         image->alpha_trait=BlendPixelTrait;
4178         break;
4179       }
4180       case 'B':
4181       case 'b':
4182       {
4183         quantum_map[i]=BlueQuantum;
4184         break;
4185       }
4186       case 'C':
4187       case 'c':
4188       {
4189         quantum_map[i]=CyanQuantum;
4190         (void) SetImageColorspace(image,CMYKColorspace,exception);
4191         break;
4192       }
4193       case 'g':
4194       case 'G':
4195       {
4196         quantum_map[i]=GreenQuantum;
4197         break;
4198       }
4199       case 'K':
4200       case 'k':
4201       {
4202         quantum_map[i]=BlackQuantum;
4203         (void) SetImageColorspace(image,CMYKColorspace,exception);
4204         break;
4205       }
4206       case 'I':
4207       case 'i':
4208       {
4209         quantum_map[i]=IndexQuantum;
4210         (void) SetImageColorspace(image,GRAYColorspace,exception);
4211         break;
4212       }
4213       case 'm':
4214       case 'M':
4215       {
4216         quantum_map[i]=MagentaQuantum;
4217         (void) SetImageColorspace(image,CMYKColorspace,exception);
4218         break;
4219       }
4220       case 'O':
4221       case 'o':
4222       {
4223         quantum_map[i]=OpacityQuantum;
4224         image->alpha_trait=BlendPixelTrait;
4225         break;
4226       }
4227       case 'P':
4228       case 'p':
4229       {
4230         quantum_map[i]=UndefinedQuantum;
4231         break;
4232       }
4233       case 'R':
4234       case 'r':
4235       {
4236         quantum_map[i]=RedQuantum;
4237         break;
4238       }
4239       case 'Y':
4240       case 'y':
4241       {
4242         quantum_map[i]=YellowQuantum;
4243         (void) SetImageColorspace(image,CMYKColorspace,exception);
4244         break;
4245       }
4246       default:
4247       {
4248         quantum_map=(QuantumType *) RelinquishMagickMemory(quantum_map);
4249         (void) ThrowMagickException(exception,GetMagickModule(),OptionError,
4250           "UnrecognizedPixelMap","`%s'",map);
4251         return(MagickFalse);
4252       }
4253     }
4254   }
4255   if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
4256     return(MagickFalse);
4257   /*
4258     Transfer the pixels from the pixel data to the image.
4259   */
4260   roi.width=width;
4261   roi.height=height;
4262   roi.x=x;
4263   roi.y=y;
4264   switch (type)
4265   {
4266     case CharPixel:
4267     {
4268       status=ImportCharPixel(image,&roi,map,quantum_map,pixels,exception);
4269       break;
4270     }
4271     case DoublePixel:
4272     {
4273       status=ImportDoublePixel(image,&roi,map,quantum_map,pixels,exception);
4274       break;
4275     }
4276     case FloatPixel:
4277     {
4278       status=ImportFloatPixel(image,&roi,map,quantum_map,pixels,exception);
4279       break;
4280     }
4281     case LongPixel:
4282     {
4283       status=ImportLongPixel(image,&roi,map,quantum_map,pixels,exception);
4284       break;
4285     }
4286     case LongLongPixel:
4287     {
4288       status=ImportLongLongPixel(image,&roi,map,quantum_map,pixels,exception);
4289       break;
4290     }
4291     case QuantumPixel:
4292     {
4293       status=ImportQuantumPixel(image,&roi,map,quantum_map,pixels,exception);
4294       break;
4295     }
4296     case ShortPixel:
4297     {
4298       status=ImportShortPixel(image,&roi,map,quantum_map,pixels,exception);
4299       break;
4300     }
4301     default:
4302     {
4303       (void) ThrowMagickException(exception,GetMagickModule(),OptionError,
4304         "UnrecognizedStorageType","`%d'",type);
4305       status=MagickFalse;
4306     }
4307   }
4308   quantum_map=(QuantumType *) RelinquishMagickMemory(quantum_map);
4309   return(status);
4310 }
4311 
4312 /*
4313 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4314 %                                                                             %
4315 %                                                                             %
4316 %                                                                             %
4317 +   I n i t i a l i z e P i x e l C h a n n e l M a p                         %
4318 %                                                                             %
4319 %                                                                             %
4320 %                                                                             %
4321 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4322 %
4323 %  InitializePixelChannelMap() defines the standard pixel component map.
4324 %
4325 %  The format of the InitializePixelChannelMap() method is:
4326 %
4327 %      void InitializePixelChannelMap(Image *image)
4328 %
4329 %  A description of each parameter follows:
4330 %
4331 %    o image: the image.
4332 %
4333 */
InitializePixelChannelMap(Image * image)4334 MagickExport void InitializePixelChannelMap(Image *image)
4335 {
4336   PixelTrait
4337     trait;
4338 
4339   ssize_t
4340     i;
4341 
4342   ssize_t
4343     n;
4344 
4345   assert(image != (Image *) NULL);
4346   assert(image->signature == MagickCoreSignature);
4347   (void) memset(image->channel_map,0,MaxPixelChannels*
4348     sizeof(*image->channel_map));
4349   trait=UpdatePixelTrait;
4350   if (image->alpha_trait != UndefinedPixelTrait)
4351     trait=(PixelTrait) (trait | BlendPixelTrait);
4352   n=0;
4353   if ((image->colorspace == LinearGRAYColorspace) ||
4354       (image->colorspace == GRAYColorspace))
4355     {
4356       SetPixelChannelAttributes(image,BluePixelChannel,trait,n);
4357       SetPixelChannelAttributes(image,GreenPixelChannel,trait,n);
4358       SetPixelChannelAttributes(image,RedPixelChannel,trait,n++);
4359     }
4360   else
4361     {
4362       SetPixelChannelAttributes(image,RedPixelChannel,trait,n++);
4363       SetPixelChannelAttributes(image,GreenPixelChannel,trait,n++);
4364       SetPixelChannelAttributes(image,BluePixelChannel,trait,n++);
4365     }
4366   if (image->colorspace == CMYKColorspace)
4367     SetPixelChannelAttributes(image,BlackPixelChannel,trait,n++);
4368   for (i=0; i < (ssize_t) image->number_meta_channels; i++)
4369   {
4370     SetPixelChannelAttributes(image,(PixelChannel) n,UpdatePixelTrait,n);
4371     n++;
4372   }
4373   if (image->alpha_trait != UndefinedPixelTrait)
4374     SetPixelChannelAttributes(image,AlphaPixelChannel,CopyPixelTrait,n++);
4375   if (image->storage_class == PseudoClass)
4376     SetPixelChannelAttributes(image,IndexPixelChannel,CopyPixelTrait,n++);
4377   if ((image->channels & ReadMaskChannel) != 0)
4378     SetPixelChannelAttributes(image,ReadMaskPixelChannel,CopyPixelTrait,n++);
4379   if ((image->channels & WriteMaskChannel) != 0)
4380     SetPixelChannelAttributes(image,WriteMaskPixelChannel,CopyPixelTrait,n++);
4381   if ((image->channels & CompositeMaskChannel) != 0)
4382     SetPixelChannelAttributes(image,CompositeMaskPixelChannel,CopyPixelTrait,
4383       n++);
4384   image->number_channels=(size_t) n;
4385   (void) SetPixelChannelMask(image,image->channel_mask);
4386 }
4387 
4388 /*
4389 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4390 %                                                                             %
4391 %                                                                             %
4392 %                                                                             %
4393 %   I n t e r p o l a t e P i x e l C h a n n e l                             %
4394 %                                                                             %
4395 %                                                                             %
4396 %                                                                             %
4397 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4398 %
4399 %  InterpolatePixelChannel() applies a pixel interpolation method between a
4400 %  floating point coordinate and the pixels surrounding that coordinate.  No
4401 %  pixel area resampling, or scaling of the result is performed.
4402 %
4403 %  Interpolation is restricted to just the specified channel.
4404 %
4405 %  The format of the InterpolatePixelChannel method is:
4406 %
4407 %      MagickBooleanType InterpolatePixelChannel(
4408 %        const Image *magick_restrict image,const CacheView *image_view,
4409 %        const PixelChannel channel,const PixelInterpolateMethod method,
4410 %        const double x,const double y,double *pixel,ExceptionInfo *exception)
4411 %
4412 %  A description of each parameter follows:
4413 %
4414 %    o image: the image.
4415 %
4416 %    o image_view: the image view.
4417 %
4418 %    o channel: the pixel channel to interpolate.
4419 %
4420 %    o method: the pixel color interpolation method.
4421 %
4422 %    o x,y: A double representing the current (x,y) position of the pixel.
4423 %
4424 %    o pixel: return the interpolated pixel here.
4425 %
4426 %    o exception: return any errors or warnings in this structure.
4427 %
4428 */
4429 
CatromWeights(const double x,double (* weights)[4])4430 static inline void CatromWeights(const double x,double (*weights)[4])
4431 {
4432   double
4433     alpha,
4434     beta,
4435     gamma;
4436 
4437   /*
4438     Nicolas Robidoux' 10 flops (4* + 5- + 1+) refactoring of the computation
4439     of the standard four 1D Catmull-Rom weights. The sampling location is
4440     assumed between the second and third input pixel locations, and x is the
4441     position relative to the second input pixel location. Formulas originally
4442     derived for the VIPS (Virtual Image Processing System) library.
4443   */
4444   alpha=(double) 1.0-x;
4445   beta=(double) (-0.5)*x*alpha;
4446   (*weights)[0]=alpha*beta;
4447   (*weights)[3]=x*beta;
4448   /*
4449     The following computation of the inner weights from the outer ones work
4450     for all Keys cubics.
4451   */
4452   gamma=(*weights)[3]-(*weights)[0];
4453   (*weights)[1]=alpha-(*weights)[0]+gamma;
4454   (*weights)[2]=x-(*weights)[3]-gamma;
4455 }
4456 
SplineWeights(const double x,double (* weights)[4])4457 static inline void SplineWeights(const double x,double (*weights)[4])
4458 {
4459   double
4460     alpha,
4461     beta;
4462 
4463   /*
4464     Nicolas Robidoux' 12 flops (6* + 5- + 1+) refactoring of the computation
4465     of the standard four 1D cubic B-spline smoothing weights. The sampling
4466     location is assumed between the second and third input pixel locations,
4467     and x is the position relative to the second input pixel location.
4468   */
4469   alpha=(double) 1.0-x;
4470   (*weights)[3]=(double) (1.0/6.0)*x*x*x;
4471   (*weights)[0]=(double) (1.0/6.0)*alpha*alpha*alpha;
4472   beta=(*weights)[3]-(*weights)[0];
4473   (*weights)[1]=alpha-(*weights)[0]+beta;
4474   (*weights)[2]=x-(*weights)[3]-beta;
4475 }
4476 
MeshInterpolate(const PointInfo * delta,const double p,const double x,const double y)4477 static inline double MeshInterpolate(const PointInfo *delta,const double p,
4478   const double x,const double y)
4479 {
4480   return(delta->x*x+delta->y*y+(1.0-delta->x-delta->y)*p);
4481 }
4482 
InterpolatePixelChannel(const Image * magick_restrict image,const CacheView_ * image_view,const PixelChannel channel,const PixelInterpolateMethod method,const double x,const double y,double * pixel,ExceptionInfo * exception)4483 MagickExport MagickBooleanType InterpolatePixelChannel(
4484   const Image *magick_restrict image,const CacheView_ *image_view,
4485   const PixelChannel channel,const PixelInterpolateMethod method,
4486   const double x,const double y,double *pixel,ExceptionInfo *exception)
4487 {
4488   double
4489     alpha[16],
4490     gamma,
4491     pixels[16];
4492 
4493   MagickBooleanType
4494     status;
4495 
4496   PixelInterpolateMethod
4497     interpolate;
4498 
4499   PixelTrait
4500     traits;
4501 
4502   const Quantum
4503     *magick_restrict p;
4504 
4505   ssize_t
4506     i;
4507 
4508   ssize_t
4509     x_offset,
4510     y_offset;
4511 
4512   assert(image != (Image *) NULL);
4513   assert(image->signature == MagickCoreSignature);
4514   assert(image_view != (CacheView *) NULL);
4515   status=MagickTrue;
4516   *pixel=0.0;
4517   traits=GetPixelChannelTraits(image,channel);
4518   x_offset=CastDoubleToLong(floor(x));
4519   y_offset=CastDoubleToLong(floor(y));
4520   interpolate=method;
4521   if (interpolate == UndefinedInterpolatePixel)
4522     interpolate=image->interpolate;
4523   switch (interpolate)
4524   {
4525     case AverageInterpolatePixel:  /* nearest 4 neighbours */
4526     case Average9InterpolatePixel:  /* nearest 9 neighbours */
4527     case Average16InterpolatePixel:  /* nearest 16 neighbours */
4528     {
4529       ssize_t
4530         count;
4531 
4532       count=2;  /* size of the area to average - default nearest 4 */
4533       if (interpolate == Average9InterpolatePixel)
4534         {
4535           count=3;
4536           x_offset=CastDoubleToLong(floor(x+0.5)-1.0);
4537           y_offset=CastDoubleToLong(floor(y+0.5)-1.0);
4538         }
4539       else
4540         if (interpolate == Average16InterpolatePixel)
4541           {
4542             count=4;
4543             x_offset--;
4544             y_offset--;
4545           }
4546       p=GetCacheViewVirtualPixels(image_view,x_offset,y_offset,(size_t) count,
4547         (size_t) count,exception);
4548       if (p == (const Quantum *) NULL)
4549         {
4550           status=MagickFalse;
4551           break;
4552         }
4553       count*=count;  /* Number of pixels to average */
4554       if ((traits & BlendPixelTrait) == 0)
4555         for (i=0; i < (ssize_t) count; i++)
4556         {
4557           alpha[i]=1.0;
4558           pixels[i]=(double) p[i*GetPixelChannels(image)+channel];
4559         }
4560       else
4561         for (i=0; i < (ssize_t) count; i++)
4562         {
4563           alpha[i]=QuantumScale*GetPixelAlpha(image,p+i*
4564             GetPixelChannels(image));
4565           pixels[i]=alpha[i]*p[i*GetPixelChannels(image)+channel];
4566         }
4567       for (i=0; i < (ssize_t) count; i++)
4568       {
4569         gamma=PerceptibleReciprocal(alpha[i])/count;
4570         *pixel+=gamma*pixels[i];
4571       }
4572       break;
4573     }
4574     case BilinearInterpolatePixel:
4575     default:
4576     {
4577       PointInfo
4578         delta,
4579         epsilon;
4580 
4581       p=GetCacheViewVirtualPixels(image_view,x_offset,y_offset,2,2,exception);
4582       if (p == (const Quantum *) NULL)
4583         {
4584           status=MagickFalse;
4585           break;
4586         }
4587       if ((traits & BlendPixelTrait) == 0)
4588         for (i=0; i < 4; i++)
4589         {
4590           alpha[i]=1.0;
4591           pixels[i]=(double) p[i*GetPixelChannels(image)+channel];
4592         }
4593       else
4594         for (i=0; i < 4; i++)
4595         {
4596           alpha[i]=QuantumScale*GetPixelAlpha(image,p+i*
4597             GetPixelChannels(image));
4598           pixels[i]=alpha[i]*p[i*GetPixelChannels(image)+channel];
4599         }
4600       delta.x=x-x_offset;
4601       delta.y=y-y_offset;
4602       epsilon.x=1.0-delta.x;
4603       epsilon.y=1.0-delta.y;
4604       gamma=((epsilon.y*(epsilon.x*alpha[0]+delta.x*alpha[1])+delta.y*
4605         (epsilon.x*alpha[2]+delta.x*alpha[3])));
4606       gamma=PerceptibleReciprocal(gamma);
4607       *pixel=gamma*(epsilon.y*(epsilon.x*pixels[0]+delta.x*pixels[1])+delta.y*
4608         (epsilon.x*pixels[2]+delta.x*pixels[3]));
4609       break;
4610     }
4611     case BlendInterpolatePixel:
4612     {
4613       p=GetCacheViewVirtualPixels(image_view,x_offset,y_offset,2,2,exception);
4614       if (p == (const Quantum *) NULL)
4615         {
4616           status=MagickFalse;
4617           break;
4618         }
4619       if ((traits & BlendPixelTrait) == 0)
4620         for (i=0; i < 4; i++)
4621         {
4622           alpha[i]=1.0;
4623           pixels[i]=(MagickRealType) p[i*GetPixelChannels(image)+channel];
4624         }
4625       else
4626         for (i=0; i < 4; i++)
4627         {
4628           alpha[i]=QuantumScale*GetPixelAlpha(image,p+i*
4629             GetPixelChannels(image));
4630           pixels[i]=alpha[i]*p[i*GetPixelChannels(image)+channel];
4631         }
4632       gamma=1.0;  /* number of pixels blended together (its variable) */
4633       for (i=0; i <= 1L; i++) {
4634         if ((y-y_offset) >= 0.75)
4635           {
4636             alpha[i]=alpha[i+2];  /* take right pixels */
4637             pixels[i]=pixels[i+2];
4638           }
4639         else
4640           if ((y-y_offset) > 0.25)
4641             {
4642               gamma=2.0;  /* blend both pixels in row */
4643               alpha[i]+=alpha[i+2];  /* add up alpha weights */
4644               pixels[i]+=pixels[i+2];
4645             }
4646       }
4647       if ((x-x_offset) >= 0.75)
4648         {
4649           alpha[0]=alpha[1];  /* take bottom row blend */
4650           pixels[0]=pixels[1];
4651         }
4652       else
4653         if ((x-x_offset) > 0.25)
4654           {
4655             gamma*=2.0;  /* blend both rows */
4656             alpha[0]+=alpha[1];  /* add up alpha weights */
4657             pixels[0]+=pixels[1];
4658           }
4659       if (channel != AlphaPixelChannel)
4660         gamma=PerceptibleReciprocal(alpha[0]);  /* (color) 1/alpha_weights */
4661       else
4662         gamma=PerceptibleReciprocal(gamma);  /* (alpha) 1/number_of_pixels */
4663       *pixel=gamma*pixels[0];
4664       break;
4665     }
4666     case CatromInterpolatePixel:
4667     {
4668       double
4669         cx[4],
4670         cy[4];
4671 
4672       p=GetCacheViewVirtualPixels(image_view,x_offset-1,y_offset-1,4,4,
4673         exception);
4674       if (p == (const Quantum *) NULL)
4675         {
4676           status=MagickFalse;
4677           break;
4678         }
4679       if ((traits & BlendPixelTrait) == 0)
4680         for (i=0; i < 16; i++)
4681         {
4682           alpha[i]=1.0;
4683           pixels[i]=(double) p[i*GetPixelChannels(image)+channel];
4684         }
4685       else
4686         for (i=0; i < 16; i++)
4687         {
4688           alpha[i]=QuantumScale*GetPixelAlpha(image,p+i*
4689             GetPixelChannels(image));
4690           pixels[i]=alpha[i]*p[i*GetPixelChannels(image)+channel];
4691         }
4692       CatromWeights((double) (x-x_offset),&cx);
4693       CatromWeights((double) (y-y_offset),&cy);
4694       gamma=(channel == AlphaPixelChannel ? (double) 1.0 :
4695         PerceptibleReciprocal(cy[0]*(cx[0]*alpha[0]+cx[1]*alpha[1]+cx[2]*
4696         alpha[2]+cx[3]*alpha[3])+cy[1]*(cx[0]*alpha[4]+cx[1]*alpha[5]+cx[2]*
4697         alpha[6]+cx[3]*alpha[7])+cy[2]*(cx[0]*alpha[8]+cx[1]*alpha[9]+cx[2]*
4698         alpha[10]+cx[3]*alpha[11])+cy[3]*(cx[0]*alpha[12]+cx[1]*alpha[13]+
4699         cx[2]*alpha[14]+cx[3]*alpha[15])));
4700       *pixel=gamma*(cy[0]*(cx[0]*pixels[0]+cx[1]*pixels[1]+cx[2]*pixels[2]+
4701         cx[3]*pixels[3])+cy[1]*(cx[0]*pixels[4]+cx[1]*pixels[5]+cx[2]*
4702         pixels[6]+cx[3]*pixels[7])+cy[2]*(cx[0]*pixels[8]+cx[1]*pixels[9]+
4703         cx[2]*pixels[10]+cx[3]*pixels[11])+cy[3]*(cx[0]*pixels[12]+cx[1]*
4704         pixels[13]+cx[2]*pixels[14]+cx[3]*pixels[15]));
4705       break;
4706     }
4707     case IntegerInterpolatePixel:
4708     {
4709       p=GetCacheViewVirtualPixels(image_view,x_offset,y_offset,1,1,exception);
4710       if (p == (const Quantum *) NULL)
4711         {
4712           status=MagickFalse;
4713           break;
4714         }
4715       *pixel=(double) GetPixelChannel(image,channel,p);
4716       break;
4717     }
4718     case NearestInterpolatePixel:
4719     {
4720       x_offset=CastDoubleToLong(floor(x+0.5));
4721       y_offset=CastDoubleToLong(floor(y+0.5));
4722       p=GetCacheViewVirtualPixels(image_view,x_offset,y_offset,1,1,exception);
4723       if (p == (const Quantum *) NULL)
4724         {
4725           status=MagickFalse;
4726           break;
4727         }
4728       *pixel=(double) GetPixelChannel(image,channel,p);
4729       break;
4730     }
4731     case MeshInterpolatePixel:
4732     {
4733       PointInfo
4734         delta,
4735         luminance;
4736 
4737       p=GetCacheViewVirtualPixels(image_view,x_offset,y_offset,2,2,exception);
4738       if (p == (const Quantum *) NULL)
4739         {
4740           status=MagickFalse;
4741           break;
4742         }
4743       if ((traits & BlendPixelTrait) == 0)
4744         for (i=0; i < 4; i++)
4745         {
4746           alpha[i]=1.0;
4747           pixels[i]=(double) p[i*GetPixelChannels(image)+channel];
4748         }
4749       else
4750         for (i=0; i < 4; i++)
4751         {
4752           alpha[i]=QuantumScale*GetPixelAlpha(image,p+i*
4753             GetPixelChannels(image));
4754           pixels[i]=alpha[i]*p[i*GetPixelChannels(image)+channel];
4755         }
4756       delta.x=x-x_offset;
4757       delta.y=y-y_offset;
4758       luminance.x=GetPixelLuma(image,p)-(double)
4759         GetPixelLuma(image,p+3*GetPixelChannels(image));
4760       luminance.y=GetPixelLuma(image,p+GetPixelChannels(image))-(double)
4761         GetPixelLuma(image,p+2*GetPixelChannels(image));
4762       if (fabs((double) luminance.x) < fabs((double) luminance.y))
4763         {
4764           /*
4765             Diagonal 0-3 NW-SE.
4766           */
4767           if (delta.x <= delta.y)
4768             {
4769               /*
4770                 Bottom-left triangle (pixel: 2, diagonal: 0-3).
4771               */
4772               delta.y=1.0-delta.y;
4773               gamma=MeshInterpolate(&delta,alpha[2],alpha[3],alpha[0]);
4774               gamma=PerceptibleReciprocal(gamma);
4775               *pixel=gamma*MeshInterpolate(&delta,pixels[2],pixels[3],
4776                 pixels[0]);
4777             }
4778           else
4779             {
4780               /*
4781                 Top-right triangle (pixel: 1, diagonal: 0-3).
4782               */
4783               delta.x=1.0-delta.x;
4784               gamma=MeshInterpolate(&delta,alpha[1],alpha[0],alpha[3]);
4785               gamma=PerceptibleReciprocal(gamma);
4786               *pixel=gamma*MeshInterpolate(&delta,pixels[1],pixels[0],
4787                 pixels[3]);
4788             }
4789         }
4790       else
4791         {
4792           /*
4793             Diagonal 1-2 NE-SW.
4794           */
4795           if (delta.x <= (1.0-delta.y))
4796             {
4797               /*
4798                 Top-left triangle (pixel: 0, diagonal: 1-2).
4799               */
4800               gamma=MeshInterpolate(&delta,alpha[0],alpha[1],alpha[2]);
4801               gamma=PerceptibleReciprocal(gamma);
4802               *pixel=gamma*MeshInterpolate(&delta,pixels[0],pixels[1],
4803                 pixels[2]);
4804             }
4805           else
4806             {
4807               /*
4808                 Bottom-right triangle (pixel: 3, diagonal: 1-2).
4809               */
4810               delta.x=1.0-delta.x;
4811               delta.y=1.0-delta.y;
4812               gamma=MeshInterpolate(&delta,alpha[3],alpha[2],alpha[1]);
4813               gamma=PerceptibleReciprocal(gamma);
4814               *pixel=gamma*MeshInterpolate(&delta,pixels[3],pixels[2],
4815                 pixels[1]);
4816             }
4817         }
4818       break;
4819     }
4820     case SplineInterpolatePixel:
4821     {
4822       double
4823         cx[4],
4824         cy[4];
4825 
4826       p=GetCacheViewVirtualPixels(image_view,x_offset-1,y_offset-1,4,4,
4827         exception);
4828       if (p == (const Quantum *) NULL)
4829         {
4830           status=MagickFalse;
4831           break;
4832         }
4833       if ((traits & BlendPixelTrait) == 0)
4834         for (i=0; i < 16; i++)
4835         {
4836           alpha[i]=1.0;
4837           pixels[i]=(double) p[i*GetPixelChannels(image)+channel];
4838         }
4839       else
4840         for (i=0; i < 16; i++)
4841         {
4842           alpha[i]=QuantumScale*GetPixelAlpha(image,p+i*
4843             GetPixelChannels(image));
4844           pixels[i]=alpha[i]*p[i*GetPixelChannels(image)+channel];
4845         }
4846       SplineWeights((double) (x-x_offset),&cx);
4847       SplineWeights((double) (y-y_offset),&cy);
4848       gamma=(channel == AlphaPixelChannel ? (double) 1.0 :
4849         PerceptibleReciprocal(cy[0]*(cx[0]*alpha[0]+cx[1]*alpha[1]+cx[2]*
4850         alpha[2]+cx[3]*alpha[3])+cy[1]*(cx[0]*alpha[4]+cx[1]*alpha[5]+cx[2]*
4851         alpha[6]+cx[3]*alpha[7])+cy[2]*(cx[0]*alpha[8]+cx[1]*alpha[9]+cx[2]*
4852         alpha[10]+cx[3]*alpha[11])+cy[3]*(cx[0]*alpha[12]+cx[1]*alpha[13]+
4853         cx[2]*alpha[14]+cx[3]*alpha[15])));
4854       *pixel=gamma*(cy[0]*(cx[0]*pixels[0]+cx[1]*pixels[1]+cx[2]*pixels[2]+
4855         cx[3]*pixels[3])+cy[1]*(cx[0]*pixels[4]+cx[1]*pixels[5]+cx[2]*
4856         pixels[6]+cx[3]*pixels[7])+cy[2]*(cx[0]*pixels[8]+cx[1]*pixels[9]+
4857         cx[2]*pixels[10]+cx[3]*pixels[11])+cy[3]*(cx[0]*pixels[12]+cx[1]*
4858         pixels[13]+cx[2]*pixels[14]+cx[3]*pixels[15]));
4859       break;
4860     }
4861   }
4862   return(status);
4863 }
4864 
4865 /*
4866 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4867 %                                                                             %
4868 %                                                                             %
4869 %                                                                             %
4870 %   I n t e r p o l a t e P i x e l C h a n n e l s                           %
4871 %                                                                             %
4872 %                                                                             %
4873 %                                                                             %
4874 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4875 %
4876 %  InterpolatePixelChannels() applies a pixel interpolation method between a
4877 %  floating point coordinate and the pixels surrounding that coordinate.  No
4878 %  pixel area resampling, or scaling of the result is performed.
4879 %
4880 %  Interpolation is restricted to just the current channel setting of the
4881 %  destination image into which the color is to be stored
4882 %
4883 %  The format of the InterpolatePixelChannels method is:
4884 %
4885 %      MagickBooleanType InterpolatePixelChannels(
4886 %        const Image *magick_restrict source,const CacheView *source_view,
4887 %        const Image *magick_restrict destination,
4888 %        const PixelInterpolateMethod method,const double x,const double y,
4889 %        Quantum *pixel,ExceptionInfo *exception)
4890 %
4891 %  A description of each parameter follows:
4892 %
4893 %    o source: the source.
4894 %
4895 %    o source_view: the source view.
4896 %
4897 %    o destination: the destination image, for the interpolated color
4898 %
4899 %    o method: the pixel color interpolation method.
4900 %
4901 %    o x,y: A double representing the current (x,y) position of the pixel.
4902 %
4903 %    o pixel: return the interpolated pixel here.
4904 %
4905 %    o exception: return any errors or warnings in this structure.
4906 %
4907 */
InterpolatePixelChannels(const Image * magick_restrict source,const CacheView_ * source_view,const Image * magick_restrict destination,const PixelInterpolateMethod method,const double x,const double y,Quantum * pixel,ExceptionInfo * exception)4908 MagickExport MagickBooleanType InterpolatePixelChannels(
4909   const Image *magick_restrict source,const CacheView_ *source_view,
4910   const Image *magick_restrict destination,const PixelInterpolateMethod method,
4911   const double x,const double y,Quantum *pixel,ExceptionInfo *exception)
4912 {
4913   MagickBooleanType
4914     status;
4915 
4916   double
4917     alpha[16],
4918     gamma,
4919     pixels[16];
4920 
4921   const Quantum
4922     *magick_restrict p;
4923 
4924   ssize_t
4925     i;
4926 
4927   ssize_t
4928     x_offset,
4929     y_offset;
4930 
4931   PixelInterpolateMethod
4932     interpolate;
4933 
4934   assert(source != (Image *) NULL);
4935   assert(source->signature == MagickCoreSignature);
4936   assert(source_view != (CacheView *) NULL);
4937   status=MagickTrue;
4938   x_offset=CastDoubleToLong(floor(x));
4939   y_offset=CastDoubleToLong(floor(y));
4940   interpolate=method;
4941   if (interpolate == UndefinedInterpolatePixel)
4942     interpolate=source->interpolate;
4943   switch (interpolate)
4944   {
4945     case AverageInterpolatePixel:  /* nearest 4 neighbours */
4946     case Average9InterpolatePixel:  /* nearest 9 neighbours */
4947     case Average16InterpolatePixel:  /* nearest 16 neighbours */
4948     {
4949       ssize_t
4950         count;
4951 
4952       count=2;  /* size of the area to average - default nearest 4 */
4953       if (interpolate == Average9InterpolatePixel)
4954         {
4955           count=3;
4956           x_offset=CastDoubleToLong(floor(x+0.5)-1.0);
4957           y_offset=CastDoubleToLong(floor(y+0.5)-1.0);
4958         }
4959       else
4960         if (interpolate == Average16InterpolatePixel)
4961           {
4962             count=4;
4963             x_offset--;
4964             y_offset--;
4965           }
4966       p=GetCacheViewVirtualPixels(source_view,x_offset,y_offset,(size_t) count,
4967         (size_t) count,exception);
4968       if (p == (const Quantum *) NULL)
4969         {
4970           status=MagickFalse;
4971           break;
4972         }
4973       count*=count;  /* Number of pixels to average */
4974       for (i=0; i < (ssize_t) GetPixelChannels(source); i++)
4975       {
4976         double
4977           sum;
4978 
4979         ssize_t
4980           j;
4981 
4982         PixelChannel channel = GetPixelChannelChannel(source,i);
4983         PixelTrait traits = GetPixelChannelTraits(source,channel);
4984         PixelTrait destination_traits=GetPixelChannelTraits(destination,
4985           channel);
4986         if ((traits == UndefinedPixelTrait) ||
4987             (destination_traits == UndefinedPixelTrait))
4988           continue;
4989         for (j=0; j < (ssize_t) count; j++)
4990           pixels[j]=(double) p[j*GetPixelChannels(source)+i];
4991         sum=0.0;
4992         if ((traits & BlendPixelTrait) == 0)
4993           {
4994             for (j=0; j < (ssize_t) count; j++)
4995               sum+=pixels[j];
4996             sum/=count;
4997             SetPixelChannel(destination,channel,ClampToQuantum(sum),pixel);
4998             continue;
4999           }
5000         for (j=0; j < (ssize_t) count; j++)
5001         {
5002           alpha[j]=QuantumScale*GetPixelAlpha(source,p+j*
5003             GetPixelChannels(source));
5004           pixels[j]*=alpha[j];
5005           gamma=PerceptibleReciprocal(alpha[j]);
5006           sum+=gamma*pixels[j];
5007         }
5008         sum/=count;
5009         SetPixelChannel(destination,channel,ClampToQuantum(sum),pixel);
5010       }
5011       break;
5012     }
5013     case BilinearInterpolatePixel:
5014     default:
5015     {
5016       p=GetCacheViewVirtualPixels(source_view,x_offset,y_offset,2,2,exception);
5017       if (p == (const Quantum *) NULL)
5018         {
5019           status=MagickFalse;
5020           break;
5021         }
5022       for (i=0; i < (ssize_t) GetPixelChannels(source); i++)
5023       {
5024         PointInfo
5025           delta,
5026           epsilon;
5027 
5028         PixelChannel channel = GetPixelChannelChannel(source,i);
5029         PixelTrait traits = GetPixelChannelTraits(source,channel);
5030         PixelTrait destination_traits=GetPixelChannelTraits(destination,
5031           channel);
5032         if ((traits == UndefinedPixelTrait) ||
5033             (destination_traits == UndefinedPixelTrait))
5034           continue;
5035         delta.x=x-x_offset;
5036         delta.y=y-y_offset;
5037         epsilon.x=1.0-delta.x;
5038         epsilon.y=1.0-delta.y;
5039         pixels[0]=(double) p[i];
5040         pixels[1]=(double) p[GetPixelChannels(source)+i];
5041         pixels[2]=(double) p[2*GetPixelChannels(source)+i];
5042         pixels[3]=(double) p[3*GetPixelChannels(source)+i];
5043         if ((traits & BlendPixelTrait) == 0)
5044           {
5045             gamma=((epsilon.y*(epsilon.x+delta.x)+delta.y*(epsilon.x+delta.x)));
5046             gamma=PerceptibleReciprocal(gamma);
5047             SetPixelChannel(destination,channel,ClampToQuantum(gamma*(epsilon.y*
5048               (epsilon.x*pixels[0]+delta.x*pixels[1])+delta.y*(epsilon.x*
5049               pixels[2]+delta.x*pixels[3]))),pixel);
5050             continue;
5051           }
5052         alpha[0]=QuantumScale*GetPixelAlpha(source,p);
5053         alpha[1]=QuantumScale*GetPixelAlpha(source,p+GetPixelChannels(source));
5054         alpha[2]=QuantumScale*GetPixelAlpha(source,p+2*
5055           GetPixelChannels(source));
5056         alpha[3]=QuantumScale*GetPixelAlpha(source,p+3*
5057           GetPixelChannels(source));
5058         pixels[0]*=alpha[0];
5059         pixels[1]*=alpha[1];
5060         pixels[2]*=alpha[2];
5061         pixels[3]*=alpha[3];
5062         gamma=((epsilon.y*(epsilon.x*alpha[0]+delta.x*alpha[1])+delta.y*
5063           (epsilon.x*alpha[2]+delta.x*alpha[3])));
5064         gamma=PerceptibleReciprocal(gamma);
5065         SetPixelChannel(destination,channel,ClampToQuantum(gamma*(epsilon.y*
5066           (epsilon.x*pixels[0]+delta.x*pixels[1])+delta.y*(epsilon.x*pixels[2]+
5067           delta.x*pixels[3]))),pixel);
5068       }
5069       break;
5070     }
5071     case BlendInterpolatePixel:
5072     {
5073       p=GetCacheViewVirtualPixels(source_view,x_offset,y_offset,2,2,exception);
5074       if (p == (const Quantum *) NULL)
5075         {
5076           status=MagickFalse;
5077           break;
5078         }
5079       for (i=0; i < (ssize_t) GetPixelChannels(source); i++)
5080       {
5081         ssize_t
5082           j;
5083 
5084         PixelChannel channel = GetPixelChannelChannel(source,i);
5085         PixelTrait traits = GetPixelChannelTraits(source,channel);
5086         PixelTrait destination_traits=GetPixelChannelTraits(destination,
5087           channel);
5088         if ((traits == UndefinedPixelTrait) ||
5089             (destination_traits == UndefinedPixelTrait))
5090           continue;
5091         if (source->alpha_trait != BlendPixelTrait)
5092           for (j=0; j < 4; j++)
5093           {
5094             alpha[j]=1.0;
5095             pixels[j]=(double) p[j*GetPixelChannels(source)+i];
5096           }
5097         else
5098           for (j=0; j < 4; j++)
5099           {
5100             alpha[j]=QuantumScale*GetPixelAlpha(source,p+j*
5101               GetPixelChannels(source));
5102             pixels[j]=(double) p[j*GetPixelChannels(source)+i];
5103             if (channel != AlphaPixelChannel)
5104               pixels[j]*=alpha[j];
5105           }
5106         gamma=1.0;  /* number of pixels blended together (its variable) */
5107         for (j=0; j <= 1L; j++)
5108         {
5109           if ((y-y_offset) >= 0.75)
5110             {
5111               alpha[j]=alpha[j+2];  /* take right pixels */
5112               pixels[j]=pixels[j+2];
5113             }
5114           else
5115             if ((y-y_offset) > 0.25)
5116               {
5117                 gamma=2.0;  /* blend both pixels in row */
5118                 alpha[j]+=alpha[j+2];  /* add up alpha weights */
5119                 pixels[j]+=pixels[j+2];
5120               }
5121         }
5122         if ((x-x_offset) >= 0.75)
5123           {
5124             alpha[0]=alpha[1];  /* take bottom row blend */
5125             pixels[0]=pixels[1];
5126           }
5127         else
5128            if ((x-x_offset) > 0.25)
5129              {
5130                gamma*=2.0;  /* blend both rows */
5131                alpha[0]+=alpha[1];  /* add up alpha weights */
5132                pixels[0]+=pixels[1];
5133              }
5134         if (channel != AlphaPixelChannel)
5135           gamma=PerceptibleReciprocal(alpha[0]);  /* (color) 1/alpha_weights */
5136         else
5137           gamma=PerceptibleReciprocal(gamma);  /* (alpha) 1/number_of_pixels */
5138         SetPixelChannel(destination,channel,ClampToQuantum(gamma*pixels[0]),
5139           pixel);
5140       }
5141       break;
5142     }
5143     case CatromInterpolatePixel:
5144     {
5145       double
5146         cx[4],
5147         cy[4];
5148 
5149       p=GetCacheViewVirtualPixels(source_view,x_offset-1,y_offset-1,4,4,
5150         exception);
5151       if (p == (const Quantum *) NULL)
5152         {
5153           status=MagickFalse;
5154           break;
5155         }
5156       for (i=0; i < (ssize_t) GetPixelChannels(source); i++)
5157       {
5158         ssize_t
5159           j;
5160 
5161         PixelChannel channel = GetPixelChannelChannel(source,i);
5162         PixelTrait traits = GetPixelChannelTraits(source,channel);
5163         PixelTrait destination_traits=GetPixelChannelTraits(destination,
5164           channel);
5165         if ((traits == UndefinedPixelTrait) ||
5166             (destination_traits == UndefinedPixelTrait))
5167           continue;
5168         if ((traits & BlendPixelTrait) == 0)
5169           for (j=0; j < 16; j++)
5170           {
5171             alpha[j]=1.0;
5172             pixels[j]=(double) p[j*GetPixelChannels(source)+i];
5173           }
5174         else
5175           for (j=0; j < 16; j++)
5176           {
5177             alpha[j]=QuantumScale*GetPixelAlpha(source,p+j*
5178               GetPixelChannels(source));
5179             pixels[j]=alpha[j]*p[j*GetPixelChannels(source)+i];
5180           }
5181         CatromWeights((double) (x-x_offset),&cx);
5182         CatromWeights((double) (y-y_offset),&cy);
5183         gamma=((traits & BlendPixelTrait) ? (double) (1.0) :
5184           PerceptibleReciprocal(cy[0]*(cx[0]*alpha[0]+cx[1]*alpha[1]+cx[2]*
5185           alpha[2]+cx[3]*alpha[3])+cy[1]*(cx[0]*alpha[4]+cx[1]*alpha[5]+cx[2]*
5186           alpha[6]+cx[3]*alpha[7])+cy[2]*(cx[0]*alpha[8]+cx[1]*alpha[9]+cx[2]*
5187           alpha[10]+cx[3]*alpha[11])+cy[3]*(cx[0]*alpha[12]+cx[1]*alpha[13]+
5188           cx[2]*alpha[14]+cx[3]*alpha[15])));
5189         SetPixelChannel(destination,channel,ClampToQuantum(gamma*(cy[0]*(cx[0]*
5190           pixels[0]+cx[1]*pixels[1]+cx[2]*pixels[2]+cx[3]*pixels[3])+cy[1]*
5191           (cx[0]*pixels[4]+cx[1]*pixels[5]+cx[2]*pixels[6]+cx[3]*pixels[7])+
5192           cy[2]*(cx[0]*pixels[8]+cx[1]*pixels[9]+cx[2]*pixels[10]+cx[3]*
5193           pixels[11])+cy[3]*(cx[0]*pixels[12]+cx[1]*pixels[13]+cx[2]*
5194           pixels[14]+cx[3]*pixels[15]))),pixel);
5195       }
5196       break;
5197     }
5198     case IntegerInterpolatePixel:
5199     {
5200       p=GetCacheViewVirtualPixels(source_view,x_offset,y_offset,1,1,exception);
5201       if (p == (const Quantum *) NULL)
5202         {
5203           status=MagickFalse;
5204           break;
5205         }
5206       for (i=0; i < (ssize_t) GetPixelChannels(source); i++)
5207       {
5208         PixelChannel channel = GetPixelChannelChannel(source,i);
5209         PixelTrait traits = GetPixelChannelTraits(source,channel);
5210         PixelTrait destination_traits=GetPixelChannelTraits(destination,
5211           channel);
5212         if ((traits == UndefinedPixelTrait) ||
5213             (destination_traits == UndefinedPixelTrait))
5214           continue;
5215         SetPixelChannel(destination,channel,p[i],pixel);
5216       }
5217       break;
5218     }
5219     case NearestInterpolatePixel:
5220     {
5221       x_offset=CastDoubleToLong(floor(x+0.5));
5222       y_offset=CastDoubleToLong(floor(y+0.5));
5223       p=GetCacheViewVirtualPixels(source_view,x_offset,y_offset,1,1,exception);
5224       if (p == (const Quantum *) NULL)
5225         {
5226           status=MagickFalse;
5227           break;
5228         }
5229       for (i=0; i < (ssize_t) GetPixelChannels(source); i++)
5230       {
5231         PixelChannel channel = GetPixelChannelChannel(source,i);
5232         PixelTrait traits = GetPixelChannelTraits(source,channel);
5233         PixelTrait destination_traits=GetPixelChannelTraits(destination,
5234           channel);
5235         if ((traits == UndefinedPixelTrait) ||
5236             (destination_traits == UndefinedPixelTrait))
5237           continue;
5238         SetPixelChannel(destination,channel,p[i],pixel);
5239       }
5240       break;
5241     }
5242     case MeshInterpolatePixel:
5243     {
5244       p=GetCacheViewVirtualPixels(source_view,x_offset,y_offset,2,2,exception);
5245       if (p == (const Quantum *) NULL)
5246         {
5247           status=MagickFalse;
5248           break;
5249         }
5250       for (i=0; i < (ssize_t) GetPixelChannels(source); i++)
5251       {
5252         PointInfo
5253           delta,
5254           luminance;
5255 
5256         PixelChannel channel = GetPixelChannelChannel(source,i);
5257         PixelTrait traits = GetPixelChannelTraits(source,channel);
5258         PixelTrait destination_traits=GetPixelChannelTraits(destination,
5259           channel);
5260         if ((traits == UndefinedPixelTrait) ||
5261             (destination_traits == UndefinedPixelTrait))
5262           continue;
5263         pixels[0]=(double) p[i];
5264         pixels[1]=(double) p[GetPixelChannels(source)+i];
5265         pixels[2]=(double) p[2*GetPixelChannels(source)+i];
5266         pixels[3]=(double) p[3*GetPixelChannels(source)+i];
5267         if ((traits & BlendPixelTrait) == 0)
5268           {
5269             alpha[0]=1.0;
5270             alpha[1]=1.0;
5271             alpha[2]=1.0;
5272             alpha[3]=1.0;
5273           }
5274         else
5275           {
5276             alpha[0]=QuantumScale*GetPixelAlpha(source,p);
5277             alpha[1]=QuantumScale*GetPixelAlpha(source,p+
5278               GetPixelChannels(source));
5279             alpha[2]=QuantumScale*GetPixelAlpha(source,p+2*
5280               GetPixelChannels(source));
5281             alpha[3]=QuantumScale*GetPixelAlpha(source,p+3*
5282               GetPixelChannels(source));
5283           }
5284         delta.x=x-x_offset;
5285         delta.y=y-y_offset;
5286         luminance.x=fabs((double) (GetPixelLuma(source,p)-
5287           GetPixelLuma(source,p+3*GetPixelChannels(source))));
5288         luminance.y=fabs((double) (GetPixelLuma(source,p+
5289           GetPixelChannels(source))-GetPixelLuma(source,p+2*
5290           GetPixelChannels(source))));
5291         if (luminance.x < luminance.y)
5292           {
5293             /*
5294               Diagonal 0-3 NW-SE.
5295             */
5296             if (delta.x <= delta.y)
5297               {
5298                 /*
5299                   Bottom-left triangle (pixel: 2, diagonal: 0-3).
5300                 */
5301                 delta.y=1.0-delta.y;
5302                 gamma=MeshInterpolate(&delta,alpha[2],alpha[3],alpha[0]);
5303                 gamma=PerceptibleReciprocal(gamma);
5304                 SetPixelChannel(destination,channel,ClampToQuantum(gamma*
5305                   MeshInterpolate(&delta,pixels[2],pixels[3],pixels[0])),pixel);
5306               }
5307             else
5308               {
5309                 /*
5310                   Top-right triangle (pixel: 1, diagonal: 0-3).
5311                 */
5312                 delta.x=1.0-delta.x;
5313                 gamma=MeshInterpolate(&delta,alpha[1],alpha[0],alpha[3]);
5314                 gamma=PerceptibleReciprocal(gamma);
5315                 SetPixelChannel(destination,channel,ClampToQuantum(gamma*
5316                   MeshInterpolate(&delta,pixels[1],pixels[0],pixels[3])),pixel);
5317               }
5318           }
5319         else
5320           {
5321             /*
5322               Diagonal 1-2 NE-SW.
5323             */
5324             if (delta.x <= (1.0-delta.y))
5325               {
5326                 /*
5327                   Top-left triangle (pixel: 0, diagonal: 1-2).
5328                 */
5329                 gamma=MeshInterpolate(&delta,alpha[0],alpha[1],alpha[2]);
5330                 gamma=PerceptibleReciprocal(gamma);
5331                 SetPixelChannel(destination,channel,ClampToQuantum(gamma*
5332                   MeshInterpolate(&delta,pixels[0],pixels[1],pixels[2])),pixel);
5333               }
5334             else
5335               {
5336                 /*
5337                   Bottom-right triangle (pixel: 3, diagonal: 1-2).
5338                 */
5339                 delta.x=1.0-delta.x;
5340                 delta.y=1.0-delta.y;
5341                 gamma=MeshInterpolate(&delta,alpha[3],alpha[2],alpha[1]);
5342                 gamma=PerceptibleReciprocal(gamma);
5343                 SetPixelChannel(destination,channel,ClampToQuantum(gamma*
5344                   MeshInterpolate(&delta,pixels[3],pixels[2],pixels[1])),pixel);
5345               }
5346           }
5347       }
5348       break;
5349     }
5350     case SplineInterpolatePixel:
5351     {
5352       double
5353         cx[4],
5354         cy[4];
5355 
5356       p=GetCacheViewVirtualPixels(source_view,x_offset-1,y_offset-1,4,4,
5357         exception);
5358       if (p == (const Quantum *) NULL)
5359         {
5360           status=MagickFalse;
5361           break;
5362         }
5363       for (i=0; i < (ssize_t) GetPixelChannels(source); i++)
5364       {
5365         ssize_t
5366           j;
5367 
5368         PixelChannel channel = GetPixelChannelChannel(source,i);
5369         PixelTrait traits = GetPixelChannelTraits(source,channel);
5370         PixelTrait destination_traits=GetPixelChannelTraits(destination,
5371           channel);
5372         if ((traits == UndefinedPixelTrait) ||
5373             (destination_traits == UndefinedPixelTrait))
5374           continue;
5375         if ((traits & BlendPixelTrait) == 0)
5376           for (j=0; j < 16; j++)
5377           {
5378             alpha[j]=1.0;
5379             pixels[j]=(double) p[j*GetPixelChannels(source)+i];
5380           }
5381         else
5382           for (j=0; j < 16; j++)
5383           {
5384             alpha[j]=QuantumScale*GetPixelAlpha(source,p+j*
5385               GetPixelChannels(source));
5386             pixels[j]=alpha[j]*p[j*GetPixelChannels(source)+i];
5387           }
5388         SplineWeights((double) (x-x_offset),&cx);
5389         SplineWeights((double) (y-y_offset),&cy);
5390         gamma=((traits & BlendPixelTrait) ? (double) (1.0) :
5391           PerceptibleReciprocal(cy[0]*(cx[0]*alpha[0]+cx[1]*alpha[1]+cx[2]*
5392           alpha[2]+cx[3]*alpha[3])+cy[1]*(cx[0]*alpha[4]+cx[1]*alpha[5]+cx[2]*
5393           alpha[6]+cx[3]*alpha[7])+cy[2]*(cx[0]*alpha[8]+cx[1]*alpha[9]+cx[2]*
5394           alpha[10]+cx[3]*alpha[11])+cy[3]*(cx[0]*alpha[12]+cx[1]*alpha[13]+
5395           cx[2]*alpha[14]+cx[3]*alpha[15])));
5396         SetPixelChannel(destination,channel,ClampToQuantum(gamma*(cy[0]*(cx[0]*
5397           pixels[0]+cx[1]*pixels[1]+cx[2]*pixels[2]+cx[3]*pixels[3])+cy[1]*
5398           (cx[0]*pixels[4]+cx[1]*pixels[5]+cx[2]*pixels[6]+cx[3]*pixels[7])+
5399           cy[2]*(cx[0]*pixels[8]+cx[1]*pixels[9]+cx[2]*pixels[10]+cx[3]*
5400           pixels[11])+cy[3]*(cx[0]*pixels[12]+cx[1]*pixels[13]+cx[2]*
5401           pixels[14]+cx[3]*pixels[15]))),pixel);
5402       }
5403       break;
5404     }
5405   }
5406   return(status);
5407 }
5408 
5409 /*
5410 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5411 %                                                                             %
5412 %                                                                             %
5413 %                                                                             %
5414 %   I n t e r p o l a t e P i x e l I n f o                                   %
5415 %                                                                             %
5416 %                                                                             %
5417 %                                                                             %
5418 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5419 %
5420 %  InterpolatePixelInfo() applies a pixel interpolation method between a
5421 %  floating point coordinate and the pixels surrounding that coordinate.  No
5422 %  pixel area resampling, or scaling of the result is performed.
5423 %
5424 %  Interpolation is restricted to just RGBKA channels.
5425 %
5426 %  The format of the InterpolatePixelInfo method is:
5427 %
5428 %      MagickBooleanType InterpolatePixelInfo(const Image *image,
5429 %        const CacheView *image_view,const PixelInterpolateMethod method,
5430 %        const double x,const double y,PixelInfo *pixel,
5431 %        ExceptionInfo *exception)
5432 %
5433 %  A description of each parameter follows:
5434 %
5435 %    o image: the image.
5436 %
5437 %    o image_view: the image view.
5438 %
5439 %    o method: the pixel color interpolation method.
5440 %
5441 %    o x,y: A double representing the current (x,y) position of the pixel.
5442 %
5443 %    o pixel: return the interpolated pixel here.
5444 %
5445 %    o exception: return any errors or warnings in this structure.
5446 %
5447 */
5448 
AlphaBlendPixelInfo(const Image * image,const Quantum * pixel,PixelInfo * pixel_info,double * alpha)5449 static inline void AlphaBlendPixelInfo(const Image *image,
5450   const Quantum *pixel,PixelInfo *pixel_info,double *alpha)
5451 {
5452   if (image->alpha_trait == UndefinedPixelTrait)
5453     {
5454       *alpha=1.0;
5455       pixel_info->red=(double) GetPixelRed(image,pixel);
5456       pixel_info->green=(double) GetPixelGreen(image,pixel);
5457       pixel_info->blue=(double) GetPixelBlue(image,pixel);
5458       pixel_info->black=0.0;
5459       if (image->colorspace == CMYKColorspace)
5460         pixel_info->black=(double) GetPixelBlack(image,pixel);
5461       pixel_info->alpha=(double) GetPixelAlpha(image,pixel);
5462       return;
5463     }
5464   *alpha=QuantumScale*GetPixelAlpha(image,pixel);
5465   pixel_info->red=(*alpha*GetPixelRed(image,pixel));
5466   pixel_info->green=(*alpha*GetPixelGreen(image,pixel));
5467   pixel_info->blue=(*alpha*GetPixelBlue(image,pixel));
5468   pixel_info->black=0.0;
5469   if (image->colorspace == CMYKColorspace)
5470     pixel_info->black=(*alpha*GetPixelBlack(image,pixel));
5471   pixel_info->alpha=(double) GetPixelAlpha(image,pixel);
5472 }
5473 
InterpolatePixelInfo(const Image * image,const CacheView_ * image_view,const PixelInterpolateMethod method,const double x,const double y,PixelInfo * pixel,ExceptionInfo * exception)5474 MagickExport MagickBooleanType InterpolatePixelInfo(const Image *image,
5475   const CacheView_ *image_view,const PixelInterpolateMethod method,
5476   const double x,const double y,PixelInfo *pixel,ExceptionInfo *exception)
5477 {
5478   MagickBooleanType
5479     status;
5480 
5481   double
5482     alpha[16],
5483     gamma;
5484 
5485   PixelInfo
5486     pixels[16];
5487 
5488   const Quantum
5489     *p;
5490 
5491   ssize_t
5492     i;
5493 
5494   ssize_t
5495     x_offset,
5496     y_offset;
5497 
5498   PixelInterpolateMethod
5499     interpolate;
5500 
5501   assert(image != (Image *) NULL);
5502   assert(image->signature == MagickCoreSignature);
5503   assert(image_view != (CacheView *) NULL);
5504   status=MagickTrue;
5505   x_offset=CastDoubleToLong(floor(x));
5506   y_offset=CastDoubleToLong(floor(y));
5507   interpolate=method;
5508   if (interpolate == UndefinedInterpolatePixel)
5509     interpolate=image->interpolate;
5510   GetPixelInfoPixel(image,(const Quantum *) NULL,pixel);
5511   (void) memset(&pixels,0,sizeof(pixels));
5512   switch (interpolate)
5513   {
5514     case AverageInterpolatePixel:  /* nearest 4 neighbours */
5515     case Average9InterpolatePixel:  /* nearest 9 neighbours */
5516     case Average16InterpolatePixel:  /* nearest 16 neighbours */
5517     {
5518       ssize_t
5519         count;
5520 
5521       count=2;  /* size of the area to average - default nearest 4 */
5522       if (interpolate == Average9InterpolatePixel)
5523         {
5524           count=3;
5525           x_offset=CastDoubleToLong(floor(x+0.5)-1.0);
5526           y_offset=CastDoubleToLong(floor(y+0.5)-1.0);
5527         }
5528       else if (interpolate == Average16InterpolatePixel)
5529         {
5530           count=4;
5531           x_offset--;
5532           y_offset--;
5533         }
5534       p=GetCacheViewVirtualPixels(image_view,x_offset,y_offset,(size_t) count,
5535         (size_t) count,exception);
5536       if (p == (const Quantum *) NULL)
5537         {
5538           status=MagickFalse;
5539           break;
5540         }
5541       count*=count;  /* number of pixels - square of size */
5542       for (i=0; i < (ssize_t) count; i++)
5543       {
5544         AlphaBlendPixelInfo(image,p,pixels,alpha);
5545         gamma=PerceptibleReciprocal(alpha[0]);
5546         pixel->red+=gamma*pixels[0].red;
5547         pixel->green+=gamma*pixels[0].green;
5548         pixel->blue+=gamma*pixels[0].blue;
5549         pixel->black+=gamma*pixels[0].black;
5550         pixel->alpha+=pixels[0].alpha;
5551         p += GetPixelChannels(image);
5552       }
5553       gamma=1.0/count;   /* average weighting of each pixel in area */
5554       pixel->red*=gamma;
5555       pixel->green*=gamma;
5556       pixel->blue*=gamma;
5557       pixel->black*=gamma;
5558       pixel->alpha*=gamma;
5559       break;
5560     }
5561     case BackgroundInterpolatePixel:
5562     {
5563       *pixel=image->background_color;  /* Copy PixelInfo Structure  */
5564       break;
5565     }
5566     case BilinearInterpolatePixel:
5567     default:
5568     {
5569       PointInfo
5570         delta,
5571         epsilon;
5572 
5573       p=GetCacheViewVirtualPixels(image_view,x_offset,y_offset,2,2,exception);
5574       if (p == (const Quantum *) NULL)
5575         {
5576           status=MagickFalse;
5577           break;
5578         }
5579       for (i=0; i < 4L; i++)
5580         AlphaBlendPixelInfo(image,p+i*GetPixelChannels(image),pixels+i,alpha+i);
5581       delta.x=x-x_offset;
5582       delta.y=y-y_offset;
5583       epsilon.x=1.0-delta.x;
5584       epsilon.y=1.0-delta.y;
5585       gamma=((epsilon.y*(epsilon.x*alpha[0]+delta.x*alpha[1])+delta.y*
5586         (epsilon.x*alpha[2]+delta.x*alpha[3])));
5587       gamma=PerceptibleReciprocal(gamma);
5588       pixel->red=gamma*(epsilon.y*(epsilon.x*pixels[0].red+delta.x*
5589         pixels[1].red)+delta.y*(epsilon.x*pixels[2].red+delta.x*pixels[3].red));
5590       pixel->green=gamma*(epsilon.y*(epsilon.x*pixels[0].green+delta.x*
5591         pixels[1].green)+delta.y*(epsilon.x*pixels[2].green+delta.x*
5592         pixels[3].green));
5593       pixel->blue=gamma*(epsilon.y*(epsilon.x*pixels[0].blue+delta.x*
5594         pixels[1].blue)+delta.y*(epsilon.x*pixels[2].blue+delta.x*
5595         pixels[3].blue));
5596       if (image->colorspace == CMYKColorspace)
5597         pixel->black=gamma*(epsilon.y*(epsilon.x*pixels[0].black+delta.x*
5598           pixels[1].black)+delta.y*(epsilon.x*pixels[2].black+delta.x*
5599           pixels[3].black));
5600       gamma=((epsilon.y*(epsilon.x+delta.x)+delta.y*(epsilon.x+delta.x)));
5601       gamma=PerceptibleReciprocal(gamma);
5602       pixel->alpha=gamma*(epsilon.y*(epsilon.x*pixels[0].alpha+delta.x*
5603         pixels[1].alpha)+delta.y*(epsilon.x*pixels[2].alpha+delta.x*
5604         pixels[3].alpha));
5605       break;
5606     }
5607     case BlendInterpolatePixel:
5608     {
5609       p=GetCacheViewVirtualPixels(image_view,x_offset,y_offset,2,2,exception);
5610       if (p == (const Quantum *) NULL)
5611         {
5612           status=MagickFalse;
5613           break;
5614         }
5615       for (i=0; i < 4L; i++)
5616       {
5617         GetPixelInfoPixel(image,p+i*GetPixelChannels(image),pixels+i);
5618         AlphaBlendPixelInfo(image,p+i*GetPixelChannels(image),pixels+i,alpha+i);
5619       }
5620       gamma=1.0;  /* number of pixels blended together (its variable) */
5621       for (i=0; i <= 1L; i++)
5622       {
5623         if ((y-y_offset) >= 0.75)
5624           {
5625             alpha[i]=alpha[i+2];  /* take right pixels */
5626             pixels[i]=pixels[i+2];
5627           }
5628         else
5629           if ((y-y_offset) > 0.25)
5630             {
5631               gamma=2.0;  /* blend both pixels in row */
5632               alpha[i]+=alpha[i+2];  /* add up alpha weights */
5633               pixels[i].red+=pixels[i+2].red;
5634               pixels[i].green+=pixels[i+2].green;
5635               pixels[i].blue+=pixels[i+2].blue;
5636               pixels[i].black+=pixels[i+2].black;
5637               pixels[i].alpha+=pixels[i+2].alpha;
5638             }
5639       }
5640       if ((x-x_offset) >= 0.75)
5641         {
5642           alpha[0]=alpha[1];
5643           pixels[0]=pixels[1];
5644         }
5645       else
5646         if ((x-x_offset) > 0.25)
5647           {
5648             gamma*=2.0;  /* blend both rows */
5649             alpha[0]+= alpha[1];  /* add up alpha weights */
5650             pixels[0].red+=pixels[1].red;
5651             pixels[0].green+=pixels[1].green;
5652             pixels[0].blue+=pixels[1].blue;
5653             pixels[0].black+=pixels[1].black;
5654             pixels[0].alpha+=pixels[1].alpha;
5655           }
5656       gamma=1.0/gamma;
5657       alpha[0]=PerceptibleReciprocal(alpha[0]);
5658       pixel->red=alpha[0]*pixels[0].red;
5659       pixel->green=alpha[0]*pixels[0].green;  /* divide by sum of alpha */
5660       pixel->blue=alpha[0]*pixels[0].blue;
5661       pixel->black=alpha[0]*pixels[0].black;
5662       pixel->alpha=gamma*pixels[0].alpha;   /* divide by number of pixels */
5663       break;
5664     }
5665     case CatromInterpolatePixel:
5666     {
5667       double
5668         cx[4],
5669         cy[4];
5670 
5671       p=GetCacheViewVirtualPixels(image_view,x_offset-1,y_offset-1,4,4,
5672         exception);
5673       if (p == (const Quantum *) NULL)
5674         {
5675           status=MagickFalse;
5676           break;
5677         }
5678       for (i=0; i < 16L; i++)
5679         AlphaBlendPixelInfo(image,p+i*GetPixelChannels(image),pixels+i,alpha+i);
5680       CatromWeights((double) (x-x_offset),&cx);
5681       CatromWeights((double) (y-y_offset),&cy);
5682       pixel->red=(cy[0]*(cx[0]*pixels[0].red+cx[1]*pixels[1].red+cx[2]*
5683         pixels[2].red+cx[3]*pixels[3].red)+cy[1]*(cx[0]*pixels[4].red+cx[1]*
5684         pixels[5].red+cx[2]*pixels[6].red+cx[3]*pixels[7].red)+cy[2]*(cx[0]*
5685         pixels[8].red+cx[1]*pixels[9].red+cx[2]*pixels[10].red+cx[3]*
5686         pixels[11].red)+cy[3]*(cx[0]*pixels[12].red+cx[1]*pixels[13].red+cx[2]*
5687         pixels[14].red+cx[3]*pixels[15].red));
5688       pixel->green=(cy[0]*(cx[0]*pixels[0].green+cx[1]*pixels[1].green+cx[2]*
5689         pixels[2].green+cx[3]*pixels[3].green)+cy[1]*(cx[0]*pixels[4].green+
5690         cx[1]*pixels[5].green+cx[2]*pixels[6].green+cx[3]*pixels[7].green)+
5691         cy[2]*(cx[0]*pixels[8].green+cx[1]*pixels[9].green+cx[2]*
5692         pixels[10].green+cx[3]*pixels[11].green)+cy[3]*(cx[0]*
5693         pixels[12].green+cx[1]*pixels[13].green+cx[2]*pixels[14].green+cx[3]*
5694         pixels[15].green));
5695       pixel->blue=(cy[0]*(cx[0]*pixels[0].blue+cx[1]*pixels[1].blue+cx[2]*
5696         pixels[2].blue+cx[3]*pixels[3].blue)+cy[1]*(cx[0]*pixels[4].blue+cx[1]*
5697         pixels[5].blue+cx[2]*pixels[6].blue+cx[3]*pixels[7].blue)+cy[2]*(cx[0]*
5698         pixels[8].blue+cx[1]*pixels[9].blue+cx[2]*pixels[10].blue+cx[3]*
5699         pixels[11].blue)+cy[3]*(cx[0]*pixels[12].blue+cx[1]*pixels[13].blue+
5700         cx[2]*pixels[14].blue+cx[3]*pixels[15].blue));
5701       if (image->colorspace == CMYKColorspace)
5702         pixel->black=(cy[0]*(cx[0]*pixels[0].black+cx[1]*pixels[1].black+cx[2]*
5703           pixels[2].black+cx[3]*pixels[3].black)+cy[1]*(cx[0]*pixels[4].black+
5704           cx[1]*pixels[5].black+cx[2]*pixels[6].black+cx[3]*pixels[7].black)+
5705           cy[2]*(cx[0]*pixels[8].black+cx[1]*pixels[9].black+cx[2]*
5706           pixels[10].black+cx[3]*pixels[11].black)+cy[3]*(cx[0]*
5707           pixels[12].black+cx[1]*pixels[13].black+cx[2]*pixels[14].black+cx[3]*
5708           pixels[15].black));
5709       pixel->alpha=(cy[0]*(cx[0]*pixels[0].alpha+cx[1]*pixels[1].alpha+cx[2]*
5710         pixels[2].alpha+cx[3]*pixels[3].alpha)+cy[1]*(cx[0]*pixels[4].alpha+
5711         cx[1]*pixels[5].alpha+cx[2]*pixels[6].alpha+cx[3]*pixels[7].alpha)+
5712         cy[2]*(cx[0]*pixels[8].alpha+cx[1]*pixels[9].alpha+cx[2]*
5713         pixels[10].alpha+cx[3]*pixels[11].alpha)+cy[3]*(cx[0]*pixels[12].alpha+
5714         cx[1]*pixels[13].alpha+cx[2]*pixels[14].alpha+cx[3]*pixels[15].alpha));
5715       break;
5716     }
5717     case IntegerInterpolatePixel:
5718     {
5719       p=GetCacheViewVirtualPixels(image_view,x_offset,y_offset,1,1,exception);
5720       if (p == (const Quantum *) NULL)
5721         {
5722           status=MagickFalse;
5723           break;
5724         }
5725       GetPixelInfoPixel(image,p,pixel);
5726       break;
5727     }
5728     case MeshInterpolatePixel:
5729     {
5730       PointInfo
5731         delta,
5732         luminance;
5733 
5734       p=GetCacheViewVirtualPixels(image_view,x_offset,y_offset,2,2,exception);
5735       if (p == (const Quantum *) NULL)
5736         {
5737           status=MagickFalse;
5738           break;
5739         }
5740       delta.x=x-x_offset;
5741       delta.y=y-y_offset;
5742       luminance.x=GetPixelLuma(image,p)-(double)
5743         GetPixelLuma(image,p+3*GetPixelChannels(image));
5744       luminance.y=GetPixelLuma(image,p+GetPixelChannels(image))-(double)
5745         GetPixelLuma(image,p+2*GetPixelChannels(image));
5746       AlphaBlendPixelInfo(image,p,pixels+0,alpha+0);
5747       AlphaBlendPixelInfo(image,p+GetPixelChannels(image),pixels+1,alpha+1);
5748       AlphaBlendPixelInfo(image,p+2*GetPixelChannels(image),pixels+2,alpha+2);
5749       AlphaBlendPixelInfo(image,p+3*GetPixelChannels(image),pixels+3,alpha+3);
5750       if (fabs((double) luminance.x) < fabs((double) luminance.y))
5751         {
5752           /*
5753             Diagonal 0-3 NW-SE.
5754           */
5755           if (delta.x <= delta.y)
5756             {
5757               /*
5758                 Bottom-left triangle (pixel: 2, diagonal: 0-3).
5759               */
5760               delta.y=1.0-delta.y;
5761               gamma=MeshInterpolate(&delta,alpha[2],alpha[3],alpha[0]);
5762               gamma=PerceptibleReciprocal(gamma);
5763               pixel->red=gamma*MeshInterpolate(&delta,pixels[2].red,
5764                 pixels[3].red,pixels[0].red);
5765               pixel->green=gamma*MeshInterpolate(&delta,pixels[2].green,
5766                 pixels[3].green,pixels[0].green);
5767               pixel->blue=gamma*MeshInterpolate(&delta,pixels[2].blue,
5768                 pixels[3].blue,pixels[0].blue);
5769               if (image->colorspace == CMYKColorspace)
5770                 pixel->black=gamma*MeshInterpolate(&delta,pixels[2].black,
5771                   pixels[3].black,pixels[0].black);
5772               gamma=MeshInterpolate(&delta,1.0,1.0,1.0);
5773               pixel->alpha=gamma*MeshInterpolate(&delta,pixels[2].alpha,
5774                 pixels[3].alpha,pixels[0].alpha);
5775             }
5776           else
5777             {
5778               /*
5779                 Top-right triangle (pixel:1 , diagonal: 0-3).
5780               */
5781               delta.x=1.0-delta.x;
5782               gamma=MeshInterpolate(&delta,alpha[1],alpha[0],alpha[3]);
5783               gamma=PerceptibleReciprocal(gamma);
5784               pixel->red=gamma*MeshInterpolate(&delta,pixels[1].red,
5785                 pixels[0].red,pixels[3].red);
5786               pixel->green=gamma*MeshInterpolate(&delta,pixels[1].green,
5787                 pixels[0].green,pixels[3].green);
5788               pixel->blue=gamma*MeshInterpolate(&delta,pixels[1].blue,
5789                 pixels[0].blue,pixels[3].blue);
5790               if (image->colorspace == CMYKColorspace)
5791                 pixel->black=gamma*MeshInterpolate(&delta,pixels[1].black,
5792                   pixels[0].black,pixels[3].black);
5793               gamma=MeshInterpolate(&delta,1.0,1.0,1.0);
5794               pixel->alpha=gamma*MeshInterpolate(&delta,pixels[1].alpha,
5795                 pixels[0].alpha,pixels[3].alpha);
5796             }
5797         }
5798       else
5799         {
5800           /*
5801             Diagonal 1-2 NE-SW.
5802           */
5803           if (delta.x <= (1.0-delta.y))
5804             {
5805               /*
5806                 Top-left triangle (pixel: 0, diagonal: 1-2).
5807               */
5808               gamma=MeshInterpolate(&delta,alpha[0],alpha[1],alpha[2]);
5809               gamma=PerceptibleReciprocal(gamma);
5810               pixel->red=gamma*MeshInterpolate(&delta,pixels[0].red,
5811                 pixels[1].red,pixels[2].red);
5812               pixel->green=gamma*MeshInterpolate(&delta,pixels[0].green,
5813                 pixels[1].green,pixels[2].green);
5814               pixel->blue=gamma*MeshInterpolate(&delta,pixels[0].blue,
5815                 pixels[1].blue,pixels[2].blue);
5816               if (image->colorspace == CMYKColorspace)
5817                 pixel->black=gamma*MeshInterpolate(&delta,pixels[0].black,
5818                   pixels[1].black,pixels[2].black);
5819               gamma=MeshInterpolate(&delta,1.0,1.0,1.0);
5820               pixel->alpha=gamma*MeshInterpolate(&delta,pixels[0].alpha,
5821                 pixels[1].alpha,pixels[2].alpha);
5822             }
5823           else
5824             {
5825               /*
5826                 Bottom-right triangle (pixel: 3, diagonal: 1-2).
5827               */
5828               delta.x=1.0-delta.x;
5829               delta.y=1.0-delta.y;
5830               gamma=MeshInterpolate(&delta,alpha[3],alpha[2],alpha[1]);
5831               gamma=PerceptibleReciprocal(gamma);
5832               pixel->red=gamma*MeshInterpolate(&delta,pixels[3].red,
5833                 pixels[2].red,pixels[1].red);
5834               pixel->green=gamma*MeshInterpolate(&delta,pixels[3].green,
5835                 pixels[2].green,pixels[1].green);
5836               pixel->blue=gamma*MeshInterpolate(&delta,pixels[3].blue,
5837                 pixels[2].blue,pixels[1].blue);
5838               if (image->colorspace == CMYKColorspace)
5839                 pixel->black=gamma*MeshInterpolate(&delta,pixels[3].black,
5840                   pixels[2].black,pixels[1].black);
5841               gamma=MeshInterpolate(&delta,1.0,1.0,1.0);
5842               pixel->alpha=gamma*MeshInterpolate(&delta,pixels[3].alpha,
5843                 pixels[2].alpha,pixels[1].alpha);
5844             }
5845         }
5846       break;
5847     }
5848     case NearestInterpolatePixel:
5849     {
5850       x_offset=CastDoubleToLong(floor(x+0.5));
5851       y_offset=CastDoubleToLong(floor(y+0.5));
5852       p=GetCacheViewVirtualPixels(image_view,x_offset,y_offset,1,1,exception);
5853       if (p == (const Quantum *) NULL)
5854         {
5855           status=MagickFalse;
5856           break;
5857         }
5858       GetPixelInfoPixel(image,p,pixel);
5859       break;
5860     }
5861     case SplineInterpolatePixel:
5862     {
5863       double
5864         cx[4],
5865         cy[4];
5866 
5867       p=GetCacheViewVirtualPixels(image_view,x_offset-1,y_offset-1,4,4,
5868         exception);
5869       if (p == (const Quantum *) NULL)
5870         {
5871           status=MagickFalse;
5872           break;
5873         }
5874       for (i=0; i < 16L; i++)
5875         AlphaBlendPixelInfo(image,p+i*GetPixelChannels(image),pixels+i,alpha+i);
5876       SplineWeights((double) (x-x_offset),&cx);
5877       SplineWeights((double) (y-y_offset),&cy);
5878       pixel->red=(cy[0]*(cx[0]*pixels[0].red+cx[1]*pixels[1].red+cx[2]*
5879         pixels[2].red+cx[3]*pixels[3].red)+cy[1]*(cx[0]*pixels[4].red+cx[1]*
5880         pixels[5].red+cx[2]*pixels[6].red+cx[3]*pixels[7].red)+cy[2]*(cx[0]*
5881         pixels[8].red+cx[1]*pixels[9].red+cx[2]*pixels[10].red+cx[3]*
5882         pixels[11].red)+cy[3]*(cx[0]*pixels[12].red+cx[1]*pixels[13].red+cx[2]*
5883         pixels[14].red+cx[3]*pixels[15].red));
5884       pixel->green=(cy[0]*(cx[0]*pixels[0].green+cx[1]*pixels[1].green+cx[2]*
5885         pixels[2].green+cx[3]*pixels[3].green)+cy[1]*(cx[0]*pixels[4].green+
5886         cx[1]*pixels[5].green+cx[2]*pixels[6].green+cx[3]*pixels[7].green)+
5887         cy[2]*(cx[0]*pixels[8].green+cx[1]*pixels[9].green+cx[2]*
5888         pixels[10].green+cx[3]*pixels[11].green)+cy[3]*(cx[0]*pixels[12].green+
5889         cx[1]*pixels[13].green+cx[2]*pixels[14].green+cx[3]*pixels[15].green));
5890       pixel->blue=(cy[0]*(cx[0]*pixels[0].blue+cx[1]*pixels[1].blue+cx[2]*
5891         pixels[2].blue+cx[3]*pixels[3].blue)+cy[1]*(cx[0]*pixels[4].blue+cx[1]*
5892         pixels[5].blue+cx[2]*pixels[6].blue+cx[3]*pixels[7].blue)+cy[2]*(cx[0]*
5893         pixels[8].blue+cx[1]*pixels[9].blue+cx[2]*pixels[10].blue+cx[3]*
5894         pixels[11].blue)+cy[3]*(cx[0]*pixels[12].blue+cx[1]*pixels[13].blue+
5895         cx[2]*pixels[14].blue+cx[3]*pixels[15].blue));
5896       if (image->colorspace == CMYKColorspace)
5897         pixel->black=(cy[0]*(cx[0]*pixels[0].black+cx[1]*pixels[1].black+cx[2]*
5898           pixels[2].black+cx[3]*pixels[3].black)+cy[1]*(cx[0]*pixels[4].black+
5899           cx[1]*pixels[5].black+cx[2]*pixels[6].black+cx[3]*pixels[7].black)+
5900           cy[2]*(cx[0]*pixels[8].black+cx[1]*pixels[9].black+cx[2]*
5901           pixels[10].black+cx[3]*pixels[11].black)+cy[3]*(cx[0]*
5902           pixels[12].black+cx[1]*pixels[13].black+cx[2]*pixels[14].black+cx[3]*
5903           pixels[15].black));
5904       pixel->alpha=(cy[0]*(cx[0]*pixels[0].alpha+cx[1]*pixels[1].alpha+cx[2]*
5905         pixels[2].alpha+cx[3]*pixels[3].alpha)+cy[1]*(cx[0]*pixels[4].alpha+
5906         cx[1]*pixels[5].alpha+cx[2]*pixels[6].alpha+cx[3]*pixels[7].alpha)+
5907         cy[2]*(cx[0]*pixels[8].alpha+cx[1]*pixels[9].alpha+cx[2]*
5908         pixels[10].alpha+cx[3]*pixels[11].alpha)+cy[3]*(cx[0]*pixels[12].alpha+
5909         cx[1]*pixels[13].alpha+cx[2]*pixels[14].alpha+cx[3]*pixels[15].alpha));
5910       break;
5911     }
5912   }
5913   return(status);
5914 }
5915 
5916 /*
5917 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5918 %                                                                             %
5919 %                                                                             %
5920 %                                                                             %
5921 +   I s F u z z y E q u i v a l e n c e P i x e l                             %
5922 %                                                                             %
5923 %                                                                             %
5924 %                                                                             %
5925 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5926 %
5927 %  IsFuzzyEquivalencePixel() returns MagickTrue if the distance between two
5928 %  pixels is less than the specified distance in a linear three (or four)
5929 %  dimensional color space.
5930 %
5931 %  The format of the IsFuzzyEquivalencePixel method is:
5932 %
5933 %      void IsFuzzyEquivalencePixel(const Image *source,const Quantum *p,
5934 %        const Image *destination,const Quantum *q)
5935 %
5936 %  A description of each parameter follows:
5937 %
5938 %    o source: the source image.
5939 %
5940 %    o p: Pixel p.
5941 %
5942 %    o destination: the destination image.
5943 %
5944 %    o q: Pixel q.
5945 %
5946 */
IsFuzzyEquivalencePixel(const Image * source,const Quantum * p,const Image * destination,const Quantum * q)5947 MagickExport MagickBooleanType IsFuzzyEquivalencePixel(const Image *source,
5948   const Quantum *p,const Image *destination,const Quantum *q)
5949 {
5950   double
5951     fuzz,
5952     pixel;
5953 
5954   double
5955     distance,
5956     scale;
5957 
5958   fuzz=GetFuzzyColorDistance(source,destination);
5959   scale=1.0;
5960   distance=0.0;
5961   if (source->alpha_trait != UndefinedPixelTrait ||
5962       destination->alpha_trait != UndefinedPixelTrait)
5963     {
5964       /*
5965         Transparencies are involved - set alpha distance
5966       */
5967       pixel=GetPixelAlpha(source,p)-(double) GetPixelAlpha(destination,q);
5968       distance=pixel*pixel;
5969       if (distance > fuzz)
5970         return(MagickFalse);
5971       /*
5972         Generate a alpha scaling factor to generate a 4D cone on colorspace
5973         Note that if one color is transparent, distance has no color component.
5974       */
5975       if (source->alpha_trait != UndefinedPixelTrait)
5976         scale=QuantumScale*GetPixelAlpha(source,p);
5977       if (destination->alpha_trait != UndefinedPixelTrait)
5978         scale*=QuantumScale*GetPixelAlpha(destination,q);
5979       if (scale <= MagickEpsilon)
5980         return(MagickTrue);
5981     }
5982   /*
5983     RGB or CMY color cube
5984   */
5985   distance*=3.0;  /* rescale appropriately */
5986   fuzz*=3.0;
5987   pixel=GetPixelRed(source,p)-(double) GetPixelRed(destination,q);
5988   if (IsHueCompatibleColorspace(source->colorspace) != MagickFalse)
5989     {
5990       /*
5991         Compute an arc distance for hue.  It should be a vector angle of
5992         'S'/'W' length with 'L'/'B' forming appropriate cones.
5993       */
5994       if (fabs((double) pixel) > (QuantumRange/2))
5995         pixel-=QuantumRange;
5996       pixel*=2.0;
5997     }
5998   distance+=scale*pixel*pixel;
5999   if (distance > fuzz)
6000     return(MagickFalse);
6001   pixel=GetPixelGreen(source,p)-(double) GetPixelGreen(destination,q);
6002   distance+=scale*pixel*pixel;
6003   if (distance > fuzz)
6004     return(MagickFalse);
6005   pixel=GetPixelBlue(source,p)-(double) GetPixelBlue(destination,q);
6006   distance+=scale*pixel*pixel;
6007   if (distance > fuzz)
6008     return(MagickFalse);
6009   return(MagickTrue);
6010 }
6011 
6012 /*
6013 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6014 %                                                                             %
6015 %                                                                             %
6016 %                                                                             %
6017 +   I s F u z z y E q u i v a l e n c e P i x e l I n f o                     %
6018 %                                                                             %
6019 %                                                                             %
6020 %                                                                             %
6021 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6022 %
6023 %  IsFuzzyEquivalencePixelInfo() returns true if the distance between two
6024 %  colors is less than the specified distance in a linear three (or four)
6025 %  dimensional color space.
6026 %
6027 %  This implements the equivalent of:
6028 %    fuzz < sqrt(color_distance^2 * u.a*v.a  + alpha_distance^2)
6029 %
6030 %  Which produces a multi-dimensional cone for that colorspace along the
6031 %  transparency vector.
6032 %
6033 %  For example for an RGB:
6034 %    color_distance^2  = ( (u.r-v.r)^2 + (u.g-v.g)^2 + (u.b-v.b)^2 ) / 3
6035 %
6036 %  See https://imagemagick.org/Usage/bugs/fuzz_distance/
6037 %
6038 %  Hue colorspace distances need more work.  Hue is not a distance, it is an
6039 %  angle!
6040 %
6041 %  A check that q is in the same color space as p should be made and the
6042 %  appropriate mapping made.  -- Anthony Thyssen  8 December 2010
6043 %
6044 %  The format of the IsFuzzyEquivalencePixelInfo method is:
6045 %
6046 %      MagickBooleanType IsFuzzyEquivalencePixelInfo(const PixelInfo *p,
6047 %        const PixelInfo *q)
6048 %
6049 %  A description of each parameter follows:
6050 %
6051 %    o p: Pixel p.
6052 %
6053 %    o q: Pixel q.
6054 %
6055 */
IsFuzzyEquivalencePixelInfo(const PixelInfo * p,const PixelInfo * q)6056 MagickExport MagickBooleanType IsFuzzyEquivalencePixelInfo(const PixelInfo *p,
6057   const PixelInfo *q)
6058 {
6059   double
6060     fuzz,
6061     pixel;
6062 
6063   double
6064     scale,
6065     distance;
6066 
6067   fuzz=(double) MagickMax(MagickMax(p->fuzz,q->fuzz),(MagickRealType)
6068     MagickSQ1_2);
6069   fuzz*=fuzz;
6070   scale=1.0;
6071   distance=0.0;
6072   if ((p->alpha_trait != UndefinedPixelTrait) ||
6073       (q->alpha_trait != UndefinedPixelTrait))
6074     {
6075       /*
6076         Transparencies are involved - set alpha distance.
6077       */
6078       pixel=(p->alpha_trait != UndefinedPixelTrait ? p->alpha : OpaqueAlpha)-
6079         (q->alpha_trait != UndefinedPixelTrait ? q->alpha : OpaqueAlpha);
6080       distance=pixel*pixel;
6081       if (distance > fuzz)
6082         return(MagickFalse);
6083       /*
6084         Generate a alpha scaling factor to generate a 4D cone on colorspace.
6085         If one color is transparent, distance has no color component.
6086       */
6087       if (p->alpha_trait != UndefinedPixelTrait)
6088         scale=(QuantumScale*p->alpha);
6089       if (q->alpha_trait != UndefinedPixelTrait)
6090         scale*=(QuantumScale*q->alpha);
6091       if (scale <= MagickEpsilon )
6092         return(MagickTrue);
6093     }
6094   /*
6095     CMYK create a CMY cube with a multi-dimensional cone toward black.
6096   */
6097   if (p->colorspace == CMYKColorspace)
6098     {
6099       pixel=p->black-q->black;
6100       distance+=pixel*pixel*scale;
6101       if (distance > fuzz)
6102         return(MagickFalse);
6103       scale*=(double) (QuantumScale*(QuantumRange-p->black));
6104       scale*=(double) (QuantumScale*(QuantumRange-q->black));
6105     }
6106   /*
6107     RGB or CMY color cube.
6108   */
6109   distance*=3.0;  /* rescale appropriately */
6110   fuzz*=3.0;
6111   pixel=p->red-q->red;
6112   if (IsHueCompatibleColorspace(p->colorspace) != MagickFalse)
6113     {
6114       /*
6115         This calculates a arc distance for hue-- it should be a vector
6116         angle of 'S'/'W' length with 'L'/'B' forming appropriate cones.
6117         In other words this is a hack - Anthony.
6118       */
6119       if (fabs((double) pixel) > (QuantumRange/2))
6120         pixel-=QuantumRange;
6121       pixel*=2.0;
6122     }
6123   distance+=pixel*pixel*scale;
6124   if (distance > fuzz)
6125     return(MagickFalse);
6126   pixel=p->green-q->green;
6127   distance+=pixel*pixel*scale;
6128   if (distance > fuzz)
6129     return(MagickFalse);
6130   pixel=p->blue-q->blue;
6131   distance+=pixel*pixel*scale;
6132   if (distance > fuzz)
6133     return(MagickFalse);
6134   return(MagickTrue);
6135 }
6136 
6137 /*
6138 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6139 %                                                                             %
6140 %                                                                             %
6141 %                                                                             %
6142 %   S e t P i x e l C h a n n e l M a s k                                     %
6143 %                                                                             %
6144 %                                                                             %
6145 %                                                                             %
6146 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6147 %
6148 %  SetPixelChannelMask() sets the pixel channel map from the specified channel
6149 %  mask.
6150 %
6151 %  The format of the SetPixelChannelMask method is:
6152 %
6153 %      ChannelType SetPixelChannelMask(Image *image,
6154 %        const ChannelType channel_mask)
6155 %
6156 %  A description of each parameter follows:
6157 %
6158 %    o image: the image.
6159 %
6160 %    o channel_mask: the channel mask.
6161 %
6162 */
6163 
LogPixelChannels(const Image * image)6164 static void LogPixelChannels(const Image *image)
6165 {
6166   ssize_t
6167     i;
6168 
6169   (void) LogMagickEvent(PixelEvent,GetMagickModule(),"%s[%08x]",
6170     image->filename,image->channel_mask);
6171   for (i=0; i < (ssize_t) image->number_channels; i++)
6172   {
6173     char
6174       channel_name[MagickPathExtent],
6175       traits[MagickPathExtent];
6176 
6177     const char
6178       *name;
6179 
6180     PixelChannel
6181       channel;
6182 
6183     channel=GetPixelChannelChannel(image,i);
6184     switch (channel)
6185     {
6186       case RedPixelChannel:
6187       {
6188         name="red";
6189         if (image->colorspace == CMYKColorspace)
6190           name="cyan";
6191         if ((image->colorspace == LinearGRAYColorspace) ||
6192             (image->colorspace == GRAYColorspace))
6193           name="gray";
6194         break;
6195       }
6196       case GreenPixelChannel:
6197       {
6198         name="green";
6199         if (image->colorspace == CMYKColorspace)
6200           name="magenta";
6201         break;
6202       }
6203       case BluePixelChannel:
6204       {
6205         name="blue";
6206         if (image->colorspace == CMYKColorspace)
6207           name="yellow";
6208         break;
6209       }
6210       case BlackPixelChannel:
6211       {
6212         name="black";
6213         if (image->storage_class == PseudoClass)
6214           name="index";
6215         break;
6216       }
6217       case IndexPixelChannel:
6218       {
6219         name="index";
6220         break;
6221       }
6222       case AlphaPixelChannel:
6223       {
6224         name="alpha";
6225         break;
6226       }
6227       case ReadMaskPixelChannel:
6228       {
6229         name="read-mask";
6230         break;
6231       }
6232       case WriteMaskPixelChannel:
6233       {
6234         name="write-mask";
6235         break;
6236       }
6237       case CompositeMaskPixelChannel:
6238       {
6239         name="composite-mask";
6240         break;
6241       }
6242       case MetaPixelChannel:
6243       {
6244         name="meta";
6245         break;
6246       }
6247       default:
6248         name="undefined";
6249     }
6250     if (image->colorspace ==  UndefinedColorspace)
6251       {
6252         (void) FormatLocaleString(channel_name,MagickPathExtent,"%.20g",
6253           (double) channel);
6254         name=(const char *) channel_name;
6255       }
6256     *traits='\0';
6257     if ((GetPixelChannelTraits(image,channel) & UpdatePixelTrait) != 0)
6258       (void) ConcatenateMagickString(traits,"update,",MagickPathExtent);
6259     if ((GetPixelChannelTraits(image,channel) & BlendPixelTrait) != 0)
6260       (void) ConcatenateMagickString(traits,"blend,",MagickPathExtent);
6261     if ((GetPixelChannelTraits(image,channel) & CopyPixelTrait) != 0)
6262       (void) ConcatenateMagickString(traits,"copy,",MagickPathExtent);
6263     if (*traits == '\0')
6264       (void) ConcatenateMagickString(traits,"undefined,",MagickPathExtent);
6265     traits[strlen(traits)-1]='\0';
6266     (void) LogMagickEvent(PixelEvent,GetMagickModule(),"  %.20g: %s (%s)",
6267       (double) i,name,traits);
6268   }
6269 }
6270 
SetPixelChannelMask(Image * image,const ChannelType channel_mask)6271 MagickExport ChannelType SetPixelChannelMask(Image *image,
6272   const ChannelType channel_mask)
6273 {
6274 #define GetChannelBit(mask,bit)  (((size_t) (mask) >> (size_t) (bit)) & 0x01)
6275 
6276   ChannelType
6277     mask;
6278 
6279   ssize_t
6280     i;
6281 
6282   assert(image != (Image *) NULL);
6283   assert(image->signature == MagickCoreSignature);
6284   if (image->debug != MagickFalse)
6285     (void) LogMagickEvent(PixelEvent,GetMagickModule(),"%s[%08x]",
6286       image->filename,channel_mask);
6287   mask=image->channel_mask;
6288   image->channel_mask=channel_mask;
6289   for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
6290   {
6291     PixelChannel channel = GetPixelChannelChannel(image,i);
6292     if (GetChannelBit(channel_mask,channel) == 0)
6293       {
6294         SetPixelChannelTraits(image,channel,CopyPixelTrait);
6295         continue;
6296       }
6297     if (channel == AlphaPixelChannel)
6298       {
6299         if ((image->alpha_trait & CopyPixelTrait) != 0)
6300           {
6301             SetPixelChannelTraits(image,channel,CopyPixelTrait);
6302             continue;
6303           }
6304         SetPixelChannelTraits(image,channel,UpdatePixelTrait);
6305         continue;
6306       }
6307     if (image->alpha_trait != UndefinedPixelTrait)
6308       {
6309         SetPixelChannelTraits(image,channel,(const PixelTrait)
6310           (UpdatePixelTrait | BlendPixelTrait));
6311         continue;
6312       }
6313     SetPixelChannelTraits(image,channel,UpdatePixelTrait);
6314   }
6315   if (image->storage_class == PseudoClass)
6316     SetPixelChannelTraits(image,IndexPixelChannel,CopyPixelTrait);
6317   if ((image->channels & ReadMaskChannel) != 0)
6318     SetPixelChannelTraits(image,ReadMaskPixelChannel,CopyPixelTrait);
6319   if ((image->channels & WriteMaskChannel) != 0)
6320     SetPixelChannelTraits(image,WriteMaskPixelChannel,CopyPixelTrait);
6321   if ((image->channels & CompositeMaskChannel) != 0)
6322     SetPixelChannelTraits(image,CompositeMaskPixelChannel,CopyPixelTrait);
6323   if (image->debug != MagickFalse)
6324     LogPixelChannels(image);
6325   return(mask);
6326 }
6327 
6328 /*
6329 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6330 %                                                                             %
6331 %                                                                             %
6332 %                                                                             %
6333 %   S e t P i x e l M e t a C h a n n e l s                                   %
6334 %                                                                             %
6335 %                                                                             %
6336 %                                                                             %
6337 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6338 %
6339 %  SetPixelMetaChannels() sets the image meta channels.
6340 %
6341 %  The format of the SetPixelMetaChannels method is:
6342 %
6343 %      MagickBooleanType SetPixelMetaChannels(Image *image,
6344 %        const size_t number_meta_channels,ExceptionInfo *exception)
6345 %
6346 %  A description of each parameter follows:
6347 %
6348 %    o image: the image.
6349 %
6350 %    o number_meta_channels:  the number of meta channels.
6351 %
6352 %    o exception: return any errors or warnings in this structure.
6353 %
6354 */
SetPixelMetaChannels(Image * image,const size_t number_meta_channels,ExceptionInfo * exception)6355 MagickExport MagickBooleanType SetPixelMetaChannels(Image *image,
6356   const size_t number_meta_channels,ExceptionInfo *exception)
6357 {
6358   image->number_meta_channels=number_meta_channels;
6359   InitializePixelChannelMap(image);
6360   return(SyncImagePixelCache(image,exception));
6361 }
6362 
6363 /*
6364 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6365 %                                                                             %
6366 %                                                                             %
6367 %                                                                             %
6368 %   S o r t I m a g e P i x e l s                                             %
6369 %                                                                             %
6370 %                                                                             %
6371 %                                                                             %
6372 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6373 %
6374 %  SortImagePixels() sorts pixels within each scanline in ascending order of
6375 %  intensity.
6376 %
6377 %  The format of the SortImagePixels method is:
6378 %
6379 %      MagickBooleanType SortImagePixels(Image *image,ExceptionInfo *exception)
6380 %
6381 %  A description of each parameter follows:
6382 %
6383 %    o image: the image.
6384 %
6385 %    o exception: return any errors or warnings in this structure.
6386 %
6387 */
SortImagePixels(Image * image,ExceptionInfo * exception)6388 MagickExport MagickBooleanType SortImagePixels(Image *image,
6389   ExceptionInfo *exception)
6390 {
6391 #define SolarizeImageTag  "Solarize/Image"
6392 
6393   CacheView
6394     *image_view;
6395 
6396   MagickBooleanType
6397     status;
6398 
6399   MagickOffsetType
6400     progress;
6401 
6402   ssize_t
6403     y;
6404 
6405   /*
6406     Sort image pixels.
6407   */
6408   assert(image != (Image *) NULL);
6409   assert(image->signature == MagickCoreSignature);
6410   if (image->debug != MagickFalse)
6411     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
6412   status=MagickTrue;
6413   progress=0;
6414   image_view=AcquireAuthenticCacheView(image,exception);
6415 #if defined(MAGICKCORE_OPENMP_SUPPORT)
6416   #pragma omp parallel for schedule(static) shared(progress,status) \
6417     magick_number_threads(image,image,image->rows,1)
6418 #endif
6419   for (y=0; y < (ssize_t) image->rows; y++)
6420   {
6421     Quantum
6422       *magick_restrict q;
6423 
6424     ssize_t
6425       x;
6426 
6427     if (status == MagickFalse)
6428       continue;
6429     q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
6430     if (q == (Quantum *) NULL)
6431       {
6432         status=MagickFalse;
6433         continue;
6434       }
6435     for (x=0; x < (ssize_t) image->columns-1; x++)
6436     {
6437       MagickRealType
6438         current,
6439         previous;
6440 
6441       ssize_t
6442         j;
6443 
6444       previous=GetPixelIntensity(image,q);
6445       for (j=0; j < (ssize_t) (image->columns-x-1); j++)
6446       {
6447         current=GetPixelIntensity(image,q+(j+1)*GetPixelChannels(image));
6448         if (previous > current)
6449           {
6450             Quantum
6451               pixel[MaxPixelChannels];
6452 
6453             /*
6454               Swap adjacent pixels.
6455             */
6456             (void) memcpy(pixel,q+j*GetPixelChannels(image),
6457               GetPixelChannels(image)*sizeof(Quantum));
6458             (void) memcpy(q+j*GetPixelChannels(image),q+(j+1)*
6459               GetPixelChannels(image),GetPixelChannels(image)*sizeof(Quantum));
6460             (void) memcpy(q+(j+1)*GetPixelChannels(image),pixel,
6461               GetPixelChannels(image)*sizeof(Quantum));
6462           }
6463         else
6464           previous=current;
6465       }
6466     }
6467     if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
6468       status=MagickFalse;
6469     if (image->progress_monitor != (MagickProgressMonitor) NULL)
6470       {
6471         MagickBooleanType
6472           proceed;
6473 
6474 #if defined(MAGICKCORE_OPENMP_SUPPORT)
6475         #pragma omp atomic
6476 #endif
6477         progress++;
6478         proceed=SetImageProgress(image,SolarizeImageTag,progress,image->rows);
6479         if (proceed == MagickFalse)
6480           status=MagickFalse;
6481       }
6482   }
6483   image_view=DestroyCacheView(image_view);
6484   return(status);
6485 }
6486