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