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