]> granicus.if.org Git - imagemagick/blob - MagickCore/pixel.c
sigmoidal-contrast: prevent argument out of range and remove unnecessary ClampToQuantum
[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 (GetPixelChannelChannel(image,i)) \
92     { \
93       case RedPixelChannel: \
94       { \
95         name="red"; \
96         if (image->colorspace == CMYKColorspace) \
97           name="cyan"; \
98         if (image->colorspace == GRAYColorspace) \
99           name="gray"; \
100         break; \
101       } \
102       case GreenPixelChannel: \
103       { \
104         name="green"; \
105         if (image->colorspace == CMYKColorspace) \
106           name="magenta"; \
107         break; \
108       } \
109       case BluePixelChannel: \
110       { \
111         name="blue"; \
112         if (image->colorspace == CMYKColorspace) \
113           name="yellow"; \
114         break; \
115       } \
116       case BlackPixelChannel: \
117       { \
118         name="black"; \
119         if (image->storage_class == PseudoClass) \
120           name="index"; \
121         break; \
122       } \
123       case IndexPixelChannel: \
124       { \
125         name="index"; \
126         break; \
127       } \
128       case AlphaPixelChannel: \
129       { \
130         name="alpha"; \
131         break; \
132       } \
133       case 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=GetPixelChannelChannel(image,i); \
147     *traits='\0'; \
148     if ((GetPixelChannelTraits(image,channel) & UpdatePixelTrait) != 0) \
149       (void) ConcatenateMagickString(traits,"update,",MaxTextExtent); \
150     if ((GetPixelChannelTraits(image,channel) & BlendPixelTrait) != 0) \
151       (void) ConcatenateMagickString(traits,"blend,",MaxTextExtent); \
152     if ((GetPixelChannelTraits(image,channel) & CopyPixelTrait) != 0) \
153       (void) ConcatenateMagickString(traits,"copy,",MaxTextExtent); \
154     if (*traits == '\0') \
155       (void) ConcatenateMagickString(traits,"undefined,",MaxTextExtent); \
156     traits[strlen(traits)-1]='\0'; \
157     (void) LogMagickEvent(PixelEvent,GetMagickModule(),"  %.20g: %s (%s)", \
158       (double) i,name,traits); \
159   } \
160 }
161 \f
162 /*
163 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
164 %                                                                             %
165 %                                                                             %
166 %                                                                             %
167 +   A c q u i r e P i x e l C h a n n e l M a p                               %
168 %                                                                             %
169 %                                                                             %
170 %                                                                             %
171 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
172 %
173 %  AcquirePixelChannelMap() acquires a pixel component map.
174 %
175 %  The format of the AcquirePixelChannelMap() method is:
176 %
177 %      PixelChannelMap *AcquirePixelChannelMap(void)
178 %
179 */
180 MagickExport PixelChannelMap *AcquirePixelChannelMap(void)
181 {
182   PixelChannelMap
183     *channel_map;
184
185   register ssize_t
186     i;
187
188   channel_map=(PixelChannelMap *) AcquireQuantumMemory(MaxPixelChannels,
189     sizeof(*channel_map));
190   if (channel_map == (PixelChannelMap *) NULL)
191     ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
192   (void) ResetMagickMemory(channel_map,0,MaxPixelChannels*sizeof(*channel_map));
193   for (i=0; i < MaxPixelChannels; i++)
194     channel_map[i].channel=(PixelChannel) i;
195   return(channel_map);
196 }
197 \f
198 /*
199 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
200 %                                                                             %
201 %                                                                             %
202 %                                                                             %
203 +   C l o n e P i x e l C h a n n e l M a p                                   %
204 %                                                                             %
205 %                                                                             %
206 %                                                                             %
207 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
208 %
209 %  ClonePixelChannelMap() clones a pixel component map.
210 %
211 %  The format of the ClonePixelChannelMap() method is:
212 %
213 %      PixelChannelMap *ClonePixelChannelMap(PixelChannelMap *channel_map)
214 %
215 %  A description of each parameter follows:
216 %
217 %    o channel_map: the pixel component map.
218 %
219 */
220 MagickExport PixelChannelMap *ClonePixelChannelMap(PixelChannelMap *channel_map)
221 {
222   PixelChannelMap
223     *clone_map;
224
225   assert(channel_map != (PixelChannelMap *) NULL);
226   clone_map=AcquirePixelChannelMap();
227   if (clone_map == (PixelChannelMap *) NULL)
228     return((PixelChannelMap *) NULL);
229   (void) CopyMagickMemory(clone_map,channel_map,MaxPixelChannels*
230     sizeof(*channel_map));
231   return(clone_map);
232 }
233 \f
234 /*
235 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
236 %                                                                             %
237 %                                                                             %
238 %                                                                             %
239 +   C l o n e P i x e l I n f o                                               %
240 %                                                                             %
241 %                                                                             %
242 %                                                                             %
243 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
244 %
245 %  ClonePixelInfo() makes a duplicate of the given pixel info structure, or if
246 %  pixel info is NULL, a new one.
247 %
248 %  The format of the ClonePixelInfo method is:
249 %
250 %      PixelInfo *ClonePixelInfo(const PixelInfo *pixel_info)
251 %
252 %  A description of each parameter follows:
253 %
254 %    o pixel_info: the pixel info.
255 %
256 */
257 MagickExport PixelInfo *ClonePixelInfo(const PixelInfo *pixel)
258 {
259   PixelInfo
260     *pixel_info;
261
262   pixel_info=(PixelInfo *) AcquireQuantumMemory(1,sizeof(*pixel_info));
263   if (pixel_info == (PixelInfo *) NULL)
264     ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
265   *pixel_info=(*pixel);
266   return(pixel_info);
267 }
268 \f
269 /*
270 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
271 %                                                                             %
272 %                                                                             %
273 %                                                                             %
274 +   D e 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(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(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(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(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(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(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(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(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->alpha_trait=UndefinedPixelTrait;
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=(double) 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->alpha_trait=image->alpha_trait;
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(QuantumRange*(*p)),q);
2373           p++;
2374           SetPixelGreen(image,ClampToQuantum(QuantumRange*(*p)),q);
2375           p++;
2376           SetPixelRed(image,ClampToQuantum(QuantumRange*(*p)),q);
2377           p++;
2378           q+=GetPixelChannels(image);
2379         }
2380         if (SyncAuthenticPixels(image,exception) == MagickFalse)
2381           break;
2382       }
2383       return;
2384     }
2385   if (LocaleCompare(map,"BGRA") == 0)
2386     {
2387       for (y=0; y < (ssize_t) roi->height; y++)
2388       {
2389         q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
2390         if (q == (Quantum *) NULL)
2391           break;
2392         for (x=0; x < (ssize_t) roi->width; x++)
2393         {
2394           SetPixelBlue(image,ClampToQuantum(QuantumRange*(*p)),q);
2395           p++;
2396           SetPixelGreen(image,ClampToQuantum(QuantumRange*(*p)),q);
2397           p++;
2398           SetPixelRed(image,ClampToQuantum(QuantumRange*(*p)),q);
2399           p++;
2400           SetPixelAlpha(image,ClampToQuantum(QuantumRange*(*p)),q);
2401           p++;
2402           q+=GetPixelChannels(image);
2403         }
2404         if (SyncAuthenticPixels(image,exception) == MagickFalse)
2405           break;
2406       }
2407       return;
2408     }
2409   if (LocaleCompare(map,"BGRP") == 0)
2410     {
2411       for (y=0; y < (ssize_t) roi->height; y++)
2412       {
2413         q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
2414         if (q == (Quantum *) NULL)
2415           break;
2416         for (x=0; x < (ssize_t) roi->width; x++)
2417         {
2418           SetPixelBlue(image,ClampToQuantum(QuantumRange*(*p)),q);
2419           p++;
2420           SetPixelGreen(image,ClampToQuantum(QuantumRange*(*p)),q);
2421           p++;
2422           SetPixelRed(image,ClampToQuantum(QuantumRange*(*p)),q);
2423           p++;
2424           p++;
2425           q+=GetPixelChannels(image);
2426         }
2427         if (SyncAuthenticPixels(image,exception) == MagickFalse)
2428           break;
2429       }
2430       return;
2431     }
2432   if (LocaleCompare(map,"I") == 0)
2433     {
2434       for (y=0; y < (ssize_t) roi->height; y++)
2435       {
2436         q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
2437         if (q == (Quantum *) NULL)
2438           break;
2439         for (x=0; x < (ssize_t) roi->width; x++)
2440         {
2441           SetPixelGray(image,ClampToQuantum(QuantumRange*(*p)),q);
2442           p++;
2443           q+=GetPixelChannels(image);
2444         }
2445         if (SyncAuthenticPixels(image,exception) == MagickFalse)
2446           break;
2447       }
2448       return;
2449     }
2450   if (LocaleCompare(map,"RGB") == 0)
2451     {
2452       for (y=0; y < (ssize_t) roi->height; y++)
2453       {
2454         q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
2455         if (q == (Quantum *) NULL)
2456           break;
2457         for (x=0; x < (ssize_t) roi->width; x++)
2458         {
2459           SetPixelRed(image,ClampToQuantum(QuantumRange*(*p)),q);
2460           p++;
2461           SetPixelGreen(image,ClampToQuantum(QuantumRange*(*p)),q);
2462           p++;
2463           SetPixelBlue(image,ClampToQuantum(QuantumRange*(*p)),q);
2464           p++;
2465           q+=GetPixelChannels(image);
2466         }
2467         if (SyncAuthenticPixels(image,exception) == MagickFalse)
2468           break;
2469       }
2470       return;
2471     }
2472   if (LocaleCompare(map,"RGBA") == 0)
2473     {
2474       for (y=0; y < (ssize_t) roi->height; y++)
2475       {
2476         q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
2477         if (q == (Quantum *) NULL)
2478           break;
2479         for (x=0; x < (ssize_t) roi->width; x++)
2480         {
2481           SetPixelRed(image,ClampToQuantum(QuantumRange*(*p)),q);
2482           p++;
2483           SetPixelGreen(image,ClampToQuantum(QuantumRange*(*p)),q);
2484           p++;
2485           SetPixelBlue(image,ClampToQuantum(QuantumRange*(*p)),q);
2486           p++;
2487           SetPixelAlpha(image,ClampToQuantum(QuantumRange*(*p)),q);
2488           p++;
2489           q+=GetPixelChannels(image);
2490         }
2491         if (SyncAuthenticPixels(image,exception) == MagickFalse)
2492           break;
2493       }
2494       return;
2495     }
2496   if (LocaleCompare(map,"RGBP") == 0)
2497     {
2498       for (y=0; y < (ssize_t) roi->height; y++)
2499       {
2500         q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
2501         if (q == (Quantum *) NULL)
2502           break;
2503         for (x=0; x < (ssize_t) roi->width; x++)
2504         {
2505           SetPixelRed(image,ClampToQuantum(QuantumRange*(*p)),q);
2506           p++;
2507           SetPixelGreen(image,ClampToQuantum(QuantumRange*(*p)),q);
2508           p++;
2509           SetPixelBlue(image,ClampToQuantum(QuantumRange*(*p)),q);
2510           p++;
2511           q+=GetPixelChannels(image);
2512         }
2513         if (SyncAuthenticPixels(image,exception) == MagickFalse)
2514           break;
2515       }
2516       return;
2517     }
2518    length=strlen(map);
2519   for (y=0; y < (ssize_t) roi->height; y++)
2520   {
2521     q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
2522     if (q == (Quantum *) NULL)
2523       break;
2524     for (x=0; x < (ssize_t) roi->width; x++)
2525     {
2526       register ssize_t
2527         i;
2528
2529       for (i=0; i < (ssize_t) length; i++)
2530       {
2531         switch (quantum_map[i])
2532         {
2533           case RedQuantum:
2534           case CyanQuantum:
2535           {
2536             SetPixelRed(image,ClampToQuantum(QuantumRange*(*p)),q);
2537             break;
2538           }
2539           case GreenQuantum:
2540           case MagentaQuantum:
2541           {
2542             SetPixelGreen(image,ClampToQuantum(QuantumRange*(*p)),q);
2543             break;
2544           }
2545           case BlueQuantum:
2546           case YellowQuantum:
2547           {
2548             SetPixelBlue(image,ClampToQuantum(QuantumRange*(*p)),q);
2549             break;
2550           }
2551           case AlphaQuantum:
2552           {
2553             SetPixelAlpha(image,ClampToQuantum(QuantumRange*(*p)),q);
2554             break;
2555           }
2556           case OpacityQuantum:
2557           {
2558             SetPixelAlpha(image,ClampToQuantum(QuantumRange*(*p)),q);
2559             break;
2560           }
2561           case BlackQuantum:
2562           {
2563             SetPixelBlack(image,ClampToQuantum(QuantumRange*(*p)),q);
2564             break;
2565           }
2566           case IndexQuantum:
2567           {
2568             SetPixelGray(image,ClampToQuantum(QuantumRange*(*p)),q);
2569             break;
2570           }
2571           default:
2572             break;
2573         }
2574         p++;
2575       }
2576       q+=GetPixelChannels(image);
2577     }
2578     if (SyncAuthenticPixels(image,exception) == MagickFalse)
2579       break;
2580   }
2581 }
2582
2583 static void ImportFloatPixel(Image *image,const RectangleInfo *roi,
2584   const char *restrict map,const QuantumType *quantum_map,const void *pixels,
2585   ExceptionInfo *exception)
2586 {
2587   register const float
2588     *restrict p;
2589
2590   register Quantum
2591     *restrict q;
2592
2593   register ssize_t
2594     x;
2595
2596   size_t
2597     length;
2598
2599   ssize_t
2600     y;
2601
2602   p=(const float *) pixels;
2603   if (LocaleCompare(map,"BGR") == 0)
2604     {
2605       for (y=0; y < (ssize_t) roi->height; y++)
2606       {
2607         q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
2608         if (q == (Quantum *) NULL)
2609           break;
2610         for (x=0; x < (ssize_t) roi->width; x++)
2611         {
2612           SetPixelBlue(image,ClampToQuantum(QuantumRange*(*p)),q);
2613           p++;
2614           SetPixelGreen(image,ClampToQuantum(QuantumRange*(*p)),q);
2615           p++;
2616           SetPixelRed(image,ClampToQuantum(QuantumRange*(*p)),q);
2617           p++;
2618           q+=GetPixelChannels(image);
2619         }
2620         if (SyncAuthenticPixels(image,exception) == MagickFalse)
2621           break;
2622       }
2623       return;
2624     }
2625   if (LocaleCompare(map,"BGRA") == 0)
2626     {
2627       for (y=0; y < (ssize_t) roi->height; y++)
2628       {
2629         q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
2630         if (q == (Quantum *) NULL)
2631           break;
2632         for (x=0; x < (ssize_t) roi->width; x++)
2633         {
2634           SetPixelBlue(image,ClampToQuantum(QuantumRange*(*p)),q);
2635           p++;
2636           SetPixelGreen(image,ClampToQuantum(QuantumRange*(*p)),q);
2637           p++;
2638           SetPixelRed(image,ClampToQuantum(QuantumRange*(*p)),q);
2639           p++;
2640           SetPixelAlpha(image,ClampToQuantum(QuantumRange*(*p)),q);
2641           p++;
2642           q+=GetPixelChannels(image);
2643         }
2644         if (SyncAuthenticPixels(image,exception) == MagickFalse)
2645           break;
2646       }
2647       return;
2648     }
2649   if (LocaleCompare(map,"BGRP") == 0)
2650     {
2651       for (y=0; y < (ssize_t) roi->height; y++)
2652       {
2653         q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
2654         if (q == (Quantum *) NULL)
2655           break;
2656         for (x=0; x < (ssize_t) roi->width; x++)
2657         {
2658           SetPixelBlue(image,ClampToQuantum(QuantumRange*(*p)),q);
2659           p++;
2660           SetPixelGreen(image,ClampToQuantum(QuantumRange*(*p)),q);
2661           p++;
2662           SetPixelRed(image,ClampToQuantum(QuantumRange*(*p)),q);
2663           p++;
2664           p++;
2665           q+=GetPixelChannels(image);
2666         }
2667         if (SyncAuthenticPixels(image,exception) == MagickFalse)
2668           break;
2669       }
2670       return;
2671     }
2672   if (LocaleCompare(map,"I") == 0)
2673     {
2674       for (y=0; y < (ssize_t) roi->height; y++)
2675       {
2676         q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
2677         if (q == (Quantum *) NULL)
2678           break;
2679         for (x=0; x < (ssize_t) roi->width; x++)
2680         {
2681           SetPixelGray(image,ClampToQuantum(QuantumRange*(*p)),q);
2682           p++;
2683           q+=GetPixelChannels(image);
2684         }
2685         if (SyncAuthenticPixels(image,exception) == MagickFalse)
2686           break;
2687       }
2688       return;
2689     }
2690   if (LocaleCompare(map,"RGB") == 0)
2691     {
2692       for (y=0; y < (ssize_t) roi->height; y++)
2693       {
2694         q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
2695         if (q == (Quantum *) NULL)
2696           break;
2697         for (x=0; x < (ssize_t) roi->width; x++)
2698         {
2699           SetPixelRed(image,ClampToQuantum(QuantumRange*(*p)),q);
2700           p++;
2701           SetPixelGreen(image,ClampToQuantum(QuantumRange*(*p)),q);
2702           p++;
2703           SetPixelBlue(image,ClampToQuantum(QuantumRange*(*p)),q);
2704           p++;
2705           q+=GetPixelChannels(image);
2706         }
2707         if (SyncAuthenticPixels(image,exception) == MagickFalse)
2708           break;
2709       }
2710       return;
2711     }
2712   if (LocaleCompare(map,"RGBA") == 0)
2713     {
2714       for (y=0; y < (ssize_t) roi->height; y++)
2715       {
2716         q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
2717         if (q == (Quantum *) NULL)
2718           break;
2719         for (x=0; x < (ssize_t) roi->width; x++)
2720         {
2721           SetPixelRed(image,ClampToQuantum(QuantumRange*(*p)),q);
2722           p++;
2723           SetPixelGreen(image,ClampToQuantum(QuantumRange*(*p)),q);
2724           p++;
2725           SetPixelBlue(image,ClampToQuantum(QuantumRange*(*p)),q);
2726           p++;
2727           SetPixelAlpha(image,ClampToQuantum(QuantumRange*(*p)),q);
2728           p++;
2729           q+=GetPixelChannels(image);
2730         }
2731         if (SyncAuthenticPixels(image,exception) == MagickFalse)
2732           break;
2733       }
2734       return;
2735     }
2736   if (LocaleCompare(map,"RGBP") == 0)
2737     {
2738       for (y=0; y < (ssize_t) roi->height; y++)
2739       {
2740         q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
2741         if (q == (Quantum *) NULL)
2742           break;
2743         for (x=0; x < (ssize_t) roi->width; x++)
2744         {
2745           SetPixelRed(image,ClampToQuantum(QuantumRange*(*p)),q);
2746           p++;
2747           SetPixelGreen(image,ClampToQuantum(QuantumRange*(*p)),q);
2748           p++;
2749           SetPixelBlue(image,ClampToQuantum(QuantumRange*(*p)),q);
2750           p++;
2751           q+=GetPixelChannels(image);
2752         }
2753         if (SyncAuthenticPixels(image,exception) == MagickFalse)
2754           break;
2755       }
2756       return;
2757     }
2758   length=strlen(map);
2759   for (y=0; y < (ssize_t) roi->height; y++)
2760   {
2761     q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
2762     if (q == (Quantum *) NULL)
2763       break;
2764     for (x=0; x < (ssize_t) roi->width; x++)
2765     {
2766       register ssize_t
2767         i;
2768
2769       for (i=0; i < (ssize_t) length; i++)
2770       {
2771         switch (quantum_map[i])
2772         {
2773           case RedQuantum:
2774           case CyanQuantum:
2775           {
2776             SetPixelRed(image,ClampToQuantum(QuantumRange*(*p)),q);
2777             break;
2778           }
2779           case GreenQuantum:
2780           case MagentaQuantum:
2781           {
2782             SetPixelGreen(image,ClampToQuantum(QuantumRange*(*p)),q);
2783             break;
2784           }
2785           case BlueQuantum:
2786           case YellowQuantum:
2787           {
2788             SetPixelBlue(image,ClampToQuantum(QuantumRange*(*p)),q);
2789             break;
2790           }
2791           case AlphaQuantum:
2792           {
2793             SetPixelAlpha(image,ClampToQuantum(QuantumRange*(*p)),q);
2794             break;
2795           }
2796           case OpacityQuantum:
2797           {
2798             SetPixelAlpha(image,ClampToQuantum(QuantumRange*(*p)),q);
2799             break;
2800           }
2801           case BlackQuantum:
2802           {
2803             SetPixelBlack(image,ClampToQuantum(QuantumRange*(*p)),q);
2804             break;
2805           }
2806           case IndexQuantum:
2807           {
2808             SetPixelGray(image,ClampToQuantum(QuantumRange*(*p)),q);
2809             break;
2810           }
2811           default:
2812             break;
2813         }
2814         p++;
2815       }
2816       q+=GetPixelChannels(image);
2817     }
2818     if (SyncAuthenticPixels(image,exception) == MagickFalse)
2819       break;
2820   }
2821 }
2822
2823 static void ImportLongPixel(Image *image,const RectangleInfo *roi,
2824   const char *restrict map,const QuantumType *quantum_map,const void *pixels,
2825   ExceptionInfo *exception)
2826 {
2827   register const unsigned int
2828     *restrict p;
2829
2830   register Quantum
2831     *restrict q;
2832
2833   register ssize_t
2834     x;
2835
2836   size_t
2837     length;
2838
2839   ssize_t
2840     y;
2841
2842   p=(const unsigned int *) pixels;
2843   if (LocaleCompare(map,"BGR") == 0)
2844     {
2845       for (y=0; y < (ssize_t) roi->height; y++)
2846       {
2847         q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
2848         if (q == (Quantum *) NULL)
2849           break;
2850         for (x=0; x < (ssize_t) roi->width; x++)
2851         {
2852           SetPixelBlue(image,ScaleLongToQuantum(*p++),q);
2853           SetPixelGreen(image,ScaleLongToQuantum(*p++),q);
2854           SetPixelRed(image,ScaleLongToQuantum(*p++),q);
2855           q+=GetPixelChannels(image);
2856         }
2857         if (SyncAuthenticPixels(image,exception) == MagickFalse)
2858           break;
2859       }
2860       return;
2861     }
2862   if (LocaleCompare(map,"BGRA") == 0)
2863     {
2864       for (y=0; y < (ssize_t) roi->height; y++)
2865       {
2866         q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
2867         if (q == (Quantum *) NULL)
2868           break;
2869         for (x=0; x < (ssize_t) roi->width; x++)
2870         {
2871           SetPixelBlue(image,ScaleLongToQuantum(*p++),q);
2872           SetPixelGreen(image,ScaleLongToQuantum(*p++),q);
2873           SetPixelRed(image,ScaleLongToQuantum(*p++),q);
2874           SetPixelAlpha(image,ScaleLongToQuantum(*p++),q);
2875           q+=GetPixelChannels(image);
2876         }
2877         if (SyncAuthenticPixels(image,exception) == MagickFalse)
2878           break;
2879       }
2880       return;
2881     }
2882   if (LocaleCompare(map,"BGRP") == 0)
2883     {
2884       for (y=0; y < (ssize_t) roi->height; y++)
2885       {
2886         q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
2887         if (q == (Quantum *) NULL)
2888           break;
2889         for (x=0; x < (ssize_t) roi->width; x++)
2890         {
2891           SetPixelBlue(image,ScaleLongToQuantum(*p++),q);
2892           SetPixelGreen(image,ScaleLongToQuantum(*p++),q);
2893           SetPixelRed(image,ScaleLongToQuantum(*p++),q);
2894           p++;
2895           q+=GetPixelChannels(image);
2896         }
2897         if (SyncAuthenticPixels(image,exception) == MagickFalse)
2898           break;
2899       }
2900       return;
2901     }
2902   if (LocaleCompare(map,"I") == 0)
2903     {
2904       for (y=0; y < (ssize_t) roi->height; y++)
2905       {
2906         q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
2907         if (q == (Quantum *) NULL)
2908           break;
2909         for (x=0; x < (ssize_t) roi->width; x++)
2910         {
2911           SetPixelGray(image,ScaleLongToQuantum(*p++),q);
2912           q+=GetPixelChannels(image);
2913         }
2914         if (SyncAuthenticPixels(image,exception) == MagickFalse)
2915           break;
2916       }
2917       return;
2918     }
2919   if (LocaleCompare(map,"RGB") == 0)
2920     {
2921       for (y=0; y < (ssize_t) roi->height; y++)
2922       {
2923         q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
2924         if (q == (Quantum *) NULL)
2925           break;
2926         for (x=0; x < (ssize_t) roi->width; x++)
2927         {
2928           SetPixelRed(image,ScaleLongToQuantum(*p++),q);
2929           SetPixelGreen(image,ScaleLongToQuantum(*p++),q);
2930           SetPixelBlue(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,"RGBA") == 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           SetPixelRed(image,ScaleLongToQuantum(*p++),q);
2948           SetPixelGreen(image,ScaleLongToQuantum(*p++),q);
2949           SetPixelBlue(image,ScaleLongToQuantum(*p++),q);
2950           SetPixelAlpha(image,ScaleLongToQuantum(*p++),q);
2951           q+=GetPixelChannels(image);
2952         }
2953         if (SyncAuthenticPixels(image,exception) == MagickFalse)
2954           break;
2955       }
2956       return;
2957     }
2958   if (LocaleCompare(map,"RGBP") == 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           SetPixelRed(image,ScaleLongToQuantum(*p++),q);
2968           SetPixelGreen(image,ScaleLongToQuantum(*p++),q);
2969           SetPixelBlue(image,ScaleLongToQuantum(*p++),q);
2970           p++;
2971           q+=GetPixelChannels(image);
2972         }
2973         if (SyncAuthenticPixels(image,exception) == MagickFalse)
2974           break;
2975       }
2976       return;
2977     }
2978   length=strlen(map);
2979   for (y=0; y < (ssize_t) roi->height; y++)
2980   {
2981     q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
2982     if (q == (Quantum *) NULL)
2983       break;
2984     for (x=0; x < (ssize_t) roi->width; x++)
2985     {
2986       register ssize_t
2987         i;
2988
2989       for (i=0; i < (ssize_t) length; i++)
2990       {
2991         switch (quantum_map[i])
2992         {
2993           case RedQuantum:
2994           case CyanQuantum:
2995           {
2996             SetPixelRed(image,ScaleLongToQuantum(*p),q);
2997             break;
2998           }
2999           case GreenQuantum:
3000           case MagentaQuantum:
3001           {
3002             SetPixelGreen(image,ScaleLongToQuantum(*p),q);
3003             break;
3004           }
3005           case BlueQuantum:
3006           case YellowQuantum:
3007           {
3008             SetPixelBlue(image,ScaleLongToQuantum(*p),q);
3009             break;
3010           }
3011           case AlphaQuantum:
3012           {
3013             SetPixelAlpha(image,ScaleLongToQuantum(*p),q);
3014             break;
3015           }
3016           case OpacityQuantum:
3017           {
3018             SetPixelAlpha(image,ScaleLongToQuantum(*p),q);
3019             break;
3020           }
3021           case BlackQuantum:
3022           {
3023             SetPixelBlack(image,ScaleLongToQuantum(*p),q);
3024             break;
3025           }
3026           case IndexQuantum:
3027           {
3028             SetPixelGray(image,ScaleLongToQuantum(*p),q);
3029             break;
3030           }
3031           default:
3032             break;
3033         }
3034         p++;
3035       }
3036       q+=GetPixelChannels(image);
3037     }
3038     if (SyncAuthenticPixels(image,exception) == MagickFalse)
3039       break;
3040   }
3041 }
3042
3043 static void ImportLongLongPixel(Image *image,const RectangleInfo *roi,
3044   const char *restrict map,const QuantumType *quantum_map,const void *pixels,
3045   ExceptionInfo *exception)
3046 {
3047   register const MagickSizeType
3048     *restrict p;
3049
3050   register Quantum
3051     *restrict q;
3052
3053   register ssize_t
3054     x;
3055
3056   size_t
3057     length;
3058
3059   ssize_t
3060     y;
3061
3062   p=(const MagickSizeType *) pixels;
3063   if (LocaleCompare(map,"BGR") == 0)
3064     {
3065       for (y=0; y < (ssize_t) roi->height; y++)
3066       {
3067         q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
3068         if (q == (Quantum *) NULL)
3069           break;
3070         for (x=0; x < (ssize_t) roi->width; x++)
3071         {
3072           SetPixelBlue(image,ScaleLongLongToQuantum(*p++),q);
3073           SetPixelGreen(image,ScaleLongLongToQuantum(*p++),q);
3074           SetPixelRed(image,ScaleLongLongToQuantum(*p++),q);
3075           q+=GetPixelChannels(image);
3076         }
3077         if (SyncAuthenticPixels(image,exception) == MagickFalse)
3078           break;
3079       }
3080       return;
3081     }
3082   if (LocaleCompare(map,"BGRA") == 0)
3083     {
3084       for (y=0; y < (ssize_t) roi->height; y++)
3085       {
3086         q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
3087         if (q == (Quantum *) NULL)
3088           break;
3089         for (x=0; x < (ssize_t) roi->width; x++)
3090         {
3091           SetPixelBlue(image,ScaleLongLongToQuantum(*p++),q);
3092           SetPixelGreen(image,ScaleLongLongToQuantum(*p++),q);
3093           SetPixelRed(image,ScaleLongLongToQuantum(*p++),q);
3094           SetPixelAlpha(image,ScaleLongLongToQuantum(*p++),q);
3095           q+=GetPixelChannels(image);
3096         }
3097         if (SyncAuthenticPixels(image,exception) == MagickFalse)
3098           break;
3099       }
3100       return;
3101     }
3102   if (LocaleCompare(map,"BGRP") == 0)
3103     {
3104       for (y=0; y < (ssize_t) roi->height; y++)
3105       {
3106         q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
3107         if (q == (Quantum *) NULL)
3108           break;
3109         for (x=0; x < (ssize_t) roi->width; x++)
3110         {
3111           SetPixelBlue(image,ScaleLongLongToQuantum(*p++),q);
3112           SetPixelGreen(image,ScaleLongLongToQuantum(*p++),q);
3113           SetPixelRed(image,ScaleLongLongToQuantum(*p++),q);
3114           p++;
3115           q+=GetPixelChannels(image);
3116         }
3117         if (SyncAuthenticPixels(image,exception) == MagickFalse)
3118           break;
3119       }
3120       return;
3121     }
3122   if (LocaleCompare(map,"I") == 0)
3123     {
3124       for (y=0; y < (ssize_t) roi->height; y++)
3125       {
3126         q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
3127         if (q == (Quantum *) NULL)
3128           break;
3129         for (x=0; x < (ssize_t) roi->width; x++)
3130         {
3131           SetPixelGray(image,ScaleLongLongToQuantum(*p++),q);
3132           q+=GetPixelChannels(image);
3133         }
3134         if (SyncAuthenticPixels(image,exception) == MagickFalse)
3135           break;
3136       }
3137       return;
3138     }
3139   if (LocaleCompare(map,"RGB") == 0)
3140     {
3141       for (y=0; y < (ssize_t) roi->height; y++)
3142       {
3143         q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
3144         if (q == (Quantum *) NULL)
3145           break;
3146         for (x=0; x < (ssize_t) roi->width; x++)
3147         {
3148           SetPixelRed(image,ScaleLongLongToQuantum(*p++),q);
3149           SetPixelGreen(image,ScaleLongLongToQuantum(*p++),q);
3150           SetPixelBlue(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,"RGBA") == 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           SetPixelRed(image,ScaleLongLongToQuantum(*p++),q);
3168           SetPixelGreen(image,ScaleLongLongToQuantum(*p++),q);
3169           SetPixelBlue(image,ScaleLongLongToQuantum(*p++),q);
3170           SetPixelAlpha(image,ScaleLongLongToQuantum(*p++),q);
3171           q+=GetPixelChannels(image);
3172         }
3173         if (SyncAuthenticPixels(image,exception) == MagickFalse)
3174           break;
3175       }
3176       return;
3177     }
3178   if (LocaleCompare(map,"RGBP") == 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           SetPixelRed(image,ScaleLongLongToQuantum(*p++),q);
3188           SetPixelGreen(image,ScaleLongLongToQuantum(*p++),q);
3189           SetPixelBlue(image,ScaleLongLongToQuantum(*p++),q);
3190           p++;
3191           q+=GetPixelChannels(image);
3192         }
3193         if (SyncAuthenticPixels(image,exception) == MagickFalse)
3194           break;
3195       }
3196       return;
3197     }
3198   length=strlen(map);
3199   for (y=0; y < (ssize_t) roi->height; y++)
3200   {
3201     q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
3202     if (q == (Quantum *) NULL)
3203       break;
3204     for (x=0; x < (ssize_t) roi->width; x++)
3205     {
3206       register ssize_t
3207         i;
3208
3209       for (i=0; i < (ssize_t) length; i++)
3210       {
3211         switch (quantum_map[i])
3212         {
3213           case RedQuantum:
3214           case CyanQuantum:
3215           {
3216             SetPixelRed(image,ScaleLongLongToQuantum(*p),q);
3217             break;
3218           }
3219           case GreenQuantum:
3220           case MagentaQuantum:
3221           {
3222             SetPixelGreen(image,ScaleLongLongToQuantum(*p),q);
3223             break;
3224           }
3225           case BlueQuantum:
3226           case YellowQuantum:
3227           {
3228             SetPixelBlue(image,ScaleLongLongToQuantum(*p),q);
3229             break;
3230           }
3231           case AlphaQuantum:
3232           {
3233             SetPixelAlpha(image,ScaleLongLongToQuantum(*p),q);
3234             break;
3235           }
3236           case OpacityQuantum:
3237           {
3238             SetPixelAlpha(image,ScaleLongLongToQuantum(*p),q);
3239             break;
3240           }
3241           case BlackQuantum:
3242           {
3243             SetPixelBlack(image,ScaleLongLongToQuantum(*p),q);
3244             break;
3245           }
3246           case IndexQuantum:
3247           {
3248             SetPixelGray(image,ScaleLongLongToQuantum(*p),q);
3249             break;
3250           }
3251           default:
3252             break;
3253         }
3254         p++;
3255       }
3256       q+=GetPixelChannels(image);
3257     }
3258     if (SyncAuthenticPixels(image,exception) == MagickFalse)
3259       break;
3260   }
3261 }
3262
3263 static void ImportQuantumPixel(Image *image,const RectangleInfo *roi,
3264   const char *restrict map,const QuantumType *quantum_map,const void *pixels,
3265   ExceptionInfo *exception)
3266 {
3267   register const Quantum
3268     *restrict p;
3269
3270   register Quantum
3271     *restrict q;
3272
3273   register ssize_t
3274     x;
3275
3276   size_t
3277     length;
3278
3279   ssize_t
3280     y;
3281
3282   p=(const Quantum *) pixels;
3283   if (LocaleCompare(map,"BGR") == 0)
3284     {
3285       for (y=0; y < (ssize_t) roi->height; y++)
3286       {
3287         q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
3288         if (q == (Quantum *) NULL)
3289           break;
3290         for (x=0; x < (ssize_t) roi->width; x++)
3291         {
3292           SetPixelBlue(image,*p++,q);
3293           SetPixelGreen(image,*p++,q);
3294           SetPixelRed(image,*p++,q);
3295           q+=GetPixelChannels(image);
3296         }
3297         if (SyncAuthenticPixels(image,exception) == MagickFalse)
3298           break;
3299       }
3300       return;
3301     }
3302   if (LocaleCompare(map,"BGRA") == 0)
3303     {
3304       for (y=0; y < (ssize_t) roi->height; y++)
3305       {
3306         q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
3307         if (q == (Quantum *) NULL)
3308           break;
3309         for (x=0; x < (ssize_t) roi->width; x++)
3310         {
3311           SetPixelBlue(image,*p++,q);
3312           SetPixelGreen(image,*p++,q);
3313           SetPixelRed(image,*p++,q);
3314           SetPixelAlpha(image,*p++,q);
3315           q+=GetPixelChannels(image);
3316         }
3317         if (SyncAuthenticPixels(image,exception) == MagickFalse)
3318           break;
3319       }
3320       return;
3321     }
3322   if (LocaleCompare(map,"BGRP") == 0)
3323     {
3324       for (y=0; y < (ssize_t) roi->height; y++)
3325       {
3326         q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
3327         if (q == (Quantum *) NULL)
3328           break;
3329         for (x=0; x < (ssize_t) roi->width; x++)
3330         {
3331           SetPixelBlue(image,*p++,q);
3332           SetPixelGreen(image,*p++,q);
3333           SetPixelRed(image,*p++,q);
3334           p++;
3335           q+=GetPixelChannels(image);
3336         }
3337         if (SyncAuthenticPixels(image,exception) == MagickFalse)
3338           break;
3339       }
3340       return;
3341     }
3342   if (LocaleCompare(map,"I") == 0)
3343     {
3344       for (y=0; y < (ssize_t) roi->height; y++)
3345       {
3346         q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
3347         if (q == (Quantum *) NULL)
3348           break;
3349         for (x=0; x < (ssize_t) roi->width; x++)
3350         {
3351           SetPixelGray(image,*p++,q);
3352           q+=GetPixelChannels(image);
3353         }
3354         if (SyncAuthenticPixels(image,exception) == MagickFalse)
3355           break;
3356       }
3357       return;
3358     }
3359   if (LocaleCompare(map,"RGB") == 0)
3360     {
3361       for (y=0; y < (ssize_t) roi->height; y++)
3362       {
3363         q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
3364         if (q == (Quantum *) NULL)
3365           break;
3366         for (x=0; x < (ssize_t) roi->width; x++)
3367         {
3368           SetPixelRed(image,*p++,q);
3369           SetPixelGreen(image,*p++,q);
3370           SetPixelBlue(image,*p++,q);
3371           q+=GetPixelChannels(image);
3372         }
3373         if (SyncAuthenticPixels(image,exception) == MagickFalse)
3374           break;
3375       }
3376       return;
3377     }
3378   if (LocaleCompare(map,"RGBA") == 0)
3379     {
3380       for (y=0; y < (ssize_t) roi->height; y++)
3381       {
3382         q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
3383         if (q == (Quantum *) NULL)
3384           break;
3385         for (x=0; x < (ssize_t) roi->width; x++)
3386         {
3387           SetPixelRed(image,*p++,q);
3388           SetPixelGreen(image,*p++,q);
3389           SetPixelBlue(image,*p++,q);
3390           SetPixelAlpha(image,*p++,q);
3391           q+=GetPixelChannels(image);
3392         }
3393         if (SyncAuthenticPixels(image,exception) == MagickFalse)
3394           break;
3395       }
3396       return;
3397     }
3398   if (LocaleCompare(map,"RGBP") == 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           SetPixelRed(image,*p++,q);
3408           SetPixelGreen(image,*p++,q);
3409           SetPixelBlue(image,*p++,q);
3410           p++;
3411           q+=GetPixelChannels(image);
3412         }
3413         if (SyncAuthenticPixels(image,exception) == MagickFalse)
3414           break;
3415       }
3416       return;
3417     }
3418   length=strlen(map);
3419   for (y=0; y < (ssize_t) roi->height; y++)
3420   {
3421     q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
3422     if (q == (Quantum *) NULL)
3423       break;
3424     for (x=0; x < (ssize_t) roi->width; x++)
3425     {
3426       register ssize_t
3427         i;
3428
3429       for (i=0; i < (ssize_t) length; i++)
3430       {
3431         switch (quantum_map[i])
3432         {
3433           case RedQuantum:
3434           case CyanQuantum:
3435           {
3436             SetPixelRed(image,*p,q);
3437             break;
3438           }
3439           case GreenQuantum:
3440           case MagentaQuantum:
3441           {
3442             SetPixelGreen(image,*p,q);
3443             break;
3444           }
3445           case BlueQuantum:
3446           case YellowQuantum:
3447           {
3448             SetPixelBlue(image,*p,q);
3449             break;
3450           }
3451           case AlphaQuantum:
3452           {
3453             SetPixelAlpha(image,*p,q);
3454             break;
3455           }
3456           case OpacityQuantum:
3457           {
3458             SetPixelAlpha(image,*p,q);
3459             break;
3460           }
3461           case BlackQuantum:
3462           {
3463             SetPixelBlack(image,*p,q);
3464             break;
3465           }
3466           case IndexQuantum:
3467           {
3468             SetPixelGray(image,*p,q);
3469             break;
3470           }
3471           default:
3472             break;
3473         }
3474         p++;
3475       }
3476       q+=GetPixelChannels(image);
3477     }
3478     if (SyncAuthenticPixels(image,exception) == MagickFalse)
3479       break;
3480   }
3481 }
3482
3483 static void ImportShortPixel(Image *image,const RectangleInfo *roi,
3484   const char *restrict map,const QuantumType *quantum_map,const void *pixels,
3485   ExceptionInfo *exception)
3486 {
3487   register const unsigned short
3488     *restrict p;
3489
3490   register Quantum
3491     *restrict q;
3492
3493   register ssize_t
3494     x;
3495
3496   size_t
3497     length;
3498
3499   ssize_t
3500     y;
3501
3502   p=(const unsigned short *) pixels;
3503   if (LocaleCompare(map,"BGR") == 0)
3504     {
3505       for (y=0; y < (ssize_t) roi->height; y++)
3506       {
3507         q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
3508         if (q == (Quantum *) NULL)
3509           break;
3510         for (x=0; x < (ssize_t) roi->width; x++)
3511         {
3512           SetPixelBlue(image,ScaleShortToQuantum(*p++),q);
3513           SetPixelGreen(image,ScaleShortToQuantum(*p++),q);
3514           SetPixelRed(image,ScaleShortToQuantum(*p++),q);
3515           q+=GetPixelChannels(image);
3516         }
3517         if (SyncAuthenticPixels(image,exception) == MagickFalse)
3518           break;
3519       }
3520       return;
3521     }
3522   if (LocaleCompare(map,"BGRA") == 0)
3523     {
3524       for (y=0; y < (ssize_t) roi->height; y++)
3525       {
3526         q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
3527         if (q == (Quantum *) NULL)
3528           break;
3529         for (x=0; x < (ssize_t) roi->width; x++)
3530         {
3531           SetPixelBlue(image,ScaleShortToQuantum(*p++),q);
3532           SetPixelGreen(image,ScaleShortToQuantum(*p++),q);
3533           SetPixelRed(image,ScaleShortToQuantum(*p++),q);
3534           SetPixelAlpha(image,ScaleShortToQuantum(*p++),q);
3535           q+=GetPixelChannels(image);
3536         }
3537         if (SyncAuthenticPixels(image,exception) == MagickFalse)
3538           break;
3539       }
3540       return;
3541     }
3542   if (LocaleCompare(map,"BGRP") == 0)
3543     {
3544       for (y=0; y < (ssize_t) roi->height; y++)
3545       {
3546         q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
3547         if (q == (Quantum *) NULL)
3548           break;
3549         for (x=0; x < (ssize_t) roi->width; x++)
3550         {
3551           SetPixelBlue(image,ScaleShortToQuantum(*p++),q);
3552           SetPixelGreen(image,ScaleShortToQuantum(*p++),q);
3553           SetPixelRed(image,ScaleShortToQuantum(*p++),q);
3554           p++;
3555           q+=GetPixelChannels(image);
3556         }
3557         if (SyncAuthenticPixels(image,exception) == MagickFalse)
3558           break;
3559       }
3560       return;
3561     }
3562   if (LocaleCompare(map,"I") == 0)
3563     {
3564       for (y=0; y < (ssize_t) roi->height; y++)
3565       {
3566         q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
3567         if (q == (Quantum *) NULL)
3568           break;
3569         for (x=0; x < (ssize_t) roi->width; x++)
3570         {
3571           SetPixelGray(image,ScaleShortToQuantum(*p++),q);
3572           q+=GetPixelChannels(image);
3573         }
3574         if (SyncAuthenticPixels(image,exception) == MagickFalse)
3575           break;
3576       }
3577       return;
3578     }
3579   if (LocaleCompare(map,"RGB") == 0)
3580     {
3581       for (y=0; y < (ssize_t) roi->height; y++)
3582       {
3583         q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
3584         if (q == (Quantum *) NULL)
3585           break;
3586         for (x=0; x < (ssize_t) roi->width; x++)
3587         {
3588           SetPixelRed(image,ScaleShortToQuantum(*p++),q);
3589           SetPixelGreen(image,ScaleShortToQuantum(*p++),q);
3590           SetPixelBlue(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,"RGBA") == 0)
3599     {
3600       for (y=0; y < (ssize_t) roi->height; y++)
3601       {
3602         q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
3603         if (q == (Quantum *) NULL)
3604           break;
3605         for (x=0; x < (ssize_t) roi->width; x++)
3606         {
3607           SetPixelRed(image,ScaleShortToQuantum(*p++),q);
3608           SetPixelGreen(image,ScaleShortToQuantum(*p++),q);
3609           SetPixelBlue(image,ScaleShortToQuantum(*p++),q);
3610           SetPixelAlpha(image,ScaleShortToQuantum(*p++),q);
3611           q+=GetPixelChannels(image);
3612         }
3613         if (SyncAuthenticPixels(image,exception) == MagickFalse)
3614           break;
3615       }
3616       return;
3617     }
3618   if (LocaleCompare(map,"RGBP") == 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           SetPixelRed(image,ScaleShortToQuantum(*p++),q);
3628           SetPixelGreen(image,ScaleShortToQuantum(*p++),q);
3629           SetPixelBlue(image,ScaleShortToQuantum(*p++),q);
3630           p++;
3631           q+=GetPixelChannels(image);
3632         }
3633         if (SyncAuthenticPixels(image,exception) == MagickFalse)
3634           break;
3635       }
3636       return;
3637     }
3638   length=strlen(map);
3639   for (y=0; y < (ssize_t) roi->height; y++)
3640   {
3641     q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
3642     if (q == (Quantum *) NULL)
3643       break;
3644     for (x=0; x < (ssize_t) roi->width; x++)
3645     {
3646       register ssize_t
3647         i;
3648
3649       for (i=0; i < (ssize_t) length; i++)
3650       {
3651         switch (quantum_map[i])
3652         {
3653           case RedQuantum:
3654           case CyanQuantum:
3655           {
3656             SetPixelRed(image,ScaleShortToQuantum(*p),q);
3657             break;
3658           }
3659           case GreenQuantum:
3660           case MagentaQuantum:
3661           {
3662             SetPixelGreen(image,ScaleShortToQuantum(*p),q);
3663             break;
3664           }
3665           case BlueQuantum:
3666           case YellowQuantum:
3667           {
3668             SetPixelBlue(image,ScaleShortToQuantum(*p),q);
3669             break;
3670           }
3671           case AlphaQuantum:
3672           {
3673             SetPixelAlpha(image,ScaleShortToQuantum(*p),q);
3674             break;
3675           }
3676           case OpacityQuantum:
3677           {
3678             SetPixelAlpha(image,ScaleShortToQuantum(*p),q);
3679             break;
3680           }
3681           case BlackQuantum:
3682           {
3683             SetPixelBlack(image,ScaleShortToQuantum(*p),q);
3684             break;
3685           }
3686           case IndexQuantum:
3687           {
3688             SetPixelGray(image,ScaleShortToQuantum(*p),q);
3689             break;
3690           }
3691           default:
3692             break;
3693         }
3694         p++;
3695       }
3696       q+=GetPixelChannels(image);
3697     }
3698     if (SyncAuthenticPixels(image,exception) == MagickFalse)
3699       break;
3700   }
3701 }
3702
3703 MagickExport MagickBooleanType ImportImagePixels(Image *image,const ssize_t x,
3704   const ssize_t y,const size_t width,const size_t height,const char *map,
3705   const StorageType type,const void *pixels,ExceptionInfo *exception)
3706 {
3707   QuantumType
3708     *quantum_map;
3709
3710   RectangleInfo
3711     roi;
3712
3713   register ssize_t
3714     i;
3715
3716   size_t
3717     length;
3718
3719   /*
3720     Allocate image structure.
3721   */
3722   assert(image != (Image *) NULL);
3723   assert(image->signature == MagickSignature);
3724   if (image->debug != MagickFalse)
3725     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3726   length=strlen(map);
3727   quantum_map=(QuantumType *) AcquireQuantumMemory(length,sizeof(*quantum_map));
3728   if (quantum_map == (QuantumType *) NULL)
3729     ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
3730       image->filename);
3731   for (i=0; i < (ssize_t) length; i++)
3732   {
3733     switch (map[i])
3734     {
3735       case 'a':
3736       case 'A':
3737       {
3738         quantum_map[i]=AlphaQuantum;
3739         image->alpha_trait=BlendPixelTrait;
3740         break;
3741       }
3742       case 'B':
3743       case 'b':
3744       {
3745         quantum_map[i]=BlueQuantum;
3746         break;
3747       }
3748       case 'C':
3749       case 'c':
3750       {
3751         quantum_map[i]=CyanQuantum;
3752         (void) SetImageColorspace(image,CMYKColorspace,exception);
3753         break;
3754       }
3755       case 'g':
3756       case 'G':
3757       {
3758         quantum_map[i]=GreenQuantum;
3759         break;
3760       }
3761       case 'K':
3762       case 'k':
3763       {
3764         quantum_map[i]=BlackQuantum;
3765         (void) SetImageColorspace(image,CMYKColorspace,exception);
3766         break;
3767       }
3768       case 'I':
3769       case 'i':
3770       {
3771         quantum_map[i]=IndexQuantum;
3772         (void) SetImageColorspace(image,GRAYColorspace,exception);
3773         break;
3774       }
3775       case 'm':
3776       case 'M':
3777       {
3778         quantum_map[i]=MagentaQuantum;
3779         (void) SetImageColorspace(image,CMYKColorspace,exception);
3780         break;
3781       }
3782       case 'O':
3783       case 'o':
3784       {
3785         quantum_map[i]=OpacityQuantum;
3786         image->alpha_trait=BlendPixelTrait;
3787         break;
3788       }
3789       case 'P':
3790       case 'p':
3791       {
3792         quantum_map[i]=UndefinedQuantum;
3793         break;
3794       }
3795       case 'R':
3796       case 'r':
3797       {
3798         quantum_map[i]=RedQuantum;
3799         break;
3800       }
3801       case 'Y':
3802       case 'y':
3803       {
3804         quantum_map[i]=YellowQuantum;
3805         (void) SetImageColorspace(image,CMYKColorspace,exception);
3806         break;
3807       }
3808       default:
3809       {
3810         quantum_map=(QuantumType *) RelinquishMagickMemory(quantum_map);
3811         (void) ThrowMagickException(exception,GetMagickModule(),OptionError,
3812           "UnrecognizedPixelMap","'%s'",map);
3813         return(MagickFalse);
3814       }
3815     }
3816   }
3817   if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
3818     return(MagickFalse);
3819   /*
3820     Transfer the pixels from the pixel data to the image.
3821   */
3822   roi.width=width;
3823   roi.height=height;
3824   roi.x=x;
3825   roi.y=y;
3826   switch (type)
3827   {
3828     case CharPixel:
3829     {
3830       ImportCharPixel(image,&roi,map,quantum_map,pixels,exception);
3831       break;
3832     }
3833     case DoublePixel:
3834     {
3835       ImportDoublePixel(image,&roi,map,quantum_map,pixels,exception);
3836       break;
3837     }
3838     case FloatPixel:
3839     {
3840       ImportFloatPixel(image,&roi,map,quantum_map,pixels,exception);
3841       break;
3842     }
3843     case LongPixel:
3844     {
3845       ImportLongPixel(image,&roi,map,quantum_map,pixels,exception);
3846       break;
3847     }
3848     case LongLongPixel:
3849     {
3850       ImportLongLongPixel(image,&roi,map,quantum_map,pixels,exception);
3851       break;
3852     }
3853     case QuantumPixel:
3854     {
3855       ImportQuantumPixel(image,&roi,map,quantum_map,pixels,exception);
3856       break;
3857     }
3858     case ShortPixel:
3859     {
3860       ImportShortPixel(image,&roi,map,quantum_map,pixels,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       break;
3869     }
3870   }
3871   quantum_map=(QuantumType *) RelinquishMagickMemory(quantum_map);
3872   return(MagickTrue);
3873 }
3874 \f
3875 /*
3876 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3877 %                                                                             %
3878 %                                                                             %
3879 %                                                                             %
3880 +   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                         %
3881 %                                                                             %
3882 %                                                                             %
3883 %                                                                             %
3884 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3885 %
3886 %  InitializePixelChannelMap() defines the standard pixel component map.
3887 %
3888 %  The format of the InitializePixelChannelMap() method is:
3889 %
3890 %      void InitializePixelChannelMap(Image *image)
3891 %
3892 %  A description of each parameter follows:
3893 %
3894 %    o image: the image.
3895 %
3896 */
3897 MagickExport void InitializePixelChannelMap(Image *image)
3898 {
3899   PixelTrait
3900     trait;
3901
3902   register ssize_t
3903     i;
3904
3905   ssize_t
3906     n;
3907
3908   assert(image != (Image *) NULL);
3909   assert(image->signature == MagickSignature);
3910   (void) ResetMagickMemory(image->channel_map,0,MaxPixelChannels*
3911     sizeof(*image->channel_map));
3912   trait=UpdatePixelTrait;
3913   if (image->alpha_trait == BlendPixelTrait)
3914     trait=(PixelTrait) (trait | BlendPixelTrait);
3915   n=0;
3916   if (image->colorspace == GRAYColorspace)
3917     {
3918       SetPixelChannelAttributes(image,BluePixelChannel,trait,n);
3919       SetPixelChannelAttributes(image,GreenPixelChannel,trait,n);
3920       SetPixelChannelAttributes(image,RedPixelChannel,trait,n++);
3921     }
3922   else
3923     {
3924       SetPixelChannelAttributes(image,RedPixelChannel,trait,n++);
3925       SetPixelChannelAttributes(image,GreenPixelChannel,trait,n++);
3926       SetPixelChannelAttributes(image,BluePixelChannel,trait,n++);
3927     }
3928   if (image->colorspace == CMYKColorspace)
3929     SetPixelChannelAttributes(image,BlackPixelChannel,trait,n++);
3930   if (image->alpha_trait != UndefinedPixelTrait)
3931     SetPixelChannelAttributes(image,AlphaPixelChannel,CopyPixelTrait,n++);
3932   if (image->storage_class == PseudoClass)
3933     SetPixelChannelAttributes(image,IndexPixelChannel,CopyPixelTrait,n++);
3934   if (image->mask != MagickFalse)
3935     SetPixelChannelAttributes(image,MaskPixelChannel,CopyPixelTrait,n++);
3936   assert((n+image->number_meta_channels) < MaxPixelChannels);
3937   for (i=0; i < (ssize_t) image->number_meta_channels; i++)
3938     SetPixelChannelAttributes(image,(PixelChannel) (MetaPixelChannel+i),
3939       CopyPixelTrait,n++);
3940   image->number_channels=(size_t) n;
3941   if (image->debug != MagickFalse)
3942     LogPixelChannels(image);
3943   (void) SetImageChannelMask(image,image->channel_mask);
3944 }
3945 \f
3946 /*
3947 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3948 %                                                                             %
3949 %                                                                             %
3950 %                                                                             %
3951 %   I n t e r p o l a t e P i x e l C h a n n e l                             %
3952 %                                                                             %
3953 %                                                                             %
3954 %                                                                             %
3955 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3956 %
3957 %  InterpolatePixelChannel() applies a pixel interpolation method between a
3958 %  floating point coordinate and the pixels surrounding that coordinate.  No
3959 %  pixel area resampling, or scaling of the result is performed.
3960 %
3961 %  Interpolation is restricted to just the specified channel.
3962 %
3963 %  The format of the InterpolatePixelChannel method is:
3964 %
3965 %      MagickBooleanType InterpolatePixelChannel(const Image *image,
3966 %        const CacheView *image_view,const PixelChannel channel,
3967 %        const PixelInterpolateMethod method,const double x,const double y,
3968 %        double *pixel,ExceptionInfo *exception)
3969 %
3970 %  A description of each parameter follows:
3971 %
3972 %    o image: the image.
3973 %
3974 %    o image_view: the image view.
3975 %
3976 %    o channel: the pixel channel to interpolate.
3977 %
3978 %    o method: the pixel color interpolation method.
3979 %
3980 %    o x,y: A double representing the current (x,y) position of the pixel.
3981 %
3982 %    o pixel: return the interpolated pixel here.
3983 %
3984 %    o exception: return any errors or warnings in this structure.
3985 %
3986 */
3987
3988 static inline double MagickMax(const double x,const double y)
3989 {
3990   if (x > y)
3991     return(x);
3992   return(y);
3993 }
3994
3995 static inline void CatromWeights(const double x,double (*weights)[4])
3996 {
3997   double
3998     alpha,
3999     beta,
4000     gamma;
4001
4002   /*
4003     Nicolas Robidoux' 10 flops (4* + 5- + 1+) refactoring of the computation
4004     of the standard four 1D Catmull-Rom weights. The sampling location is
4005     assumed between the second and third input pixel locations, and x is the
4006     position relative to the second input pixel location. Formulas originally
4007     derived for the VIPS (Virtual Image Processing System) library.
4008   */
4009   alpha=(double) 1.0-x;
4010   beta=(double) (-0.5)*x*alpha;
4011   (*weights)[0]=alpha*beta;
4012   (*weights)[3]=x*beta;
4013   /*
4014     The following computation of the inner weights from the outer ones work
4015     for all Keys cubics.
4016   */
4017   gamma=(*weights)[3]-(*weights)[0];
4018   (*weights)[1]=alpha-(*weights)[0]+gamma;
4019   (*weights)[2]=x-(*weights)[3]-gamma;
4020 }
4021
4022 static inline void SplineWeights(const double x,double (*weights)[4])
4023 {
4024   double
4025     alpha,
4026     beta;
4027
4028   /*
4029     Nicolas Robidoux' 12 flops (6* + 5- + 1+) refactoring of the
4030     computation of the standard four 1D cubic B-spline smoothing
4031     weights. The sampling location is assumed between the second and
4032     third input pixel locations, and x is the position relative to the
4033     second input pixel location.
4034   */
4035   alpha=(double) 1.0-x;
4036   (*weights)[3]=(double) (1.0/6.0)*x*x*x;
4037   (*weights)[0]=(double) (1.0/6.0)*alpha*alpha*alpha;
4038   beta=(*weights)[3]-(*weights)[0];
4039   (*weights)[1]=alpha-(*weights)[0]+beta;
4040   (*weights)[2]=x-(*weights)[3]-beta;
4041 }
4042
4043 static inline double MeshInterpolate(const PointInfo *delta,const double p,
4044   const double x,const double y)
4045 {
4046   return(delta->x*x+delta->y*y+(1.0-delta->x-delta->y)*p);
4047 }
4048
4049 /*
4050 static inline ssize_t NearestNeighbor(const double x)
4051 {
4052   if (x >= 0.0)
4053     return((ssize_t) (x+0.5));
4054   return((ssize_t) (x-0.5));
4055 }
4056 */
4057
4058 MagickExport MagickBooleanType InterpolatePixelChannel(const Image *image,
4059   const CacheView *image_view,const PixelChannel channel,
4060   const PixelInterpolateMethod method,const double x,const double y,
4061   double *pixel,ExceptionInfo *exception)
4062 {
4063   MagickBooleanType
4064     status;
4065
4066   double
4067     alpha[16],
4068     gamma,
4069     pixels[16];
4070
4071   PixelTrait
4072     traits;
4073
4074   register const Quantum
4075     *p;
4076
4077   register ssize_t
4078     i;
4079
4080   ssize_t
4081     x_offset,
4082     y_offset;
4083
4084   PixelInterpolateMethod
4085     interpolate;
4086
4087   assert(image != (Image *) NULL);
4088   assert(image != (Image *) NULL);
4089   assert(image->signature == MagickSignature);
4090   assert(image_view != (CacheView *) NULL);
4091   status=MagickTrue;
4092   *pixel=0.0;
4093   traits=GetPixelChannelTraits(image,channel);
4094   x_offset=(ssize_t) floor(x);
4095   y_offset=(ssize_t) floor(y);
4096   interpolate = method;
4097   if ( interpolate == UndefinedInterpolatePixel )
4098     interpolate = image->interpolate;
4099   switch (interpolate)
4100   {
4101     case AverageInterpolatePixel:        /* nearest 4 neighbours */
4102     case Average9InterpolatePixel:       /* nearest 9 neighbours */
4103     case Average16InterpolatePixel:      /* nearest 16 neighbours */
4104     {
4105       size_t
4106         count=2; /* size of the area to average - default nearest 4 */
4107
4108       if (interpolate == Average9InterpolatePixel)
4109         {
4110           count=3;
4111           x_offset=(ssize_t) (floor(x+0.5)-1);
4112           y_offset=(ssize_t) (floor(y+0.5)-1);
4113         }
4114       else if (interpolate == Average16InterpolatePixel)
4115         {
4116           count=4;
4117           x_offset--;
4118           y_offset--;
4119         }
4120       p=GetCacheViewVirtualPixels(image_view,x_offset,y_offset,count,count,
4121         exception);
4122       if (p == (const Quantum *) NULL)
4123         {
4124           status=MagickFalse;
4125           break;
4126         }
4127
4128       count*=count;   /* Number of pixels to Average */
4129       if ((traits & BlendPixelTrait) == 0)
4130         for (i=0; i < (ssize_t) count; i++)
4131         {
4132           alpha[i]=1.0;
4133           pixels[i]=(double) p[i*GetPixelChannels(image)+channel];
4134         }
4135       else
4136         for (i=0; i < (ssize_t) count; i++)
4137         {
4138           alpha[i]=QuantumScale*GetPixelAlpha(image,p+i*
4139             GetPixelChannels(image));
4140           pixels[i]=alpha[i]*p[i*GetPixelChannels(image)+channel];
4141         }
4142       for (i=0; i < (ssize_t) count; i++)
4143       {
4144         gamma=MagickEpsilonReciprocal(alpha[i])/count;
4145         *pixel+=gamma*pixels[i];
4146       }
4147       break;
4148     }
4149     case BilinearInterpolatePixel:
4150     default:
4151     {
4152       PointInfo
4153         delta,
4154         epsilon;
4155
4156       p=GetCacheViewVirtualPixels(image_view,x_offset,y_offset,2,2,exception);
4157       if (p == (const Quantum *) NULL)
4158         {
4159           status=MagickFalse;
4160           break;
4161         }
4162       if ((traits & BlendPixelTrait) == 0)
4163         for (i=0; i < 4; i++)
4164         {
4165           alpha[i]=1.0;
4166           pixels[i]=(double) p[i*GetPixelChannels(image)+channel];
4167         }
4168       else
4169         for (i=0; i < 4; i++)
4170         {
4171           alpha[i]=QuantumScale*GetPixelAlpha(image,p+i*
4172             GetPixelChannels(image));
4173           pixels[i]=alpha[i]*p[i*GetPixelChannels(image)+channel];
4174         }
4175       delta.x=x-x_offset;
4176       delta.y=y-y_offset;
4177       epsilon.x=1.0-delta.x;
4178       epsilon.y=1.0-delta.y;
4179       gamma=((epsilon.y*(epsilon.x*alpha[0]+delta.x*alpha[1])+delta.y*
4180         (epsilon.x*alpha[2]+delta.x*alpha[3])));
4181       gamma=MagickEpsilonReciprocal(gamma);
4182       *pixel=gamma*(epsilon.y*(epsilon.x*pixels[0]+delta.x*pixels[1])+delta.y*
4183         (epsilon.x*pixels[2]+delta.x*pixels[3]));
4184       break;
4185     }
4186     case CatromInterpolatePixel:
4187     {
4188       double
4189         cx[4],
4190         cy[4];
4191
4192       p=GetCacheViewVirtualPixels(image_view,x_offset-1,y_offset-1,4,4,
4193         exception);
4194       if (p == (const Quantum *) NULL)
4195         {
4196           status=MagickFalse;
4197           break;
4198         }
4199       if ((traits & BlendPixelTrait) == 0)
4200         for (i=0; i < 16; i++)
4201         {
4202           alpha[i]=1.0;
4203           pixels[i]=(double) p[i*GetPixelChannels(image)+channel];
4204         }
4205       else
4206         for (i=0; i < 16; i++)
4207         {
4208           alpha[i]=QuantumScale*GetPixelAlpha(image,p+i*
4209             GetPixelChannels(image));
4210           pixels[i]=alpha[i]*p[i*GetPixelChannels(image)+channel];
4211         }
4212       CatromWeights((double) (x-x_offset),&cx);
4213       CatromWeights((double) (y-y_offset),&cy);
4214       gamma=(channel == AlphaPixelChannel ? (double) 1.0 :
4215         MagickEpsilonReciprocal(cy[0]*(cx[0]*alpha[0]+cx[1]*alpha[1]+cx[2]*
4216         alpha[2]+cx[3]*alpha[3])+cy[1]*(cx[0]*alpha[4]+cx[1]*alpha[5]+cx[2]*
4217         alpha[6]+cx[3]*alpha[7])+cy[2]*(cx[0]*alpha[8]+cx[1]*alpha[9]+cx[2]*
4218         alpha[10]+cx[3]*alpha[11])+cy[3]*(cx[0]*alpha[12]+cx[1]*alpha[13]+
4219         cx[2]*alpha[14]+cx[3]*alpha[15])));
4220       *pixel=gamma*(cy[0]*(cx[0]*pixels[0]+cx[1]*pixels[1]+cx[2]*pixels[2]+
4221         cx[3]*pixels[3])+cy[1]*(cx[0]*pixels[4]+cx[1]*pixels[5]+cx[2]*
4222         pixels[6]+cx[3]*pixels[7])+cy[2]*(cx[0]*pixels[8]+cx[1]*pixels[9]+
4223         cx[2]*pixels[10]+cx[3]*pixels[11])+cy[3]*(cx[0]*pixels[12]+cx[1]*
4224         pixels[13]+cx[2]*pixels[14]+cx[3]*pixels[15]));
4225       break;
4226     }
4227 #if 0
4228     /* deprecated useless and very slow interpolator */
4229     case FilterInterpolatePixel:
4230     {
4231       CacheView
4232         *filter_view;
4233
4234       Image
4235         *excerpt_image,
4236         *filter_image;
4237
4238       RectangleInfo
4239         geometry;
4240
4241       geometry.width=4L;
4242       geometry.height=4L;
4243       geometry.x=x_offset-1;
4244       geometry.y=y_offset-1;
4245       excerpt_image=ExcerptImage(image,&geometry,exception);
4246       if (excerpt_image == (Image *) NULL)
4247         {
4248           status=MagickFalse;
4249           break;
4250         }
4251       filter_image=ResizeImage(excerpt_image,1,1,image->filter,exception);
4252       excerpt_image=DestroyImage(excerpt_image);
4253       if (filter_image == (Image *) NULL)
4254         break;
4255       filter_view=AcquireVirtualCacheView(filter_image,exception);
4256       p=GetCacheViewVirtualPixels(filter_view,0,0,1,1,exception);
4257       if (p == (const Quantum *) NULL)
4258         status=MagickFalse;
4259       else
4260         *pixel=(double) GetPixelChannel(image,channel,p);
4261       filter_view=DestroyCacheView(filter_view);
4262       filter_image=DestroyImage(filter_image);
4263       break;
4264     }
4265 #endif
4266     case IntegerInterpolatePixel:
4267     {
4268       p=GetCacheViewVirtualPixels(image_view,x_offset,y_offset,1,1,exception);
4269       if (p == (const Quantum *) NULL)
4270         {
4271           status=MagickFalse;
4272           break;
4273         }
4274       *pixel=(double) GetPixelChannel(image,channel,p);
4275       break;
4276     }
4277     case NearestInterpolatePixel:
4278     {
4279       x_offset=(ssize_t) floor(x+0.5);
4280       y_offset=(ssize_t) floor(y+0.5);
4281       p=GetCacheViewVirtualPixels(image_view,x_offset,y_offset,1,1,exception);
4282       if (p == (const Quantum *) NULL)
4283         {
4284           status=MagickFalse;
4285           break;
4286         }
4287       *pixel=(double) GetPixelChannel(image,channel,p);
4288       break;
4289     }
4290     case MeshInterpolatePixel:
4291     {
4292       PointInfo
4293         delta,
4294         luminance;
4295
4296       p=GetCacheViewVirtualPixels(image_view,x_offset,y_offset,2,2,exception);
4297       if (p == (const Quantum *) NULL)
4298         {
4299           status=MagickFalse;
4300           break;
4301         }
4302       if ((traits & BlendPixelTrait) == 0)
4303         for (i=0; i < 4; i++)
4304         {
4305           alpha[i]=1.0;
4306           pixels[i]=(double) p[i*GetPixelChannels(image)+channel];
4307         }
4308       else
4309         for (i=0; i < 4; i++)
4310         {
4311           alpha[i]=QuantumScale*GetPixelAlpha(image,p+i*
4312             GetPixelChannels(image));
4313           pixels[i]=alpha[i]*p[i*GetPixelChannels(image)+channel];
4314         }
4315       delta.x=x-x_offset;
4316       delta.y=y-y_offset;
4317       luminance.x=GetPixelLuminance(image,p)-(double)
4318         GetPixelLuminance(image,p+3*GetPixelChannels(image));
4319       luminance.y=GetPixelLuminance(image,p+GetPixelChannels(image))-(double)
4320         GetPixelLuminance(image,p+2*GetPixelChannels(image));
4321       if (fabs(luminance.x) < fabs(luminance.y))
4322         {
4323           /*
4324             Diagonal 0-3 NW-SE.
4325           */
4326           if (delta.x <= delta.y)
4327             {
4328               /*
4329                 Bottom-left triangle (pixel: 2, diagonal: 0-3).
4330               */
4331               delta.y=1.0-delta.y;
4332               gamma=MeshInterpolate(&delta,alpha[2],alpha[3],alpha[0]);
4333               gamma=MagickEpsilonReciprocal(gamma);
4334               *pixel=gamma*MeshInterpolate(&delta,pixels[2],pixels[3],
4335                 pixels[0]);
4336             }
4337           else
4338             {
4339               /*
4340                 Top-right triangle (pixel: 1, diagonal: 0-3).
4341               */
4342               delta.x=1.0-delta.x;
4343               gamma=MeshInterpolate(&delta,alpha[1],alpha[0],alpha[3]);
4344               gamma=MagickEpsilonReciprocal(gamma);
4345               *pixel=gamma*MeshInterpolate(&delta,pixels[1],pixels[0],
4346                 pixels[3]);
4347             }
4348         }
4349       else
4350         {
4351           /*
4352             Diagonal 1-2 NE-SW.
4353           */
4354           if (delta.x <= (1.0-delta.y))
4355             {
4356               /*
4357                 Top-left triangle (pixel: 0, diagonal: 1-2).
4358               */
4359               gamma=MeshInterpolate(&delta,alpha[0],alpha[1],alpha[2]);
4360               gamma=MagickEpsilonReciprocal(gamma);
4361               *pixel=gamma*MeshInterpolate(&delta,pixels[0],pixels[1],
4362                 pixels[2]);
4363             }
4364           else
4365             {
4366               /*
4367                 Bottom-right triangle (pixel: 3, diagonal: 1-2).
4368               */
4369               delta.x=1.0-delta.x;
4370               delta.y=1.0-delta.y;
4371               gamma=MeshInterpolate(&delta,alpha[3],alpha[2],alpha[1]);
4372               gamma=MagickEpsilonReciprocal(gamma);
4373               *pixel=gamma*MeshInterpolate(&delta,pixels[3],pixels[2],
4374                 pixels[1]);
4375             }
4376         }
4377       break;
4378     }
4379     case SplineInterpolatePixel:
4380     {
4381       double
4382         cx[4],
4383         cy[4];
4384
4385       p=GetCacheViewVirtualPixels(image_view,x_offset-1,y_offset-1,4,4,
4386         exception);
4387       if (p == (const Quantum *) NULL)
4388         {
4389           status=MagickFalse;
4390           break;
4391         }
4392       if ((traits & BlendPixelTrait) == 0)
4393         for (i=0; i < 16; i++)
4394         {
4395           alpha[i]=1.0;
4396           pixels[i]=(double) p[i*GetPixelChannels(image)+channel];
4397         }
4398       else
4399         for (i=0; i < 16; i++)
4400         {
4401           alpha[i]=QuantumScale*GetPixelAlpha(image,p+i*
4402             GetPixelChannels(image));
4403           pixels[i]=alpha[i]*p[i*GetPixelChannels(image)+channel];
4404         }
4405       SplineWeights((double) (x-x_offset),&cx);
4406       SplineWeights((double) (y-y_offset),&cy);
4407       gamma=(channel == AlphaPixelChannel ? (double) 1.0 :
4408         MagickEpsilonReciprocal(cy[0]*(cx[0]*alpha[0]+cx[1]*alpha[1]+cx[2]*
4409         alpha[2]+cx[3]*alpha[3])+cy[1]*(cx[0]*alpha[4]+cx[1]*alpha[5]+cx[2]*
4410         alpha[6]+cx[3]*alpha[7])+cy[2]*(cx[0]*alpha[8]+cx[1]*alpha[9]+cx[2]*
4411         alpha[10]+cx[3]*alpha[11])+cy[3]*(cx[0]*alpha[12]+cx[1]*alpha[13]+
4412         cx[2]*alpha[14]+cx[3]*alpha[15])));
4413       *pixel=gamma*(cy[0]*(cx[0]*pixels[0]+cx[1]*pixels[1]+cx[2]*pixels[2]+
4414         cx[3]*pixels[3])+cy[1]*(cx[0]*pixels[4]+cx[1]*pixels[5]+cx[2]*
4415         pixels[6]+cx[3]*pixels[7])+cy[2]*(cx[0]*pixels[8]+cx[1]*pixels[9]+
4416         cx[2]*pixels[10]+cx[3]*pixels[11])+cy[3]*(cx[0]*pixels[12]+cx[1]*
4417         pixels[13]+cx[2]*pixels[14]+cx[3]*pixels[15]));
4418       break;
4419     }
4420   }
4421   return(status);
4422 }
4423 \f
4424 /*
4425 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4426 %                                                                             %
4427 %                                                                             %
4428 %                                                                             %
4429 %   I n t e r p o l a t e P i x e l C h a n n e l s                           %
4430 %                                                                             %
4431 %                                                                             %
4432 %                                                                             %
4433 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4434 %
4435 %  InterpolatePixelChannels() applies a pixel interpolation method between a
4436 %  floating point coordinate and the pixels surrounding that coordinate.  No
4437 %  pixel area resampling, or scaling of the result is performed.
4438 %
4439 %  Interpolation is restricted to just the current channel setting of the
4440 %  destination image into which the color is to be stored
4441 %
4442 %  The format of the InterpolatePixelChannels method is:
4443 %
4444 %      MagickBooleanType InterpolatePixelChannels(const Image *source,
4445 %        const CacheView *source_view,const Image *destination,
4446 %        const PixelInterpolateMethod method,const double x,const double y,
4447 %        Quantum *pixel,ExceptionInfo *exception)
4448 %
4449 %  A description of each parameter follows:
4450 %
4451 %    o source: the source.
4452 %
4453 %    o source_view: the source view.
4454 %
4455 %    o destination: the destination image, for the interpolated color
4456 %
4457 %    o method: the pixel color interpolation method.
4458 %
4459 %    o x,y: A double representing the current (x,y) position of the pixel.
4460 %
4461 %    o pixel: return the interpolated pixel here.
4462 %
4463 %    o exception: return any errors or warnings in this structure.
4464 %
4465 */
4466 MagickExport MagickBooleanType InterpolatePixelChannels(const Image *source,
4467   const CacheView *source_view,const Image *destination,
4468   const PixelInterpolateMethod method,const double x,const double y,
4469   Quantum *pixel,ExceptionInfo *exception)
4470 {
4471   MagickBooleanType
4472     status;
4473
4474   double
4475     alpha[16],
4476     gamma,
4477     pixels[16];
4478
4479   PixelChannel
4480     channel;
4481
4482   PixelTrait
4483     destination_traits,
4484     traits;
4485
4486   register const Quantum
4487     *p;
4488
4489   register ssize_t
4490     i;
4491
4492   ssize_t
4493     x_offset,
4494     y_offset;
4495
4496   PixelInterpolateMethod
4497     interpolate;
4498
4499   assert(source != (Image *) NULL);
4500   assert(source != (Image *) NULL);
4501   assert(source->signature == MagickSignature);
4502   assert(source_view != (CacheView *) NULL);
4503   status=MagickTrue;
4504   x_offset=(ssize_t) floor(x);
4505   y_offset=(ssize_t) floor(y);
4506   interpolate = method;
4507   if ( interpolate == UndefinedInterpolatePixel )
4508     interpolate = source->interpolate;
4509   switch (interpolate)
4510   {
4511     case AverageInterpolatePixel:        /* nearest 4 neighbours */
4512     case Average9InterpolatePixel:       /* nearest 9 neighbours */
4513     case Average16InterpolatePixel:      /* nearest 16 neighbours */
4514     {
4515       size_t
4516         count=2; /* size of the area to average - default nearest 4 */
4517
4518       if (interpolate == Average9InterpolatePixel)
4519         {
4520           count=3;
4521           x_offset=(ssize_t) (floor(x+0.5)-1);
4522           y_offset=(ssize_t) (floor(y+0.5)-1);
4523         }
4524       else if (interpolate == Average16InterpolatePixel)
4525         {
4526           count=4;
4527           x_offset--;
4528           y_offset--;
4529         }
4530       p=GetCacheViewVirtualPixels(source_view,x_offset,y_offset,count,count,
4531         exception);
4532       if (p == (const Quantum *) NULL)
4533         {
4534           status=MagickFalse;
4535           break;
4536         }
4537       count*=count;   /* Number of pixels to Average */
4538       for (i=0; i < (ssize_t) GetPixelChannels(source); i++)
4539       {
4540         double
4541           sum;
4542
4543         register ssize_t
4544           j;
4545
4546         channel=GetPixelChannelChannel(source,i);
4547         traits=GetPixelChannelTraits(source,channel);
4548         destination_traits=GetPixelChannelTraits(destination,channel);
4549         if ((traits == UndefinedPixelTrait) ||
4550             (destination_traits == UndefinedPixelTrait))
4551           continue;
4552         for (j=0; j < (ssize_t) count; j++)
4553           pixels[j]=(double) p[j*GetPixelChannels(source)+i];
4554         sum=0.0;
4555         if ((traits & BlendPixelTrait) == 0)
4556           {
4557             for (j=0; j < (ssize_t) count; j++)
4558               sum+=pixels[j];
4559             sum/=count;
4560             SetPixelChannel(destination,channel,ClampToQuantum(sum),pixel);
4561             continue;
4562           }
4563         for (j=0; j < (ssize_t) count; j++)
4564         {
4565           alpha[j]=QuantumScale*GetPixelAlpha(source,p+j*
4566             GetPixelChannels(source));
4567           pixels[j]*=alpha[j];
4568           gamma=MagickEpsilonReciprocal(alpha[j]);
4569           sum+=gamma*pixels[j];
4570         }
4571         sum/=count;
4572         SetPixelChannel(destination,channel,ClampToQuantum(sum),pixel);
4573       }
4574       break;
4575     }
4576     case BilinearInterpolatePixel:
4577     default:
4578     {
4579       p=GetCacheViewVirtualPixels(source_view,x_offset,y_offset,2,2,exception);
4580       if (p == (const Quantum *) NULL)
4581         {
4582           status=MagickFalse;
4583           break;
4584         }
4585       for (i=0; i < (ssize_t) GetPixelChannels(source); i++)
4586       {
4587         PointInfo
4588           delta,
4589           epsilon;
4590
4591         channel=GetPixelChannelChannel(source,i);
4592         traits=GetPixelChannelTraits(source,channel);
4593         destination_traits=GetPixelChannelTraits(destination,channel);
4594         if ((traits == UndefinedPixelTrait) ||
4595             (destination_traits == UndefinedPixelTrait))
4596           continue;
4597         delta.x=x-x_offset;
4598         delta.y=y-y_offset;
4599         epsilon.x=1.0-delta.x;
4600         epsilon.y=1.0-delta.y;
4601         pixels[0]=(double) p[i];
4602         pixels[1]=(double) p[GetPixelChannels(source)+i];
4603         pixels[2]=(double) p[2*GetPixelChannels(source)+i];
4604         pixels[3]=(double) p[3*GetPixelChannels(source)+i];
4605         if ((traits & BlendPixelTrait) == 0)
4606           {
4607             gamma=((epsilon.y*(epsilon.x+delta.x)+delta.y*(epsilon.x+delta.x)));
4608             gamma=MagickEpsilonReciprocal(gamma);
4609             SetPixelChannel(destination,channel,ClampToQuantum(gamma*(epsilon.y*
4610               (epsilon.x*pixels[0]+delta.x*pixels[1])+delta.y*(epsilon.x*
4611               pixels[2]+delta.x*pixels[3]))),pixel);
4612             continue;
4613           }
4614         alpha[0]=QuantumScale*GetPixelAlpha(source,p);
4615         alpha[1]=QuantumScale*GetPixelAlpha(source,p+GetPixelChannels(source));
4616         alpha[2]=QuantumScale*GetPixelAlpha(source,p+2*
4617           GetPixelChannels(source));
4618         alpha[3]=QuantumScale*GetPixelAlpha(source,p+3*
4619           GetPixelChannels(source));
4620         pixels[0]*=alpha[0];
4621         pixels[1]*=alpha[1];
4622         pixels[2]*=alpha[2];
4623         pixels[3]*=alpha[3];
4624         gamma=((epsilon.y*(epsilon.x*alpha[0]+delta.x*alpha[1])+delta.y*
4625           (epsilon.x*alpha[2]+delta.x*alpha[3])));
4626         gamma=MagickEpsilonReciprocal(gamma);
4627         SetPixelChannel(destination,channel,ClampToQuantum(gamma*(epsilon.y*
4628           (epsilon.x*pixels[0]+delta.x*pixels[1])+delta.y*(epsilon.x*pixels[2]+
4629           delta.x*pixels[3]))),pixel);
4630       }
4631       break;
4632     }
4633     case CatromInterpolatePixel:
4634     {
4635       double
4636         cx[4],
4637         cy[4];
4638
4639       p=GetCacheViewVirtualPixels(source_view,x_offset-1,y_offset-1,4,4,
4640         exception);
4641       if (p == (const Quantum *) NULL)
4642         {
4643           status=MagickFalse;
4644           break;
4645         }
4646       for (i=0; i < (ssize_t) GetPixelChannels(source); i++)
4647       {
4648         register ssize_t
4649           j;
4650
4651         channel=GetPixelChannelChannel(source,i);
4652         traits=GetPixelChannelTraits(source,channel);
4653         destination_traits=GetPixelChannelTraits(destination,channel);
4654         if ((traits == UndefinedPixelTrait) ||
4655             (destination_traits == UndefinedPixelTrait))
4656           continue;
4657         if ((traits & BlendPixelTrait) == 0)
4658           for (j=0; j < 16; j++)
4659           {
4660             alpha[j]=1.0;
4661             pixels[j]=(double) p[j*GetPixelChannels(source)+i];
4662           }
4663         else
4664           for (j=0; j < 16; j++)
4665           {
4666             alpha[j]=QuantumScale*GetPixelAlpha(source,p+j*
4667               GetPixelChannels(source));
4668             pixels[j]=alpha[j]*p[j*GetPixelChannels(source)+i];
4669           }
4670         CatromWeights((double) (x-x_offset),&cx);
4671         CatromWeights((double) (y-y_offset),&cy);
4672         gamma=((traits & BlendPixelTrait) ? (double) (1.0) :
4673           MagickEpsilonReciprocal(cy[0]*(cx[0]*alpha[0]+cx[1]*alpha[1]+cx[2]*
4674           alpha[2]+cx[3]*alpha[3])+cy[1]*(cx[0]*alpha[4]+cx[1]*alpha[5]+cx[2]*
4675           alpha[6]+cx[3]*alpha[7])+cy[2]*(cx[0]*alpha[8]+cx[1]*alpha[9]+cx[2]*
4676           alpha[10]+cx[3]*alpha[11])+cy[3]*(cx[0]*alpha[12]+cx[1]*alpha[13]+
4677           cx[2]*alpha[14]+cx[3]*alpha[15])));
4678         SetPixelChannel(destination,channel,ClampToQuantum(gamma*(cy[0]*(cx[0]*
4679           pixels[0]+cx[1]*pixels[1]+cx[2]*pixels[2]+cx[3]*pixels[3])+cy[1]*
4680           (cx[0]*pixels[4]+cx[1]*pixels[5]+cx[2]*pixels[6]+cx[3]*pixels[7])+
4681           cy[2]*(cx[0]*pixels[8]+cx[1]*pixels[9]+cx[2]*pixels[10]+cx[3]*
4682           pixels[11])+cy[3]*(cx[0]*pixels[12]+cx[1]*pixels[13]+cx[2]*
4683           pixels[14]+cx[3]*pixels[15]))),pixel);
4684       }
4685       break;
4686     }
4687 #if 0
4688     /* deprecated useless and very slow interpolator */
4689     case FilterInterpolatePixel:
4690     {
4691       for (i=0; i < (ssize_t) GetPixelChannels(source); i++)
4692       {
4693         CacheView
4694           *filter_view;
4695
4696         Image
4697           *excerpt_source,
4698           *filter_source;
4699
4700         RectangleInfo
4701           geometry;
4702
4703         channel=GetPixelChannelChannel(source,i);
4704         traits=GetPixelChannelTraits(source,channel);
4705         destination_traits=GetPixelChannelTraits(destination,channel);
4706         if ((traits == UndefinedPixelTrait) ||
4707             (destination_traits == UndefinedPixelTrait))
4708           continue;
4709         geometry.width=4L;
4710         geometry.height=4L;
4711         geometry.x=x_offset-1;
4712         geometry.y=y_offset-1;
4713         excerpt_source=ExcerptImage(source,&geometry,exception);
4714         if (excerpt_source == (Image *) NULL)
4715           {
4716             status=MagickFalse;
4717             continue;
4718           }
4719         filter_source=ResizeImage(excerpt_source,1,1,source->filter,exception);
4720         excerpt_source=DestroyImage(excerpt_source);
4721         if (filter_source == (Image *) NULL)
4722           continue;
4723         filter_view=AcquireVirtualCacheView(filter_source,exception);
4724         p=GetCacheViewVirtualPixels(filter_view,0,0,1,1,exception);
4725         if (p == (const Quantum *) NULL)
4726           status=MagickFalse;
4727         else
4728           {
4729             SetPixelChannel(destination,channel,p[i],pixel);
4730           }
4731         filter_view=DestroyCacheView(filter_view);
4732         filter_source=DestroyImage(filter_source);
4733       }
4734       break;
4735     }
4736 #endif
4737     case IntegerInterpolatePixel:
4738     {
4739       p=GetCacheViewVirtualPixels(source_view,x_offset,y_offset,1,1,exception);
4740       if (p == (const Quantum *) NULL)
4741         {
4742           status=MagickFalse;
4743           break;
4744         }
4745       for (i=0; i < (ssize_t) GetPixelChannels(source); i++)
4746       {
4747         channel=GetPixelChannelChannel(source,i);
4748         traits=GetPixelChannelTraits(source,channel);
4749         destination_traits=GetPixelChannelTraits(destination,channel);
4750         if ((traits == UndefinedPixelTrait) ||
4751             (destination_traits == UndefinedPixelTrait))
4752           continue;
4753         SetPixelChannel(destination,channel,p[i],pixel);
4754       }
4755       break;
4756     }
4757     case NearestInterpolatePixel:
4758     {
4759       x_offset=(ssize_t) floor(x+0.5);
4760       y_offset=(ssize_t) floor(y+0.5);
4761       p=GetCacheViewVirtualPixels(source_view,x_offset,y_offset,1,1,exception);
4762       if (p == (const Quantum *) NULL)
4763         {
4764           status=MagickFalse;
4765           break;
4766         }
4767       for (i=0; i < (ssize_t) GetPixelChannels(source); i++)
4768       {
4769         channel=GetPixelChannelChannel(source,i);
4770         traits=GetPixelChannelTraits(source,channel);
4771         destination_traits=GetPixelChannelTraits(destination,channel);
4772         if ((traits == UndefinedPixelTrait) ||
4773             (destination_traits == UndefinedPixelTrait))
4774           continue;
4775         SetPixelChannel(destination,channel,p[i],pixel);
4776       }
4777       break;
4778     }
4779     case MeshInterpolatePixel:
4780     {
4781       p=GetCacheViewVirtualPixels(source_view,x_offset,y_offset,2,2,exception);
4782       if (p == (const Quantum *) NULL)
4783         {
4784           status=MagickFalse;
4785           break;
4786         }
4787       for (i=0; i < (ssize_t) GetPixelChannels(source); i++)
4788       {
4789         PointInfo
4790           delta,
4791           luminance;
4792
4793         channel=GetPixelChannelChannel(source,i);
4794         traits=GetPixelChannelTraits(source,channel);
4795         destination_traits=GetPixelChannelTraits(destination,channel);
4796         if ((traits == UndefinedPixelTrait) ||
4797             (destination_traits == UndefinedPixelTrait))
4798           continue;
4799         pixels[0]=(double) p[i];
4800         pixels[1]=(double) p[GetPixelChannels(source)+i];
4801         pixels[2]=(double) p[2*GetPixelChannels(source)+i];
4802         pixels[3]=(double) p[3*GetPixelChannels(source)+i];
4803         if ((traits & BlendPixelTrait) == 0)
4804           {
4805             alpha[0]=1.0;
4806             alpha[1]=1.0;
4807             alpha[2]=1.0;
4808             alpha[3]=1.0;
4809           }
4810         else
4811           {
4812             alpha[0]=QuantumScale*GetPixelAlpha(source,p);
4813             alpha[1]=QuantumScale*GetPixelAlpha(source,p+
4814               GetPixelChannels(source));
4815             alpha[2]=QuantumScale*GetPixelAlpha(source,p+2*
4816               GetPixelChannels(source));
4817             alpha[3]=QuantumScale*GetPixelAlpha(source,p+3*
4818               GetPixelChannels(source));
4819           }
4820         delta.x=x-x_offset;
4821         delta.y=y-y_offset;
4822         luminance.x=fabs((double)(
4823               GetPixelLuminance(source,p)
4824                -GetPixelLuminance(source,p+3*GetPixelChannels(source))));
4825         luminance.y=fabs((double)(
4826               GetPixelLuminance(source,p+GetPixelChannels(source))
4827                -GetPixelLuminance(source,p+2*GetPixelChannels(source))));
4828         if (luminance.x < luminance.y)
4829           {
4830             /*
4831               Diagonal 0-3 NW-SE.
4832             */
4833             if (delta.x <= delta.y)
4834               {
4835                 /*
4836                   Bottom-left triangle (pixel: 2, diagonal: 0-3).
4837                 */
4838                 delta.y=1.0-delta.y;
4839                 gamma=MeshInterpolate(&delta,alpha[2],alpha[3],alpha[0]);
4840                 gamma=MagickEpsilonReciprocal(gamma);
4841                 SetPixelChannel(destination,channel,ClampToQuantum(gamma*
4842                   MeshInterpolate(&delta,pixels[2],pixels[3],pixels[0])),pixel);
4843               }
4844             else
4845               {
4846                 /*
4847                   Top-right triangle (pixel: 1, diagonal: 0-3).
4848                 */
4849                 delta.x=1.0-delta.x;
4850                 gamma=MeshInterpolate(&delta,alpha[1],alpha[0],alpha[3]);
4851                 gamma=MagickEpsilonReciprocal(gamma);
4852                 SetPixelChannel(destination,channel,ClampToQuantum(gamma*
4853                   MeshInterpolate(&delta,pixels[1],pixels[0],pixels[3])),pixel);
4854               }
4855           }
4856         else
4857           {
4858             /*
4859               Diagonal 1-2 NE-SW.
4860             */
4861             if (delta.x <= (1.0-delta.y))
4862               {
4863                 /*
4864                   Top-left triangle (pixel: 0, diagonal: 1-2).
4865                 */
4866                 gamma=MeshInterpolate(&delta,alpha[0],alpha[1],alpha[2]);
4867                 gamma=MagickEpsilonReciprocal(gamma);
4868                 SetPixelChannel(destination,channel,ClampToQuantum(gamma*
4869                   MeshInterpolate(&delta,pixels[0],pixels[1],pixels[2])),pixel);
4870               }
4871             else
4872               {
4873                 /*
4874                   Bottom-right triangle (pixel: 3, diagonal: 1-2).
4875                 */
4876                 delta.x=1.0-delta.x;
4877                 delta.y=1.0-delta.y;
4878                 gamma=MeshInterpolate(&delta,alpha[3],alpha[2],alpha[1]);
4879                 gamma=MagickEpsilonReciprocal(gamma);
4880                 SetPixelChannel(destination,channel,ClampToQuantum(gamma*
4881                   MeshInterpolate(&delta,pixels[3],pixels[2],pixels[1])),pixel);
4882               }
4883           }
4884       }
4885       break;
4886     }
4887     case SplineInterpolatePixel:
4888     {
4889       double
4890         cx[4],
4891         cy[4];
4892
4893       p=GetCacheViewVirtualPixels(source_view,x_offset-1,y_offset-1,4,4,
4894         exception);
4895       if (p == (const Quantum *) NULL)
4896         {
4897           status=MagickFalse;
4898           break;
4899         }
4900       for (i=0; i < (ssize_t) GetPixelChannels(source); i++)
4901       {
4902         register ssize_t
4903           j;
4904
4905         channel=GetPixelChannelChannel(source,i);
4906         traits=GetPixelChannelTraits(source,channel);
4907         destination_traits=GetPixelChannelTraits(destination,channel);
4908         if ((traits == UndefinedPixelTrait) ||
4909             (destination_traits == UndefinedPixelTrait))
4910           continue;
4911         if ((traits & BlendPixelTrait) == 0)
4912           for (j=0; j < 16; j++)
4913           {
4914             alpha[j]=1.0;
4915             pixels[j]=(double) p[j*GetPixelChannels(source)+i];
4916           }
4917         else
4918           for (j=0; j < 16; j++)
4919           {
4920             alpha[j]=QuantumScale*GetPixelAlpha(source,p+j*
4921               GetPixelChannels(source));
4922             pixels[j]=alpha[j]*p[j*GetPixelChannels(source)+i];
4923           }
4924         SplineWeights((double) (x-x_offset),&cx);
4925         SplineWeights((double) (y-y_offset),&cy);
4926         gamma=((traits & BlendPixelTrait) ? (double) (1.0) :
4927           MagickEpsilonReciprocal(cy[0]*(cx[0]*alpha[0]+cx[1]*alpha[1]+cx[2]*
4928           alpha[2]+cx[3]*alpha[3])+cy[1]*(cx[0]*alpha[4]+cx[1]*alpha[5]+cx[2]*
4929           alpha[6]+cx[3]*alpha[7])+cy[2]*(cx[0]*alpha[8]+cx[1]*alpha[9]+cx[2]*
4930           alpha[10]+cx[3]*alpha[11])+cy[3]*(cx[0]*alpha[12]+cx[1]*alpha[13]+
4931           cx[2]*alpha[14]+cx[3]*alpha[15])));
4932         SetPixelChannel(destination,channel,ClampToQuantum(gamma*(cy[0]*(cx[0]*
4933           pixels[0]+cx[1]*pixels[1]+cx[2]*pixels[2]+cx[3]*pixels[3])+cy[1]*
4934           (cx[0]*pixels[4]+cx[1]*pixels[5]+cx[2]*pixels[6]+cx[3]*pixels[7])+
4935           cy[2]*(cx[0]*pixels[8]+cx[1]*pixels[9]+cx[2]*pixels[10]+cx[3]*
4936           pixels[11])+cy[3]*(cx[0]*pixels[12]+cx[1]*pixels[13]+cx[2]*
4937           pixels[14]+cx[3]*pixels[15]))),pixel);
4938       }
4939       break;
4940     }
4941   }
4942   return(status);
4943 }
4944 \f
4945 /*
4946 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4947 %                                                                             %
4948 %                                                                             %
4949 %                                                                             %
4950 %   I n t e r p o l a t e P i x e l I n f o                                   %
4951 %                                                                             %
4952 %                                                                             %
4953 %                                                                             %
4954 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4955 %
4956 %  InterpolatePixelInfo() applies a pixel interpolation method between a
4957 %  floating point coordinate and the pixels surrounding that coordinate.  No
4958 %  pixel area resampling, or scaling of the result is performed.
4959 %
4960 %  Interpolation is restricted to just RGBKA channels.
4961 %
4962 %  The format of the InterpolatePixelInfo method is:
4963 %
4964 %      MagickBooleanType InterpolatePixelInfo(const Image *image,
4965 %        const CacheView *image_view,const PixelInterpolateMethod method,
4966 %        const double x,const double y,PixelInfo *pixel,
4967 %        ExceptionInfo *exception)
4968 %
4969 %  A description of each parameter follows:
4970 %
4971 %    o image: the image.
4972 %
4973 %    o image_view: the image view.
4974 %
4975 %    o method: the pixel color interpolation method.
4976 %
4977 %    o x,y: A double representing the current (x,y) position of the pixel.
4978 %
4979 %    o pixel: return the interpolated pixel here.
4980 %
4981 %    o exception: return any errors or warnings in this structure.
4982 %
4983 */
4984
4985 static inline void AlphaBlendPixelInfo(const Image *image,
4986   const Quantum *pixel,PixelInfo *pixel_info,double *alpha)
4987 {
4988   if (image->alpha_trait != BlendPixelTrait)
4989     {
4990       *alpha=1.0;
4991       pixel_info->red=(double) GetPixelRed(image,pixel);
4992       pixel_info->green=(double) GetPixelGreen(image,pixel);
4993       pixel_info->blue=(double) GetPixelBlue(image,pixel);
4994       pixel_info->black=0.0;
4995       if (image->colorspace == CMYKColorspace)
4996         pixel_info->black=(double) GetPixelBlack(image,pixel);
4997       pixel_info->alpha=(double) GetPixelAlpha(image,pixel);
4998       return;
4999     }
5000   *alpha=QuantumScale*GetPixelAlpha(image,pixel);
5001   pixel_info->red=(*alpha*GetPixelRed(image,pixel));
5002   pixel_info->green=(*alpha*GetPixelGreen(image,pixel));
5003   pixel_info->blue=(*alpha*GetPixelBlue(image,pixel));
5004   pixel_info->black=0.0;
5005   if (image->colorspace == CMYKColorspace)
5006     pixel_info->black=(*alpha*GetPixelBlack(image,pixel));
5007   pixel_info->alpha=(double) GetPixelAlpha(image,pixel);
5008 }
5009
5010 MagickExport MagickBooleanType InterpolatePixelInfo(const Image *image,
5011   const CacheView *image_view,const PixelInterpolateMethod method,
5012   const double x,const double y,PixelInfo *pixel,ExceptionInfo *exception)
5013 {
5014   MagickBooleanType
5015     status;
5016
5017   double
5018     alpha[16],
5019     gamma;
5020
5021   PixelInfo
5022     pixels[16];
5023
5024   register const Quantum
5025     *p;
5026
5027   register ssize_t
5028     i;
5029
5030   ssize_t
5031     x_offset,
5032     y_offset;
5033
5034   PixelInterpolateMethod
5035     interpolate;
5036
5037   assert(image != (Image *) NULL);
5038   assert(image->signature == MagickSignature);
5039   assert(image_view != (CacheView *) NULL);
5040   status=MagickTrue;
5041   x_offset=(ssize_t) floor(x);
5042   y_offset=(ssize_t) floor(y);
5043   interpolate = method;
5044   if ( interpolate == UndefinedInterpolatePixel )
5045     interpolate = image->interpolate;
5046   switch (interpolate)
5047   {
5048     case AverageInterpolatePixel:        /* nearest 4 neighbours */
5049     case Average9InterpolatePixel:       /* nearest 9 neighbours */
5050     case Average16InterpolatePixel:      /* nearest 16 neighbours */
5051     {
5052       size_t
5053         count=2; /* size of the area to average - default nearest 4 */
5054
5055       if (interpolate == Average9InterpolatePixel)
5056         {
5057           count=3;
5058           x_offset=(ssize_t) (floor(x+0.5)-1);
5059           y_offset=(ssize_t) (floor(y+0.5)-1);
5060         }
5061       else if (interpolate == Average16InterpolatePixel)
5062         {
5063           count=4;
5064           x_offset--;
5065           y_offset--;
5066         }
5067       p=GetCacheViewVirtualPixels(image_view,x_offset,y_offset,count,count,
5068         exception);
5069       if (p == (const Quantum *) NULL)
5070         {
5071           status=MagickFalse;
5072           break;
5073         }
5074       pixel->red=0.0;
5075       pixel->green=0.0;
5076       pixel->blue=0.0;
5077       pixel->black=0.0;
5078       pixel->alpha=0.0;
5079       count*=count;         /* number of pixels - square of size */
5080       for (i=0; i < (ssize_t) count; i++)
5081       {
5082         AlphaBlendPixelInfo(image,p,pixels,alpha);
5083         gamma=MagickEpsilonReciprocal(alpha[0]);
5084         pixel->red   += gamma*pixels[0].red;
5085         pixel->green += gamma*pixels[0].green;
5086         pixel->blue  += gamma*pixels[0].blue;
5087         pixel->black += gamma*pixels[0].black;
5088         pixel->alpha +=       pixels[0].alpha;
5089         p += GetPixelChannels(image);
5090       }
5091       gamma=1.0/count;   /* average weighting of each pixel in area */
5092       pixel->red   *= gamma;
5093       pixel->green *= gamma;
5094       pixel->blue  *= gamma;
5095       pixel->black *= gamma;
5096       pixel->alpha *= gamma;
5097       break;
5098     }
5099     case BackgroundInterpolatePixel:
5100     {
5101       *pixel = image->background_color;  /* Copy PixelInfo Structure  */
5102       break;
5103     }
5104     case BilinearInterpolatePixel:
5105     default:
5106     {
5107       PointInfo
5108         delta,
5109         epsilon;
5110
5111       p=GetCacheViewVirtualPixels(image_view,x_offset,y_offset,2,2,exception);
5112       if (p == (const Quantum *) NULL)
5113         {
5114           status=MagickFalse;
5115           break;
5116         }
5117       for (i=0; i < 4L; i++)
5118         AlphaBlendPixelInfo(image,p+i*GetPixelChannels(image),pixels+i,alpha+i);
5119       delta.x=x-x_offset;
5120       delta.y=y-y_offset;
5121       epsilon.x=1.0-delta.x;
5122       epsilon.y=1.0-delta.y;
5123       gamma=((epsilon.y*(epsilon.x*alpha[0]+delta.x*alpha[1])+delta.y*
5124         (epsilon.x*alpha[2]+delta.x*alpha[3])));
5125       gamma=MagickEpsilonReciprocal(gamma);
5126       pixel->red=gamma*(epsilon.y*(epsilon.x*pixels[0].red+delta.x*
5127         pixels[1].red)+delta.y*(epsilon.x*pixels[2].red+delta.x*pixels[3].red));
5128       pixel->green=gamma*(epsilon.y*(epsilon.x*pixels[0].green+delta.x*
5129         pixels[1].green)+delta.y*(epsilon.x*pixels[2].green+delta.x*
5130         pixels[3].green));
5131       pixel->blue=gamma*(epsilon.y*(epsilon.x*pixels[0].blue+delta.x*
5132         pixels[1].blue)+delta.y*(epsilon.x*pixels[2].blue+delta.x*
5133         pixels[3].blue));
5134       if (image->colorspace == CMYKColorspace)
5135         pixel->black=gamma*(epsilon.y*(epsilon.x*pixels[0].black+delta.x*
5136           pixels[1].black)+delta.y*(epsilon.x*pixels[2].black+delta.x*
5137           pixels[3].black));
5138       gamma=((epsilon.y*(epsilon.x+delta.x)+delta.y*(epsilon.x+delta.x)));
5139       gamma=MagickEpsilonReciprocal(gamma);
5140       pixel->alpha=(epsilon.y*(epsilon.x*pixels[0].alpha+delta.x*
5141         pixels[1].alpha)+delta.y*(epsilon.x*pixels[2].alpha+delta.x*
5142         pixels[3].alpha));
5143       break;
5144     }
5145     case BlendInterpolatePixel:
5146     {
5147       p=GetCacheViewVirtualPixels(image_view,x_offset,y_offset,2,2,exception);
5148       if (p == (const Quantum *) NULL)
5149         {
5150           status=MagickFalse;
5151           break;
5152         }
5153       for (i=0; i < 4L; i++)
5154         AlphaBlendPixelInfo(image,p+i*GetPixelChannels(image),pixels+i,alpha+i);
5155       gamma=1.0;       /* number of pixels blended together */
5156       for (i=0; i <= 1L; i++) {
5157         if ( y-y_offset >= 0.75 ) {
5158           alpha[i]  = alpha[i+2];
5159           pixels[i] = pixels[i+2];
5160         }
5161         else if ( y-y_offset > 0.25 ) {
5162           gamma = 2.0;             /* each y pixels have been blended */
5163           alpha[i]        += alpha[i+2];  /* add up alpha weights */
5164           pixels[i].red   += pixels[i+2].red;
5165           pixels[i].green += pixels[i+2].green;
5166           pixels[i].blue  += pixels[i+2].blue;
5167           pixels[i].black += pixels[i+2].black;
5168           pixels[i].alpha += pixels[i+2].alpha;
5169         }
5170       }
5171       if ( x-x_offset >= 0.75 ) {
5172         alpha[0]  = alpha[1];
5173         pixels[0] = pixels[1];
5174       }
5175       else if ( x-x_offset > 0.25 ) {
5176         gamma *= 2.0;          /* double number of pixels blended */
5177         alpha[0]        += alpha[1];  /* add up alpha weights */
5178         pixels[0].red   += pixels[1].red;
5179         pixels[0].green += pixels[1].green;
5180         pixels[0].blue  += pixels[1].blue;
5181         pixels[0].black += pixels[1].black;
5182         pixels[0].alpha += pixels[1].alpha;
5183       }
5184       gamma = 1.0/gamma;
5185       alpha[0]=MagickEpsilonReciprocal(alpha[0]);
5186       pixel->red   = alpha[0]*pixels[0].red;
5187       pixel->green = alpha[0]*pixels[0].green; /* divide by sum of alpha */
5188       pixel->blue  = alpha[0]*pixels[0].blue;
5189       pixel->black = alpha[0]*pixels[0].black;
5190       pixel->alpha =    gamma*pixels[0].alpha; /* divide by number of pixels */
5191       break;
5192     }
5193     case CatromInterpolatePixel:
5194     {
5195       double
5196         cx[4],
5197         cy[4];
5198
5199       p=GetCacheViewVirtualPixels(image_view,x_offset-1,y_offset-1,4,4,
5200         exception);
5201       if (p == (const Quantum *) NULL)
5202         {
5203           status=MagickFalse;
5204           break;
5205         }
5206       for (i=0; i < 16L; i++)
5207         AlphaBlendPixelInfo(image,p+i*GetPixelChannels(image),pixels+i,alpha+i);
5208       CatromWeights((double) (x-x_offset),&cx);
5209       CatromWeights((double) (y-y_offset),&cy);
5210       pixel->red=(cy[0]*(cx[0]*pixels[0].red+cx[1]*
5211         pixels[1].red+cx[2]*pixels[2].red+cx[3]*
5212         pixels[3].red)+cy[1]*(cx[0]*pixels[4].red+cx[1]*
5213         pixels[5].red+cx[2]*pixels[6].red+cx[3]*
5214         pixels[7].red)+cy[2]*(cx[0]*pixels[8].red+cx[1]*
5215         pixels[9].red+cx[2]*pixels[10].red+cx[3]*
5216         pixels[11].red)+cy[3]*(cx[0]*pixels[12].red+cx[1]*
5217         pixels[13].red+cx[2]*pixels[14].red+cx[3]*pixels[15].red));
5218       pixel->green=(cy[0]*(cx[0]*pixels[0].green+cx[1]*
5219         pixels[1].green+cx[2]*pixels[2].green+cx[3]*
5220         pixels[3].green)+cy[1]*(cx[0]*pixels[4].green+cx[1]*
5221         pixels[5].green+cx[2]*pixels[6].green+cx[3]*
5222         pixels[7].green)+cy[2]*(cx[0]*pixels[8].green+cx[1]*
5223         pixels[9].green+cx[2]*pixels[10].green+cx[3]*
5224         pixels[11].green)+cy[3]*(cx[0]*pixels[12].green+cx[1]*
5225         pixels[13].green+cx[2]*pixels[14].green+cx[3]*pixels[15].green));
5226       pixel->blue=(cy[0]*(cx[0]*pixels[0].blue+cx[1]*
5227         pixels[1].blue+cx[2]*pixels[2].blue+cx[3]*
5228         pixels[3].blue)+cy[1]*(cx[0]*pixels[4].blue+cx[1]*
5229         pixels[5].blue+cx[2]*pixels[6].blue+cx[3]*
5230         pixels[7].blue)+cy[2]*(cx[0]*pixels[8].blue+cx[1]*
5231         pixels[9].blue+cx[2]*pixels[10].blue+cx[3]*
5232         pixels[11].blue)+cy[3]*(cx[0]*pixels[12].blue+cx[1]*
5233         pixels[13].blue+cx[2]*pixels[14].blue+cx[3]*pixels[15].blue));
5234       if (image->colorspace == CMYKColorspace)
5235         pixel->black=(cy[0]*(cx[0]*pixels[0].black+cx[1]*
5236           pixels[1].black+cx[2]*pixels[2].black+cx[3]*
5237           pixels[3].black)+cy[1]*(cx[0]*pixels[4].black+cx[1]*
5238           pixels[5].black+cx[2]*pixels[6].black+cx[3]*
5239           pixels[7].black)+cy[2]*(cx[0]*pixels[8].black+cx[1]*
5240           pixels[9].black+cx[2]*pixels[10].black+cx[3]*
5241           pixels[11].black)+cy[3]*(cx[0]*pixels[12].black+cx[1]*
5242           pixels[13].black+cx[2]*pixels[14].black+cx[3]*pixels[15].black));
5243       pixel->alpha=(cy[0]*(cx[0]*pixels[0].alpha+cx[1]*
5244         pixels[1].alpha+cx[2]*pixels[2].alpha+cx[3]*
5245         pixels[3].alpha)+cy[1]*(cx[0]*pixels[4].alpha+cx[1]*
5246         pixels[5].alpha+cx[2]*pixels[6].alpha+cx[3]*
5247         pixels[7].alpha)+cy[2]*(cx[0]*pixels[8].alpha+cx[1]*
5248         pixels[9].alpha+cx[2]*pixels[10].alpha+cx[3]*
5249         pixels[11].alpha)+cy[3]*(cx[0]*pixels[12].alpha+cx[1]*
5250         pixels[13].alpha+cx[2]*pixels[14].alpha+cx[3]*pixels[15].alpha));
5251       break;
5252     }
5253 #if 0
5254     /* deprecated useless and very slow interpolator */
5255     case FilterInterpolatePixel:
5256     {
5257       CacheView
5258         *filter_view;
5259
5260       Image
5261         *excerpt_image,
5262         *filter_image;
5263
5264       RectangleInfo
5265         geometry;
5266
5267       geometry.width=4L;
5268       geometry.height=4L;
5269       geometry.x=x_offset-1;
5270       geometry.y=y_offset-1;
5271       excerpt_image=ExcerptImage(image,&geometry,exception);
5272       if (excerpt_image == (Image *) NULL)
5273         {
5274           status=MagickFalse;
5275           break;
5276         }
5277       filter_image=ResizeImage(excerpt_image,1,1,image->filter,exception);
5278       excerpt_image=DestroyImage(excerpt_image);
5279       if (filter_image == (Image *) NULL)
5280         break;
5281       filter_view=AcquireVirtualCacheView(filter_image,exception);
5282       p=GetCacheViewVirtualPixels(filter_view,0,0,1,1,exception);
5283       if (p != (const Quantum *) NULL)
5284         GetPixelInfoPixel(image,p,pixel);
5285       filter_view=DestroyCacheView(filter_view);
5286       filter_image=DestroyImage(filter_image);
5287       break;
5288     }
5289 #endif
5290     case IntegerInterpolatePixel:
5291     {
5292       p=GetCacheViewVirtualPixels(image_view,x_offset,y_offset,1,1,exception);
5293       if (p == (const Quantum *) NULL)
5294         {
5295           status=MagickFalse;
5296           break;
5297         }
5298       GetPixelInfoPixel(image,p,pixel);
5299       break;
5300     }
5301     case MeshInterpolatePixel:
5302     {
5303       PointInfo
5304         delta,
5305         luminance;
5306
5307       p=GetCacheViewVirtualPixels(image_view,x_offset,y_offset,2,2,exception);
5308       if (p == (const Quantum *) NULL)
5309         {
5310           status=MagickFalse;
5311           break;
5312         }
5313       delta.x=x-x_offset;
5314       delta.y=y-y_offset;
5315       luminance.x=GetPixelLuminance(image,p)-(double)
5316         GetPixelLuminance(image,p+3*GetPixelChannels(image));
5317       luminance.y=GetPixelLuminance(image,p+GetPixelChannels(image))-(double)
5318         GetPixelLuminance(image,p+2*GetPixelChannels(image));
5319       AlphaBlendPixelInfo(image,p,pixels+0,alpha+0);
5320       AlphaBlendPixelInfo(image,p+GetPixelChannels(image),pixels+1,alpha+1);
5321       AlphaBlendPixelInfo(image,p+2*GetPixelChannels(image),pixels+2,alpha+2);
5322       AlphaBlendPixelInfo(image,p+3*GetPixelChannels(image),pixels+3,alpha+3);
5323       if (fabs(luminance.x) < fabs(luminance.y))
5324         {
5325           /*
5326             Diagonal 0-3 NW-SE.
5327           */
5328           if (delta.x <= delta.y)
5329             {
5330               /*
5331                 Bottom-left triangle (pixel: 2, diagonal: 0-3).
5332               */
5333               delta.y=1.0-delta.y;
5334               gamma=MeshInterpolate(&delta,alpha[2],alpha[3],alpha[0]);
5335               gamma=MagickEpsilonReciprocal(gamma);
5336               pixel->red=gamma*MeshInterpolate(&delta,pixels[2].red,
5337                 pixels[3].red,pixels[0].red);
5338               pixel->green=gamma*MeshInterpolate(&delta,pixels[2].green,
5339                 pixels[3].green,pixels[0].green);
5340               pixel->blue=gamma*MeshInterpolate(&delta,pixels[2].blue,
5341                 pixels[3].blue,pixels[0].blue);
5342               if (image->colorspace == CMYKColorspace)
5343                 pixel->black=gamma*MeshInterpolate(&delta,pixels[2].black,
5344                   pixels[3].black,pixels[0].black);
5345               gamma=MeshInterpolate(&delta,1.0,1.0,1.0);
5346               pixel->alpha=gamma*MeshInterpolate(&delta,pixels[2].alpha,
5347                 pixels[3].alpha,pixels[0].alpha);
5348             }
5349           else
5350             {
5351               /*
5352                 Top-right triangle (pixel:1 , diagonal: 0-3).
5353               */
5354               delta.x=1.0-delta.x;
5355               gamma=MeshInterpolate(&delta,alpha[1],alpha[0],alpha[3]);
5356               gamma=MagickEpsilonReciprocal(gamma);
5357               pixel->red=gamma*MeshInterpolate(&delta,pixels[1].red,
5358                 pixels[0].red,pixels[3].red);
5359               pixel->green=gamma*MeshInterpolate(&delta,pixels[1].green,
5360                 pixels[0].green,pixels[3].green);
5361               pixel->blue=gamma*MeshInterpolate(&delta,pixels[1].blue,
5362                 pixels[0].blue,pixels[3].blue);
5363               if (image->colorspace == CMYKColorspace)
5364                 pixel->black=gamma*MeshInterpolate(&delta,pixels[1].black,
5365                   pixels[0].black,pixels[3].black);
5366               gamma=MeshInterpolate(&delta,1.0,1.0,1.0);
5367               pixel->alpha=gamma*MeshInterpolate(&delta,pixels[1].alpha,
5368                 pixels[0].alpha,pixels[3].alpha);
5369             }
5370         }
5371       else
5372         {
5373           /*
5374             Diagonal 1-2 NE-SW.
5375           */
5376           if (delta.x <= (1.0-delta.y))
5377             {
5378               /*
5379                 Top-left triangle (pixel: 0, diagonal: 1-2).
5380               */
5381               gamma=MeshInterpolate(&delta,alpha[0],alpha[1],alpha[2]);
5382               gamma=MagickEpsilonReciprocal(gamma);
5383               pixel->red=gamma*MeshInterpolate(&delta,pixels[0].red,
5384                 pixels[1].red,pixels[2].red);
5385               pixel->green=gamma*MeshInterpolate(&delta,pixels[0].green,
5386                 pixels[1].green,pixels[2].green);
5387               pixel->blue=gamma*MeshInterpolate(&delta,pixels[0].blue,
5388                 pixels[1].blue,pixels[2].blue);
5389               if (image->colorspace == CMYKColorspace)
5390                 pixel->black=gamma*MeshInterpolate(&delta,pixels[0].black,
5391                   pixels[1].black,pixels[2].black);
5392               gamma=MeshInterpolate(&delta,1.0,1.0,1.0);
5393               pixel->alpha=gamma*MeshInterpolate(&delta,pixels[0].alpha,
5394                 pixels[1].alpha,pixels[2].alpha);
5395             }
5396           else
5397             {
5398               /*
5399                 Bottom-right triangle (pixel: 3, diagonal: 1-2).
5400               */
5401               delta.x=1.0-delta.x;
5402               delta.y=1.0-delta.y;
5403               gamma=MeshInterpolate(&delta,alpha[3],alpha[2],alpha[1]);
5404               gamma=MagickEpsilonReciprocal(gamma);
5405               pixel->red=gamma*MeshInterpolate(&delta,pixels[3].red,
5406                 pixels[2].red,pixels[1].red);
5407               pixel->green=gamma*MeshInterpolate(&delta,pixels[3].green,
5408                 pixels[2].green,pixels[1].green);
5409               pixel->blue=gamma*MeshInterpolate(&delta,pixels[3].blue,
5410                 pixels[2].blue,pixels[1].blue);
5411               if (image->colorspace == CMYKColorspace)
5412                 pixel->black=gamma*MeshInterpolate(&delta,pixels[3].black,
5413                   pixels[2].black,pixels[1].black);
5414               gamma=MeshInterpolate(&delta,1.0,1.0,1.0);
5415               pixel->alpha=gamma*MeshInterpolate(&delta,pixels[3].alpha,
5416                 pixels[2].alpha,pixels[1].alpha);
5417             }
5418         }
5419       break;
5420     }
5421     case NearestInterpolatePixel:
5422     {
5423       x_offset=(ssize_t) floor(x+0.5);
5424       y_offset=(ssize_t) floor(y+0.5);
5425       p=GetCacheViewVirtualPixels(image_view,x_offset,y_offset,1,1,exception);
5426       if (p == (const Quantum *) NULL)
5427         {
5428           status=MagickFalse;
5429           break;
5430         }
5431       GetPixelInfoPixel(image,p,pixel);
5432       break;
5433     }
5434     case SplineInterpolatePixel:
5435     {
5436       double
5437         cx[4],
5438         cy[4];
5439
5440       p=GetCacheViewVirtualPixels(image_view,x_offset-1,y_offset-1,4,4,
5441         exception);
5442       if (p == (const Quantum *) NULL)
5443         {
5444           status=MagickFalse;
5445           break;
5446         }
5447       for (i=0; i < 16L; i++)
5448         AlphaBlendPixelInfo(image,p+i*GetPixelChannels(image),pixels+i,alpha+i);
5449       SplineWeights((double) (x-x_offset),&cx);
5450       SplineWeights((double) (y-y_offset),&cy);
5451       pixel->red=(cy[0]*(cx[0]*pixels[0].red+cx[1]*
5452         pixels[1].red+cx[2]*pixels[2].red+cx[3]*
5453         pixels[3].red)+cy[1]*(cx[0]*pixels[4].red+cx[1]*
5454         pixels[5].red+cx[2]*pixels[6].red+cx[3]*
5455         pixels[7].red)+cy[2]*(cx[0]*pixels[8].red+cx[1]*
5456         pixels[9].red+cx[2]*pixels[10].red+cx[3]*
5457         pixels[11].red)+cy[3]*(cx[0]*pixels[12].red+cx[1]*
5458         pixels[13].red+cx[2]*pixels[14].red+cx[3]*pixels[15].red));
5459       pixel->green=(cy[0]*(cx[0]*pixels[0].green+cx[1]*
5460         pixels[1].green+cx[2]*pixels[2].green+cx[3]*
5461         pixels[3].green)+cy[1]*(cx[0]*pixels[4].green+cx[1]*
5462         pixels[5].green+cx[2]*pixels[6].green+cx[3]*
5463         pixels[7].green)+cy[2]*(cx[0]*pixels[8].green+cx[1]*
5464         pixels[9].green+cx[2]*pixels[10].green+cx[3]*
5465         pixels[11].green)+cy[3]*(cx[0]*pixels[12].green+cx[1]*
5466         pixels[13].green+cx[2]*pixels[14].green+cx[3]*pixels[15].green));
5467       pixel->blue=(cy[0]*(cx[0]*pixels[0].blue+cx[1]*
5468         pixels[1].blue+cx[2]*pixels[2].blue+cx[3]*
5469         pixels[3].blue)+cy[1]*(cx[0]*pixels[4].blue+cx[1]*
5470         pixels[5].blue+cx[2]*pixels[6].blue+cx[3]*
5471         pixels[7].blue)+cy[2]*(cx[0]*pixels[8].blue+cx[1]*
5472         pixels[9].blue+cx[2]*pixels[10].blue+cx[3]*
5473         pixels[11].blue)+cy[3]*(cx[0]*pixels[12].blue+cx[1]*
5474         pixels[13].blue+cx[2]*pixels[14].blue+cx[3]*pixels[15].blue));
5475       if (image->colorspace == CMYKColorspace)
5476         pixel->black=(cy[0]*(cx[0]*pixels[0].black+cx[1]*
5477           pixels[1].black+cx[2]*pixels[2].black+cx[3]*
5478           pixels[3].black)+cy[1]*(cx[0]*pixels[4].black+cx[1]*
5479           pixels[5].black+cx[2]*pixels[6].black+cx[3]*
5480           pixels[7].black)+cy[2]*(cx[0]*pixels[8].black+cx[1]*
5481           pixels[9].black+cx[2]*pixels[10].black+cx[3]*
5482           pixels[11].black)+cy[3]*(cx[0]*pixels[12].black+cx[1]*
5483           pixels[13].black+cx[2]*pixels[14].black+cx[3]*pixels[15].black));
5484       pixel->alpha=(cy[0]*(cx[0]*pixels[0].alpha+cx[1]*
5485         pixels[1].alpha+cx[2]*pixels[2].alpha+cx[3]*
5486         pixels[3].alpha)+cy[1]*(cx[0]*pixels[4].alpha+cx[1]*
5487         pixels[5].alpha+cx[2]*pixels[6].alpha+cx[3]*
5488         pixels[7].alpha)+cy[2]*(cx[0]*pixels[8].alpha+cx[1]*
5489         pixels[9].alpha+cx[2]*pixels[10].alpha+cx[3]*
5490         pixels[11].alpha)+cy[3]*(cx[0]*pixels[12].alpha+cx[1]*
5491         pixels[13].alpha+cx[2]*pixels[14].alpha+cx[3]*pixels[15].alpha));
5492       break;
5493     }
5494   }
5495   return(status);
5496 }
5497 \f
5498 /*
5499 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5500 %                                                                             %
5501 %                                                                             %
5502 %                                                                             %
5503 +   I s F u z z y E q u i v a l e n c e P i x e l                             %
5504 %                                                                             %
5505 %                                                                             %
5506 %                                                                             %
5507 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5508 %
5509 %  IsFuzzyEquivalencePixel() returns MagickTrue if the distance between two
5510 %  pixels is less than the specified distance in a linear three (or four)u
5511 %  dimensional color space.
5512 %
5513 %  The format of the IsFuzzyEquivalencePixel method is:
5514 %
5515 %      void IsFuzzyEquivalencePixel(const Image *source,const Quantum *p,
5516 %        const Image *destination,const Quantum *q)
5517 %
5518 %  A description of each parameter follows:
5519 %
5520 %    o source: the source image.
5521 %
5522 %    o p: Pixel p.
5523 %
5524 %    o destination: the destination image.
5525 %
5526 %    o q: Pixel q.
5527 %
5528 */
5529 MagickExport MagickBooleanType IsFuzzyEquivalencePixel(const Image *source,
5530   const Quantum *p,const Image *destination,const Quantum *q)
5531 {
5532   double
5533     fuzz,
5534     pixel;
5535
5536   register double
5537     distance,
5538     scale;
5539
5540   fuzz=MagickMax(source->fuzz,(double) MagickSQ1_2)*MagickMax(
5541     destination->fuzz,(double) MagickSQ1_2);
5542   scale=1.0;
5543   distance=0.0;
5544   if (source->alpha_trait == BlendPixelTrait)
5545     {
5546       /*
5547         Transparencies are involved - set alpha distance
5548       */
5549       pixel=GetPixelAlpha(source,p)-(double)
5550         GetPixelAlpha(destination,q);
5551       distance=pixel*pixel;
5552       if (distance > fuzz)
5553         return(MagickFalse);
5554       /*
5555         Generate a alpha scaling factor to generate a 4D cone on colorspace
5556         Note that if one color is transparent, distance has no color component.
5557       */
5558       scale=QuantumScale*GetPixelAlpha(source,p);
5559       scale*=QuantumScale*GetPixelAlpha(destination,q);
5560       if (scale <= MagickEpsilon)
5561         return(MagickTrue);
5562     }
5563   /*
5564     RGB or CMY color cube
5565   */
5566   distance*=3.0;  /* rescale appropriately */
5567   fuzz*=3.0;
5568   pixel=GetPixelRed(source,p)-(double) GetPixelRed(destination,q);
5569   if ((source->colorspace == HSLColorspace) ||
5570       (source->colorspace == HSBColorspace) ||
5571       (source->colorspace == HWBColorspace))
5572     {
5573       /*
5574         Compute an arc distance for hue.  It should be a vector angle of
5575         'S'/'W' length with 'L'/'B' forming appropriate cones.
5576       */
5577       if (fabs((double) pixel) > (QuantumRange/2))
5578         pixel-=QuantumRange;
5579       pixel*=2;
5580     }
5581   distance+=scale*pixel*pixel;
5582   if (distance > fuzz)
5583     return(MagickFalse);
5584   pixel=GetPixelGreen(source,p)-(double) GetPixelGreen(destination,q);
5585   distance+=scale*pixel*pixel;
5586   if (distance > fuzz)
5587     return(MagickFalse);
5588   pixel=GetPixelBlue(source,p)-(double) GetPixelBlue(destination,q);
5589   distance+=scale*pixel*pixel;
5590   if (distance > fuzz)
5591     return(MagickFalse);
5592   return(MagickTrue);
5593 }
5594 \f
5595 /*
5596 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5597 %                                                                             %
5598 %                                                                             %
5599 %                                                                             %
5600 +   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                     %
5601 %                                                                             %
5602 %                                                                             %
5603 %                                                                             %
5604 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5605 %
5606 %  IsFuzzyEquivalencePixelInfo() returns true if the distance between two
5607 %  colors is less than the specified distance in a linear three (or four)
5608 %  dimensional color space.
5609 %
5610 %  This implements the equivalent of:
5611 %    fuzz < sqrt(color_distance^2 * u.a*v.a  + alpha_distance^2)
5612 %
5613 %  Which produces a multi-dimensional cone for that colorspace along the
5614 %  transparency vector.
5615 %
5616 %  For example for an RGB:
5617 %    color_distance^2  = ( (u.r-v.r)^2 + (u.g-v.g)^2 + (u.b-v.b)^2 ) / 3
5618 %
5619 %  See http://www.imagemagick.org/Usage/bugs/fuzz_distance/
5620 %
5621 %  Hue colorspace distances need more work.  Hue is not a distance, it is an
5622 %  angle!
5623 %
5624 %  A check that q is in the same color space as p should be made and the
5625 %  appropriate mapping made.  -- Anthony Thyssen  8 December 2010
5626 %
5627 %  The format of the IsFuzzyEquivalencePixelInfo method is:
5628 %
5629 %      MagickBooleanType IsFuzzyEquivalencePixelInfo(const PixelInfo *p,
5630 %        const PixelInfo *q)
5631 %
5632 %  A description of each parameter follows:
5633 %
5634 %    o p: Pixel p.
5635 %
5636 %    o q: Pixel q.
5637 %
5638 */
5639 MagickExport MagickBooleanType IsFuzzyEquivalencePixelInfo(const PixelInfo *p,
5640   const PixelInfo *q)
5641 {
5642   double
5643     fuzz,
5644     pixel;
5645
5646   register double
5647     scale,
5648     distance;
5649
5650   if ((p->fuzz == 0.0) && (q->fuzz == 0.0))
5651     return(IsPixelInfoEquivalent(p,q));
5652   if (p->fuzz == 0.0)
5653     fuzz=MagickMax(q->fuzz,(double) MagickSQ1_2)*MagickMax(q->fuzz,
5654       (double) MagickSQ1_2);
5655   else if (q->fuzz == 0.0)
5656     fuzz=MagickMax(p->fuzz,(double) MagickSQ1_2)*MagickMax(p->fuzz,
5657       (double) MagickSQ1_2);
5658   else
5659     fuzz=MagickMax(p->fuzz,(double) MagickSQ1_2)*MagickMax(q->fuzz,
5660       (double) MagickSQ1_2);
5661   scale=1.0;
5662   distance=0.0;
5663   if ((p->alpha_trait == BlendPixelTrait) || (q->alpha_trait == BlendPixelTrait))
5664     {
5665       /*
5666         Transparencies are involved - set alpha distance.
5667       */
5668       pixel=(p->alpha_trait == BlendPixelTrait ? p->alpha : OpaqueAlpha)-
5669         (q->alpha_trait == BlendPixelTrait ? q->alpha : OpaqueAlpha);
5670       distance=pixel*pixel;
5671       if (distance > fuzz)
5672         return(MagickFalse);
5673       /*
5674         Generate a alpha scaling factor to generate a 4D cone on colorspace.
5675         If one color is transparent, distance has no color component.
5676       */
5677       if (p->alpha_trait == BlendPixelTrait)
5678         scale=(QuantumScale*p->alpha);
5679       if (q->alpha_trait == BlendPixelTrait)
5680         scale*=(QuantumScale*q->alpha);
5681       if (scale <= MagickEpsilon )
5682         return(MagickTrue);
5683     }
5684   /*
5685     CMYK create a CMY cube with a multi-dimensional cone toward black.
5686   */
5687   if (p->colorspace == CMYKColorspace)
5688     {
5689       pixel=p->black-q->black;
5690       distance+=pixel*pixel*scale;
5691       if (distance > fuzz)
5692         return(MagickFalse);
5693       scale*=(double) (QuantumScale*(QuantumRange-p->black));
5694       scale*=(double) (QuantumScale*(QuantumRange-q->black));
5695     }
5696   /*
5697     RGB or CMY color cube.
5698   */
5699   distance*=3.0;  /* rescale appropriately */
5700   fuzz*=3.0;
5701   pixel=p->red-q->red;
5702   if ((p->colorspace == HSLColorspace) || (p->colorspace == HSBColorspace) ||
5703       (p->colorspace == HWBColorspace))
5704     {
5705       /*
5706         This calculates a arc distance for hue-- it should be a vector angle
5707         of 'S'/'W' length with 'L'/'B' forming appropriate cones.  In other
5708         words this is a hack - Anthony.
5709       */
5710       if (fabs((double) pixel) > (QuantumRange/2))
5711         pixel-=QuantumRange;
5712       pixel*=2;
5713     }
5714   distance+=pixel*pixel*scale;
5715   if (distance > fuzz)
5716     return(MagickFalse);
5717   pixel=p->green-q->green;
5718   distance+=pixel*pixel*scale;
5719   if (distance > fuzz)
5720     return(MagickFalse);
5721   pixel=p->blue-q->blue;
5722   distance+=pixel*pixel*scale;
5723   if (distance > fuzz)
5724     return(MagickFalse);
5725   return(MagickTrue);
5726 }
5727 \f
5728 /*
5729 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5730 %                                                                             %
5731 %                                                                             %
5732 %                                                                             %
5733 %   S e t P i x e l C h a n n e l M a p M a s k                               %
5734 %                                                                             %
5735 %                                                                             %
5736 %                                                                             %
5737 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5738 %
5739 %  SetPixelChannelMask() sets the pixel channel map from the specified
5740 %  channel mask.
5741 %
5742 %  The format of the SetPixelChannelMask method is:
5743 %
5744 %      void SetPixelChannelMask(Image *image,const ChannelType channel_mask)
5745 %
5746 %  A description of each parameter follows:
5747 %
5748 %    o image: the image.
5749 %
5750 %    o channel_mask: the channel mask.
5751 %
5752 */
5753 MagickExport void SetPixelChannelMask(Image *image,
5754   const ChannelType channel_mask)
5755 {
5756 #define GetChannelBit(mask,bit)  (((size_t) (mask) >> (size_t) (bit)) & 0x01)
5757
5758   register ssize_t
5759     i;
5760
5761   if (image->debug != MagickFalse)
5762     (void) LogMagickEvent(PixelEvent,GetMagickModule(),"%s[%08x]", \
5763       image->filename,channel_mask); \
5764   image->channel_mask=channel_mask;
5765   for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
5766   {
5767     PixelChannel
5768       channel;
5769
5770     channel=GetPixelChannelChannel(image,i);
5771     SetPixelChannelTraits(image,channel,
5772       GetChannelBit(channel_mask,channel) == 0 ? CopyPixelTrait :
5773       image->alpha_trait != BlendPixelTrait || (channel == AlphaPixelChannel) ?
5774       UpdatePixelTrait : (PixelTrait) (UpdatePixelTrait | image->alpha_trait));
5775   }
5776   if (image->storage_class == PseudoClass)
5777     SetPixelChannelTraits(image,IndexPixelChannel,CopyPixelTrait);
5778   if (image->mask != MagickFalse)
5779     SetPixelChannelTraits(image,MaskPixelChannel,CopyPixelTrait);
5780   if (image->debug != MagickFalse)
5781     LogPixelChannels(image);
5782 }
5783 \f
5784 /*
5785 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5786 %                                                                             %
5787 %                                                                             %
5788 %                                                                             %
5789 %   S e t P i x e l M e t a C h a n n e l s                                   %
5790 %                                                                             %
5791 %                                                                             %
5792 %                                                                             %
5793 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5794 %
5795 %  SetPixelMetaChannels() sets the image meta channels.
5796 %
5797 %  The format of the SetPixelMetaChannels method is:
5798 %
5799 %      MagickBooleanType SetPixelMetaChannels(Image *image,
5800 %        const size_t number_meta_channels,ExceptionInfo *exception)
5801 %
5802 %  A description of each parameter follows:
5803 %
5804 %    o image: the image.
5805 %
5806 %    o number_meta_channels:  the number of meta channels.
5807 %
5808 %    o exception: return any errors or warnings in this structure.
5809 %
5810 */
5811 MagickExport MagickBooleanType SetPixelMetaChannels(Image *image,
5812   const size_t number_meta_channels,ExceptionInfo *exception)
5813 {
5814   image->number_meta_channels=number_meta_channels;
5815   return(SyncImagePixelCache(image,exception));
5816 }