]> granicus.if.org Git - imagemagick/blob - MagickCore/pixel.c
(no commit message)
[imagemagick] / MagickCore / pixel.c
1 /*
2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3 %                                                                             %
4 %                                                                             %
5 %                                                                             %
6 %                      PPPP   IIIII  X   X  EEEEE  L                          %
7 %                      P   P    I     X X   E      L                          %
8 %                      PPPP     I      X    EEE    L                          %
9 %                      P        I     X X   E      L                          %
10 %                      P      IIIII  X   X  EEEEE  LLLLL                      %
11 %                                                                             %
12 %                  MagickCore Methods to Import/Export Pixels                 %
13 %                                                                             %
14 %                             Software Design                                 %
15 %                               John Cristy                                   %
16 %                               October 1998                                  %
17 %                                                                             %
18 %                                                                             %
19 %  Copyright 1999-2012 ImageMagick Studio LLC, a non-profit organization      %
20 %  dedicated to making software imaging solutions freely available.           %
21 %                                                                             %
22 %  You may not use this file except in compliance with the License.  You may  %
23 %  obtain a copy of the License at                                            %
24 %                                                                             %
25 %    http://www.imagemagick.org/script/license.php                            %
26 %                                                                             %
27 %  Unless required by applicable law or agreed to in writing, software        %
28 %  distributed under the License is distributed on an "AS IS" BASIS,          %
29 %  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   %
30 %  See the License for the specific language governing permissions and        %
31 %  limitations under the License.                                             %
32 %                                                                             %
33 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
34 %
35 %
36 */
37 \f
38 /*
39   Include declarations.
40 */
41 #include "MagickCore/studio.h"
42 #include "MagickCore/property.h"
43 #include "MagickCore/blob.h"
44 #include "MagickCore/blob-private.h"
45 #include "MagickCore/cache-private.h"
46 #include "MagickCore/color-private.h"
47 #include "MagickCore/draw.h"
48 #include "MagickCore/exception.h"
49 #include "MagickCore/exception-private.h"
50 #include "MagickCore/cache.h"
51 #include "MagickCore/constitute.h"
52 #include "MagickCore/delegate.h"
53 #include "MagickCore/geometry.h"
54 #include "MagickCore/image-private.h"
55 #include "MagickCore/list.h"
56 #include "MagickCore/magick.h"
57 #include "MagickCore/memory_.h"
58 #include "MagickCore/monitor.h"
59 #include "MagickCore/option.h"
60 #include "MagickCore/pixel.h"
61 #include "MagickCore/pixel-accessor.h"
62 #include "MagickCore/pixel-private.h"
63 #include "MagickCore/quantum.h"
64 #include "MagickCore/quantum-private.h"
65 #include "MagickCore/resource_.h"
66 #include "MagickCore/semaphore.h"
67 #include "MagickCore/statistic.h"
68 #include "MagickCore/stream.h"
69 #include "MagickCore/string_.h"
70 #include "MagickCore/transform.h"
71 #include "MagickCore/utility.h"
72 \f
73 #define LogPixelChannels(image) \
74 { \
75   register ssize_t \
76     i; \
77  \
78   (void) LogMagickEvent(PixelEvent,GetMagickModule(),"%s[%.20g]", \
79     image->filename,(double) image->number_channels); \
80   for (i=0; i < (ssize_t) image->number_channels; i++) \
81   { \
82     char \
83       traits[MaxTextExtent]; \
84  \
85     const char \
86       *name; \
87  \
88     PixelChannel \
89       channel; \
90  \
91     switch (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 BlendInterpolatePixel:
4187     {
4188       p=GetCacheViewVirtualPixels(image_view,x_offset,y_offset,2,2,exception);
4189       if (p == (const Quantum *) NULL)
4190         {
4191           status=MagickFalse;
4192           break;
4193         }
4194       if ((traits & BlendPixelTrait) == 0)
4195         for (i=0; i < 4; i++)
4196         {
4197           alpha[i]=1.0;
4198           pixels[i]=(MagickRealType) p[i*GetPixelChannels(image)+channel];
4199         }
4200       else
4201         for (i=0; i < 4; i++)
4202         {
4203           alpha[i]=QuantumScale*GetPixelAlpha(image,p+i*
4204             GetPixelChannels(image));
4205           pixels[i]=alpha[i]*p[i*GetPixelChannels(image)+channel];
4206         }
4207       gamma=1.0;    /* number of pixels blended together (its variable) */
4208       for (i=0; i <= 1L; i++) {
4209         if ( y-y_offset >= 0.75 ) { /* take right pixels */
4210           alpha[i]  = alpha[i+2];
4211           pixels[i] = pixels[i+2];
4212         }
4213         else if ( y-y_offset > 0.25 ) {
4214           gamma = 2.0;              /* blend both pixels in row */
4215           alpha[i]  += alpha[i+2];  /* add up alpha weights */
4216           pixels[i] += pixels[i+2];
4217         }
4218       }
4219       if ( x-x_offset >= 0.75 ) {   /* take bottom row blend */
4220         alpha[0]  = alpha[1];
4221         pixels[0] = pixels[1];
4222       }
4223       else if ( x-x_offset > 0.25 ) {
4224         gamma *= 2.0;               /* blend both rows */
4225         alpha[0]  += alpha[1];      /* add up alpha weights */
4226         pixels[0] += pixels[1];
4227       }
4228       if (channel != AlphaPixelChannel)
4229         gamma=MagickEpsilonReciprocal(alpha[0]); /* (color) 1/alpha_weights */
4230       else
4231         gamma=MagickEpsilonReciprocal(gamma); /* (alpha) 1/number_of_pixels */
4232       *pixel=gamma*pixels[0];
4233       break;
4234     }
4235     case CatromInterpolatePixel:
4236     {
4237       double
4238         cx[4],
4239         cy[4];
4240
4241       p=GetCacheViewVirtualPixels(image_view,x_offset-1,y_offset-1,4,4,
4242         exception);
4243       if (p == (const Quantum *) NULL)
4244         {
4245           status=MagickFalse;
4246           break;
4247         }
4248       if ((traits & BlendPixelTrait) == 0)
4249         for (i=0; i < 16; i++)
4250         {
4251           alpha[i]=1.0;
4252           pixels[i]=(double) p[i*GetPixelChannels(image)+channel];
4253         }
4254       else
4255         for (i=0; i < 16; i++)
4256         {
4257           alpha[i]=QuantumScale*GetPixelAlpha(image,p+i*
4258             GetPixelChannels(image));
4259           pixels[i]=alpha[i]*p[i*GetPixelChannels(image)+channel];
4260         }
4261       CatromWeights((double) (x-x_offset),&cx);
4262       CatromWeights((double) (y-y_offset),&cy);
4263       gamma=(channel == AlphaPixelChannel ? (double) 1.0 :
4264         MagickEpsilonReciprocal(cy[0]*(cx[0]*alpha[0]+cx[1]*alpha[1]+cx[2]*
4265         alpha[2]+cx[3]*alpha[3])+cy[1]*(cx[0]*alpha[4]+cx[1]*alpha[5]+cx[2]*
4266         alpha[6]+cx[3]*alpha[7])+cy[2]*(cx[0]*alpha[8]+cx[1]*alpha[9]+cx[2]*
4267         alpha[10]+cx[3]*alpha[11])+cy[3]*(cx[0]*alpha[12]+cx[1]*alpha[13]+
4268         cx[2]*alpha[14]+cx[3]*alpha[15])));
4269       *pixel=gamma*(cy[0]*(cx[0]*pixels[0]+cx[1]*pixels[1]+cx[2]*pixels[2]+
4270         cx[3]*pixels[3])+cy[1]*(cx[0]*pixels[4]+cx[1]*pixels[5]+cx[2]*
4271         pixels[6]+cx[3]*pixels[7])+cy[2]*(cx[0]*pixels[8]+cx[1]*pixels[9]+
4272         cx[2]*pixels[10]+cx[3]*pixels[11])+cy[3]*(cx[0]*pixels[12]+cx[1]*
4273         pixels[13]+cx[2]*pixels[14]+cx[3]*pixels[15]));
4274       break;
4275     }
4276 #if 0
4277     /* deprecated useless and very slow interpolator */
4278     case FilterInterpolatePixel:
4279     {
4280       CacheView
4281         *filter_view;
4282
4283       Image
4284         *excerpt_image,
4285         *filter_image;
4286
4287       RectangleInfo
4288         geometry;
4289
4290       geometry.width=4L;
4291       geometry.height=4L;
4292       geometry.x=x_offset-1;
4293       geometry.y=y_offset-1;
4294       excerpt_image=ExcerptImage(image,&geometry,exception);
4295       if (excerpt_image == (Image *) NULL)
4296         {
4297           status=MagickFalse;
4298           break;
4299         }
4300       filter_image=ResizeImage(excerpt_image,1,1,image->filter,exception);
4301       excerpt_image=DestroyImage(excerpt_image);
4302       if (filter_image == (Image *) NULL)
4303         break;
4304       filter_view=AcquireVirtualCacheView(filter_image,exception);
4305       p=GetCacheViewVirtualPixels(filter_view,0,0,1,1,exception);
4306       if (p == (const Quantum *) NULL)
4307         status=MagickFalse;
4308       else
4309         *pixel=(double) GetPixelChannel(image,channel,p);
4310       filter_view=DestroyCacheView(filter_view);
4311       filter_image=DestroyImage(filter_image);
4312       break;
4313     }
4314 #endif
4315     case IntegerInterpolatePixel:
4316     {
4317       p=GetCacheViewVirtualPixels(image_view,x_offset,y_offset,1,1,exception);
4318       if (p == (const Quantum *) NULL)
4319         {
4320           status=MagickFalse;
4321           break;
4322         }
4323       *pixel=(double) GetPixelChannel(image,channel,p);
4324       break;
4325     }
4326     case NearestInterpolatePixel:
4327     {
4328       x_offset=(ssize_t) floor(x+0.5);
4329       y_offset=(ssize_t) floor(y+0.5);
4330       p=GetCacheViewVirtualPixels(image_view,x_offset,y_offset,1,1,exception);
4331       if (p == (const Quantum *) NULL)
4332         {
4333           status=MagickFalse;
4334           break;
4335         }
4336       *pixel=(double) GetPixelChannel(image,channel,p);
4337       break;
4338     }
4339     case MeshInterpolatePixel:
4340     {
4341       PointInfo
4342         delta,
4343         luminance;
4344
4345       p=GetCacheViewVirtualPixels(image_view,x_offset,y_offset,2,2,exception);
4346       if (p == (const Quantum *) NULL)
4347         {
4348           status=MagickFalse;
4349           break;
4350         }
4351       if ((traits & BlendPixelTrait) == 0)
4352         for (i=0; i < 4; i++)
4353         {
4354           alpha[i]=1.0;
4355           pixels[i]=(double) p[i*GetPixelChannels(image)+channel];
4356         }
4357       else
4358         for (i=0; i < 4; i++)
4359         {
4360           alpha[i]=QuantumScale*GetPixelAlpha(image,p+i*
4361             GetPixelChannels(image));
4362           pixels[i]=alpha[i]*p[i*GetPixelChannels(image)+channel];
4363         }
4364       delta.x=x-x_offset;
4365       delta.y=y-y_offset;
4366       luminance.x=GetPixelLuminance(image,p)-(double)
4367         GetPixelLuminance(image,p+3*GetPixelChannels(image));
4368       luminance.y=GetPixelLuminance(image,p+GetPixelChannels(image))-(double)
4369         GetPixelLuminance(image,p+2*GetPixelChannels(image));
4370       if (fabs(luminance.x) < fabs(luminance.y))
4371         {
4372           /*
4373             Diagonal 0-3 NW-SE.
4374           */
4375           if (delta.x <= delta.y)
4376             {
4377               /*
4378                 Bottom-left triangle (pixel: 2, diagonal: 0-3).
4379               */
4380               delta.y=1.0-delta.y;
4381               gamma=MeshInterpolate(&delta,alpha[2],alpha[3],alpha[0]);
4382               gamma=MagickEpsilonReciprocal(gamma);
4383               *pixel=gamma*MeshInterpolate(&delta,pixels[2],pixels[3],
4384                 pixels[0]);
4385             }
4386           else
4387             {
4388               /*
4389                 Top-right triangle (pixel: 1, diagonal: 0-3).
4390               */
4391               delta.x=1.0-delta.x;
4392               gamma=MeshInterpolate(&delta,alpha[1],alpha[0],alpha[3]);
4393               gamma=MagickEpsilonReciprocal(gamma);
4394               *pixel=gamma*MeshInterpolate(&delta,pixels[1],pixels[0],
4395                 pixels[3]);
4396             }
4397         }
4398       else
4399         {
4400           /*
4401             Diagonal 1-2 NE-SW.
4402           */
4403           if (delta.x <= (1.0-delta.y))
4404             {
4405               /*
4406                 Top-left triangle (pixel: 0, diagonal: 1-2).
4407               */
4408               gamma=MeshInterpolate(&delta,alpha[0],alpha[1],alpha[2]);
4409               gamma=MagickEpsilonReciprocal(gamma);
4410               *pixel=gamma*MeshInterpolate(&delta,pixels[0],pixels[1],
4411                 pixels[2]);
4412             }
4413           else
4414             {
4415               /*
4416                 Bottom-right triangle (pixel: 3, diagonal: 1-2).
4417               */
4418               delta.x=1.0-delta.x;
4419               delta.y=1.0-delta.y;
4420               gamma=MeshInterpolate(&delta,alpha[3],alpha[2],alpha[1]);
4421               gamma=MagickEpsilonReciprocal(gamma);
4422               *pixel=gamma*MeshInterpolate(&delta,pixels[3],pixels[2],
4423                 pixels[1]);
4424             }
4425         }
4426       break;
4427     }
4428     case SplineInterpolatePixel:
4429     {
4430       double
4431         cx[4],
4432         cy[4];
4433
4434       p=GetCacheViewVirtualPixels(image_view,x_offset-1,y_offset-1,4,4,
4435         exception);
4436       if (p == (const Quantum *) NULL)
4437         {
4438           status=MagickFalse;
4439           break;
4440         }
4441       if ((traits & BlendPixelTrait) == 0)
4442         for (i=0; i < 16; i++)
4443         {
4444           alpha[i]=1.0;
4445           pixels[i]=(double) p[i*GetPixelChannels(image)+channel];
4446         }
4447       else
4448         for (i=0; i < 16; i++)
4449         {
4450           alpha[i]=QuantumScale*GetPixelAlpha(image,p+i*
4451             GetPixelChannels(image));
4452           pixels[i]=alpha[i]*p[i*GetPixelChannels(image)+channel];
4453         }
4454       SplineWeights((double) (x-x_offset),&cx);
4455       SplineWeights((double) (y-y_offset),&cy);
4456       gamma=(channel == AlphaPixelChannel ? (double) 1.0 :
4457         MagickEpsilonReciprocal(cy[0]*(cx[0]*alpha[0]+cx[1]*alpha[1]+cx[2]*
4458         alpha[2]+cx[3]*alpha[3])+cy[1]*(cx[0]*alpha[4]+cx[1]*alpha[5]+cx[2]*
4459         alpha[6]+cx[3]*alpha[7])+cy[2]*(cx[0]*alpha[8]+cx[1]*alpha[9]+cx[2]*
4460         alpha[10]+cx[3]*alpha[11])+cy[3]*(cx[0]*alpha[12]+cx[1]*alpha[13]+
4461         cx[2]*alpha[14]+cx[3]*alpha[15])));
4462       *pixel=gamma*(cy[0]*(cx[0]*pixels[0]+cx[1]*pixels[1]+cx[2]*pixels[2]+
4463         cx[3]*pixels[3])+cy[1]*(cx[0]*pixels[4]+cx[1]*pixels[5]+cx[2]*
4464         pixels[6]+cx[3]*pixels[7])+cy[2]*(cx[0]*pixels[8]+cx[1]*pixels[9]+
4465         cx[2]*pixels[10]+cx[3]*pixels[11])+cy[3]*(cx[0]*pixels[12]+cx[1]*
4466         pixels[13]+cx[2]*pixels[14]+cx[3]*pixels[15]));
4467       break;
4468     }
4469   }
4470   return(status);
4471 }
4472 \f
4473 /*
4474 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4475 %                                                                             %
4476 %                                                                             %
4477 %                                                                             %
4478 %   I n t e r p o l a t e P i x e l C h a n n e l s                           %
4479 %                                                                             %
4480 %                                                                             %
4481 %                                                                             %
4482 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4483 %
4484 %  InterpolatePixelChannels() applies a pixel interpolation method between a
4485 %  floating point coordinate and the pixels surrounding that coordinate.  No
4486 %  pixel area resampling, or scaling of the result is performed.
4487 %
4488 %  Interpolation is restricted to just the current channel setting of the
4489 %  destination image into which the color is to be stored
4490 %
4491 %  The format of the InterpolatePixelChannels method is:
4492 %
4493 %      MagickBooleanType InterpolatePixelChannels(const Image *source,
4494 %        const CacheView *source_view,const Image *destination,
4495 %        const PixelInterpolateMethod method,const double x,const double y,
4496 %        Quantum *pixel,ExceptionInfo *exception)
4497 %
4498 %  A description of each parameter follows:
4499 %
4500 %    o source: the source.
4501 %
4502 %    o source_view: the source view.
4503 %
4504 %    o destination: the destination image, for the interpolated color
4505 %
4506 %    o method: the pixel color interpolation method.
4507 %
4508 %    o x,y: A double representing the current (x,y) position of the pixel.
4509 %
4510 %    o pixel: return the interpolated pixel here.
4511 %
4512 %    o exception: return any errors or warnings in this structure.
4513 %
4514 */
4515 MagickExport MagickBooleanType InterpolatePixelChannels(const Image *source,
4516   const CacheView *source_view,const Image *destination,
4517   const PixelInterpolateMethod method,const double x,const double y,
4518   Quantum *pixel,ExceptionInfo *exception)
4519 {
4520   MagickBooleanType
4521     status;
4522
4523   double
4524     alpha[16],
4525     gamma,
4526     pixels[16];
4527
4528   PixelChannel
4529     channel;
4530
4531   PixelTrait
4532     destination_traits,
4533     traits;
4534
4535   register const Quantum
4536     *p;
4537
4538   register ssize_t
4539     i;
4540
4541   ssize_t
4542     x_offset,
4543     y_offset;
4544
4545   PixelInterpolateMethod
4546     interpolate;
4547
4548   assert(source != (Image *) NULL);
4549   assert(source != (Image *) NULL);
4550   assert(source->signature == MagickSignature);
4551   assert(source_view != (CacheView *) NULL);
4552   status=MagickTrue;
4553   x_offset=(ssize_t) floor(x);
4554   y_offset=(ssize_t) floor(y);
4555   interpolate = method;
4556   if ( interpolate == UndefinedInterpolatePixel )
4557     interpolate = source->interpolate;
4558   switch (interpolate)
4559   {
4560     case AverageInterpolatePixel:        /* nearest 4 neighbours */
4561     case Average9InterpolatePixel:       /* nearest 9 neighbours */
4562     case Average16InterpolatePixel:      /* nearest 16 neighbours */
4563     {
4564       size_t
4565         count=2; /* size of the area to average - default nearest 4 */
4566
4567       if (interpolate == Average9InterpolatePixel)
4568         {
4569           count=3;
4570           x_offset=(ssize_t) (floor(x+0.5)-1);
4571           y_offset=(ssize_t) (floor(y+0.5)-1);
4572         }
4573       else if (interpolate == Average16InterpolatePixel)
4574         {
4575           count=4;
4576           x_offset--;
4577           y_offset--;
4578         }
4579       p=GetCacheViewVirtualPixels(source_view,x_offset,y_offset,count,count,
4580         exception);
4581       if (p == (const Quantum *) NULL)
4582         {
4583           status=MagickFalse;
4584           break;
4585         }
4586       count*=count;   /* Number of pixels to Average */
4587       for (i=0; i < (ssize_t) GetPixelChannels(source); i++)
4588       {
4589         double
4590           sum;
4591
4592         register ssize_t
4593           j;
4594
4595         channel=GetPixelChannelChannel(source,i);
4596         traits=GetPixelChannelTraits(source,channel);
4597         destination_traits=GetPixelChannelTraits(destination,channel);
4598         if ((traits == UndefinedPixelTrait) ||
4599             (destination_traits == UndefinedPixelTrait))
4600           continue;
4601         for (j=0; j < (ssize_t) count; j++)
4602           pixels[j]=(double) p[j*GetPixelChannels(source)+i];
4603         sum=0.0;
4604         if ((traits & BlendPixelTrait) == 0)
4605           {
4606             for (j=0; j < (ssize_t) count; j++)
4607               sum+=pixels[j];
4608             sum/=count;
4609             SetPixelChannel(destination,channel,ClampToQuantum(sum),pixel);
4610             continue;
4611           }
4612         for (j=0; j < (ssize_t) count; j++)
4613         {
4614           alpha[j]=QuantumScale*GetPixelAlpha(source,p+j*
4615             GetPixelChannels(source));
4616           pixels[j]*=alpha[j];
4617           gamma=MagickEpsilonReciprocal(alpha[j]);
4618           sum+=gamma*pixels[j];
4619         }
4620         sum/=count;
4621         SetPixelChannel(destination,channel,ClampToQuantum(sum),pixel);
4622       }
4623       break;
4624     }
4625     case BilinearInterpolatePixel:
4626     default:
4627     {
4628       p=GetCacheViewVirtualPixels(source_view,x_offset,y_offset,2,2,exception);
4629       if (p == (const Quantum *) NULL)
4630         {
4631           status=MagickFalse;
4632           break;
4633         }
4634       for (i=0; i < (ssize_t) GetPixelChannels(source); i++)
4635       {
4636         PointInfo
4637           delta,
4638           epsilon;
4639
4640         channel=GetPixelChannelChannel(source,i);
4641         traits=GetPixelChannelTraits(source,channel);
4642         destination_traits=GetPixelChannelTraits(destination,channel);
4643         if ((traits == UndefinedPixelTrait) ||
4644             (destination_traits == UndefinedPixelTrait))
4645           continue;
4646         delta.x=x-x_offset;
4647         delta.y=y-y_offset;
4648         epsilon.x=1.0-delta.x;
4649         epsilon.y=1.0-delta.y;
4650         pixels[0]=(double) p[i];
4651         pixels[1]=(double) p[GetPixelChannels(source)+i];
4652         pixels[2]=(double) p[2*GetPixelChannels(source)+i];
4653         pixels[3]=(double) p[3*GetPixelChannels(source)+i];
4654         if ((traits & BlendPixelTrait) == 0)
4655           {
4656             gamma=((epsilon.y*(epsilon.x+delta.x)+delta.y*(epsilon.x+delta.x)));
4657             gamma=MagickEpsilonReciprocal(gamma);
4658             SetPixelChannel(destination,channel,ClampToQuantum(gamma*(epsilon.y*
4659               (epsilon.x*pixels[0]+delta.x*pixels[1])+delta.y*(epsilon.x*
4660               pixels[2]+delta.x*pixels[3]))),pixel);
4661             continue;
4662           }
4663         alpha[0]=QuantumScale*GetPixelAlpha(source,p);
4664         alpha[1]=QuantumScale*GetPixelAlpha(source,p+GetPixelChannels(source));
4665         alpha[2]=QuantumScale*GetPixelAlpha(source,p+2*
4666           GetPixelChannels(source));
4667         alpha[3]=QuantumScale*GetPixelAlpha(source,p+3*
4668           GetPixelChannels(source));
4669         pixels[0]*=alpha[0];
4670         pixels[1]*=alpha[1];
4671         pixels[2]*=alpha[2];
4672         pixels[3]*=alpha[3];
4673         gamma=((epsilon.y*(epsilon.x*alpha[0]+delta.x*alpha[1])+delta.y*
4674           (epsilon.x*alpha[2]+delta.x*alpha[3])));
4675         gamma=MagickEpsilonReciprocal(gamma);
4676         SetPixelChannel(destination,channel,ClampToQuantum(gamma*(epsilon.y*
4677           (epsilon.x*pixels[0]+delta.x*pixels[1])+delta.y*(epsilon.x*pixels[2]+
4678           delta.x*pixels[3]))),pixel);
4679       }
4680       break;
4681     }
4682     case BlendInterpolatePixel:
4683     {
4684       p=GetCacheViewVirtualPixels(source_view,x_offset,y_offset,2,2,exception);
4685       if (p == (const Quantum *) NULL)
4686         {
4687           status=MagickFalse;
4688           break;
4689         }
4690       for (i=0; i < (ssize_t) GetPixelChannels(source); i++)
4691       {
4692         register ssize_t
4693           j;
4694
4695         channel=GetPixelChannelChannel(source,i);
4696         traits=GetPixelChannelTraits(source,channel);
4697         destination_traits=GetPixelChannelTraits(destination,channel);
4698         if ((traits == UndefinedPixelTrait) ||
4699             (destination_traits == UndefinedPixelTrait))
4700           continue;
4701         if ((traits & BlendPixelTrait) == 0)
4702           for (j=0; j < 4; j++)
4703           {
4704             alpha[j]=1.0;
4705             pixels[j]=(MagickRealType) p[j*GetPixelChannels(source)+channel];
4706           }
4707         else
4708           for (j=0; j < 4; j++)
4709           {
4710             alpha[j]=QuantumScale*GetPixelAlpha(source,p+j*
4711               GetPixelChannels(source));
4712             pixels[j]=alpha[j]*p[j*GetPixelChannels(source)+channel];
4713           }
4714         gamma=1.0;    /* number of pixels blended together (its variable) */
4715         for (j=0; j <= 1L; j++) {
4716           if ( y-y_offset >= 0.75 ) { /* take right pixels */
4717             alpha[j]  = alpha[j+2];
4718             pixels[j] = pixels[j+2];
4719           }
4720           else if ( y-y_offset > 0.25 ) {
4721             gamma = 2.0;              /* blend both pixels in row */
4722             alpha[j]  += alpha[j+2];  /* add up alpha weights */
4723             pixels[j] += pixels[j+2];
4724           }
4725         }
4726         if ( x-x_offset >= 0.75 ) {   /* take bottom row blend */
4727           alpha[0]  = alpha[1];
4728           pixels[0] = pixels[1];
4729         }
4730         else if ( x-x_offset > 0.25 ) {
4731           gamma *= 2.0;               /* blend both rows */
4732           alpha[0]  += alpha[1];      /* add up alpha weights */
4733           pixels[0] += pixels[1];
4734         }
4735         if ((traits & BlendPixelTrait) == 0)
4736           gamma=MagickEpsilonReciprocal(alpha[0]); /* (color) 1/alpha_weights */
4737         else
4738           gamma=MagickEpsilonReciprocal(gamma); /* (alpha) 1/number_of_pixels */
4739         SetPixelChannel(destination,channel,ClampToQuantum(gamma*pixels[0]),
4740              pixel);
4741       }
4742       break;
4743     }
4744     case CatromInterpolatePixel:
4745     {
4746       double
4747         cx[4],
4748         cy[4];
4749
4750       p=GetCacheViewVirtualPixels(source_view,x_offset-1,y_offset-1,4,4,
4751         exception);
4752       if (p == (const Quantum *) NULL)
4753         {
4754           status=MagickFalse;
4755           break;
4756         }
4757       for (i=0; i < (ssize_t) GetPixelChannels(source); i++)
4758       {
4759         register ssize_t
4760           j;
4761
4762         channel=GetPixelChannelChannel(source,i);
4763         traits=GetPixelChannelTraits(source,channel);
4764         destination_traits=GetPixelChannelTraits(destination,channel);
4765         if ((traits == UndefinedPixelTrait) ||
4766             (destination_traits == UndefinedPixelTrait))
4767           continue;
4768         if ((traits & BlendPixelTrait) == 0)
4769           for (j=0; j < 16; j++)
4770           {
4771             alpha[j]=1.0;
4772             pixels[j]=(double) p[j*GetPixelChannels(source)+i];
4773           }
4774         else
4775           for (j=0; j < 16; j++)
4776           {
4777             alpha[j]=QuantumScale*GetPixelAlpha(source,p+j*
4778               GetPixelChannels(source));
4779             pixels[j]=alpha[j]*p[j*GetPixelChannels(source)+i];
4780           }
4781         CatromWeights((double) (x-x_offset),&cx);
4782         CatromWeights((double) (y-y_offset),&cy);
4783         gamma=((traits & BlendPixelTrait) ? (double) (1.0) :
4784           MagickEpsilonReciprocal(cy[0]*(cx[0]*alpha[0]+cx[1]*alpha[1]+cx[2]*
4785           alpha[2]+cx[3]*alpha[3])+cy[1]*(cx[0]*alpha[4]+cx[1]*alpha[5]+cx[2]*
4786           alpha[6]+cx[3]*alpha[7])+cy[2]*(cx[0]*alpha[8]+cx[1]*alpha[9]+cx[2]*
4787           alpha[10]+cx[3]*alpha[11])+cy[3]*(cx[0]*alpha[12]+cx[1]*alpha[13]+
4788           cx[2]*alpha[14]+cx[3]*alpha[15])));
4789         SetPixelChannel(destination,channel,ClampToQuantum(gamma*(cy[0]*(cx[0]*
4790           pixels[0]+cx[1]*pixels[1]+cx[2]*pixels[2]+cx[3]*pixels[3])+cy[1]*
4791           (cx[0]*pixels[4]+cx[1]*pixels[5]+cx[2]*pixels[6]+cx[3]*pixels[7])+
4792           cy[2]*(cx[0]*pixels[8]+cx[1]*pixels[9]+cx[2]*pixels[10]+cx[3]*
4793           pixels[11])+cy[3]*(cx[0]*pixels[12]+cx[1]*pixels[13]+cx[2]*
4794           pixels[14]+cx[3]*pixels[15]))),pixel);
4795       }
4796       break;
4797     }
4798 #if 0
4799     /* deprecated useless and very slow interpolator */
4800     case FilterInterpolatePixel:
4801     {
4802       for (i=0; i < (ssize_t) GetPixelChannels(source); i++)
4803       {
4804         CacheView
4805           *filter_view;
4806
4807         Image
4808           *excerpt_source,
4809           *filter_source;
4810
4811         RectangleInfo
4812           geometry;
4813
4814         channel=GetPixelChannelChannel(source,i);
4815         traits=GetPixelChannelTraits(source,channel);
4816         destination_traits=GetPixelChannelTraits(destination,channel);
4817         if ((traits == UndefinedPixelTrait) ||
4818             (destination_traits == UndefinedPixelTrait))
4819           continue;
4820         geometry.width=4L;
4821         geometry.height=4L;
4822         geometry.x=x_offset-1;
4823         geometry.y=y_offset-1;
4824         excerpt_source=ExcerptImage(source,&geometry,exception);
4825         if (excerpt_source == (Image *) NULL)
4826           {
4827             status=MagickFalse;
4828             continue;
4829           }
4830         filter_source=ResizeImage(excerpt_source,1,1,source->filter,exception);
4831         excerpt_source=DestroyImage(excerpt_source);
4832         if (filter_source == (Image *) NULL)
4833           continue;
4834         filter_view=AcquireVirtualCacheView(filter_source,exception);
4835         p=GetCacheViewVirtualPixels(filter_view,0,0,1,1,exception);
4836         if (p == (const Quantum *) NULL)
4837           status=MagickFalse;
4838         else
4839           {
4840             SetPixelChannel(destination,channel,p[i],pixel);
4841           }
4842         filter_view=DestroyCacheView(filter_view);
4843         filter_source=DestroyImage(filter_source);
4844       }
4845       break;
4846     }
4847 #endif
4848     case IntegerInterpolatePixel:
4849     {
4850       p=GetCacheViewVirtualPixels(source_view,x_offset,y_offset,1,1,exception);
4851       if (p == (const Quantum *) NULL)
4852         {
4853           status=MagickFalse;
4854           break;
4855         }
4856       for (i=0; i < (ssize_t) GetPixelChannels(source); i++)
4857       {
4858         channel=GetPixelChannelChannel(source,i);
4859         traits=GetPixelChannelTraits(source,channel);
4860         destination_traits=GetPixelChannelTraits(destination,channel);
4861         if ((traits == UndefinedPixelTrait) ||
4862             (destination_traits == UndefinedPixelTrait))
4863           continue;
4864         SetPixelChannel(destination,channel,p[i],pixel);
4865       }
4866       break;
4867     }
4868     case NearestInterpolatePixel:
4869     {
4870       x_offset=(ssize_t) floor(x+0.5);
4871       y_offset=(ssize_t) floor(y+0.5);
4872       p=GetCacheViewVirtualPixels(source_view,x_offset,y_offset,1,1,exception);
4873       if (p == (const Quantum *) NULL)
4874         {
4875           status=MagickFalse;
4876           break;
4877         }
4878       for (i=0; i < (ssize_t) GetPixelChannels(source); i++)
4879       {
4880         channel=GetPixelChannelChannel(source,i);
4881         traits=GetPixelChannelTraits(source,channel);
4882         destination_traits=GetPixelChannelTraits(destination,channel);
4883         if ((traits == UndefinedPixelTrait) ||
4884             (destination_traits == UndefinedPixelTrait))
4885           continue;
4886         SetPixelChannel(destination,channel,p[i],pixel);
4887       }
4888       break;
4889     }
4890     case MeshInterpolatePixel:
4891     {
4892       p=GetCacheViewVirtualPixels(source_view,x_offset,y_offset,2,2,exception);
4893       if (p == (const Quantum *) NULL)
4894         {
4895           status=MagickFalse;
4896           break;
4897         }
4898       for (i=0; i < (ssize_t) GetPixelChannels(source); i++)
4899       {
4900         PointInfo
4901           delta,
4902           luminance;
4903
4904         channel=GetPixelChannelChannel(source,i);
4905         traits=GetPixelChannelTraits(source,channel);
4906         destination_traits=GetPixelChannelTraits(destination,channel);
4907         if ((traits == UndefinedPixelTrait) ||
4908             (destination_traits == UndefinedPixelTrait))
4909           continue;
4910         pixels[0]=(double) p[i];
4911         pixels[1]=(double) p[GetPixelChannels(source)+i];
4912         pixels[2]=(double) p[2*GetPixelChannels(source)+i];
4913         pixels[3]=(double) p[3*GetPixelChannels(source)+i];
4914         if ((traits & BlendPixelTrait) == 0)
4915           {
4916             alpha[0]=1.0;
4917             alpha[1]=1.0;
4918             alpha[2]=1.0;
4919             alpha[3]=1.0;
4920           }
4921         else
4922           {
4923             alpha[0]=QuantumScale*GetPixelAlpha(source,p);
4924             alpha[1]=QuantumScale*GetPixelAlpha(source,p+
4925               GetPixelChannels(source));
4926             alpha[2]=QuantumScale*GetPixelAlpha(source,p+2*
4927               GetPixelChannels(source));
4928             alpha[3]=QuantumScale*GetPixelAlpha(source,p+3*
4929               GetPixelChannels(source));
4930           }
4931         delta.x=x-x_offset;
4932         delta.y=y-y_offset;
4933         luminance.x=fabs((double)(
4934               GetPixelLuminance(source,p)
4935                -GetPixelLuminance(source,p+3*GetPixelChannels(source))));
4936         luminance.y=fabs((double)(
4937               GetPixelLuminance(source,p+GetPixelChannels(source))
4938                -GetPixelLuminance(source,p+2*GetPixelChannels(source))));
4939         if (luminance.x < luminance.y)
4940           {
4941             /*
4942               Diagonal 0-3 NW-SE.
4943             */
4944             if (delta.x <= delta.y)
4945               {
4946                 /*
4947                   Bottom-left triangle (pixel: 2, diagonal: 0-3).
4948                 */
4949                 delta.y=1.0-delta.y;
4950                 gamma=MeshInterpolate(&delta,alpha[2],alpha[3],alpha[0]);
4951                 gamma=MagickEpsilonReciprocal(gamma);
4952                 SetPixelChannel(destination,channel,ClampToQuantum(gamma*
4953                   MeshInterpolate(&delta,pixels[2],pixels[3],pixels[0])),pixel);
4954               }
4955             else
4956               {
4957                 /*
4958                   Top-right triangle (pixel: 1, diagonal: 0-3).
4959                 */
4960                 delta.x=1.0-delta.x;
4961                 gamma=MeshInterpolate(&delta,alpha[1],alpha[0],alpha[3]);
4962                 gamma=MagickEpsilonReciprocal(gamma);
4963                 SetPixelChannel(destination,channel,ClampToQuantum(gamma*
4964                   MeshInterpolate(&delta,pixels[1],pixels[0],pixels[3])),pixel);
4965               }
4966           }
4967         else
4968           {
4969             /*
4970               Diagonal 1-2 NE-SW.
4971             */
4972             if (delta.x <= (1.0-delta.y))
4973               {
4974                 /*
4975                   Top-left triangle (pixel: 0, diagonal: 1-2).
4976                 */
4977                 gamma=MeshInterpolate(&delta,alpha[0],alpha[1],alpha[2]);
4978                 gamma=MagickEpsilonReciprocal(gamma);
4979                 SetPixelChannel(destination,channel,ClampToQuantum(gamma*
4980                   MeshInterpolate(&delta,pixels[0],pixels[1],pixels[2])),pixel);
4981               }
4982             else
4983               {
4984                 /*
4985                   Bottom-right triangle (pixel: 3, diagonal: 1-2).
4986                 */
4987                 delta.x=1.0-delta.x;
4988                 delta.y=1.0-delta.y;
4989                 gamma=MeshInterpolate(&delta,alpha[3],alpha[2],alpha[1]);
4990                 gamma=MagickEpsilonReciprocal(gamma);
4991                 SetPixelChannel(destination,channel,ClampToQuantum(gamma*
4992                   MeshInterpolate(&delta,pixels[3],pixels[2],pixels[1])),pixel);
4993               }
4994           }
4995       }
4996       break;
4997     }
4998     case SplineInterpolatePixel:
4999     {
5000       double
5001         cx[4],
5002         cy[4];
5003
5004       p=GetCacheViewVirtualPixels(source_view,x_offset-1,y_offset-1,4,4,
5005         exception);
5006       if (p == (const Quantum *) NULL)
5007         {
5008           status=MagickFalse;
5009           break;
5010         }
5011       for (i=0; i < (ssize_t) GetPixelChannels(source); i++)
5012       {
5013         register ssize_t
5014           j;
5015
5016         channel=GetPixelChannelChannel(source,i);
5017         traits=GetPixelChannelTraits(source,channel);
5018         destination_traits=GetPixelChannelTraits(destination,channel);
5019         if ((traits == UndefinedPixelTrait) ||
5020             (destination_traits == UndefinedPixelTrait))
5021           continue;
5022         if ((traits & BlendPixelTrait) == 0)
5023           for (j=0; j < 16; j++)
5024           {
5025             alpha[j]=1.0;
5026             pixels[j]=(double) p[j*GetPixelChannels(source)+i];
5027           }
5028         else
5029           for (j=0; j < 16; j++)
5030           {
5031             alpha[j]=QuantumScale*GetPixelAlpha(source,p+j*
5032               GetPixelChannels(source));
5033             pixels[j]=alpha[j]*p[j*GetPixelChannels(source)+i];
5034           }
5035         SplineWeights((double) (x-x_offset),&cx);
5036         SplineWeights((double) (y-y_offset),&cy);
5037         gamma=((traits & BlendPixelTrait) ? (double) (1.0) :
5038           MagickEpsilonReciprocal(cy[0]*(cx[0]*alpha[0]+cx[1]*alpha[1]+cx[2]*
5039           alpha[2]+cx[3]*alpha[3])+cy[1]*(cx[0]*alpha[4]+cx[1]*alpha[5]+cx[2]*
5040           alpha[6]+cx[3]*alpha[7])+cy[2]*(cx[0]*alpha[8]+cx[1]*alpha[9]+cx[2]*
5041           alpha[10]+cx[3]*alpha[11])+cy[3]*(cx[0]*alpha[12]+cx[1]*alpha[13]+
5042           cx[2]*alpha[14]+cx[3]*alpha[15])));
5043         SetPixelChannel(destination,channel,ClampToQuantum(gamma*(cy[0]*(cx[0]*
5044           pixels[0]+cx[1]*pixels[1]+cx[2]*pixels[2]+cx[3]*pixels[3])+cy[1]*
5045           (cx[0]*pixels[4]+cx[1]*pixels[5]+cx[2]*pixels[6]+cx[3]*pixels[7])+
5046           cy[2]*(cx[0]*pixels[8]+cx[1]*pixels[9]+cx[2]*pixels[10]+cx[3]*
5047           pixels[11])+cy[3]*(cx[0]*pixels[12]+cx[1]*pixels[13]+cx[2]*
5048           pixels[14]+cx[3]*pixels[15]))),pixel);
5049       }
5050       break;
5051     }
5052   }
5053   return(status);
5054 }
5055 \f
5056 /*
5057 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5058 %                                                                             %
5059 %                                                                             %
5060 %                                                                             %
5061 %   I n t e r p o l a t e P i x e l I n f o                                   %
5062 %                                                                             %
5063 %                                                                             %
5064 %                                                                             %
5065 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5066 %
5067 %  InterpolatePixelInfo() applies a pixel interpolation method between a
5068 %  floating point coordinate and the pixels surrounding that coordinate.  No
5069 %  pixel area resampling, or scaling of the result is performed.
5070 %
5071 %  Interpolation is restricted to just RGBKA channels.
5072 %
5073 %  The format of the InterpolatePixelInfo method is:
5074 %
5075 %      MagickBooleanType InterpolatePixelInfo(const Image *image,
5076 %        const CacheView *image_view,const PixelInterpolateMethod method,
5077 %        const double x,const double y,PixelInfo *pixel,
5078 %        ExceptionInfo *exception)
5079 %
5080 %  A description of each parameter follows:
5081 %
5082 %    o image: the image.
5083 %
5084 %    o image_view: the image view.
5085 %
5086 %    o method: the pixel color interpolation method.
5087 %
5088 %    o x,y: A double representing the current (x,y) position of the pixel.
5089 %
5090 %    o pixel: return the interpolated pixel here.
5091 %
5092 %    o exception: return any errors or warnings in this structure.
5093 %
5094 */
5095
5096 static inline void AlphaBlendPixelInfo(const Image *image,
5097   const Quantum *pixel,PixelInfo *pixel_info,double *alpha)
5098 {
5099   if (image->alpha_trait != BlendPixelTrait)
5100     {
5101       *alpha=1.0;
5102       pixel_info->red=(double) GetPixelRed(image,pixel);
5103       pixel_info->green=(double) GetPixelGreen(image,pixel);
5104       pixel_info->blue=(double) GetPixelBlue(image,pixel);
5105       pixel_info->black=0.0;
5106       if (image->colorspace == CMYKColorspace)
5107         pixel_info->black=(double) GetPixelBlack(image,pixel);
5108       pixel_info->alpha=(double) GetPixelAlpha(image,pixel);
5109       return;
5110     }
5111   *alpha=QuantumScale*GetPixelAlpha(image,pixel);
5112   pixel_info->red=(*alpha*GetPixelRed(image,pixel));
5113   pixel_info->green=(*alpha*GetPixelGreen(image,pixel));
5114   pixel_info->blue=(*alpha*GetPixelBlue(image,pixel));
5115   pixel_info->black=0.0;
5116   if (image->colorspace == CMYKColorspace)
5117     pixel_info->black=(*alpha*GetPixelBlack(image,pixel));
5118   pixel_info->alpha=(double) GetPixelAlpha(image,pixel);
5119 }
5120
5121 MagickExport MagickBooleanType InterpolatePixelInfo(const Image *image,
5122   const CacheView *image_view,const PixelInterpolateMethod method,
5123   const double x,const double y,PixelInfo *pixel,ExceptionInfo *exception)
5124 {
5125   MagickBooleanType
5126     status;
5127
5128   double
5129     alpha[16],
5130     gamma;
5131
5132   PixelInfo
5133     pixels[16];
5134
5135   register const Quantum
5136     *p;
5137
5138   register ssize_t
5139     i;
5140
5141   ssize_t
5142     x_offset,
5143     y_offset;
5144
5145   PixelInterpolateMethod
5146     interpolate;
5147
5148   assert(image != (Image *) NULL);
5149   assert(image->signature == MagickSignature);
5150   assert(image_view != (CacheView *) NULL);
5151   status=MagickTrue;
5152   x_offset=(ssize_t) floor(x);
5153   y_offset=(ssize_t) floor(y);
5154   interpolate = method;
5155   if ( interpolate == UndefinedInterpolatePixel )
5156     interpolate = image->interpolate;
5157   switch (interpolate)
5158   {
5159     case AverageInterpolatePixel:        /* nearest 4 neighbours */
5160     case Average9InterpolatePixel:       /* nearest 9 neighbours */
5161     case Average16InterpolatePixel:      /* nearest 16 neighbours */
5162     {
5163       size_t
5164         count=2; /* size of the area to average - default nearest 4 */
5165
5166       if (interpolate == Average9InterpolatePixel)
5167         {
5168           count=3;
5169           x_offset=(ssize_t) (floor(x+0.5)-1);
5170           y_offset=(ssize_t) (floor(y+0.5)-1);
5171         }
5172       else if (interpolate == Average16InterpolatePixel)
5173         {
5174           count=4;
5175           x_offset--;
5176           y_offset--;
5177         }
5178       p=GetCacheViewVirtualPixels(image_view,x_offset,y_offset,count,count,
5179         exception);
5180       if (p == (const Quantum *) NULL)
5181         {
5182           status=MagickFalse;
5183           break;
5184         }
5185       pixel->red=0.0;
5186       pixel->green=0.0;
5187       pixel->blue=0.0;
5188       pixel->black=0.0;
5189       pixel->alpha=0.0;
5190       count*=count;         /* number of pixels - square of size */
5191       for (i=0; i < (ssize_t) count; i++)
5192       {
5193         AlphaBlendPixelInfo(image,p,pixels,alpha);
5194         gamma=MagickEpsilonReciprocal(alpha[0]);
5195         pixel->red   += gamma*pixels[0].red;
5196         pixel->green += gamma*pixels[0].green;
5197         pixel->blue  += gamma*pixels[0].blue;
5198         pixel->black += gamma*pixels[0].black;
5199         pixel->alpha +=       pixels[0].alpha;
5200         p += GetPixelChannels(image);
5201       }
5202       gamma=1.0/count;   /* average weighting of each pixel in area */
5203       pixel->red   *= gamma;
5204       pixel->green *= gamma;
5205       pixel->blue  *= gamma;
5206       pixel->black *= gamma;
5207       pixel->alpha *= gamma;
5208       break;
5209     }
5210     case BackgroundInterpolatePixel:
5211     {
5212       *pixel = image->background_color;  /* Copy PixelInfo Structure  */
5213       break;
5214     }
5215     case BilinearInterpolatePixel:
5216     default:
5217     {
5218       PointInfo
5219         delta,
5220         epsilon;
5221
5222       p=GetCacheViewVirtualPixels(image_view,x_offset,y_offset,2,2,exception);
5223       if (p == (const Quantum *) NULL)
5224         {
5225           status=MagickFalse;
5226           break;
5227         }
5228       for (i=0; i < 4L; i++)
5229         AlphaBlendPixelInfo(image,p+i*GetPixelChannels(image),pixels+i,alpha+i);
5230       delta.x=x-x_offset;
5231       delta.y=y-y_offset;
5232       epsilon.x=1.0-delta.x;
5233       epsilon.y=1.0-delta.y;
5234       gamma=((epsilon.y*(epsilon.x*alpha[0]+delta.x*alpha[1])+delta.y*
5235         (epsilon.x*alpha[2]+delta.x*alpha[3])));
5236       gamma=MagickEpsilonReciprocal(gamma);
5237       pixel->red=gamma*(epsilon.y*(epsilon.x*pixels[0].red+delta.x*
5238         pixels[1].red)+delta.y*(epsilon.x*pixels[2].red+delta.x*pixels[3].red));
5239       pixel->green=gamma*(epsilon.y*(epsilon.x*pixels[0].green+delta.x*
5240         pixels[1].green)+delta.y*(epsilon.x*pixels[2].green+delta.x*
5241         pixels[3].green));
5242       pixel->blue=gamma*(epsilon.y*(epsilon.x*pixels[0].blue+delta.x*
5243         pixels[1].blue)+delta.y*(epsilon.x*pixels[2].blue+delta.x*
5244         pixels[3].blue));
5245       if (image->colorspace == CMYKColorspace)
5246         pixel->black=gamma*(epsilon.y*(epsilon.x*pixels[0].black+delta.x*
5247           pixels[1].black)+delta.y*(epsilon.x*pixels[2].black+delta.x*
5248           pixels[3].black));
5249       gamma=((epsilon.y*(epsilon.x+delta.x)+delta.y*(epsilon.x+delta.x)));
5250       gamma=MagickEpsilonReciprocal(gamma);
5251       pixel->alpha=(epsilon.y*(epsilon.x*pixels[0].alpha+delta.x*
5252         pixels[1].alpha)+delta.y*(epsilon.x*pixels[2].alpha+delta.x*
5253         pixels[3].alpha));
5254       break;
5255     }
5256     case BlendInterpolatePixel:
5257     {
5258       p=GetCacheViewVirtualPixels(image_view,x_offset,y_offset,2,2,exception);
5259       if (p == (const Quantum *) NULL)
5260         {
5261           status=MagickFalse;
5262           break;
5263         }
5264       for (i=0; i < 4L; i++)
5265         AlphaBlendPixelInfo(image,p+i*GetPixelChannels(image),pixels+i,alpha+i);
5266       gamma=1.0;    /* number of pixels blended together (its variable) */
5267       for (i=0; i <= 1L; i++) {
5268         if ( y-y_offset >= 0.75 ) {       /* take right pixels */
5269           alpha[i]  = alpha[i+2];
5270           pixels[i] = pixels[i+2];
5271         }
5272         else if ( y-y_offset > 0.25 ) {
5273           gamma = 2.0;                    /* blend both pixels in row */
5274           alpha[i]        += alpha[i+2];  /* add up alpha weights */
5275           pixels[i].red   += pixels[i+2].red;
5276           pixels[i].green += pixels[i+2].green;
5277           pixels[i].blue  += pixels[i+2].blue;
5278           pixels[i].black += pixels[i+2].black;
5279           pixels[i].alpha += pixels[i+2].alpha;
5280         }
5281       }
5282       if ( x-x_offset >= 0.75 ) {
5283         alpha[0]  = alpha[1];
5284         pixels[0] = pixels[1];
5285       }
5286       else if ( x-x_offset > 0.25 ) {
5287         gamma *= 2.0;                     /* blend both rows */
5288         alpha[0]        += alpha[1];      /* add up alpha weights */
5289         pixels[0].red   += pixels[1].red;
5290         pixels[0].green += pixels[1].green;
5291         pixels[0].blue  += pixels[1].blue;
5292         pixels[0].black += pixels[1].black;
5293         pixels[0].alpha += pixels[1].alpha;
5294       }
5295       gamma = 1.0/gamma;
5296       alpha[0]=MagickEpsilonReciprocal(alpha[0]);
5297       pixel->red   = alpha[0]*pixels[0].red;
5298       pixel->green = alpha[0]*pixels[0].green; /* divide by sum of alpha */
5299       pixel->blue  = alpha[0]*pixels[0].blue;
5300       pixel->black = alpha[0]*pixels[0].black;
5301       pixel->alpha =    gamma*pixels[0].alpha; /* divide by number of pixels */
5302       break;
5303     }
5304     case CatromInterpolatePixel:
5305     {
5306       double
5307         cx[4],
5308         cy[4];
5309
5310       p=GetCacheViewVirtualPixels(image_view,x_offset-1,y_offset-1,4,4,
5311         exception);
5312       if (p == (const Quantum *) NULL)
5313         {
5314           status=MagickFalse;
5315           break;
5316         }
5317       for (i=0; i < 16L; i++)
5318         AlphaBlendPixelInfo(image,p+i*GetPixelChannels(image),pixels+i,alpha+i);
5319       CatromWeights((double) (x-x_offset),&cx);
5320       CatromWeights((double) (y-y_offset),&cy);
5321       pixel->red=(cy[0]*(cx[0]*pixels[0].red+cx[1]*
5322         pixels[1].red+cx[2]*pixels[2].red+cx[3]*
5323         pixels[3].red)+cy[1]*(cx[0]*pixels[4].red+cx[1]*
5324         pixels[5].red+cx[2]*pixels[6].red+cx[3]*
5325         pixels[7].red)+cy[2]*(cx[0]*pixels[8].red+cx[1]*
5326         pixels[9].red+cx[2]*pixels[10].red+cx[3]*
5327         pixels[11].red)+cy[3]*(cx[0]*pixels[12].red+cx[1]*
5328         pixels[13].red+cx[2]*pixels[14].red+cx[3]*pixels[15].red));
5329       pixel->green=(cy[0]*(cx[0]*pixels[0].green+cx[1]*
5330         pixels[1].green+cx[2]*pixels[2].green+cx[3]*
5331         pixels[3].green)+cy[1]*(cx[0]*pixels[4].green+cx[1]*
5332         pixels[5].green+cx[2]*pixels[6].green+cx[3]*
5333         pixels[7].green)+cy[2]*(cx[0]*pixels[8].green+cx[1]*
5334         pixels[9].green+cx[2]*pixels[10].green+cx[3]*
5335         pixels[11].green)+cy[3]*(cx[0]*pixels[12].green+cx[1]*
5336         pixels[13].green+cx[2]*pixels[14].green+cx[3]*pixels[15].green));
5337       pixel->blue=(cy[0]*(cx[0]*pixels[0].blue+cx[1]*
5338         pixels[1].blue+cx[2]*pixels[2].blue+cx[3]*
5339         pixels[3].blue)+cy[1]*(cx[0]*pixels[4].blue+cx[1]*
5340         pixels[5].blue+cx[2]*pixels[6].blue+cx[3]*
5341         pixels[7].blue)+cy[2]*(cx[0]*pixels[8].blue+cx[1]*
5342         pixels[9].blue+cx[2]*pixels[10].blue+cx[3]*
5343         pixels[11].blue)+cy[3]*(cx[0]*pixels[12].blue+cx[1]*
5344         pixels[13].blue+cx[2]*pixels[14].blue+cx[3]*pixels[15].blue));
5345       if (image->colorspace == CMYKColorspace)
5346         pixel->black=(cy[0]*(cx[0]*pixels[0].black+cx[1]*
5347           pixels[1].black+cx[2]*pixels[2].black+cx[3]*
5348           pixels[3].black)+cy[1]*(cx[0]*pixels[4].black+cx[1]*
5349           pixels[5].black+cx[2]*pixels[6].black+cx[3]*
5350           pixels[7].black)+cy[2]*(cx[0]*pixels[8].black+cx[1]*
5351           pixels[9].black+cx[2]*pixels[10].black+cx[3]*
5352           pixels[11].black)+cy[3]*(cx[0]*pixels[12].black+cx[1]*
5353           pixels[13].black+cx[2]*pixels[14].black+cx[3]*pixels[15].black));
5354       pixel->alpha=(cy[0]*(cx[0]*pixels[0].alpha+cx[1]*
5355         pixels[1].alpha+cx[2]*pixels[2].alpha+cx[3]*
5356         pixels[3].alpha)+cy[1]*(cx[0]*pixels[4].alpha+cx[1]*
5357         pixels[5].alpha+cx[2]*pixels[6].alpha+cx[3]*
5358         pixels[7].alpha)+cy[2]*(cx[0]*pixels[8].alpha+cx[1]*
5359         pixels[9].alpha+cx[2]*pixels[10].alpha+cx[3]*
5360         pixels[11].alpha)+cy[3]*(cx[0]*pixels[12].alpha+cx[1]*
5361         pixels[13].alpha+cx[2]*pixels[14].alpha+cx[3]*pixels[15].alpha));
5362       break;
5363     }
5364 #if 0
5365     /* deprecated useless and very slow interpolator */
5366     case FilterInterpolatePixel:
5367     {
5368       CacheView
5369         *filter_view;
5370
5371       Image
5372         *excerpt_image,
5373         *filter_image;
5374
5375       RectangleInfo
5376         geometry;
5377
5378       geometry.width=4L;
5379       geometry.height=4L;
5380       geometry.x=x_offset-1;
5381       geometry.y=y_offset-1;
5382       excerpt_image=ExcerptImage(image,&geometry,exception);
5383       if (excerpt_image == (Image *) NULL)
5384         {
5385           status=MagickFalse;
5386           break;
5387         }
5388       filter_image=ResizeImage(excerpt_image,1,1,image->filter,exception);
5389       excerpt_image=DestroyImage(excerpt_image);
5390       if (filter_image == (Image *) NULL)
5391         break;
5392       filter_view=AcquireVirtualCacheView(filter_image,exception);
5393       p=GetCacheViewVirtualPixels(filter_view,0,0,1,1,exception);
5394       if (p != (const Quantum *) NULL)
5395         GetPixelInfoPixel(image,p,pixel);
5396       filter_view=DestroyCacheView(filter_view);
5397       filter_image=DestroyImage(filter_image);
5398       break;
5399     }
5400 #endif
5401     case IntegerInterpolatePixel:
5402     {
5403       p=GetCacheViewVirtualPixels(image_view,x_offset,y_offset,1,1,exception);
5404       if (p == (const Quantum *) NULL)
5405         {
5406           status=MagickFalse;
5407           break;
5408         }
5409       GetPixelInfoPixel(image,p,pixel);
5410       break;
5411     }
5412     case MeshInterpolatePixel:
5413     {
5414       PointInfo
5415         delta,
5416         luminance;
5417
5418       p=GetCacheViewVirtualPixels(image_view,x_offset,y_offset,2,2,exception);
5419       if (p == (const Quantum *) NULL)
5420         {
5421           status=MagickFalse;
5422           break;
5423         }
5424       delta.x=x-x_offset;
5425       delta.y=y-y_offset;
5426       luminance.x=GetPixelLuminance(image,p)-(double)
5427         GetPixelLuminance(image,p+3*GetPixelChannels(image));
5428       luminance.y=GetPixelLuminance(image,p+GetPixelChannels(image))-(double)
5429         GetPixelLuminance(image,p+2*GetPixelChannels(image));
5430       AlphaBlendPixelInfo(image,p,pixels+0,alpha+0);
5431       AlphaBlendPixelInfo(image,p+GetPixelChannels(image),pixels+1,alpha+1);
5432       AlphaBlendPixelInfo(image,p+2*GetPixelChannels(image),pixels+2,alpha+2);
5433       AlphaBlendPixelInfo(image,p+3*GetPixelChannels(image),pixels+3,alpha+3);
5434       if (fabs(luminance.x) < fabs(luminance.y))
5435         {
5436           /*
5437             Diagonal 0-3 NW-SE.
5438           */
5439           if (delta.x <= delta.y)
5440             {
5441               /*
5442                 Bottom-left triangle (pixel: 2, diagonal: 0-3).
5443               */
5444               delta.y=1.0-delta.y;
5445               gamma=MeshInterpolate(&delta,alpha[2],alpha[3],alpha[0]);
5446               gamma=MagickEpsilonReciprocal(gamma);
5447               pixel->red=gamma*MeshInterpolate(&delta,pixels[2].red,
5448                 pixels[3].red,pixels[0].red);
5449               pixel->green=gamma*MeshInterpolate(&delta,pixels[2].green,
5450                 pixels[3].green,pixels[0].green);
5451               pixel->blue=gamma*MeshInterpolate(&delta,pixels[2].blue,
5452                 pixels[3].blue,pixels[0].blue);
5453               if (image->colorspace == CMYKColorspace)
5454                 pixel->black=gamma*MeshInterpolate(&delta,pixels[2].black,
5455                   pixels[3].black,pixels[0].black);
5456               gamma=MeshInterpolate(&delta,1.0,1.0,1.0);
5457               pixel->alpha=gamma*MeshInterpolate(&delta,pixels[2].alpha,
5458                 pixels[3].alpha,pixels[0].alpha);
5459             }
5460           else
5461             {
5462               /*
5463                 Top-right triangle (pixel:1 , diagonal: 0-3).
5464               */
5465               delta.x=1.0-delta.x;
5466               gamma=MeshInterpolate(&delta,alpha[1],alpha[0],alpha[3]);
5467               gamma=MagickEpsilonReciprocal(gamma);
5468               pixel->red=gamma*MeshInterpolate(&delta,pixels[1].red,
5469                 pixels[0].red,pixels[3].red);
5470               pixel->green=gamma*MeshInterpolate(&delta,pixels[1].green,
5471                 pixels[0].green,pixels[3].green);
5472               pixel->blue=gamma*MeshInterpolate(&delta,pixels[1].blue,
5473                 pixels[0].blue,pixels[3].blue);
5474               if (image->colorspace == CMYKColorspace)
5475                 pixel->black=gamma*MeshInterpolate(&delta,pixels[1].black,
5476                   pixels[0].black,pixels[3].black);
5477               gamma=MeshInterpolate(&delta,1.0,1.0,1.0);
5478               pixel->alpha=gamma*MeshInterpolate(&delta,pixels[1].alpha,
5479                 pixels[0].alpha,pixels[3].alpha);
5480             }
5481         }
5482       else
5483         {
5484           /*
5485             Diagonal 1-2 NE-SW.
5486           */
5487           if (delta.x <= (1.0-delta.y))
5488             {
5489               /*
5490                 Top-left triangle (pixel: 0, diagonal: 1-2).
5491               */
5492               gamma=MeshInterpolate(&delta,alpha[0],alpha[1],alpha[2]);
5493               gamma=MagickEpsilonReciprocal(gamma);
5494               pixel->red=gamma*MeshInterpolate(&delta,pixels[0].red,
5495                 pixels[1].red,pixels[2].red);
5496               pixel->green=gamma*MeshInterpolate(&delta,pixels[0].green,
5497                 pixels[1].green,pixels[2].green);
5498               pixel->blue=gamma*MeshInterpolate(&delta,pixels[0].blue,
5499                 pixels[1].blue,pixels[2].blue);
5500               if (image->colorspace == CMYKColorspace)
5501                 pixel->black=gamma*MeshInterpolate(&delta,pixels[0].black,
5502                   pixels[1].black,pixels[2].black);
5503               gamma=MeshInterpolate(&delta,1.0,1.0,1.0);
5504               pixel->alpha=gamma*MeshInterpolate(&delta,pixels[0].alpha,
5505                 pixels[1].alpha,pixels[2].alpha);
5506             }
5507           else
5508             {
5509               /*
5510                 Bottom-right triangle (pixel: 3, diagonal: 1-2).
5511               */
5512               delta.x=1.0-delta.x;
5513               delta.y=1.0-delta.y;
5514               gamma=MeshInterpolate(&delta,alpha[3],alpha[2],alpha[1]);
5515               gamma=MagickEpsilonReciprocal(gamma);
5516               pixel->red=gamma*MeshInterpolate(&delta,pixels[3].red,
5517                 pixels[2].red,pixels[1].red);
5518               pixel->green=gamma*MeshInterpolate(&delta,pixels[3].green,
5519                 pixels[2].green,pixels[1].green);
5520               pixel->blue=gamma*MeshInterpolate(&delta,pixels[3].blue,
5521                 pixels[2].blue,pixels[1].blue);
5522               if (image->colorspace == CMYKColorspace)
5523                 pixel->black=gamma*MeshInterpolate(&delta,pixels[3].black,
5524                   pixels[2].black,pixels[1].black);
5525               gamma=MeshInterpolate(&delta,1.0,1.0,1.0);
5526               pixel->alpha=gamma*MeshInterpolate(&delta,pixels[3].alpha,
5527                 pixels[2].alpha,pixels[1].alpha);
5528             }
5529         }
5530       break;
5531     }
5532     case NearestInterpolatePixel:
5533     {
5534       x_offset=(ssize_t) floor(x+0.5);
5535       y_offset=(ssize_t) floor(y+0.5);
5536       p=GetCacheViewVirtualPixels(image_view,x_offset,y_offset,1,1,exception);
5537       if (p == (const Quantum *) NULL)
5538         {
5539           status=MagickFalse;
5540           break;
5541         }
5542       GetPixelInfoPixel(image,p,pixel);
5543       break;
5544     }
5545     case SplineInterpolatePixel:
5546     {
5547       double
5548         cx[4],
5549         cy[4];
5550
5551       p=GetCacheViewVirtualPixels(image_view,x_offset-1,y_offset-1,4,4,
5552         exception);
5553       if (p == (const Quantum *) NULL)
5554         {
5555           status=MagickFalse;
5556           break;
5557         }
5558       for (i=0; i < 16L; i++)
5559         AlphaBlendPixelInfo(image,p+i*GetPixelChannels(image),pixels+i,alpha+i);
5560       SplineWeights((double) (x-x_offset),&cx);
5561       SplineWeights((double) (y-y_offset),&cy);
5562       pixel->red=(cy[0]*(cx[0]*pixels[0].red+cx[1]*
5563         pixels[1].red+cx[2]*pixels[2].red+cx[3]*
5564         pixels[3].red)+cy[1]*(cx[0]*pixels[4].red+cx[1]*
5565         pixels[5].red+cx[2]*pixels[6].red+cx[3]*
5566         pixels[7].red)+cy[2]*(cx[0]*pixels[8].red+cx[1]*
5567         pixels[9].red+cx[2]*pixels[10].red+cx[3]*
5568         pixels[11].red)+cy[3]*(cx[0]*pixels[12].red+cx[1]*
5569         pixels[13].red+cx[2]*pixels[14].red+cx[3]*pixels[15].red));
5570       pixel->green=(cy[0]*(cx[0]*pixels[0].green+cx[1]*
5571         pixels[1].green+cx[2]*pixels[2].green+cx[3]*
5572         pixels[3].green)+cy[1]*(cx[0]*pixels[4].green+cx[1]*
5573         pixels[5].green+cx[2]*pixels[6].green+cx[3]*
5574         pixels[7].green)+cy[2]*(cx[0]*pixels[8].green+cx[1]*
5575         pixels[9].green+cx[2]*pixels[10].green+cx[3]*
5576         pixels[11].green)+cy[3]*(cx[0]*pixels[12].green+cx[1]*
5577         pixels[13].green+cx[2]*pixels[14].green+cx[3]*pixels[15].green));
5578       pixel->blue=(cy[0]*(cx[0]*pixels[0].blue+cx[1]*
5579         pixels[1].blue+cx[2]*pixels[2].blue+cx[3]*
5580         pixels[3].blue)+cy[1]*(cx[0]*pixels[4].blue+cx[1]*
5581         pixels[5].blue+cx[2]*pixels[6].blue+cx[3]*
5582         pixels[7].blue)+cy[2]*(cx[0]*pixels[8].blue+cx[1]*
5583         pixels[9].blue+cx[2]*pixels[10].blue+cx[3]*
5584         pixels[11].blue)+cy[3]*(cx[0]*pixels[12].blue+cx[1]*
5585         pixels[13].blue+cx[2]*pixels[14].blue+cx[3]*pixels[15].blue));
5586       if (image->colorspace == CMYKColorspace)
5587         pixel->black=(cy[0]*(cx[0]*pixels[0].black+cx[1]*
5588           pixels[1].black+cx[2]*pixels[2].black+cx[3]*
5589           pixels[3].black)+cy[1]*(cx[0]*pixels[4].black+cx[1]*
5590           pixels[5].black+cx[2]*pixels[6].black+cx[3]*
5591           pixels[7].black)+cy[2]*(cx[0]*pixels[8].black+cx[1]*
5592           pixels[9].black+cx[2]*pixels[10].black+cx[3]*
5593           pixels[11].black)+cy[3]*(cx[0]*pixels[12].black+cx[1]*
5594           pixels[13].black+cx[2]*pixels[14].black+cx[3]*pixels[15].black));
5595       pixel->alpha=(cy[0]*(cx[0]*pixels[0].alpha+cx[1]*
5596         pixels[1].alpha+cx[2]*pixels[2].alpha+cx[3]*
5597         pixels[3].alpha)+cy[1]*(cx[0]*pixels[4].alpha+cx[1]*
5598         pixels[5].alpha+cx[2]*pixels[6].alpha+cx[3]*
5599         pixels[7].alpha)+cy[2]*(cx[0]*pixels[8].alpha+cx[1]*
5600         pixels[9].alpha+cx[2]*pixels[10].alpha+cx[3]*
5601         pixels[11].alpha)+cy[3]*(cx[0]*pixels[12].alpha+cx[1]*
5602         pixels[13].alpha+cx[2]*pixels[14].alpha+cx[3]*pixels[15].alpha));
5603       break;
5604     }
5605   }
5606   return(status);
5607 }
5608 \f
5609 /*
5610 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5611 %                                                                             %
5612 %                                                                             %
5613 %                                                                             %
5614 +   I s F u z z y E q u i v a l e n c e P i x e l                             %
5615 %                                                                             %
5616 %                                                                             %
5617 %                                                                             %
5618 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5619 %
5620 %  IsFuzzyEquivalencePixel() returns MagickTrue if the distance between two
5621 %  pixels is less than the specified distance in a linear three (or four)u
5622 %  dimensional color space.
5623 %
5624 %  The format of the IsFuzzyEquivalencePixel method is:
5625 %
5626 %      void IsFuzzyEquivalencePixel(const Image *source,const Quantum *p,
5627 %        const Image *destination,const Quantum *q)
5628 %
5629 %  A description of each parameter follows:
5630 %
5631 %    o source: the source image.
5632 %
5633 %    o p: Pixel p.
5634 %
5635 %    o destination: the destination image.
5636 %
5637 %    o q: Pixel q.
5638 %
5639 */
5640 MagickExport MagickBooleanType IsFuzzyEquivalencePixel(const Image *source,
5641   const Quantum *p,const Image *destination,const Quantum *q)
5642 {
5643   double
5644     fuzz,
5645     pixel;
5646
5647   register double
5648     distance,
5649     scale;
5650
5651   fuzz=MagickMax(source->fuzz,(double) MagickSQ1_2)*MagickMax(
5652     destination->fuzz,(double) MagickSQ1_2);
5653   scale=1.0;
5654   distance=0.0;
5655   if (source->alpha_trait == BlendPixelTrait)
5656     {
5657       /*
5658         Transparencies are involved - set alpha distance
5659       */
5660       pixel=GetPixelAlpha(source,p)-(double)
5661         GetPixelAlpha(destination,q);
5662       distance=pixel*pixel;
5663       if (distance > fuzz)
5664         return(MagickFalse);
5665       /*
5666         Generate a alpha scaling factor to generate a 4D cone on colorspace
5667         Note that if one color is transparent, distance has no color component.
5668       */
5669       scale=QuantumScale*GetPixelAlpha(source,p);
5670       scale*=QuantumScale*GetPixelAlpha(destination,q);
5671       if (scale <= MagickEpsilon)
5672         return(MagickTrue);
5673     }
5674   /*
5675     RGB or CMY color cube
5676   */
5677   distance*=3.0;  /* rescale appropriately */
5678   fuzz*=3.0;
5679   pixel=GetPixelRed(source,p)-(double) GetPixelRed(destination,q);
5680   if ((source->colorspace == HSLColorspace) ||
5681       (source->colorspace == HSBColorspace) ||
5682       (source->colorspace == HWBColorspace))
5683     {
5684       /*
5685         Compute an arc distance for hue.  It should be a vector angle of
5686         'S'/'W' length with 'L'/'B' forming appropriate cones.
5687       */
5688       if (fabs((double) pixel) > (QuantumRange/2))
5689         pixel-=QuantumRange;
5690       pixel*=2;
5691     }
5692   distance+=scale*pixel*pixel;
5693   if (distance > fuzz)
5694     return(MagickFalse);
5695   pixel=GetPixelGreen(source,p)-(double) GetPixelGreen(destination,q);
5696   distance+=scale*pixel*pixel;
5697   if (distance > fuzz)
5698     return(MagickFalse);
5699   pixel=GetPixelBlue(source,p)-(double) GetPixelBlue(destination,q);
5700   distance+=scale*pixel*pixel;
5701   if (distance > fuzz)
5702     return(MagickFalse);
5703   return(MagickTrue);
5704 }
5705 \f
5706 /*
5707 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5708 %                                                                             %
5709 %                                                                             %
5710 %                                                                             %
5711 +   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                     %
5712 %                                                                             %
5713 %                                                                             %
5714 %                                                                             %
5715 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5716 %
5717 %  IsFuzzyEquivalencePixelInfo() returns true if the distance between two
5718 %  colors is less than the specified distance in a linear three (or four)
5719 %  dimensional color space.
5720 %
5721 %  This implements the equivalent of:
5722 %    fuzz < sqrt(color_distance^2 * u.a*v.a  + alpha_distance^2)
5723 %
5724 %  Which produces a multi-dimensional cone for that colorspace along the
5725 %  transparency vector.
5726 %
5727 %  For example for an RGB:
5728 %    color_distance^2  = ( (u.r-v.r)^2 + (u.g-v.g)^2 + (u.b-v.b)^2 ) / 3
5729 %
5730 %  See http://www.imagemagick.org/Usage/bugs/fuzz_distance/
5731 %
5732 %  Hue colorspace distances need more work.  Hue is not a distance, it is an
5733 %  angle!
5734 %
5735 %  A check that q is in the same color space as p should be made and the
5736 %  appropriate mapping made.  -- Anthony Thyssen  8 December 2010
5737 %
5738 %  The format of the IsFuzzyEquivalencePixelInfo method is:
5739 %
5740 %      MagickBooleanType IsFuzzyEquivalencePixelInfo(const PixelInfo *p,
5741 %        const PixelInfo *q)
5742 %
5743 %  A description of each parameter follows:
5744 %
5745 %    o p: Pixel p.
5746 %
5747 %    o q: Pixel q.
5748 %
5749 */
5750 MagickExport MagickBooleanType IsFuzzyEquivalencePixelInfo(const PixelInfo *p,
5751   const PixelInfo *q)
5752 {
5753   double
5754     fuzz,
5755     pixel;
5756
5757   register double
5758     scale,
5759     distance;
5760
5761   if ((p->fuzz == 0.0) && (q->fuzz == 0.0))
5762     return(IsPixelInfoEquivalent(p,q));
5763   if (p->fuzz == 0.0)
5764     fuzz=MagickMax(q->fuzz,(double) MagickSQ1_2)*MagickMax(q->fuzz,
5765       (double) MagickSQ1_2);
5766   else if (q->fuzz == 0.0)
5767     fuzz=MagickMax(p->fuzz,(double) MagickSQ1_2)*MagickMax(p->fuzz,
5768       (double) MagickSQ1_2);
5769   else
5770     fuzz=MagickMax(p->fuzz,(double) MagickSQ1_2)*MagickMax(q->fuzz,
5771       (double) MagickSQ1_2);
5772   scale=1.0;
5773   distance=0.0;
5774   if ((p->alpha_trait == BlendPixelTrait) || (q->alpha_trait == BlendPixelTrait))
5775     {
5776       /*
5777         Transparencies are involved - set alpha distance.
5778       */
5779       pixel=(p->alpha_trait == BlendPixelTrait ? p->alpha : OpaqueAlpha)-
5780         (q->alpha_trait == BlendPixelTrait ? q->alpha : OpaqueAlpha);
5781       distance=pixel*pixel;
5782       if (distance > fuzz)
5783         return(MagickFalse);
5784       /*
5785         Generate a alpha scaling factor to generate a 4D cone on colorspace.
5786         If one color is transparent, distance has no color component.
5787       */
5788       if (p->alpha_trait == BlendPixelTrait)
5789         scale=(QuantumScale*p->alpha);
5790       if (q->alpha_trait == BlendPixelTrait)
5791         scale*=(QuantumScale*q->alpha);
5792       if (scale <= MagickEpsilon )
5793         return(MagickTrue);
5794     }
5795   /*
5796     CMYK create a CMY cube with a multi-dimensional cone toward black.
5797   */
5798   if (p->colorspace == CMYKColorspace)
5799     {
5800       pixel=p->black-q->black;
5801       distance+=pixel*pixel*scale;
5802       if (distance > fuzz)
5803         return(MagickFalse);
5804       scale*=(double) (QuantumScale*(QuantumRange-p->black));
5805       scale*=(double) (QuantumScale*(QuantumRange-q->black));
5806     }
5807   /*
5808     RGB or CMY color cube.
5809   */
5810   distance*=3.0;  /* rescale appropriately */
5811   fuzz*=3.0;
5812   pixel=p->red-q->red;
5813   if ((p->colorspace == HSLColorspace) || (p->colorspace == HSBColorspace) ||
5814       (p->colorspace == HWBColorspace))
5815     {
5816       /*
5817         This calculates a arc distance for hue-- it should be a vector angle
5818         of 'S'/'W' length with 'L'/'B' forming appropriate cones.  In other
5819         words this is a hack - Anthony.
5820       */
5821       if (fabs((double) pixel) > (QuantumRange/2))
5822         pixel-=QuantumRange;
5823       pixel*=2;
5824     }
5825   distance+=pixel*pixel*scale;
5826   if (distance > fuzz)
5827     return(MagickFalse);
5828   pixel=p->green-q->green;
5829   distance+=pixel*pixel*scale;
5830   if (distance > fuzz)
5831     return(MagickFalse);
5832   pixel=p->blue-q->blue;
5833   distance+=pixel*pixel*scale;
5834   if (distance > fuzz)
5835     return(MagickFalse);
5836   return(MagickTrue);
5837 }
5838 \f
5839 /*
5840 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5841 %                                                                             %
5842 %                                                                             %
5843 %                                                                             %
5844 %   S e t P i x e l C h a n n e l M a p M a s k                               %
5845 %                                                                             %
5846 %                                                                             %
5847 %                                                                             %
5848 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5849 %
5850 %  SetPixelChannelMask() sets the pixel channel map from the specified
5851 %  channel mask.
5852 %
5853 %  The format of the SetPixelChannelMask method is:
5854 %
5855 %      void SetPixelChannelMask(Image *image,const ChannelType channel_mask)
5856 %
5857 %  A description of each parameter follows:
5858 %
5859 %    o image: the image.
5860 %
5861 %    o channel_mask: the channel mask.
5862 %
5863 */
5864 MagickExport void SetPixelChannelMask(Image *image,
5865   const ChannelType channel_mask)
5866 {
5867 #define GetChannelBit(mask,bit)  (((size_t) (mask) >> (size_t) (bit)) & 0x01)
5868
5869   register ssize_t
5870     i;
5871
5872   if (image->debug != MagickFalse)
5873     (void) LogMagickEvent(PixelEvent,GetMagickModule(),"%s[%08x]", \
5874       image->filename,channel_mask); \
5875   image->channel_mask=channel_mask;
5876   for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
5877   {
5878     PixelChannel
5879       channel;
5880
5881     channel=GetPixelChannelChannel(image,i);
5882     SetPixelChannelTraits(image,channel,
5883       GetChannelBit(channel_mask,channel) == 0 ? CopyPixelTrait :
5884       image->alpha_trait != BlendPixelTrait || (channel == AlphaPixelChannel) ?
5885       UpdatePixelTrait : (PixelTrait) (UpdatePixelTrait | image->alpha_trait));
5886   }
5887   if (image->storage_class == PseudoClass)
5888     SetPixelChannelTraits(image,IndexPixelChannel,CopyPixelTrait);
5889   if (image->mask != MagickFalse)
5890     SetPixelChannelTraits(image,MaskPixelChannel,CopyPixelTrait);
5891   if (image->debug != MagickFalse)
5892     LogPixelChannels(image);
5893 }
5894 \f
5895 /*
5896 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5897 %                                                                             %
5898 %                                                                             %
5899 %                                                                             %
5900 %   S e t P i x e l M e t a C h a n n e l s                                   %
5901 %                                                                             %
5902 %                                                                             %
5903 %                                                                             %
5904 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5905 %
5906 %  SetPixelMetaChannels() sets the image meta channels.
5907 %
5908 %  The format of the SetPixelMetaChannels method is:
5909 %
5910 %      MagickBooleanType SetPixelMetaChannels(Image *image,
5911 %        const size_t number_meta_channels,ExceptionInfo *exception)
5912 %
5913 %  A description of each parameter follows:
5914 %
5915 %    o image: the image.
5916 %
5917 %    o number_meta_channels:  the number of meta channels.
5918 %
5919 %    o exception: return any errors or warnings in this structure.
5920 %
5921 */
5922 MagickExport MagickBooleanType SetPixelMetaChannels(Image *image,
5923   const size_t number_meta_channels,ExceptionInfo *exception)
5924 {
5925   image->number_meta_channels=number_meta_channels;
5926   return(SyncImagePixelCache(image,exception));
5927 }