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