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