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