• 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-2019 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   register 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 *) AcquireQuantumMemory(1,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))
222         ConvertRGBToCMYK(destination);
223     }
224   else
225     if (destination->colorspace == CMYKColorspace)
226       {
227         if (IssRGBCompatibleColorspace(image->colorspace))
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   register const Quantum
514     *magick_restrict p;
515 
516   register ssize_t
517     x;
518 
519   register 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       register 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   register const Quantum
721     *magick_restrict p;
722 
723   register double
724     *magick_restrict q;
725 
726   register 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       register 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   register const Quantum
929     *magick_restrict p;
930 
931   register float
932     *magick_restrict q;
933 
934   register 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       register 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   register const Quantum
1136     *magick_restrict p;
1137 
1138   register ssize_t
1139     x;
1140 
1141   register 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       register 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   register const Quantum
1343     *magick_restrict p;
1344 
1345   register ssize_t
1346     x;
1347 
1348   register 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       register 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   register const Quantum
1552     *magick_restrict p;
1553 
1554   register Quantum
1555     *magick_restrict q;
1556 
1557   register 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       register 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   register const Quantum
1762     *magick_restrict p;
1763 
1764   register ssize_t
1765     x;
1766 
1767   register 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       register 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   register 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   green=(MagickRealType) GetPixelGreen(image,pixel);
2369   blue=(MagickRealType) GetPixelBlue(image,pixel);
2370   switch (image->intensity)
2371   {
2372     case AveragePixelIntensityMethod:
2373     {
2374       intensity=(red+green+blue)/3.0;
2375       break;
2376     }
2377     case BrightnessPixelIntensityMethod:
2378     {
2379       intensity=MagickMax(MagickMax(red,green),blue);
2380       break;
2381     }
2382     case LightnessPixelIntensityMethod:
2383     {
2384       intensity=(MagickMin(MagickMin(red,green),blue)+
2385         MagickMax(MagickMax(red,green),blue))/2.0;
2386       break;
2387     }
2388     case MSPixelIntensityMethod:
2389     {
2390       intensity=(MagickRealType) (((double) red*red+green*green+blue*blue)/
2391         (3.0*QuantumRange));
2392       break;
2393     }
2394     case Rec601LumaPixelIntensityMethod:
2395     {
2396       if (image->colorspace == RGBColorspace)
2397         {
2398           red=EncodePixelGamma(red);
2399           green=EncodePixelGamma(green);
2400           blue=EncodePixelGamma(blue);
2401         }
2402       intensity=0.298839*red+0.586811*green+0.114350*blue;
2403       break;
2404     }
2405     case Rec601LuminancePixelIntensityMethod:
2406     {
2407       if (image->colorspace == sRGBColorspace)
2408         {
2409           red=DecodePixelGamma(red);
2410           green=DecodePixelGamma(green);
2411           blue=DecodePixelGamma(blue);
2412         }
2413       intensity=0.298839*red+0.586811*green+0.114350*blue;
2414       break;
2415     }
2416     case Rec709LumaPixelIntensityMethod:
2417     default:
2418     {
2419       if (image->colorspace == RGBColorspace)
2420         {
2421           red=EncodePixelGamma(red);
2422           green=EncodePixelGamma(green);
2423           blue=EncodePixelGamma(blue);
2424         }
2425       intensity=0.212656*red+0.715158*green+0.072186*blue;
2426       break;
2427     }
2428     case Rec709LuminancePixelIntensityMethod:
2429     {
2430       if (image->colorspace == sRGBColorspace)
2431         {
2432           red=DecodePixelGamma(red);
2433           green=DecodePixelGamma(green);
2434           blue=DecodePixelGamma(blue);
2435         }
2436       intensity=0.212656*red+0.715158*green+0.072186*blue;
2437       break;
2438     }
2439     case RMSPixelIntensityMethod:
2440     {
2441       intensity=(MagickRealType) (sqrt((double) red*red+green*green+blue*blue)/
2442         sqrt(3.0));
2443       break;
2444     }
2445   }
2446   return(intensity);
2447 }
2448 
2449 /*
2450 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2451 %                                                                             %
2452 %                                                                             %
2453 %                                                                             %
2454 %   I m p o r t I m a g e P i x e l s                                         %
2455 %                                                                             %
2456 %                                                                             %
2457 %                                                                             %
2458 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2459 %
2460 %  ImportImagePixels() accepts pixel data and stores in the image at the
2461 %  location you specify.  The method returns MagickTrue on success otherwise
2462 %  MagickFalse if an error is encountered.  The pixel data can be either char,
2463 %  Quantum, short int, unsigned int, unsigned long long, float, or double in
2464 %  the order specified by map.
2465 %
2466 %  Suppose your want to upload the first scanline of a 640x480 image from
2467 %  character data in red-green-blue order:
2468 %
2469 %      ImportImagePixels(image,0,0,640,1,"RGB",CharPixel,pixels);
2470 %
2471 %  The format of the ImportImagePixels method is:
2472 %
2473 %      MagickBooleanType ImportImagePixels(Image *image,const ssize_t x,
2474 %        const ssize_t y,const size_t width,const size_t height,
2475 %        const char *map,const StorageType type,const void *pixels,
2476 %        ExceptionInfo *exception)
2477 %
2478 %  A description of each parameter follows:
2479 %
2480 %    o image: the image.
2481 %
2482 %    o x,y,width,height:  These values define the perimeter
2483 %      of a region of pixels you want to define.
2484 %
2485 %    o map:  This string reflects the expected ordering of the pixel array.
2486 %      It can be any combination or order of R = red, G = green, B = blue,
2487 %      A = alpha (0 is transparent), O = opacity (0 is opaque), C = cyan,
2488 %      Y = yellow, M = magenta, K = black, I = intensity (for grayscale),
2489 %      P = pad.
2490 %
2491 %    o type: Define the data type of the pixels.  Float and double types are
2492 %      normalized to [0..1] otherwise [0..QuantumRange].  Choose from these
2493 %      types: CharPixel (char *), DoublePixel (double *), FloatPixel (float *),
2494 %      LongPixel (unsigned int *), LongLongPixel (unsigned long long *),
2495 %      QuantumPixel (Quantum *), or ShortPixel (unsigned short *).
2496 %
2497 %    o pixels: This array of values contain the pixel components as defined by
2498 %      map and type.  You must preallocate this array where the expected
2499 %      length varies depending on the values of width, height, map, and type.
2500 %
2501 %    o exception: return any errors or warnings in this structure.
2502 %
2503 */
2504 
ImportCharPixel(Image * image,const RectangleInfo * roi,const char * magick_restrict map,const QuantumType * quantum_map,const void * pixels,ExceptionInfo * exception)2505 static MagickBooleanType ImportCharPixel(Image *image,const RectangleInfo *roi,
2506   const char *magick_restrict map,const QuantumType *quantum_map,
2507   const void *pixels,ExceptionInfo *exception)
2508 {
2509   register const unsigned char
2510     *magick_restrict p;
2511 
2512   register Quantum
2513     *magick_restrict q;
2514 
2515   register ssize_t
2516     x;
2517 
2518   size_t
2519     length;
2520 
2521   ssize_t
2522     y;
2523 
2524   p=(const unsigned char *) pixels;
2525   if (LocaleCompare(map,"BGR") == 0)
2526     {
2527       for (y=0; y < (ssize_t) roi->height; y++)
2528       {
2529         q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
2530         if (q == (Quantum *) NULL)
2531           break;
2532         for (x=0; x < (ssize_t) roi->width; x++)
2533         {
2534           SetPixelBlue(image,ScaleCharToQuantum(*p++),q);
2535           SetPixelGreen(image,ScaleCharToQuantum(*p++),q);
2536           SetPixelRed(image,ScaleCharToQuantum(*p++),q);
2537           q+=GetPixelChannels(image);
2538         }
2539         if (SyncAuthenticPixels(image,exception) == MagickFalse)
2540           break;
2541       }
2542       return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
2543     }
2544   if (LocaleCompare(map,"BGRA") == 0)
2545     {
2546       for (y=0; y < (ssize_t) roi->height; y++)
2547       {
2548         q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
2549         if (q == (Quantum *) NULL)
2550           break;
2551         for (x=0; x < (ssize_t) roi->width; x++)
2552         {
2553           SetPixelBlue(image,ScaleCharToQuantum(*p++),q);
2554           SetPixelGreen(image,ScaleCharToQuantum(*p++),q);
2555           SetPixelRed(image,ScaleCharToQuantum(*p++),q);
2556           SetPixelAlpha(image,ScaleCharToQuantum(*p++),q);
2557           q+=GetPixelChannels(image);
2558         }
2559         if (SyncAuthenticPixels(image,exception) == MagickFalse)
2560           break;
2561       }
2562       return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
2563     }
2564   if (LocaleCompare(map,"BGRO") == 0)
2565     {
2566       for (y=0; y < (ssize_t) roi->height; y++)
2567       {
2568         q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
2569         if (q == (Quantum *) NULL)
2570           break;
2571         for (x=0; x < (ssize_t) roi->width; x++)
2572         {
2573           SetPixelBlue(image,ScaleCharToQuantum(*p++),q);
2574           SetPixelGreen(image,ScaleCharToQuantum(*p++),q);
2575           SetPixelRed(image,ScaleCharToQuantum(*p++),q);
2576           SetPixelAlpha(image,ScaleCharToQuantum(*p++),q);
2577           q+=GetPixelChannels(image);
2578         }
2579         if (SyncAuthenticPixels(image,exception) == MagickFalse)
2580           break;
2581       }
2582       return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
2583     }
2584   if (LocaleCompare(map,"BGRP") == 0)
2585     {
2586       for (y=0; y < (ssize_t) roi->height; y++)
2587       {
2588         q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
2589         if (q == (Quantum *) NULL)
2590           break;
2591         for (x=0; x < (ssize_t) roi->width; x++)
2592         {
2593           SetPixelBlue(image,ScaleCharToQuantum(*p++),q);
2594           SetPixelGreen(image,ScaleCharToQuantum(*p++),q);
2595           SetPixelRed(image,ScaleCharToQuantum(*p++),q);
2596           p++;
2597           q+=GetPixelChannels(image);
2598         }
2599         if (SyncAuthenticPixels(image,exception) == MagickFalse)
2600           break;
2601       }
2602       return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
2603     }
2604   if (LocaleCompare(map,"I") == 0)
2605     {
2606       for (y=0; y < (ssize_t) roi->height; y++)
2607       {
2608         q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
2609         if (q == (Quantum *) NULL)
2610           break;
2611         for (x=0; x < (ssize_t) roi->width; x++)
2612         {
2613           SetPixelGray(image,ScaleCharToQuantum(*p++),q);
2614           q+=GetPixelChannels(image);
2615         }
2616         if (SyncAuthenticPixels(image,exception) == MagickFalse)
2617           break;
2618       }
2619       return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
2620     }
2621   if (LocaleCompare(map,"RGB") == 0)
2622     {
2623       for (y=0; y < (ssize_t) roi->height; y++)
2624       {
2625         q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
2626         if (q == (Quantum *) NULL)
2627           break;
2628         for (x=0; x < (ssize_t) roi->width; x++)
2629         {
2630           SetPixelRed(image,ScaleCharToQuantum(*p++),q);
2631           SetPixelGreen(image,ScaleCharToQuantum(*p++),q);
2632           SetPixelBlue(image,ScaleCharToQuantum(*p++),q);
2633           q+=GetPixelChannels(image);
2634         }
2635         if (SyncAuthenticPixels(image,exception) == MagickFalse)
2636           break;
2637       }
2638       return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
2639     }
2640   if (LocaleCompare(map,"RGBA") == 0)
2641     {
2642       for (y=0; y < (ssize_t) roi->height; y++)
2643       {
2644         q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
2645         if (q == (Quantum *) NULL)
2646           break;
2647         for (x=0; x < (ssize_t) roi->width; x++)
2648         {
2649           SetPixelRed(image,ScaleCharToQuantum(*p++),q);
2650           SetPixelGreen(image,ScaleCharToQuantum(*p++),q);
2651           SetPixelBlue(image,ScaleCharToQuantum(*p++),q);
2652           SetPixelAlpha(image,ScaleCharToQuantum(*p++),q);
2653           q+=GetPixelChannels(image);
2654         }
2655         if (SyncAuthenticPixels(image,exception) == MagickFalse)
2656           break;
2657       }
2658       return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
2659     }
2660   if (LocaleCompare(map,"RGBO") == 0)
2661     {
2662       for (y=0; y < (ssize_t) roi->height; y++)
2663       {
2664         q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
2665         if (q == (Quantum *) NULL)
2666           break;
2667         for (x=0; x < (ssize_t) roi->width; x++)
2668         {
2669           SetPixelRed(image,ScaleCharToQuantum(*p++),q);
2670           SetPixelGreen(image,ScaleCharToQuantum(*p++),q);
2671           SetPixelBlue(image,ScaleCharToQuantum(*p++),q);
2672           SetPixelAlpha(image,ScaleCharToQuantum(*p++),q);
2673           q+=GetPixelChannels(image);
2674         }
2675         if (SyncAuthenticPixels(image,exception) == MagickFalse)
2676           break;
2677       }
2678       return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
2679     }
2680   if (LocaleCompare(map,"RGBP") == 0)
2681     {
2682       for (y=0; y < (ssize_t) roi->height; y++)
2683       {
2684         q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
2685         if (q == (Quantum *) NULL)
2686           break;
2687         for (x=0; x < (ssize_t) roi->width; x++)
2688         {
2689           SetPixelRed(image,ScaleCharToQuantum(*p++),q);
2690           SetPixelGreen(image,ScaleCharToQuantum(*p++),q);
2691           SetPixelBlue(image,ScaleCharToQuantum(*p++),q);
2692           p++;
2693           q+=GetPixelChannels(image);
2694         }
2695         if (SyncAuthenticPixels(image,exception) == MagickFalse)
2696           break;
2697       }
2698       return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
2699     }
2700   length=strlen(map);
2701   for (y=0; y < (ssize_t) roi->height; y++)
2702   {
2703     q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
2704     if (q == (Quantum *) NULL)
2705       break;
2706     for (x=0; x < (ssize_t) roi->width; x++)
2707     {
2708       register ssize_t
2709         i;
2710 
2711       for (i=0; i < (ssize_t) length; i++)
2712       {
2713         switch (quantum_map[i])
2714         {
2715           case RedQuantum:
2716           case CyanQuantum:
2717           {
2718             SetPixelRed(image,ScaleCharToQuantum(*p),q);
2719             break;
2720           }
2721           case GreenQuantum:
2722           case MagentaQuantum:
2723           {
2724             SetPixelGreen(image,ScaleCharToQuantum(*p),q);
2725             break;
2726           }
2727           case BlueQuantum:
2728           case YellowQuantum:
2729           {
2730             SetPixelBlue(image,ScaleCharToQuantum(*p),q);
2731             break;
2732           }
2733           case AlphaQuantum:
2734           {
2735             SetPixelAlpha(image,ScaleCharToQuantum(*p),q);
2736             break;
2737           }
2738           case OpacityQuantum:
2739           {
2740             SetPixelAlpha(image,ScaleCharToQuantum(*p),q);
2741             break;
2742           }
2743           case BlackQuantum:
2744           {
2745             SetPixelBlack(image,ScaleCharToQuantum(*p),q);
2746             break;
2747           }
2748           case IndexQuantum:
2749           {
2750             SetPixelGray(image,ScaleCharToQuantum(*p),q);
2751             break;
2752           }
2753           default:
2754             break;
2755         }
2756         p++;
2757       }
2758       q+=GetPixelChannels(image);
2759     }
2760     if (SyncAuthenticPixels(image,exception) == MagickFalse)
2761       break;
2762   }
2763   return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
2764 }
2765 
ImportDoublePixel(Image * image,const RectangleInfo * roi,const char * magick_restrict map,const QuantumType * quantum_map,const void * pixels,ExceptionInfo * exception)2766 static MagickBooleanType ImportDoublePixel(Image *image,
2767   const RectangleInfo *roi,const char *magick_restrict map,
2768   const QuantumType *quantum_map,const void *pixels,ExceptionInfo *exception)
2769 {
2770   register const double
2771     *magick_restrict p;
2772 
2773   register Quantum
2774     *magick_restrict q;
2775 
2776   register ssize_t
2777     x;
2778 
2779   size_t
2780     length;
2781 
2782   ssize_t
2783     y;
2784 
2785   p=(const double *) pixels;
2786   if (LocaleCompare(map,"BGR") == 0)
2787     {
2788       for (y=0; y < (ssize_t) roi->height; y++)
2789       {
2790         q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
2791         if (q == (Quantum *) NULL)
2792           break;
2793         for (x=0; x < (ssize_t) roi->width; x++)
2794         {
2795           SetPixelBlue(image,ClampToQuantum(QuantumRange*(*p)),q);
2796           p++;
2797           SetPixelGreen(image,ClampToQuantum(QuantumRange*(*p)),q);
2798           p++;
2799           SetPixelRed(image,ClampToQuantum(QuantumRange*(*p)),q);
2800           p++;
2801           q+=GetPixelChannels(image);
2802         }
2803         if (SyncAuthenticPixels(image,exception) == MagickFalse)
2804           break;
2805       }
2806       return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
2807     }
2808   if (LocaleCompare(map,"BGRA") == 0)
2809     {
2810       for (y=0; y < (ssize_t) roi->height; y++)
2811       {
2812         q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
2813         if (q == (Quantum *) NULL)
2814           break;
2815         for (x=0; x < (ssize_t) roi->width; x++)
2816         {
2817           SetPixelBlue(image,ClampToQuantum(QuantumRange*(*p)),q);
2818           p++;
2819           SetPixelGreen(image,ClampToQuantum(QuantumRange*(*p)),q);
2820           p++;
2821           SetPixelRed(image,ClampToQuantum(QuantumRange*(*p)),q);
2822           p++;
2823           SetPixelAlpha(image,ClampToQuantum(QuantumRange*(*p)),q);
2824           p++;
2825           q+=GetPixelChannels(image);
2826         }
2827         if (SyncAuthenticPixels(image,exception) == MagickFalse)
2828           break;
2829       }
2830       return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
2831     }
2832   if (LocaleCompare(map,"BGRP") == 0)
2833     {
2834       for (y=0; y < (ssize_t) roi->height; y++)
2835       {
2836         q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
2837         if (q == (Quantum *) NULL)
2838           break;
2839         for (x=0; x < (ssize_t) roi->width; x++)
2840         {
2841           SetPixelBlue(image,ClampToQuantum(QuantumRange*(*p)),q);
2842           p++;
2843           SetPixelGreen(image,ClampToQuantum(QuantumRange*(*p)),q);
2844           p++;
2845           SetPixelRed(image,ClampToQuantum(QuantumRange*(*p)),q);
2846           p++;
2847           p++;
2848           q+=GetPixelChannels(image);
2849         }
2850         if (SyncAuthenticPixels(image,exception) == MagickFalse)
2851           break;
2852       }
2853       return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
2854     }
2855   if (LocaleCompare(map,"I") == 0)
2856     {
2857       for (y=0; y < (ssize_t) roi->height; y++)
2858       {
2859         q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
2860         if (q == (Quantum *) NULL)
2861           break;
2862         for (x=0; x < (ssize_t) roi->width; x++)
2863         {
2864           SetPixelGray(image,ClampToQuantum(QuantumRange*(*p)),q);
2865           p++;
2866           q+=GetPixelChannels(image);
2867         }
2868         if (SyncAuthenticPixels(image,exception) == MagickFalse)
2869           break;
2870       }
2871       return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
2872     }
2873   if (LocaleCompare(map,"RGB") == 0)
2874     {
2875       for (y=0; y < (ssize_t) roi->height; y++)
2876       {
2877         q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
2878         if (q == (Quantum *) NULL)
2879           break;
2880         for (x=0; x < (ssize_t) roi->width; x++)
2881         {
2882           SetPixelRed(image,ClampToQuantum(QuantumRange*(*p)),q);
2883           p++;
2884           SetPixelGreen(image,ClampToQuantum(QuantumRange*(*p)),q);
2885           p++;
2886           SetPixelBlue(image,ClampToQuantum(QuantumRange*(*p)),q);
2887           p++;
2888           q+=GetPixelChannels(image);
2889         }
2890         if (SyncAuthenticPixels(image,exception) == MagickFalse)
2891           break;
2892       }
2893       return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
2894     }
2895   if (LocaleCompare(map,"RGBA") == 0)
2896     {
2897       for (y=0; y < (ssize_t) roi->height; y++)
2898       {
2899         q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
2900         if (q == (Quantum *) NULL)
2901           break;
2902         for (x=0; x < (ssize_t) roi->width; x++)
2903         {
2904           SetPixelRed(image,ClampToQuantum(QuantumRange*(*p)),q);
2905           p++;
2906           SetPixelGreen(image,ClampToQuantum(QuantumRange*(*p)),q);
2907           p++;
2908           SetPixelBlue(image,ClampToQuantum(QuantumRange*(*p)),q);
2909           p++;
2910           SetPixelAlpha(image,ClampToQuantum(QuantumRange*(*p)),q);
2911           p++;
2912           q+=GetPixelChannels(image);
2913         }
2914         if (SyncAuthenticPixels(image,exception) == MagickFalse)
2915           break;
2916       }
2917       return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
2918     }
2919   if (LocaleCompare(map,"RGBP") == 0)
2920     {
2921       for (y=0; y < (ssize_t) roi->height; y++)
2922       {
2923         q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
2924         if (q == (Quantum *) NULL)
2925           break;
2926         for (x=0; x < (ssize_t) roi->width; x++)
2927         {
2928           SetPixelRed(image,ClampToQuantum(QuantumRange*(*p)),q);
2929           p++;
2930           SetPixelGreen(image,ClampToQuantum(QuantumRange*(*p)),q);
2931           p++;
2932           SetPixelBlue(image,ClampToQuantum(QuantumRange*(*p)),q);
2933           p++;
2934           q+=GetPixelChannels(image);
2935         }
2936         if (SyncAuthenticPixels(image,exception) == MagickFalse)
2937           break;
2938       }
2939       return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
2940     }
2941    length=strlen(map);
2942   for (y=0; y < (ssize_t) roi->height; y++)
2943   {
2944     q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
2945     if (q == (Quantum *) NULL)
2946       break;
2947     for (x=0; x < (ssize_t) roi->width; x++)
2948     {
2949       register ssize_t
2950         i;
2951 
2952       for (i=0; i < (ssize_t) length; i++)
2953       {
2954         switch (quantum_map[i])
2955         {
2956           case RedQuantum:
2957           case CyanQuantum:
2958           {
2959             SetPixelRed(image,ClampToQuantum(QuantumRange*(*p)),q);
2960             break;
2961           }
2962           case GreenQuantum:
2963           case MagentaQuantum:
2964           {
2965             SetPixelGreen(image,ClampToQuantum(QuantumRange*(*p)),q);
2966             break;
2967           }
2968           case BlueQuantum:
2969           case YellowQuantum:
2970           {
2971             SetPixelBlue(image,ClampToQuantum(QuantumRange*(*p)),q);
2972             break;
2973           }
2974           case AlphaQuantum:
2975           {
2976             SetPixelAlpha(image,ClampToQuantum(QuantumRange*(*p)),q);
2977             break;
2978           }
2979           case OpacityQuantum:
2980           {
2981             SetPixelAlpha(image,ClampToQuantum(QuantumRange*(*p)),q);
2982             break;
2983           }
2984           case BlackQuantum:
2985           {
2986             SetPixelBlack(image,ClampToQuantum(QuantumRange*(*p)),q);
2987             break;
2988           }
2989           case IndexQuantum:
2990           {
2991             SetPixelGray(image,ClampToQuantum(QuantumRange*(*p)),q);
2992             break;
2993           }
2994           default:
2995             break;
2996         }
2997         p++;
2998       }
2999       q+=GetPixelChannels(image);
3000     }
3001     if (SyncAuthenticPixels(image,exception) == MagickFalse)
3002       break;
3003   }
3004   return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
3005 }
3006 
ImportFloatPixel(Image * image,const RectangleInfo * roi,const char * magick_restrict map,const QuantumType * quantum_map,const void * pixels,ExceptionInfo * exception)3007 static MagickBooleanType ImportFloatPixel(Image *image,const RectangleInfo *roi,
3008   const char *magick_restrict map,const QuantumType *quantum_map,
3009   const void *pixels,ExceptionInfo *exception)
3010 {
3011   register const float
3012     *magick_restrict p;
3013 
3014   register Quantum
3015     *magick_restrict q;
3016 
3017   register ssize_t
3018     x;
3019 
3020   size_t
3021     length;
3022 
3023   ssize_t
3024     y;
3025 
3026   p=(const float *) pixels;
3027   if (LocaleCompare(map,"BGR") == 0)
3028     {
3029       for (y=0; y < (ssize_t) roi->height; y++)
3030       {
3031         q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
3032         if (q == (Quantum *) NULL)
3033           break;
3034         for (x=0; x < (ssize_t) roi->width; x++)
3035         {
3036           SetPixelBlue(image,ClampToQuantum(QuantumRange*(*p)),q);
3037           p++;
3038           SetPixelGreen(image,ClampToQuantum(QuantumRange*(*p)),q);
3039           p++;
3040           SetPixelRed(image,ClampToQuantum(QuantumRange*(*p)),q);
3041           p++;
3042           q+=GetPixelChannels(image);
3043         }
3044         if (SyncAuthenticPixels(image,exception) == MagickFalse)
3045           break;
3046       }
3047       return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
3048     }
3049   if (LocaleCompare(map,"BGRA") == 0)
3050     {
3051       for (y=0; y < (ssize_t) roi->height; y++)
3052       {
3053         q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
3054         if (q == (Quantum *) NULL)
3055           break;
3056         for (x=0; x < (ssize_t) roi->width; x++)
3057         {
3058           SetPixelBlue(image,ClampToQuantum(QuantumRange*(*p)),q);
3059           p++;
3060           SetPixelGreen(image,ClampToQuantum(QuantumRange*(*p)),q);
3061           p++;
3062           SetPixelRed(image,ClampToQuantum(QuantumRange*(*p)),q);
3063           p++;
3064           SetPixelAlpha(image,ClampToQuantum(QuantumRange*(*p)),q);
3065           p++;
3066           q+=GetPixelChannels(image);
3067         }
3068         if (SyncAuthenticPixels(image,exception) == MagickFalse)
3069           break;
3070       }
3071       return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
3072     }
3073   if (LocaleCompare(map,"BGRP") == 0)
3074     {
3075       for (y=0; y < (ssize_t) roi->height; y++)
3076       {
3077         q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
3078         if (q == (Quantum *) NULL)
3079           break;
3080         for (x=0; x < (ssize_t) roi->width; x++)
3081         {
3082           SetPixelBlue(image,ClampToQuantum(QuantumRange*(*p)),q);
3083           p++;
3084           SetPixelGreen(image,ClampToQuantum(QuantumRange*(*p)),q);
3085           p++;
3086           SetPixelRed(image,ClampToQuantum(QuantumRange*(*p)),q);
3087           p++;
3088           p++;
3089           q+=GetPixelChannels(image);
3090         }
3091         if (SyncAuthenticPixels(image,exception) == MagickFalse)
3092           break;
3093       }
3094       return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
3095     }
3096   if (LocaleCompare(map,"I") == 0)
3097     {
3098       for (y=0; y < (ssize_t) roi->height; y++)
3099       {
3100         q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
3101         if (q == (Quantum *) NULL)
3102           break;
3103         for (x=0; x < (ssize_t) roi->width; x++)
3104         {
3105           SetPixelGray(image,ClampToQuantum(QuantumRange*(*p)),q);
3106           p++;
3107           q+=GetPixelChannels(image);
3108         }
3109         if (SyncAuthenticPixels(image,exception) == MagickFalse)
3110           break;
3111       }
3112       return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
3113     }
3114   if (LocaleCompare(map,"RGB") == 0)
3115     {
3116       for (y=0; y < (ssize_t) roi->height; y++)
3117       {
3118         q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
3119         if (q == (Quantum *) NULL)
3120           break;
3121         for (x=0; x < (ssize_t) roi->width; x++)
3122         {
3123           SetPixelRed(image,ClampToQuantum(QuantumRange*(*p)),q);
3124           p++;
3125           SetPixelGreen(image,ClampToQuantum(QuantumRange*(*p)),q);
3126           p++;
3127           SetPixelBlue(image,ClampToQuantum(QuantumRange*(*p)),q);
3128           p++;
3129           q+=GetPixelChannels(image);
3130         }
3131         if (SyncAuthenticPixels(image,exception) == MagickFalse)
3132           break;
3133       }
3134       return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
3135     }
3136   if (LocaleCompare(map,"RGBA") == 0)
3137     {
3138       for (y=0; y < (ssize_t) roi->height; y++)
3139       {
3140         q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
3141         if (q == (Quantum *) NULL)
3142           break;
3143         for (x=0; x < (ssize_t) roi->width; x++)
3144         {
3145           SetPixelRed(image,ClampToQuantum(QuantumRange*(*p)),q);
3146           p++;
3147           SetPixelGreen(image,ClampToQuantum(QuantumRange*(*p)),q);
3148           p++;
3149           SetPixelBlue(image,ClampToQuantum(QuantumRange*(*p)),q);
3150           p++;
3151           SetPixelAlpha(image,ClampToQuantum(QuantumRange*(*p)),q);
3152           p++;
3153           q+=GetPixelChannels(image);
3154         }
3155         if (SyncAuthenticPixels(image,exception) == MagickFalse)
3156           break;
3157       }
3158       return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
3159     }
3160   if (LocaleCompare(map,"RGBP") == 0)
3161     {
3162       for (y=0; y < (ssize_t) roi->height; y++)
3163       {
3164         q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
3165         if (q == (Quantum *) NULL)
3166           break;
3167         for (x=0; x < (ssize_t) roi->width; x++)
3168         {
3169           SetPixelRed(image,ClampToQuantum(QuantumRange*(*p)),q);
3170           p++;
3171           SetPixelGreen(image,ClampToQuantum(QuantumRange*(*p)),q);
3172           p++;
3173           SetPixelBlue(image,ClampToQuantum(QuantumRange*(*p)),q);
3174           p++;
3175           q+=GetPixelChannels(image);
3176         }
3177         if (SyncAuthenticPixels(image,exception) == MagickFalse)
3178           break;
3179       }
3180       return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
3181     }
3182   length=strlen(map);
3183   for (y=0; y < (ssize_t) roi->height; y++)
3184   {
3185     q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
3186     if (q == (Quantum *) NULL)
3187       break;
3188     for (x=0; x < (ssize_t) roi->width; x++)
3189     {
3190       register ssize_t
3191         i;
3192 
3193       for (i=0; i < (ssize_t) length; i++)
3194       {
3195         switch (quantum_map[i])
3196         {
3197           case RedQuantum:
3198           case CyanQuantum:
3199           {
3200             SetPixelRed(image,ClampToQuantum(QuantumRange*(*p)),q);
3201             break;
3202           }
3203           case GreenQuantum:
3204           case MagentaQuantum:
3205           {
3206             SetPixelGreen(image,ClampToQuantum(QuantumRange*(*p)),q);
3207             break;
3208           }
3209           case BlueQuantum:
3210           case YellowQuantum:
3211           {
3212             SetPixelBlue(image,ClampToQuantum(QuantumRange*(*p)),q);
3213             break;
3214           }
3215           case AlphaQuantum:
3216           {
3217             SetPixelAlpha(image,ClampToQuantum(QuantumRange*(*p)),q);
3218             break;
3219           }
3220           case OpacityQuantum:
3221           {
3222             SetPixelAlpha(image,ClampToQuantum(QuantumRange*(*p)),q);
3223             break;
3224           }
3225           case BlackQuantum:
3226           {
3227             SetPixelBlack(image,ClampToQuantum(QuantumRange*(*p)),q);
3228             break;
3229           }
3230           case IndexQuantum:
3231           {
3232             SetPixelGray(image,ClampToQuantum(QuantumRange*(*p)),q);
3233             break;
3234           }
3235           default:
3236             break;
3237         }
3238         p++;
3239       }
3240       q+=GetPixelChannels(image);
3241     }
3242     if (SyncAuthenticPixels(image,exception) == MagickFalse)
3243       break;
3244   }
3245   return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
3246 }
3247 
ImportLongPixel(Image * image,const RectangleInfo * roi,const char * magick_restrict map,const QuantumType * quantum_map,const void * pixels,ExceptionInfo * exception)3248 static MagickBooleanType ImportLongPixel(Image *image,const RectangleInfo *roi,
3249   const char *magick_restrict map,const QuantumType *quantum_map,
3250   const void *pixels,ExceptionInfo *exception)
3251 {
3252   register const unsigned int
3253     *magick_restrict p;
3254 
3255   register Quantum
3256     *magick_restrict q;
3257 
3258   register ssize_t
3259     x;
3260 
3261   size_t
3262     length;
3263 
3264   ssize_t
3265     y;
3266 
3267   p=(const unsigned int *) pixels;
3268   if (LocaleCompare(map,"BGR") == 0)
3269     {
3270       for (y=0; y < (ssize_t) roi->height; y++)
3271       {
3272         q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
3273         if (q == (Quantum *) NULL)
3274           break;
3275         for (x=0; x < (ssize_t) roi->width; x++)
3276         {
3277           SetPixelBlue(image,ScaleLongToQuantum(*p++),q);
3278           SetPixelGreen(image,ScaleLongToQuantum(*p++),q);
3279           SetPixelRed(image,ScaleLongToQuantum(*p++),q);
3280           q+=GetPixelChannels(image);
3281         }
3282         if (SyncAuthenticPixels(image,exception) == MagickFalse)
3283           break;
3284       }
3285       return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
3286     }
3287   if (LocaleCompare(map,"BGRA") == 0)
3288     {
3289       for (y=0; y < (ssize_t) roi->height; y++)
3290       {
3291         q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
3292         if (q == (Quantum *) NULL)
3293           break;
3294         for (x=0; x < (ssize_t) roi->width; x++)
3295         {
3296           SetPixelBlue(image,ScaleLongToQuantum(*p++),q);
3297           SetPixelGreen(image,ScaleLongToQuantum(*p++),q);
3298           SetPixelRed(image,ScaleLongToQuantum(*p++),q);
3299           SetPixelAlpha(image,ScaleLongToQuantum(*p++),q);
3300           q+=GetPixelChannels(image);
3301         }
3302         if (SyncAuthenticPixels(image,exception) == MagickFalse)
3303           break;
3304       }
3305       return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
3306     }
3307   if (LocaleCompare(map,"BGRP") == 0)
3308     {
3309       for (y=0; y < (ssize_t) roi->height; y++)
3310       {
3311         q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
3312         if (q == (Quantum *) NULL)
3313           break;
3314         for (x=0; x < (ssize_t) roi->width; x++)
3315         {
3316           SetPixelBlue(image,ScaleLongToQuantum(*p++),q);
3317           SetPixelGreen(image,ScaleLongToQuantum(*p++),q);
3318           SetPixelRed(image,ScaleLongToQuantum(*p++),q);
3319           p++;
3320           q+=GetPixelChannels(image);
3321         }
3322         if (SyncAuthenticPixels(image,exception) == MagickFalse)
3323           break;
3324       }
3325       return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
3326     }
3327   if (LocaleCompare(map,"I") == 0)
3328     {
3329       for (y=0; y < (ssize_t) roi->height; y++)
3330       {
3331         q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
3332         if (q == (Quantum *) NULL)
3333           break;
3334         for (x=0; x < (ssize_t) roi->width; x++)
3335         {
3336           SetPixelGray(image,ScaleLongToQuantum(*p++),q);
3337           q+=GetPixelChannels(image);
3338         }
3339         if (SyncAuthenticPixels(image,exception) == MagickFalse)
3340           break;
3341       }
3342       return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
3343     }
3344   if (LocaleCompare(map,"RGB") == 0)
3345     {
3346       for (y=0; y < (ssize_t) roi->height; y++)
3347       {
3348         q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
3349         if (q == (Quantum *) NULL)
3350           break;
3351         for (x=0; x < (ssize_t) roi->width; x++)
3352         {
3353           SetPixelRed(image,ScaleLongToQuantum(*p++),q);
3354           SetPixelGreen(image,ScaleLongToQuantum(*p++),q);
3355           SetPixelBlue(image,ScaleLongToQuantum(*p++),q);
3356           q+=GetPixelChannels(image);
3357         }
3358         if (SyncAuthenticPixels(image,exception) == MagickFalse)
3359           break;
3360       }
3361       return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
3362     }
3363   if (LocaleCompare(map,"RGBA") == 0)
3364     {
3365       for (y=0; y < (ssize_t) roi->height; y++)
3366       {
3367         q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
3368         if (q == (Quantum *) NULL)
3369           break;
3370         for (x=0; x < (ssize_t) roi->width; x++)
3371         {
3372           SetPixelRed(image,ScaleLongToQuantum(*p++),q);
3373           SetPixelGreen(image,ScaleLongToQuantum(*p++),q);
3374           SetPixelBlue(image,ScaleLongToQuantum(*p++),q);
3375           SetPixelAlpha(image,ScaleLongToQuantum(*p++),q);
3376           q+=GetPixelChannels(image);
3377         }
3378         if (SyncAuthenticPixels(image,exception) == MagickFalse)
3379           break;
3380       }
3381       return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
3382     }
3383   if (LocaleCompare(map,"RGBP") == 0)
3384     {
3385       for (y=0; y < (ssize_t) roi->height; y++)
3386       {
3387         q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
3388         if (q == (Quantum *) NULL)
3389           break;
3390         for (x=0; x < (ssize_t) roi->width; x++)
3391         {
3392           SetPixelRed(image,ScaleLongToQuantum(*p++),q);
3393           SetPixelGreen(image,ScaleLongToQuantum(*p++),q);
3394           SetPixelBlue(image,ScaleLongToQuantum(*p++),q);
3395           p++;
3396           q+=GetPixelChannels(image);
3397         }
3398         if (SyncAuthenticPixels(image,exception) == MagickFalse)
3399           break;
3400       }
3401       return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
3402     }
3403   length=strlen(map);
3404   for (y=0; y < (ssize_t) roi->height; y++)
3405   {
3406     q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
3407     if (q == (Quantum *) NULL)
3408       break;
3409     for (x=0; x < (ssize_t) roi->width; x++)
3410     {
3411       register ssize_t
3412         i;
3413 
3414       for (i=0; i < (ssize_t) length; i++)
3415       {
3416         switch (quantum_map[i])
3417         {
3418           case RedQuantum:
3419           case CyanQuantum:
3420           {
3421             SetPixelRed(image,ScaleLongToQuantum(*p),q);
3422             break;
3423           }
3424           case GreenQuantum:
3425           case MagentaQuantum:
3426           {
3427             SetPixelGreen(image,ScaleLongToQuantum(*p),q);
3428             break;
3429           }
3430           case BlueQuantum:
3431           case YellowQuantum:
3432           {
3433             SetPixelBlue(image,ScaleLongToQuantum(*p),q);
3434             break;
3435           }
3436           case AlphaQuantum:
3437           {
3438             SetPixelAlpha(image,ScaleLongToQuantum(*p),q);
3439             break;
3440           }
3441           case OpacityQuantum:
3442           {
3443             SetPixelAlpha(image,ScaleLongToQuantum(*p),q);
3444             break;
3445           }
3446           case BlackQuantum:
3447           {
3448             SetPixelBlack(image,ScaleLongToQuantum(*p),q);
3449             break;
3450           }
3451           case IndexQuantum:
3452           {
3453             SetPixelGray(image,ScaleLongToQuantum(*p),q);
3454             break;
3455           }
3456           default:
3457             break;
3458         }
3459         p++;
3460       }
3461       q+=GetPixelChannels(image);
3462     }
3463     if (SyncAuthenticPixels(image,exception) == MagickFalse)
3464       break;
3465   }
3466   return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
3467 }
3468 
ImportLongLongPixel(Image * image,const RectangleInfo * roi,const char * magick_restrict map,const QuantumType * quantum_map,const void * pixels,ExceptionInfo * exception)3469 static MagickBooleanType ImportLongLongPixel(Image *image,
3470   const RectangleInfo *roi,const char *magick_restrict map,
3471   const QuantumType *quantum_map,const void *pixels,ExceptionInfo *exception)
3472 {
3473   register const MagickSizeType
3474     *magick_restrict p;
3475 
3476   register Quantum
3477     *magick_restrict q;
3478 
3479   register ssize_t
3480     x;
3481 
3482   size_t
3483     length;
3484 
3485   ssize_t
3486     y;
3487 
3488   p=(const MagickSizeType *) pixels;
3489   if (LocaleCompare(map,"BGR") == 0)
3490     {
3491       for (y=0; y < (ssize_t) roi->height; y++)
3492       {
3493         q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
3494         if (q == (Quantum *) NULL)
3495           break;
3496         for (x=0; x < (ssize_t) roi->width; x++)
3497         {
3498           SetPixelBlue(image,ScaleLongLongToQuantum(*p++),q);
3499           SetPixelGreen(image,ScaleLongLongToQuantum(*p++),q);
3500           SetPixelRed(image,ScaleLongLongToQuantum(*p++),q);
3501           q+=GetPixelChannels(image);
3502         }
3503         if (SyncAuthenticPixels(image,exception) == MagickFalse)
3504           break;
3505       }
3506       return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
3507     }
3508   if (LocaleCompare(map,"BGRA") == 0)
3509     {
3510       for (y=0; y < (ssize_t) roi->height; y++)
3511       {
3512         q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
3513         if (q == (Quantum *) NULL)
3514           break;
3515         for (x=0; x < (ssize_t) roi->width; x++)
3516         {
3517           SetPixelBlue(image,ScaleLongLongToQuantum(*p++),q);
3518           SetPixelGreen(image,ScaleLongLongToQuantum(*p++),q);
3519           SetPixelRed(image,ScaleLongLongToQuantum(*p++),q);
3520           SetPixelAlpha(image,ScaleLongLongToQuantum(*p++),q);
3521           q+=GetPixelChannels(image);
3522         }
3523         if (SyncAuthenticPixels(image,exception) == MagickFalse)
3524           break;
3525       }
3526       return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
3527     }
3528   if (LocaleCompare(map,"BGRP") == 0)
3529     {
3530       for (y=0; y < (ssize_t) roi->height; y++)
3531       {
3532         q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
3533         if (q == (Quantum *) NULL)
3534           break;
3535         for (x=0; x < (ssize_t) roi->width; x++)
3536         {
3537           SetPixelBlue(image,ScaleLongLongToQuantum(*p++),q);
3538           SetPixelGreen(image,ScaleLongLongToQuantum(*p++),q);
3539           SetPixelRed(image,ScaleLongLongToQuantum(*p++),q);
3540           p++;
3541           q+=GetPixelChannels(image);
3542         }
3543         if (SyncAuthenticPixels(image,exception) == MagickFalse)
3544           break;
3545       }
3546       return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
3547     }
3548   if (LocaleCompare(map,"I") == 0)
3549     {
3550       for (y=0; y < (ssize_t) roi->height; y++)
3551       {
3552         q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
3553         if (q == (Quantum *) NULL)
3554           break;
3555         for (x=0; x < (ssize_t) roi->width; x++)
3556         {
3557           SetPixelGray(image,ScaleLongLongToQuantum(*p++),q);
3558           q+=GetPixelChannels(image);
3559         }
3560         if (SyncAuthenticPixels(image,exception) == MagickFalse)
3561           break;
3562       }
3563       return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
3564     }
3565   if (LocaleCompare(map,"RGB") == 0)
3566     {
3567       for (y=0; y < (ssize_t) roi->height; y++)
3568       {
3569         q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
3570         if (q == (Quantum *) NULL)
3571           break;
3572         for (x=0; x < (ssize_t) roi->width; x++)
3573         {
3574           SetPixelRed(image,ScaleLongLongToQuantum(*p++),q);
3575           SetPixelGreen(image,ScaleLongLongToQuantum(*p++),q);
3576           SetPixelBlue(image,ScaleLongLongToQuantum(*p++),q);
3577           q+=GetPixelChannels(image);
3578         }
3579         if (SyncAuthenticPixels(image,exception) == MagickFalse)
3580           break;
3581       }
3582       return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
3583     }
3584   if (LocaleCompare(map,"RGBA") == 0)
3585     {
3586       for (y=0; y < (ssize_t) roi->height; y++)
3587       {
3588         q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
3589         if (q == (Quantum *) NULL)
3590           break;
3591         for (x=0; x < (ssize_t) roi->width; x++)
3592         {
3593           SetPixelRed(image,ScaleLongLongToQuantum(*p++),q);
3594           SetPixelGreen(image,ScaleLongLongToQuantum(*p++),q);
3595           SetPixelBlue(image,ScaleLongLongToQuantum(*p++),q);
3596           SetPixelAlpha(image,ScaleLongLongToQuantum(*p++),q);
3597           q+=GetPixelChannels(image);
3598         }
3599         if (SyncAuthenticPixels(image,exception) == MagickFalse)
3600           break;
3601       }
3602       return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
3603     }
3604   if (LocaleCompare(map,"RGBP") == 0)
3605     {
3606       for (y=0; y < (ssize_t) roi->height; y++)
3607       {
3608         q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
3609         if (q == (Quantum *) NULL)
3610           break;
3611         for (x=0; x < (ssize_t) roi->width; x++)
3612         {
3613           SetPixelRed(image,ScaleLongLongToQuantum(*p++),q);
3614           SetPixelGreen(image,ScaleLongLongToQuantum(*p++),q);
3615           SetPixelBlue(image,ScaleLongLongToQuantum(*p++),q);
3616           p++;
3617           q+=GetPixelChannels(image);
3618         }
3619         if (SyncAuthenticPixels(image,exception) == MagickFalse)
3620           break;
3621       }
3622       return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
3623     }
3624   length=strlen(map);
3625   for (y=0; y < (ssize_t) roi->height; y++)
3626   {
3627     q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
3628     if (q == (Quantum *) NULL)
3629       break;
3630     for (x=0; x < (ssize_t) roi->width; x++)
3631     {
3632       register ssize_t
3633         i;
3634 
3635       for (i=0; i < (ssize_t) length; i++)
3636       {
3637         switch (quantum_map[i])
3638         {
3639           case RedQuantum:
3640           case CyanQuantum:
3641           {
3642             SetPixelRed(image,ScaleLongLongToQuantum(*p),q);
3643             break;
3644           }
3645           case GreenQuantum:
3646           case MagentaQuantum:
3647           {
3648             SetPixelGreen(image,ScaleLongLongToQuantum(*p),q);
3649             break;
3650           }
3651           case BlueQuantum:
3652           case YellowQuantum:
3653           {
3654             SetPixelBlue(image,ScaleLongLongToQuantum(*p),q);
3655             break;
3656           }
3657           case AlphaQuantum:
3658           {
3659             SetPixelAlpha(image,ScaleLongLongToQuantum(*p),q);
3660             break;
3661           }
3662           case OpacityQuantum:
3663           {
3664             SetPixelAlpha(image,ScaleLongLongToQuantum(*p),q);
3665             break;
3666           }
3667           case BlackQuantum:
3668           {
3669             SetPixelBlack(image,ScaleLongLongToQuantum(*p),q);
3670             break;
3671           }
3672           case IndexQuantum:
3673           {
3674             SetPixelGray(image,ScaleLongLongToQuantum(*p),q);
3675             break;
3676           }
3677           default:
3678             break;
3679         }
3680         p++;
3681       }
3682       q+=GetPixelChannels(image);
3683     }
3684     if (SyncAuthenticPixels(image,exception) == MagickFalse)
3685       break;
3686   }
3687   return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
3688 }
3689 
ImportQuantumPixel(Image * image,const RectangleInfo * roi,const char * magick_restrict map,const QuantumType * quantum_map,const void * pixels,ExceptionInfo * exception)3690 static MagickBooleanType ImportQuantumPixel(Image *image,
3691   const RectangleInfo *roi,const char *magick_restrict map,
3692   const QuantumType *quantum_map,const void *pixels,ExceptionInfo *exception)
3693 {
3694   register const Quantum
3695     *magick_restrict p;
3696 
3697   register Quantum
3698     *magick_restrict q;
3699 
3700   register ssize_t
3701     x;
3702 
3703   size_t
3704     length;
3705 
3706   ssize_t
3707     y;
3708 
3709   p=(const Quantum *) pixels;
3710   if (LocaleCompare(map,"BGR") == 0)
3711     {
3712       for (y=0; y < (ssize_t) roi->height; y++)
3713       {
3714         q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
3715         if (q == (Quantum *) NULL)
3716           break;
3717         for (x=0; x < (ssize_t) roi->width; x++)
3718         {
3719           SetPixelBlue(image,*p++,q);
3720           SetPixelGreen(image,*p++,q);
3721           SetPixelRed(image,*p++,q);
3722           q+=GetPixelChannels(image);
3723         }
3724         if (SyncAuthenticPixels(image,exception) == MagickFalse)
3725           break;
3726       }
3727       return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
3728     }
3729   if (LocaleCompare(map,"BGRA") == 0)
3730     {
3731       for (y=0; y < (ssize_t) roi->height; y++)
3732       {
3733         q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
3734         if (q == (Quantum *) NULL)
3735           break;
3736         for (x=0; x < (ssize_t) roi->width; x++)
3737         {
3738           SetPixelBlue(image,*p++,q);
3739           SetPixelGreen(image,*p++,q);
3740           SetPixelRed(image,*p++,q);
3741           SetPixelAlpha(image,*p++,q);
3742           q+=GetPixelChannels(image);
3743         }
3744         if (SyncAuthenticPixels(image,exception) == MagickFalse)
3745           break;
3746       }
3747       return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
3748     }
3749   if (LocaleCompare(map,"BGRP") == 0)
3750     {
3751       for (y=0; y < (ssize_t) roi->height; y++)
3752       {
3753         q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
3754         if (q == (Quantum *) NULL)
3755           break;
3756         for (x=0; x < (ssize_t) roi->width; x++)
3757         {
3758           SetPixelBlue(image,*p++,q);
3759           SetPixelGreen(image,*p++,q);
3760           SetPixelRed(image,*p++,q);
3761           p++;
3762           q+=GetPixelChannels(image);
3763         }
3764         if (SyncAuthenticPixels(image,exception) == MagickFalse)
3765           break;
3766       }
3767       return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
3768     }
3769   if (LocaleCompare(map,"I") == 0)
3770     {
3771       for (y=0; y < (ssize_t) roi->height; y++)
3772       {
3773         q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
3774         if (q == (Quantum *) NULL)
3775           break;
3776         for (x=0; x < (ssize_t) roi->width; x++)
3777         {
3778           SetPixelGray(image,*p++,q);
3779           q+=GetPixelChannels(image);
3780         }
3781         if (SyncAuthenticPixels(image,exception) == MagickFalse)
3782           break;
3783       }
3784       return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
3785     }
3786   if (LocaleCompare(map,"RGB") == 0)
3787     {
3788       for (y=0; y < (ssize_t) roi->height; y++)
3789       {
3790         q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
3791         if (q == (Quantum *) NULL)
3792           break;
3793         for (x=0; x < (ssize_t) roi->width; x++)
3794         {
3795           SetPixelRed(image,*p++,q);
3796           SetPixelGreen(image,*p++,q);
3797           SetPixelBlue(image,*p++,q);
3798           q+=GetPixelChannels(image);
3799         }
3800         if (SyncAuthenticPixels(image,exception) == MagickFalse)
3801           break;
3802       }
3803       return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
3804     }
3805   if (LocaleCompare(map,"RGBA") == 0)
3806     {
3807       for (y=0; y < (ssize_t) roi->height; y++)
3808       {
3809         q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
3810         if (q == (Quantum *) NULL)
3811           break;
3812         for (x=0; x < (ssize_t) roi->width; x++)
3813         {
3814           SetPixelRed(image,*p++,q);
3815           SetPixelGreen(image,*p++,q);
3816           SetPixelBlue(image,*p++,q);
3817           SetPixelAlpha(image,*p++,q);
3818           q+=GetPixelChannels(image);
3819         }
3820         if (SyncAuthenticPixels(image,exception) == MagickFalse)
3821           break;
3822       }
3823       return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
3824     }
3825   if (LocaleCompare(map,"RGBP") == 0)
3826     {
3827       for (y=0; y < (ssize_t) roi->height; y++)
3828       {
3829         q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
3830         if (q == (Quantum *) NULL)
3831           break;
3832         for (x=0; x < (ssize_t) roi->width; x++)
3833         {
3834           SetPixelRed(image,*p++,q);
3835           SetPixelGreen(image,*p++,q);
3836           SetPixelBlue(image,*p++,q);
3837           p++;
3838           q+=GetPixelChannels(image);
3839         }
3840         if (SyncAuthenticPixels(image,exception) == MagickFalse)
3841           break;
3842       }
3843       return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
3844     }
3845   length=strlen(map);
3846   for (y=0; y < (ssize_t) roi->height; y++)
3847   {
3848     q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
3849     if (q == (Quantum *) NULL)
3850       break;
3851     for (x=0; x < (ssize_t) roi->width; x++)
3852     {
3853       register ssize_t
3854         i;
3855 
3856       for (i=0; i < (ssize_t) length; i++)
3857       {
3858         switch (quantum_map[i])
3859         {
3860           case RedQuantum:
3861           case CyanQuantum:
3862           {
3863             SetPixelRed(image,*p,q);
3864             break;
3865           }
3866           case GreenQuantum:
3867           case MagentaQuantum:
3868           {
3869             SetPixelGreen(image,*p,q);
3870             break;
3871           }
3872           case BlueQuantum:
3873           case YellowQuantum:
3874           {
3875             SetPixelBlue(image,*p,q);
3876             break;
3877           }
3878           case AlphaQuantum:
3879           {
3880             SetPixelAlpha(image,*p,q);
3881             break;
3882           }
3883           case OpacityQuantum:
3884           {
3885             SetPixelAlpha(image,*p,q);
3886             break;
3887           }
3888           case BlackQuantum:
3889           {
3890             SetPixelBlack(image,*p,q);
3891             break;
3892           }
3893           case IndexQuantum:
3894           {
3895             SetPixelGray(image,*p,q);
3896             break;
3897           }
3898           default:
3899             break;
3900         }
3901         p++;
3902       }
3903       q+=GetPixelChannels(image);
3904     }
3905     if (SyncAuthenticPixels(image,exception) == MagickFalse)
3906       break;
3907   }
3908   return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
3909 }
3910 
ImportShortPixel(Image * image,const RectangleInfo * roi,const char * magick_restrict map,const QuantumType * quantum_map,const void * pixels,ExceptionInfo * exception)3911 static MagickBooleanType ImportShortPixel(Image *image,const RectangleInfo *roi,
3912   const char *magick_restrict map,const QuantumType *quantum_map,
3913   const void *pixels,ExceptionInfo *exception)
3914 {
3915   register const unsigned short
3916     *magick_restrict p;
3917 
3918   register Quantum
3919     *magick_restrict q;
3920 
3921   register ssize_t
3922     x;
3923 
3924   size_t
3925     length;
3926 
3927   ssize_t
3928     y;
3929 
3930   p=(const unsigned short *) pixels;
3931   if (LocaleCompare(map,"BGR") == 0)
3932     {
3933       for (y=0; y < (ssize_t) roi->height; y++)
3934       {
3935         q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
3936         if (q == (Quantum *) NULL)
3937           break;
3938         for (x=0; x < (ssize_t) roi->width; x++)
3939         {
3940           SetPixelBlue(image,ScaleShortToQuantum(*p++),q);
3941           SetPixelGreen(image,ScaleShortToQuantum(*p++),q);
3942           SetPixelRed(image,ScaleShortToQuantum(*p++),q);
3943           q+=GetPixelChannels(image);
3944         }
3945         if (SyncAuthenticPixels(image,exception) == MagickFalse)
3946           break;
3947       }
3948       return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
3949     }
3950   if (LocaleCompare(map,"BGRA") == 0)
3951     {
3952       for (y=0; y < (ssize_t) roi->height; y++)
3953       {
3954         q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
3955         if (q == (Quantum *) NULL)
3956           break;
3957         for (x=0; x < (ssize_t) roi->width; x++)
3958         {
3959           SetPixelBlue(image,ScaleShortToQuantum(*p++),q);
3960           SetPixelGreen(image,ScaleShortToQuantum(*p++),q);
3961           SetPixelRed(image,ScaleShortToQuantum(*p++),q);
3962           SetPixelAlpha(image,ScaleShortToQuantum(*p++),q);
3963           q+=GetPixelChannels(image);
3964         }
3965         if (SyncAuthenticPixels(image,exception) == MagickFalse)
3966           break;
3967       }
3968       return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
3969     }
3970   if (LocaleCompare(map,"BGRP") == 0)
3971     {
3972       for (y=0; y < (ssize_t) roi->height; y++)
3973       {
3974         q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
3975         if (q == (Quantum *) NULL)
3976           break;
3977         for (x=0; x < (ssize_t) roi->width; x++)
3978         {
3979           SetPixelBlue(image,ScaleShortToQuantum(*p++),q);
3980           SetPixelGreen(image,ScaleShortToQuantum(*p++),q);
3981           SetPixelRed(image,ScaleShortToQuantum(*p++),q);
3982           p++;
3983           q+=GetPixelChannels(image);
3984         }
3985         if (SyncAuthenticPixels(image,exception) == MagickFalse)
3986           break;
3987       }
3988       return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
3989     }
3990   if (LocaleCompare(map,"I") == 0)
3991     {
3992       for (y=0; y < (ssize_t) roi->height; y++)
3993       {
3994         q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
3995         if (q == (Quantum *) NULL)
3996           break;
3997         for (x=0; x < (ssize_t) roi->width; x++)
3998         {
3999           SetPixelGray(image,ScaleShortToQuantum(*p++),q);
4000           q+=GetPixelChannels(image);
4001         }
4002         if (SyncAuthenticPixels(image,exception) == MagickFalse)
4003           break;
4004       }
4005       return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
4006     }
4007   if (LocaleCompare(map,"RGB") == 0)
4008     {
4009       for (y=0; y < (ssize_t) roi->height; y++)
4010       {
4011         q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
4012         if (q == (Quantum *) NULL)
4013           break;
4014         for (x=0; x < (ssize_t) roi->width; x++)
4015         {
4016           SetPixelRed(image,ScaleShortToQuantum(*p++),q);
4017           SetPixelGreen(image,ScaleShortToQuantum(*p++),q);
4018           SetPixelBlue(image,ScaleShortToQuantum(*p++),q);
4019           q+=GetPixelChannels(image);
4020         }
4021         if (SyncAuthenticPixels(image,exception) == MagickFalse)
4022           break;
4023       }
4024       return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
4025     }
4026   if (LocaleCompare(map,"RGBA") == 0)
4027     {
4028       for (y=0; y < (ssize_t) roi->height; y++)
4029       {
4030         q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
4031         if (q == (Quantum *) NULL)
4032           break;
4033         for (x=0; x < (ssize_t) roi->width; x++)
4034         {
4035           SetPixelRed(image,ScaleShortToQuantum(*p++),q);
4036           SetPixelGreen(image,ScaleShortToQuantum(*p++),q);
4037           SetPixelBlue(image,ScaleShortToQuantum(*p++),q);
4038           SetPixelAlpha(image,ScaleShortToQuantum(*p++),q);
4039           q+=GetPixelChannels(image);
4040         }
4041         if (SyncAuthenticPixels(image,exception) == MagickFalse)
4042           break;
4043       }
4044       return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
4045     }
4046   if (LocaleCompare(map,"RGBP") == 0)
4047     {
4048       for (y=0; y < (ssize_t) roi->height; y++)
4049       {
4050         q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
4051         if (q == (Quantum *) NULL)
4052           break;
4053         for (x=0; x < (ssize_t) roi->width; x++)
4054         {
4055           SetPixelRed(image,ScaleShortToQuantum(*p++),q);
4056           SetPixelGreen(image,ScaleShortToQuantum(*p++),q);
4057           SetPixelBlue(image,ScaleShortToQuantum(*p++),q);
4058           p++;
4059           q+=GetPixelChannels(image);
4060         }
4061         if (SyncAuthenticPixels(image,exception) == MagickFalse)
4062           break;
4063       }
4064       return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
4065     }
4066   length=strlen(map);
4067   for (y=0; y < (ssize_t) roi->height; y++)
4068   {
4069     q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
4070     if (q == (Quantum *) NULL)
4071       break;
4072     for (x=0; x < (ssize_t) roi->width; x++)
4073     {
4074       register ssize_t
4075         i;
4076 
4077       for (i=0; i < (ssize_t) length; i++)
4078       {
4079         switch (quantum_map[i])
4080         {
4081           case RedQuantum:
4082           case CyanQuantum:
4083           {
4084             SetPixelRed(image,ScaleShortToQuantum(*p),q);
4085             break;
4086           }
4087           case GreenQuantum:
4088           case MagentaQuantum:
4089           {
4090             SetPixelGreen(image,ScaleShortToQuantum(*p),q);
4091             break;
4092           }
4093           case BlueQuantum:
4094           case YellowQuantum:
4095           {
4096             SetPixelBlue(image,ScaleShortToQuantum(*p),q);
4097             break;
4098           }
4099           case AlphaQuantum:
4100           {
4101             SetPixelAlpha(image,ScaleShortToQuantum(*p),q);
4102             break;
4103           }
4104           case OpacityQuantum:
4105           {
4106             SetPixelAlpha(image,ScaleShortToQuantum(*p),q);
4107             break;
4108           }
4109           case BlackQuantum:
4110           {
4111             SetPixelBlack(image,ScaleShortToQuantum(*p),q);
4112             break;
4113           }
4114           case IndexQuantum:
4115           {
4116             SetPixelGray(image,ScaleShortToQuantum(*p),q);
4117             break;
4118           }
4119           default:
4120             break;
4121         }
4122         p++;
4123       }
4124       q+=GetPixelChannels(image);
4125     }
4126     if (SyncAuthenticPixels(image,exception) == MagickFalse)
4127       break;
4128   }
4129   return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
4130 }
4131 
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)4132 MagickExport MagickBooleanType ImportImagePixels(Image *image,const ssize_t x,
4133   const ssize_t y,const size_t width,const size_t height,const char *map,
4134   const StorageType type,const void *pixels,ExceptionInfo *exception)
4135 {
4136   MagickBooleanType
4137     status;
4138 
4139   QuantumType
4140     *quantum_map;
4141 
4142   RectangleInfo
4143     roi;
4144 
4145   register ssize_t
4146     i;
4147 
4148   size_t
4149     length;
4150 
4151   /*
4152     Allocate image structure.
4153   */
4154   assert(image != (Image *) NULL);
4155   assert(image->signature == MagickCoreSignature);
4156   if (image->debug != MagickFalse)
4157     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
4158   length=strlen(map);
4159   quantum_map=(QuantumType *) AcquireQuantumMemory(length,sizeof(*quantum_map));
4160   if (quantum_map == (QuantumType *) NULL)
4161     ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
4162       image->filename);
4163   for (i=0; i < (ssize_t) length; i++)
4164   {
4165     switch (map[i])
4166     {
4167       case 'a':
4168       case 'A':
4169       {
4170         quantum_map[i]=AlphaQuantum;
4171         image->alpha_trait=BlendPixelTrait;
4172         break;
4173       }
4174       case 'B':
4175       case 'b':
4176       {
4177         quantum_map[i]=BlueQuantum;
4178         break;
4179       }
4180       case 'C':
4181       case 'c':
4182       {
4183         quantum_map[i]=CyanQuantum;
4184         (void) SetImageColorspace(image,CMYKColorspace,exception);
4185         break;
4186       }
4187       case 'g':
4188       case 'G':
4189       {
4190         quantum_map[i]=GreenQuantum;
4191         break;
4192       }
4193       case 'K':
4194       case 'k':
4195       {
4196         quantum_map[i]=BlackQuantum;
4197         (void) SetImageColorspace(image,CMYKColorspace,exception);
4198         break;
4199       }
4200       case 'I':
4201       case 'i':
4202       {
4203         quantum_map[i]=IndexQuantum;
4204         (void) SetImageColorspace(image,GRAYColorspace,exception);
4205         break;
4206       }
4207       case 'm':
4208       case 'M':
4209       {
4210         quantum_map[i]=MagentaQuantum;
4211         (void) SetImageColorspace(image,CMYKColorspace,exception);
4212         break;
4213       }
4214       case 'O':
4215       case 'o':
4216       {
4217         quantum_map[i]=OpacityQuantum;
4218         image->alpha_trait=BlendPixelTrait;
4219         break;
4220       }
4221       case 'P':
4222       case 'p':
4223       {
4224         quantum_map[i]=UndefinedQuantum;
4225         break;
4226       }
4227       case 'R':
4228       case 'r':
4229       {
4230         quantum_map[i]=RedQuantum;
4231         break;
4232       }
4233       case 'Y':
4234       case 'y':
4235       {
4236         quantum_map[i]=YellowQuantum;
4237         (void) SetImageColorspace(image,CMYKColorspace,exception);
4238         break;
4239       }
4240       default:
4241       {
4242         quantum_map=(QuantumType *) RelinquishMagickMemory(quantum_map);
4243         (void) ThrowMagickException(exception,GetMagickModule(),OptionError,
4244           "UnrecognizedPixelMap","`%s'",map);
4245         return(MagickFalse);
4246       }
4247     }
4248   }
4249   if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
4250     return(MagickFalse);
4251   /*
4252     Transfer the pixels from the pixel data to the image.
4253   */
4254   roi.width=width;
4255   roi.height=height;
4256   roi.x=x;
4257   roi.y=y;
4258   switch (type)
4259   {
4260     case CharPixel:
4261     {
4262       status=ImportCharPixel(image,&roi,map,quantum_map,pixels,exception);
4263       break;
4264     }
4265     case DoublePixel:
4266     {
4267       status=ImportDoublePixel(image,&roi,map,quantum_map,pixels,exception);
4268       break;
4269     }
4270     case FloatPixel:
4271     {
4272       status=ImportFloatPixel(image,&roi,map,quantum_map,pixels,exception);
4273       break;
4274     }
4275     case LongPixel:
4276     {
4277       status=ImportLongPixel(image,&roi,map,quantum_map,pixels,exception);
4278       break;
4279     }
4280     case LongLongPixel:
4281     {
4282       status=ImportLongLongPixel(image,&roi,map,quantum_map,pixels,exception);
4283       break;
4284     }
4285     case QuantumPixel:
4286     {
4287       status=ImportQuantumPixel(image,&roi,map,quantum_map,pixels,exception);
4288       break;
4289     }
4290     case ShortPixel:
4291     {
4292       status=ImportShortPixel(image,&roi,map,quantum_map,pixels,exception);
4293       break;
4294     }
4295     default:
4296     {
4297       (void) ThrowMagickException(exception,GetMagickModule(),OptionError,
4298         "UnrecognizedStorageType","`%d'",type);
4299       status=MagickFalse;
4300     }
4301   }
4302   quantum_map=(QuantumType *) RelinquishMagickMemory(quantum_map);
4303   return(status);
4304 }
4305 
4306 /*
4307 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4308 %                                                                             %
4309 %                                                                             %
4310 %                                                                             %
4311 +   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                         %
4312 %                                                                             %
4313 %                                                                             %
4314 %                                                                             %
4315 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4316 %
4317 %  InitializePixelChannelMap() defines the standard pixel component map.
4318 %
4319 %  The format of the InitializePixelChannelMap() method is:
4320 %
4321 %      void InitializePixelChannelMap(Image *image)
4322 %
4323 %  A description of each parameter follows:
4324 %
4325 %    o image: the image.
4326 %
4327 */
InitializePixelChannelMap(Image * image)4328 MagickExport void InitializePixelChannelMap(Image *image)
4329 {
4330   PixelTrait
4331     trait;
4332 
4333   register ssize_t
4334     i;
4335 
4336   ssize_t
4337     n;
4338 
4339   assert(image != (Image *) NULL);
4340   assert(image->signature == MagickCoreSignature);
4341   (void) memset(image->channel_map,0,MaxPixelChannels*
4342     sizeof(*image->channel_map));
4343   trait=UpdatePixelTrait;
4344   if (image->alpha_trait != UndefinedPixelTrait)
4345     trait=(PixelTrait) (trait | BlendPixelTrait);
4346   n=0;
4347   if ((image->colorspace == LinearGRAYColorspace) ||
4348       (image->colorspace == GRAYColorspace))
4349     {
4350       SetPixelChannelAttributes(image,BluePixelChannel,trait,n);
4351       SetPixelChannelAttributes(image,GreenPixelChannel,trait,n);
4352       SetPixelChannelAttributes(image,RedPixelChannel,trait,n++);
4353     }
4354   else
4355     {
4356       SetPixelChannelAttributes(image,RedPixelChannel,trait,n++);
4357       SetPixelChannelAttributes(image,GreenPixelChannel,trait,n++);
4358       SetPixelChannelAttributes(image,BluePixelChannel,trait,n++);
4359     }
4360   if (image->colorspace == CMYKColorspace)
4361     SetPixelChannelAttributes(image,BlackPixelChannel,trait,n++);
4362   for (i=0; i < (ssize_t) image->number_meta_channels; i++)
4363   {
4364     SetPixelChannelAttributes(image,(PixelChannel) n,UpdatePixelTrait,n);
4365     n++;
4366   }
4367   if (image->alpha_trait != UndefinedPixelTrait)
4368     SetPixelChannelAttributes(image,AlphaPixelChannel,CopyPixelTrait,n++);
4369   if (image->storage_class == PseudoClass)
4370     SetPixelChannelAttributes(image,IndexPixelChannel,CopyPixelTrait,n++);
4371   if ((image->channels & ReadMaskChannel) != 0)
4372     SetPixelChannelAttributes(image,ReadMaskPixelChannel,CopyPixelTrait,n++);
4373   if ((image->channels & WriteMaskChannel) != 0)
4374     SetPixelChannelAttributes(image,WriteMaskPixelChannel,CopyPixelTrait,n++);
4375   if ((image->channels & CompositeMaskChannel) != 0)
4376     SetPixelChannelAttributes(image,CompositeMaskPixelChannel,CopyPixelTrait,
4377       n++);
4378   image->number_channels=(size_t) n;
4379   (void) SetPixelChannelMask(image,image->channel_mask);
4380 }
4381 
4382 /*
4383 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4384 %                                                                             %
4385 %                                                                             %
4386 %                                                                             %
4387 %   I n t e r p o l a t e P i x e l C h a n n e l                             %
4388 %                                                                             %
4389 %                                                                             %
4390 %                                                                             %
4391 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4392 %
4393 %  InterpolatePixelChannel() applies a pixel interpolation method between a
4394 %  floating point coordinate and the pixels surrounding that coordinate.  No
4395 %  pixel area resampling, or scaling of the result is performed.
4396 %
4397 %  Interpolation is restricted to just the specified channel.
4398 %
4399 %  The format of the InterpolatePixelChannel method is:
4400 %
4401 %      MagickBooleanType InterpolatePixelChannel(const Image *image,
4402 %        const CacheView *image_view,const PixelChannel channel,
4403 %        const PixelInterpolateMethod method,const double x,const double y,
4404 %        double *pixel,ExceptionInfo *exception)
4405 %
4406 %  A description of each parameter follows:
4407 %
4408 %    o image: the image.
4409 %
4410 %    o image_view: the image view.
4411 %
4412 %    o channel: the pixel channel to interpolate.
4413 %
4414 %    o method: the pixel color interpolation method.
4415 %
4416 %    o x,y: A double representing the current (x,y) position of the pixel.
4417 %
4418 %    o pixel: return the interpolated pixel here.
4419 %
4420 %    o exception: return any errors or warnings in this structure.
4421 %
4422 */
4423 
CatromWeights(const double x,double (* weights)[4])4424 static inline void CatromWeights(const double x,double (*weights)[4])
4425 {
4426   double
4427     alpha,
4428     beta,
4429     gamma;
4430 
4431   /*
4432     Nicolas Robidoux' 10 flops (4* + 5- + 1+) refactoring of the computation
4433     of the standard four 1D Catmull-Rom weights. The sampling location is
4434     assumed between the second and third input pixel locations, and x is the
4435     position relative to the second input pixel location. Formulas originally
4436     derived for the VIPS (Virtual Image Processing System) library.
4437   */
4438   alpha=(double) 1.0-x;
4439   beta=(double) (-0.5)*x*alpha;
4440   (*weights)[0]=alpha*beta;
4441   (*weights)[3]=x*beta;
4442   /*
4443     The following computation of the inner weights from the outer ones work
4444     for all Keys cubics.
4445   */
4446   gamma=(*weights)[3]-(*weights)[0];
4447   (*weights)[1]=alpha-(*weights)[0]+gamma;
4448   (*weights)[2]=x-(*weights)[3]-gamma;
4449 }
4450 
SplineWeights(const double x,double (* weights)[4])4451 static inline void SplineWeights(const double x,double (*weights)[4])
4452 {
4453   double
4454     alpha,
4455     beta;
4456 
4457   /*
4458     Nicolas Robidoux' 12 flops (6* + 5- + 1+) refactoring of the computation
4459     of the standard four 1D cubic B-spline smoothing weights. The sampling
4460     location is assumed between the second and third input pixel locations,
4461     and x is the position relative to the second input pixel location.
4462   */
4463   alpha=(double) 1.0-x;
4464   (*weights)[3]=(double) (1.0/6.0)*x*x*x;
4465   (*weights)[0]=(double) (1.0/6.0)*alpha*alpha*alpha;
4466   beta=(*weights)[3]-(*weights)[0];
4467   (*weights)[1]=alpha-(*weights)[0]+beta;
4468   (*weights)[2]=x-(*weights)[3]-beta;
4469 }
4470 
MeshInterpolate(const PointInfo * delta,const double p,const double x,const double y)4471 static inline double MeshInterpolate(const PointInfo *delta,const double p,
4472   const double x,const double y)
4473 {
4474   return(delta->x*x+delta->y*y+(1.0-delta->x-delta->y)*p);
4475 }
4476 
4477 /*
4478 static inline ssize_t NearestNeighbor(const double x)
4479 {
4480   if (x >= 0.0)
4481     return((ssize_t) (x+0.5));
4482   return((ssize_t) (x-0.5));
4483 }
4484 */
4485 
InterpolatePixelChannel(const Image * image,const CacheView_ * image_view,const PixelChannel channel,const PixelInterpolateMethod method,const double x,const double y,double * pixel,ExceptionInfo * exception)4486 MagickExport MagickBooleanType InterpolatePixelChannel(const Image *image,
4487   const CacheView_ *image_view,const PixelChannel channel,
4488   const PixelInterpolateMethod method,const double x,const double y,
4489   double *pixel,ExceptionInfo *exception)
4490 {
4491   double
4492     alpha[16],
4493     gamma,
4494     pixels[16];
4495 
4496   MagickBooleanType
4497     status;
4498 
4499   PixelInterpolateMethod
4500     interpolate;
4501 
4502   PixelTrait
4503     traits;
4504 
4505   register const Quantum
4506     *p;
4507 
4508   register ssize_t
4509     i;
4510 
4511   ssize_t
4512     x_offset,
4513     y_offset;
4514 
4515   assert(image != (Image *) NULL);
4516   assert(image->signature == MagickCoreSignature);
4517   assert(image_view != (CacheView *) NULL);
4518   status=MagickTrue;
4519   *pixel=0.0;
4520   traits=GetPixelChannelTraits(image,channel);
4521   x_offset=(ssize_t) floor(x);
4522   y_offset=(ssize_t) floor(y);
4523   interpolate=method;
4524   if (interpolate == UndefinedInterpolatePixel)
4525     interpolate=image->interpolate;
4526   switch (interpolate)
4527   {
4528     case AverageInterpolatePixel:  /* nearest 4 neighbours */
4529     case Average9InterpolatePixel:  /* nearest 9 neighbours */
4530     case Average16InterpolatePixel:  /* nearest 16 neighbours */
4531     {
4532       ssize_t
4533         count;
4534 
4535       count=2;  /* size of the area to average - default nearest 4 */
4536       if (interpolate == Average9InterpolatePixel)
4537         {
4538           count=3;
4539           x_offset=(ssize_t) (floor(x+0.5)-1);
4540           y_offset=(ssize_t) (floor(y+0.5)-1);
4541         }
4542       else
4543         if (interpolate == Average16InterpolatePixel)
4544           {
4545             count=4;
4546             x_offset--;
4547             y_offset--;
4548           }
4549       p=GetCacheViewVirtualPixels(image_view,x_offset,y_offset,(size_t) count,
4550         (size_t) count,exception);
4551       if (p == (const Quantum *) NULL)
4552         {
4553           status=MagickFalse;
4554           break;
4555         }
4556       count*=count;  /* Number of pixels to average */
4557       if ((traits & BlendPixelTrait) == 0)
4558         for (i=0; i < (ssize_t) count; i++)
4559         {
4560           alpha[i]=1.0;
4561           pixels[i]=(double) p[i*GetPixelChannels(image)+channel];
4562         }
4563       else
4564         for (i=0; i < (ssize_t) count; i++)
4565         {
4566           alpha[i]=QuantumScale*GetPixelAlpha(image,p+i*
4567             GetPixelChannels(image));
4568           pixels[i]=alpha[i]*p[i*GetPixelChannels(image)+channel];
4569         }
4570       for (i=0; i < (ssize_t) count; i++)
4571       {
4572         gamma=PerceptibleReciprocal(alpha[i])/count;
4573         *pixel+=gamma*pixels[i];
4574       }
4575       break;
4576     }
4577     case BilinearInterpolatePixel:
4578     default:
4579     {
4580       PointInfo
4581         delta,
4582         epsilon;
4583 
4584       p=GetCacheViewVirtualPixels(image_view,x_offset,y_offset,2,2,exception);
4585       if (p == (const Quantum *) NULL)
4586         {
4587           status=MagickFalse;
4588           break;
4589         }
4590       if ((traits & BlendPixelTrait) == 0)
4591         for (i=0; i < 4; i++)
4592         {
4593           alpha[i]=1.0;
4594           pixels[i]=(double) p[i*GetPixelChannels(image)+channel];
4595         }
4596       else
4597         for (i=0; i < 4; i++)
4598         {
4599           alpha[i]=QuantumScale*GetPixelAlpha(image,p+i*
4600             GetPixelChannels(image));
4601           pixels[i]=alpha[i]*p[i*GetPixelChannels(image)+channel];
4602         }
4603       delta.x=x-x_offset;
4604       delta.y=y-y_offset;
4605       epsilon.x=1.0-delta.x;
4606       epsilon.y=1.0-delta.y;
4607       gamma=((epsilon.y*(epsilon.x*alpha[0]+delta.x*alpha[1])+delta.y*
4608         (epsilon.x*alpha[2]+delta.x*alpha[3])));
4609       gamma=PerceptibleReciprocal(gamma);
4610       *pixel=gamma*(epsilon.y*(epsilon.x*pixels[0]+delta.x*pixels[1])+delta.y*
4611         (epsilon.x*pixels[2]+delta.x*pixels[3]));
4612       break;
4613     }
4614     case BlendInterpolatePixel:
4615     {
4616       p=GetCacheViewVirtualPixels(image_view,x_offset,y_offset,2,2,exception);
4617       if (p == (const Quantum *) NULL)
4618         {
4619           status=MagickFalse;
4620           break;
4621         }
4622       if ((traits & BlendPixelTrait) == 0)
4623         for (i=0; i < 4; i++)
4624         {
4625           alpha[i]=1.0;
4626           pixels[i]=(MagickRealType) p[i*GetPixelChannels(image)+channel];
4627         }
4628       else
4629         for (i=0; i < 4; i++)
4630         {
4631           alpha[i]=QuantumScale*GetPixelAlpha(image,p+i*
4632             GetPixelChannels(image));
4633           pixels[i]=alpha[i]*p[i*GetPixelChannels(image)+channel];
4634         }
4635       gamma=1.0;  /* number of pixels blended together (its variable) */
4636       for (i=0; i <= 1L; i++) {
4637         if ((y-y_offset) >= 0.75)
4638           {
4639             alpha[i]=alpha[i+2];  /* take right pixels */
4640             pixels[i]=pixels[i+2];
4641           }
4642         else
4643           if ((y-y_offset) > 0.25)
4644             {
4645               gamma=2.0;  /* blend both pixels in row */
4646               alpha[i]+=alpha[i+2];  /* add up alpha weights */
4647               pixels[i]+=pixels[i+2];
4648             }
4649       }
4650       if ((x-x_offset) >= 0.75)
4651         {
4652           alpha[0]=alpha[1];  /* take bottom row blend */
4653           pixels[0]=pixels[1];
4654         }
4655       else
4656         if ((x-x_offset) > 0.25)
4657           {
4658             gamma*=2.0;  /* blend both rows */
4659             alpha[0]+=alpha[1];  /* add up alpha weights */
4660             pixels[0]+=pixels[1];
4661           }
4662       if (channel != AlphaPixelChannel)
4663         gamma=PerceptibleReciprocal(alpha[0]);  /* (color) 1/alpha_weights */
4664       else
4665         gamma=PerceptibleReciprocal(gamma);  /* (alpha) 1/number_of_pixels */
4666       *pixel=gamma*pixels[0];
4667       break;
4668     }
4669     case CatromInterpolatePixel:
4670     {
4671       double
4672         cx[4],
4673         cy[4];
4674 
4675       p=GetCacheViewVirtualPixels(image_view,x_offset-1,y_offset-1,4,4,
4676         exception);
4677       if (p == (const Quantum *) NULL)
4678         {
4679           status=MagickFalse;
4680           break;
4681         }
4682       if ((traits & BlendPixelTrait) == 0)
4683         for (i=0; i < 16; i++)
4684         {
4685           alpha[i]=1.0;
4686           pixels[i]=(double) p[i*GetPixelChannels(image)+channel];
4687         }
4688       else
4689         for (i=0; i < 16; i++)
4690         {
4691           alpha[i]=QuantumScale*GetPixelAlpha(image,p+i*
4692             GetPixelChannels(image));
4693           pixels[i]=alpha[i]*p[i*GetPixelChannels(image)+channel];
4694         }
4695       CatromWeights((double) (x-x_offset),&cx);
4696       CatromWeights((double) (y-y_offset),&cy);
4697       gamma=(channel == AlphaPixelChannel ? (double) 1.0 :
4698         PerceptibleReciprocal(cy[0]*(cx[0]*alpha[0]+cx[1]*alpha[1]+cx[2]*
4699         alpha[2]+cx[3]*alpha[3])+cy[1]*(cx[0]*alpha[4]+cx[1]*alpha[5]+cx[2]*
4700         alpha[6]+cx[3]*alpha[7])+cy[2]*(cx[0]*alpha[8]+cx[1]*alpha[9]+cx[2]*
4701         alpha[10]+cx[3]*alpha[11])+cy[3]*(cx[0]*alpha[12]+cx[1]*alpha[13]+
4702         cx[2]*alpha[14]+cx[3]*alpha[15])));
4703       *pixel=gamma*(cy[0]*(cx[0]*pixels[0]+cx[1]*pixels[1]+cx[2]*pixels[2]+
4704         cx[3]*pixels[3])+cy[1]*(cx[0]*pixels[4]+cx[1]*pixels[5]+cx[2]*
4705         pixels[6]+cx[3]*pixels[7])+cy[2]*(cx[0]*pixels[8]+cx[1]*pixels[9]+
4706         cx[2]*pixels[10]+cx[3]*pixels[11])+cy[3]*(cx[0]*pixels[12]+cx[1]*
4707         pixels[13]+cx[2]*pixels[14]+cx[3]*pixels[15]));
4708       break;
4709     }
4710     case IntegerInterpolatePixel:
4711     {
4712       p=GetCacheViewVirtualPixels(image_view,x_offset,y_offset,1,1,exception);
4713       if (p == (const Quantum *) NULL)
4714         {
4715           status=MagickFalse;
4716           break;
4717         }
4718       *pixel=(double) GetPixelChannel(image,channel,p);
4719       break;
4720     }
4721     case NearestInterpolatePixel:
4722     {
4723       x_offset=(ssize_t) floor(x+0.5);
4724       y_offset=(ssize_t) floor(y+0.5);
4725       p=GetCacheViewVirtualPixels(image_view,x_offset,y_offset,1,1,exception);
4726       if (p == (const Quantum *) NULL)
4727         {
4728           status=MagickFalse;
4729           break;
4730         }
4731       *pixel=(double) GetPixelChannel(image,channel,p);
4732       break;
4733     }
4734     case MeshInterpolatePixel:
4735     {
4736       PointInfo
4737         delta,
4738         luminance;
4739 
4740       p=GetCacheViewVirtualPixels(image_view,x_offset,y_offset,2,2,exception);
4741       if (p == (const Quantum *) NULL)
4742         {
4743           status=MagickFalse;
4744           break;
4745         }
4746       if ((traits & BlendPixelTrait) == 0)
4747         for (i=0; i < 4; i++)
4748         {
4749           alpha[i]=1.0;
4750           pixels[i]=(double) p[i*GetPixelChannels(image)+channel];
4751         }
4752       else
4753         for (i=0; i < 4; i++)
4754         {
4755           alpha[i]=QuantumScale*GetPixelAlpha(image,p+i*
4756             GetPixelChannels(image));
4757           pixels[i]=alpha[i]*p[i*GetPixelChannels(image)+channel];
4758         }
4759       delta.x=x-x_offset;
4760       delta.y=y-y_offset;
4761       luminance.x=GetPixelLuma(image,p)-(double)
4762         GetPixelLuma(image,p+3*GetPixelChannels(image));
4763       luminance.y=GetPixelLuma(image,p+GetPixelChannels(image))-(double)
4764         GetPixelLuma(image,p+2*GetPixelChannels(image));
4765       if (fabs(luminance.x) < fabs(luminance.y))
4766         {
4767           /*
4768             Diagonal 0-3 NW-SE.
4769           */
4770           if (delta.x <= delta.y)
4771             {
4772               /*
4773                 Bottom-left triangle (pixel: 2, diagonal: 0-3).
4774               */
4775               delta.y=1.0-delta.y;
4776               gamma=MeshInterpolate(&delta,alpha[2],alpha[3],alpha[0]);
4777               gamma=PerceptibleReciprocal(gamma);
4778               *pixel=gamma*MeshInterpolate(&delta,pixels[2],pixels[3],
4779                 pixels[0]);
4780             }
4781           else
4782             {
4783               /*
4784                 Top-right triangle (pixel: 1, diagonal: 0-3).
4785               */
4786               delta.x=1.0-delta.x;
4787               gamma=MeshInterpolate(&delta,alpha[1],alpha[0],alpha[3]);
4788               gamma=PerceptibleReciprocal(gamma);
4789               *pixel=gamma*MeshInterpolate(&delta,pixels[1],pixels[0],
4790                 pixels[3]);
4791             }
4792         }
4793       else
4794         {
4795           /*
4796             Diagonal 1-2 NE-SW.
4797           */
4798           if (delta.x <= (1.0-delta.y))
4799             {
4800               /*
4801                 Top-left triangle (pixel: 0, diagonal: 1-2).
4802               */
4803               gamma=MeshInterpolate(&delta,alpha[0],alpha[1],alpha[2]);
4804               gamma=PerceptibleReciprocal(gamma);
4805               *pixel=gamma*MeshInterpolate(&delta,pixels[0],pixels[1],
4806                 pixels[2]);
4807             }
4808           else
4809             {
4810               /*
4811                 Bottom-right triangle (pixel: 3, diagonal: 1-2).
4812               */
4813               delta.x=1.0-delta.x;
4814               delta.y=1.0-delta.y;
4815               gamma=MeshInterpolate(&delta,alpha[3],alpha[2],alpha[1]);
4816               gamma=PerceptibleReciprocal(gamma);
4817               *pixel=gamma*MeshInterpolate(&delta,pixels[3],pixels[2],
4818                 pixels[1]);
4819             }
4820         }
4821       break;
4822     }
4823     case SplineInterpolatePixel:
4824     {
4825       double
4826         cx[4],
4827         cy[4];
4828 
4829       p=GetCacheViewVirtualPixels(image_view,x_offset-1,y_offset-1,4,4,
4830         exception);
4831       if (p == (const Quantum *) NULL)
4832         {
4833           status=MagickFalse;
4834           break;
4835         }
4836       if ((traits & BlendPixelTrait) == 0)
4837         for (i=0; i < 16; i++)
4838         {
4839           alpha[i]=1.0;
4840           pixels[i]=(double) p[i*GetPixelChannels(image)+channel];
4841         }
4842       else
4843         for (i=0; i < 16; i++)
4844         {
4845           alpha[i]=QuantumScale*GetPixelAlpha(image,p+i*
4846             GetPixelChannels(image));
4847           pixels[i]=alpha[i]*p[i*GetPixelChannels(image)+channel];
4848         }
4849       SplineWeights((double) (x-x_offset),&cx);
4850       SplineWeights((double) (y-y_offset),&cy);
4851       gamma=(channel == AlphaPixelChannel ? (double) 1.0 :
4852         PerceptibleReciprocal(cy[0]*(cx[0]*alpha[0]+cx[1]*alpha[1]+cx[2]*
4853         alpha[2]+cx[3]*alpha[3])+cy[1]*(cx[0]*alpha[4]+cx[1]*alpha[5]+cx[2]*
4854         alpha[6]+cx[3]*alpha[7])+cy[2]*(cx[0]*alpha[8]+cx[1]*alpha[9]+cx[2]*
4855         alpha[10]+cx[3]*alpha[11])+cy[3]*(cx[0]*alpha[12]+cx[1]*alpha[13]+
4856         cx[2]*alpha[14]+cx[3]*alpha[15])));
4857       *pixel=gamma*(cy[0]*(cx[0]*pixels[0]+cx[1]*pixels[1]+cx[2]*pixels[2]+
4858         cx[3]*pixels[3])+cy[1]*(cx[0]*pixels[4]+cx[1]*pixels[5]+cx[2]*
4859         pixels[6]+cx[3]*pixels[7])+cy[2]*(cx[0]*pixels[8]+cx[1]*pixels[9]+
4860         cx[2]*pixels[10]+cx[3]*pixels[11])+cy[3]*(cx[0]*pixels[12]+cx[1]*
4861         pixels[13]+cx[2]*pixels[14]+cx[3]*pixels[15]));
4862       break;
4863     }
4864   }
4865   return(status);
4866 }
4867 
4868 /*
4869 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4870 %                                                                             %
4871 %                                                                             %
4872 %                                                                             %
4873 %   I n t e r p o l a t e P i x e l C h a n n e l s                           %
4874 %                                                                             %
4875 %                                                                             %
4876 %                                                                             %
4877 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4878 %
4879 %  InterpolatePixelChannels() applies a pixel interpolation method between a
4880 %  floating point coordinate and the pixels surrounding that coordinate.  No
4881 %  pixel area resampling, or scaling of the result is performed.
4882 %
4883 %  Interpolation is restricted to just the current channel setting of the
4884 %  destination image into which the color is to be stored
4885 %
4886 %  The format of the InterpolatePixelChannels method is:
4887 %
4888 %      MagickBooleanType InterpolatePixelChannels(const Image *source,
4889 %        const CacheView *source_view,const Image *destination,
4890 %        const PixelInterpolateMethod method,const double x,const double y,
4891 %        Quantum *pixel,ExceptionInfo *exception)
4892 %
4893 %  A description of each parameter follows:
4894 %
4895 %    o source: the source.
4896 %
4897 %    o source_view: the source view.
4898 %
4899 %    o destination: the destination image, for the interpolated color
4900 %
4901 %    o method: the pixel color interpolation method.
4902 %
4903 %    o x,y: A double representing the current (x,y) position of the pixel.
4904 %
4905 %    o pixel: return the interpolated pixel here.
4906 %
4907 %    o exception: return any errors or warnings in this structure.
4908 %
4909 */
InterpolatePixelChannels(const Image * source,const CacheView_ * source_view,const Image * destination,const PixelInterpolateMethod method,const double x,const double y,Quantum * pixel,ExceptionInfo * exception)4910 MagickExport MagickBooleanType InterpolatePixelChannels(const Image *source,
4911   const CacheView_ *source_view,const Image *destination,
4912   const PixelInterpolateMethod method,const double x,const double y,
4913   Quantum *pixel,ExceptionInfo *exception)
4914 {
4915   MagickBooleanType
4916     status;
4917 
4918   double
4919     alpha[16],
4920     gamma,
4921     pixels[16];
4922 
4923   register const Quantum
4924     *p;
4925 
4926   register ssize_t
4927     i;
4928 
4929   ssize_t
4930     x_offset,
4931     y_offset;
4932 
4933   PixelInterpolateMethod
4934     interpolate;
4935 
4936   assert(source != (Image *) NULL);
4937   assert(source->signature == MagickCoreSignature);
4938   assert(source_view != (CacheView *) NULL);
4939   status=MagickTrue;
4940   x_offset=(ssize_t) floor(x);
4941   y_offset=(ssize_t) floor(y);
4942   interpolate=method;
4943   if (interpolate == UndefinedInterpolatePixel)
4944     interpolate=source->interpolate;
4945   switch (interpolate)
4946   {
4947     case AverageInterpolatePixel:  /* nearest 4 neighbours */
4948     case Average9InterpolatePixel:  /* nearest 9 neighbours */
4949     case Average16InterpolatePixel:  /* nearest 16 neighbours */
4950     {
4951       ssize_t
4952         count;
4953 
4954       count=2;  /* size of the area to average - default nearest 4 */
4955       if (interpolate == Average9InterpolatePixel)
4956         {
4957           count=3;
4958           x_offset=(ssize_t) (floor(x+0.5)-1);
4959           y_offset=(ssize_t) (floor(y+0.5)-1);
4960         }
4961       else
4962         if (interpolate == Average16InterpolatePixel)
4963           {
4964             count=4;
4965             x_offset--;
4966             y_offset--;
4967           }
4968       p=GetCacheViewVirtualPixels(source_view,x_offset,y_offset,(size_t) count,
4969         (size_t) count,exception);
4970       if (p == (const Quantum *) NULL)
4971         {
4972           status=MagickFalse;
4973           break;
4974         }
4975       count*=count;  /* Number of pixels to average */
4976       for (i=0; i < (ssize_t) GetPixelChannels(source); i++)
4977       {
4978         double
4979           sum;
4980 
4981         register ssize_t
4982           j;
4983 
4984         PixelChannel channel = GetPixelChannelChannel(source,i);
4985         PixelTrait traits = GetPixelChannelTraits(source,channel);
4986         PixelTrait destination_traits=GetPixelChannelTraits(destination,
4987           channel);
4988         if ((traits == UndefinedPixelTrait) ||
4989             (destination_traits == UndefinedPixelTrait))
4990           continue;
4991         for (j=0; j < (ssize_t) count; j++)
4992           pixels[j]=(double) p[j*GetPixelChannels(source)+i];
4993         sum=0.0;
4994         if ((traits & BlendPixelTrait) == 0)
4995           {
4996             for (j=0; j < (ssize_t) count; j++)
4997               sum+=pixels[j];
4998             sum/=count;
4999             SetPixelChannel(destination,channel,ClampToQuantum(sum),pixel);
5000             continue;
5001           }
5002         for (j=0; j < (ssize_t) count; j++)
5003         {
5004           alpha[j]=QuantumScale*GetPixelAlpha(source,p+j*
5005             GetPixelChannels(source));
5006           pixels[j]*=alpha[j];
5007           gamma=PerceptibleReciprocal(alpha[j]);
5008           sum+=gamma*pixels[j];
5009         }
5010         sum/=count;
5011         SetPixelChannel(destination,channel,ClampToQuantum(sum),pixel);
5012       }
5013       break;
5014     }
5015     case BilinearInterpolatePixel:
5016     default:
5017     {
5018       p=GetCacheViewVirtualPixels(source_view,x_offset,y_offset,2,2,exception);
5019       if (p == (const Quantum *) NULL)
5020         {
5021           status=MagickFalse;
5022           break;
5023         }
5024       for (i=0; i < (ssize_t) GetPixelChannels(source); i++)
5025       {
5026         PointInfo
5027           delta,
5028           epsilon;
5029 
5030         PixelChannel channel = GetPixelChannelChannel(source,i);
5031         PixelTrait traits = GetPixelChannelTraits(source,channel);
5032         PixelTrait destination_traits=GetPixelChannelTraits(destination,
5033           channel);
5034         if ((traits == UndefinedPixelTrait) ||
5035             (destination_traits == UndefinedPixelTrait))
5036           continue;
5037         delta.x=x-x_offset;
5038         delta.y=y-y_offset;
5039         epsilon.x=1.0-delta.x;
5040         epsilon.y=1.0-delta.y;
5041         pixels[0]=(double) p[i];
5042         pixels[1]=(double) p[GetPixelChannels(source)+i];
5043         pixels[2]=(double) p[2*GetPixelChannels(source)+i];
5044         pixels[3]=(double) p[3*GetPixelChannels(source)+i];
5045         if ((traits & BlendPixelTrait) == 0)
5046           {
5047             gamma=((epsilon.y*(epsilon.x+delta.x)+delta.y*(epsilon.x+delta.x)));
5048             gamma=PerceptibleReciprocal(gamma);
5049             SetPixelChannel(destination,channel,ClampToQuantum(gamma*(epsilon.y*
5050               (epsilon.x*pixels[0]+delta.x*pixels[1])+delta.y*(epsilon.x*
5051               pixels[2]+delta.x*pixels[3]))),pixel);
5052             continue;
5053           }
5054         alpha[0]=QuantumScale*GetPixelAlpha(source,p);
5055         alpha[1]=QuantumScale*GetPixelAlpha(source,p+GetPixelChannels(source));
5056         alpha[2]=QuantumScale*GetPixelAlpha(source,p+2*
5057           GetPixelChannels(source));
5058         alpha[3]=QuantumScale*GetPixelAlpha(source,p+3*
5059           GetPixelChannels(source));
5060         pixels[0]*=alpha[0];
5061         pixels[1]*=alpha[1];
5062         pixels[2]*=alpha[2];
5063         pixels[3]*=alpha[3];
5064         gamma=((epsilon.y*(epsilon.x*alpha[0]+delta.x*alpha[1])+delta.y*
5065           (epsilon.x*alpha[2]+delta.x*alpha[3])));
5066         gamma=PerceptibleReciprocal(gamma);
5067         SetPixelChannel(destination,channel,ClampToQuantum(gamma*(epsilon.y*
5068           (epsilon.x*pixels[0]+delta.x*pixels[1])+delta.y*(epsilon.x*pixels[2]+
5069           delta.x*pixels[3]))),pixel);
5070       }
5071       break;
5072     }
5073     case BlendInterpolatePixel:
5074     {
5075       p=GetCacheViewVirtualPixels(source_view,x_offset,y_offset,2,2,exception);
5076       if (p == (const Quantum *) NULL)
5077         {
5078           status=MagickFalse;
5079           break;
5080         }
5081       for (i=0; i < (ssize_t) GetPixelChannels(source); i++)
5082       {
5083         register ssize_t
5084           j;
5085 
5086         PixelChannel channel = GetPixelChannelChannel(source,i);
5087         PixelTrait traits = GetPixelChannelTraits(source,channel);
5088         PixelTrait destination_traits=GetPixelChannelTraits(destination,
5089           channel);
5090         if ((traits == UndefinedPixelTrait) ||
5091             (destination_traits == UndefinedPixelTrait))
5092           continue;
5093         if (source->alpha_trait != BlendPixelTrait)
5094           for (j=0; j < 4; j++)
5095           {
5096             alpha[j]=1.0;
5097             pixels[j]=(double) p[j*GetPixelChannels(source)+i];
5098           }
5099         else
5100           for (j=0; j < 4; j++)
5101           {
5102             alpha[j]=QuantumScale*GetPixelAlpha(source,p+j*
5103               GetPixelChannels(source));
5104             pixels[j]=(double) p[j*GetPixelChannels(source)+i];
5105             if (channel != AlphaPixelChannel)
5106               pixels[j]*=alpha[j];
5107           }
5108         gamma=1.0;  /* number of pixels blended together (its variable) */
5109         for (j=0; j <= 1L; j++)
5110         {
5111           if ((y-y_offset) >= 0.75)
5112             {
5113               alpha[j]=alpha[j+2];  /* take right pixels */
5114               pixels[j]=pixels[j+2];
5115             }
5116           else
5117             if ((y-y_offset) > 0.25)
5118               {
5119                 gamma=2.0;  /* blend both pixels in row */
5120                 alpha[j]+=alpha[j+2];  /* add up alpha weights */
5121                 pixels[j]+=pixels[j+2];
5122               }
5123         }
5124         if ((x-x_offset) >= 0.75)
5125           {
5126             alpha[0]=alpha[1];  /* take bottom row blend */
5127             pixels[0]=pixels[1];
5128           }
5129         else
5130            if ((x-x_offset) > 0.25)
5131              {
5132                gamma*=2.0;  /* blend both rows */
5133                alpha[0]+=alpha[1];  /* add up alpha weights */
5134                pixels[0]+=pixels[1];
5135              }
5136         if (channel != AlphaPixelChannel)
5137           gamma=PerceptibleReciprocal(alpha[0]);  /* (color) 1/alpha_weights */
5138         else
5139           gamma=PerceptibleReciprocal(gamma);  /* (alpha) 1/number_of_pixels */
5140         SetPixelChannel(destination,channel,ClampToQuantum(gamma*pixels[0]),
5141           pixel);
5142       }
5143       break;
5144     }
5145     case CatromInterpolatePixel:
5146     {
5147       double
5148         cx[4],
5149         cy[4];
5150 
5151       p=GetCacheViewVirtualPixels(source_view,x_offset-1,y_offset-1,4,4,
5152         exception);
5153       if (p == (const Quantum *) NULL)
5154         {
5155           status=MagickFalse;
5156           break;
5157         }
5158       for (i=0; i < (ssize_t) GetPixelChannels(source); i++)
5159       {
5160         register ssize_t
5161           j;
5162 
5163         PixelChannel channel = GetPixelChannelChannel(source,i);
5164         PixelTrait traits = GetPixelChannelTraits(source,channel);
5165         PixelTrait destination_traits=GetPixelChannelTraits(destination,
5166           channel);
5167         if ((traits == UndefinedPixelTrait) ||
5168             (destination_traits == UndefinedPixelTrait))
5169           continue;
5170         if ((traits & BlendPixelTrait) == 0)
5171           for (j=0; j < 16; j++)
5172           {
5173             alpha[j]=1.0;
5174             pixels[j]=(double) p[j*GetPixelChannels(source)+i];
5175           }
5176         else
5177           for (j=0; j < 16; j++)
5178           {
5179             alpha[j]=QuantumScale*GetPixelAlpha(source,p+j*
5180               GetPixelChannels(source));
5181             pixels[j]=alpha[j]*p[j*GetPixelChannels(source)+i];
5182           }
5183         CatromWeights((double) (x-x_offset),&cx);
5184         CatromWeights((double) (y-y_offset),&cy);
5185         gamma=((traits & BlendPixelTrait) ? (double) (1.0) :
5186           PerceptibleReciprocal(cy[0]*(cx[0]*alpha[0]+cx[1]*alpha[1]+cx[2]*
5187           alpha[2]+cx[3]*alpha[3])+cy[1]*(cx[0]*alpha[4]+cx[1]*alpha[5]+cx[2]*
5188           alpha[6]+cx[3]*alpha[7])+cy[2]*(cx[0]*alpha[8]+cx[1]*alpha[9]+cx[2]*
5189           alpha[10]+cx[3]*alpha[11])+cy[3]*(cx[0]*alpha[12]+cx[1]*alpha[13]+
5190           cx[2]*alpha[14]+cx[3]*alpha[15])));
5191         SetPixelChannel(destination,channel,ClampToQuantum(gamma*(cy[0]*(cx[0]*
5192           pixels[0]+cx[1]*pixels[1]+cx[2]*pixels[2]+cx[3]*pixels[3])+cy[1]*
5193           (cx[0]*pixels[4]+cx[1]*pixels[5]+cx[2]*pixels[6]+cx[3]*pixels[7])+
5194           cy[2]*(cx[0]*pixels[8]+cx[1]*pixels[9]+cx[2]*pixels[10]+cx[3]*
5195           pixels[11])+cy[3]*(cx[0]*pixels[12]+cx[1]*pixels[13]+cx[2]*
5196           pixels[14]+cx[3]*pixels[15]))),pixel);
5197       }
5198       break;
5199     }
5200     case IntegerInterpolatePixel:
5201     {
5202       p=GetCacheViewVirtualPixels(source_view,x_offset,y_offset,1,1,exception);
5203       if (p == (const Quantum *) NULL)
5204         {
5205           status=MagickFalse;
5206           break;
5207         }
5208       for (i=0; i < (ssize_t) GetPixelChannels(source); i++)
5209       {
5210         PixelChannel channel = GetPixelChannelChannel(source,i);
5211         PixelTrait traits = GetPixelChannelTraits(source,channel);
5212         PixelTrait destination_traits=GetPixelChannelTraits(destination,
5213           channel);
5214         if ((traits == UndefinedPixelTrait) ||
5215             (destination_traits == UndefinedPixelTrait))
5216           continue;
5217         SetPixelChannel(destination,channel,p[i],pixel);
5218       }
5219       break;
5220     }
5221     case NearestInterpolatePixel:
5222     {
5223       x_offset=(ssize_t) floor(x+0.5);
5224       y_offset=(ssize_t) floor(y+0.5);
5225       p=GetCacheViewVirtualPixels(source_view,x_offset,y_offset,1,1,exception);
5226       if (p == (const Quantum *) NULL)
5227         {
5228           status=MagickFalse;
5229           break;
5230         }
5231       for (i=0; i < (ssize_t) GetPixelChannels(source); i++)
5232       {
5233         PixelChannel channel = GetPixelChannelChannel(source,i);
5234         PixelTrait traits = GetPixelChannelTraits(source,channel);
5235         PixelTrait destination_traits=GetPixelChannelTraits(destination,
5236           channel);
5237         if ((traits == UndefinedPixelTrait) ||
5238             (destination_traits == UndefinedPixelTrait))
5239           continue;
5240         SetPixelChannel(destination,channel,p[i],pixel);
5241       }
5242       break;
5243     }
5244     case MeshInterpolatePixel:
5245     {
5246       p=GetCacheViewVirtualPixels(source_view,x_offset,y_offset,2,2,exception);
5247       if (p == (const Quantum *) NULL)
5248         {
5249           status=MagickFalse;
5250           break;
5251         }
5252       for (i=0; i < (ssize_t) GetPixelChannels(source); i++)
5253       {
5254         PointInfo
5255           delta,
5256           luminance;
5257 
5258         PixelChannel channel = GetPixelChannelChannel(source,i);
5259         PixelTrait traits = GetPixelChannelTraits(source,channel);
5260         PixelTrait destination_traits=GetPixelChannelTraits(destination,
5261           channel);
5262         if ((traits == UndefinedPixelTrait) ||
5263             (destination_traits == UndefinedPixelTrait))
5264           continue;
5265         pixels[0]=(double) p[i];
5266         pixels[1]=(double) p[GetPixelChannels(source)+i];
5267         pixels[2]=(double) p[2*GetPixelChannels(source)+i];
5268         pixels[3]=(double) p[3*GetPixelChannels(source)+i];
5269         if ((traits & BlendPixelTrait) == 0)
5270           {
5271             alpha[0]=1.0;
5272             alpha[1]=1.0;
5273             alpha[2]=1.0;
5274             alpha[3]=1.0;
5275           }
5276         else
5277           {
5278             alpha[0]=QuantumScale*GetPixelAlpha(source,p);
5279             alpha[1]=QuantumScale*GetPixelAlpha(source,p+
5280               GetPixelChannels(source));
5281             alpha[2]=QuantumScale*GetPixelAlpha(source,p+2*
5282               GetPixelChannels(source));
5283             alpha[3]=QuantumScale*GetPixelAlpha(source,p+3*
5284               GetPixelChannels(source));
5285           }
5286         delta.x=x-x_offset;
5287         delta.y=y-y_offset;
5288         luminance.x=fabs((double) (GetPixelLuma(source,p)-
5289           GetPixelLuma(source,p+3*GetPixelChannels(source))));
5290         luminance.y=fabs((double) (GetPixelLuma(source,p+
5291           GetPixelChannels(source))-GetPixelLuma(source,p+2*
5292           GetPixelChannels(source))));
5293         if (luminance.x < luminance.y)
5294           {
5295             /*
5296               Diagonal 0-3 NW-SE.
5297             */
5298             if (delta.x <= delta.y)
5299               {
5300                 /*
5301                   Bottom-left triangle (pixel: 2, diagonal: 0-3).
5302                 */
5303                 delta.y=1.0-delta.y;
5304                 gamma=MeshInterpolate(&delta,alpha[2],alpha[3],alpha[0]);
5305                 gamma=PerceptibleReciprocal(gamma);
5306                 SetPixelChannel(destination,channel,ClampToQuantum(gamma*
5307                   MeshInterpolate(&delta,pixels[2],pixels[3],pixels[0])),pixel);
5308               }
5309             else
5310               {
5311                 /*
5312                   Top-right triangle (pixel: 1, diagonal: 0-3).
5313                 */
5314                 delta.x=1.0-delta.x;
5315                 gamma=MeshInterpolate(&delta,alpha[1],alpha[0],alpha[3]);
5316                 gamma=PerceptibleReciprocal(gamma);
5317                 SetPixelChannel(destination,channel,ClampToQuantum(gamma*
5318                   MeshInterpolate(&delta,pixels[1],pixels[0],pixels[3])),pixel);
5319               }
5320           }
5321         else
5322           {
5323             /*
5324               Diagonal 1-2 NE-SW.
5325             */
5326             if (delta.x <= (1.0-delta.y))
5327               {
5328                 /*
5329                   Top-left triangle (pixel: 0, diagonal: 1-2).
5330                 */
5331                 gamma=MeshInterpolate(&delta,alpha[0],alpha[1],alpha[2]);
5332                 gamma=PerceptibleReciprocal(gamma);
5333                 SetPixelChannel(destination,channel,ClampToQuantum(gamma*
5334                   MeshInterpolate(&delta,pixels[0],pixels[1],pixels[2])),pixel);
5335               }
5336             else
5337               {
5338                 /*
5339                   Bottom-right triangle (pixel: 3, diagonal: 1-2).
5340                 */
5341                 delta.x=1.0-delta.x;
5342                 delta.y=1.0-delta.y;
5343                 gamma=MeshInterpolate(&delta,alpha[3],alpha[2],alpha[1]);
5344                 gamma=PerceptibleReciprocal(gamma);
5345                 SetPixelChannel(destination,channel,ClampToQuantum(gamma*
5346                   MeshInterpolate(&delta,pixels[3],pixels[2],pixels[1])),pixel);
5347               }
5348           }
5349       }
5350       break;
5351     }
5352     case SplineInterpolatePixel:
5353     {
5354       double
5355         cx[4],
5356         cy[4];
5357 
5358       p=GetCacheViewVirtualPixels(source_view,x_offset-1,y_offset-1,4,4,
5359         exception);
5360       if (p == (const Quantum *) NULL)
5361         {
5362           status=MagickFalse;
5363           break;
5364         }
5365       for (i=0; i < (ssize_t) GetPixelChannels(source); i++)
5366       {
5367         register ssize_t
5368           j;
5369 
5370         PixelChannel channel = GetPixelChannelChannel(source,i);
5371         PixelTrait traits = GetPixelChannelTraits(source,channel);
5372         PixelTrait destination_traits=GetPixelChannelTraits(destination,
5373           channel);
5374         if ((traits == UndefinedPixelTrait) ||
5375             (destination_traits == UndefinedPixelTrait))
5376           continue;
5377         if ((traits & BlendPixelTrait) == 0)
5378           for (j=0; j < 16; j++)
5379           {
5380             alpha[j]=1.0;
5381             pixels[j]=(double) p[j*GetPixelChannels(source)+i];
5382           }
5383         else
5384           for (j=0; j < 16; j++)
5385           {
5386             alpha[j]=QuantumScale*GetPixelAlpha(source,p+j*
5387               GetPixelChannels(source));
5388             pixels[j]=alpha[j]*p[j*GetPixelChannels(source)+i];
5389           }
5390         SplineWeights((double) (x-x_offset),&cx);
5391         SplineWeights((double) (y-y_offset),&cy);
5392         gamma=((traits & BlendPixelTrait) ? (double) (1.0) :
5393           PerceptibleReciprocal(cy[0]*(cx[0]*alpha[0]+cx[1]*alpha[1]+cx[2]*
5394           alpha[2]+cx[3]*alpha[3])+cy[1]*(cx[0]*alpha[4]+cx[1]*alpha[5]+cx[2]*
5395           alpha[6]+cx[3]*alpha[7])+cy[2]*(cx[0]*alpha[8]+cx[1]*alpha[9]+cx[2]*
5396           alpha[10]+cx[3]*alpha[11])+cy[3]*(cx[0]*alpha[12]+cx[1]*alpha[13]+
5397           cx[2]*alpha[14]+cx[3]*alpha[15])));
5398         SetPixelChannel(destination,channel,ClampToQuantum(gamma*(cy[0]*(cx[0]*
5399           pixels[0]+cx[1]*pixels[1]+cx[2]*pixels[2]+cx[3]*pixels[3])+cy[1]*
5400           (cx[0]*pixels[4]+cx[1]*pixels[5]+cx[2]*pixels[6]+cx[3]*pixels[7])+
5401           cy[2]*(cx[0]*pixels[8]+cx[1]*pixels[9]+cx[2]*pixels[10]+cx[3]*
5402           pixels[11])+cy[3]*(cx[0]*pixels[12]+cx[1]*pixels[13]+cx[2]*
5403           pixels[14]+cx[3]*pixels[15]))),pixel);
5404       }
5405       break;
5406     }
5407   }
5408   return(status);
5409 }
5410 
5411 /*
5412 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5413 %                                                                             %
5414 %                                                                             %
5415 %                                                                             %
5416 %   I n t e r p o l a t e P i x e l I n f o                                   %
5417 %                                                                             %
5418 %                                                                             %
5419 %                                                                             %
5420 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5421 %
5422 %  InterpolatePixelInfo() applies a pixel interpolation method between a
5423 %  floating point coordinate and the pixels surrounding that coordinate.  No
5424 %  pixel area resampling, or scaling of the result is performed.
5425 %
5426 %  Interpolation is restricted to just RGBKA channels.
5427 %
5428 %  The format of the InterpolatePixelInfo method is:
5429 %
5430 %      MagickBooleanType InterpolatePixelInfo(const Image *image,
5431 %        const CacheView *image_view,const PixelInterpolateMethod method,
5432 %        const double x,const double y,PixelInfo *pixel,
5433 %        ExceptionInfo *exception)
5434 %
5435 %  A description of each parameter follows:
5436 %
5437 %    o image: the image.
5438 %
5439 %    o image_view: the image view.
5440 %
5441 %    o method: the pixel color interpolation method.
5442 %
5443 %    o x,y: A double representing the current (x,y) position of the pixel.
5444 %
5445 %    o pixel: return the interpolated pixel here.
5446 %
5447 %    o exception: return any errors or warnings in this structure.
5448 %
5449 */
5450 
AlphaBlendPixelInfo(const Image * image,const Quantum * pixel,PixelInfo * pixel_info,double * alpha)5451 static inline void AlphaBlendPixelInfo(const Image *image,
5452   const Quantum *pixel,PixelInfo *pixel_info,double *alpha)
5453 {
5454   if (image->alpha_trait == UndefinedPixelTrait)
5455     {
5456       *alpha=1.0;
5457       pixel_info->red=(double) GetPixelRed(image,pixel);
5458       pixel_info->green=(double) GetPixelGreen(image,pixel);
5459       pixel_info->blue=(double) GetPixelBlue(image,pixel);
5460       pixel_info->black=0.0;
5461       if (image->colorspace == CMYKColorspace)
5462         pixel_info->black=(double) GetPixelBlack(image,pixel);
5463       pixel_info->alpha=(double) GetPixelAlpha(image,pixel);
5464       return;
5465     }
5466   *alpha=QuantumScale*GetPixelAlpha(image,pixel);
5467   pixel_info->red=(*alpha*GetPixelRed(image,pixel));
5468   pixel_info->green=(*alpha*GetPixelGreen(image,pixel));
5469   pixel_info->blue=(*alpha*GetPixelBlue(image,pixel));
5470   pixel_info->black=0.0;
5471   if (image->colorspace == CMYKColorspace)
5472     pixel_info->black=(*alpha*GetPixelBlack(image,pixel));
5473   pixel_info->alpha=(double) GetPixelAlpha(image,pixel);
5474 }
5475 
InterpolatePixelInfo(const Image * image,const CacheView_ * image_view,const PixelInterpolateMethod method,const double x,const double y,PixelInfo * pixel,ExceptionInfo * exception)5476 MagickExport MagickBooleanType InterpolatePixelInfo(const Image *image,
5477   const CacheView_ *image_view,const PixelInterpolateMethod method,
5478   const double x,const double y,PixelInfo *pixel,ExceptionInfo *exception)
5479 {
5480   MagickBooleanType
5481     status;
5482 
5483   double
5484     alpha[16],
5485     gamma;
5486 
5487   PixelInfo
5488     pixels[16];
5489 
5490   register const Quantum
5491     *p;
5492 
5493   register ssize_t
5494     i;
5495 
5496   ssize_t
5497     x_offset,
5498     y_offset;
5499 
5500   PixelInterpolateMethod
5501     interpolate;
5502 
5503   assert(image != (Image *) NULL);
5504   assert(image->signature == MagickCoreSignature);
5505   assert(image_view != (CacheView *) NULL);
5506   status=MagickTrue;
5507   x_offset=(ssize_t) floor(x);
5508   y_offset=(ssize_t) floor(y);
5509   interpolate=method;
5510   if (interpolate == UndefinedInterpolatePixel)
5511     interpolate=image->interpolate;
5512   GetPixelInfoPixel(image,(const Quantum *) NULL,pixel);
5513   (void) memset(&pixels,0,sizeof(pixels));
5514   switch (interpolate)
5515   {
5516     case AverageInterpolatePixel:  /* nearest 4 neighbours */
5517     case Average9InterpolatePixel:  /* nearest 9 neighbours */
5518     case Average16InterpolatePixel:  /* nearest 16 neighbours */
5519     {
5520       ssize_t
5521         count;
5522 
5523       count=2;  /* size of the area to average - default nearest 4 */
5524       if (interpolate == Average9InterpolatePixel)
5525         {
5526           count=3;
5527           x_offset=(ssize_t) (floor(x+0.5)-1);
5528           y_offset=(ssize_t) (floor(y+0.5)-1);
5529         }
5530       else if (interpolate == Average16InterpolatePixel)
5531         {
5532           count=4;
5533           x_offset--;
5534           y_offset--;
5535         }
5536       p=GetCacheViewVirtualPixels(image_view,x_offset,y_offset,(size_t) count,
5537         (size_t) count,exception);
5538       if (p == (const Quantum *) NULL)
5539         {
5540           status=MagickFalse;
5541           break;
5542         }
5543       count*=count;  /* number of pixels - square of size */
5544       for (i=0; i < (ssize_t) count; i++)
5545       {
5546         AlphaBlendPixelInfo(image,p,pixels,alpha);
5547         gamma=PerceptibleReciprocal(alpha[0]);
5548         pixel->red+=gamma*pixels[0].red;
5549         pixel->green+=gamma*pixels[0].green;
5550         pixel->blue+=gamma*pixels[0].blue;
5551         pixel->black+=gamma*pixels[0].black;
5552         pixel->alpha+=pixels[0].alpha;
5553         p += GetPixelChannels(image);
5554       }
5555       gamma=1.0/count;   /* average weighting of each pixel in area */
5556       pixel->red*=gamma;
5557       pixel->green*=gamma;
5558       pixel->blue*=gamma;
5559       pixel->black*=gamma;
5560       pixel->alpha*=gamma;
5561       break;
5562     }
5563     case BackgroundInterpolatePixel:
5564     {
5565       *pixel=image->background_color;  /* Copy PixelInfo Structure  */
5566       break;
5567     }
5568     case BilinearInterpolatePixel:
5569     default:
5570     {
5571       PointInfo
5572         delta,
5573         epsilon;
5574 
5575       p=GetCacheViewVirtualPixels(image_view,x_offset,y_offset,2,2,exception);
5576       if (p == (const Quantum *) NULL)
5577         {
5578           status=MagickFalse;
5579           break;
5580         }
5581       for (i=0; i < 4L; i++)
5582         AlphaBlendPixelInfo(image,p+i*GetPixelChannels(image),pixels+i,alpha+i);
5583       delta.x=x-x_offset;
5584       delta.y=y-y_offset;
5585       epsilon.x=1.0-delta.x;
5586       epsilon.y=1.0-delta.y;
5587       gamma=((epsilon.y*(epsilon.x*alpha[0]+delta.x*alpha[1])+delta.y*
5588         (epsilon.x*alpha[2]+delta.x*alpha[3])));
5589       gamma=PerceptibleReciprocal(gamma);
5590       pixel->red=gamma*(epsilon.y*(epsilon.x*pixels[0].red+delta.x*
5591         pixels[1].red)+delta.y*(epsilon.x*pixels[2].red+delta.x*pixels[3].red));
5592       pixel->green=gamma*(epsilon.y*(epsilon.x*pixels[0].green+delta.x*
5593         pixels[1].green)+delta.y*(epsilon.x*pixels[2].green+delta.x*
5594         pixels[3].green));
5595       pixel->blue=gamma*(epsilon.y*(epsilon.x*pixels[0].blue+delta.x*
5596         pixels[1].blue)+delta.y*(epsilon.x*pixels[2].blue+delta.x*
5597         pixels[3].blue));
5598       if (image->colorspace == CMYKColorspace)
5599         pixel->black=gamma*(epsilon.y*(epsilon.x*pixels[0].black+delta.x*
5600           pixels[1].black)+delta.y*(epsilon.x*pixels[2].black+delta.x*
5601           pixels[3].black));
5602       gamma=((epsilon.y*(epsilon.x+delta.x)+delta.y*(epsilon.x+delta.x)));
5603       gamma=PerceptibleReciprocal(gamma);
5604       pixel->alpha=gamma*(epsilon.y*(epsilon.x*pixels[0].alpha+delta.x*
5605         pixels[1].alpha)+delta.y*(epsilon.x*pixels[2].alpha+delta.x*
5606         pixels[3].alpha));
5607       break;
5608     }
5609     case BlendInterpolatePixel:
5610     {
5611       p=GetCacheViewVirtualPixels(image_view,x_offset,y_offset,2,2,exception);
5612       if (p == (const Quantum *) NULL)
5613         {
5614           status=MagickFalse;
5615           break;
5616         }
5617       for (i=0; i < 4L; i++)
5618       {
5619         GetPixelInfoPixel(image,p+i*GetPixelChannels(image),pixels+i);
5620         AlphaBlendPixelInfo(image,p+i*GetPixelChannels(image),pixels+i,alpha+i);
5621       }
5622       gamma=1.0;  /* number of pixels blended together (its variable) */
5623       for (i=0; i <= 1L; i++)
5624       {
5625         if ((y-y_offset) >= 0.75)
5626           {
5627             alpha[i]=alpha[i+2];  /* take right pixels */
5628             pixels[i]=pixels[i+2];
5629           }
5630         else
5631           if ((y-y_offset) > 0.25)
5632             {
5633               gamma=2.0;  /* blend both pixels in row */
5634               alpha[i]+=alpha[i+2];  /* add up alpha weights */
5635               pixels[i].red+=pixels[i+2].red;
5636               pixels[i].green+=pixels[i+2].green;
5637               pixels[i].blue+=pixels[i+2].blue;
5638               pixels[i].black+=pixels[i+2].black;
5639               pixels[i].alpha+=pixels[i+2].alpha;
5640             }
5641       }
5642       if ((x-x_offset) >= 0.75)
5643         {
5644           alpha[0]=alpha[1];
5645           pixels[0]=pixels[1];
5646         }
5647       else
5648         if ((x-x_offset) > 0.25)
5649           {
5650             gamma*=2.0;  /* blend both rows */
5651             alpha[0]+= alpha[1];  /* add up alpha weights */
5652             pixels[0].red+=pixels[1].red;
5653             pixels[0].green+=pixels[1].green;
5654             pixels[0].blue+=pixels[1].blue;
5655             pixels[0].black+=pixels[1].black;
5656             pixels[0].alpha+=pixels[1].alpha;
5657           }
5658       gamma=1.0/gamma;
5659       alpha[0]=PerceptibleReciprocal(alpha[0]);
5660       pixel->red=alpha[0]*pixels[0].red;
5661       pixel->green=alpha[0]*pixels[0].green;  /* divide by sum of alpha */
5662       pixel->blue=alpha[0]*pixels[0].blue;
5663       pixel->black=alpha[0]*pixels[0].black;
5664       pixel->alpha=gamma*pixels[0].alpha;   /* divide by number of pixels */
5665       break;
5666     }
5667     case CatromInterpolatePixel:
5668     {
5669       double
5670         cx[4],
5671         cy[4];
5672 
5673       p=GetCacheViewVirtualPixels(image_view,x_offset-1,y_offset-1,4,4,
5674         exception);
5675       if (p == (const Quantum *) NULL)
5676         {
5677           status=MagickFalse;
5678           break;
5679         }
5680       for (i=0; i < 16L; i++)
5681         AlphaBlendPixelInfo(image,p+i*GetPixelChannels(image),pixels+i,alpha+i);
5682       CatromWeights((double) (x-x_offset),&cx);
5683       CatromWeights((double) (y-y_offset),&cy);
5684       pixel->red=(cy[0]*(cx[0]*pixels[0].red+cx[1]*pixels[1].red+cx[2]*
5685         pixels[2].red+cx[3]*pixels[3].red)+cy[1]*(cx[0]*pixels[4].red+cx[1]*
5686         pixels[5].red+cx[2]*pixels[6].red+cx[3]*pixels[7].red)+cy[2]*(cx[0]*
5687         pixels[8].red+cx[1]*pixels[9].red+cx[2]*pixels[10].red+cx[3]*
5688         pixels[11].red)+cy[3]*(cx[0]*pixels[12].red+cx[1]*pixels[13].red+cx[2]*
5689         pixels[14].red+cx[3]*pixels[15].red));
5690       pixel->green=(cy[0]*(cx[0]*pixels[0].green+cx[1]*pixels[1].green+cx[2]*
5691         pixels[2].green+cx[3]*pixels[3].green)+cy[1]*(cx[0]*pixels[4].green+
5692         cx[1]*pixels[5].green+cx[2]*pixels[6].green+cx[3]*pixels[7].green)+
5693         cy[2]*(cx[0]*pixels[8].green+cx[1]*pixels[9].green+cx[2]*
5694         pixels[10].green+cx[3]*pixels[11].green)+cy[3]*(cx[0]*
5695         pixels[12].green+cx[1]*pixels[13].green+cx[2]*pixels[14].green+cx[3]*
5696         pixels[15].green));
5697       pixel->blue=(cy[0]*(cx[0]*pixels[0].blue+cx[1]*pixels[1].blue+cx[2]*
5698         pixels[2].blue+cx[3]*pixels[3].blue)+cy[1]*(cx[0]*pixels[4].blue+cx[1]*
5699         pixels[5].blue+cx[2]*pixels[6].blue+cx[3]*pixels[7].blue)+cy[2]*(cx[0]*
5700         pixels[8].blue+cx[1]*pixels[9].blue+cx[2]*pixels[10].blue+cx[3]*
5701         pixels[11].blue)+cy[3]*(cx[0]*pixels[12].blue+cx[1]*pixels[13].blue+
5702         cx[2]*pixels[14].blue+cx[3]*pixels[15].blue));
5703       if (image->colorspace == CMYKColorspace)
5704         pixel->black=(cy[0]*(cx[0]*pixels[0].black+cx[1]*pixels[1].black+cx[2]*
5705           pixels[2].black+cx[3]*pixels[3].black)+cy[1]*(cx[0]*pixels[4].black+
5706           cx[1]*pixels[5].black+cx[2]*pixels[6].black+cx[3]*pixels[7].black)+
5707           cy[2]*(cx[0]*pixels[8].black+cx[1]*pixels[9].black+cx[2]*
5708           pixels[10].black+cx[3]*pixels[11].black)+cy[3]*(cx[0]*
5709           pixels[12].black+cx[1]*pixels[13].black+cx[2]*pixels[14].black+cx[3]*
5710           pixels[15].black));
5711       pixel->alpha=(cy[0]*(cx[0]*pixels[0].alpha+cx[1]*pixels[1].alpha+cx[2]*
5712         pixels[2].alpha+cx[3]*pixels[3].alpha)+cy[1]*(cx[0]*pixels[4].alpha+
5713         cx[1]*pixels[5].alpha+cx[2]*pixels[6].alpha+cx[3]*pixels[7].alpha)+
5714         cy[2]*(cx[0]*pixels[8].alpha+cx[1]*pixels[9].alpha+cx[2]*
5715         pixels[10].alpha+cx[3]*pixels[11].alpha)+cy[3]*(cx[0]*pixels[12].alpha+
5716         cx[1]*pixels[13].alpha+cx[2]*pixels[14].alpha+cx[3]*pixels[15].alpha));
5717       break;
5718     }
5719     case IntegerInterpolatePixel:
5720     {
5721       p=GetCacheViewVirtualPixels(image_view,x_offset,y_offset,1,1,exception);
5722       if (p == (const Quantum *) NULL)
5723         {
5724           status=MagickFalse;
5725           break;
5726         }
5727       GetPixelInfoPixel(image,p,pixel);
5728       break;
5729     }
5730     case MeshInterpolatePixel:
5731     {
5732       PointInfo
5733         delta,
5734         luminance;
5735 
5736       p=GetCacheViewVirtualPixels(image_view,x_offset,y_offset,2,2,exception);
5737       if (p == (const Quantum *) NULL)
5738         {
5739           status=MagickFalse;
5740           break;
5741         }
5742       delta.x=x-x_offset;
5743       delta.y=y-y_offset;
5744       luminance.x=GetPixelLuma(image,p)-(double)
5745         GetPixelLuma(image,p+3*GetPixelChannels(image));
5746       luminance.y=GetPixelLuma(image,p+GetPixelChannels(image))-(double)
5747         GetPixelLuma(image,p+2*GetPixelChannels(image));
5748       AlphaBlendPixelInfo(image,p,pixels+0,alpha+0);
5749       AlphaBlendPixelInfo(image,p+GetPixelChannels(image),pixels+1,alpha+1);
5750       AlphaBlendPixelInfo(image,p+2*GetPixelChannels(image),pixels+2,alpha+2);
5751       AlphaBlendPixelInfo(image,p+3*GetPixelChannels(image),pixels+3,alpha+3);
5752       if (fabs(luminance.x) < fabs(luminance.y))
5753         {
5754           /*
5755             Diagonal 0-3 NW-SE.
5756           */
5757           if (delta.x <= delta.y)
5758             {
5759               /*
5760                 Bottom-left triangle (pixel: 2, diagonal: 0-3).
5761               */
5762               delta.y=1.0-delta.y;
5763               gamma=MeshInterpolate(&delta,alpha[2],alpha[3],alpha[0]);
5764               gamma=PerceptibleReciprocal(gamma);
5765               pixel->red=gamma*MeshInterpolate(&delta,pixels[2].red,
5766                 pixels[3].red,pixels[0].red);
5767               pixel->green=gamma*MeshInterpolate(&delta,pixels[2].green,
5768                 pixels[3].green,pixels[0].green);
5769               pixel->blue=gamma*MeshInterpolate(&delta,pixels[2].blue,
5770                 pixels[3].blue,pixels[0].blue);
5771               if (image->colorspace == CMYKColorspace)
5772                 pixel->black=gamma*MeshInterpolate(&delta,pixels[2].black,
5773                   pixels[3].black,pixels[0].black);
5774               gamma=MeshInterpolate(&delta,1.0,1.0,1.0);
5775               pixel->alpha=gamma*MeshInterpolate(&delta,pixels[2].alpha,
5776                 pixels[3].alpha,pixels[0].alpha);
5777             }
5778           else
5779             {
5780               /*
5781                 Top-right triangle (pixel:1 , diagonal: 0-3).
5782               */
5783               delta.x=1.0-delta.x;
5784               gamma=MeshInterpolate(&delta,alpha[1],alpha[0],alpha[3]);
5785               gamma=PerceptibleReciprocal(gamma);
5786               pixel->red=gamma*MeshInterpolate(&delta,pixels[1].red,
5787                 pixels[0].red,pixels[3].red);
5788               pixel->green=gamma*MeshInterpolate(&delta,pixels[1].green,
5789                 pixels[0].green,pixels[3].green);
5790               pixel->blue=gamma*MeshInterpolate(&delta,pixels[1].blue,
5791                 pixels[0].blue,pixels[3].blue);
5792               if (image->colorspace == CMYKColorspace)
5793                 pixel->black=gamma*MeshInterpolate(&delta,pixels[1].black,
5794                   pixels[0].black,pixels[3].black);
5795               gamma=MeshInterpolate(&delta,1.0,1.0,1.0);
5796               pixel->alpha=gamma*MeshInterpolate(&delta,pixels[1].alpha,
5797                 pixels[0].alpha,pixels[3].alpha);
5798             }
5799         }
5800       else
5801         {
5802           /*
5803             Diagonal 1-2 NE-SW.
5804           */
5805           if (delta.x <= (1.0-delta.y))
5806             {
5807               /*
5808                 Top-left triangle (pixel: 0, diagonal: 1-2).
5809               */
5810               gamma=MeshInterpolate(&delta,alpha[0],alpha[1],alpha[2]);
5811               gamma=PerceptibleReciprocal(gamma);
5812               pixel->red=gamma*MeshInterpolate(&delta,pixels[0].red,
5813                 pixels[1].red,pixels[2].red);
5814               pixel->green=gamma*MeshInterpolate(&delta,pixels[0].green,
5815                 pixels[1].green,pixels[2].green);
5816               pixel->blue=gamma*MeshInterpolate(&delta,pixels[0].blue,
5817                 pixels[1].blue,pixels[2].blue);
5818               if (image->colorspace == CMYKColorspace)
5819                 pixel->black=gamma*MeshInterpolate(&delta,pixels[0].black,
5820                   pixels[1].black,pixels[2].black);
5821               gamma=MeshInterpolate(&delta,1.0,1.0,1.0);
5822               pixel->alpha=gamma*MeshInterpolate(&delta,pixels[0].alpha,
5823                 pixels[1].alpha,pixels[2].alpha);
5824             }
5825           else
5826             {
5827               /*
5828                 Bottom-right triangle (pixel: 3, diagonal: 1-2).
5829               */
5830               delta.x=1.0-delta.x;
5831               delta.y=1.0-delta.y;
5832               gamma=MeshInterpolate(&delta,alpha[3],alpha[2],alpha[1]);
5833               gamma=PerceptibleReciprocal(gamma);
5834               pixel->red=gamma*MeshInterpolate(&delta,pixels[3].red,
5835                 pixels[2].red,pixels[1].red);
5836               pixel->green=gamma*MeshInterpolate(&delta,pixels[3].green,
5837                 pixels[2].green,pixels[1].green);
5838               pixel->blue=gamma*MeshInterpolate(&delta,pixels[3].blue,
5839                 pixels[2].blue,pixels[1].blue);
5840               if (image->colorspace == CMYKColorspace)
5841                 pixel->black=gamma*MeshInterpolate(&delta,pixels[3].black,
5842                   pixels[2].black,pixels[1].black);
5843               gamma=MeshInterpolate(&delta,1.0,1.0,1.0);
5844               pixel->alpha=gamma*MeshInterpolate(&delta,pixels[3].alpha,
5845                 pixels[2].alpha,pixels[1].alpha);
5846             }
5847         }
5848       break;
5849     }
5850     case NearestInterpolatePixel:
5851     {
5852       x_offset=(ssize_t) floor(x+0.5);
5853       y_offset=(ssize_t) floor(y+0.5);
5854       p=GetCacheViewVirtualPixels(image_view,x_offset,y_offset,1,1,exception);
5855       if (p == (const Quantum *) NULL)
5856         {
5857           status=MagickFalse;
5858           break;
5859         }
5860       GetPixelInfoPixel(image,p,pixel);
5861       break;
5862     }
5863     case SplineInterpolatePixel:
5864     {
5865       double
5866         cx[4],
5867         cy[4];
5868 
5869       p=GetCacheViewVirtualPixels(image_view,x_offset-1,y_offset-1,4,4,
5870         exception);
5871       if (p == (const Quantum *) NULL)
5872         {
5873           status=MagickFalse;
5874           break;
5875         }
5876       for (i=0; i < 16L; i++)
5877         AlphaBlendPixelInfo(image,p+i*GetPixelChannels(image),pixels+i,alpha+i);
5878       SplineWeights((double) (x-x_offset),&cx);
5879       SplineWeights((double) (y-y_offset),&cy);
5880       pixel->red=(cy[0]*(cx[0]*pixels[0].red+cx[1]*pixels[1].red+cx[2]*
5881         pixels[2].red+cx[3]*pixels[3].red)+cy[1]*(cx[0]*pixels[4].red+cx[1]*
5882         pixels[5].red+cx[2]*pixels[6].red+cx[3]*pixels[7].red)+cy[2]*(cx[0]*
5883         pixels[8].red+cx[1]*pixels[9].red+cx[2]*pixels[10].red+cx[3]*
5884         pixels[11].red)+cy[3]*(cx[0]*pixels[12].red+cx[1]*pixels[13].red+cx[2]*
5885         pixels[14].red+cx[3]*pixels[15].red));
5886       pixel->green=(cy[0]*(cx[0]*pixels[0].green+cx[1]*pixels[1].green+cx[2]*
5887         pixels[2].green+cx[3]*pixels[3].green)+cy[1]*(cx[0]*pixels[4].green+
5888         cx[1]*pixels[5].green+cx[2]*pixels[6].green+cx[3]*pixels[7].green)+
5889         cy[2]*(cx[0]*pixels[8].green+cx[1]*pixels[9].green+cx[2]*
5890         pixels[10].green+cx[3]*pixels[11].green)+cy[3]*(cx[0]*pixels[12].green+
5891         cx[1]*pixels[13].green+cx[2]*pixels[14].green+cx[3]*pixels[15].green));
5892       pixel->blue=(cy[0]*(cx[0]*pixels[0].blue+cx[1]*pixels[1].blue+cx[2]*
5893         pixels[2].blue+cx[3]*pixels[3].blue)+cy[1]*(cx[0]*pixels[4].blue+cx[1]*
5894         pixels[5].blue+cx[2]*pixels[6].blue+cx[3]*pixels[7].blue)+cy[2]*(cx[0]*
5895         pixels[8].blue+cx[1]*pixels[9].blue+cx[2]*pixels[10].blue+cx[3]*
5896         pixels[11].blue)+cy[3]*(cx[0]*pixels[12].blue+cx[1]*pixels[13].blue+
5897         cx[2]*pixels[14].blue+cx[3]*pixels[15].blue));
5898       if (image->colorspace == CMYKColorspace)
5899         pixel->black=(cy[0]*(cx[0]*pixels[0].black+cx[1]*pixels[1].black+cx[2]*
5900           pixels[2].black+cx[3]*pixels[3].black)+cy[1]*(cx[0]*pixels[4].black+
5901           cx[1]*pixels[5].black+cx[2]*pixels[6].black+cx[3]*pixels[7].black)+
5902           cy[2]*(cx[0]*pixels[8].black+cx[1]*pixels[9].black+cx[2]*
5903           pixels[10].black+cx[3]*pixels[11].black)+cy[3]*(cx[0]*
5904           pixels[12].black+cx[1]*pixels[13].black+cx[2]*pixels[14].black+cx[3]*
5905           pixels[15].black));
5906       pixel->alpha=(cy[0]*(cx[0]*pixels[0].alpha+cx[1]*pixels[1].alpha+cx[2]*
5907         pixels[2].alpha+cx[3]*pixels[3].alpha)+cy[1]*(cx[0]*pixels[4].alpha+
5908         cx[1]*pixels[5].alpha+cx[2]*pixels[6].alpha+cx[3]*pixels[7].alpha)+
5909         cy[2]*(cx[0]*pixels[8].alpha+cx[1]*pixels[9].alpha+cx[2]*
5910         pixels[10].alpha+cx[3]*pixels[11].alpha)+cy[3]*(cx[0]*pixels[12].alpha+
5911         cx[1]*pixels[13].alpha+cx[2]*pixels[14].alpha+cx[3]*pixels[15].alpha));
5912       break;
5913     }
5914   }
5915   return(status);
5916 }
5917 
5918 /*
5919 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5920 %                                                                             %
5921 %                                                                             %
5922 %                                                                             %
5923 +   I s F u z z y E q u i v a l e n c e P i x e l                             %
5924 %                                                                             %
5925 %                                                                             %
5926 %                                                                             %
5927 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5928 %
5929 %  IsFuzzyEquivalencePixel() returns MagickTrue if the distance between two
5930 %  pixels is less than the specified distance in a linear three (or four)
5931 %  dimensional color space.
5932 %
5933 %  The format of the IsFuzzyEquivalencePixel method is:
5934 %
5935 %      void IsFuzzyEquivalencePixel(const Image *source,const Quantum *p,
5936 %        const Image *destination,const Quantum *q)
5937 %
5938 %  A description of each parameter follows:
5939 %
5940 %    o source: the source image.
5941 %
5942 %    o p: Pixel p.
5943 %
5944 %    o destination: the destination image.
5945 %
5946 %    o q: Pixel q.
5947 %
5948 */
IsFuzzyEquivalencePixel(const Image * source,const Quantum * p,const Image * destination,const Quantum * q)5949 MagickExport MagickBooleanType IsFuzzyEquivalencePixel(const Image *source,
5950   const Quantum *p,const Image *destination,const Quantum *q)
5951 {
5952   double
5953     fuzz,
5954     pixel;
5955 
5956   register double
5957     distance,
5958     scale;
5959 
5960   fuzz=GetFuzzyColorDistance(source,destination);
5961   scale=1.0;
5962   distance=0.0;
5963   if (source->alpha_trait != UndefinedPixelTrait ||
5964       destination->alpha_trait != UndefinedPixelTrait)
5965     {
5966       /*
5967         Transparencies are involved - set alpha distance
5968       */
5969       pixel=GetPixelAlpha(source,p)-(double) GetPixelAlpha(destination,q);
5970       distance=pixel*pixel;
5971       if (distance > fuzz)
5972         return(MagickFalse);
5973       /*
5974         Generate a alpha scaling factor to generate a 4D cone on colorspace
5975         Note that if one color is transparent, distance has no color component.
5976       */
5977       if (source->alpha_trait != UndefinedPixelTrait)
5978         scale=QuantumScale*GetPixelAlpha(source,p);
5979       if (destination->alpha_trait != UndefinedPixelTrait)
5980         scale*=QuantumScale*GetPixelAlpha(destination,q);
5981       if (scale <= MagickEpsilon)
5982         return(MagickTrue);
5983     }
5984   /*
5985     RGB or CMY color cube
5986   */
5987   distance*=3.0;  /* rescale appropriately */
5988   fuzz*=3.0;
5989   pixel=GetPixelRed(source,p)-(double) GetPixelRed(destination,q);
5990   if ((source->colorspace == HSLColorspace) ||
5991       (source->colorspace == HSBColorspace) ||
5992       (source->colorspace == HWBColorspace))
5993     {
5994       /*
5995         Compute an arc distance for hue.  It should be a vector angle of
5996         'S'/'W' length with 'L'/'B' forming appropriate cones.
5997       */
5998       if (fabs((double) pixel) > (QuantumRange/2))
5999         pixel-=QuantumRange;
6000       pixel*=2;
6001     }
6002   distance+=scale*pixel*pixel;
6003   if (distance > fuzz)
6004     return(MagickFalse);
6005   pixel=GetPixelGreen(source,p)-(double) GetPixelGreen(destination,q);
6006   distance+=scale*pixel*pixel;
6007   if (distance > fuzz)
6008     return(MagickFalse);
6009   pixel=GetPixelBlue(source,p)-(double) GetPixelBlue(destination,q);
6010   distance+=scale*pixel*pixel;
6011   if (distance > fuzz)
6012     return(MagickFalse);
6013   return(MagickTrue);
6014 }
6015 
6016 /*
6017 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6018 %                                                                             %
6019 %                                                                             %
6020 %                                                                             %
6021 +   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                     %
6022 %                                                                             %
6023 %                                                                             %
6024 %                                                                             %
6025 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6026 %
6027 %  IsFuzzyEquivalencePixelInfo() returns true if the distance between two
6028 %  colors is less than the specified distance in a linear three (or four)
6029 %  dimensional color space.
6030 %
6031 %  This implements the equivalent of:
6032 %    fuzz < sqrt(color_distance^2 * u.a*v.a  + alpha_distance^2)
6033 %
6034 %  Which produces a multi-dimensional cone for that colorspace along the
6035 %  transparency vector.
6036 %
6037 %  For example for an RGB:
6038 %    color_distance^2  = ( (u.r-v.r)^2 + (u.g-v.g)^2 + (u.b-v.b)^2 ) / 3
6039 %
6040 %  See http://imagemagick.org/Usage/bugs/fuzz_distance/
6041 %
6042 %  Hue colorspace distances need more work.  Hue is not a distance, it is an
6043 %  angle!
6044 %
6045 %  A check that q is in the same color space as p should be made and the
6046 %  appropriate mapping made.  -- Anthony Thyssen  8 December 2010
6047 %
6048 %  The format of the IsFuzzyEquivalencePixelInfo method is:
6049 %
6050 %      MagickBooleanType IsFuzzyEquivalencePixelInfo(const PixelInfo *p,
6051 %        const PixelInfo *q)
6052 %
6053 %  A description of each parameter follows:
6054 %
6055 %    o p: Pixel p.
6056 %
6057 %    o q: Pixel q.
6058 %
6059 */
IsFuzzyEquivalencePixelInfo(const PixelInfo * p,const PixelInfo * q)6060 MagickExport MagickBooleanType IsFuzzyEquivalencePixelInfo(const PixelInfo *p,
6061   const PixelInfo *q)
6062 {
6063   double
6064     fuzz,
6065     pixel;
6066 
6067   register double
6068     scale,
6069     distance;
6070 
6071   fuzz=(double) MagickMax(MagickMax(p->fuzz,q->fuzz),(MagickRealType)
6072     MagickSQ1_2);
6073   fuzz*=fuzz;
6074   scale=1.0;
6075   distance=0.0;
6076   if ((p->alpha_trait != UndefinedPixelTrait) ||
6077       (q->alpha_trait != UndefinedPixelTrait))
6078     {
6079       /*
6080         Transparencies are involved - set alpha distance.
6081       */
6082       pixel=(p->alpha_trait != UndefinedPixelTrait ? p->alpha : OpaqueAlpha)-
6083         (q->alpha_trait != UndefinedPixelTrait ? q->alpha : OpaqueAlpha);
6084       distance=pixel*pixel;
6085       if (distance > fuzz)
6086         return(MagickFalse);
6087       /*
6088         Generate a alpha scaling factor to generate a 4D cone on colorspace.
6089         If one color is transparent, distance has no color component.
6090       */
6091       if (p->alpha_trait != UndefinedPixelTrait)
6092         scale=(QuantumScale*p->alpha);
6093       if (q->alpha_trait != UndefinedPixelTrait)
6094         scale*=(QuantumScale*q->alpha);
6095       if (scale <= MagickEpsilon )
6096         return(MagickTrue);
6097     }
6098   /*
6099     CMYK create a CMY cube with a multi-dimensional cone toward black.
6100   */
6101   if (p->colorspace == CMYKColorspace)
6102     {
6103       pixel=p->black-q->black;
6104       distance+=pixel*pixel*scale;
6105       if (distance > fuzz)
6106         return(MagickFalse);
6107       scale*=(double) (QuantumScale*(QuantumRange-p->black));
6108       scale*=(double) (QuantumScale*(QuantumRange-q->black));
6109     }
6110   /*
6111     RGB or CMY color cube.
6112   */
6113   distance*=3.0;  /* rescale appropriately */
6114   fuzz*=3.0;
6115   pixel=p->red-q->red;
6116   if ((p->colorspace == HSLColorspace) || (p->colorspace == HSBColorspace) ||
6117       (p->colorspace == HWBColorspace))
6118     {
6119       /*
6120         This calculates a arc distance for hue-- it should be a vector
6121         angle of 'S'/'W' length with 'L'/'B' forming appropriate cones.
6122         In other words this is a hack - Anthony.
6123       */
6124       if (fabs((double) pixel) > (QuantumRange/2))
6125         pixel-=QuantumRange;
6126       pixel*=2;
6127     }
6128   distance+=pixel*pixel*scale;
6129   if (distance > fuzz)
6130     return(MagickFalse);
6131   pixel=p->green-q->green;
6132   distance+=pixel*pixel*scale;
6133   if (distance > fuzz)
6134     return(MagickFalse);
6135   pixel=p->blue-q->blue;
6136   distance+=pixel*pixel*scale;
6137   if (distance > fuzz)
6138     return(MagickFalse);
6139   return(MagickTrue);
6140 }
6141 
6142 /*
6143 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6144 %                                                                             %
6145 %                                                                             %
6146 %                                                                             %
6147 %   S e t P i x e l C h a n n e l M a s k                                     %
6148 %                                                                             %
6149 %                                                                             %
6150 %                                                                             %
6151 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6152 %
6153 %  SetPixelChannelMask() sets the pixel channel map from the specified channel
6154 %  mask.
6155 %
6156 %  The format of the SetPixelChannelMask method is:
6157 %
6158 %      ChannelType SetPixelChannelMask(Image *image,
6159 %        const ChannelType channel_mask)
6160 %
6161 %  A description of each parameter follows:
6162 %
6163 %    o image: the image.
6164 %
6165 %    o channel_mask: the channel mask.
6166 %
6167 */
6168 
LogPixelChannels(const Image * image)6169 static void LogPixelChannels(const Image *image)
6170 {
6171   register ssize_t
6172     i;
6173 
6174   (void) LogMagickEvent(PixelEvent,GetMagickModule(),"%s[%08x]",
6175     image->filename,image->channel_mask);
6176   for (i=0; i < (ssize_t) image->number_channels; i++)
6177   {
6178     char
6179       channel_name[MagickPathExtent],
6180       traits[MagickPathExtent];
6181 
6182     const char
6183       *name;
6184 
6185     PixelChannel
6186       channel;
6187 
6188     channel=GetPixelChannelChannel(image,i);
6189     switch (channel)
6190     {
6191       case RedPixelChannel:
6192       {
6193         name="red";
6194         if (image->colorspace == CMYKColorspace)
6195           name="cyan";
6196         if ((image->colorspace == LinearGRAYColorspace) ||
6197             (image->colorspace == GRAYColorspace))
6198           name="gray";
6199         break;
6200       }
6201       case GreenPixelChannel:
6202       {
6203         name="green";
6204         if (image->colorspace == CMYKColorspace)
6205           name="magenta";
6206         break;
6207       }
6208       case BluePixelChannel:
6209       {
6210         name="blue";
6211         if (image->colorspace == CMYKColorspace)
6212           name="yellow";
6213         break;
6214       }
6215       case BlackPixelChannel:
6216       {
6217         name="black";
6218         if (image->storage_class == PseudoClass)
6219           name="index";
6220         break;
6221       }
6222       case IndexPixelChannel:
6223       {
6224         name="index";
6225         break;
6226       }
6227       case AlphaPixelChannel:
6228       {
6229         name="alpha";
6230         break;
6231       }
6232       case ReadMaskPixelChannel:
6233       {
6234         name="read-mask";
6235         break;
6236       }
6237       case WriteMaskPixelChannel:
6238       {
6239         name="write-mask";
6240         break;
6241       }
6242       case CompositeMaskPixelChannel:
6243       {
6244         name="composite-mask";
6245         break;
6246       }
6247       case MetaPixelChannel:
6248       {
6249         name="meta";
6250         break;
6251       }
6252       default:
6253         name="undefined";
6254     }
6255     if (image->colorspace ==  UndefinedColorspace)
6256       {
6257         (void) FormatLocaleString(channel_name,MagickPathExtent,"%.20g",
6258           (double) channel);
6259         name=(const char *) channel_name;
6260       }
6261     *traits='\0';
6262     if ((GetPixelChannelTraits(image,channel) & UpdatePixelTrait) != 0)
6263       (void) ConcatenateMagickString(traits,"update,",MagickPathExtent);
6264     if ((GetPixelChannelTraits(image,channel) & BlendPixelTrait) != 0)
6265       (void) ConcatenateMagickString(traits,"blend,",MagickPathExtent);
6266     if ((GetPixelChannelTraits(image,channel) & CopyPixelTrait) != 0)
6267       (void) ConcatenateMagickString(traits,"copy,",MagickPathExtent);
6268     if (*traits == '\0')
6269       (void) ConcatenateMagickString(traits,"undefined,",MagickPathExtent);
6270     traits[strlen(traits)-1]='\0';
6271     (void) LogMagickEvent(PixelEvent,GetMagickModule(),"  %.20g: %s (%s)",
6272       (double) i,name,traits);
6273   }
6274 }
6275 
SetPixelChannelMask(Image * image,const ChannelType channel_mask)6276 MagickExport ChannelType SetPixelChannelMask(Image *image,
6277   const ChannelType channel_mask)
6278 {
6279 #define GetChannelBit(mask,bit)  (((size_t) (mask) >> (size_t) (bit)) & 0x01)
6280 
6281   ChannelType
6282     mask;
6283 
6284   register ssize_t
6285     i;
6286 
6287   assert(image != (Image *) NULL);
6288   assert(image->signature == MagickCoreSignature);
6289   if (image->debug != MagickFalse)
6290     (void) LogMagickEvent(PixelEvent,GetMagickModule(),"%s[%08x]",
6291       image->filename,channel_mask);
6292   mask=image->channel_mask;
6293   image->channel_mask=channel_mask;
6294   for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
6295   {
6296     PixelChannel channel = GetPixelChannelChannel(image,i);
6297     if (GetChannelBit(channel_mask,channel) == 0)
6298       {
6299         SetPixelChannelTraits(image,channel,CopyPixelTrait);
6300         continue;
6301       }
6302     if (channel == AlphaPixelChannel)
6303       {
6304         if ((image->alpha_trait & CopyPixelTrait) != 0)
6305           {
6306             SetPixelChannelTraits(image,channel,CopyPixelTrait);
6307             continue;
6308           }
6309         SetPixelChannelTraits(image,channel,UpdatePixelTrait);
6310         continue;
6311       }
6312     if (image->alpha_trait != UndefinedPixelTrait)
6313       {
6314         SetPixelChannelTraits(image,channel,(const PixelTrait)
6315           (UpdatePixelTrait | BlendPixelTrait));
6316         continue;
6317       }
6318     SetPixelChannelTraits(image,channel,UpdatePixelTrait);
6319   }
6320   if (image->storage_class == PseudoClass)
6321     SetPixelChannelTraits(image,IndexPixelChannel,CopyPixelTrait);
6322   if ((image->channels & ReadMaskChannel) != 0)
6323     SetPixelChannelTraits(image,ReadMaskPixelChannel,CopyPixelTrait);
6324   if ((image->channels & WriteMaskChannel) != 0)
6325     SetPixelChannelTraits(image,WriteMaskPixelChannel,CopyPixelTrait);
6326   if ((image->channels & CompositeMaskChannel) != 0)
6327     SetPixelChannelTraits(image,CompositeMaskPixelChannel,CopyPixelTrait);
6328   if (image->debug != MagickFalse)
6329     LogPixelChannels(image);
6330   return(mask);
6331 }
6332 
6333 /*
6334 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6335 %                                                                             %
6336 %                                                                             %
6337 %                                                                             %
6338 %   S e t P i x e l M e t a C h a n n e l s                                   %
6339 %                                                                             %
6340 %                                                                             %
6341 %                                                                             %
6342 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6343 %
6344 %  SetPixelMetaChannels() sets the image meta channels.
6345 %
6346 %  The format of the SetPixelMetaChannels method is:
6347 %
6348 %      MagickBooleanType SetPixelMetaChannels(Image *image,
6349 %        const size_t number_meta_channels,ExceptionInfo *exception)
6350 %
6351 %  A description of each parameter follows:
6352 %
6353 %    o image: the image.
6354 %
6355 %    o number_meta_channels:  the number of meta channels.
6356 %
6357 %    o exception: return any errors or warnings in this structure.
6358 %
6359 */
SetPixelMetaChannels(Image * image,const size_t number_meta_channels,ExceptionInfo * exception)6360 MagickExport MagickBooleanType SetPixelMetaChannels(Image *image,
6361   const size_t number_meta_channels,ExceptionInfo *exception)
6362 {
6363   image->number_meta_channels=number_meta_channels;
6364   InitializePixelChannelMap(image);
6365   return(SyncImagePixelCache(image,exception));
6366 }
6367