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