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