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