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