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