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