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