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