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