blob: 5f39178557540da1dbc14930019aecc1752b5ee3 [file] [log] [blame]
cristy4c08aed2011-07-01 19:47:50 +00001/*
2%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3% %
4% %
5% %
6% PPPP IIIII X X EEEEE L %
7% P P I X X E L %
8% PPPP I X EEE L %
9% P I X X E L %
10% P IIIII X X EEEEE LLLLL %
11% %
12% MagickCore Methods to Import/Export Pixels %
13% %
14% Software Design %
15% John Cristy %
16% October 1998 %
17% %
18% %
cristy45ef08f2012-12-07 13:13:34 +000019% Copyright 1999-2013 ImageMagick Studio LLC, a non-profit organization %
cristy4c08aed2011-07-01 19:47:50 +000020% 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"
cristy322d07d2012-03-18 21:17:23 +000045#include "MagickCore/cache-private.h"
cristy4c08aed2011-07-01 19:47:50 +000046#include "MagickCore/color-private.h"
47#include "MagickCore/draw.h"
48#include "MagickCore/exception.h"
49#include "MagickCore/exception-private.h"
50#include "MagickCore/cache.h"
51#include "MagickCore/constitute.h"
52#include "MagickCore/delegate.h"
53#include "MagickCore/geometry.h"
54#include "MagickCore/image-private.h"
55#include "MagickCore/list.h"
56#include "MagickCore/magick.h"
57#include "MagickCore/memory_.h"
58#include "MagickCore/monitor.h"
59#include "MagickCore/option.h"
60#include "MagickCore/pixel.h"
61#include "MagickCore/pixel-accessor.h"
cristy380a11c2012-06-02 15:15:22 +000062#include "MagickCore/pixel-private.h"
cristy4c08aed2011-07-01 19:47:50 +000063#include "MagickCore/quantum.h"
64#include "MagickCore/quantum-private.h"
65#include "MagickCore/resource_.h"
66#include "MagickCore/semaphore.h"
67#include "MagickCore/statistic.h"
68#include "MagickCore/stream.h"
69#include "MagickCore/string_.h"
70#include "MagickCore/transform.h"
71#include "MagickCore/utility.h"
72
cristy146a62b2011-10-23 23:40:46 +000073#define LogPixelChannels(image) \
74{ \
75 register ssize_t \
76 i; \
77 \
78 (void) LogMagickEvent(PixelEvent,GetMagickModule(),"%s[%.20g]", \
79 image->filename,(double) image->number_channels); \
80 for (i=0; i < (ssize_t) image->number_channels; i++) \
81 { \
82 char \
83 traits[MaxTextExtent]; \
84 \
85 const char \
cristy46795722011-12-10 23:56:57 +000086 *name; \
87 \
88 PixelChannel \
89 channel; \
cristy146a62b2011-10-23 23:40:46 +000090 \
cristycf1296e2012-08-26 23:40:49 +000091 switch (GetPixelChannelChannel(image,i)) \
cristy146a62b2011-10-23 23:40:46 +000092 { \
93 case RedPixelChannel: \
94 { \
cristy46795722011-12-10 23:56:57 +000095 name="red"; \
cristy146a62b2011-10-23 23:40:46 +000096 if (image->colorspace == CMYKColorspace) \
cristy46795722011-12-10 23:56:57 +000097 name="cyan"; \
cristy146a62b2011-10-23 23:40:46 +000098 if (image->colorspace == GRAYColorspace) \
cristy46795722011-12-10 23:56:57 +000099 name="gray"; \
cristy146a62b2011-10-23 23:40:46 +0000100 break; \
101 } \
102 case GreenPixelChannel: \
103 { \
cristy46795722011-12-10 23:56:57 +0000104 name="green"; \
cristy146a62b2011-10-23 23:40:46 +0000105 if (image->colorspace == CMYKColorspace) \
cristy46795722011-12-10 23:56:57 +0000106 name="magenta"; \
cristy146a62b2011-10-23 23:40:46 +0000107 break; \
108 } \
109 case BluePixelChannel: \
110 { \
cristy46795722011-12-10 23:56:57 +0000111 name="blue"; \
cristy146a62b2011-10-23 23:40:46 +0000112 if (image->colorspace == CMYKColorspace) \
cristy46795722011-12-10 23:56:57 +0000113 name="yellow"; \
cristy146a62b2011-10-23 23:40:46 +0000114 break; \
115 } \
116 case BlackPixelChannel: \
117 { \
cristy46795722011-12-10 23:56:57 +0000118 name="black"; \
cristy146a62b2011-10-23 23:40:46 +0000119 if (image->storage_class == PseudoClass) \
cristy46795722011-12-10 23:56:57 +0000120 name="index"; \
cristy146a62b2011-10-23 23:40:46 +0000121 break; \
122 } \
cristye2a912b2011-12-05 20:02:07 +0000123 case IndexPixelChannel: \
124 { \
cristy46795722011-12-10 23:56:57 +0000125 name="index"; \
cristye2a912b2011-12-05 20:02:07 +0000126 break; \
127 } \
cristy146a62b2011-10-23 23:40:46 +0000128 case AlphaPixelChannel: \
129 { \
cristy46795722011-12-10 23:56:57 +0000130 name="alpha"; \
cristy146a62b2011-10-23 23:40:46 +0000131 break; \
132 } \
133 case MaskPixelChannel: \
134 { \
cristy46795722011-12-10 23:56:57 +0000135 name="mask"; \
cristy146a62b2011-10-23 23:40:46 +0000136 break; \
137 } \
cristye2a912b2011-12-05 20:02:07 +0000138 case MetaPixelChannel: \
cristy146a62b2011-10-23 23:40:46 +0000139 { \
cristy46795722011-12-10 23:56:57 +0000140 name="meta"; \
cristye2a912b2011-12-05 20:02:07 +0000141 break; \
cristy146a62b2011-10-23 23:40:46 +0000142 } \
cristye2a912b2011-12-05 20:02:07 +0000143 default: \
cristy46795722011-12-10 23:56:57 +0000144 name="undefined"; \
cristy146a62b2011-10-23 23:40:46 +0000145 } \
cristycf1296e2012-08-26 23:40:49 +0000146 channel=GetPixelChannelChannel(image,i); \
cristy146a62b2011-10-23 23:40:46 +0000147 *traits='\0'; \
cristycf1296e2012-08-26 23:40:49 +0000148 if ((GetPixelChannelTraits(image,channel) & UpdatePixelTrait) != 0) \
cristy146a62b2011-10-23 23:40:46 +0000149 (void) ConcatenateMagickString(traits,"update,",MaxTextExtent); \
cristycf1296e2012-08-26 23:40:49 +0000150 if ((GetPixelChannelTraits(image,channel) & BlendPixelTrait) != 0) \
cristy146a62b2011-10-23 23:40:46 +0000151 (void) ConcatenateMagickString(traits,"blend,",MaxTextExtent); \
cristycf1296e2012-08-26 23:40:49 +0000152 if ((GetPixelChannelTraits(image,channel) & CopyPixelTrait) != 0) \
cristy146a62b2011-10-23 23:40:46 +0000153 (void) ConcatenateMagickString(traits,"copy,",MaxTextExtent); \
154 if (*traits == '\0') \
155 (void) ConcatenateMagickString(traits,"undefined,",MaxTextExtent); \
156 traits[strlen(traits)-1]='\0'; \
157 (void) LogMagickEvent(PixelEvent,GetMagickModule()," %.20g: %s (%s)", \
cristy46795722011-12-10 23:56:57 +0000158 (double) i,name,traits); \
cristy146a62b2011-10-23 23:40:46 +0000159 } \
160}
161
162/*
cristy4c08aed2011-07-01 19:47:50 +0000163%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
164% %
165% %
166% %
cristyed231572011-07-14 02:18:59 +0000167+ A c q u i r e P i x e l C h a n n e l M a p %
cristy4c08aed2011-07-01 19:47:50 +0000168% %
169% %
170% %
171%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
172%
cristyed231572011-07-14 02:18:59 +0000173% AcquirePixelChannelMap() acquires a pixel component map.
cristy4c08aed2011-07-01 19:47:50 +0000174%
cristyed231572011-07-14 02:18:59 +0000175% The format of the AcquirePixelChannelMap() method is:
cristy4c08aed2011-07-01 19:47:50 +0000176%
cristybd5a96c2011-08-21 00:04:26 +0000177% PixelChannelMap *AcquirePixelChannelMap(void)
cristy4c08aed2011-07-01 19:47:50 +0000178%
179*/
cristybd5a96c2011-08-21 00:04:26 +0000180MagickExport PixelChannelMap *AcquirePixelChannelMap(void)
cristy4c08aed2011-07-01 19:47:50 +0000181{
cristyed231572011-07-14 02:18:59 +0000182 PixelChannelMap
cristybd5a96c2011-08-21 00:04:26 +0000183 *channel_map;
cristy4c08aed2011-07-01 19:47:50 +0000184
185 register ssize_t
186 i;
187
cristybd5a96c2011-08-21 00:04:26 +0000188 channel_map=(PixelChannelMap *) AcquireQuantumMemory(MaxPixelChannels,
189 sizeof(*channel_map));
190 if (channel_map == (PixelChannelMap *) NULL)
cristy4c08aed2011-07-01 19:47:50 +0000191 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
cristybd5a96c2011-08-21 00:04:26 +0000192 (void) ResetMagickMemory(channel_map,0,MaxPixelChannels*sizeof(*channel_map));
193 for (i=0; i < MaxPixelChannels; i++)
194 channel_map[i].channel=(PixelChannel) i;
cristyed231572011-07-14 02:18:59 +0000195 return(channel_map);
cristy4c08aed2011-07-01 19:47:50 +0000196}
197
198/*
199%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
200% %
201% %
202% %
cristyed231572011-07-14 02:18:59 +0000203+ C l o n e P i x e l C h a n n e l M a p %
cristy4c08aed2011-07-01 19:47:50 +0000204% %
205% %
206% %
207%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
208%
cristyed231572011-07-14 02:18:59 +0000209% ClonePixelChannelMap() clones a pixel component map.
cristy4c08aed2011-07-01 19:47:50 +0000210%
cristyed231572011-07-14 02:18:59 +0000211% The format of the ClonePixelChannelMap() method is:
cristy4c08aed2011-07-01 19:47:50 +0000212%
cristybd5a96c2011-08-21 00:04:26 +0000213% PixelChannelMap *ClonePixelChannelMap(PixelChannelMap *channel_map)
cristy4c08aed2011-07-01 19:47:50 +0000214%
215% A description of each parameter follows:
216%
cristyed231572011-07-14 02:18:59 +0000217% o channel_map: the pixel component map.
cristy4c08aed2011-07-01 19:47:50 +0000218%
219*/
cristybd5a96c2011-08-21 00:04:26 +0000220MagickExport PixelChannelMap *ClonePixelChannelMap(PixelChannelMap *channel_map)
cristy4c08aed2011-07-01 19:47:50 +0000221{
cristyed231572011-07-14 02:18:59 +0000222 PixelChannelMap
cristybd5a96c2011-08-21 00:04:26 +0000223 *clone_map;
cristy4c08aed2011-07-01 19:47:50 +0000224
cristybd5a96c2011-08-21 00:04:26 +0000225 assert(channel_map != (PixelChannelMap *) NULL);
cristyed231572011-07-14 02:18:59 +0000226 clone_map=AcquirePixelChannelMap();
cristybd5a96c2011-08-21 00:04:26 +0000227 if (clone_map == (PixelChannelMap *) NULL)
228 return((PixelChannelMap *) NULL);
229 (void) CopyMagickMemory(clone_map,channel_map,MaxPixelChannels*
230 sizeof(*channel_map));
cristy4c08aed2011-07-01 19:47:50 +0000231 return(clone_map);
232}
233
234/*
235%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
236% %
237% %
238% %
239+ C l o n e P i x e l I n f o %
240% %
241% %
242% %
243%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
244%
245% ClonePixelInfo() makes a duplicate of the given pixel info structure, or if
246% pixel info is NULL, a new one.
247%
248% The format of the ClonePixelInfo method is:
249%
250% PixelInfo *ClonePixelInfo(const PixelInfo *pixel_info)
251%
252% A description of each parameter follows:
253%
254% o pixel_info: the pixel info.
255%
256*/
257MagickExport PixelInfo *ClonePixelInfo(const PixelInfo *pixel)
258{
259 PixelInfo
260 *pixel_info;
261
cristya64b85d2011-09-14 01:02:31 +0000262 pixel_info=(PixelInfo *) AcquireQuantumMemory(1,sizeof(*pixel_info));
cristy4c08aed2011-07-01 19:47:50 +0000263 if (pixel_info == (PixelInfo *) NULL)
264 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
265 *pixel_info=(*pixel);
266 return(pixel_info);
267}
268
269/*
270%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
271% %
272% %
273% %
cristyc8aff842012-12-24 16:59:46 +0000274% D e c o d e P i x e l G a m m a %
275% %
276% %
277% %
278%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
279%
280% DecodePixelGamma() applies the expansive power-law nonlinearity to the pixel.
281%
282% The format of the DecodePixelGammaImage method is:
283%
284% double DecodePixelGamma(const MagickRealType pixel)
285%
286% A description of each parameter follows:
287%
288% o pixel: the pixel.
289%
290*/
291MagickExport MagickRealType DecodePixelGamma(const MagickRealType pixel)
292{
293 if (pixel <= (0.0404482362771076*QuantumRange))
294 return(pixel/12.92f);
295 return((MagickRealType) (QuantumRange*pow((double) (QuantumScale*pixel+
296 0.055)/1.055,2.4)));
297}
298
299/*
300%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
301% %
302% %
303% %
cristyed231572011-07-14 02:18:59 +0000304+ D e s t r o y P i x e l C h a n n e l M a p %
cristy4c08aed2011-07-01 19:47:50 +0000305% %
306% %
307% %
308%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
309%
cristyed231572011-07-14 02:18:59 +0000310% DestroyPixelChannelMap() deallocates memory associated with the pixel
311% channel map.
cristy4c08aed2011-07-01 19:47:50 +0000312%
cristyed231572011-07-14 02:18:59 +0000313% The format of the DestroyPixelChannelMap() method is:
cristy4c08aed2011-07-01 19:47:50 +0000314%
cristybd5a96c2011-08-21 00:04:26 +0000315% PixelChannelMap *DestroyPixelChannelMap(PixelChannelMap *channel_map)
cristy4c08aed2011-07-01 19:47:50 +0000316%
317% A description of each parameter follows:
318%
cristyed231572011-07-14 02:18:59 +0000319% o channel_map: the pixel component map.
cristy4c08aed2011-07-01 19:47:50 +0000320%
321*/
cristybd5a96c2011-08-21 00:04:26 +0000322MagickExport PixelChannelMap *DestroyPixelChannelMap(
323 PixelChannelMap *channel_map)
cristy4c08aed2011-07-01 19:47:50 +0000324{
cristybd5a96c2011-08-21 00:04:26 +0000325 assert(channel_map != (PixelChannelMap *) NULL);
326 channel_map=(PixelChannelMap *) RelinquishMagickMemory(channel_map);
327 return((PixelChannelMap *) RelinquishMagickMemory(channel_map));
cristy4c08aed2011-07-01 19:47:50 +0000328}
329
330/*
331%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
332% %
333% %
334% %
cristyc8aff842012-12-24 16:59:46 +0000335+ E n c o d e P i x e l G a m m a %
336% %
337% %
338% %
339%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
340%
341% EncodePixelGamma() cancels any nonlinearity in the pixel.
342%
343% The format of the EncodePixelGammaImage method is:
344%
345% MagickRealType EncodePixelGamma(const double MagickRealType)
346%
347% A description of each parameter follows:
348%
349% o pixel: the pixel.
350%
351*/
352MagickExport MagickRealType EncodePixelGamma(const MagickRealType pixel)
353{
354 if (pixel <= (0.0031306684425005883*QuantumRange))
355 return(12.92f*pixel);
356 return((MagickRealType) QuantumRange*(1.055*pow((double) QuantumScale*pixel,
357 1.0/2.4)-0.055));
358}
359
360/*
361%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
362% %
363% %
364% %
cristy4c08aed2011-07-01 19:47:50 +0000365% E x p o r t I m a g e P i x e l s %
366% %
367% %
368% %
369%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
370%
371% ExportImagePixels() extracts pixel data from an image and returns it to you.
372% The method returns MagickTrue on success otherwise MagickFalse if an error is
cristyb5a45a32012-01-10 13:31:13 +0000373% encountered. The data is returned as char, short int, Quantum, unsigned int,
cristycafe0412012-01-10 13:29:58 +0000374% unsigned long long, float, or double in the order specified by map.
cristy4c08aed2011-07-01 19:47:50 +0000375%
376% Suppose you want to extract the first scanline of a 640x480 image as
377% character data in red-green-blue order:
378%
379% ExportImagePixels(image,0,0,640,1,"RGB",CharPixel,pixels,exception);
380%
381% The format of the ExportImagePixels method is:
382%
cristycafe0412012-01-10 13:29:58 +0000383% MagickBooleanType ExportImagePixels(const Image *image,const ssize_t x,
384% const ssize_t y,const size_t width,const size_t height,
385% const char *map,const StorageType type,void *pixels,
cristy46f4be22012-01-07 00:26:39 +0000386% ExceptionInfo *exception)
cristy4c08aed2011-07-01 19:47:50 +0000387%
388% A description of each parameter follows:
389%
390% o image: the image.
391%
cristycafe0412012-01-10 13:29:58 +0000392% o x,y,width,height: These values define the perimeter
cristy4c08aed2011-07-01 19:47:50 +0000393% of a region of pixels you want to extract.
394%
395% o map: This string reflects the expected ordering of the pixel array.
396% It can be any combination or order of R = red, G = green, B = blue,
397% A = alpha (0 is transparent), O = opacity (0 is opaque), C = cyan,
398% Y = yellow, M = magenta, K = black, I = intensity (for grayscale),
399% P = pad.
400%
401% o type: Define the data type of the pixels. Float and double types are
402% normalized to [0..1] otherwise [0..QuantumRange]. Choose from these
cristy6c9e1682012-01-07 21:37:44 +0000403% types: CharPixel (char *), DoublePixel (double *), FloatPixel (float *),
cristyff6834e2012-01-10 03:00:25 +0000404% LongPixel (unsigned int *), LongLongPixel (unsigned long long *),
cristy6c9e1682012-01-07 21:37:44 +0000405% QuantumPixel (Quantum *), or ShortPixel (unsigned short *).
cristy4c08aed2011-07-01 19:47:50 +0000406%
407% o pixels: This array of values contain the pixel components as defined by
408% map and type. You must preallocate this array where the expected
409% length varies depending on the values of width, height, map, and type.
410%
411% o exception: return any errors or warnings in this structure.
412%
413*/
cristye5370942012-01-06 03:49:31 +0000414
cristy2dc655d2012-07-05 13:16:28 +0000415static void ExportCharPixel(Image *image,const RectangleInfo *roi,
cristy46f4be22012-01-07 00:26:39 +0000416 const char *restrict map,const QuantumType *quantum_map,void *pixels,
417 ExceptionInfo *exception)
cristye5370942012-01-06 03:49:31 +0000418{
419 register const Quantum
420 *restrict p;
421
422 register ssize_t
423 x;
424
425 register unsigned char
cristy3fe11452012-01-09 01:27:42 +0000426 *restrict q;
cristye5370942012-01-06 03:49:31 +0000427
cristy14d71292012-05-20 16:48:13 +0000428 size_t
429 length;
430
cristye5370942012-01-06 03:49:31 +0000431 ssize_t
432 y;
433
cristy46f4be22012-01-07 00:26:39 +0000434 q=(unsigned char *) pixels;
cristye5370942012-01-06 03:49:31 +0000435 if (LocaleCompare(map,"BGR") == 0)
436 {
cristycafe0412012-01-10 13:29:58 +0000437 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +0000438 {
cristycafe0412012-01-10 13:29:58 +0000439 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +0000440 if (p == (const Quantum *) NULL)
441 break;
cristycafe0412012-01-10 13:29:58 +0000442 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +0000443 {
444 *q++=ScaleQuantumToChar(GetPixelBlue(image,p));
445 *q++=ScaleQuantumToChar(GetPixelGreen(image,p));
446 *q++=ScaleQuantumToChar(GetPixelRed(image,p));
447 p+=GetPixelChannels(image);
448 }
449 }
450 return;
451 }
452 if (LocaleCompare(map,"BGRA") == 0)
453 {
cristycafe0412012-01-10 13:29:58 +0000454 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +0000455 {
cristycafe0412012-01-10 13:29:58 +0000456 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +0000457 if (p == (const Quantum *) NULL)
458 break;
cristycafe0412012-01-10 13:29:58 +0000459 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +0000460 {
461 *q++=ScaleQuantumToChar(GetPixelBlue(image,p));
462 *q++=ScaleQuantumToChar(GetPixelGreen(image,p));
463 *q++=ScaleQuantumToChar(GetPixelRed(image,p));
464 *q++=ScaleQuantumToChar(GetPixelAlpha(image,p));
465 p+=GetPixelChannels(image);
466 }
467 }
468 return;
469 }
470 if (LocaleCompare(map,"BGRP") == 0)
471 {
cristycafe0412012-01-10 13:29:58 +0000472 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +0000473 {
cristycafe0412012-01-10 13:29:58 +0000474 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +0000475 if (p == (const Quantum *) NULL)
476 break;
cristycafe0412012-01-10 13:29:58 +0000477 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +0000478 {
479 *q++=ScaleQuantumToChar(GetPixelBlue(image,p));
480 *q++=ScaleQuantumToChar(GetPixelGreen(image,p));
481 *q++=ScaleQuantumToChar(GetPixelRed(image,p));
482 *q++=ScaleQuantumToChar((Quantum) 0);
483 p+=GetPixelChannels(image);
484 }
485 }
486 return;
487 }
488 if (LocaleCompare(map,"I") == 0)
489 {
cristycafe0412012-01-10 13:29:58 +0000490 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +0000491 {
cristycafe0412012-01-10 13:29:58 +0000492 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +0000493 if (p == (const Quantum *) NULL)
494 break;
cristycafe0412012-01-10 13:29:58 +0000495 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +0000496 {
cristy70e9f682013-03-12 22:31:22 +0000497 *q++=ScaleQuantumToChar(ClampToQuantum(GetPixelIntensity(image,p)));
cristye5370942012-01-06 03:49:31 +0000498 p+=GetPixelChannels(image);
499 }
500 }
501 return;
502 }
503 if (LocaleCompare(map,"RGB") == 0)
504 {
cristycafe0412012-01-10 13:29:58 +0000505 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +0000506 {
cristycafe0412012-01-10 13:29:58 +0000507 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +0000508 if (p == (const Quantum *) NULL)
509 break;
cristycafe0412012-01-10 13:29:58 +0000510 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +0000511 {
512 *q++=ScaleQuantumToChar(GetPixelRed(image,p));
513 *q++=ScaleQuantumToChar(GetPixelGreen(image,p));
514 *q++=ScaleQuantumToChar(GetPixelBlue(image,p));
515 p+=GetPixelChannels(image);
516 }
517 }
518 return;
519 }
520 if (LocaleCompare(map,"RGBA") == 0)
521 {
cristycafe0412012-01-10 13:29:58 +0000522 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +0000523 {
cristycafe0412012-01-10 13:29:58 +0000524 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +0000525 if (p == (const Quantum *) NULL)
526 break;
cristycafe0412012-01-10 13:29:58 +0000527 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +0000528 {
529 *q++=ScaleQuantumToChar(GetPixelRed(image,p));
530 *q++=ScaleQuantumToChar(GetPixelGreen(image,p));
531 *q++=ScaleQuantumToChar(GetPixelBlue(image,p));
532 *q++=ScaleQuantumToChar(GetPixelAlpha(image,p));
533 p+=GetPixelChannels(image);
534 }
535 }
536 return;
537 }
538 if (LocaleCompare(map,"RGBP") == 0)
539 {
cristycafe0412012-01-10 13:29:58 +0000540 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +0000541 {
cristycafe0412012-01-10 13:29:58 +0000542 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +0000543 if (p == (const Quantum *) NULL)
544 break;
cristycafe0412012-01-10 13:29:58 +0000545 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +0000546 {
547 *q++=ScaleQuantumToChar(GetPixelRed(image,p));
548 *q++=ScaleQuantumToChar(GetPixelGreen(image,p));
549 *q++=ScaleQuantumToChar(GetPixelBlue(image,p));
550 *q++=ScaleQuantumToChar((Quantum) 0);
551 p+=GetPixelChannels(image);
552 }
553 }
554 return;
555 }
cristy14d71292012-05-20 16:48:13 +0000556 length=strlen(map);
cristycafe0412012-01-10 13:29:58 +0000557 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +0000558 {
cristycafe0412012-01-10 13:29:58 +0000559 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +0000560 if (p == (const Quantum *) NULL)
561 break;
cristycafe0412012-01-10 13:29:58 +0000562 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +0000563 {
564 register ssize_t
565 i;
566
cristy14d71292012-05-20 16:48:13 +0000567 for (i=0; i < (ssize_t) length; i++)
cristye5370942012-01-06 03:49:31 +0000568 {
569 *q=0;
570 switch (quantum_map[i])
571 {
572 case RedQuantum:
573 case CyanQuantum:
574 {
575 *q=ScaleQuantumToChar(GetPixelRed(image,p));
576 break;
577 }
578 case GreenQuantum:
579 case MagentaQuantum:
580 {
581 *q=ScaleQuantumToChar(GetPixelGreen(image,p));
582 break;
583 }
584 case BlueQuantum:
585 case YellowQuantum:
586 {
587 *q=ScaleQuantumToChar(GetPixelBlue(image,p));
588 break;
589 }
590 case AlphaQuantum:
591 {
592 *q=ScaleQuantumToChar(GetPixelAlpha(image,p));
593 break;
594 }
595 case OpacityQuantum:
596 {
597 *q=ScaleQuantumToChar(GetPixelAlpha(image,p));
598 break;
599 }
600 case BlackQuantum:
601 {
602 if (image->colorspace == CMYKColorspace)
603 *q=ScaleQuantumToChar(GetPixelBlack(image,p));
604 break;
605 }
606 case IndexQuantum:
607 {
cristy70e9f682013-03-12 22:31:22 +0000608 *q=ScaleQuantumToChar(ClampToQuantum(GetPixelIntensity(image,p)));
cristye5370942012-01-06 03:49:31 +0000609 break;
610 }
611 default:
612 break;
613 }
614 q++;
615 }
616 p+=GetPixelChannels(image);
617 }
618 }
619}
620
cristy2dc655d2012-07-05 13:16:28 +0000621static void ExportDoublePixel(Image *image,const RectangleInfo *roi,
cristy46f4be22012-01-07 00:26:39 +0000622 const char *restrict map,const QuantumType *quantum_map,void *pixels,
623 ExceptionInfo *exception)
cristye5370942012-01-06 03:49:31 +0000624{
625 register const Quantum
626 *restrict p;
627
628 register double
cristy3fe11452012-01-09 01:27:42 +0000629 *restrict q;
cristye5370942012-01-06 03:49:31 +0000630
631 register ssize_t
632 x;
633
cristy14d71292012-05-20 16:48:13 +0000634 size_t
635 length;
636
cristye5370942012-01-06 03:49:31 +0000637 ssize_t
638 y;
639
640 q=(double *) pixels;
641 if (LocaleCompare(map,"BGR") == 0)
642 {
cristycafe0412012-01-10 13:29:58 +0000643 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +0000644 {
cristycafe0412012-01-10 13:29:58 +0000645 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +0000646 if (p == (const Quantum *) NULL)
647 break;
cristycafe0412012-01-10 13:29:58 +0000648 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +0000649 {
650 *q++=(double) (QuantumScale*GetPixelBlue(image,p));
651 *q++=(double) (QuantumScale*GetPixelGreen(image,p));
652 *q++=(double) (QuantumScale*GetPixelRed(image,p));
653 p+=GetPixelChannels(image);
654 }
655 }
656 return;
657 }
658 if (LocaleCompare(map,"BGRA") == 0)
659 {
cristycafe0412012-01-10 13:29:58 +0000660 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +0000661 {
cristycafe0412012-01-10 13:29:58 +0000662 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +0000663 if (p == (const Quantum *) NULL)
664 break;
cristycafe0412012-01-10 13:29:58 +0000665 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +0000666 {
667 *q++=(double) (QuantumScale*GetPixelBlue(image,p));
668 *q++=(double) (QuantumScale*GetPixelGreen(image,p));
669 *q++=(double) (QuantumScale*GetPixelRed(image,p));
670 *q++=(double) (QuantumScale*GetPixelAlpha(image,p));
671 p+=GetPixelChannels(image);
672 }
673 }
674 return;
675 }
676 if (LocaleCompare(map,"BGRP") == 0)
677 {
cristycafe0412012-01-10 13:29:58 +0000678 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +0000679 {
cristycafe0412012-01-10 13:29:58 +0000680 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +0000681 if (p == (const Quantum *) NULL)
682 break;
cristycafe0412012-01-10 13:29:58 +0000683 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +0000684 {
685 *q++=(double) (QuantumScale*GetPixelBlue(image,p));
686 *q++=(double) (QuantumScale*GetPixelGreen(image,p));
687 *q++=(double) (QuantumScale*GetPixelRed(image,p));
688 *q++=0.0;
689 p+=GetPixelChannels(image);
690 }
691 }
692 return;
693 }
694 if (LocaleCompare(map,"I") == 0)
695 {
cristycafe0412012-01-10 13:29:58 +0000696 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +0000697 {
cristycafe0412012-01-10 13:29:58 +0000698 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +0000699 if (p == (const Quantum *) NULL)
700 break;
cristycafe0412012-01-10 13:29:58 +0000701 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +0000702 {
703 *q++=(double) (QuantumScale*GetPixelIntensity(image,p));
704 p+=GetPixelChannels(image);
705 }
706 }
707 return;
708 }
709 if (LocaleCompare(map,"RGB") == 0)
710 {
cristycafe0412012-01-10 13:29:58 +0000711 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +0000712 {
cristycafe0412012-01-10 13:29:58 +0000713 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +0000714 if (p == (const Quantum *) NULL)
715 break;
cristycafe0412012-01-10 13:29:58 +0000716 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +0000717 {
718 *q++=(double) (QuantumScale*GetPixelRed(image,p));
719 *q++=(double) (QuantumScale*GetPixelGreen(image,p));
720 *q++=(double) (QuantumScale*GetPixelBlue(image,p));
721 p+=GetPixelChannels(image);
722 }
723 }
724 return;
725 }
726 if (LocaleCompare(map,"RGBA") == 0)
727 {
cristycafe0412012-01-10 13:29:58 +0000728 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +0000729 {
cristycafe0412012-01-10 13:29:58 +0000730 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +0000731 if (p == (const Quantum *) NULL)
732 break;
cristycafe0412012-01-10 13:29:58 +0000733 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +0000734 {
735 *q++=(double) (QuantumScale*GetPixelRed(image,p));
736 *q++=(double) (QuantumScale*GetPixelGreen(image,p));
737 *q++=(double) (QuantumScale*GetPixelBlue(image,p));
738 *q++=(double) (QuantumScale*GetPixelAlpha(image,p));
739 p+=GetPixelChannels(image);
740 }
741 }
742 return;
743 }
744 if (LocaleCompare(map,"RGBP") == 0)
745 {
cristycafe0412012-01-10 13:29:58 +0000746 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +0000747 {
cristycafe0412012-01-10 13:29:58 +0000748 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +0000749 if (p == (const Quantum *) NULL)
750 break;
cristycafe0412012-01-10 13:29:58 +0000751 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +0000752 {
753 *q++=(double) (QuantumScale*GetPixelRed(image,p));
754 *q++=(double) (QuantumScale*GetPixelGreen(image,p));
755 *q++=(double) (QuantumScale*GetPixelBlue(image,p));
756 *q++=0.0;
757 p+=GetPixelChannels(image);
758 }
759 }
760 return;
761 }
cristy14d71292012-05-20 16:48:13 +0000762 length=strlen(map);
cristycafe0412012-01-10 13:29:58 +0000763 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +0000764 {
cristycafe0412012-01-10 13:29:58 +0000765 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +0000766 if (p == (const Quantum *) NULL)
767 break;
cristycafe0412012-01-10 13:29:58 +0000768 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +0000769 {
770 register ssize_t
771 i;
772
cristy14d71292012-05-20 16:48:13 +0000773 for (i=0; i < (ssize_t) length; i++)
cristye5370942012-01-06 03:49:31 +0000774 {
775 *q=0;
776 switch (quantum_map[i])
777 {
778 case RedQuantum:
779 case CyanQuantum:
780 {
781 *q=(double) (QuantumScale*GetPixelRed(image,p));
782 break;
783 }
784 case GreenQuantum:
785 case MagentaQuantum:
786 {
787 *q=(double) (QuantumScale*GetPixelGreen(image,p));
788 break;
789 }
790 case BlueQuantum:
791 case YellowQuantum:
792 {
793 *q=(double) (QuantumScale*GetPixelBlue(image,p));
794 break;
795 }
796 case AlphaQuantum:
797 {
798 *q=(double) (QuantumScale*GetPixelAlpha(image,p));
799 break;
800 }
801 case OpacityQuantum:
802 {
803 *q=(double) (QuantumScale*GetPixelAlpha(image,p));
804 break;
805 }
806 case BlackQuantum:
807 {
808 if (image->colorspace == CMYKColorspace)
809 *q=(double) (QuantumScale*
810 GetPixelBlack(image,p));
811 break;
812 }
813 case IndexQuantum:
814 {
815 *q=(double) (QuantumScale*GetPixelIntensity(image,p));
816 break;
817 }
818 default:
819 *q=0;
820 }
821 q++;
822 }
823 p+=GetPixelChannels(image);
824 }
825 }
826}
827
cristy2dc655d2012-07-05 13:16:28 +0000828static void ExportFloatPixel(Image *image,const RectangleInfo *roi,
cristy46f4be22012-01-07 00:26:39 +0000829 const char *restrict map,const QuantumType *quantum_map,void *pixels,
830 ExceptionInfo *exception)
cristye5370942012-01-06 03:49:31 +0000831{
832 register const Quantum
833 *restrict p;
834
835 register float
cristy3fe11452012-01-09 01:27:42 +0000836 *restrict q;
cristye5370942012-01-06 03:49:31 +0000837
838 register ssize_t
839 x;
840
cristy14d71292012-05-20 16:48:13 +0000841 size_t
842 length;
843
cristye5370942012-01-06 03:49:31 +0000844 ssize_t
845 y;
846
847 q=(float *) pixels;
848 if (LocaleCompare(map,"BGR") == 0)
849 {
cristycafe0412012-01-10 13:29:58 +0000850 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +0000851 {
cristycafe0412012-01-10 13:29:58 +0000852 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +0000853 if (p == (const Quantum *) NULL)
854 break;
cristycafe0412012-01-10 13:29:58 +0000855 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +0000856 {
857 *q++=(float) (QuantumScale*GetPixelBlue(image,p));
858 *q++=(float) (QuantumScale*GetPixelGreen(image,p));
859 *q++=(float) (QuantumScale*GetPixelRed(image,p));
860 p+=GetPixelChannels(image);
861 }
862 }
863 return;
864 }
865 if (LocaleCompare(map,"BGRA") == 0)
866 {
cristycafe0412012-01-10 13:29:58 +0000867 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +0000868 {
cristycafe0412012-01-10 13:29:58 +0000869 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +0000870 if (p == (const Quantum *) NULL)
871 break;
cristycafe0412012-01-10 13:29:58 +0000872 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +0000873 {
874 *q++=(float) (QuantumScale*GetPixelBlue(image,p));
875 *q++=(float) (QuantumScale*GetPixelGreen(image,p));
876 *q++=(float) (QuantumScale*GetPixelRed(image,p));
877 *q++=(float) (QuantumScale*GetPixelAlpha(image,p));
878 p+=GetPixelChannels(image);
879 }
880 }
881 return;
882 }
883 if (LocaleCompare(map,"BGRP") == 0)
884 {
cristycafe0412012-01-10 13:29:58 +0000885 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +0000886 {
cristycafe0412012-01-10 13:29:58 +0000887 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +0000888 if (p == (const Quantum *) NULL)
889 break;
cristycafe0412012-01-10 13:29:58 +0000890 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +0000891 {
892 *q++=(float) (QuantumScale*GetPixelBlue(image,p));
893 *q++=(float) (QuantumScale*GetPixelGreen(image,p));
894 *q++=(float) (QuantumScale*GetPixelRed(image,p));
895 *q++=0.0;
896 p+=GetPixelChannels(image);
897 }
898 }
899 return;
900 }
901 if (LocaleCompare(map,"I") == 0)
902 {
cristycafe0412012-01-10 13:29:58 +0000903 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +0000904 {
cristycafe0412012-01-10 13:29:58 +0000905 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +0000906 if (p == (const Quantum *) NULL)
907 break;
cristycafe0412012-01-10 13:29:58 +0000908 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +0000909 {
910 *q++=(float) (QuantumScale*GetPixelIntensity(image,p));
911 p+=GetPixelChannels(image);
912 }
913 }
914 return;
915 }
916 if (LocaleCompare(map,"RGB") == 0)
917 {
cristycafe0412012-01-10 13:29:58 +0000918 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +0000919 {
cristycafe0412012-01-10 13:29:58 +0000920 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +0000921 if (p == (const Quantum *) NULL)
922 break;
cristycafe0412012-01-10 13:29:58 +0000923 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +0000924 {
925 *q++=(float) (QuantumScale*GetPixelRed(image,p));
926 *q++=(float) (QuantumScale*GetPixelGreen(image,p));
927 *q++=(float) (QuantumScale*GetPixelBlue(image,p));
928 p+=GetPixelChannels(image);
929 }
930 }
931 return;
932 }
933 if (LocaleCompare(map,"RGBA") == 0)
934 {
cristycafe0412012-01-10 13:29:58 +0000935 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +0000936 {
cristycafe0412012-01-10 13:29:58 +0000937 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +0000938 if (p == (const Quantum *) NULL)
939 break;
cristycafe0412012-01-10 13:29:58 +0000940 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +0000941 {
942 *q++=(float) (QuantumScale*GetPixelRed(image,p));
943 *q++=(float) (QuantumScale*GetPixelGreen(image,p));
944 *q++=(float) (QuantumScale*GetPixelBlue(image,p));
945 *q++=(float) (QuantumScale*GetPixelAlpha(image,p));
946 p+=GetPixelChannels(image);
947 }
948 }
949 return;
950 }
951 if (LocaleCompare(map,"RGBP") == 0)
952 {
cristycafe0412012-01-10 13:29:58 +0000953 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +0000954 {
cristycafe0412012-01-10 13:29:58 +0000955 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +0000956 if (p == (const Quantum *) NULL)
957 break;
cristycafe0412012-01-10 13:29:58 +0000958 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +0000959 {
960 *q++=(float) (QuantumScale*GetPixelRed(image,p));
961 *q++=(float) (QuantumScale*GetPixelGreen(image,p));
962 *q++=(float) (QuantumScale*GetPixelBlue(image,p));
963 *q++=0.0;
964 p+=GetPixelChannels(image);
965 }
966 }
967 return;
968 }
cristy14d71292012-05-20 16:48:13 +0000969 length=strlen(map);
cristycafe0412012-01-10 13:29:58 +0000970 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +0000971 {
cristycafe0412012-01-10 13:29:58 +0000972 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +0000973 if (p == (const Quantum *) NULL)
974 break;
cristycafe0412012-01-10 13:29:58 +0000975 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +0000976 {
977 register ssize_t
978 i;
979
cristy14d71292012-05-20 16:48:13 +0000980 for (i=0; i < (ssize_t) length; i++)
cristye5370942012-01-06 03:49:31 +0000981 {
982 *q=0;
983 switch (quantum_map[i])
984 {
985 case RedQuantum:
986 case CyanQuantum:
987 {
988 *q=(float) (QuantumScale*GetPixelRed(image,p));
989 break;
990 }
991 case GreenQuantum:
992 case MagentaQuantum:
993 {
994 *q=(float) (QuantumScale*GetPixelGreen(image,p));
995 break;
996 }
997 case BlueQuantum:
998 case YellowQuantum:
999 {
1000 *q=(float) (QuantumScale*GetPixelBlue(image,p));
1001 break;
1002 }
1003 case AlphaQuantum:
1004 {
1005 *q=(float) (QuantumScale*((Quantum) (GetPixelAlpha(image,p))));
1006 break;
1007 }
1008 case OpacityQuantum:
1009 {
1010 *q=(float) (QuantumScale*GetPixelAlpha(image,p));
1011 break;
1012 }
1013 case BlackQuantum:
1014 {
1015 if (image->colorspace == CMYKColorspace)
1016 *q=(float) (QuantumScale* GetPixelBlack(image,p));
1017 break;
1018 }
1019 case IndexQuantum:
1020 {
1021 *q=(float) (QuantumScale*GetPixelIntensity(image,p));
1022 break;
1023 }
1024 default:
1025 *q=0;
1026 }
1027 q++;
1028 }
1029 p+=GetPixelChannels(image);
1030 }
1031 }
1032}
1033
cristy2dc655d2012-07-05 13:16:28 +00001034static void ExportLongPixel(Image *image,const RectangleInfo *roi,
cristy46f4be22012-01-07 00:26:39 +00001035 const char *restrict map,const QuantumType *quantum_map,void *pixels,
1036 ExceptionInfo *exception)
cristye5370942012-01-06 03:49:31 +00001037{
1038 register const Quantum
1039 *restrict p;
1040
1041 register ssize_t
1042 x;
1043
1044 register unsigned int
cristy3fe11452012-01-09 01:27:42 +00001045 *restrict q;
cristye5370942012-01-06 03:49:31 +00001046
cristy14d71292012-05-20 16:48:13 +00001047 size_t
1048 length;
1049
cristye5370942012-01-06 03:49:31 +00001050 ssize_t
1051 y;
1052
1053 q=(unsigned int *) pixels;
1054 if (LocaleCompare(map,"BGR") == 0)
1055 {
cristycafe0412012-01-10 13:29:58 +00001056 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00001057 {
cristycafe0412012-01-10 13:29:58 +00001058 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00001059 if (p == (const Quantum *) NULL)
1060 break;
cristycafe0412012-01-10 13:29:58 +00001061 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00001062 {
cristy6c9e1682012-01-07 21:37:44 +00001063 *q++=ScaleQuantumToLong(GetPixelBlue(image,p));
1064 *q++=ScaleQuantumToLong(GetPixelGreen(image,p));
1065 *q++=ScaleQuantumToLong(GetPixelRed(image,p));
cristye5370942012-01-06 03:49:31 +00001066 p+=GetPixelChannels(image);
1067 }
1068 }
1069 return;
1070 }
1071 if (LocaleCompare(map,"BGRA") == 0)
1072 {
cristycafe0412012-01-10 13:29:58 +00001073 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00001074 {
cristycafe0412012-01-10 13:29:58 +00001075 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00001076 if (p == (const Quantum *) NULL)
1077 break;
cristycafe0412012-01-10 13:29:58 +00001078 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00001079 {
cristy6c9e1682012-01-07 21:37:44 +00001080 *q++=ScaleQuantumToLong(GetPixelBlue(image,p));
1081 *q++=ScaleQuantumToLong(GetPixelGreen(image,p));
1082 *q++=ScaleQuantumToLong(GetPixelRed(image,p));
1083 *q++=ScaleQuantumToLong(GetPixelAlpha(image,p));
cristye5370942012-01-06 03:49:31 +00001084 p+=GetPixelChannels(image);
1085 }
1086 }
1087 return;
1088 }
1089 if (LocaleCompare(map,"BGRP") == 0)
1090 {
cristycafe0412012-01-10 13:29:58 +00001091 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00001092 {
cristycafe0412012-01-10 13:29:58 +00001093 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00001094 if (p == (const Quantum *) NULL)
1095 break;
cristycafe0412012-01-10 13:29:58 +00001096 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00001097 {
cristy6c9e1682012-01-07 21:37:44 +00001098 *q++=ScaleQuantumToLong(GetPixelBlue(image,p));
1099 *q++=ScaleQuantumToLong(GetPixelGreen(image,p));
1100 *q++=ScaleQuantumToLong(GetPixelRed(image,p));
1101 *q++=0;
cristye5370942012-01-06 03:49:31 +00001102 p+=GetPixelChannels(image);
1103 }
1104 }
1105 return;
1106 }
1107 if (LocaleCompare(map,"I") == 0)
1108 {
cristycafe0412012-01-10 13:29:58 +00001109 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00001110 {
cristycafe0412012-01-10 13:29:58 +00001111 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00001112 if (p == (const Quantum *) NULL)
1113 break;
cristycafe0412012-01-10 13:29:58 +00001114 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00001115 {
cristy70e9f682013-03-12 22:31:22 +00001116 *q++=ScaleQuantumToLong(ClampToQuantum(GetPixelIntensity(image,p)));
cristye5370942012-01-06 03:49:31 +00001117 p+=GetPixelChannels(image);
1118 }
1119 }
1120 return;
1121 }
1122 if (LocaleCompare(map,"RGB") == 0)
1123 {
cristycafe0412012-01-10 13:29:58 +00001124 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00001125 {
cristycafe0412012-01-10 13:29:58 +00001126 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00001127 if (p == (const Quantum *) NULL)
1128 break;
cristycafe0412012-01-10 13:29:58 +00001129 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00001130 {
cristy6c9e1682012-01-07 21:37:44 +00001131 *q++=ScaleQuantumToLong(GetPixelRed(image,p));
1132 *q++=ScaleQuantumToLong(GetPixelGreen(image,p));
1133 *q++=ScaleQuantumToLong(GetPixelBlue(image,p));
cristye5370942012-01-06 03:49:31 +00001134 p+=GetPixelChannels(image);
1135 }
1136 }
1137 return;
1138 }
1139 if (LocaleCompare(map,"RGBA") == 0)
1140 {
cristycafe0412012-01-10 13:29:58 +00001141 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00001142 {
cristycafe0412012-01-10 13:29:58 +00001143 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00001144 if (p == (const Quantum *) NULL)
1145 break;
cristycafe0412012-01-10 13:29:58 +00001146 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00001147 {
cristy6c9e1682012-01-07 21:37:44 +00001148 *q++=ScaleQuantumToLong(GetPixelRed(image,p));
1149 *q++=ScaleQuantumToLong(GetPixelGreen(image,p));
1150 *q++=ScaleQuantumToLong(GetPixelBlue(image,p));
1151 *q++=ScaleQuantumToLong(GetPixelAlpha(image,p));
cristye5370942012-01-06 03:49:31 +00001152 p+=GetPixelChannels(image);
1153 }
1154 }
1155 return;
1156 }
1157 if (LocaleCompare(map,"RGBP") == 0)
1158 {
cristycafe0412012-01-10 13:29:58 +00001159 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00001160 {
cristycafe0412012-01-10 13:29:58 +00001161 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00001162 if (p == (const Quantum *) NULL)
1163 break;
cristycafe0412012-01-10 13:29:58 +00001164 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00001165 {
cristy6c9e1682012-01-07 21:37:44 +00001166 *q++=ScaleQuantumToLong(GetPixelRed(image,p));
1167 *q++=ScaleQuantumToLong(GetPixelGreen(image,p));
1168 *q++=ScaleQuantumToLong(GetPixelBlue(image,p));
1169 *q++=0;
cristye5370942012-01-06 03:49:31 +00001170 p+=GetPixelChannels(image);
1171 }
1172 }
1173 return;
1174 }
cristy14d71292012-05-20 16:48:13 +00001175 length=strlen(map);
cristycafe0412012-01-10 13:29:58 +00001176 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00001177 {
cristycafe0412012-01-10 13:29:58 +00001178 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00001179 if (p == (const Quantum *) NULL)
1180 break;
cristycafe0412012-01-10 13:29:58 +00001181 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00001182 {
1183 register ssize_t
1184 i;
1185
cristy14d71292012-05-20 16:48:13 +00001186 for (i=0; i < (ssize_t) length; i++)
cristye5370942012-01-06 03:49:31 +00001187 {
1188 *q=0;
1189 switch (quantum_map[i])
1190 {
1191 case RedQuantum:
1192 case CyanQuantum:
1193 {
cristy6c9e1682012-01-07 21:37:44 +00001194 *q=ScaleQuantumToLong(GetPixelRed(image,p));
cristye5370942012-01-06 03:49:31 +00001195 break;
1196 }
1197 case GreenQuantum:
1198 case MagentaQuantum:
1199 {
cristy6c9e1682012-01-07 21:37:44 +00001200 *q=ScaleQuantumToLong(GetPixelGreen(image,p));
cristye5370942012-01-06 03:49:31 +00001201 break;
1202 }
1203 case BlueQuantum:
1204 case YellowQuantum:
1205 {
cristy6c9e1682012-01-07 21:37:44 +00001206 *q=ScaleQuantumToLong(GetPixelBlue(image,p));
cristye5370942012-01-06 03:49:31 +00001207 break;
1208 }
1209 case AlphaQuantum:
1210 {
cristy6c9e1682012-01-07 21:37:44 +00001211 *q=ScaleQuantumToLong(GetPixelAlpha(image,p));
cristye5370942012-01-06 03:49:31 +00001212 break;
1213 }
1214 case OpacityQuantum:
1215 {
cristy6c9e1682012-01-07 21:37:44 +00001216 *q=ScaleQuantumToLong(GetPixelAlpha(image,p));
cristye5370942012-01-06 03:49:31 +00001217 break;
1218 }
1219 case BlackQuantum:
1220 {
1221 if (image->colorspace == CMYKColorspace)
cristy6c9e1682012-01-07 21:37:44 +00001222 *q=ScaleQuantumToLong(GetPixelBlack(image,p));
cristye5370942012-01-06 03:49:31 +00001223 break;
1224 }
1225 case IndexQuantum:
1226 {
cristy70e9f682013-03-12 22:31:22 +00001227 *q=ScaleQuantumToLong(ClampToQuantum(GetPixelIntensity(image,p)));
cristye5370942012-01-06 03:49:31 +00001228 break;
1229 }
1230 default:
cristy6c9e1682012-01-07 21:37:44 +00001231 break;
cristye5370942012-01-06 03:49:31 +00001232 }
1233 q++;
1234 }
1235 p+=GetPixelChannels(image);
1236 }
1237 }
1238}
1239
cristy2dc655d2012-07-05 13:16:28 +00001240static void ExportLongLongPixel(Image *image,const RectangleInfo *roi,
cristy46f4be22012-01-07 00:26:39 +00001241 const char *restrict map,const QuantumType *quantum_map,void *pixels,
1242 ExceptionInfo *exception)
cristye5370942012-01-06 03:49:31 +00001243{
1244 register const Quantum
1245 *restrict p;
1246
1247 register ssize_t
1248 x;
1249
cristyb13e12a2012-01-06 21:48:27 +00001250 register MagickSizeType
cristy3fe11452012-01-09 01:27:42 +00001251 *restrict q;
cristye5370942012-01-06 03:49:31 +00001252
cristy14d71292012-05-20 16:48:13 +00001253 size_t
1254 length;
1255
cristye5370942012-01-06 03:49:31 +00001256 ssize_t
1257 y;
1258
cristyb13e12a2012-01-06 21:48:27 +00001259 q=(MagickSizeType *) pixels;
cristye5370942012-01-06 03:49:31 +00001260 if (LocaleCompare(map,"BGR") == 0)
1261 {
cristycafe0412012-01-10 13:29:58 +00001262 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00001263 {
cristycafe0412012-01-10 13:29:58 +00001264 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00001265 if (p == (const Quantum *) NULL)
1266 break;
cristycafe0412012-01-10 13:29:58 +00001267 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00001268 {
cristyb13e12a2012-01-06 21:48:27 +00001269 *q++=ScaleQuantumToLongLong(GetPixelBlue(image,p));
1270 *q++=ScaleQuantumToLongLong(GetPixelGreen(image,p));
1271 *q++=ScaleQuantumToLongLong(GetPixelRed(image,p));
cristye5370942012-01-06 03:49:31 +00001272 p+=GetPixelChannels(image);
1273 }
1274 }
1275 return;
1276 }
1277 if (LocaleCompare(map,"BGRA") == 0)
1278 {
cristycafe0412012-01-10 13:29:58 +00001279 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00001280 {
cristycafe0412012-01-10 13:29:58 +00001281 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00001282 if (p == (const Quantum *) NULL)
1283 break;
cristycafe0412012-01-10 13:29:58 +00001284 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00001285 {
cristyb13e12a2012-01-06 21:48:27 +00001286 *q++=ScaleQuantumToLongLong(GetPixelBlue(image,p));
1287 *q++=ScaleQuantumToLongLong(GetPixelGreen(image,p));
1288 *q++=ScaleQuantumToLongLong(GetPixelRed(image,p));
1289 *q++=ScaleQuantumToLongLong(GetPixelAlpha(image,p));
cristye5370942012-01-06 03:49:31 +00001290 p+=GetPixelChannels(image);
1291 }
1292 }
1293 return;
1294 }
1295 if (LocaleCompare(map,"BGRP") == 0)
1296 {
cristycafe0412012-01-10 13:29:58 +00001297 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00001298 {
cristycafe0412012-01-10 13:29:58 +00001299 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00001300 if (p == (const Quantum *) NULL)
1301 break;
cristycafe0412012-01-10 13:29:58 +00001302 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00001303 {
cristyb13e12a2012-01-06 21:48:27 +00001304 *q++=ScaleQuantumToLongLong(GetPixelBlue(image,p));
1305 *q++=ScaleQuantumToLongLong(GetPixelGreen(image,p));
1306 *q++=ScaleQuantumToLongLong(GetPixelRed(image,p));
cristye5370942012-01-06 03:49:31 +00001307 *q++=0;
1308 p+=GetPixelChannels(image);
1309 }
1310 }
1311 return;
1312 }
1313 if (LocaleCompare(map,"I") == 0)
1314 {
cristycafe0412012-01-10 13:29:58 +00001315 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00001316 {
cristycafe0412012-01-10 13:29:58 +00001317 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00001318 if (p == (const Quantum *) NULL)
1319 break;
cristycafe0412012-01-10 13:29:58 +00001320 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00001321 {
cristy70e9f682013-03-12 22:31:22 +00001322 *q++=ScaleQuantumToLongLong(ClampToQuantum(GetPixelIntensity(image,p)));
cristye5370942012-01-06 03:49:31 +00001323 p+=GetPixelChannels(image);
1324 }
1325 }
1326 return;
1327 }
1328 if (LocaleCompare(map,"RGB") == 0)
1329 {
cristycafe0412012-01-10 13:29:58 +00001330 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00001331 {
cristycafe0412012-01-10 13:29:58 +00001332 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00001333 if (p == (const Quantum *) NULL)
1334 break;
cristycafe0412012-01-10 13:29:58 +00001335 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00001336 {
cristyb13e12a2012-01-06 21:48:27 +00001337 *q++=ScaleQuantumToLongLong(GetPixelRed(image,p));
1338 *q++=ScaleQuantumToLongLong(GetPixelGreen(image,p));
1339 *q++=ScaleQuantumToLongLong(GetPixelBlue(image,p));
cristye5370942012-01-06 03:49:31 +00001340 p+=GetPixelChannels(image);
1341 }
1342 }
1343 return;
1344 }
1345 if (LocaleCompare(map,"RGBA") == 0)
1346 {
cristycafe0412012-01-10 13:29:58 +00001347 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00001348 {
cristycafe0412012-01-10 13:29:58 +00001349 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00001350 if (p == (const Quantum *) NULL)
1351 break;
cristycafe0412012-01-10 13:29:58 +00001352 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00001353 {
cristyb13e12a2012-01-06 21:48:27 +00001354 *q++=ScaleQuantumToLongLong(GetPixelRed(image,p));
1355 *q++=ScaleQuantumToLongLong(GetPixelGreen(image,p));
1356 *q++=ScaleQuantumToLongLong(GetPixelBlue(image,p));
1357 *q++=ScaleQuantumToLongLong(GetPixelAlpha(image,p));
cristye5370942012-01-06 03:49:31 +00001358 p+=GetPixelChannels(image);
1359 }
1360 }
1361 return;
1362 }
1363 if (LocaleCompare(map,"RGBP") == 0)
1364 {
cristycafe0412012-01-10 13:29:58 +00001365 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00001366 {
cristycafe0412012-01-10 13:29:58 +00001367 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00001368 if (p == (const Quantum *) NULL)
1369 break;
cristycafe0412012-01-10 13:29:58 +00001370 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00001371 {
cristyb13e12a2012-01-06 21:48:27 +00001372 *q++=ScaleQuantumToLongLong(GetPixelRed(image,p));
1373 *q++=ScaleQuantumToLongLong(GetPixelGreen(image,p));
1374 *q++=ScaleQuantumToLongLong(GetPixelBlue(image,p));
cristye5370942012-01-06 03:49:31 +00001375 *q++=0;
1376 p+=GetPixelChannels(image);
1377 }
1378 }
1379 return;
1380 }
cristy14d71292012-05-20 16:48:13 +00001381 length=strlen(map);
cristycafe0412012-01-10 13:29:58 +00001382 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00001383 {
cristycafe0412012-01-10 13:29:58 +00001384 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00001385 if (p == (const Quantum *) NULL)
1386 break;
cristycafe0412012-01-10 13:29:58 +00001387 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00001388 {
1389 register ssize_t
1390 i;
1391
cristy14d71292012-05-20 16:48:13 +00001392 for (i=0; i < (ssize_t) length; i++)
cristye5370942012-01-06 03:49:31 +00001393 {
1394 *q=0;
1395 switch (quantum_map[i])
1396 {
1397 case RedQuantum:
1398 case CyanQuantum:
1399 {
cristyb13e12a2012-01-06 21:48:27 +00001400 *q=ScaleQuantumToLongLong(GetPixelRed(image,p));
cristye5370942012-01-06 03:49:31 +00001401 break;
1402 }
1403 case GreenQuantum:
1404 case MagentaQuantum:
1405 {
cristyb13e12a2012-01-06 21:48:27 +00001406 *q=ScaleQuantumToLongLong(GetPixelGreen(image,p));
cristye5370942012-01-06 03:49:31 +00001407 break;
1408 }
1409 case BlueQuantum:
1410 case YellowQuantum:
1411 {
cristyb13e12a2012-01-06 21:48:27 +00001412 *q=ScaleQuantumToLongLong(GetPixelBlue(image,p));
cristye5370942012-01-06 03:49:31 +00001413 break;
1414 }
1415 case AlphaQuantum:
1416 {
cristyb13e12a2012-01-06 21:48:27 +00001417 *q=ScaleQuantumToLongLong(GetPixelAlpha(image,p));
cristye5370942012-01-06 03:49:31 +00001418 break;
1419 }
1420 case OpacityQuantum:
1421 {
cristyb13e12a2012-01-06 21:48:27 +00001422 *q=ScaleQuantumToLongLong(GetPixelAlpha(image,p));
cristye5370942012-01-06 03:49:31 +00001423 break;
1424 }
1425 case BlackQuantum:
1426 {
1427 if (image->colorspace == CMYKColorspace)
cristyb13e12a2012-01-06 21:48:27 +00001428 *q=ScaleQuantumToLongLong(GetPixelBlack(image,p));
cristye5370942012-01-06 03:49:31 +00001429 break;
1430 }
1431 case IndexQuantum:
1432 {
cristy70e9f682013-03-12 22:31:22 +00001433 *q=ScaleQuantumToLongLong(ClampToQuantum(GetPixelIntensity(image,p)));
cristye5370942012-01-06 03:49:31 +00001434 break;
1435 }
1436 default:
1437 break;
1438 }
1439 q++;
1440 }
1441 p+=GetPixelChannels(image);
1442 }
1443 }
1444}
1445
cristy2dc655d2012-07-05 13:16:28 +00001446static void ExportQuantumPixel(Image *image,const RectangleInfo *roi,
cristy46f4be22012-01-07 00:26:39 +00001447 const char *restrict map,const QuantumType *quantum_map,void *pixels,
1448 ExceptionInfo *exception)
cristye5370942012-01-06 03:49:31 +00001449{
1450 register const Quantum
1451 *restrict p;
1452
1453 register Quantum
cristy3fe11452012-01-09 01:27:42 +00001454 *restrict q;
cristye5370942012-01-06 03:49:31 +00001455
1456 register ssize_t
1457 x;
1458
cristy14d71292012-05-20 16:48:13 +00001459 size_t
1460 length;
1461
cristye5370942012-01-06 03:49:31 +00001462 ssize_t
1463 y;
1464
1465 q=(Quantum *) pixels;
1466 if (LocaleCompare(map,"BGR") == 0)
1467 {
cristycafe0412012-01-10 13:29:58 +00001468 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00001469 {
cristycafe0412012-01-10 13:29:58 +00001470 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00001471 if (p == (const Quantum *) NULL)
1472 break;
cristycafe0412012-01-10 13:29:58 +00001473 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00001474 {
1475 *q++=GetPixelBlue(image,p);
1476 *q++=GetPixelGreen(image,p);
1477 *q++=GetPixelRed(image,p);
1478 p+=GetPixelChannels(image);
1479 }
1480 }
1481 return;
1482 }
1483 if (LocaleCompare(map,"BGRA") == 0)
1484 {
cristycafe0412012-01-10 13:29:58 +00001485 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00001486 {
cristycafe0412012-01-10 13:29:58 +00001487 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00001488 if (p == (const Quantum *) NULL)
1489 break;
cristycafe0412012-01-10 13:29:58 +00001490 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00001491 {
1492 *q++=GetPixelBlue(image,p);
1493 *q++=GetPixelGreen(image,p);
1494 *q++=GetPixelRed(image,p);
1495 *q++=(Quantum) (GetPixelAlpha(image,p));
1496 p+=GetPixelChannels(image);
1497 }
1498 }
1499 return;
1500 }
1501 if (LocaleCompare(map,"BGRP") == 0)
1502 {
cristycafe0412012-01-10 13:29:58 +00001503 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00001504 {
cristycafe0412012-01-10 13:29:58 +00001505 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00001506 if (p == (const Quantum *) NULL)
1507 break;
cristycafe0412012-01-10 13:29:58 +00001508 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00001509 {
1510 *q++=GetPixelBlue(image,p);
1511 *q++=GetPixelGreen(image,p);
1512 *q++=GetPixelRed(image,p);
1513 *q++=(Quantum) 0;
1514 p+=GetPixelChannels(image);
1515 }
1516 }
1517 return;
1518 }
1519 if (LocaleCompare(map,"I") == 0)
1520 {
cristycafe0412012-01-10 13:29:58 +00001521 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00001522 {
cristycafe0412012-01-10 13:29:58 +00001523 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00001524 if (p == (const Quantum *) NULL)
1525 break;
cristycafe0412012-01-10 13:29:58 +00001526 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00001527 {
cristy70e9f682013-03-12 22:31:22 +00001528 *q++=ClampToQuantum(GetPixelIntensity(image,p));
cristye5370942012-01-06 03:49:31 +00001529 p+=GetPixelChannels(image);
1530 }
1531 }
1532 return;
1533 }
1534 if (LocaleCompare(map,"RGB") == 0)
1535 {
cristycafe0412012-01-10 13:29:58 +00001536 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00001537 {
cristycafe0412012-01-10 13:29:58 +00001538 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00001539 if (p == (const Quantum *) NULL)
1540 break;
cristycafe0412012-01-10 13:29:58 +00001541 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00001542 {
1543 *q++=GetPixelRed(image,p);
1544 *q++=GetPixelGreen(image,p);
1545 *q++=GetPixelBlue(image,p);
1546 p+=GetPixelChannels(image);
1547 }
1548 }
1549 return;
1550 }
1551 if (LocaleCompare(map,"RGBA") == 0)
1552 {
cristycafe0412012-01-10 13:29:58 +00001553 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00001554 {
cristycafe0412012-01-10 13:29:58 +00001555 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00001556 if (p == (const Quantum *) NULL)
1557 break;
cristycafe0412012-01-10 13:29:58 +00001558 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00001559 {
1560 *q++=GetPixelRed(image,p);
1561 *q++=GetPixelGreen(image,p);
1562 *q++=GetPixelBlue(image,p);
1563 *q++=(Quantum) (GetPixelAlpha(image,p));
1564 p+=GetPixelChannels(image);
1565 }
1566 }
1567 return;
1568 }
1569 if (LocaleCompare(map,"RGBP") == 0)
1570 {
cristycafe0412012-01-10 13:29:58 +00001571 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00001572 {
cristycafe0412012-01-10 13:29:58 +00001573 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00001574 if (p == (const Quantum *) NULL)
1575 break;
cristycafe0412012-01-10 13:29:58 +00001576 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00001577 {
1578 *q++=GetPixelRed(image,p);
1579 *q++=GetPixelGreen(image,p);
1580 *q++=GetPixelBlue(image,p);
1581 *q++=(Quantum) 0;
1582 p+=GetPixelChannels(image);
1583 }
1584 }
1585 return;
1586 }
cristy14d71292012-05-20 16:48:13 +00001587 length=strlen(map);
cristycafe0412012-01-10 13:29:58 +00001588 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00001589 {
cristycafe0412012-01-10 13:29:58 +00001590 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00001591 if (p == (const Quantum *) NULL)
1592 break;
cristycafe0412012-01-10 13:29:58 +00001593 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00001594 {
1595 register ssize_t
1596 i;
1597
cristy14d71292012-05-20 16:48:13 +00001598 for (i=0; i < (ssize_t) length; i++)
cristye5370942012-01-06 03:49:31 +00001599 {
1600 *q=(Quantum) 0;
1601 switch (quantum_map[i])
1602 {
1603 case RedQuantum:
1604 case CyanQuantum:
1605 {
1606 *q=GetPixelRed(image,p);
1607 break;
1608 }
1609 case GreenQuantum:
1610 case MagentaQuantum:
1611 {
1612 *q=GetPixelGreen(image,p);
1613 break;
1614 }
1615 case BlueQuantum:
1616 case YellowQuantum:
1617 {
1618 *q=GetPixelBlue(image,p);
1619 break;
1620 }
1621 case AlphaQuantum:
1622 {
1623 *q=GetPixelAlpha(image,p);
1624 break;
1625 }
1626 case OpacityQuantum:
1627 {
1628 *q=GetPixelAlpha(image,p);
1629 break;
1630 }
1631 case BlackQuantum:
1632 {
1633 if (image->colorspace == CMYKColorspace)
1634 *q=GetPixelBlack(image,p);
1635 break;
1636 }
1637 case IndexQuantum:
1638 {
cristy70e9f682013-03-12 22:31:22 +00001639 *q=ClampToQuantum(GetPixelIntensity(image,p));
cristye5370942012-01-06 03:49:31 +00001640 break;
1641 }
1642 default:
1643 {
1644 *q=(Quantum) 0;
1645 break;
1646 }
1647 }
1648 q++;
1649 }
1650 p+=GetPixelChannels(image);
1651 }
1652 }
1653}
1654
cristy2dc655d2012-07-05 13:16:28 +00001655static void ExportShortPixel(Image *image,const RectangleInfo *roi,
cristy46f4be22012-01-07 00:26:39 +00001656 const char *restrict map,const QuantumType *quantum_map,void *pixels,
1657 ExceptionInfo *exception)
cristye5370942012-01-06 03:49:31 +00001658{
1659 register const Quantum
1660 *restrict p;
1661
1662 register ssize_t
1663 x;
1664
cristye5370942012-01-06 03:49:31 +00001665 register unsigned short
cristy3fe11452012-01-09 01:27:42 +00001666 *restrict q;
cristye5370942012-01-06 03:49:31 +00001667
cristy14d71292012-05-20 16:48:13 +00001668 size_t
1669 length;
1670
1671 ssize_t
1672 y;
1673
cristye5370942012-01-06 03:49:31 +00001674 q=(unsigned short *) pixels;
1675 if (LocaleCompare(map,"BGR") == 0)
1676 {
cristycafe0412012-01-10 13:29:58 +00001677 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00001678 {
cristycafe0412012-01-10 13:29:58 +00001679 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00001680 if (p == (const Quantum *) NULL)
1681 break;
cristycafe0412012-01-10 13:29:58 +00001682 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00001683 {
1684 *q++=ScaleQuantumToShort(GetPixelBlue(image,p));
1685 *q++=ScaleQuantumToShort(GetPixelGreen(image,p));
1686 *q++=ScaleQuantumToShort(GetPixelRed(image,p));
1687 p+=GetPixelChannels(image);
1688 }
1689 }
1690 return;
1691 }
1692 if (LocaleCompare(map,"BGRA") == 0)
1693 {
cristycafe0412012-01-10 13:29:58 +00001694 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00001695 {
cristycafe0412012-01-10 13:29:58 +00001696 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00001697 if (p == (const Quantum *) NULL)
1698 break;
cristycafe0412012-01-10 13:29:58 +00001699 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00001700 {
1701 *q++=ScaleQuantumToShort(GetPixelBlue(image,p));
1702 *q++=ScaleQuantumToShort(GetPixelGreen(image,p));
1703 *q++=ScaleQuantumToShort(GetPixelRed(image,p));
1704 *q++=ScaleQuantumToShort(GetPixelAlpha(image,p));
1705 p+=GetPixelChannels(image);
1706 }
1707 }
1708 return;
1709 }
1710 if (LocaleCompare(map,"BGRP") == 0)
1711 {
cristycafe0412012-01-10 13:29:58 +00001712 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00001713 {
cristycafe0412012-01-10 13:29:58 +00001714 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00001715 if (p == (const Quantum *) NULL)
1716 break;
cristycafe0412012-01-10 13:29:58 +00001717 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00001718 {
1719 *q++=ScaleQuantumToShort(GetPixelBlue(image,p));
1720 *q++=ScaleQuantumToShort(GetPixelGreen(image,p));
1721 *q++=ScaleQuantumToShort(GetPixelRed(image,p));
1722 *q++=0;
1723 p+=GetPixelChannels(image);
1724 }
1725 }
1726 return;
1727 }
1728 if (LocaleCompare(map,"I") == 0)
1729 {
cristycafe0412012-01-10 13:29:58 +00001730 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00001731 {
cristycafe0412012-01-10 13:29:58 +00001732 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00001733 if (p == (const Quantum *) NULL)
1734 break;
cristycafe0412012-01-10 13:29:58 +00001735 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00001736 {
cristy70e9f682013-03-12 22:31:22 +00001737 *q++=ScaleQuantumToShort(ClampToQuantum(GetPixelIntensity(image,p)));
cristye5370942012-01-06 03:49:31 +00001738 p+=GetPixelChannels(image);
1739 }
1740 }
1741 return;
1742 }
1743 if (LocaleCompare(map,"RGB") == 0)
1744 {
cristycafe0412012-01-10 13:29:58 +00001745 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00001746 {
cristycafe0412012-01-10 13:29:58 +00001747 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00001748 if (p == (const Quantum *) NULL)
1749 break;
cristycafe0412012-01-10 13:29:58 +00001750 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00001751 {
1752 *q++=ScaleQuantumToShort(GetPixelRed(image,p));
1753 *q++=ScaleQuantumToShort(GetPixelGreen(image,p));
1754 *q++=ScaleQuantumToShort(GetPixelBlue(image,p));
1755 p+=GetPixelChannels(image);
1756 }
1757 }
1758 return;
1759 }
1760 if (LocaleCompare(map,"RGBA") == 0)
1761 {
cristycafe0412012-01-10 13:29:58 +00001762 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00001763 {
cristycafe0412012-01-10 13:29:58 +00001764 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00001765 if (p == (const Quantum *) NULL)
1766 break;
cristycafe0412012-01-10 13:29:58 +00001767 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00001768 {
1769 *q++=ScaleQuantumToShort(GetPixelRed(image,p));
1770 *q++=ScaleQuantumToShort(GetPixelGreen(image,p));
1771 *q++=ScaleQuantumToShort(GetPixelBlue(image,p));
1772 *q++=ScaleQuantumToShort(GetPixelAlpha(image,p));
1773 p+=GetPixelChannels(image);
1774 }
1775 }
1776 return;
1777 }
1778 if (LocaleCompare(map,"RGBP") == 0)
1779 {
cristycafe0412012-01-10 13:29:58 +00001780 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00001781 {
cristycafe0412012-01-10 13:29:58 +00001782 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00001783 if (p == (const Quantum *) NULL)
1784 break;
cristycafe0412012-01-10 13:29:58 +00001785 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00001786 {
1787 *q++=ScaleQuantumToShort(GetPixelRed(image,p));
1788 *q++=ScaleQuantumToShort(GetPixelGreen(image,p));
1789 *q++=ScaleQuantumToShort(GetPixelBlue(image,p));
1790 *q++=0;
1791 p+=GetPixelChannels(image);
1792 }
1793 }
1794 return;
1795 }
cristy14d71292012-05-20 16:48:13 +00001796 length=strlen(map);
cristycafe0412012-01-10 13:29:58 +00001797 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00001798 {
cristycafe0412012-01-10 13:29:58 +00001799 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00001800 if (p == (const Quantum *) NULL)
1801 break;
cristycafe0412012-01-10 13:29:58 +00001802 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00001803 {
1804 register ssize_t
1805 i;
1806
cristy14d71292012-05-20 16:48:13 +00001807 for (i=0; i < (ssize_t) length; i++)
cristye5370942012-01-06 03:49:31 +00001808 {
1809 *q=0;
1810 switch (quantum_map[i])
1811 {
1812 case RedQuantum:
1813 case CyanQuantum:
1814 {
1815 *q=ScaleQuantumToShort(GetPixelRed(image,p));
1816 break;
1817 }
1818 case GreenQuantum:
1819 case MagentaQuantum:
1820 {
1821 *q=ScaleQuantumToShort(GetPixelGreen(image,p));
1822 break;
1823 }
1824 case BlueQuantum:
1825 case YellowQuantum:
1826 {
1827 *q=ScaleQuantumToShort(GetPixelBlue(image,p));
1828 break;
1829 }
1830 case AlphaQuantum:
1831 {
1832 *q=ScaleQuantumToShort(GetPixelAlpha(image,p));
1833 break;
1834 }
1835 case OpacityQuantum:
1836 {
1837 *q=ScaleQuantumToShort(GetPixelAlpha(image,p));
1838 break;
1839 }
1840 case BlackQuantum:
1841 {
1842 if (image->colorspace == CMYKColorspace)
1843 *q=ScaleQuantumToShort(GetPixelBlack(image,p));
1844 break;
1845 }
1846 case IndexQuantum:
1847 {
cristy70e9f682013-03-12 22:31:22 +00001848 *q=ScaleQuantumToShort(ClampToQuantum(GetPixelIntensity(image,p)));
cristye5370942012-01-06 03:49:31 +00001849 break;
1850 }
1851 default:
1852 break;
1853 }
1854 q++;
1855 }
1856 p+=GetPixelChannels(image);
1857 }
1858 }
1859}
1860
cristy2dc655d2012-07-05 13:16:28 +00001861MagickExport MagickBooleanType ExportImagePixels(Image *image,
cristycafe0412012-01-10 13:29:58 +00001862 const ssize_t x,const ssize_t y,const size_t width,const size_t height,
1863 const char *map,const StorageType type,void *pixels,ExceptionInfo *exception)
cristy4c08aed2011-07-01 19:47:50 +00001864{
1865 QuantumType
1866 *quantum_map;
1867
cristycafe0412012-01-10 13:29:58 +00001868 RectangleInfo
1869 roi;
1870
cristy4c08aed2011-07-01 19:47:50 +00001871 register ssize_t
cristye5370942012-01-06 03:49:31 +00001872 i;
cristy4c08aed2011-07-01 19:47:50 +00001873
cristy14d71292012-05-20 16:48:13 +00001874 size_t
1875 length;
1876
cristy4c08aed2011-07-01 19:47:50 +00001877 assert(image != (Image *) NULL);
1878 assert(image->signature == MagickSignature);
1879 if (image->debug != MagickFalse)
1880 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
cristy14d71292012-05-20 16:48:13 +00001881 length=strlen(map);
1882 quantum_map=(QuantumType *) AcquireQuantumMemory(length,sizeof(*quantum_map));
cristy4c08aed2011-07-01 19:47:50 +00001883 if (quantum_map == (QuantumType *) NULL)
1884 {
1885 (void) ThrowMagickException(exception,GetMagickModule(),
cristyefe601c2013-01-05 17:51:12 +00001886 ResourceLimitError,"MemoryAllocationFailed","`%s'",image->filename);
cristy4c08aed2011-07-01 19:47:50 +00001887 return(MagickFalse);
1888 }
cristy14d71292012-05-20 16:48:13 +00001889 for (i=0; i < (ssize_t) length; i++)
cristy4c08aed2011-07-01 19:47:50 +00001890 {
1891 switch (map[i])
1892 {
1893 case 'A':
1894 case 'a':
1895 {
1896 quantum_map[i]=AlphaQuantum;
1897 break;
1898 }
1899 case 'B':
1900 case 'b':
1901 {
1902 quantum_map[i]=BlueQuantum;
1903 break;
1904 }
1905 case 'C':
1906 case 'c':
1907 {
1908 quantum_map[i]=CyanQuantum;
1909 if (image->colorspace == CMYKColorspace)
1910 break;
1911 quantum_map=(QuantumType *) RelinquishMagickMemory(quantum_map);
1912 (void) ThrowMagickException(exception,GetMagickModule(),ImageError,
cristyefe601c2013-01-05 17:51:12 +00001913 "ColorSeparatedImageRequired","`%s'",map);
cristy4c08aed2011-07-01 19:47:50 +00001914 return(MagickFalse);
1915 }
1916 case 'g':
1917 case 'G':
1918 {
1919 quantum_map[i]=GreenQuantum;
1920 break;
1921 }
1922 case 'I':
1923 case 'i':
1924 {
1925 quantum_map[i]=IndexQuantum;
1926 break;
1927 }
1928 case 'K':
1929 case 'k':
1930 {
1931 quantum_map[i]=BlackQuantum;
1932 if (image->colorspace == CMYKColorspace)
1933 break;
1934 quantum_map=(QuantumType *) RelinquishMagickMemory(quantum_map);
1935 (void) ThrowMagickException(exception,GetMagickModule(),ImageError,
cristyefe601c2013-01-05 17:51:12 +00001936 "ColorSeparatedImageRequired","`%s'",map);
cristy4c08aed2011-07-01 19:47:50 +00001937 return(MagickFalse);
1938 }
1939 case 'M':
1940 case 'm':
1941 {
1942 quantum_map[i]=MagentaQuantum;
1943 if (image->colorspace == CMYKColorspace)
1944 break;
1945 quantum_map=(QuantumType *) RelinquishMagickMemory(quantum_map);
1946 (void) ThrowMagickException(exception,GetMagickModule(),ImageError,
cristyefe601c2013-01-05 17:51:12 +00001947 "ColorSeparatedImageRequired","`%s'",map);
cristy4c08aed2011-07-01 19:47:50 +00001948 return(MagickFalse);
1949 }
1950 case 'o':
1951 case 'O':
1952 {
1953 quantum_map[i]=OpacityQuantum;
1954 break;
1955 }
1956 case 'P':
1957 case 'p':
1958 {
1959 quantum_map[i]=UndefinedQuantum;
1960 break;
1961 }
1962 case 'R':
1963 case 'r':
1964 {
1965 quantum_map[i]=RedQuantum;
1966 break;
1967 }
1968 case 'Y':
1969 case 'y':
1970 {
1971 quantum_map[i]=YellowQuantum;
1972 if (image->colorspace == CMYKColorspace)
1973 break;
1974 quantum_map=(QuantumType *) RelinquishMagickMemory(quantum_map);
1975 (void) ThrowMagickException(exception,GetMagickModule(),ImageError,
cristyefe601c2013-01-05 17:51:12 +00001976 "ColorSeparatedImageRequired","`%s'",map);
cristy4c08aed2011-07-01 19:47:50 +00001977 return(MagickFalse);
1978 }
1979 default:
1980 {
1981 quantum_map=(QuantumType *) RelinquishMagickMemory(quantum_map);
1982 (void) ThrowMagickException(exception,GetMagickModule(),OptionError,
cristyefe601c2013-01-05 17:51:12 +00001983 "UnrecognizedPixelMap","`%s'",map);
cristy4c08aed2011-07-01 19:47:50 +00001984 return(MagickFalse);
1985 }
1986 }
1987 }
cristycafe0412012-01-10 13:29:58 +00001988 roi.width=width;
1989 roi.height=height;
1990 roi.x=x;
1991 roi.y=y;
cristy4c08aed2011-07-01 19:47:50 +00001992 switch (type)
1993 {
1994 case CharPixel:
1995 {
cristycafe0412012-01-10 13:29:58 +00001996 ExportCharPixel(image,&roi,map,quantum_map,pixels,exception);
cristy4c08aed2011-07-01 19:47:50 +00001997 break;
1998 }
1999 case DoublePixel:
2000 {
cristycafe0412012-01-10 13:29:58 +00002001 ExportDoublePixel(image,&roi,map,quantum_map,pixels,exception);
cristy4c08aed2011-07-01 19:47:50 +00002002 break;
2003 }
2004 case FloatPixel:
2005 {
cristycafe0412012-01-10 13:29:58 +00002006 ExportFloatPixel(image,&roi,map,quantum_map,pixels,exception);
cristy4c08aed2011-07-01 19:47:50 +00002007 break;
2008 }
cristy4c08aed2011-07-01 19:47:50 +00002009 case LongPixel:
2010 {
cristycafe0412012-01-10 13:29:58 +00002011 ExportLongPixel(image,&roi,map,quantum_map,pixels,exception);
cristy4c08aed2011-07-01 19:47:50 +00002012 break;
2013 }
cristy6c9e1682012-01-07 21:37:44 +00002014 case LongLongPixel:
2015 {
cristycafe0412012-01-10 13:29:58 +00002016 ExportLongLongPixel(image,&roi,map,quantum_map,pixels,exception);
cristy6c9e1682012-01-07 21:37:44 +00002017 break;
2018 }
cristy4c08aed2011-07-01 19:47:50 +00002019 case QuantumPixel:
2020 {
cristycafe0412012-01-10 13:29:58 +00002021 ExportQuantumPixel(image,&roi,map,quantum_map,pixels,exception);
cristy4c08aed2011-07-01 19:47:50 +00002022 break;
2023 }
2024 case ShortPixel:
2025 {
cristycafe0412012-01-10 13:29:58 +00002026 ExportShortPixel(image,&roi,map,quantum_map,pixels,exception);
cristy4c08aed2011-07-01 19:47:50 +00002027 break;
2028 }
2029 default:
2030 {
2031 quantum_map=(QuantumType *) RelinquishMagickMemory(quantum_map);
2032 (void) ThrowMagickException(exception,GetMagickModule(),OptionError,
cristyefe601c2013-01-05 17:51:12 +00002033 "UnrecognizedPixelMap","`%s'",map);
cristy4c08aed2011-07-01 19:47:50 +00002034 break;
2035 }
2036 }
2037 quantum_map=(QuantumType *) RelinquishMagickMemory(quantum_map);
2038 return(MagickTrue);
2039}
2040
2041/*
2042%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2043% %
2044% %
2045% %
cristyaa8634f2011-10-01 13:25:12 +00002046% G e t P i x e l I n f o %
cristy4c08aed2011-07-01 19:47:50 +00002047% %
2048% %
2049% %
2050%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2051%
2052% GetPixelInfo() initializes the PixelInfo structure.
2053%
2054% The format of the GetPixelInfo method is:
2055%
2056% GetPixelInfo(const Image *image,PixelInfo *pixel)
2057%
2058% A description of each parameter follows:
2059%
2060% o image: the image.
2061%
cristy101ab702011-10-13 13:06:32 +00002062% o pixel: Specifies a pointer to a PixelInfo structure.
cristy4c08aed2011-07-01 19:47:50 +00002063%
2064*/
cristyaa8634f2011-10-01 13:25:12 +00002065MagickExport void GetPixelInfo(const Image *image,PixelInfo *pixel)
cristy4c08aed2011-07-01 19:47:50 +00002066{
2067 pixel->storage_class=DirectClass;
cristy7020ae62012-04-18 12:58:34 +00002068 pixel->colorspace=sRGBColorspace;
cristy8a46d822012-08-28 23:32:39 +00002069 pixel->alpha_trait=UndefinedPixelTrait;
cristy4c08aed2011-07-01 19:47:50 +00002070 pixel->fuzz=0.0;
2071 pixel->depth=MAGICKCORE_QUANTUM_DEPTH;
2072 pixel->red=0.0;
2073 pixel->green=0.0;
2074 pixel->blue=0.0;
2075 pixel->black=0.0;
cristya19f1d72012-08-07 18:24:38 +00002076 pixel->alpha=(double) OpaqueAlpha;
cristy4c08aed2011-07-01 19:47:50 +00002077 pixel->index=0.0;
2078 if (image == (const Image *) NULL)
2079 return;
2080 pixel->storage_class=image->storage_class;
2081 pixel->colorspace=image->colorspace;
cristy8a46d822012-08-28 23:32:39 +00002082 pixel->alpha_trait=image->alpha_trait;
cristy4c08aed2011-07-01 19:47:50 +00002083 pixel->depth=image->depth;
2084 pixel->fuzz=image->fuzz;
2085}
2086
2087/*
2088%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2089% %
2090% %
2091% %
cristy9731df72013-03-12 16:31:13 +00002092% G e t P i x e l I n t e n s i t y %
2093% %
2094% %
2095% %
2096%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2097%
cristy0c5c8892013-03-12 16:33:48 +00002098% GetPixelIntensity() returns a single sample intensity value from the red,
cristy70e9f682013-03-12 22:31:22 +00002099% green, and blue components of a pixel based on the selected method:
2100%
cristy2cf5d372013-03-13 12:03:11 +00002101% Rec601Luma 0.298839R' + 0.586811G' + 0.114350B'
2102% Rec601Luminance 0.298839R + 0.586811G + 0.114350B
2103% Rec709Luma 0.21260R' + 0.71520G' + 0.07220B'
2104% Rec709Luminance 0.21260R + 0.71520G + 0.07220B
2105% Brightness max(R, G, B)
2106% Lightness (min(R, G, B) + max(R, G, B)) / 2.0
2107% RMS (R'^2 + G'^2 + B'^2) / 3.0
2108% Average (R' + G' + B') / 3.0
cristy9731df72013-03-12 16:31:13 +00002109%
2110% The format of the GetPixelIntensity method is:
2111%
cristy2cf5d372013-03-13 12:03:11 +00002112% MagickRealType GetPixelIntensity(const Image *image,
2113% const Quantum *pixel)
cristy9731df72013-03-12 16:31:13 +00002114%
2115% A description of each parameter follows:
2116%
2117% o image: the image.
2118%
2119% o pixel: Specifies a pointer to a Quantum structure.
2120%
2121*/
cristy70e9f682013-03-12 22:31:22 +00002122
2123static inline MagickRealType MagickMax(const MagickRealType x,
2124 const MagickRealType y)
2125{
2126 if (x > y)
2127 return(x);
2128 return(y);
2129}
2130
2131static inline MagickRealType MagickMin(const MagickRealType x,
2132 const MagickRealType y)
2133{
2134 if (x < y)
2135 return(x);
2136 return(y);
2137}
2138
cristy9731df72013-03-12 16:31:13 +00002139MagickExport MagickRealType GetPixelIntensity(const Image *restrict image,
2140 const Quantum *restrict pixel)
2141{
2142 MagickRealType
2143 blue,
2144 green,
cristy70e9f682013-03-12 22:31:22 +00002145 red,
2146 intensity;
cristy9731df72013-03-12 16:31:13 +00002147
2148 if (image->colorspace == GRAYColorspace)
cristy592d6bb2013-04-07 15:20:37 +00002149 return((MagickRealType) GetPixelGray(image,pixel));
2150 red=(MagickRealType) GetPixelRed(image,pixel);
2151 green=(MagickRealType) GetPixelGreen(image,pixel);
2152 blue=(MagickRealType) GetPixelBlue(image,pixel);
cristy70e9f682013-03-12 22:31:22 +00002153 switch (image->intensity)
2154 {
cristybf02d732013-03-13 16:28:58 +00002155 case AveragePixelIntensityMethod:
2156 {
2157 intensity=(red+green+blue)/3.0;
2158 break;
2159 }
2160 case BrightnessPixelIntensityMethod:
2161 {
2162 intensity=MagickMax(MagickMax(red,green),blue);
2163 break;
2164 }
2165 case LightnessPixelIntensityMethod:
2166 {
2167 intensity=MagickMin(MagickMin(red,green),blue);
2168 break;
2169 }
cristy70e9f682013-03-12 22:31:22 +00002170 case Rec601LumaPixelIntensityMethod:
cristy70e9f682013-03-12 22:31:22 +00002171 {
cristy2cf5d372013-03-13 12:03:11 +00002172 intensity=0.298839f*red+0.586811f*green+0.114350f*blue;
2173 break;
2174 }
2175 case Rec601LuminancePixelIntensityMethod:
cristy205c9872013-04-07 02:52:58 +00002176 default:
cristy2cf5d372013-03-13 12:03:11 +00002177 {
cristy70e9f682013-03-12 22:31:22 +00002178 if (image->colorspace == sRGBColorspace)
2179 {
2180 red=DecodePixelGamma(red);
2181 green=DecodePixelGamma(green);
2182 blue=DecodePixelGamma(blue);
2183 }
2184 intensity=0.298839f*red+0.586811f*green+0.114350f*blue;
2185 break;
2186 }
2187 case Rec709LumaPixelIntensityMethod:
2188 {
cristy2cf5d372013-03-13 12:03:11 +00002189 intensity=0.21260f*red+0.71520f*green+0.07220f*blue;
2190 break;
2191 }
2192 case Rec709LuminancePixelIntensityMethod:
2193 {
cristy70e9f682013-03-12 22:31:22 +00002194 if (image->colorspace == sRGBColorspace)
2195 {
2196 red=DecodePixelGamma(red);
2197 green=DecodePixelGamma(green);
2198 blue=DecodePixelGamma(blue);
2199 }
2200 intensity=0.21260f*red+0.71520f*green+0.07220f*blue;
2201 break;
2202 }
cristy70e9f682013-03-12 22:31:22 +00002203 case RMSPixelIntensityMethod:
2204 {
2205 intensity=(MagickRealType) sqrt((double) red*red+green*green+blue*blue);
2206 break;
2207 }
cristy70e9f682013-03-12 22:31:22 +00002208 }
2209 return(intensity);
cristy9731df72013-03-12 16:31:13 +00002210}
cristy9731df72013-03-12 16:31:13 +00002211
2212/*
2213%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2214% %
2215% %
2216% %
cristy4c08aed2011-07-01 19:47:50 +00002217% I m p o r t I m a g e P i x e l s %
2218% %
2219% %
2220% %
2221%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2222%
2223% ImportImagePixels() accepts pixel data and stores in the image at the
2224% location you specify. The method returns MagickTrue on success otherwise
2225% MagickFalse if an error is encountered. The pixel data can be either char,
cristyb5a45a32012-01-10 13:31:13 +00002226% Quantum, short int, unsigned int, unsigned long long, float, or double in
2227% the order specified by map.
cristy4c08aed2011-07-01 19:47:50 +00002228%
2229% Suppose your want to upload the first scanline of a 640x480 image from
2230% character data in red-green-blue order:
2231%
2232% ImportImagePixels(image,0,0,640,1,"RGB",CharPixel,pixels);
2233%
2234% The format of the ImportImagePixels method is:
2235%
cristycafe0412012-01-10 13:29:58 +00002236% MagickBooleanType ImportImagePixels(Image *image,const ssize_t x,
2237% const ssize_t y,const size_t width,const size_t height,
2238% const char *map,const StorageType type,const void *pixels,
2239% ExceptionInfo *exception)
cristy4c08aed2011-07-01 19:47:50 +00002240%
2241% A description of each parameter follows:
2242%
2243% o image: the image.
2244%
cristycafe0412012-01-10 13:29:58 +00002245% o x,y,width,height: These values define the perimeter
cristy4c08aed2011-07-01 19:47:50 +00002246% of a region of pixels you want to define.
2247%
2248% o map: This string reflects the expected ordering of the pixel array.
2249% It can be any combination or order of R = red, G = green, B = blue,
2250% A = alpha (0 is transparent), O = opacity (0 is opaque), C = cyan,
2251% Y = yellow, M = magenta, K = black, I = intensity (for grayscale),
2252% P = pad.
2253%
2254% o type: Define the data type of the pixels. Float and double types are
2255% normalized to [0..1] otherwise [0..QuantumRange]. Choose from these
cristy6c9e1682012-01-07 21:37:44 +00002256% types: CharPixel (char *), DoublePixel (double *), FloatPixel (float *),
cristyff6834e2012-01-10 03:00:25 +00002257% LongPixel (unsigned int *), LongLongPixel (unsigned long long *),
cristy6c9e1682012-01-07 21:37:44 +00002258% QuantumPixel (Quantum *), or ShortPixel (unsigned short *).
cristy4c08aed2011-07-01 19:47:50 +00002259%
2260% o pixels: This array of values contain the pixel components as defined by
2261% map and type. You must preallocate this array where the expected
2262% length varies depending on the values of width, height, map, and type.
2263%
cristy018f07f2011-09-04 21:15:19 +00002264% o exception: return any errors or warnings in this structure.
2265%
cristy4c08aed2011-07-01 19:47:50 +00002266*/
cristye5370942012-01-06 03:49:31 +00002267
cristycafe0412012-01-10 13:29:58 +00002268static void ImportCharPixel(Image *image,const RectangleInfo *roi,
cristy46f4be22012-01-07 00:26:39 +00002269 const char *restrict map,const QuantumType *quantum_map,const void *pixels,
2270 ExceptionInfo *exception)
cristye5370942012-01-06 03:49:31 +00002271{
2272 register const unsigned char
2273 *restrict p;
2274
2275 register Quantum
cristy3fe11452012-01-09 01:27:42 +00002276 *restrict q;
cristye5370942012-01-06 03:49:31 +00002277
2278 register ssize_t
2279 x;
2280
cristy14d71292012-05-20 16:48:13 +00002281 size_t
2282 length;
2283
cristye5370942012-01-06 03:49:31 +00002284 ssize_t
2285 y;
2286
2287 p=(const unsigned char *) pixels;
2288 if (LocaleCompare(map,"BGR") == 0)
2289 {
cristycafe0412012-01-10 13:29:58 +00002290 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00002291 {
cristycafe0412012-01-10 13:29:58 +00002292 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00002293 if (q == (Quantum *) NULL)
2294 break;
cristycafe0412012-01-10 13:29:58 +00002295 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00002296 {
2297 SetPixelBlue(image,ScaleCharToQuantum(*p++),q);
2298 SetPixelGreen(image,ScaleCharToQuantum(*p++),q);
2299 SetPixelRed(image,ScaleCharToQuantum(*p++),q);
2300 q+=GetPixelChannels(image);
2301 }
2302 if (SyncAuthenticPixels(image,exception) == MagickFalse)
2303 break;
2304 }
2305 return;
2306 }
2307 if (LocaleCompare(map,"BGRA") == 0)
2308 {
cristycafe0412012-01-10 13:29:58 +00002309 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00002310 {
cristycafe0412012-01-10 13:29:58 +00002311 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00002312 if (q == (Quantum *) NULL)
2313 break;
cristycafe0412012-01-10 13:29:58 +00002314 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00002315 {
2316 SetPixelBlue(image,ScaleCharToQuantum(*p++),q);
2317 SetPixelGreen(image,ScaleCharToQuantum(*p++),q);
2318 SetPixelRed(image,ScaleCharToQuantum(*p++),q);
2319 SetPixelAlpha(image,ScaleCharToQuantum(*p++),q);
2320 q+=GetPixelChannels(image);
2321 }
2322 if (SyncAuthenticPixels(image,exception) == MagickFalse)
2323 break;
2324 }
2325 return;
2326 }
2327 if (LocaleCompare(map,"BGRO") == 0)
2328 {
cristycafe0412012-01-10 13:29:58 +00002329 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00002330 {
cristycafe0412012-01-10 13:29:58 +00002331 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00002332 if (q == (Quantum *) NULL)
2333 break;
cristycafe0412012-01-10 13:29:58 +00002334 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00002335 {
2336 SetPixelBlue(image,ScaleCharToQuantum(*p++),q);
2337 SetPixelGreen(image,ScaleCharToQuantum(*p++),q);
2338 SetPixelRed(image,ScaleCharToQuantum(*p++),q);
2339 SetPixelAlpha(image,ScaleCharToQuantum(*p++),q);
2340 q+=GetPixelChannels(image);
2341 }
2342 if (SyncAuthenticPixels(image,exception) == MagickFalse)
2343 break;
2344 }
2345 return;
2346 }
2347 if (LocaleCompare(map,"BGRP") == 0)
2348 {
cristycafe0412012-01-10 13:29:58 +00002349 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00002350 {
cristycafe0412012-01-10 13:29:58 +00002351 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00002352 if (q == (Quantum *) NULL)
2353 break;
cristycafe0412012-01-10 13:29:58 +00002354 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00002355 {
2356 SetPixelBlue(image,ScaleCharToQuantum(*p++),q);
2357 SetPixelGreen(image,ScaleCharToQuantum(*p++),q);
2358 SetPixelRed(image,ScaleCharToQuantum(*p++),q);
2359 p++;
2360 q+=GetPixelChannels(image);
2361 }
2362 if (SyncAuthenticPixels(image,exception) == MagickFalse)
2363 break;
2364 }
2365 return;
2366 }
2367 if (LocaleCompare(map,"I") == 0)
2368 {
cristycafe0412012-01-10 13:29:58 +00002369 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00002370 {
cristycafe0412012-01-10 13:29:58 +00002371 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00002372 if (q == (Quantum *) NULL)
2373 break;
cristycafe0412012-01-10 13:29:58 +00002374 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00002375 {
2376 SetPixelGray(image,ScaleCharToQuantum(*p++),q);
2377 q+=GetPixelChannels(image);
2378 }
2379 if (SyncAuthenticPixels(image,exception) == MagickFalse)
2380 break;
2381 }
2382 return;
2383 }
2384 if (LocaleCompare(map,"RGB") == 0)
2385 {
cristycafe0412012-01-10 13:29:58 +00002386 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00002387 {
cristycafe0412012-01-10 13:29:58 +00002388 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00002389 if (q == (Quantum *) NULL)
2390 break;
cristycafe0412012-01-10 13:29:58 +00002391 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00002392 {
2393 SetPixelRed(image,ScaleCharToQuantum(*p++),q);
2394 SetPixelGreen(image,ScaleCharToQuantum(*p++),q);
2395 SetPixelBlue(image,ScaleCharToQuantum(*p++),q);
2396 q+=GetPixelChannels(image);
2397 }
2398 if (SyncAuthenticPixels(image,exception) == MagickFalse)
2399 break;
2400 }
2401 return;
2402 }
2403 if (LocaleCompare(map,"RGBA") == 0)
2404 {
cristycafe0412012-01-10 13:29:58 +00002405 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00002406 {
cristycafe0412012-01-10 13:29:58 +00002407 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00002408 if (q == (Quantum *) NULL)
2409 break;
cristycafe0412012-01-10 13:29:58 +00002410 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00002411 {
2412 SetPixelRed(image,ScaleCharToQuantum(*p++),q);
2413 SetPixelGreen(image,ScaleCharToQuantum(*p++),q);
2414 SetPixelBlue(image,ScaleCharToQuantum(*p++),q);
2415 SetPixelAlpha(image,ScaleCharToQuantum(*p++),q);
2416 q+=GetPixelChannels(image);
2417 }
2418 if (SyncAuthenticPixels(image,exception) == MagickFalse)
2419 break;
2420 }
2421 return;
2422 }
2423 if (LocaleCompare(map,"RGBO") == 0)
2424 {
cristycafe0412012-01-10 13:29:58 +00002425 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00002426 {
cristycafe0412012-01-10 13:29:58 +00002427 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00002428 if (q == (Quantum *) NULL)
2429 break;
cristycafe0412012-01-10 13:29:58 +00002430 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00002431 {
2432 SetPixelRed(image,ScaleCharToQuantum(*p++),q);
2433 SetPixelGreen(image,ScaleCharToQuantum(*p++),q);
2434 SetPixelBlue(image,ScaleCharToQuantum(*p++),q);
2435 SetPixelAlpha(image,ScaleCharToQuantum(*p++),q);
2436 q+=GetPixelChannels(image);
2437 }
2438 if (SyncAuthenticPixels(image,exception) == MagickFalse)
2439 break;
2440 }
2441 return;
2442 }
2443 if (LocaleCompare(map,"RGBP") == 0)
2444 {
cristycafe0412012-01-10 13:29:58 +00002445 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00002446 {
cristycafe0412012-01-10 13:29:58 +00002447 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00002448 if (q == (Quantum *) NULL)
2449 break;
cristycafe0412012-01-10 13:29:58 +00002450 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00002451 {
2452 SetPixelRed(image,ScaleCharToQuantum(*p++),q);
2453 SetPixelGreen(image,ScaleCharToQuantum(*p++),q);
2454 SetPixelBlue(image,ScaleCharToQuantum(*p++),q);
2455 p++;
2456 q+=GetPixelChannels(image);
2457 }
2458 if (SyncAuthenticPixels(image,exception) == MagickFalse)
2459 break;
2460 }
2461 return;
2462 }
cristy14d71292012-05-20 16:48:13 +00002463 length=strlen(map);
cristycafe0412012-01-10 13:29:58 +00002464 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00002465 {
cristycafe0412012-01-10 13:29:58 +00002466 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00002467 if (q == (Quantum *) NULL)
2468 break;
cristycafe0412012-01-10 13:29:58 +00002469 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00002470 {
2471 register ssize_t
2472 i;
2473
cristy14d71292012-05-20 16:48:13 +00002474 for (i=0; i < (ssize_t) length; i++)
cristye5370942012-01-06 03:49:31 +00002475 {
2476 switch (quantum_map[i])
2477 {
2478 case RedQuantum:
2479 case CyanQuantum:
2480 {
2481 SetPixelRed(image,ScaleCharToQuantum(*p),q);
2482 break;
2483 }
2484 case GreenQuantum:
2485 case MagentaQuantum:
2486 {
2487 SetPixelGreen(image,ScaleCharToQuantum(*p),q);
2488 break;
2489 }
2490 case BlueQuantum:
2491 case YellowQuantum:
2492 {
2493 SetPixelBlue(image,ScaleCharToQuantum(*p),q);
2494 break;
2495 }
2496 case AlphaQuantum:
2497 {
2498 SetPixelAlpha(image,ScaleCharToQuantum(*p),q);
2499 break;
2500 }
2501 case OpacityQuantum:
2502 {
2503 SetPixelAlpha(image,ScaleCharToQuantum(*p),q);
2504 break;
2505 }
2506 case BlackQuantum:
2507 {
2508 SetPixelBlack(image,ScaleCharToQuantum(*p),q);
2509 break;
2510 }
2511 case IndexQuantum:
2512 {
2513 SetPixelGray(image,ScaleCharToQuantum(*p),q);
2514 break;
2515 }
2516 default:
2517 break;
2518 }
2519 p++;
2520 }
2521 q+=GetPixelChannels(image);
2522 }
2523 if (SyncAuthenticPixels(image,exception) == MagickFalse)
2524 break;
2525 }
2526}
2527
cristycafe0412012-01-10 13:29:58 +00002528static void ImportDoublePixel(Image *image,const RectangleInfo *roi,
cristy46f4be22012-01-07 00:26:39 +00002529 const char *restrict map,const QuantumType *quantum_map,const void *pixels,
2530 ExceptionInfo *exception)
cristye5370942012-01-06 03:49:31 +00002531{
2532 register const double
2533 *restrict p;
2534
2535 register Quantum
cristy3fe11452012-01-09 01:27:42 +00002536 *restrict q;
cristye5370942012-01-06 03:49:31 +00002537
2538 register ssize_t
2539 x;
2540
cristy14d71292012-05-20 16:48:13 +00002541 size_t
2542 length;
2543
cristye5370942012-01-06 03:49:31 +00002544 ssize_t
2545 y;
2546
2547 p=(const double *) pixels;
2548 if (LocaleCompare(map,"BGR") == 0)
2549 {
cristycafe0412012-01-10 13:29:58 +00002550 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00002551 {
cristycafe0412012-01-10 13:29:58 +00002552 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00002553 if (q == (Quantum *) NULL)
2554 break;
cristycafe0412012-01-10 13:29:58 +00002555 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00002556 {
cristy8cd03c32012-07-07 18:57:59 +00002557 SetPixelBlue(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002558 p++;
cristy8cd03c32012-07-07 18:57:59 +00002559 SetPixelGreen(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002560 p++;
cristy8cd03c32012-07-07 18:57:59 +00002561 SetPixelRed(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002562 p++;
2563 q+=GetPixelChannels(image);
2564 }
2565 if (SyncAuthenticPixels(image,exception) == MagickFalse)
2566 break;
2567 }
2568 return;
2569 }
2570 if (LocaleCompare(map,"BGRA") == 0)
2571 {
cristycafe0412012-01-10 13:29:58 +00002572 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00002573 {
cristycafe0412012-01-10 13:29:58 +00002574 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00002575 if (q == (Quantum *) NULL)
2576 break;
cristycafe0412012-01-10 13:29:58 +00002577 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00002578 {
cristy8cd03c32012-07-07 18:57:59 +00002579 SetPixelBlue(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002580 p++;
cristy8cd03c32012-07-07 18:57:59 +00002581 SetPixelGreen(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002582 p++;
cristy8cd03c32012-07-07 18:57:59 +00002583 SetPixelRed(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002584 p++;
cristy8cd03c32012-07-07 18:57:59 +00002585 SetPixelAlpha(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002586 p++;
2587 q+=GetPixelChannels(image);
2588 }
2589 if (SyncAuthenticPixels(image,exception) == MagickFalse)
2590 break;
2591 }
2592 return;
2593 }
2594 if (LocaleCompare(map,"BGRP") == 0)
2595 {
cristycafe0412012-01-10 13:29:58 +00002596 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00002597 {
cristycafe0412012-01-10 13:29:58 +00002598 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00002599 if (q == (Quantum *) NULL)
2600 break;
cristycafe0412012-01-10 13:29:58 +00002601 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00002602 {
cristy8cd03c32012-07-07 18:57:59 +00002603 SetPixelBlue(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002604 p++;
cristy8cd03c32012-07-07 18:57:59 +00002605 SetPixelGreen(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002606 p++;
cristy8cd03c32012-07-07 18:57:59 +00002607 SetPixelRed(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002608 p++;
2609 p++;
2610 q+=GetPixelChannels(image);
2611 }
2612 if (SyncAuthenticPixels(image,exception) == MagickFalse)
2613 break;
2614 }
2615 return;
2616 }
2617 if (LocaleCompare(map,"I") == 0)
2618 {
cristycafe0412012-01-10 13:29:58 +00002619 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00002620 {
cristycafe0412012-01-10 13:29:58 +00002621 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00002622 if (q == (Quantum *) NULL)
2623 break;
cristycafe0412012-01-10 13:29:58 +00002624 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00002625 {
cristy8cd03c32012-07-07 18:57:59 +00002626 SetPixelGray(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002627 p++;
2628 q+=GetPixelChannels(image);
2629 }
2630 if (SyncAuthenticPixels(image,exception) == MagickFalse)
2631 break;
2632 }
2633 return;
2634 }
2635 if (LocaleCompare(map,"RGB") == 0)
2636 {
cristycafe0412012-01-10 13:29:58 +00002637 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00002638 {
cristycafe0412012-01-10 13:29:58 +00002639 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00002640 if (q == (Quantum *) NULL)
2641 break;
cristycafe0412012-01-10 13:29:58 +00002642 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00002643 {
cristy8cd03c32012-07-07 18:57:59 +00002644 SetPixelRed(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002645 p++;
cristy8cd03c32012-07-07 18:57:59 +00002646 SetPixelGreen(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002647 p++;
cristy8cd03c32012-07-07 18:57:59 +00002648 SetPixelBlue(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002649 p++;
2650 q+=GetPixelChannels(image);
2651 }
2652 if (SyncAuthenticPixels(image,exception) == MagickFalse)
2653 break;
2654 }
2655 return;
2656 }
2657 if (LocaleCompare(map,"RGBA") == 0)
2658 {
cristycafe0412012-01-10 13:29:58 +00002659 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00002660 {
cristycafe0412012-01-10 13:29:58 +00002661 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00002662 if (q == (Quantum *) NULL)
2663 break;
cristycafe0412012-01-10 13:29:58 +00002664 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00002665 {
cristy8cd03c32012-07-07 18:57:59 +00002666 SetPixelRed(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002667 p++;
cristy8cd03c32012-07-07 18:57:59 +00002668 SetPixelGreen(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002669 p++;
cristy8cd03c32012-07-07 18:57:59 +00002670 SetPixelBlue(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002671 p++;
cristy8cd03c32012-07-07 18:57:59 +00002672 SetPixelAlpha(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002673 p++;
2674 q+=GetPixelChannels(image);
2675 }
2676 if (SyncAuthenticPixels(image,exception) == MagickFalse)
2677 break;
2678 }
2679 return;
2680 }
2681 if (LocaleCompare(map,"RGBP") == 0)
2682 {
cristycafe0412012-01-10 13:29:58 +00002683 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00002684 {
cristycafe0412012-01-10 13:29:58 +00002685 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00002686 if (q == (Quantum *) NULL)
2687 break;
cristycafe0412012-01-10 13:29:58 +00002688 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00002689 {
cristy8cd03c32012-07-07 18:57:59 +00002690 SetPixelRed(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002691 p++;
cristy8cd03c32012-07-07 18:57:59 +00002692 SetPixelGreen(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002693 p++;
cristy8cd03c32012-07-07 18:57:59 +00002694 SetPixelBlue(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002695 p++;
2696 q+=GetPixelChannels(image);
2697 }
2698 if (SyncAuthenticPixels(image,exception) == MagickFalse)
2699 break;
2700 }
2701 return;
2702 }
cristy14d71292012-05-20 16:48:13 +00002703 length=strlen(map);
cristycafe0412012-01-10 13:29:58 +00002704 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00002705 {
cristycafe0412012-01-10 13:29:58 +00002706 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00002707 if (q == (Quantum *) NULL)
2708 break;
cristycafe0412012-01-10 13:29:58 +00002709 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00002710 {
2711 register ssize_t
2712 i;
2713
cristy14d71292012-05-20 16:48:13 +00002714 for (i=0; i < (ssize_t) length; i++)
cristye5370942012-01-06 03:49:31 +00002715 {
2716 switch (quantum_map[i])
2717 {
2718 case RedQuantum:
2719 case CyanQuantum:
2720 {
cristy8cd03c32012-07-07 18:57:59 +00002721 SetPixelRed(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002722 break;
2723 }
2724 case GreenQuantum:
2725 case MagentaQuantum:
2726 {
cristy8cd03c32012-07-07 18:57:59 +00002727 SetPixelGreen(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002728 break;
2729 }
2730 case BlueQuantum:
2731 case YellowQuantum:
2732 {
cristy8cd03c32012-07-07 18:57:59 +00002733 SetPixelBlue(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002734 break;
2735 }
2736 case AlphaQuantum:
2737 {
cristy8cd03c32012-07-07 18:57:59 +00002738 SetPixelAlpha(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002739 break;
2740 }
2741 case OpacityQuantum:
2742 {
cristy8cd03c32012-07-07 18:57:59 +00002743 SetPixelAlpha(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002744 break;
2745 }
2746 case BlackQuantum:
2747 {
cristy8cd03c32012-07-07 18:57:59 +00002748 SetPixelBlack(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002749 break;
2750 }
2751 case IndexQuantum:
2752 {
cristy8cd03c32012-07-07 18:57:59 +00002753 SetPixelGray(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002754 break;
2755 }
2756 default:
2757 break;
2758 }
2759 p++;
2760 }
2761 q+=GetPixelChannels(image);
2762 }
2763 if (SyncAuthenticPixels(image,exception) == MagickFalse)
2764 break;
2765 }
2766}
2767
cristycafe0412012-01-10 13:29:58 +00002768static void ImportFloatPixel(Image *image,const RectangleInfo *roi,
cristy46f4be22012-01-07 00:26:39 +00002769 const char *restrict map,const QuantumType *quantum_map,const void *pixels,
2770 ExceptionInfo *exception)
cristye5370942012-01-06 03:49:31 +00002771{
2772 register const float
2773 *restrict p;
2774
2775 register Quantum
cristy3fe11452012-01-09 01:27:42 +00002776 *restrict q;
cristye5370942012-01-06 03:49:31 +00002777
2778 register ssize_t
2779 x;
2780
cristy14d71292012-05-20 16:48:13 +00002781 size_t
2782 length;
2783
cristye5370942012-01-06 03:49:31 +00002784 ssize_t
2785 y;
2786
2787 p=(const float *) pixels;
2788 if (LocaleCompare(map,"BGR") == 0)
2789 {
cristycafe0412012-01-10 13:29:58 +00002790 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00002791 {
cristycafe0412012-01-10 13:29:58 +00002792 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00002793 if (q == (Quantum *) NULL)
2794 break;
cristycafe0412012-01-10 13:29:58 +00002795 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00002796 {
cristy8cd03c32012-07-07 18:57:59 +00002797 SetPixelBlue(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002798 p++;
cristy8cd03c32012-07-07 18:57:59 +00002799 SetPixelGreen(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002800 p++;
cristy8cd03c32012-07-07 18:57:59 +00002801 SetPixelRed(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002802 p++;
2803 q+=GetPixelChannels(image);
2804 }
2805 if (SyncAuthenticPixels(image,exception) == MagickFalse)
2806 break;
2807 }
2808 return;
2809 }
2810 if (LocaleCompare(map,"BGRA") == 0)
2811 {
cristycafe0412012-01-10 13:29:58 +00002812 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00002813 {
cristycafe0412012-01-10 13:29:58 +00002814 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00002815 if (q == (Quantum *) NULL)
2816 break;
cristycafe0412012-01-10 13:29:58 +00002817 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00002818 {
cristy8cd03c32012-07-07 18:57:59 +00002819 SetPixelBlue(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002820 p++;
cristy8cd03c32012-07-07 18:57:59 +00002821 SetPixelGreen(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002822 p++;
cristy8cd03c32012-07-07 18:57:59 +00002823 SetPixelRed(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002824 p++;
cristy8cd03c32012-07-07 18:57:59 +00002825 SetPixelAlpha(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002826 p++;
2827 q+=GetPixelChannels(image);
2828 }
2829 if (SyncAuthenticPixels(image,exception) == MagickFalse)
2830 break;
2831 }
2832 return;
2833 }
2834 if (LocaleCompare(map,"BGRP") == 0)
2835 {
cristycafe0412012-01-10 13:29:58 +00002836 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00002837 {
cristycafe0412012-01-10 13:29:58 +00002838 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00002839 if (q == (Quantum *) NULL)
2840 break;
cristycafe0412012-01-10 13:29:58 +00002841 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00002842 {
cristy8cd03c32012-07-07 18:57:59 +00002843 SetPixelBlue(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002844 p++;
cristy8cd03c32012-07-07 18:57:59 +00002845 SetPixelGreen(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002846 p++;
cristy8cd03c32012-07-07 18:57:59 +00002847 SetPixelRed(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002848 p++;
2849 p++;
2850 q+=GetPixelChannels(image);
2851 }
2852 if (SyncAuthenticPixels(image,exception) == MagickFalse)
2853 break;
2854 }
2855 return;
2856 }
2857 if (LocaleCompare(map,"I") == 0)
2858 {
cristycafe0412012-01-10 13:29:58 +00002859 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00002860 {
cristycafe0412012-01-10 13:29:58 +00002861 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00002862 if (q == (Quantum *) NULL)
2863 break;
cristycafe0412012-01-10 13:29:58 +00002864 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00002865 {
cristy8cd03c32012-07-07 18:57:59 +00002866 SetPixelGray(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002867 p++;
2868 q+=GetPixelChannels(image);
2869 }
2870 if (SyncAuthenticPixels(image,exception) == MagickFalse)
2871 break;
2872 }
2873 return;
2874 }
2875 if (LocaleCompare(map,"RGB") == 0)
2876 {
cristycafe0412012-01-10 13:29:58 +00002877 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00002878 {
cristycafe0412012-01-10 13:29:58 +00002879 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00002880 if (q == (Quantum *) NULL)
2881 break;
cristycafe0412012-01-10 13:29:58 +00002882 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00002883 {
cristy8cd03c32012-07-07 18:57:59 +00002884 SetPixelRed(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002885 p++;
cristy8cd03c32012-07-07 18:57:59 +00002886 SetPixelGreen(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002887 p++;
cristy8cd03c32012-07-07 18:57:59 +00002888 SetPixelBlue(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002889 p++;
2890 q+=GetPixelChannels(image);
2891 }
2892 if (SyncAuthenticPixels(image,exception) == MagickFalse)
2893 break;
2894 }
2895 return;
2896 }
2897 if (LocaleCompare(map,"RGBA") == 0)
2898 {
cristycafe0412012-01-10 13:29:58 +00002899 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00002900 {
cristycafe0412012-01-10 13:29:58 +00002901 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00002902 if (q == (Quantum *) NULL)
2903 break;
cristycafe0412012-01-10 13:29:58 +00002904 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00002905 {
cristy8cd03c32012-07-07 18:57:59 +00002906 SetPixelRed(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002907 p++;
cristy8cd03c32012-07-07 18:57:59 +00002908 SetPixelGreen(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002909 p++;
cristy8cd03c32012-07-07 18:57:59 +00002910 SetPixelBlue(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002911 p++;
cristy8cd03c32012-07-07 18:57:59 +00002912 SetPixelAlpha(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002913 p++;
2914 q+=GetPixelChannels(image);
2915 }
2916 if (SyncAuthenticPixels(image,exception) == MagickFalse)
2917 break;
2918 }
2919 return;
2920 }
2921 if (LocaleCompare(map,"RGBP") == 0)
2922 {
cristycafe0412012-01-10 13:29:58 +00002923 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00002924 {
cristycafe0412012-01-10 13:29:58 +00002925 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00002926 if (q == (Quantum *) NULL)
2927 break;
cristycafe0412012-01-10 13:29:58 +00002928 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00002929 {
cristy8cd03c32012-07-07 18:57:59 +00002930 SetPixelRed(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002931 p++;
cristy8cd03c32012-07-07 18:57:59 +00002932 SetPixelGreen(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002933 p++;
cristy8cd03c32012-07-07 18:57:59 +00002934 SetPixelBlue(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002935 p++;
2936 q+=GetPixelChannels(image);
2937 }
2938 if (SyncAuthenticPixels(image,exception) == MagickFalse)
2939 break;
2940 }
2941 return;
2942 }
cristy14d71292012-05-20 16:48:13 +00002943 length=strlen(map);
cristycafe0412012-01-10 13:29:58 +00002944 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00002945 {
cristycafe0412012-01-10 13:29:58 +00002946 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00002947 if (q == (Quantum *) NULL)
2948 break;
cristycafe0412012-01-10 13:29:58 +00002949 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00002950 {
2951 register ssize_t
2952 i;
2953
cristy14d71292012-05-20 16:48:13 +00002954 for (i=0; i < (ssize_t) length; i++)
cristye5370942012-01-06 03:49:31 +00002955 {
2956 switch (quantum_map[i])
2957 {
2958 case RedQuantum:
2959 case CyanQuantum:
2960 {
cristy8cd03c32012-07-07 18:57:59 +00002961 SetPixelRed(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002962 break;
2963 }
2964 case GreenQuantum:
2965 case MagentaQuantum:
2966 {
cristy8cd03c32012-07-07 18:57:59 +00002967 SetPixelGreen(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002968 break;
2969 }
2970 case BlueQuantum:
2971 case YellowQuantum:
2972 {
cristy8cd03c32012-07-07 18:57:59 +00002973 SetPixelBlue(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002974 break;
2975 }
2976 case AlphaQuantum:
2977 {
cristy8cd03c32012-07-07 18:57:59 +00002978 SetPixelAlpha(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002979 break;
2980 }
2981 case OpacityQuantum:
2982 {
cristy8cd03c32012-07-07 18:57:59 +00002983 SetPixelAlpha(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002984 break;
2985 }
2986 case BlackQuantum:
2987 {
cristy8cd03c32012-07-07 18:57:59 +00002988 SetPixelBlack(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002989 break;
2990 }
2991 case IndexQuantum:
2992 {
cristy8cd03c32012-07-07 18:57:59 +00002993 SetPixelGray(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002994 break;
2995 }
2996 default:
2997 break;
2998 }
2999 p++;
3000 }
3001 q+=GetPixelChannels(image);
3002 }
3003 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3004 break;
3005 }
3006}
3007
cristycafe0412012-01-10 13:29:58 +00003008static void ImportLongPixel(Image *image,const RectangleInfo *roi,
cristy46f4be22012-01-07 00:26:39 +00003009 const char *restrict map,const QuantumType *quantum_map,const void *pixels,
3010 ExceptionInfo *exception)
cristye5370942012-01-06 03:49:31 +00003011{
3012 register const unsigned int
3013 *restrict p;
3014
3015 register Quantum
cristy3fe11452012-01-09 01:27:42 +00003016 *restrict q;
cristye5370942012-01-06 03:49:31 +00003017
3018 register ssize_t
3019 x;
3020
cristy14d71292012-05-20 16:48:13 +00003021 size_t
3022 length;
3023
cristye5370942012-01-06 03:49:31 +00003024 ssize_t
3025 y;
3026
3027 p=(const unsigned int *) pixels;
3028 if (LocaleCompare(map,"BGR") == 0)
3029 {
cristycafe0412012-01-10 13:29:58 +00003030 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00003031 {
cristycafe0412012-01-10 13:29:58 +00003032 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00003033 if (q == (Quantum *) NULL)
3034 break;
cristycafe0412012-01-10 13:29:58 +00003035 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00003036 {
3037 SetPixelBlue(image,ScaleLongToQuantum(*p++),q);
3038 SetPixelGreen(image,ScaleLongToQuantum(*p++),q);
3039 SetPixelRed(image,ScaleLongToQuantum(*p++),q);
3040 q+=GetPixelChannels(image);
3041 }
3042 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3043 break;
3044 }
3045 return;
3046 }
3047 if (LocaleCompare(map,"BGRA") == 0)
3048 {
cristycafe0412012-01-10 13:29:58 +00003049 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00003050 {
cristycafe0412012-01-10 13:29:58 +00003051 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00003052 if (q == (Quantum *) NULL)
3053 break;
cristycafe0412012-01-10 13:29:58 +00003054 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00003055 {
3056 SetPixelBlue(image,ScaleLongToQuantum(*p++),q);
3057 SetPixelGreen(image,ScaleLongToQuantum(*p++),q);
3058 SetPixelRed(image,ScaleLongToQuantum(*p++),q);
3059 SetPixelAlpha(image,ScaleLongToQuantum(*p++),q);
3060 q+=GetPixelChannels(image);
3061 }
3062 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3063 break;
3064 }
3065 return;
3066 }
3067 if (LocaleCompare(map,"BGRP") == 0)
3068 {
cristycafe0412012-01-10 13:29:58 +00003069 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00003070 {
cristycafe0412012-01-10 13:29:58 +00003071 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00003072 if (q == (Quantum *) NULL)
3073 break;
cristycafe0412012-01-10 13:29:58 +00003074 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00003075 {
3076 SetPixelBlue(image,ScaleLongToQuantum(*p++),q);
3077 SetPixelGreen(image,ScaleLongToQuantum(*p++),q);
3078 SetPixelRed(image,ScaleLongToQuantum(*p++),q);
3079 p++;
3080 q+=GetPixelChannels(image);
3081 }
3082 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3083 break;
3084 }
3085 return;
3086 }
3087 if (LocaleCompare(map,"I") == 0)
3088 {
cristycafe0412012-01-10 13:29:58 +00003089 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00003090 {
cristycafe0412012-01-10 13:29:58 +00003091 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00003092 if (q == (Quantum *) NULL)
3093 break;
cristycafe0412012-01-10 13:29:58 +00003094 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00003095 {
3096 SetPixelGray(image,ScaleLongToQuantum(*p++),q);
3097 q+=GetPixelChannels(image);
3098 }
3099 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3100 break;
3101 }
3102 return;
3103 }
3104 if (LocaleCompare(map,"RGB") == 0)
3105 {
cristycafe0412012-01-10 13:29:58 +00003106 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00003107 {
cristycafe0412012-01-10 13:29:58 +00003108 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00003109 if (q == (Quantum *) NULL)
3110 break;
cristycafe0412012-01-10 13:29:58 +00003111 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00003112 {
3113 SetPixelRed(image,ScaleLongToQuantum(*p++),q);
3114 SetPixelGreen(image,ScaleLongToQuantum(*p++),q);
3115 SetPixelBlue(image,ScaleLongToQuantum(*p++),q);
3116 q+=GetPixelChannels(image);
3117 }
3118 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3119 break;
3120 }
3121 return;
3122 }
3123 if (LocaleCompare(map,"RGBA") == 0)
3124 {
cristycafe0412012-01-10 13:29:58 +00003125 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00003126 {
cristycafe0412012-01-10 13:29:58 +00003127 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00003128 if (q == (Quantum *) NULL)
3129 break;
cristycafe0412012-01-10 13:29:58 +00003130 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00003131 {
3132 SetPixelRed(image,ScaleLongToQuantum(*p++),q);
3133 SetPixelGreen(image,ScaleLongToQuantum(*p++),q);
3134 SetPixelBlue(image,ScaleLongToQuantum(*p++),q);
3135 SetPixelAlpha(image,ScaleLongToQuantum(*p++),q);
3136 q+=GetPixelChannels(image);
3137 }
3138 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3139 break;
3140 }
3141 return;
3142 }
3143 if (LocaleCompare(map,"RGBP") == 0)
3144 {
cristycafe0412012-01-10 13:29:58 +00003145 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00003146 {
cristycafe0412012-01-10 13:29:58 +00003147 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00003148 if (q == (Quantum *) NULL)
3149 break;
cristycafe0412012-01-10 13:29:58 +00003150 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00003151 {
3152 SetPixelRed(image,ScaleLongToQuantum(*p++),q);
3153 SetPixelGreen(image,ScaleLongToQuantum(*p++),q);
3154 SetPixelBlue(image,ScaleLongToQuantum(*p++),q);
3155 p++;
3156 q+=GetPixelChannels(image);
3157 }
3158 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3159 break;
3160 }
3161 return;
3162 }
cristy14d71292012-05-20 16:48:13 +00003163 length=strlen(map);
cristycafe0412012-01-10 13:29:58 +00003164 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00003165 {
cristycafe0412012-01-10 13:29:58 +00003166 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00003167 if (q == (Quantum *) NULL)
3168 break;
cristycafe0412012-01-10 13:29:58 +00003169 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00003170 {
3171 register ssize_t
3172 i;
3173
cristy14d71292012-05-20 16:48:13 +00003174 for (i=0; i < (ssize_t) length; i++)
cristye5370942012-01-06 03:49:31 +00003175 {
3176 switch (quantum_map[i])
3177 {
3178 case RedQuantum:
3179 case CyanQuantum:
3180 {
3181 SetPixelRed(image,ScaleLongToQuantum(*p),q);
3182 break;
3183 }
3184 case GreenQuantum:
3185 case MagentaQuantum:
3186 {
3187 SetPixelGreen(image,ScaleLongToQuantum(*p),q);
3188 break;
3189 }
3190 case BlueQuantum:
3191 case YellowQuantum:
3192 {
3193 SetPixelBlue(image,ScaleLongToQuantum(*p),q);
3194 break;
3195 }
3196 case AlphaQuantum:
3197 {
3198 SetPixelAlpha(image,ScaleLongToQuantum(*p),q);
3199 break;
3200 }
3201 case OpacityQuantum:
3202 {
3203 SetPixelAlpha(image,ScaleLongToQuantum(*p),q);
3204 break;
3205 }
3206 case BlackQuantum:
3207 {
3208 SetPixelBlack(image,ScaleLongToQuantum(*p),q);
3209 break;
3210 }
3211 case IndexQuantum:
3212 {
3213 SetPixelGray(image,ScaleLongToQuantum(*p),q);
3214 break;
3215 }
3216 default:
3217 break;
3218 }
3219 p++;
3220 }
3221 q+=GetPixelChannels(image);
3222 }
3223 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3224 break;
3225 }
3226}
3227
cristycafe0412012-01-10 13:29:58 +00003228static void ImportLongLongPixel(Image *image,const RectangleInfo *roi,
cristy46f4be22012-01-07 00:26:39 +00003229 const char *restrict map,const QuantumType *quantum_map,const void *pixels,
3230 ExceptionInfo *exception)
cristye5370942012-01-06 03:49:31 +00003231{
cristyb13e12a2012-01-06 21:48:27 +00003232 register const MagickSizeType
cristye5370942012-01-06 03:49:31 +00003233 *restrict p;
3234
3235 register Quantum
cristy3fe11452012-01-09 01:27:42 +00003236 *restrict q;
cristye5370942012-01-06 03:49:31 +00003237
3238 register ssize_t
3239 x;
3240
cristy14d71292012-05-20 16:48:13 +00003241 size_t
3242 length;
3243
cristye5370942012-01-06 03:49:31 +00003244 ssize_t
3245 y;
3246
cristyb13e12a2012-01-06 21:48:27 +00003247 p=(const MagickSizeType *) pixels;
cristye5370942012-01-06 03:49:31 +00003248 if (LocaleCompare(map,"BGR") == 0)
3249 {
cristycafe0412012-01-10 13:29:58 +00003250 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00003251 {
cristycafe0412012-01-10 13:29:58 +00003252 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00003253 if (q == (Quantum *) NULL)
3254 break;
cristycafe0412012-01-10 13:29:58 +00003255 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00003256 {
cristyb13e12a2012-01-06 21:48:27 +00003257 SetPixelBlue(image,ScaleLongLongToQuantum(*p++),q);
3258 SetPixelGreen(image,ScaleLongLongToQuantum(*p++),q);
3259 SetPixelRed(image,ScaleLongLongToQuantum(*p++),q);
cristye5370942012-01-06 03:49:31 +00003260 q+=GetPixelChannels(image);
3261 }
3262 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3263 break;
3264 }
3265 return;
3266 }
3267 if (LocaleCompare(map,"BGRA") == 0)
3268 {
cristycafe0412012-01-10 13:29:58 +00003269 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00003270 {
cristycafe0412012-01-10 13:29:58 +00003271 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00003272 if (q == (Quantum *) NULL)
3273 break;
cristycafe0412012-01-10 13:29:58 +00003274 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00003275 {
cristyb13e12a2012-01-06 21:48:27 +00003276 SetPixelBlue(image,ScaleLongLongToQuantum(*p++),q);
3277 SetPixelGreen(image,ScaleLongLongToQuantum(*p++),q);
3278 SetPixelRed(image,ScaleLongLongToQuantum(*p++),q);
3279 SetPixelAlpha(image,ScaleLongLongToQuantum(*p++),q);
cristye5370942012-01-06 03:49:31 +00003280 q+=GetPixelChannels(image);
3281 }
3282 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3283 break;
3284 }
3285 return;
3286 }
3287 if (LocaleCompare(map,"BGRP") == 0)
3288 {
cristycafe0412012-01-10 13:29:58 +00003289 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00003290 {
cristycafe0412012-01-10 13:29:58 +00003291 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00003292 if (q == (Quantum *) NULL)
3293 break;
cristycafe0412012-01-10 13:29:58 +00003294 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00003295 {
cristyb13e12a2012-01-06 21:48:27 +00003296 SetPixelBlue(image,ScaleLongLongToQuantum(*p++),q);
3297 SetPixelGreen(image,ScaleLongLongToQuantum(*p++),q);
3298 SetPixelRed(image,ScaleLongLongToQuantum(*p++),q);
cristye5370942012-01-06 03:49:31 +00003299 p++;
3300 q+=GetPixelChannels(image);
3301 }
3302 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3303 break;
3304 }
3305 return;
3306 }
3307 if (LocaleCompare(map,"I") == 0)
3308 {
cristycafe0412012-01-10 13:29:58 +00003309 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00003310 {
cristycafe0412012-01-10 13:29:58 +00003311 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00003312 if (q == (Quantum *) NULL)
3313 break;
cristycafe0412012-01-10 13:29:58 +00003314 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00003315 {
cristyb13e12a2012-01-06 21:48:27 +00003316 SetPixelGray(image,ScaleLongLongToQuantum(*p++),q);
cristye5370942012-01-06 03:49:31 +00003317 q+=GetPixelChannels(image);
3318 }
3319 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3320 break;
3321 }
3322 return;
3323 }
3324 if (LocaleCompare(map,"RGB") == 0)
3325 {
cristycafe0412012-01-10 13:29:58 +00003326 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00003327 {
cristycafe0412012-01-10 13:29:58 +00003328 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00003329 if (q == (Quantum *) NULL)
3330 break;
cristycafe0412012-01-10 13:29:58 +00003331 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00003332 {
cristyb13e12a2012-01-06 21:48:27 +00003333 SetPixelRed(image,ScaleLongLongToQuantum(*p++),q);
3334 SetPixelGreen(image,ScaleLongLongToQuantum(*p++),q);
3335 SetPixelBlue(image,ScaleLongLongToQuantum(*p++),q);
cristye5370942012-01-06 03:49:31 +00003336 q+=GetPixelChannels(image);
3337 }
3338 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3339 break;
3340 }
3341 return;
3342 }
3343 if (LocaleCompare(map,"RGBA") == 0)
3344 {
cristycafe0412012-01-10 13:29:58 +00003345 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00003346 {
cristycafe0412012-01-10 13:29:58 +00003347 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00003348 if (q == (Quantum *) NULL)
3349 break;
cristycafe0412012-01-10 13:29:58 +00003350 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00003351 {
cristyb13e12a2012-01-06 21:48:27 +00003352 SetPixelRed(image,ScaleLongLongToQuantum(*p++),q);
3353 SetPixelGreen(image,ScaleLongLongToQuantum(*p++),q);
3354 SetPixelBlue(image,ScaleLongLongToQuantum(*p++),q);
3355 SetPixelAlpha(image,ScaleLongLongToQuantum(*p++),q);
cristye5370942012-01-06 03:49:31 +00003356 q+=GetPixelChannels(image);
3357 }
3358 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3359 break;
3360 }
3361 return;
3362 }
3363 if (LocaleCompare(map,"RGBP") == 0)
3364 {
cristycafe0412012-01-10 13:29:58 +00003365 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00003366 {
cristycafe0412012-01-10 13:29:58 +00003367 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00003368 if (q == (Quantum *) NULL)
3369 break;
cristycafe0412012-01-10 13:29:58 +00003370 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00003371 {
cristyb13e12a2012-01-06 21:48:27 +00003372 SetPixelRed(image,ScaleLongLongToQuantum(*p++),q);
3373 SetPixelGreen(image,ScaleLongLongToQuantum(*p++),q);
3374 SetPixelBlue(image,ScaleLongLongToQuantum(*p++),q);
cristye5370942012-01-06 03:49:31 +00003375 p++;
3376 q+=GetPixelChannels(image);
3377 }
3378 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3379 break;
3380 }
3381 return;
3382 }
cristy14d71292012-05-20 16:48:13 +00003383 length=strlen(map);
cristycafe0412012-01-10 13:29:58 +00003384 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00003385 {
cristycafe0412012-01-10 13:29:58 +00003386 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00003387 if (q == (Quantum *) NULL)
3388 break;
cristycafe0412012-01-10 13:29:58 +00003389 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00003390 {
3391 register ssize_t
3392 i;
3393
cristy14d71292012-05-20 16:48:13 +00003394 for (i=0; i < (ssize_t) length; i++)
cristye5370942012-01-06 03:49:31 +00003395 {
3396 switch (quantum_map[i])
3397 {
3398 case RedQuantum:
3399 case CyanQuantum:
3400 {
cristyb13e12a2012-01-06 21:48:27 +00003401 SetPixelRed(image,ScaleLongLongToQuantum(*p),q);
cristye5370942012-01-06 03:49:31 +00003402 break;
3403 }
3404 case GreenQuantum:
3405 case MagentaQuantum:
3406 {
cristyb13e12a2012-01-06 21:48:27 +00003407 SetPixelGreen(image,ScaleLongLongToQuantum(*p),q);
cristye5370942012-01-06 03:49:31 +00003408 break;
3409 }
3410 case BlueQuantum:
3411 case YellowQuantum:
3412 {
cristyb13e12a2012-01-06 21:48:27 +00003413 SetPixelBlue(image,ScaleLongLongToQuantum(*p),q);
cristye5370942012-01-06 03:49:31 +00003414 break;
3415 }
3416 case AlphaQuantum:
3417 {
cristyb13e12a2012-01-06 21:48:27 +00003418 SetPixelAlpha(image,ScaleLongLongToQuantum(*p),q);
cristye5370942012-01-06 03:49:31 +00003419 break;
3420 }
3421 case OpacityQuantum:
3422 {
cristyb13e12a2012-01-06 21:48:27 +00003423 SetPixelAlpha(image,ScaleLongLongToQuantum(*p),q);
cristye5370942012-01-06 03:49:31 +00003424 break;
3425 }
3426 case BlackQuantum:
3427 {
cristyb13e12a2012-01-06 21:48:27 +00003428 SetPixelBlack(image,ScaleLongLongToQuantum(*p),q);
cristye5370942012-01-06 03:49:31 +00003429 break;
3430 }
3431 case IndexQuantum:
3432 {
cristyb13e12a2012-01-06 21:48:27 +00003433 SetPixelGray(image,ScaleLongLongToQuantum(*p),q);
cristye5370942012-01-06 03:49:31 +00003434 break;
3435 }
3436 default:
3437 break;
3438 }
3439 p++;
3440 }
3441 q+=GetPixelChannels(image);
3442 }
3443 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3444 break;
3445 }
3446}
3447
cristycafe0412012-01-10 13:29:58 +00003448static void ImportQuantumPixel(Image *image,const RectangleInfo *roi,
cristy46f4be22012-01-07 00:26:39 +00003449 const char *restrict map,const QuantumType *quantum_map,const void *pixels,
3450 ExceptionInfo *exception)
cristye5370942012-01-06 03:49:31 +00003451{
3452 register const Quantum
3453 *restrict p;
3454
3455 register Quantum
cristy3fe11452012-01-09 01:27:42 +00003456 *restrict q;
cristye5370942012-01-06 03:49:31 +00003457
3458 register ssize_t
3459 x;
3460
cristy14d71292012-05-20 16:48:13 +00003461 size_t
3462 length;
3463
cristye5370942012-01-06 03:49:31 +00003464 ssize_t
3465 y;
3466
3467 p=(const Quantum *) pixels;
3468 if (LocaleCompare(map,"BGR") == 0)
3469 {
cristycafe0412012-01-10 13:29:58 +00003470 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00003471 {
cristycafe0412012-01-10 13:29:58 +00003472 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00003473 if (q == (Quantum *) NULL)
3474 break;
cristycafe0412012-01-10 13:29:58 +00003475 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00003476 {
3477 SetPixelBlue(image,*p++,q);
3478 SetPixelGreen(image,*p++,q);
3479 SetPixelRed(image,*p++,q);
3480 q+=GetPixelChannels(image);
3481 }
3482 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3483 break;
3484 }
3485 return;
3486 }
3487 if (LocaleCompare(map,"BGRA") == 0)
3488 {
cristycafe0412012-01-10 13:29:58 +00003489 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00003490 {
cristycafe0412012-01-10 13:29:58 +00003491 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00003492 if (q == (Quantum *) NULL)
3493 break;
cristycafe0412012-01-10 13:29:58 +00003494 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00003495 {
3496 SetPixelBlue(image,*p++,q);
3497 SetPixelGreen(image,*p++,q);
3498 SetPixelRed(image,*p++,q);
3499 SetPixelAlpha(image,*p++,q);
3500 q+=GetPixelChannels(image);
3501 }
3502 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3503 break;
3504 }
3505 return;
3506 }
3507 if (LocaleCompare(map,"BGRP") == 0)
3508 {
cristycafe0412012-01-10 13:29:58 +00003509 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00003510 {
cristycafe0412012-01-10 13:29:58 +00003511 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00003512 if (q == (Quantum *) NULL)
3513 break;
cristycafe0412012-01-10 13:29:58 +00003514 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00003515 {
3516 SetPixelBlue(image,*p++,q);
3517 SetPixelGreen(image,*p++,q);
3518 SetPixelRed(image,*p++,q);
3519 p++;
3520 q+=GetPixelChannels(image);
3521 }
3522 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3523 break;
3524 }
3525 return;
3526 }
3527 if (LocaleCompare(map,"I") == 0)
3528 {
cristycafe0412012-01-10 13:29:58 +00003529 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00003530 {
cristycafe0412012-01-10 13:29:58 +00003531 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00003532 if (q == (Quantum *) NULL)
3533 break;
cristycafe0412012-01-10 13:29:58 +00003534 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00003535 {
3536 SetPixelGray(image,*p++,q);
3537 q+=GetPixelChannels(image);
3538 }
3539 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3540 break;
3541 }
3542 return;
3543 }
3544 if (LocaleCompare(map,"RGB") == 0)
3545 {
cristycafe0412012-01-10 13:29:58 +00003546 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00003547 {
cristycafe0412012-01-10 13:29:58 +00003548 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00003549 if (q == (Quantum *) NULL)
3550 break;
cristycafe0412012-01-10 13:29:58 +00003551 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00003552 {
3553 SetPixelRed(image,*p++,q);
3554 SetPixelGreen(image,*p++,q);
3555 SetPixelBlue(image,*p++,q);
3556 q+=GetPixelChannels(image);
3557 }
3558 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3559 break;
3560 }
3561 return;
3562 }
3563 if (LocaleCompare(map,"RGBA") == 0)
3564 {
cristycafe0412012-01-10 13:29:58 +00003565 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00003566 {
cristycafe0412012-01-10 13:29:58 +00003567 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00003568 if (q == (Quantum *) NULL)
3569 break;
cristycafe0412012-01-10 13:29:58 +00003570 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00003571 {
3572 SetPixelRed(image,*p++,q);
3573 SetPixelGreen(image,*p++,q);
3574 SetPixelBlue(image,*p++,q);
3575 SetPixelAlpha(image,*p++,q);
3576 q+=GetPixelChannels(image);
3577 }
3578 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3579 break;
3580 }
3581 return;
3582 }
3583 if (LocaleCompare(map,"RGBP") == 0)
3584 {
cristycafe0412012-01-10 13:29:58 +00003585 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00003586 {
cristycafe0412012-01-10 13:29:58 +00003587 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00003588 if (q == (Quantum *) NULL)
3589 break;
cristycafe0412012-01-10 13:29:58 +00003590 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00003591 {
3592 SetPixelRed(image,*p++,q);
3593 SetPixelGreen(image,*p++,q);
3594 SetPixelBlue(image,*p++,q);
3595 p++;
3596 q+=GetPixelChannels(image);
3597 }
3598 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3599 break;
3600 }
3601 return;
3602 }
cristy14d71292012-05-20 16:48:13 +00003603 length=strlen(map);
cristycafe0412012-01-10 13:29:58 +00003604 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00003605 {
cristycafe0412012-01-10 13:29:58 +00003606 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00003607 if (q == (Quantum *) NULL)
3608 break;
cristycafe0412012-01-10 13:29:58 +00003609 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00003610 {
3611 register ssize_t
3612 i;
3613
cristy14d71292012-05-20 16:48:13 +00003614 for (i=0; i < (ssize_t) length; i++)
cristye5370942012-01-06 03:49:31 +00003615 {
3616 switch (quantum_map[i])
3617 {
3618 case RedQuantum:
3619 case CyanQuantum:
3620 {
3621 SetPixelRed(image,*p,q);
3622 break;
3623 }
3624 case GreenQuantum:
3625 case MagentaQuantum:
3626 {
3627 SetPixelGreen(image,*p,q);
3628 break;
3629 }
3630 case BlueQuantum:
3631 case YellowQuantum:
3632 {
3633 SetPixelBlue(image,*p,q);
3634 break;
3635 }
3636 case AlphaQuantum:
3637 {
3638 SetPixelAlpha(image,*p,q);
3639 break;
3640 }
3641 case OpacityQuantum:
3642 {
3643 SetPixelAlpha(image,*p,q);
3644 break;
3645 }
3646 case BlackQuantum:
3647 {
3648 SetPixelBlack(image,*p,q);
3649 break;
3650 }
3651 case IndexQuantum:
3652 {
3653 SetPixelGray(image,*p,q);
3654 break;
3655 }
3656 default:
3657 break;
3658 }
3659 p++;
3660 }
3661 q+=GetPixelChannels(image);
3662 }
3663 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3664 break;
3665 }
3666}
3667
cristycafe0412012-01-10 13:29:58 +00003668static void ImportShortPixel(Image *image,const RectangleInfo *roi,
cristy46f4be22012-01-07 00:26:39 +00003669 const char *restrict map,const QuantumType *quantum_map,const void *pixels,
3670 ExceptionInfo *exception)
cristye5370942012-01-06 03:49:31 +00003671{
3672 register const unsigned short
3673 *restrict p;
3674
3675 register Quantum
cristy3fe11452012-01-09 01:27:42 +00003676 *restrict q;
cristye5370942012-01-06 03:49:31 +00003677
3678 register ssize_t
3679 x;
3680
cristy14d71292012-05-20 16:48:13 +00003681 size_t
3682 length;
3683
cristye5370942012-01-06 03:49:31 +00003684 ssize_t
3685 y;
3686
3687 p=(const unsigned short *) pixels;
3688 if (LocaleCompare(map,"BGR") == 0)
3689 {
cristycafe0412012-01-10 13:29:58 +00003690 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00003691 {
cristycafe0412012-01-10 13:29:58 +00003692 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00003693 if (q == (Quantum *) NULL)
3694 break;
cristycafe0412012-01-10 13:29:58 +00003695 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00003696 {
3697 SetPixelBlue(image,ScaleShortToQuantum(*p++),q);
3698 SetPixelGreen(image,ScaleShortToQuantum(*p++),q);
3699 SetPixelRed(image,ScaleShortToQuantum(*p++),q);
3700 q+=GetPixelChannels(image);
3701 }
3702 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3703 break;
3704 }
3705 return;
3706 }
3707 if (LocaleCompare(map,"BGRA") == 0)
3708 {
cristycafe0412012-01-10 13:29:58 +00003709 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00003710 {
cristycafe0412012-01-10 13:29:58 +00003711 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00003712 if (q == (Quantum *) NULL)
3713 break;
cristycafe0412012-01-10 13:29:58 +00003714 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00003715 {
3716 SetPixelBlue(image,ScaleShortToQuantum(*p++),q);
3717 SetPixelGreen(image,ScaleShortToQuantum(*p++),q);
3718 SetPixelRed(image,ScaleShortToQuantum(*p++),q);
3719 SetPixelAlpha(image,ScaleShortToQuantum(*p++),q);
3720 q+=GetPixelChannels(image);
3721 }
3722 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3723 break;
3724 }
3725 return;
3726 }
3727 if (LocaleCompare(map,"BGRP") == 0)
3728 {
cristycafe0412012-01-10 13:29:58 +00003729 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00003730 {
cristycafe0412012-01-10 13:29:58 +00003731 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00003732 if (q == (Quantum *) NULL)
3733 break;
cristycafe0412012-01-10 13:29:58 +00003734 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00003735 {
3736 SetPixelBlue(image,ScaleShortToQuantum(*p++),q);
3737 SetPixelGreen(image,ScaleShortToQuantum(*p++),q);
3738 SetPixelRed(image,ScaleShortToQuantum(*p++),q);
3739 p++;
3740 q+=GetPixelChannels(image);
3741 }
3742 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3743 break;
3744 }
3745 return;
3746 }
3747 if (LocaleCompare(map,"I") == 0)
3748 {
cristycafe0412012-01-10 13:29:58 +00003749 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00003750 {
cristycafe0412012-01-10 13:29:58 +00003751 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00003752 if (q == (Quantum *) NULL)
3753 break;
cristycafe0412012-01-10 13:29:58 +00003754 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00003755 {
3756 SetPixelGray(image,ScaleShortToQuantum(*p++),q);
3757 q+=GetPixelChannels(image);
3758 }
3759 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3760 break;
3761 }
3762 return;
3763 }
3764 if (LocaleCompare(map,"RGB") == 0)
3765 {
cristycafe0412012-01-10 13:29:58 +00003766 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00003767 {
cristycafe0412012-01-10 13:29:58 +00003768 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00003769 if (q == (Quantum *) NULL)
3770 break;
cristycafe0412012-01-10 13:29:58 +00003771 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00003772 {
3773 SetPixelRed(image,ScaleShortToQuantum(*p++),q);
3774 SetPixelGreen(image,ScaleShortToQuantum(*p++),q);
3775 SetPixelBlue(image,ScaleShortToQuantum(*p++),q);
3776 q+=GetPixelChannels(image);
3777 }
3778 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3779 break;
3780 }
3781 return;
3782 }
3783 if (LocaleCompare(map,"RGBA") == 0)
3784 {
cristycafe0412012-01-10 13:29:58 +00003785 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00003786 {
cristycafe0412012-01-10 13:29:58 +00003787 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00003788 if (q == (Quantum *) NULL)
3789 break;
cristycafe0412012-01-10 13:29:58 +00003790 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00003791 {
3792 SetPixelRed(image,ScaleShortToQuantum(*p++),q);
3793 SetPixelGreen(image,ScaleShortToQuantum(*p++),q);
3794 SetPixelBlue(image,ScaleShortToQuantum(*p++),q);
3795 SetPixelAlpha(image,ScaleShortToQuantum(*p++),q);
3796 q+=GetPixelChannels(image);
3797 }
3798 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3799 break;
3800 }
3801 return;
3802 }
3803 if (LocaleCompare(map,"RGBP") == 0)
3804 {
cristycafe0412012-01-10 13:29:58 +00003805 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00003806 {
cristycafe0412012-01-10 13:29:58 +00003807 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00003808 if (q == (Quantum *) NULL)
3809 break;
cristycafe0412012-01-10 13:29:58 +00003810 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00003811 {
3812 SetPixelRed(image,ScaleShortToQuantum(*p++),q);
3813 SetPixelGreen(image,ScaleShortToQuantum(*p++),q);
3814 SetPixelBlue(image,ScaleShortToQuantum(*p++),q);
3815 p++;
3816 q+=GetPixelChannels(image);
3817 }
3818 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3819 break;
3820 }
3821 return;
3822 }
cristy14d71292012-05-20 16:48:13 +00003823 length=strlen(map);
cristycafe0412012-01-10 13:29:58 +00003824 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00003825 {
cristycafe0412012-01-10 13:29:58 +00003826 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00003827 if (q == (Quantum *) NULL)
3828 break;
cristycafe0412012-01-10 13:29:58 +00003829 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00003830 {
3831 register ssize_t
3832 i;
3833
cristy14d71292012-05-20 16:48:13 +00003834 for (i=0; i < (ssize_t) length; i++)
cristye5370942012-01-06 03:49:31 +00003835 {
3836 switch (quantum_map[i])
3837 {
3838 case RedQuantum:
3839 case CyanQuantum:
3840 {
3841 SetPixelRed(image,ScaleShortToQuantum(*p),q);
3842 break;
3843 }
3844 case GreenQuantum:
3845 case MagentaQuantum:
3846 {
3847 SetPixelGreen(image,ScaleShortToQuantum(*p),q);
3848 break;
3849 }
3850 case BlueQuantum:
3851 case YellowQuantum:
3852 {
3853 SetPixelBlue(image,ScaleShortToQuantum(*p),q);
3854 break;
3855 }
3856 case AlphaQuantum:
3857 {
3858 SetPixelAlpha(image,ScaleShortToQuantum(*p),q);
3859 break;
3860 }
3861 case OpacityQuantum:
3862 {
3863 SetPixelAlpha(image,ScaleShortToQuantum(*p),q);
3864 break;
3865 }
3866 case BlackQuantum:
3867 {
3868 SetPixelBlack(image,ScaleShortToQuantum(*p),q);
3869 break;
3870 }
3871 case IndexQuantum:
3872 {
3873 SetPixelGray(image,ScaleShortToQuantum(*p),q);
3874 break;
3875 }
3876 default:
3877 break;
3878 }
3879 p++;
3880 }
3881 q+=GetPixelChannels(image);
3882 }
3883 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3884 break;
3885 }
3886}
3887
cristycafe0412012-01-10 13:29:58 +00003888MagickExport MagickBooleanType ImportImagePixels(Image *image,const ssize_t x,
3889 const ssize_t y,const size_t width,const size_t height,const char *map,
3890 const StorageType type,const void *pixels,ExceptionInfo *exception)
cristy4c08aed2011-07-01 19:47:50 +00003891{
cristy4c08aed2011-07-01 19:47:50 +00003892 QuantumType
3893 *quantum_map;
3894
cristycafe0412012-01-10 13:29:58 +00003895 RectangleInfo
3896 roi;
3897
cristy4c08aed2011-07-01 19:47:50 +00003898 register ssize_t
cristye5370942012-01-06 03:49:31 +00003899 i;
cristy4c08aed2011-07-01 19:47:50 +00003900
cristy14d71292012-05-20 16:48:13 +00003901 size_t
3902 length;
3903
cristy4c08aed2011-07-01 19:47:50 +00003904 /*
3905 Allocate image structure.
3906 */
3907 assert(image != (Image *) NULL);
3908 assert(image->signature == MagickSignature);
3909 if (image->debug != MagickFalse)
3910 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
cristy14d71292012-05-20 16:48:13 +00003911 length=strlen(map);
3912 quantum_map=(QuantumType *) AcquireQuantumMemory(length,sizeof(*quantum_map));
cristy4c08aed2011-07-01 19:47:50 +00003913 if (quantum_map == (QuantumType *) NULL)
3914 ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
3915 image->filename);
cristy14d71292012-05-20 16:48:13 +00003916 for (i=0; i < (ssize_t) length; i++)
cristy4c08aed2011-07-01 19:47:50 +00003917 {
3918 switch (map[i])
3919 {
3920 case 'a':
3921 case 'A':
3922 {
3923 quantum_map[i]=AlphaQuantum;
cristy8a46d822012-08-28 23:32:39 +00003924 image->alpha_trait=BlendPixelTrait;
cristy4c08aed2011-07-01 19:47:50 +00003925 break;
3926 }
3927 case 'B':
3928 case 'b':
3929 {
3930 quantum_map[i]=BlueQuantum;
3931 break;
3932 }
3933 case 'C':
3934 case 'c':
3935 {
3936 quantum_map[i]=CyanQuantum;
cristy63240882011-08-05 19:05:27 +00003937 (void) SetImageColorspace(image,CMYKColorspace,exception);
cristy4c08aed2011-07-01 19:47:50 +00003938 break;
3939 }
3940 case 'g':
3941 case 'G':
3942 {
3943 quantum_map[i]=GreenQuantum;
3944 break;
3945 }
3946 case 'K':
3947 case 'k':
3948 {
3949 quantum_map[i]=BlackQuantum;
cristy63240882011-08-05 19:05:27 +00003950 (void) SetImageColorspace(image,CMYKColorspace,exception);
cristy4c08aed2011-07-01 19:47:50 +00003951 break;
3952 }
3953 case 'I':
3954 case 'i':
3955 {
3956 quantum_map[i]=IndexQuantum;
cristyb7b3da62012-07-05 15:43:37 +00003957 (void) SetImageColorspace(image,GRAYColorspace,exception);
cristy4c08aed2011-07-01 19:47:50 +00003958 break;
3959 }
3960 case 'm':
3961 case 'M':
3962 {
3963 quantum_map[i]=MagentaQuantum;
cristy63240882011-08-05 19:05:27 +00003964 (void) SetImageColorspace(image,CMYKColorspace,exception);
cristy4c08aed2011-07-01 19:47:50 +00003965 break;
3966 }
3967 case 'O':
3968 case 'o':
3969 {
3970 quantum_map[i]=OpacityQuantum;
cristy8a46d822012-08-28 23:32:39 +00003971 image->alpha_trait=BlendPixelTrait;
cristy4c08aed2011-07-01 19:47:50 +00003972 break;
3973 }
3974 case 'P':
3975 case 'p':
3976 {
3977 quantum_map[i]=UndefinedQuantum;
3978 break;
3979 }
3980 case 'R':
3981 case 'r':
3982 {
3983 quantum_map[i]=RedQuantum;
3984 break;
3985 }
3986 case 'Y':
3987 case 'y':
3988 {
3989 quantum_map[i]=YellowQuantum;
cristy63240882011-08-05 19:05:27 +00003990 (void) SetImageColorspace(image,CMYKColorspace,exception);
cristy4c08aed2011-07-01 19:47:50 +00003991 break;
3992 }
3993 default:
3994 {
3995 quantum_map=(QuantumType *) RelinquishMagickMemory(quantum_map);
cristy63240882011-08-05 19:05:27 +00003996 (void) ThrowMagickException(exception,GetMagickModule(),OptionError,
cristyefe601c2013-01-05 17:51:12 +00003997 "UnrecognizedPixelMap","`%s'",map);
cristy4c08aed2011-07-01 19:47:50 +00003998 return(MagickFalse);
3999 }
4000 }
4001 }
cristy63240882011-08-05 19:05:27 +00004002 if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
cristy4c08aed2011-07-01 19:47:50 +00004003 return(MagickFalse);
4004 /*
cristye5370942012-01-06 03:49:31 +00004005 Transfer the pixels from the pixel data to the image.
cristy4c08aed2011-07-01 19:47:50 +00004006 */
cristycafe0412012-01-10 13:29:58 +00004007 roi.width=width;
4008 roi.height=height;
4009 roi.x=x;
4010 roi.y=y;
cristy4c08aed2011-07-01 19:47:50 +00004011 switch (type)
4012 {
4013 case CharPixel:
4014 {
cristycafe0412012-01-10 13:29:58 +00004015 ImportCharPixel(image,&roi,map,quantum_map,pixels,exception);
cristy4c08aed2011-07-01 19:47:50 +00004016 break;
4017 }
4018 case DoublePixel:
4019 {
cristycafe0412012-01-10 13:29:58 +00004020 ImportDoublePixel(image,&roi,map,quantum_map,pixels,exception);
cristy4c08aed2011-07-01 19:47:50 +00004021 break;
4022 }
4023 case FloatPixel:
4024 {
cristycafe0412012-01-10 13:29:58 +00004025 ImportFloatPixel(image,&roi,map,quantum_map,pixels,exception);
cristy4c08aed2011-07-01 19:47:50 +00004026 break;
4027 }
cristy4c08aed2011-07-01 19:47:50 +00004028 case LongPixel:
4029 {
cristycafe0412012-01-10 13:29:58 +00004030 ImportLongPixel(image,&roi,map,quantum_map,pixels,exception);
cristy4c08aed2011-07-01 19:47:50 +00004031 break;
4032 }
cristy6c9e1682012-01-07 21:37:44 +00004033 case LongLongPixel:
4034 {
cristycafe0412012-01-10 13:29:58 +00004035 ImportLongLongPixel(image,&roi,map,quantum_map,pixels,exception);
cristy6c9e1682012-01-07 21:37:44 +00004036 break;
4037 }
cristy4c08aed2011-07-01 19:47:50 +00004038 case QuantumPixel:
4039 {
cristycafe0412012-01-10 13:29:58 +00004040 ImportQuantumPixel(image,&roi,map,quantum_map,pixels,exception);
cristy4c08aed2011-07-01 19:47:50 +00004041 break;
4042 }
4043 case ShortPixel:
4044 {
cristycafe0412012-01-10 13:29:58 +00004045 ImportShortPixel(image,&roi,map,quantum_map,pixels,exception);
cristy4c08aed2011-07-01 19:47:50 +00004046 break;
4047 }
4048 default:
4049 {
4050 quantum_map=(QuantumType *) RelinquishMagickMemory(quantum_map);
cristyc82a27b2011-10-21 01:07:16 +00004051 (void) ThrowMagickException(exception,GetMagickModule(),OptionError,
cristyefe601c2013-01-05 17:51:12 +00004052 "UnrecognizedPixelMap","`%s'",map);
cristy4c08aed2011-07-01 19:47:50 +00004053 break;
4054 }
4055 }
4056 quantum_map=(QuantumType *) RelinquishMagickMemory(quantum_map);
4057 return(MagickTrue);
4058}
4059
4060/*
4061%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4062% %
4063% %
4064% %
cristybd5a96c2011-08-21 00:04:26 +00004065+ 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 %
4066% %
4067% %
4068% %
4069%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4070%
4071% InitializePixelChannelMap() defines the standard pixel component map.
4072%
4073% The format of the InitializePixelChannelMap() method is:
4074%
4075% void InitializePixelChannelMap(Image *image)
4076%
4077% A description of each parameter follows:
4078%
4079% o image: the image.
4080%
4081*/
cristye2a912b2011-12-05 20:02:07 +00004082MagickExport void InitializePixelChannelMap(Image *image)
cristy77c30f52011-10-24 18:56:57 +00004083{
cristye2a912b2011-12-05 20:02:07 +00004084 PixelTrait
4085 trait;
4086
cristy77c30f52011-10-24 18:56:57 +00004087 register ssize_t
4088 i;
4089
cristyd26338f2011-12-14 02:39:30 +00004090 ssize_t
cristy77c30f52011-10-24 18:56:57 +00004091 n;
4092
4093 assert(image != (Image *) NULL);
4094 assert(image->signature == MagickSignature);
cristye2a912b2011-12-05 20:02:07 +00004095 (void) ResetMagickMemory(image->channel_map,0,MaxPixelChannels*
4096 sizeof(*image->channel_map));
4097 trait=UpdatePixelTrait;
cristy8a46d822012-08-28 23:32:39 +00004098 if (image->alpha_trait == BlendPixelTrait)
cristy61f18ad2011-12-08 21:12:37 +00004099 trait=(PixelTrait) (trait | BlendPixelTrait);
cristy77c30f52011-10-24 18:56:57 +00004100 n=0;
cristyc06c5802011-12-31 23:36:16 +00004101 if (image->colorspace == GRAYColorspace)
cristy77c30f52011-10-24 18:56:57 +00004102 {
cristycf1296e2012-08-26 23:40:49 +00004103 SetPixelChannelAttributes(image,BluePixelChannel,trait,n);
4104 SetPixelChannelAttributes(image,GreenPixelChannel,trait,n);
4105 SetPixelChannelAttributes(image,RedPixelChannel,trait,n++);
cristy3c316282011-12-15 15:43:24 +00004106 }
4107 else
4108 {
cristycf1296e2012-08-26 23:40:49 +00004109 SetPixelChannelAttributes(image,RedPixelChannel,trait,n++);
4110 SetPixelChannelAttributes(image,GreenPixelChannel,trait,n++);
4111 SetPixelChannelAttributes(image,BluePixelChannel,trait,n++);
cristy77c30f52011-10-24 18:56:57 +00004112 }
4113 if (image->colorspace == CMYKColorspace)
cristycf1296e2012-08-26 23:40:49 +00004114 SetPixelChannelAttributes(image,BlackPixelChannel,trait,n++);
cristy8a46d822012-08-28 23:32:39 +00004115 if (image->alpha_trait != UndefinedPixelTrait)
cristycf1296e2012-08-26 23:40:49 +00004116 SetPixelChannelAttributes(image,AlphaPixelChannel,CopyPixelTrait,n++);
cristye2a912b2011-12-05 20:02:07 +00004117 if (image->storage_class == PseudoClass)
cristycf1296e2012-08-26 23:40:49 +00004118 SetPixelChannelAttributes(image,IndexPixelChannel,CopyPixelTrait,n++);
cristy183a5c72012-01-30 01:40:35 +00004119 if (image->mask != MagickFalse)
cristycf1296e2012-08-26 23:40:49 +00004120 SetPixelChannelAttributes(image,MaskPixelChannel,CopyPixelTrait,n++);
cristye2a912b2011-12-05 20:02:07 +00004121 assert((n+image->number_meta_channels) < MaxPixelChannels);
4122 for (i=0; i < (ssize_t) image->number_meta_channels; i++)
cristycf1296e2012-08-26 23:40:49 +00004123 SetPixelChannelAttributes(image,(PixelChannel) (MetaPixelChannel+i),
4124 CopyPixelTrait,n++);
cristyd26338f2011-12-14 02:39:30 +00004125 image->number_channels=(size_t) n;
cristy77c30f52011-10-24 18:56:57 +00004126 if (image->debug != MagickFalse)
4127 LogPixelChannels(image);
cristycf1296e2012-08-26 23:40:49 +00004128 (void) SetImageChannelMask(image,image->channel_mask);
cristy77c30f52011-10-24 18:56:57 +00004129}
cristybd5a96c2011-08-21 00:04:26 +00004130
4131/*
4132%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4133% %
4134% %
4135% %
cristya085a432011-07-30 01:39:32 +00004136% I n t e r p o l a t e P i x e l C h a n n e l %
4137% %
4138% %
4139% %
4140%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4141%
cristy884f6002011-07-31 00:51:45 +00004142% InterpolatePixelChannel() applies a pixel interpolation method between a
4143% floating point coordinate and the pixels surrounding that coordinate. No
4144% pixel area resampling, or scaling of the result is performed.
cristya085a432011-07-30 01:39:32 +00004145%
anthonycf4e33d2012-06-08 07:33:23 +00004146% Interpolation is restricted to just the specified channel.
4147%
cristya085a432011-07-30 01:39:32 +00004148% The format of the InterpolatePixelChannel method is:
4149%
4150% MagickBooleanType InterpolatePixelChannel(const Image *image,
cristy444eda62011-08-10 02:07:46 +00004151% const CacheView *image_view,const PixelChannel channel,
cristy5c4e2582011-09-11 19:21:03 +00004152% const PixelInterpolateMethod method,const double x,const double y,
cristya085a432011-07-30 01:39:32 +00004153% double *pixel,ExceptionInfo *exception)
4154%
4155% A description of each parameter follows:
4156%
4157% o image: the image.
4158%
4159% o image_view: the image view.
4160%
4161% o channel: the pixel channel to interpolate.
4162%
4163% o method: the pixel color interpolation method.
4164%
4165% o x,y: A double representing the current (x,y) position of the pixel.
4166%
4167% o pixel: return the interpolated pixel here.
4168%
4169% o exception: return any errors or warnings in this structure.
4170%
4171*/
cristy94ea1632011-07-30 20:40:25 +00004172
cristyb0a657e2012-08-29 00:45:37 +00004173static inline void CatromWeights(const double x,double (*weights)[4])
cristy884f6002011-07-31 00:51:45 +00004174{
cristya19f1d72012-08-07 18:24:38 +00004175 double
cristy884f6002011-07-31 00:51:45 +00004176 alpha,
nicolasd32d5e52012-06-12 15:34:10 +00004177 beta,
cristy884f6002011-07-31 00:51:45 +00004178 gamma;
4179
cristy5a5e4d92012-08-29 00:06:25 +00004180 /*
4181 Nicolas Robidoux' 10 flops (4* + 5- + 1+) refactoring of the computation
4182 of the standard four 1D Catmull-Rom weights. The sampling location is
4183 assumed between the second and third input pixel locations, and x is the
4184 position relative to the second input pixel location. Formulas originally
4185 derived for the VIPS (Virtual Image Processing System) library.
4186 */
cristya19f1d72012-08-07 18:24:38 +00004187 alpha=(double) 1.0-x;
4188 beta=(double) (-0.5)*x*alpha;
nicolasd32d5e52012-06-12 15:34:10 +00004189 (*weights)[0]=alpha*beta;
4190 (*weights)[3]=x*beta;
4191 /*
cristy5a5e4d92012-08-29 00:06:25 +00004192 The following computation of the inner weights from the outer ones work
4193 for all Keys cubics.
nicolasd32d5e52012-06-12 15:34:10 +00004194 */
4195 gamma=(*weights)[3]-(*weights)[0];
4196 (*weights)[1]=alpha-(*weights)[0]+gamma;
4197 (*weights)[2]=x-(*weights)[3]-gamma;
4198}
4199
cristyb0a657e2012-08-29 00:45:37 +00004200static inline void SplineWeights(const double x,double (*weights)[4])
nicolasd32d5e52012-06-12 15:34:10 +00004201{
cristy5a5e4d92012-08-29 00:06:25 +00004202 double
4203 alpha,
4204 beta;
4205
nicolasd32d5e52012-06-12 15:34:10 +00004206 /*
4207 Nicolas Robidoux' 12 flops (6* + 5- + 1+) refactoring of the
4208 computation of the standard four 1D cubic B-spline smoothing
4209 weights. The sampling location is assumed between the second and
4210 third input pixel locations, and x is the position relative to the
4211 second input pixel location.
4212 */
cristya19f1d72012-08-07 18:24:38 +00004213 alpha=(double) 1.0-x;
4214 (*weights)[3]=(double) (1.0/6.0)*x*x*x;
4215 (*weights)[0]=(double) (1.0/6.0)*alpha*alpha*alpha;
nicolasd32d5e52012-06-12 15:34:10 +00004216 beta=(*weights)[3]-(*weights)[0];
4217 (*weights)[1]=alpha-(*weights)[0]+beta;
4218 (*weights)[2]=x-(*weights)[3]-beta;
cristy884f6002011-07-31 00:51:45 +00004219}
4220
cristy94ea1632011-07-30 20:40:25 +00004221static inline double MeshInterpolate(const PointInfo *delta,const double p,
4222 const double x,const double y)
4223{
4224 return(delta->x*x+delta->y*y+(1.0-delta->x-delta->y)*p);
4225}
4226
anthonycf4e33d2012-06-08 07:33:23 +00004227/*
cristya19f1d72012-08-07 18:24:38 +00004228static inline ssize_t NearestNeighbor(const double x)
cristy884f6002011-07-31 00:51:45 +00004229{
4230 if (x >= 0.0)
4231 return((ssize_t) (x+0.5));
4232 return((ssize_t) (x-0.5));
4233}
anthonycf4e33d2012-06-08 07:33:23 +00004234*/
cristy884f6002011-07-31 00:51:45 +00004235
cristya085a432011-07-30 01:39:32 +00004236MagickExport MagickBooleanType InterpolatePixelChannel(const Image *image,
4237 const CacheView *image_view,const PixelChannel channel,
cristy5c4e2582011-09-11 19:21:03 +00004238 const PixelInterpolateMethod method,const double x,const double y,
cristya085a432011-07-30 01:39:32 +00004239 double *pixel,ExceptionInfo *exception)
4240{
4241 MagickBooleanType
4242 status;
4243
cristya19f1d72012-08-07 18:24:38 +00004244 double
cristy94ea1632011-07-30 20:40:25 +00004245 alpha[16],
cristy884f6002011-07-31 00:51:45 +00004246 gamma,
4247 pixels[16];
cristy94ea1632011-07-30 20:40:25 +00004248
4249 PixelTrait
4250 traits;
4251
cristy94ea1632011-07-30 20:40:25 +00004252 register const Quantum
4253 *p;
4254
cristy50e64b82012-06-22 17:46:19 +00004255 register ssize_t
cristy94ea1632011-07-30 20:40:25 +00004256 i;
4257
cristya085a432011-07-30 01:39:32 +00004258 ssize_t
4259 x_offset,
4260 y_offset;
4261
anthonycf4e33d2012-06-08 07:33:23 +00004262 PixelInterpolateMethod
4263 interpolate;
4264
cristya085a432011-07-30 01:39:32 +00004265 assert(image != (Image *) NULL);
4266 assert(image != (Image *) NULL);
4267 assert(image->signature == MagickSignature);
4268 assert(image_view != (CacheView *) NULL);
4269 status=MagickTrue;
cristy884f6002011-07-31 00:51:45 +00004270 *pixel=0.0;
cristycf1296e2012-08-26 23:40:49 +00004271 traits=GetPixelChannelTraits(image,channel);
cristya085a432011-07-30 01:39:32 +00004272 x_offset=(ssize_t) floor(x);
4273 y_offset=(ssize_t) floor(y);
anthonycf4e33d2012-06-08 07:33:23 +00004274 interpolate = method;
4275 if ( interpolate == UndefinedInterpolatePixel )
4276 interpolate = image->interpolate;
4277 switch (interpolate)
cristya085a432011-07-30 01:39:32 +00004278 {
anthonycf4e33d2012-06-08 07:33:23 +00004279 case AverageInterpolatePixel: /* nearest 4 neighbours */
4280 case Average9InterpolatePixel: /* nearest 9 neighbours */
4281 case Average16InterpolatePixel: /* nearest 16 neighbours */
cristy884f6002011-07-31 00:51:45 +00004282 {
cristyfb122372012-10-17 23:31:21 +00004283 ssize_t
4284 count;
anthonycf4e33d2012-06-08 07:33:23 +00004285
cristyfb122372012-10-17 23:31:21 +00004286 count=2; /* size of the area to average - default nearest 4 */
anthonycf4e33d2012-06-08 07:33:23 +00004287 if (interpolate == Average9InterpolatePixel)
4288 {
4289 count=3;
4290 x_offset=(ssize_t) (floor(x+0.5)-1);
4291 y_offset=(ssize_t) (floor(y+0.5)-1);
4292 }
cristyfb122372012-10-17 23:31:21 +00004293 else
4294 if (interpolate == Average16InterpolatePixel)
4295 {
4296 count=4;
4297 x_offset--;
4298 y_offset--;
4299 }
cristy70e9f682013-03-12 22:31:22 +00004300 p=GetCacheViewVirtualPixels(image_view,x_offset,y_offset,(size_t) count,(size_t)
4301 count,exception);
cristy884f6002011-07-31 00:51:45 +00004302 if (p == (const Quantum *) NULL)
4303 {
4304 status=MagickFalse;
4305 break;
4306 }
anthonycf4e33d2012-06-08 07:33:23 +00004307 count*=count; /* Number of pixels to Average */
cristy222b19c2011-08-04 01:35:11 +00004308 if ((traits & BlendPixelTrait) == 0)
cristy50e64b82012-06-22 17:46:19 +00004309 for (i=0; i < (ssize_t) count; i++)
cristy884f6002011-07-31 00:51:45 +00004310 {
4311 alpha[i]=1.0;
cristya19f1d72012-08-07 18:24:38 +00004312 pixels[i]=(double) p[i*GetPixelChannels(image)+channel];
cristy884f6002011-07-31 00:51:45 +00004313 }
4314 else
cristy50e64b82012-06-22 17:46:19 +00004315 for (i=0; i < (ssize_t) count; i++)
cristy884f6002011-07-31 00:51:45 +00004316 {
4317 alpha[i]=QuantumScale*GetPixelAlpha(image,p+i*
4318 GetPixelChannels(image));
4319 pixels[i]=alpha[i]*p[i*GetPixelChannels(image)+channel];
4320 }
cristy50e64b82012-06-22 17:46:19 +00004321 for (i=0; i < (ssize_t) count; i++)
cristy884f6002011-07-31 00:51:45 +00004322 {
cristy3e3ec3a2012-11-03 23:11:06 +00004323 gamma=PerceptibleReciprocal(alpha[i])/count;
anthonycf4e33d2012-06-08 07:33:23 +00004324 *pixel+=gamma*pixels[i];
cristy884f6002011-07-31 00:51:45 +00004325 }
4326 break;
4327 }
anthonycf4e33d2012-06-08 07:33:23 +00004328 case BilinearInterpolatePixel:
4329 default:
4330 {
4331 PointInfo
4332 delta,
4333 epsilon;
4334
4335 p=GetCacheViewVirtualPixels(image_view,x_offset,y_offset,2,2,exception);
4336 if (p == (const Quantum *) NULL)
4337 {
4338 status=MagickFalse;
4339 break;
4340 }
4341 if ((traits & BlendPixelTrait) == 0)
4342 for (i=0; i < 4; i++)
4343 {
4344 alpha[i]=1.0;
cristya19f1d72012-08-07 18:24:38 +00004345 pixels[i]=(double) p[i*GetPixelChannels(image)+channel];
anthonycf4e33d2012-06-08 07:33:23 +00004346 }
4347 else
4348 for (i=0; i < 4; i++)
4349 {
4350 alpha[i]=QuantumScale*GetPixelAlpha(image,p+i*
4351 GetPixelChannels(image));
4352 pixels[i]=alpha[i]*p[i*GetPixelChannels(image)+channel];
4353 }
4354 delta.x=x-x_offset;
4355 delta.y=y-y_offset;
4356 epsilon.x=1.0-delta.x;
4357 epsilon.y=1.0-delta.y;
4358 gamma=((epsilon.y*(epsilon.x*alpha[0]+delta.x*alpha[1])+delta.y*
4359 (epsilon.x*alpha[2]+delta.x*alpha[3])));
cristy3e3ec3a2012-11-03 23:11:06 +00004360 gamma=PerceptibleReciprocal(gamma);
anthonycf4e33d2012-06-08 07:33:23 +00004361 *pixel=gamma*(epsilon.y*(epsilon.x*pixels[0]+delta.x*pixels[1])+delta.y*
4362 (epsilon.x*pixels[2]+delta.x*pixels[3]));
4363 break;
4364 }
anthony5f78bca2012-10-05 06:51:00 +00004365 case BlendInterpolatePixel:
4366 {
4367 p=GetCacheViewVirtualPixels(image_view,x_offset,y_offset,2,2,exception);
4368 if (p == (const Quantum *) NULL)
4369 {
4370 status=MagickFalse;
4371 break;
4372 }
4373 if ((traits & BlendPixelTrait) == 0)
4374 for (i=0; i < 4; i++)
4375 {
4376 alpha[i]=1.0;
4377 pixels[i]=(MagickRealType) p[i*GetPixelChannels(image)+channel];
4378 }
4379 else
4380 for (i=0; i < 4; i++)
4381 {
4382 alpha[i]=QuantumScale*GetPixelAlpha(image,p+i*
4383 GetPixelChannels(image));
4384 pixels[i]=alpha[i]*p[i*GetPixelChannels(image)+channel];
4385 }
4386 gamma=1.0; /* number of pixels blended together (its variable) */
4387 for (i=0; i <= 1L; i++) {
cristyfb122372012-10-17 23:31:21 +00004388 if ((y-y_offset) >= 0.75)
4389 {
4390 alpha[i]=alpha[i+2]; /* take right pixels */
4391 pixels[i]=pixels[i+2];
4392 }
4393 else
4394 if ((y-y_offset) > 0.25)
4395 {
4396 gamma=2.0; /* blend both pixels in row */
4397 alpha[i]+=alpha[i+2]; /* add up alpha weights */
4398 pixels[i]+=pixels[i+2];
4399 }
4400 }
4401 if ((x-x_offset) >= 0.75)
4402 {
4403 alpha[0]=alpha[1]; /* take bottom row blend */
4404 pixels[0]=pixels[1];
anthony5f78bca2012-10-05 06:51:00 +00004405 }
cristyfb122372012-10-17 23:31:21 +00004406 else
4407 if ((x-x_offset) > 0.25)
4408 {
4409 gamma*=2.0; /* blend both rows */
4410 alpha[0]+=alpha[1]; /* add up alpha weights */
4411 pixels[0]+=pixels[1];
4412 }
anthony5f78bca2012-10-05 06:51:00 +00004413 if (channel != AlphaPixelChannel)
cristy3e3ec3a2012-11-03 23:11:06 +00004414 gamma=PerceptibleReciprocal(alpha[0]); /* (color) 1/alpha_weights */
anthony5f78bca2012-10-05 06:51:00 +00004415 else
cristy3e3ec3a2012-11-03 23:11:06 +00004416 gamma=PerceptibleReciprocal(gamma); /* (alpha) 1/number_of_pixels */
anthony5f78bca2012-10-05 06:51:00 +00004417 *pixel=gamma*pixels[0];
4418 break;
4419 }
anthonycf4e33d2012-06-08 07:33:23 +00004420 case CatromInterpolatePixel:
cristy884f6002011-07-31 00:51:45 +00004421 {
cristya19f1d72012-08-07 18:24:38 +00004422 double
cristy380a11c2012-06-02 15:15:22 +00004423 cx[4],
nicolas6676f5a2012-06-12 16:01:15 +00004424 cy[4];
cristy884f6002011-07-31 00:51:45 +00004425
cristy884f6002011-07-31 00:51:45 +00004426 p=GetCacheViewVirtualPixels(image_view,x_offset-1,y_offset-1,4,4,
4427 exception);
4428 if (p == (const Quantum *) NULL)
4429 {
4430 status=MagickFalse;
4431 break;
4432 }
cristy222b19c2011-08-04 01:35:11 +00004433 if ((traits & BlendPixelTrait) == 0)
cristy884f6002011-07-31 00:51:45 +00004434 for (i=0; i < 16; i++)
4435 {
4436 alpha[i]=1.0;
cristya19f1d72012-08-07 18:24:38 +00004437 pixels[i]=(double) p[i*GetPixelChannels(image)+channel];
cristy884f6002011-07-31 00:51:45 +00004438 }
4439 else
4440 for (i=0; i < 16; i++)
4441 {
4442 alpha[i]=QuantumScale*GetPixelAlpha(image,p+i*
4443 GetPixelChannels(image));
4444 pixels[i]=alpha[i]*p[i*GetPixelChannels(image)+channel];
4445 }
cristya19f1d72012-08-07 18:24:38 +00004446 CatromWeights((double) (x-x_offset),&cx);
4447 CatromWeights((double) (y-y_offset),&cy);
4448 gamma=(channel == AlphaPixelChannel ? (double) 1.0 :
cristy3e3ec3a2012-11-03 23:11:06 +00004449 PerceptibleReciprocal(cy[0]*(cx[0]*alpha[0]+cx[1]*alpha[1]+cx[2]*
nicolasd32d5e52012-06-12 15:34:10 +00004450 alpha[2]+cx[3]*alpha[3])+cy[1]*(cx[0]*alpha[4]+cx[1]*alpha[5]+cx[2]*
4451 alpha[6]+cx[3]*alpha[7])+cy[2]*(cx[0]*alpha[8]+cx[1]*alpha[9]+cx[2]*
4452 alpha[10]+cx[3]*alpha[11])+cy[3]*(cx[0]*alpha[12]+cx[1]*alpha[13]+
4453 cx[2]*alpha[14]+cx[3]*alpha[15])));
cristy380a11c2012-06-02 15:15:22 +00004454 *pixel=gamma*(cy[0]*(cx[0]*pixels[0]+cx[1]*pixels[1]+cx[2]*pixels[2]+
nicolasd32d5e52012-06-12 15:34:10 +00004455 cx[3]*pixels[3])+cy[1]*(cx[0]*pixels[4]+cx[1]*pixels[5]+cx[2]*
4456 pixels[6]+cx[3]*pixels[7])+cy[2]*(cx[0]*pixels[8]+cx[1]*pixels[9]+
4457 cx[2]*pixels[10]+cx[3]*pixels[11])+cy[3]*(cx[0]*pixels[12]+cx[1]*
4458 pixels[13]+cx[2]*pixels[14]+cx[3]*pixels[15]));
cristy884f6002011-07-31 00:51:45 +00004459 break;
4460 }
anthonycf4e33d2012-06-08 07:33:23 +00004461#if 0
nicolas20075dc2012-06-12 20:47:38 +00004462 /* deprecated useless and very slow interpolator */
cristy884f6002011-07-31 00:51:45 +00004463 case FilterInterpolatePixel:
4464 {
4465 CacheView
4466 *filter_view;
4467
4468 Image
4469 *excerpt_image,
4470 *filter_image;
4471
4472 RectangleInfo
4473 geometry;
4474
4475 geometry.width=4L;
4476 geometry.height=4L;
4477 geometry.x=x_offset-1;
4478 geometry.y=y_offset-1;
4479 excerpt_image=ExcerptImage(image,&geometry,exception);
4480 if (excerpt_image == (Image *) NULL)
4481 {
4482 status=MagickFalse;
4483 break;
4484 }
cristyaa2c16c2012-03-25 22:21:35 +00004485 filter_image=ResizeImage(excerpt_image,1,1,image->filter,exception);
cristy884f6002011-07-31 00:51:45 +00004486 excerpt_image=DestroyImage(excerpt_image);
4487 if (filter_image == (Image *) NULL)
4488 break;
cristy46ff2672012-12-14 15:32:26 +00004489 filter_view=AcquireVirtualCacheView(filter_image,exception);
cristy884f6002011-07-31 00:51:45 +00004490 p=GetCacheViewVirtualPixels(filter_view,0,0,1,1,exception);
4491 if (p == (const Quantum *) NULL)
4492 status=MagickFalse;
4493 else
cristy0beccfa2011-09-25 20:47:53 +00004494 *pixel=(double) GetPixelChannel(image,channel,p);
cristy884f6002011-07-31 00:51:45 +00004495 filter_view=DestroyCacheView(filter_view);
4496 filter_image=DestroyImage(filter_image);
4497 break;
4498 }
anthonycf4e33d2012-06-08 07:33:23 +00004499#endif
cristy884f6002011-07-31 00:51:45 +00004500 case IntegerInterpolatePixel:
4501 {
4502 p=GetCacheViewVirtualPixels(image_view,x_offset,y_offset,1,1,exception);
4503 if (p == (const Quantum *) NULL)
4504 {
4505 status=MagickFalse;
4506 break;
4507 }
cristy0beccfa2011-09-25 20:47:53 +00004508 *pixel=(double) GetPixelChannel(image,channel,p);
cristy884f6002011-07-31 00:51:45 +00004509 break;
4510 }
anthonycf4e33d2012-06-08 07:33:23 +00004511 case NearestInterpolatePixel:
cristy884f6002011-07-31 00:51:45 +00004512 {
anthonycf4e33d2012-06-08 07:33:23 +00004513 x_offset=(ssize_t) floor(x+0.5);
4514 y_offset=(ssize_t) floor(y+0.5);
4515 p=GetCacheViewVirtualPixels(image_view,x_offset,y_offset,1,1,exception);
cristy884f6002011-07-31 00:51:45 +00004516 if (p == (const Quantum *) NULL)
4517 {
4518 status=MagickFalse;
4519 break;
4520 }
cristy0beccfa2011-09-25 20:47:53 +00004521 *pixel=(double) GetPixelChannel(image,channel,p);
cristy884f6002011-07-31 00:51:45 +00004522 break;
4523 }
4524 case MeshInterpolatePixel:
4525 {
4526 PointInfo
4527 delta,
cristy94ea1632011-07-30 20:40:25 +00004528 luminance;
4529
4530 p=GetCacheViewVirtualPixels(image_view,x_offset,y_offset,2,2,exception);
4531 if (p == (const Quantum *) NULL)
4532 {
4533 status=MagickFalse;
4534 break;
4535 }
cristy222b19c2011-08-04 01:35:11 +00004536 if ((traits & BlendPixelTrait) == 0)
cristy94ea1632011-07-30 20:40:25 +00004537 for (i=0; i < 4; i++)
4538 {
4539 alpha[i]=1.0;
cristya19f1d72012-08-07 18:24:38 +00004540 pixels[i]=(double) p[i*GetPixelChannels(image)+channel];
cristy94ea1632011-07-30 20:40:25 +00004541 }
4542 else
4543 for (i=0; i < 4; i++)
4544 {
4545 alpha[i]=QuantumScale*GetPixelAlpha(image,p+i*
4546 GetPixelChannels(image));
4547 pixels[i]=alpha[i]*p[i*GetPixelChannels(image)+channel];
4548 }
cristy884f6002011-07-31 00:51:45 +00004549 delta.x=x-x_offset;
4550 delta.y=y-y_offset;
4551 luminance.x=GetPixelLuminance(image,p)-(double)
4552 GetPixelLuminance(image,p+3*GetPixelChannels(image));
cristy28474bf2011-09-11 23:32:52 +00004553 luminance.y=GetPixelLuminance(image,p+GetPixelChannels(image))-(double)
cristy884f6002011-07-31 00:51:45 +00004554 GetPixelLuminance(image,p+2*GetPixelChannels(image));
cristy94ea1632011-07-30 20:40:25 +00004555 if (fabs(luminance.x) < fabs(luminance.y))
4556 {
4557 /*
4558 Diagonal 0-3 NW-SE.
4559 */
4560 if (delta.x <= delta.y)
4561 {
4562 /*
4563 Bottom-left triangle (pixel: 2, diagonal: 0-3).
4564 */
4565 delta.y=1.0-delta.y;
4566 gamma=MeshInterpolate(&delta,alpha[2],alpha[3],alpha[0]);
cristy3e3ec3a2012-11-03 23:11:06 +00004567 gamma=PerceptibleReciprocal(gamma);
cristy94ea1632011-07-30 20:40:25 +00004568 *pixel=gamma*MeshInterpolate(&delta,pixels[2],pixels[3],
4569 pixels[0]);
4570 }
4571 else
4572 {
4573 /*
4574 Top-right triangle (pixel: 1, diagonal: 0-3).
4575 */
4576 delta.x=1.0-delta.x;
4577 gamma=MeshInterpolate(&delta,alpha[1],alpha[0],alpha[3]);
cristy3e3ec3a2012-11-03 23:11:06 +00004578 gamma=PerceptibleReciprocal(gamma);
cristy94ea1632011-07-30 20:40:25 +00004579 *pixel=gamma*MeshInterpolate(&delta,pixels[1],pixels[0],
4580 pixels[3]);
4581 }
4582 }
4583 else
4584 {
4585 /*
4586 Diagonal 1-2 NE-SW.
4587 */
4588 if (delta.x <= (1.0-delta.y))
4589 {
4590 /*
4591 Top-left triangle (pixel: 0, diagonal: 1-2).
4592 */
4593 gamma=MeshInterpolate(&delta,alpha[0],alpha[1],alpha[2]);
cristy3e3ec3a2012-11-03 23:11:06 +00004594 gamma=PerceptibleReciprocal(gamma);
cristy94ea1632011-07-30 20:40:25 +00004595 *pixel=gamma*MeshInterpolate(&delta,pixels[0],pixels[1],
4596 pixels[2]);
4597 }
4598 else
4599 {
4600 /*
4601 Bottom-right triangle (pixel: 3, diagonal: 1-2).
4602 */
4603 delta.x=1.0-delta.x;
4604 delta.y=1.0-delta.y;
4605 gamma=MeshInterpolate(&delta,alpha[3],alpha[2],alpha[1]);
cristy3e3ec3a2012-11-03 23:11:06 +00004606 gamma=PerceptibleReciprocal(gamma);
cristy94ea1632011-07-30 20:40:25 +00004607 *pixel=gamma*MeshInterpolate(&delta,pixels[3],pixels[2],
4608 pixels[1]);
4609 }
4610 }
cristya085a432011-07-30 01:39:32 +00004611 break;
4612 }
cristy884f6002011-07-31 00:51:45 +00004613 case SplineInterpolatePixel:
4614 {
cristya19f1d72012-08-07 18:24:38 +00004615 double
nicolasd32d5e52012-06-12 15:34:10 +00004616 cx[4],
nicolas6676f5a2012-06-12 16:01:15 +00004617 cy[4];
cristy884f6002011-07-31 00:51:45 +00004618
4619 p=GetCacheViewVirtualPixels(image_view,x_offset-1,y_offset-1,4,4,
4620 exception);
4621 if (p == (const Quantum *) NULL)
4622 {
4623 status=MagickFalse;
4624 break;
4625 }
cristy222b19c2011-08-04 01:35:11 +00004626 if ((traits & BlendPixelTrait) == 0)
cristy884f6002011-07-31 00:51:45 +00004627 for (i=0; i < 16; i++)
4628 {
4629 alpha[i]=1.0;
cristya19f1d72012-08-07 18:24:38 +00004630 pixels[i]=(double) p[i*GetPixelChannels(image)+channel];
cristy884f6002011-07-31 00:51:45 +00004631 }
4632 else
4633 for (i=0; i < 16; i++)
4634 {
4635 alpha[i]=QuantumScale*GetPixelAlpha(image,p+i*
4636 GetPixelChannels(image));
4637 pixels[i]=alpha[i]*p[i*GetPixelChannels(image)+channel];
4638 }
cristya19f1d72012-08-07 18:24:38 +00004639 SplineWeights((double) (x-x_offset),&cx);
4640 SplineWeights((double) (y-y_offset),&cy);
4641 gamma=(channel == AlphaPixelChannel ? (double) 1.0 :
cristy3e3ec3a2012-11-03 23:11:06 +00004642 PerceptibleReciprocal(cy[0]*(cx[0]*alpha[0]+cx[1]*alpha[1]+cx[2]*
nicolasd32d5e52012-06-12 15:34:10 +00004643 alpha[2]+cx[3]*alpha[3])+cy[1]*(cx[0]*alpha[4]+cx[1]*alpha[5]+cx[2]*
4644 alpha[6]+cx[3]*alpha[7])+cy[2]*(cx[0]*alpha[8]+cx[1]*alpha[9]+cx[2]*
4645 alpha[10]+cx[3]*alpha[11])+cy[3]*(cx[0]*alpha[12]+cx[1]*alpha[13]+
4646 cx[2]*alpha[14]+cx[3]*alpha[15])));
4647 *pixel=gamma*(cy[0]*(cx[0]*pixels[0]+cx[1]*pixels[1]+cx[2]*pixels[2]+
4648 cx[3]*pixels[3])+cy[1]*(cx[0]*pixels[4]+cx[1]*pixels[5]+cx[2]*
4649 pixels[6]+cx[3]*pixels[7])+cy[2]*(cx[0]*pixels[8]+cx[1]*pixels[9]+
4650 cx[2]*pixels[10]+cx[3]*pixels[11])+cy[3]*(cx[0]*pixels[12]+cx[1]*
4651 pixels[13]+cx[2]*pixels[14]+cx[3]*pixels[15]));
cristy884f6002011-07-31 00:51:45 +00004652 break;
4653 }
cristya085a432011-07-30 01:39:32 +00004654 }
4655 return(status);
4656}
4657
4658/*
4659%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4660% %
4661% %
4662% %
cristy5c4e2582011-09-11 19:21:03 +00004663% I n t e r p o l a t e P i x e l C h a n n e l s %
4664% %
4665% %
4666% %
4667%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4668%
4669% InterpolatePixelChannels() applies a pixel interpolation method between a
4670% floating point coordinate and the pixels surrounding that coordinate. No
4671% pixel area resampling, or scaling of the result is performed.
4672%
anthonycf4e33d2012-06-08 07:33:23 +00004673% Interpolation is restricted to just the current channel setting of the
4674% destination image into which the color is to be stored
4675%
cristy5c4e2582011-09-11 19:21:03 +00004676% The format of the InterpolatePixelChannels method is:
4677%
4678% MagickBooleanType InterpolatePixelChannels(const Image *source,
4679% const CacheView *source_view,const Image *destination,
4680% const PixelInterpolateMethod method,const double x,const double y,
4681% Quantum *pixel,ExceptionInfo *exception)
4682%
4683% A description of each parameter follows:
4684%
4685% o source: the source.
4686%
4687% o source_view: the source view.
4688%
anthonycf4e33d2012-06-08 07:33:23 +00004689% o destination: the destination image, for the interpolated color
cristy5c4e2582011-09-11 19:21:03 +00004690%
4691% o method: the pixel color interpolation method.
4692%
4693% o x,y: A double representing the current (x,y) position of the pixel.
4694%
4695% o pixel: return the interpolated pixel here.
4696%
4697% o exception: return any errors or warnings in this structure.
4698%
4699*/
4700MagickExport MagickBooleanType InterpolatePixelChannels(const Image *source,
4701 const CacheView *source_view,const Image *destination,
4702 const PixelInterpolateMethod method,const double x,const double y,
4703 Quantum *pixel,ExceptionInfo *exception)
4704{
4705 MagickBooleanType
4706 status;
4707
cristya19f1d72012-08-07 18:24:38 +00004708 double
cristy5c4e2582011-09-11 19:21:03 +00004709 alpha[16],
4710 gamma,
4711 pixels[16];
4712
cristy5c4e2582011-09-11 19:21:03 +00004713 register const Quantum
4714 *p;
4715
cristy50e64b82012-06-22 17:46:19 +00004716 register ssize_t
cristy5c4e2582011-09-11 19:21:03 +00004717 i;
4718
4719 ssize_t
4720 x_offset,
4721 y_offset;
4722
anthonycf4e33d2012-06-08 07:33:23 +00004723 PixelInterpolateMethod
4724 interpolate;
4725
cristy5c4e2582011-09-11 19:21:03 +00004726 assert(source != (Image *) NULL);
4727 assert(source != (Image *) NULL);
4728 assert(source->signature == MagickSignature);
4729 assert(source_view != (CacheView *) NULL);
4730 status=MagickTrue;
4731 x_offset=(ssize_t) floor(x);
4732 y_offset=(ssize_t) floor(y);
anthonycf4e33d2012-06-08 07:33:23 +00004733 interpolate = method;
4734 if ( interpolate == UndefinedInterpolatePixel )
4735 interpolate = source->interpolate;
4736 switch (interpolate)
cristy5c4e2582011-09-11 19:21:03 +00004737 {
anthonycf4e33d2012-06-08 07:33:23 +00004738 case AverageInterpolatePixel: /* nearest 4 neighbours */
4739 case Average9InterpolatePixel: /* nearest 9 neighbours */
4740 case Average16InterpolatePixel: /* nearest 16 neighbours */
cristy5c4e2582011-09-11 19:21:03 +00004741 {
cristyfb122372012-10-17 23:31:21 +00004742 ssize_t
4743 count;
anthonycf4e33d2012-06-08 07:33:23 +00004744
cristyfb122372012-10-17 23:31:21 +00004745 count=2; /* size of the area to average - default nearest 4 */
anthonycf4e33d2012-06-08 07:33:23 +00004746 if (interpolate == Average9InterpolatePixel)
4747 {
4748 count=3;
4749 x_offset=(ssize_t) (floor(x+0.5)-1);
4750 y_offset=(ssize_t) (floor(y+0.5)-1);
4751 }
cristyfb122372012-10-17 23:31:21 +00004752 else
4753 if (interpolate == Average16InterpolatePixel)
4754 {
4755 count=4;
4756 x_offset--;
4757 y_offset--;
4758 }
cristy70e9f682013-03-12 22:31:22 +00004759 p=GetCacheViewVirtualPixels(source_view,x_offset,y_offset,(size_t) count,(size_t)
4760 count,exception);
cristy5c4e2582011-09-11 19:21:03 +00004761 if (p == (const Quantum *) NULL)
4762 {
4763 status=MagickFalse;
4764 break;
4765 }
cristyfb122372012-10-17 23:31:21 +00004766 count*=count; /* Number of pixels to Average */
cristy50e64b82012-06-22 17:46:19 +00004767 for (i=0; i < (ssize_t) GetPixelChannels(source); i++)
cristy5c4e2582011-09-11 19:21:03 +00004768 {
4769 double
4770 sum;
4771
cristy50e64b82012-06-22 17:46:19 +00004772 register ssize_t
cristy5c4e2582011-09-11 19:21:03 +00004773 j;
4774
cristy5a23c552013-02-13 14:34:28 +00004775 PixelChannel channel=GetPixelChannelChannel(source,i);
4776 PixelTrait traits=GetPixelChannelTraits(source,channel);
4777 PixelTrait destination_traits=GetPixelChannelTraits(destination,
4778 channel);
cristy5c4e2582011-09-11 19:21:03 +00004779 if ((traits == UndefinedPixelTrait) ||
4780 (destination_traits == UndefinedPixelTrait))
4781 continue;
cristy50e64b82012-06-22 17:46:19 +00004782 for (j=0; j < (ssize_t) count; j++)
cristya19f1d72012-08-07 18:24:38 +00004783 pixels[j]=(double) p[j*GetPixelChannels(source)+i];
cristy4a7ae692011-12-14 12:24:11 +00004784 sum=0.0;
cristy5c4e2582011-09-11 19:21:03 +00004785 if ((traits & BlendPixelTrait) == 0)
4786 {
cristy50e64b82012-06-22 17:46:19 +00004787 for (j=0; j < (ssize_t) count; j++)
anthonycf4e33d2012-06-08 07:33:23 +00004788 sum+=pixels[j];
4789 sum/=count;
cristy4a7ae692011-12-14 12:24:11 +00004790 SetPixelChannel(destination,channel,ClampToQuantum(sum),pixel);
cristy5c4e2582011-09-11 19:21:03 +00004791 continue;
4792 }
cristy50e64b82012-06-22 17:46:19 +00004793 for (j=0; j < (ssize_t) count; j++)
cristy5c4e2582011-09-11 19:21:03 +00004794 {
4795 alpha[j]=QuantumScale*GetPixelAlpha(source,p+j*
4796 GetPixelChannels(source));
4797 pixels[j]*=alpha[j];
cristy3e3ec3a2012-11-03 23:11:06 +00004798 gamma=PerceptibleReciprocal(alpha[j]);
anthonycf4e33d2012-06-08 07:33:23 +00004799 sum+=gamma*pixels[j];
cristy5c4e2582011-09-11 19:21:03 +00004800 }
anthonycf4e33d2012-06-08 07:33:23 +00004801 sum/=count;
cristy4a7ae692011-12-14 12:24:11 +00004802 SetPixelChannel(destination,channel,ClampToQuantum(sum),pixel);
cristy5c4e2582011-09-11 19:21:03 +00004803 }
4804 break;
4805 }
anthonycf4e33d2012-06-08 07:33:23 +00004806 case BilinearInterpolatePixel:
4807 default:
4808 {
4809 p=GetCacheViewVirtualPixels(source_view,x_offset,y_offset,2,2,exception);
4810 if (p == (const Quantum *) NULL)
4811 {
4812 status=MagickFalse;
4813 break;
4814 }
cristy50e64b82012-06-22 17:46:19 +00004815 for (i=0; i < (ssize_t) GetPixelChannels(source); i++)
anthonycf4e33d2012-06-08 07:33:23 +00004816 {
4817 PointInfo
4818 delta,
4819 epsilon;
4820
cristy5a23c552013-02-13 14:34:28 +00004821 PixelChannel channel=GetPixelChannelChannel(source,i);
4822 PixelTrait traits=GetPixelChannelTraits(source,channel);
4823 PixelTrait destination_traits=GetPixelChannelTraits(destination,
4824 channel);
anthonycf4e33d2012-06-08 07:33:23 +00004825 if ((traits == UndefinedPixelTrait) ||
4826 (destination_traits == UndefinedPixelTrait))
4827 continue;
4828 delta.x=x-x_offset;
4829 delta.y=y-y_offset;
4830 epsilon.x=1.0-delta.x;
4831 epsilon.y=1.0-delta.y;
cristya19f1d72012-08-07 18:24:38 +00004832 pixels[0]=(double) p[i];
4833 pixels[1]=(double) p[GetPixelChannels(source)+i];
4834 pixels[2]=(double) p[2*GetPixelChannels(source)+i];
4835 pixels[3]=(double) p[3*GetPixelChannels(source)+i];
anthonycf4e33d2012-06-08 07:33:23 +00004836 if ((traits & BlendPixelTrait) == 0)
4837 {
4838 gamma=((epsilon.y*(epsilon.x+delta.x)+delta.y*(epsilon.x+delta.x)));
cristy3e3ec3a2012-11-03 23:11:06 +00004839 gamma=PerceptibleReciprocal(gamma);
anthonycf4e33d2012-06-08 07:33:23 +00004840 SetPixelChannel(destination,channel,ClampToQuantum(gamma*(epsilon.y*
4841 (epsilon.x*pixels[0]+delta.x*pixels[1])+delta.y*(epsilon.x*
4842 pixels[2]+delta.x*pixels[3]))),pixel);
4843 continue;
4844 }
4845 alpha[0]=QuantumScale*GetPixelAlpha(source,p);
4846 alpha[1]=QuantumScale*GetPixelAlpha(source,p+GetPixelChannels(source));
4847 alpha[2]=QuantumScale*GetPixelAlpha(source,p+2*
4848 GetPixelChannels(source));
4849 alpha[3]=QuantumScale*GetPixelAlpha(source,p+3*
4850 GetPixelChannels(source));
4851 pixels[0]*=alpha[0];
4852 pixels[1]*=alpha[1];
4853 pixels[2]*=alpha[2];
4854 pixels[3]*=alpha[3];
4855 gamma=((epsilon.y*(epsilon.x*alpha[0]+delta.x*alpha[1])+delta.y*
4856 (epsilon.x*alpha[2]+delta.x*alpha[3])));
cristy3e3ec3a2012-11-03 23:11:06 +00004857 gamma=PerceptibleReciprocal(gamma);
anthonycf4e33d2012-06-08 07:33:23 +00004858 SetPixelChannel(destination,channel,ClampToQuantum(gamma*(epsilon.y*
4859 (epsilon.x*pixels[0]+delta.x*pixels[1])+delta.y*(epsilon.x*pixels[2]+
4860 delta.x*pixels[3]))),pixel);
4861 }
4862 break;
4863 }
anthony5f78bca2012-10-05 06:51:00 +00004864 case BlendInterpolatePixel:
4865 {
4866 p=GetCacheViewVirtualPixels(source_view,x_offset,y_offset,2,2,exception);
4867 if (p == (const Quantum *) NULL)
4868 {
4869 status=MagickFalse;
4870 break;
4871 }
4872 for (i=0; i < (ssize_t) GetPixelChannels(source); i++)
4873 {
4874 register ssize_t
4875 j;
4876
cristy5a23c552013-02-13 14:34:28 +00004877 PixelChannel channel=GetPixelChannelChannel(source,i);
4878 PixelTrait traits=GetPixelChannelTraits(source,channel);
4879 PixelTrait destination_traits=GetPixelChannelTraits(destination,
4880 channel);
anthony5f78bca2012-10-05 06:51:00 +00004881 if ((traits == UndefinedPixelTrait) ||
4882 (destination_traits == UndefinedPixelTrait))
4883 continue;
4884 if ((traits & BlendPixelTrait) == 0)
4885 for (j=0; j < 4; j++)
4886 {
4887 alpha[j]=1.0;
4888 pixels[j]=(MagickRealType) p[j*GetPixelChannels(source)+channel];
4889 }
4890 else
4891 for (j=0; j < 4; j++)
4892 {
4893 alpha[j]=QuantumScale*GetPixelAlpha(source,p+j*
4894 GetPixelChannels(source));
4895 pixels[j]=alpha[j]*p[j*GetPixelChannels(source)+channel];
4896 }
cristyfb122372012-10-17 23:31:21 +00004897 gamma=1.0; /* number of pixels blended together (its variable) */
4898 for (j=0; j <= 1L; j++)
4899 {
4900 if ((y-y_offset) >= 0.75)
4901 {
4902 alpha[j]=alpha[j+2]; /* take right pixels */
4903 pixels[j]=pixels[j+2];
4904 }
4905 else
4906 if ((y-y_offset) > 0.25)
4907 {
4908 gamma=2.0; /* blend both pixels in row */
4909 alpha[j]+=alpha[j+2]; /* add up alpha weights */
4910 pixels[j]+=pixels[j+2];
4911 }
4912 }
4913 if ((x-x_offset) >= 0.75)
4914 {
4915 alpha[0]=alpha[1]; /* take bottom row blend */
4916 pixels[0]=pixels[1];
anthony5f78bca2012-10-05 06:51:00 +00004917 }
cristyfb122372012-10-17 23:31:21 +00004918 else
4919 if ((x-x_offset) > 0.25)
4920 {
4921 gamma*=2.0; /* blend both rows */
4922 alpha[0]+=alpha[1]; /* add up alpha weights */
4923 pixels[0]+=pixels[1];
4924 }
anthony5f78bca2012-10-05 06:51:00 +00004925 if ((traits & BlendPixelTrait) == 0)
cristy3e3ec3a2012-11-03 23:11:06 +00004926 gamma=PerceptibleReciprocal(alpha[0]); /* (color) 1/alpha_weights */
anthony5f78bca2012-10-05 06:51:00 +00004927 else
cristy3e3ec3a2012-11-03 23:11:06 +00004928 gamma=PerceptibleReciprocal(gamma); /* (alpha) 1/number_of_pixels */
anthony5f78bca2012-10-05 06:51:00 +00004929 SetPixelChannel(destination,channel,ClampToQuantum(gamma*pixels[0]),
cristyfb122372012-10-17 23:31:21 +00004930 pixel);
anthony5f78bca2012-10-05 06:51:00 +00004931 }
4932 break;
4933 }
anthonycf4e33d2012-06-08 07:33:23 +00004934 case CatromInterpolatePixel:
cristy5c4e2582011-09-11 19:21:03 +00004935 {
cristya19f1d72012-08-07 18:24:38 +00004936 double
cristy380a11c2012-06-02 15:15:22 +00004937 cx[4],
4938 cy[4];
cristy5c4e2582011-09-11 19:21:03 +00004939
cristy5c4e2582011-09-11 19:21:03 +00004940 p=GetCacheViewVirtualPixels(source_view,x_offset-1,y_offset-1,4,4,
4941 exception);
4942 if (p == (const Quantum *) NULL)
4943 {
4944 status=MagickFalse;
4945 break;
4946 }
cristy50e64b82012-06-22 17:46:19 +00004947 for (i=0; i < (ssize_t) GetPixelChannels(source); i++)
cristy5c4e2582011-09-11 19:21:03 +00004948 {
4949 register ssize_t
4950 j;
4951
cristy5a23c552013-02-13 14:34:28 +00004952 PixelChannel channel=GetPixelChannelChannel(source,i);
4953 PixelTrait traits=GetPixelChannelTraits(source,channel);
4954 PixelTrait destination_traits=GetPixelChannelTraits(destination,
4955 channel);
cristy5c4e2582011-09-11 19:21:03 +00004956 if ((traits == UndefinedPixelTrait) ||
4957 (destination_traits == UndefinedPixelTrait))
4958 continue;
4959 if ((traits & BlendPixelTrait) == 0)
4960 for (j=0; j < 16; j++)
4961 {
4962 alpha[j]=1.0;
cristya19f1d72012-08-07 18:24:38 +00004963 pixels[j]=(double) p[j*GetPixelChannels(source)+i];
cristy5c4e2582011-09-11 19:21:03 +00004964 }
4965 else
4966 for (j=0; j < 16; j++)
4967 {
4968 alpha[j]=QuantumScale*GetPixelAlpha(source,p+j*
4969 GetPixelChannels(source));
4970 pixels[j]=alpha[j]*p[j*GetPixelChannels(source)+i];
4971 }
cristya19f1d72012-08-07 18:24:38 +00004972 CatromWeights((double) (x-x_offset),&cx);
4973 CatromWeights((double) (y-y_offset),&cy);
4974 gamma=((traits & BlendPixelTrait) ? (double) (1.0) :
cristy3e3ec3a2012-11-03 23:11:06 +00004975 PerceptibleReciprocal(cy[0]*(cx[0]*alpha[0]+cx[1]*alpha[1]+cx[2]*
nicolasd32d5e52012-06-12 15:34:10 +00004976 alpha[2]+cx[3]*alpha[3])+cy[1]*(cx[0]*alpha[4]+cx[1]*alpha[5]+cx[2]*
4977 alpha[6]+cx[3]*alpha[7])+cy[2]*(cx[0]*alpha[8]+cx[1]*alpha[9]+cx[2]*
4978 alpha[10]+cx[3]*alpha[11])+cy[3]*(cx[0]*alpha[12]+cx[1]*alpha[13]+
4979 cx[2]*alpha[14]+cx[3]*alpha[15])));
cristy380a11c2012-06-02 15:15:22 +00004980 SetPixelChannel(destination,channel,ClampToQuantum(gamma*(cy[0]*(cx[0]*
4981 pixels[0]+cx[1]*pixels[1]+cx[2]*pixels[2]+cx[3]*pixels[3])+cy[1]*
4982 (cx[0]*pixels[4]+cx[1]*pixels[5]+cx[2]*pixels[6]+cx[3]*pixels[7])+
4983 cy[2]*(cx[0]*pixels[8]+cx[1]*pixels[9]+cx[2]*pixels[10]+cx[3]*
nicolasd32d5e52012-06-12 15:34:10 +00004984 pixels[11])+cy[3]*(cx[0]*pixels[12]+cx[1]*pixels[13]+cx[2]*
4985 pixels[14]+cx[3]*pixels[15]))),pixel);
cristy5c4e2582011-09-11 19:21:03 +00004986 }
4987 break;
4988 }
anthonycf4e33d2012-06-08 07:33:23 +00004989#if 0
nicolas20075dc2012-06-12 20:47:38 +00004990 /* deprecated useless and very slow interpolator */
cristy5c4e2582011-09-11 19:21:03 +00004991 case FilterInterpolatePixel:
4992 {
cristy50e64b82012-06-22 17:46:19 +00004993 for (i=0; i < (ssize_t) GetPixelChannels(source); i++)
cristy5c4e2582011-09-11 19:21:03 +00004994 {
4995 CacheView
4996 *filter_view;
4997
4998 Image
4999 *excerpt_source,
5000 *filter_source;
5001
5002 RectangleInfo
5003 geometry;
5004
cristy5a23c552013-02-13 14:34:28 +00005005 PixelChannel channel=GetPixelChannelChannel(source,i);
5006 PixelTrait traits=GetPixelChannelTraits(source,channel);
5007 PixelTrait destination_traits=GetPixelChannelTraits(destination,
5008 channel);
cristy5c4e2582011-09-11 19:21:03 +00005009 if ((traits == UndefinedPixelTrait) ||
5010 (destination_traits == UndefinedPixelTrait))
5011 continue;
5012 geometry.width=4L;
5013 geometry.height=4L;
5014 geometry.x=x_offset-1;
5015 geometry.y=y_offset-1;
5016 excerpt_source=ExcerptImage(source,&geometry,exception);
5017 if (excerpt_source == (Image *) NULL)
5018 {
5019 status=MagickFalse;
5020 continue;
5021 }
cristyaa2c16c2012-03-25 22:21:35 +00005022 filter_source=ResizeImage(excerpt_source,1,1,source->filter,exception);
cristy5c4e2582011-09-11 19:21:03 +00005023 excerpt_source=DestroyImage(excerpt_source);
5024 if (filter_source == (Image *) NULL)
5025 continue;
cristy46ff2672012-12-14 15:32:26 +00005026 filter_view=AcquireVirtualCacheView(filter_source,exception);
cristy5c4e2582011-09-11 19:21:03 +00005027 p=GetCacheViewVirtualPixels(filter_view,0,0,1,1,exception);
5028 if (p == (const Quantum *) NULL)
5029 status=MagickFalse;
5030 else
cristy1861c902011-12-14 02:30:00 +00005031 {
cristy4a7ae692011-12-14 12:24:11 +00005032 SetPixelChannel(destination,channel,p[i],pixel);
cristy1861c902011-12-14 02:30:00 +00005033 }
cristy5c4e2582011-09-11 19:21:03 +00005034 filter_view=DestroyCacheView(filter_view);
5035 filter_source=DestroyImage(filter_source);
5036 }
5037 break;
5038 }
anthonycf4e33d2012-06-08 07:33:23 +00005039#endif
cristy5c4e2582011-09-11 19:21:03 +00005040 case IntegerInterpolatePixel:
5041 {
5042 p=GetCacheViewVirtualPixels(source_view,x_offset,y_offset,1,1,exception);
5043 if (p == (const Quantum *) NULL)
5044 {
5045 status=MagickFalse;
5046 break;
5047 }
cristy50e64b82012-06-22 17:46:19 +00005048 for (i=0; i < (ssize_t) GetPixelChannels(source); i++)
cristy5c4e2582011-09-11 19:21:03 +00005049 {
cristy5a23c552013-02-13 14:34:28 +00005050 PixelChannel channel=GetPixelChannelChannel(source,i);
5051 PixelTrait traits=GetPixelChannelTraits(source,channel);
5052 PixelTrait destination_traits=GetPixelChannelTraits(destination,
5053 channel);
cristy5c4e2582011-09-11 19:21:03 +00005054 if ((traits == UndefinedPixelTrait) ||
5055 (destination_traits == UndefinedPixelTrait))
5056 continue;
cristy4a7ae692011-12-14 12:24:11 +00005057 SetPixelChannel(destination,channel,p[i],pixel);
cristy5c4e2582011-09-11 19:21:03 +00005058 }
5059 break;
5060 }
anthonycf4e33d2012-06-08 07:33:23 +00005061 case NearestInterpolatePixel:
cristy5c4e2582011-09-11 19:21:03 +00005062 {
anthonycf4e33d2012-06-08 07:33:23 +00005063 x_offset=(ssize_t) floor(x+0.5);
5064 y_offset=(ssize_t) floor(y+0.5);
5065 p=GetCacheViewVirtualPixels(source_view,x_offset,y_offset,1,1,exception);
cristy5c4e2582011-09-11 19:21:03 +00005066 if (p == (const Quantum *) NULL)
5067 {
5068 status=MagickFalse;
5069 break;
5070 }
cristy50e64b82012-06-22 17:46:19 +00005071 for (i=0; i < (ssize_t) GetPixelChannels(source); i++)
cristy5c4e2582011-09-11 19:21:03 +00005072 {
cristy5a23c552013-02-13 14:34:28 +00005073 PixelChannel channel=GetPixelChannelChannel(source,i);
5074 PixelTrait traits=GetPixelChannelTraits(source,channel);
5075 PixelTrait destination_traits=GetPixelChannelTraits(destination,
5076 channel);
cristy5c4e2582011-09-11 19:21:03 +00005077 if ((traits == UndefinedPixelTrait) ||
5078 (destination_traits == UndefinedPixelTrait))
5079 continue;
cristy4a7ae692011-12-14 12:24:11 +00005080 SetPixelChannel(destination,channel,p[i],pixel);
cristy5c4e2582011-09-11 19:21:03 +00005081 }
5082 break;
5083 }
5084 case MeshInterpolatePixel:
5085 {
5086 p=GetCacheViewVirtualPixels(source_view,x_offset,y_offset,2,2,exception);
5087 if (p == (const Quantum *) NULL)
5088 {
5089 status=MagickFalse;
5090 break;
5091 }
cristy50e64b82012-06-22 17:46:19 +00005092 for (i=0; i < (ssize_t) GetPixelChannels(source); i++)
cristy5c4e2582011-09-11 19:21:03 +00005093 {
5094 PointInfo
5095 delta,
5096 luminance;
5097
cristy5a23c552013-02-13 14:34:28 +00005098 PixelChannel channel=GetPixelChannelChannel(source,i);
5099 PixelTrait traits=GetPixelChannelTraits(source,channel);
5100 PixelTrait destination_traits=GetPixelChannelTraits(destination,
5101 channel);
cristy5c4e2582011-09-11 19:21:03 +00005102 if ((traits == UndefinedPixelTrait) ||
5103 (destination_traits == UndefinedPixelTrait))
5104 continue;
cristya19f1d72012-08-07 18:24:38 +00005105 pixels[0]=(double) p[i];
5106 pixels[1]=(double) p[GetPixelChannels(source)+i];
5107 pixels[2]=(double) p[2*GetPixelChannels(source)+i];
5108 pixels[3]=(double) p[3*GetPixelChannels(source)+i];
cristy1861c902011-12-14 02:30:00 +00005109 if ((traits & BlendPixelTrait) == 0)
5110 {
5111 alpha[0]=1.0;
5112 alpha[1]=1.0;
5113 alpha[2]=1.0;
5114 alpha[3]=1.0;
5115 }
5116 else
5117 {
5118 alpha[0]=QuantumScale*GetPixelAlpha(source,p);
5119 alpha[1]=QuantumScale*GetPixelAlpha(source,p+
5120 GetPixelChannels(source));
5121 alpha[2]=QuantumScale*GetPixelAlpha(source,p+2*
5122 GetPixelChannels(source));
5123 alpha[3]=QuantumScale*GetPixelAlpha(source,p+3*
5124 GetPixelChannels(source));
5125 }
5126 delta.x=x-x_offset;
5127 delta.y=y-y_offset;
cristyfb122372012-10-17 23:31:21 +00005128 luminance.x=fabs((double) (GetPixelLuminance(source,p)-
5129 GetPixelLuminance(source,p+3*GetPixelChannels(source))));
5130 luminance.y=fabs((double) (GetPixelLuminance(source,p+
5131 GetPixelChannels(source))-GetPixelLuminance(source,p+2*
5132 GetPixelChannels(source))));
anthonycf4e33d2012-06-08 07:33:23 +00005133 if (luminance.x < luminance.y)
cristy1861c902011-12-14 02:30:00 +00005134 {
5135 /*
5136 Diagonal 0-3 NW-SE.
5137 */
5138 if (delta.x <= delta.y)
5139 {
5140 /*
5141 Bottom-left triangle (pixel: 2, diagonal: 0-3).
5142 */
5143 delta.y=1.0-delta.y;
5144 gamma=MeshInterpolate(&delta,alpha[2],alpha[3],alpha[0]);
cristy3e3ec3a2012-11-03 23:11:06 +00005145 gamma=PerceptibleReciprocal(gamma);
cristy4a7ae692011-12-14 12:24:11 +00005146 SetPixelChannel(destination,channel,ClampToQuantum(gamma*
5147 MeshInterpolate(&delta,pixels[2],pixels[3],pixels[0])),pixel);
cristy1861c902011-12-14 02:30:00 +00005148 }
5149 else
5150 {
5151 /*
5152 Top-right triangle (pixel: 1, diagonal: 0-3).
5153 */
5154 delta.x=1.0-delta.x;
5155 gamma=MeshInterpolate(&delta,alpha[1],alpha[0],alpha[3]);
cristy3e3ec3a2012-11-03 23:11:06 +00005156 gamma=PerceptibleReciprocal(gamma);
cristy4a7ae692011-12-14 12:24:11 +00005157 SetPixelChannel(destination,channel,ClampToQuantum(gamma*
5158 MeshInterpolate(&delta,pixels[1],pixels[0],pixels[3])),pixel);
cristy1861c902011-12-14 02:30:00 +00005159 }
5160 }
5161 else
5162 {
5163 /*
5164 Diagonal 1-2 NE-SW.
5165 */
5166 if (delta.x <= (1.0-delta.y))
5167 {
5168 /*
5169 Top-left triangle (pixel: 0, diagonal: 1-2).
5170 */
5171 gamma=MeshInterpolate(&delta,alpha[0],alpha[1],alpha[2]);
cristy3e3ec3a2012-11-03 23:11:06 +00005172 gamma=PerceptibleReciprocal(gamma);
cristy4a7ae692011-12-14 12:24:11 +00005173 SetPixelChannel(destination,channel,ClampToQuantum(gamma*
5174 MeshInterpolate(&delta,pixels[0],pixels[1],pixels[2])),pixel);
cristy1861c902011-12-14 02:30:00 +00005175 }
5176 else
5177 {
5178 /*
5179 Bottom-right triangle (pixel: 3, diagonal: 1-2).
5180 */
5181 delta.x=1.0-delta.x;
5182 delta.y=1.0-delta.y;
5183 gamma=MeshInterpolate(&delta,alpha[3],alpha[2],alpha[1]);
cristy3e3ec3a2012-11-03 23:11:06 +00005184 gamma=PerceptibleReciprocal(gamma);
cristy4a7ae692011-12-14 12:24:11 +00005185 SetPixelChannel(destination,channel,ClampToQuantum(gamma*
5186 MeshInterpolate(&delta,pixels[3],pixels[2],pixels[1])),pixel);
cristy1861c902011-12-14 02:30:00 +00005187 }
5188 }
cristy5c4e2582011-09-11 19:21:03 +00005189 }
5190 break;
5191 }
5192 case SplineInterpolatePixel:
5193 {
cristya19f1d72012-08-07 18:24:38 +00005194 double
nicolasd32d5e52012-06-12 15:34:10 +00005195 cx[4],
5196 cy[4];
5197
cristy5c4e2582011-09-11 19:21:03 +00005198 p=GetCacheViewVirtualPixels(source_view,x_offset-1,y_offset-1,4,4,
5199 exception);
5200 if (p == (const Quantum *) NULL)
5201 {
5202 status=MagickFalse;
5203 break;
5204 }
cristy50e64b82012-06-22 17:46:19 +00005205 for (i=0; i < (ssize_t) GetPixelChannels(source); i++)
cristy5c4e2582011-09-11 19:21:03 +00005206 {
cristy5c4e2582011-09-11 19:21:03 +00005207 register ssize_t
5208 j;
5209
cristy5a23c552013-02-13 14:34:28 +00005210 PixelChannel channel=GetPixelChannelChannel(source,i);
5211 PixelTrait traits=GetPixelChannelTraits(source,channel);
5212 PixelTrait destination_traits=GetPixelChannelTraits(destination,
5213 channel);
cristy5c4e2582011-09-11 19:21:03 +00005214 if ((traits == UndefinedPixelTrait) ||
5215 (destination_traits == UndefinedPixelTrait))
5216 continue;
5217 if ((traits & BlendPixelTrait) == 0)
5218 for (j=0; j < 16; j++)
5219 {
5220 alpha[j]=1.0;
cristya19f1d72012-08-07 18:24:38 +00005221 pixels[j]=(double) p[j*GetPixelChannels(source)+i];
cristy5c4e2582011-09-11 19:21:03 +00005222 }
5223 else
5224 for (j=0; j < 16; j++)
5225 {
5226 alpha[j]=QuantumScale*GetPixelAlpha(source,p+j*
5227 GetPixelChannels(source));
5228 pixels[j]=alpha[j]*p[j*GetPixelChannels(source)+i];
5229 }
cristya19f1d72012-08-07 18:24:38 +00005230 SplineWeights((double) (x-x_offset),&cx);
5231 SplineWeights((double) (y-y_offset),&cy);
5232 gamma=((traits & BlendPixelTrait) ? (double) (1.0) :
cristy3e3ec3a2012-11-03 23:11:06 +00005233 PerceptibleReciprocal(cy[0]*(cx[0]*alpha[0]+cx[1]*alpha[1]+cx[2]*
nicolasd32d5e52012-06-12 15:34:10 +00005234 alpha[2]+cx[3]*alpha[3])+cy[1]*(cx[0]*alpha[4]+cx[1]*alpha[5]+cx[2]*
5235 alpha[6]+cx[3]*alpha[7])+cy[2]*(cx[0]*alpha[8]+cx[1]*alpha[9]+cx[2]*
5236 alpha[10]+cx[3]*alpha[11])+cy[3]*(cx[0]*alpha[12]+cx[1]*alpha[13]+
5237 cx[2]*alpha[14]+cx[3]*alpha[15])));
5238 SetPixelChannel(destination,channel,ClampToQuantum(gamma*(cy[0]*(cx[0]*
5239 pixels[0]+cx[1]*pixels[1]+cx[2]*pixels[2]+cx[3]*pixels[3])+cy[1]*
5240 (cx[0]*pixels[4]+cx[1]*pixels[5]+cx[2]*pixels[6]+cx[3]*pixels[7])+
5241 cy[2]*(cx[0]*pixels[8]+cx[1]*pixels[9]+cx[2]*pixels[10]+cx[3]*
5242 pixels[11])+cy[3]*(cx[0]*pixels[12]+cx[1]*pixels[13]+cx[2]*
5243 pixels[14]+cx[3]*pixels[15]))),pixel);
cristy5c4e2582011-09-11 19:21:03 +00005244 }
5245 break;
5246 }
5247 }
5248 return(status);
5249}
5250
5251/*
5252%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5253% %
5254% %
5255% %
cristy9075cdb2011-07-30 01:06:23 +00005256% I n t e r p o l a t e P i x e l I n f o %
cristy4c08aed2011-07-01 19:47:50 +00005257% %
5258% %
5259% %
5260%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5261%
cristy884f6002011-07-31 00:51:45 +00005262% InterpolatePixelInfo() applies a pixel interpolation method between a
5263% floating point coordinate and the pixels surrounding that coordinate. No
5264% pixel area resampling, or scaling of the result is performed.
cristy4c08aed2011-07-01 19:47:50 +00005265%
anthonycf4e33d2012-06-08 07:33:23 +00005266% Interpolation is restricted to just RGBKA channels.
5267%
cristy4c08aed2011-07-01 19:47:50 +00005268% The format of the InterpolatePixelInfo method is:
5269%
5270% MagickBooleanType InterpolatePixelInfo(const Image *image,
cristy5c4e2582011-09-11 19:21:03 +00005271% const CacheView *image_view,const PixelInterpolateMethod method,
cristy4c08aed2011-07-01 19:47:50 +00005272% const double x,const double y,PixelInfo *pixel,
5273% ExceptionInfo *exception)
5274%
5275% A description of each parameter follows:
5276%
5277% o image: the image.
5278%
5279% o image_view: the image view.
5280%
5281% o method: the pixel color interpolation method.
5282%
5283% o x,y: A double representing the current (x,y) position of the pixel.
5284%
5285% o pixel: return the interpolated pixel here.
5286%
5287% o exception: return any errors or warnings in this structure.
5288%
5289*/
5290
5291static inline void AlphaBlendPixelInfo(const Image *image,
cristya19f1d72012-08-07 18:24:38 +00005292 const Quantum *pixel,PixelInfo *pixel_info,double *alpha)
cristy4c08aed2011-07-01 19:47:50 +00005293{
cristy8a46d822012-08-28 23:32:39 +00005294 if (image->alpha_trait != BlendPixelTrait)
cristy4c08aed2011-07-01 19:47:50 +00005295 {
5296 *alpha=1.0;
cristya19f1d72012-08-07 18:24:38 +00005297 pixel_info->red=(double) GetPixelRed(image,pixel);
5298 pixel_info->green=(double) GetPixelGreen(image,pixel);
5299 pixel_info->blue=(double) GetPixelBlue(image,pixel);
cristy4c08aed2011-07-01 19:47:50 +00005300 pixel_info->black=0.0;
5301 if (image->colorspace == CMYKColorspace)
cristya19f1d72012-08-07 18:24:38 +00005302 pixel_info->black=(double) GetPixelBlack(image,pixel);
5303 pixel_info->alpha=(double) GetPixelAlpha(image,pixel);
cristy4c08aed2011-07-01 19:47:50 +00005304 return;
5305 }
5306 *alpha=QuantumScale*GetPixelAlpha(image,pixel);
5307 pixel_info->red=(*alpha*GetPixelRed(image,pixel));
5308 pixel_info->green=(*alpha*GetPixelGreen(image,pixel));
5309 pixel_info->blue=(*alpha*GetPixelBlue(image,pixel));
5310 pixel_info->black=0.0;
5311 if (image->colorspace == CMYKColorspace)
5312 pixel_info->black=(*alpha*GetPixelBlack(image,pixel));
cristya19f1d72012-08-07 18:24:38 +00005313 pixel_info->alpha=(double) GetPixelAlpha(image,pixel);
cristy4c08aed2011-07-01 19:47:50 +00005314}
5315
cristy4c08aed2011-07-01 19:47:50 +00005316MagickExport MagickBooleanType InterpolatePixelInfo(const Image *image,
cristy5c4e2582011-09-11 19:21:03 +00005317 const CacheView *image_view,const PixelInterpolateMethod method,
cristy4c08aed2011-07-01 19:47:50 +00005318 const double x,const double y,PixelInfo *pixel,ExceptionInfo *exception)
5319{
5320 MagickBooleanType
5321 status;
5322
cristya19f1d72012-08-07 18:24:38 +00005323 double
cristy4c08aed2011-07-01 19:47:50 +00005324 alpha[16],
5325 gamma;
5326
cristy865d58d2011-07-09 00:44:52 +00005327 PixelInfo
5328 pixels[16];
5329
cristy4c08aed2011-07-01 19:47:50 +00005330 register const Quantum
5331 *p;
5332
cristy50e64b82012-06-22 17:46:19 +00005333 register ssize_t
cristy4c08aed2011-07-01 19:47:50 +00005334 i;
5335
5336 ssize_t
5337 x_offset,
5338 y_offset;
5339
anthonycf4e33d2012-06-08 07:33:23 +00005340 PixelInterpolateMethod
5341 interpolate;
5342
cristy4c08aed2011-07-01 19:47:50 +00005343 assert(image != (Image *) NULL);
5344 assert(image->signature == MagickSignature);
5345 assert(image_view != (CacheView *) NULL);
5346 status=MagickTrue;
5347 x_offset=(ssize_t) floor(x);
5348 y_offset=(ssize_t) floor(y);
anthonycf4e33d2012-06-08 07:33:23 +00005349 interpolate = method;
5350 if ( interpolate == UndefinedInterpolatePixel )
5351 interpolate = image->interpolate;
5352 switch (interpolate)
cristy4c08aed2011-07-01 19:47:50 +00005353 {
anthonycf4e33d2012-06-08 07:33:23 +00005354 case AverageInterpolatePixel: /* nearest 4 neighbours */
5355 case Average9InterpolatePixel: /* nearest 9 neighbours */
5356 case Average16InterpolatePixel: /* nearest 16 neighbours */
cristy4c08aed2011-07-01 19:47:50 +00005357 {
cristyfb122372012-10-17 23:31:21 +00005358 ssize_t
5359 count;
anthonycf4e33d2012-06-08 07:33:23 +00005360
cristyfb122372012-10-17 23:31:21 +00005361 count=2; /* size of the area to average - default nearest 4 */
anthonycf4e33d2012-06-08 07:33:23 +00005362 if (interpolate == Average9InterpolatePixel)
5363 {
5364 count=3;
5365 x_offset=(ssize_t) (floor(x+0.5)-1);
5366 y_offset=(ssize_t) (floor(y+0.5)-1);
5367 }
5368 else if (interpolate == Average16InterpolatePixel)
5369 {
5370 count=4;
5371 x_offset--;
5372 y_offset--;
5373 }
cristy70e9f682013-03-12 22:31:22 +00005374 p=GetCacheViewVirtualPixels(image_view,x_offset,y_offset,(size_t) count,(size_t)
5375 count,exception);
cristy4c08aed2011-07-01 19:47:50 +00005376 if (p == (const Quantum *) NULL)
5377 {
5378 status=MagickFalse;
5379 break;
5380 }
cristy4c08aed2011-07-01 19:47:50 +00005381 pixel->red=0.0;
5382 pixel->green=0.0;
5383 pixel->blue=0.0;
cristy4c08aed2011-07-01 19:47:50 +00005384 pixel->black=0.0;
cristy865d58d2011-07-09 00:44:52 +00005385 pixel->alpha=0.0;
anthonycf4e33d2012-06-08 07:33:23 +00005386 count*=count; /* number of pixels - square of size */
cristy50e64b82012-06-22 17:46:19 +00005387 for (i=0; i < (ssize_t) count; i++)
cristy4c08aed2011-07-01 19:47:50 +00005388 {
anthonycf4e33d2012-06-08 07:33:23 +00005389 AlphaBlendPixelInfo(image,p,pixels,alpha);
cristy3e3ec3a2012-11-03 23:11:06 +00005390 gamma=PerceptibleReciprocal(alpha[0]);
cristyfb122372012-10-17 23:31:21 +00005391 pixel->red+=gamma*pixels[0].red;
5392 pixel->green+=gamma*pixels[0].green;
5393 pixel->blue+=gamma*pixels[0].blue;
5394 pixel->black+=gamma*pixels[0].black;
5395 pixel->alpha+=pixels[0].alpha;
anthonycf4e33d2012-06-08 07:33:23 +00005396 p += GetPixelChannels(image);
cristy4c08aed2011-07-01 19:47:50 +00005397 }
anthonycf4e33d2012-06-08 07:33:23 +00005398 gamma=1.0/count; /* average weighting of each pixel in area */
cristyfb122372012-10-17 23:31:21 +00005399 pixel->red*=gamma;
5400 pixel->green*=gamma;
5401 pixel->blue*=gamma;
5402 pixel->black*=gamma;
5403 pixel->alpha*=gamma;
cristy4c08aed2011-07-01 19:47:50 +00005404 break;
5405 }
anthonycf4e33d2012-06-08 07:33:23 +00005406 case BackgroundInterpolatePixel:
5407 {
cristyfb122372012-10-17 23:31:21 +00005408 *pixel=image->background_color; /* Copy PixelInfo Structure */
anthonycf4e33d2012-06-08 07:33:23 +00005409 break;
5410 }
5411 case BilinearInterpolatePixel:
5412 default:
5413 {
5414 PointInfo
5415 delta,
5416 epsilon;
5417
5418 p=GetCacheViewVirtualPixels(image_view,x_offset,y_offset,2,2,exception);
5419 if (p == (const Quantum *) NULL)
5420 {
5421 status=MagickFalse;
5422 break;
5423 }
5424 for (i=0; i < 4L; i++)
5425 AlphaBlendPixelInfo(image,p+i*GetPixelChannels(image),pixels+i,alpha+i);
5426 delta.x=x-x_offset;
5427 delta.y=y-y_offset;
5428 epsilon.x=1.0-delta.x;
5429 epsilon.y=1.0-delta.y;
5430 gamma=((epsilon.y*(epsilon.x*alpha[0]+delta.x*alpha[1])+delta.y*
5431 (epsilon.x*alpha[2]+delta.x*alpha[3])));
cristy3e3ec3a2012-11-03 23:11:06 +00005432 gamma=PerceptibleReciprocal(gamma);
anthonycf4e33d2012-06-08 07:33:23 +00005433 pixel->red=gamma*(epsilon.y*(epsilon.x*pixels[0].red+delta.x*
5434 pixels[1].red)+delta.y*(epsilon.x*pixels[2].red+delta.x*pixels[3].red));
5435 pixel->green=gamma*(epsilon.y*(epsilon.x*pixels[0].green+delta.x*
5436 pixels[1].green)+delta.y*(epsilon.x*pixels[2].green+delta.x*
5437 pixels[3].green));
5438 pixel->blue=gamma*(epsilon.y*(epsilon.x*pixels[0].blue+delta.x*
5439 pixels[1].blue)+delta.y*(epsilon.x*pixels[2].blue+delta.x*
5440 pixels[3].blue));
5441 if (image->colorspace == CMYKColorspace)
5442 pixel->black=gamma*(epsilon.y*(epsilon.x*pixels[0].black+delta.x*
5443 pixels[1].black)+delta.y*(epsilon.x*pixels[2].black+delta.x*
5444 pixels[3].black));
5445 gamma=((epsilon.y*(epsilon.x+delta.x)+delta.y*(epsilon.x+delta.x)));
cristy3e3ec3a2012-11-03 23:11:06 +00005446 gamma=PerceptibleReciprocal(gamma);
anthonycf4e33d2012-06-08 07:33:23 +00005447 pixel->alpha=(epsilon.y*(epsilon.x*pixels[0].alpha+delta.x*
5448 pixels[1].alpha)+delta.y*(epsilon.x*pixels[2].alpha+delta.x*
5449 pixels[3].alpha));
5450 break;
5451 }
5452 case BlendInterpolatePixel:
5453 {
5454 p=GetCacheViewVirtualPixels(image_view,x_offset,y_offset,2,2,exception);
5455 if (p == (const Quantum *) NULL)
5456 {
5457 status=MagickFalse;
5458 break;
5459 }
5460 for (i=0; i < 4L; i++)
5461 AlphaBlendPixelInfo(image,p+i*GetPixelChannels(image),pixels+i,alpha+i);
cristyfb122372012-10-17 23:31:21 +00005462 gamma=1.0; /* number of pixels blended together (its variable) */
5463 for (i=0; i <= 1L; i++)
5464 {
5465 if ((y-y_offset) >= 0.75)
5466 {
5467 alpha[i]=alpha[i+2]; /* take right pixels */
5468 pixels[i]=pixels[i+2];
5469 }
5470 else
5471 if ((y-y_offset) > 0.25)
5472 {
5473 gamma=2.0; /* blend both pixels in row */
5474 alpha[i]+=alpha[i+2]; /* add up alpha weights */
5475 pixels[i].red+=pixels[i+2].red;
5476 pixels[i].green+=pixels[i+2].green;
5477 pixels[i].blue+=pixels[i+2].blue;
5478 pixels[i].black+=pixels[i+2].black;
5479 pixels[i].alpha+=pixels[i+2].alpha;
5480 }
5481 }
5482 if ((x-x_offset) >= 0.75)
5483 {
5484 alpha[0]=alpha[1];
5485 pixels[0]=pixels[1];
anthonycf4e33d2012-06-08 07:33:23 +00005486 }
cristyfb122372012-10-17 23:31:21 +00005487 else
5488 if ((x-x_offset) > 0.25)
5489 {
5490 gamma*=2.0; /* blend both rows */
5491 alpha[0]+= alpha[1]; /* add up alpha weights */
5492 pixels[0].red+=pixels[1].red;
5493 pixels[0].green+=pixels[1].green;
5494 pixels[0].blue+=pixels[1].blue;
5495 pixels[0].black+=pixels[1].black;
5496 pixels[0].alpha+=pixels[1].alpha;
5497 }
5498 gamma=1.0/gamma;
cristy3e3ec3a2012-11-03 23:11:06 +00005499 alpha[0]=PerceptibleReciprocal(alpha[0]);
cristyfb122372012-10-17 23:31:21 +00005500 pixel->red=alpha[0]*pixels[0].red;
5501 pixel->green=alpha[0]*pixels[0].green; /* divide by sum of alpha */
5502 pixel->blue=alpha[0]*pixels[0].blue;
5503 pixel->black=alpha[0]*pixels[0].black;
5504 pixel->alpha=gamma*pixels[0].alpha; /* divide by number of pixels */
anthonycf4e33d2012-06-08 07:33:23 +00005505 break;
5506 }
5507 case CatromInterpolatePixel:
cristy4c08aed2011-07-01 19:47:50 +00005508 {
cristya19f1d72012-08-07 18:24:38 +00005509 double
cristy380a11c2012-06-02 15:15:22 +00005510 cx[4],
5511 cy[4];
cristy4c08aed2011-07-01 19:47:50 +00005512
cristy4c08aed2011-07-01 19:47:50 +00005513 p=GetCacheViewVirtualPixels(image_view,x_offset-1,y_offset-1,4,4,
5514 exception);
5515 if (p == (const Quantum *) NULL)
5516 {
5517 status=MagickFalse;
5518 break;
5519 }
anthonycf4e33d2012-06-08 07:33:23 +00005520 for (i=0; i < 16L; i++)
5521 AlphaBlendPixelInfo(image,p+i*GetPixelChannels(image),pixels+i,alpha+i);
cristya19f1d72012-08-07 18:24:38 +00005522 CatromWeights((double) (x-x_offset),&cx);
5523 CatromWeights((double) (y-y_offset),&cy);
cristyfb122372012-10-17 23:31:21 +00005524 pixel->red=(cy[0]*(cx[0]*pixels[0].red+cx[1]*pixels[1].red+cx[2]*
5525 pixels[2].red+cx[3]*pixels[3].red)+cy[1]*(cx[0]*pixels[4].red+cx[1]*
5526 pixels[5].red+cx[2]*pixels[6].red+cx[3]*pixels[7].red)+cy[2]*(cx[0]*
5527 pixels[8].red+cx[1]*pixels[9].red+cx[2]*pixels[10].red+cx[3]*
5528 pixels[11].red)+cy[3]*(cx[0]*pixels[12].red+cx[1]*pixels[13].red+cx[2]*
5529 pixels[14].red+cx[3]*pixels[15].red));
5530 pixel->green=(cy[0]*(cx[0]*pixels[0].green+cx[1]*pixels[1].green+cx[2]*
5531 pixels[2].green+cx[3]*pixels[3].green)+cy[1]*(cx[0]*pixels[4].green+
5532 cx[1]*pixels[5].green+cx[2]*pixels[6].green+cx[3]*pixels[7].green)+
5533 cy[2]*(cx[0]*pixels[8].green+cx[1]*pixels[9].green+cx[2]*
5534 pixels[10].green+cx[3]*pixels[11].green)+cy[3]*(cx[0]*
5535 pixels[12].green+cx[1]*pixels[13].green+cx[2]*pixels[14].green+cx[3]*
5536 pixels[15].green));
5537 pixel->blue=(cy[0]*(cx[0]*pixels[0].blue+cx[1]*pixels[1].blue+cx[2]*
5538 pixels[2].blue+cx[3]*pixels[3].blue)+cy[1]*(cx[0]*pixels[4].blue+cx[1]*
5539 pixels[5].blue+cx[2]*pixels[6].blue+cx[3]*pixels[7].blue)+cy[2]*(cx[0]*
5540 pixels[8].blue+cx[1]*pixels[9].blue+cx[2]*pixels[10].blue+cx[3]*
5541 pixels[11].blue)+cy[3]*(cx[0]*pixels[12].blue+cx[1]*pixels[13].blue+
5542 cx[2]*pixels[14].blue+cx[3]*pixels[15].blue));
cristy380a11c2012-06-02 15:15:22 +00005543 if (image->colorspace == CMYKColorspace)
cristyfb122372012-10-17 23:31:21 +00005544 pixel->black=(cy[0]*(cx[0]*pixels[0].black+cx[1]*pixels[1].black+cx[2]*
5545 pixels[2].black+cx[3]*pixels[3].black)+cy[1]*(cx[0]*pixels[4].black+
5546 cx[1]*pixels[5].black+cx[2]*pixels[6].black+cx[3]*pixels[7].black)+
5547 cy[2]*(cx[0]*pixels[8].black+cx[1]*pixels[9].black+cx[2]*
5548 pixels[10].black+cx[3]*pixels[11].black)+cy[3]*(cx[0]*
5549 pixels[12].black+cx[1]*pixels[13].black+cx[2]*pixels[14].black+cx[3]*
5550 pixels[15].black));
5551 pixel->alpha=(cy[0]*(cx[0]*pixels[0].alpha+cx[1]*pixels[1].alpha+cx[2]*
5552 pixels[2].alpha+cx[3]*pixels[3].alpha)+cy[1]*(cx[0]*pixels[4].alpha+
5553 cx[1]*pixels[5].alpha+cx[2]*pixels[6].alpha+cx[3]*pixels[7].alpha)+
5554 cy[2]*(cx[0]*pixels[8].alpha+cx[1]*pixels[9].alpha+cx[2]*
5555 pixels[10].alpha+cx[3]*pixels[11].alpha)+cy[3]*(cx[0]*pixels[12].alpha+
5556 cx[1]*pixels[13].alpha+cx[2]*pixels[14].alpha+cx[3]*pixels[15].alpha));
cristy4c08aed2011-07-01 19:47:50 +00005557 break;
5558 }
anthonycf4e33d2012-06-08 07:33:23 +00005559#if 0
nicolas20075dc2012-06-12 20:47:38 +00005560 /* deprecated useless and very slow interpolator */
cristy4c08aed2011-07-01 19:47:50 +00005561 case FilterInterpolatePixel:
5562 {
5563 CacheView
5564 *filter_view;
5565
5566 Image
5567 *excerpt_image,
5568 *filter_image;
5569
5570 RectangleInfo
5571 geometry;
5572
5573 geometry.width=4L;
5574 geometry.height=4L;
5575 geometry.x=x_offset-1;
5576 geometry.y=y_offset-1;
5577 excerpt_image=ExcerptImage(image,&geometry,exception);
5578 if (excerpt_image == (Image *) NULL)
5579 {
5580 status=MagickFalse;
5581 break;
5582 }
cristyaa2c16c2012-03-25 22:21:35 +00005583 filter_image=ResizeImage(excerpt_image,1,1,image->filter,exception);
cristy4c08aed2011-07-01 19:47:50 +00005584 excerpt_image=DestroyImage(excerpt_image);
5585 if (filter_image == (Image *) NULL)
5586 break;
cristy46ff2672012-12-14 15:32:26 +00005587 filter_view=AcquireVirtualCacheView(filter_image,exception);
cristy4c08aed2011-07-01 19:47:50 +00005588 p=GetCacheViewVirtualPixels(filter_view,0,0,1,1,exception);
5589 if (p != (const Quantum *) NULL)
cristy803640d2011-11-17 02:11:32 +00005590 GetPixelInfoPixel(image,p,pixel);
cristy4c08aed2011-07-01 19:47:50 +00005591 filter_view=DestroyCacheView(filter_view);
5592 filter_image=DestroyImage(filter_image);
5593 break;
5594 }
anthonycf4e33d2012-06-08 07:33:23 +00005595#endif
cristy4c08aed2011-07-01 19:47:50 +00005596 case IntegerInterpolatePixel:
5597 {
5598 p=GetCacheViewVirtualPixels(image_view,x_offset,y_offset,1,1,exception);
5599 if (p == (const Quantum *) NULL)
5600 {
5601 status=MagickFalse;
5602 break;
5603 }
cristy803640d2011-11-17 02:11:32 +00005604 GetPixelInfoPixel(image,p,pixel);
cristy4c08aed2011-07-01 19:47:50 +00005605 break;
5606 }
5607 case MeshInterpolatePixel:
5608 {
5609 PointInfo
5610 delta,
5611 luminance;
5612
cristy94ea1632011-07-30 20:40:25 +00005613 p=GetCacheViewVirtualPixels(image_view,x_offset,y_offset,2,2,exception);
cristy4c08aed2011-07-01 19:47:50 +00005614 if (p == (const Quantum *) NULL)
5615 {
5616 status=MagickFalse;
5617 break;
5618 }
cristy94ea1632011-07-30 20:40:25 +00005619 delta.x=x-x_offset;
5620 delta.y=y-y_offset;
cristy884f6002011-07-31 00:51:45 +00005621 luminance.x=GetPixelLuminance(image,p)-(double)
cristy94ea1632011-07-30 20:40:25 +00005622 GetPixelLuminance(image,p+3*GetPixelChannels(image));
cristy28474bf2011-09-11 23:32:52 +00005623 luminance.y=GetPixelLuminance(image,p+GetPixelChannels(image))-(double)
cristy94ea1632011-07-30 20:40:25 +00005624 GetPixelLuminance(image,p+2*GetPixelChannels(image));
cristy5ce8df82011-07-07 14:52:23 +00005625 AlphaBlendPixelInfo(image,p,pixels+0,alpha+0);
cristy28474bf2011-09-11 23:32:52 +00005626 AlphaBlendPixelInfo(image,p+GetPixelChannels(image),pixels+1,alpha+1);
cristyed231572011-07-14 02:18:59 +00005627 AlphaBlendPixelInfo(image,p+2*GetPixelChannels(image),pixels+2,alpha+2);
5628 AlphaBlendPixelInfo(image,p+3*GetPixelChannels(image),pixels+3,alpha+3);
cristy4c08aed2011-07-01 19:47:50 +00005629 if (fabs(luminance.x) < fabs(luminance.y))
5630 {
5631 /*
5632 Diagonal 0-3 NW-SE.
5633 */
5634 if (delta.x <= delta.y)
5635 {
5636 /*
cristy94ea1632011-07-30 20:40:25 +00005637 Bottom-left triangle (pixel: 2, diagonal: 0-3).
cristy4c08aed2011-07-01 19:47:50 +00005638 */
5639 delta.y=1.0-delta.y;
5640 gamma=MeshInterpolate(&delta,alpha[2],alpha[3],alpha[0]);
cristy3e3ec3a2012-11-03 23:11:06 +00005641 gamma=PerceptibleReciprocal(gamma);
cristy4c08aed2011-07-01 19:47:50 +00005642 pixel->red=gamma*MeshInterpolate(&delta,pixels[2].red,
5643 pixels[3].red,pixels[0].red);
5644 pixel->green=gamma*MeshInterpolate(&delta,pixels[2].green,
5645 pixels[3].green,pixels[0].green);
5646 pixel->blue=gamma*MeshInterpolate(&delta,pixels[2].blue,
5647 pixels[3].blue,pixels[0].blue);
cristy4c08aed2011-07-01 19:47:50 +00005648 if (image->colorspace == CMYKColorspace)
5649 pixel->black=gamma*MeshInterpolate(&delta,pixels[2].black,
5650 pixels[3].black,pixels[0].black);
cristy94ea1632011-07-30 20:40:25 +00005651 gamma=MeshInterpolate(&delta,1.0,1.0,1.0);
cristy865d58d2011-07-09 00:44:52 +00005652 pixel->alpha=gamma*MeshInterpolate(&delta,pixels[2].alpha,
5653 pixels[3].alpha,pixels[0].alpha);
cristy4c08aed2011-07-01 19:47:50 +00005654 }
5655 else
5656 {
5657 /*
cristy94ea1632011-07-30 20:40:25 +00005658 Top-right triangle (pixel:1 , diagonal: 0-3).
cristy4c08aed2011-07-01 19:47:50 +00005659 */
5660 delta.x=1.0-delta.x;
5661 gamma=MeshInterpolate(&delta,alpha[1],alpha[0],alpha[3]);
cristy3e3ec3a2012-11-03 23:11:06 +00005662 gamma=PerceptibleReciprocal(gamma);
cristy4c08aed2011-07-01 19:47:50 +00005663 pixel->red=gamma*MeshInterpolate(&delta,pixels[1].red,
5664 pixels[0].red,pixels[3].red);
5665 pixel->green=gamma*MeshInterpolate(&delta,pixels[1].green,
5666 pixels[0].green,pixels[3].green);
5667 pixel->blue=gamma*MeshInterpolate(&delta,pixels[1].blue,
5668 pixels[0].blue,pixels[3].blue);
cristy4c08aed2011-07-01 19:47:50 +00005669 if (image->colorspace == CMYKColorspace)
5670 pixel->black=gamma*MeshInterpolate(&delta,pixels[1].black,
5671 pixels[0].black,pixels[3].black);
cristy94ea1632011-07-30 20:40:25 +00005672 gamma=MeshInterpolate(&delta,1.0,1.0,1.0);
cristy865d58d2011-07-09 00:44:52 +00005673 pixel->alpha=gamma*MeshInterpolate(&delta,pixels[1].alpha,
5674 pixels[0].alpha,pixels[3].alpha);
cristy4c08aed2011-07-01 19:47:50 +00005675 }
5676 }
5677 else
5678 {
5679 /*
5680 Diagonal 1-2 NE-SW.
5681 */
5682 if (delta.x <= (1.0-delta.y))
5683 {
5684 /*
cristy94ea1632011-07-30 20:40:25 +00005685 Top-left triangle (pixel: 0, diagonal: 1-2).
cristy4c08aed2011-07-01 19:47:50 +00005686 */
5687 gamma=MeshInterpolate(&delta,alpha[0],alpha[1],alpha[2]);
cristy3e3ec3a2012-11-03 23:11:06 +00005688 gamma=PerceptibleReciprocal(gamma);
cristy4c08aed2011-07-01 19:47:50 +00005689 pixel->red=gamma*MeshInterpolate(&delta,pixels[0].red,
5690 pixels[1].red,pixels[2].red);
5691 pixel->green=gamma*MeshInterpolate(&delta,pixels[0].green,
5692 pixels[1].green,pixels[2].green);
5693 pixel->blue=gamma*MeshInterpolate(&delta,pixels[0].blue,
5694 pixels[1].blue,pixels[2].blue);
cristy4c08aed2011-07-01 19:47:50 +00005695 if (image->colorspace == CMYKColorspace)
5696 pixel->black=gamma*MeshInterpolate(&delta,pixels[0].black,
5697 pixels[1].black,pixels[2].black);
cristy94ea1632011-07-30 20:40:25 +00005698 gamma=MeshInterpolate(&delta,1.0,1.0,1.0);
cristy865d58d2011-07-09 00:44:52 +00005699 pixel->alpha=gamma*MeshInterpolate(&delta,pixels[0].alpha,
5700 pixels[1].alpha,pixels[2].alpha);
cristy4c08aed2011-07-01 19:47:50 +00005701 }
5702 else
5703 {
5704 /*
5705 Bottom-right triangle (pixel: 3, diagonal: 1-2).
5706 */
5707 delta.x=1.0-delta.x;
5708 delta.y=1.0-delta.y;
5709 gamma=MeshInterpolate(&delta,alpha[3],alpha[2],alpha[1]);
cristy3e3ec3a2012-11-03 23:11:06 +00005710 gamma=PerceptibleReciprocal(gamma);
cristy4c08aed2011-07-01 19:47:50 +00005711 pixel->red=gamma*MeshInterpolate(&delta,pixels[3].red,
5712 pixels[2].red,pixels[1].red);
5713 pixel->green=gamma*MeshInterpolate(&delta,pixels[3].green,
5714 pixels[2].green,pixels[1].green);
5715 pixel->blue=gamma*MeshInterpolate(&delta,pixels[3].blue,
5716 pixels[2].blue,pixels[1].blue);
cristy4c08aed2011-07-01 19:47:50 +00005717 if (image->colorspace == CMYKColorspace)
5718 pixel->black=gamma*MeshInterpolate(&delta,pixels[3].black,
5719 pixels[2].black,pixels[1].black);
cristy94ea1632011-07-30 20:40:25 +00005720 gamma=MeshInterpolate(&delta,1.0,1.0,1.0);
cristy865d58d2011-07-09 00:44:52 +00005721 pixel->alpha=gamma*MeshInterpolate(&delta,pixels[3].alpha,
5722 pixels[2].alpha,pixels[1].alpha);
cristy4c08aed2011-07-01 19:47:50 +00005723 }
5724 }
5725 break;
5726 }
anthonycf4e33d2012-06-08 07:33:23 +00005727 case NearestInterpolatePixel:
cristy4c08aed2011-07-01 19:47:50 +00005728 {
anthonycf4e33d2012-06-08 07:33:23 +00005729 x_offset=(ssize_t) floor(x+0.5);
5730 y_offset=(ssize_t) floor(y+0.5);
5731 p=GetCacheViewVirtualPixels(image_view,x_offset,y_offset,1,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00005732 if (p == (const Quantum *) NULL)
5733 {
5734 status=MagickFalse;
5735 break;
5736 }
cristy803640d2011-11-17 02:11:32 +00005737 GetPixelInfoPixel(image,p,pixel);
cristy4c08aed2011-07-01 19:47:50 +00005738 break;
5739 }
5740 case SplineInterpolatePixel:
5741 {
cristya19f1d72012-08-07 18:24:38 +00005742 double
nicolasd32d5e52012-06-12 15:34:10 +00005743 cx[4],
5744 cy[4];
cristy4c08aed2011-07-01 19:47:50 +00005745
5746 p=GetCacheViewVirtualPixels(image_view,x_offset-1,y_offset-1,4,4,
5747 exception);
5748 if (p == (const Quantum *) NULL)
5749 {
5750 status=MagickFalse;
5751 break;
5752 }
anthonycf4e33d2012-06-08 07:33:23 +00005753 for (i=0; i < 16L; i++)
5754 AlphaBlendPixelInfo(image,p+i*GetPixelChannels(image),pixels+i,alpha+i);
cristya19f1d72012-08-07 18:24:38 +00005755 SplineWeights((double) (x-x_offset),&cx);
5756 SplineWeights((double) (y-y_offset),&cy);
cristyfb122372012-10-17 23:31:21 +00005757 pixel->red=(cy[0]*(cx[0]*pixels[0].red+cx[1]*pixels[1].red+cx[2]*
5758 pixels[2].red+cx[3]*pixels[3].red)+cy[1]*(cx[0]*pixels[4].red+cx[1]*
5759 pixels[5].red+cx[2]*pixels[6].red+cx[3]*pixels[7].red)+cy[2]*(cx[0]*
5760 pixels[8].red+cx[1]*pixels[9].red+cx[2]*pixels[10].red+cx[3]*
5761 pixels[11].red)+cy[3]*(cx[0]*pixels[12].red+cx[1]*pixels[13].red+cx[2]*
5762 pixels[14].red+cx[3]*pixels[15].red));
5763 pixel->green=(cy[0]*(cx[0]*pixels[0].green+cx[1]*pixels[1].green+cx[2]*
5764 pixels[2].green+cx[3]*pixels[3].green)+cy[1]*(cx[0]*pixels[4].green+
5765 cx[1]*pixels[5].green+cx[2]*pixels[6].green+cx[3]*pixels[7].green)+
5766 cy[2]*(cx[0]*pixels[8].green+cx[1]*pixels[9].green+cx[2]*
5767 pixels[10].green+cx[3]*pixels[11].green)+cy[3]*(cx[0]*pixels[12].green+
5768 cx[1]*pixels[13].green+cx[2]*pixels[14].green+cx[3]*pixels[15].green));
5769 pixel->blue=(cy[0]*(cx[0]*pixels[0].blue+cx[1]*pixels[1].blue+cx[2]*
5770 pixels[2].blue+cx[3]*pixels[3].blue)+cy[1]*(cx[0]*pixels[4].blue+cx[1]*
5771 pixels[5].blue+cx[2]*pixels[6].blue+cx[3]*pixels[7].blue)+cy[2]*(cx[0]*
5772 pixels[8].blue+cx[1]*pixels[9].blue+cx[2]*pixels[10].blue+cx[3]*
5773 pixels[11].blue)+cy[3]*(cx[0]*pixels[12].blue+cx[1]*pixels[13].blue+
5774 cx[2]*pixels[14].blue+cx[3]*pixels[15].blue));
nicolasd32d5e52012-06-12 15:34:10 +00005775 if (image->colorspace == CMYKColorspace)
cristyfb122372012-10-17 23:31:21 +00005776 pixel->black=(cy[0]*(cx[0]*pixels[0].black+cx[1]*pixels[1].black+cx[2]*
5777 pixels[2].black+cx[3]*pixels[3].black)+cy[1]*(cx[0]*pixels[4].black+
5778 cx[1]*pixels[5].black+cx[2]*pixels[6].black+cx[3]*pixels[7].black)+
5779 cy[2]*(cx[0]*pixels[8].black+cx[1]*pixels[9].black+cx[2]*
5780 pixels[10].black+cx[3]*pixels[11].black)+cy[3]*(cx[0]*
5781 pixels[12].black+cx[1]*pixels[13].black+cx[2]*pixels[14].black+cx[3]*
5782 pixels[15].black));
5783 pixel->alpha=(cy[0]*(cx[0]*pixels[0].alpha+cx[1]*pixels[1].alpha+cx[2]*
5784 pixels[2].alpha+cx[3]*pixels[3].alpha)+cy[1]*(cx[0]*pixels[4].alpha+
5785 cx[1]*pixels[5].alpha+cx[2]*pixels[6].alpha+cx[3]*pixels[7].alpha)+
5786 cy[2]*(cx[0]*pixels[8].alpha+cx[1]*pixels[9].alpha+cx[2]*
5787 pixels[10].alpha+cx[3]*pixels[11].alpha)+cy[3]*(cx[0]*pixels[12].alpha+
5788 cx[1]*pixels[13].alpha+cx[2]*pixels[14].alpha+cx[3]*pixels[15].alpha));
cristy4c08aed2011-07-01 19:47:50 +00005789 break;
5790 }
5791 }
5792 return(status);
5793}
5794
5795/*
5796%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5797% %
5798% %
5799% %
5800+ I s F u z z y E q u i v a l e n c e P i x e l %
5801% %
5802% %
5803% %
5804%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5805%
5806% IsFuzzyEquivalencePixel() returns MagickTrue if the distance between two
5807% pixels is less than the specified distance in a linear three (or four)u
5808% dimensional color space.
5809%
5810% The format of the IsFuzzyEquivalencePixel method is:
5811%
cristye4a40472011-12-22 02:56:19 +00005812% void IsFuzzyEquivalencePixel(const Image *source,const Quantum *p,
5813% const Image *destination,const Quantum *q)
cristy4c08aed2011-07-01 19:47:50 +00005814%
5815% A description of each parameter follows:
5816%
cristye4a40472011-12-22 02:56:19 +00005817% o source: the source image.
cristy4c08aed2011-07-01 19:47:50 +00005818%
5819% o p: Pixel p.
5820%
cristye4a40472011-12-22 02:56:19 +00005821% o destination: the destination image.
5822%
cristy4c08aed2011-07-01 19:47:50 +00005823% o q: Pixel q.
5824%
5825*/
cristye4a40472011-12-22 02:56:19 +00005826MagickExport MagickBooleanType IsFuzzyEquivalencePixel(const Image *source,
5827 const Quantum *p,const Image *destination,const Quantum *q)
cristy4c08aed2011-07-01 19:47:50 +00005828{
cristya19f1d72012-08-07 18:24:38 +00005829 double
cristy4c08aed2011-07-01 19:47:50 +00005830 fuzz,
5831 pixel;
5832
cristya19f1d72012-08-07 18:24:38 +00005833 register double
cristy4c08aed2011-07-01 19:47:50 +00005834 distance,
5835 scale;
5836
cristya19f1d72012-08-07 18:24:38 +00005837 fuzz=MagickMax(source->fuzz,(double) MagickSQ1_2)*MagickMax(
5838 destination->fuzz,(double) MagickSQ1_2);
cristy4c08aed2011-07-01 19:47:50 +00005839 scale=1.0;
5840 distance=0.0;
cristy8a46d822012-08-28 23:32:39 +00005841 if (source->alpha_trait == BlendPixelTrait)
cristy4c08aed2011-07-01 19:47:50 +00005842 {
5843 /*
5844 Transparencies are involved - set alpha distance
5845 */
cristy70e9f682013-03-12 22:31:22 +00005846 pixel=GetPixelAlpha(source,p)-(double) GetPixelAlpha(destination,q);
cristy4c08aed2011-07-01 19:47:50 +00005847 distance=pixel*pixel;
5848 if (distance > fuzz)
5849 return(MagickFalse);
5850 /*
5851 Generate a alpha scaling factor to generate a 4D cone on colorspace
5852 Note that if one color is transparent, distance has no color component.
5853 */
cristye4a40472011-12-22 02:56:19 +00005854 scale=QuantumScale*GetPixelAlpha(source,p);
5855 scale*=QuantumScale*GetPixelAlpha(destination,q);
cristy4c08aed2011-07-01 19:47:50 +00005856 if (scale <= MagickEpsilon)
5857 return(MagickTrue);
5858 }
5859 /*
5860 RGB or CMY color cube
5861 */
5862 distance*=3.0; /* rescale appropriately */
5863 fuzz*=3.0;
cristya19f1d72012-08-07 18:24:38 +00005864 pixel=GetPixelRed(source,p)-(double) GetPixelRed(destination,q);
cristye4a40472011-12-22 02:56:19 +00005865 if ((source->colorspace == HSLColorspace) ||
5866 (source->colorspace == HSBColorspace) ||
5867 (source->colorspace == HWBColorspace))
cristy4c08aed2011-07-01 19:47:50 +00005868 {
5869 /*
5870 Compute an arc distance for hue. It should be a vector angle of
5871 'S'/'W' length with 'L'/'B' forming appropriate cones.
5872 */
5873 if (fabs((double) pixel) > (QuantumRange/2))
5874 pixel-=QuantumRange;
5875 pixel*=2;
5876 }
5877 distance+=scale*pixel*pixel;
5878 if (distance > fuzz)
5879 return(MagickFalse);
cristya19f1d72012-08-07 18:24:38 +00005880 pixel=GetPixelGreen(source,p)-(double) GetPixelGreen(destination,q);
cristy4c08aed2011-07-01 19:47:50 +00005881 distance+=scale*pixel*pixel;
5882 if (distance > fuzz)
5883 return(MagickFalse);
cristya19f1d72012-08-07 18:24:38 +00005884 pixel=GetPixelBlue(source,p)-(double) GetPixelBlue(destination,q);
cristy4c08aed2011-07-01 19:47:50 +00005885 distance+=scale*pixel*pixel;
5886 if (distance > fuzz)
5887 return(MagickFalse);
5888 return(MagickTrue);
5889}
5890
5891/*
5892%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5893% %
5894% %
5895% %
5896+ 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 %
5897% %
5898% %
5899% %
5900%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5901%
5902% IsFuzzyEquivalencePixelInfo() returns true if the distance between two
5903% colors is less than the specified distance in a linear three (or four)
5904% dimensional color space.
5905%
cristy5f95f4f2011-10-23 01:01:01 +00005906% This implements the equivalent of:
5907% fuzz < sqrt(color_distance^2 * u.a*v.a + alpha_distance^2)
cristy4c08aed2011-07-01 19:47:50 +00005908%
5909% Which produces a multi-dimensional cone for that colorspace along the
5910% transparency vector.
5911%
cristy5f95f4f2011-10-23 01:01:01 +00005912% For example for an RGB:
cristy4c08aed2011-07-01 19:47:50 +00005913% color_distance^2 = ( (u.r-v.r)^2 + (u.g-v.g)^2 + (u.b-v.b)^2 ) / 3
5914%
5915% See http://www.imagemagick.org/Usage/bugs/fuzz_distance/
5916%
5917% Hue colorspace distances need more work. Hue is not a distance, it is an
5918% angle!
5919%
5920% A check that q is in the same color space as p should be made and the
5921% appropriate mapping made. -- Anthony Thyssen 8 December 2010
5922%
5923% The format of the IsFuzzyEquivalencePixelInfo method is:
5924%
5925% MagickBooleanType IsFuzzyEquivalencePixelInfo(const PixelInfo *p,
5926% const PixelInfo *q)
5927%
5928% A description of each parameter follows:
5929%
5930% o p: Pixel p.
5931%
5932% o q: Pixel q.
5933%
5934*/
5935MagickExport MagickBooleanType IsFuzzyEquivalencePixelInfo(const PixelInfo *p,
5936 const PixelInfo *q)
5937{
cristya19f1d72012-08-07 18:24:38 +00005938 double
cristy4c08aed2011-07-01 19:47:50 +00005939 fuzz,
5940 pixel;
5941
cristya19f1d72012-08-07 18:24:38 +00005942 register double
cristy4c08aed2011-07-01 19:47:50 +00005943 scale,
5944 distance;
5945
5946 if ((p->fuzz == 0.0) && (q->fuzz == 0.0))
5947 return(IsPixelInfoEquivalent(p,q));
5948 if (p->fuzz == 0.0)
cristya19f1d72012-08-07 18:24:38 +00005949 fuzz=MagickMax(q->fuzz,(double) MagickSQ1_2)*MagickMax(q->fuzz,
5950 (double) MagickSQ1_2);
cristy4c08aed2011-07-01 19:47:50 +00005951 else if (q->fuzz == 0.0)
cristya19f1d72012-08-07 18:24:38 +00005952 fuzz=MagickMax(p->fuzz,(double) MagickSQ1_2)*MagickMax(p->fuzz,
5953 (double) MagickSQ1_2);
cristy4c08aed2011-07-01 19:47:50 +00005954 else
cristya19f1d72012-08-07 18:24:38 +00005955 fuzz=MagickMax(p->fuzz,(double) MagickSQ1_2)*MagickMax(q->fuzz,
5956 (double) MagickSQ1_2);
cristy4c08aed2011-07-01 19:47:50 +00005957 scale=1.0;
5958 distance=0.0;
cristy8a46d822012-08-28 23:32:39 +00005959 if ((p->alpha_trait == BlendPixelTrait) || (q->alpha_trait == BlendPixelTrait))
cristy4c08aed2011-07-01 19:47:50 +00005960 {
5961 /*
5962 Transparencies are involved - set alpha distance.
5963 */
cristy8a46d822012-08-28 23:32:39 +00005964 pixel=(p->alpha_trait == BlendPixelTrait ? p->alpha : OpaqueAlpha)-
5965 (q->alpha_trait == BlendPixelTrait ? q->alpha : OpaqueAlpha);
cristy4c08aed2011-07-01 19:47:50 +00005966 distance=pixel*pixel;
5967 if (distance > fuzz)
5968 return(MagickFalse);
5969 /*
5970 Generate a alpha scaling factor to generate a 4D cone on colorspace.
cristy5f95f4f2011-10-23 01:01:01 +00005971 If one color is transparent, distance has no color component.
cristy4c08aed2011-07-01 19:47:50 +00005972 */
cristy8a46d822012-08-28 23:32:39 +00005973 if (p->alpha_trait == BlendPixelTrait)
cristy4c08aed2011-07-01 19:47:50 +00005974 scale=(QuantumScale*p->alpha);
cristy8a46d822012-08-28 23:32:39 +00005975 if (q->alpha_trait == BlendPixelTrait)
cristy4c08aed2011-07-01 19:47:50 +00005976 scale*=(QuantumScale*q->alpha);
5977 if (scale <= MagickEpsilon )
5978 return(MagickTrue);
5979 }
5980 /*
5981 CMYK create a CMY cube with a multi-dimensional cone toward black.
5982 */
5983 if (p->colorspace == CMYKColorspace)
5984 {
5985 pixel=p->black-q->black;
5986 distance+=pixel*pixel*scale;
5987 if (distance > fuzz)
5988 return(MagickFalse);
cristya19f1d72012-08-07 18:24:38 +00005989 scale*=(double) (QuantumScale*(QuantumRange-p->black));
5990 scale*=(double) (QuantumScale*(QuantumRange-q->black));
cristy4c08aed2011-07-01 19:47:50 +00005991 }
5992 /*
5993 RGB or CMY color cube.
5994 */
5995 distance*=3.0; /* rescale appropriately */
5996 fuzz*=3.0;
5997 pixel=p->red-q->red;
5998 if ((p->colorspace == HSLColorspace) || (p->colorspace == HSBColorspace) ||
5999 (p->colorspace == HWBColorspace))
6000 {
cristy5f95f4f2011-10-23 01:01:01 +00006001 /*
6002 This calculates a arc distance for hue-- it should be a vector angle
6003 of 'S'/'W' length with 'L'/'B' forming appropriate cones. In other
6004 words this is a hack - Anthony.
cristy4c08aed2011-07-01 19:47:50 +00006005 */
6006 if (fabs((double) pixel) > (QuantumRange/2))
6007 pixel-=QuantumRange;
6008 pixel*=2;
6009 }
6010 distance+=pixel*pixel*scale;
6011 if (distance > fuzz)
6012 return(MagickFalse);
6013 pixel=p->green-q->green;
6014 distance+=pixel*pixel*scale;
6015 if (distance > fuzz)
6016 return(MagickFalse);
6017 pixel=p->blue-q->blue;
6018 distance+=pixel*pixel*scale;
6019 if (distance > fuzz)
6020 return(MagickFalse);
6021 return(MagickTrue);
6022}
6023
6024/*
6025%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6026% %
6027% %
6028% %
cristye2a912b2011-12-05 20:02:07 +00006029% S e t P i x e l C h a n n e l M a p M a s k %
cristy2b9582a2011-07-04 17:38:56 +00006030% %
6031% %
6032% %
6033%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6034%
cristycf1296e2012-08-26 23:40:49 +00006035% SetPixelChannelMask() sets the pixel channel map from the specified
cristye2a912b2011-12-05 20:02:07 +00006036% channel mask.
cristy2b9582a2011-07-04 17:38:56 +00006037%
cristycf1296e2012-08-26 23:40:49 +00006038% The format of the SetPixelChannelMask method is:
cristy2b9582a2011-07-04 17:38:56 +00006039%
cristycf1296e2012-08-26 23:40:49 +00006040% void SetPixelChannelMask(Image *image,const ChannelType channel_mask)
cristy2b9582a2011-07-04 17:38:56 +00006041%
6042% A description of each parameter follows:
6043%
6044% o image: the image.
6045%
cristydfdb19e2012-03-21 22:22:24 +00006046% o channel_mask: the channel mask.
cristy2b9582a2011-07-04 17:38:56 +00006047%
6048*/
cristycf1296e2012-08-26 23:40:49 +00006049MagickExport void SetPixelChannelMask(Image *image,
cristy07a67852011-08-26 13:25:03 +00006050 const ChannelType channel_mask)
cristy2b9582a2011-07-04 17:38:56 +00006051{
cristy6a917d62011-08-24 17:31:30 +00006052#define GetChannelBit(mask,bit) (((size_t) (mask) >> (size_t) (bit)) & 0x01)
cristydafd2872011-07-24 22:06:13 +00006053
cristy2b9582a2011-07-04 17:38:56 +00006054 register ssize_t
6055 i;
6056
cristy177e41c2012-04-15 15:08:25 +00006057 if (image->debug != MagickFalse)
6058 (void) LogMagickEvent(PixelEvent,GetMagickModule(),"%s[%08x]", \
6059 image->filename,channel_mask); \
cristy3c309812011-11-08 02:40:43 +00006060 image->channel_mask=channel_mask;
cristydafd2872011-07-24 22:06:13 +00006061 for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
cristye2a912b2011-12-05 20:02:07 +00006062 {
cristy5a23c552013-02-13 14:34:28 +00006063 PixelChannel channel=GetPixelChannelChannel(image,i);
cristy297e3a42012-08-26 21:27:29 +00006064 SetPixelChannelTraits(image,channel,
cristye2a912b2011-12-05 20:02:07 +00006065 GetChannelBit(channel_mask,channel) == 0 ? CopyPixelTrait :
cristy8a46d822012-08-28 23:32:39 +00006066 image->alpha_trait != BlendPixelTrait || (channel == AlphaPixelChannel) ?
6067 UpdatePixelTrait : (PixelTrait) (UpdatePixelTrait | image->alpha_trait));
cristye2a912b2011-12-05 20:02:07 +00006068 }
cristy1685e722011-09-06 00:04:19 +00006069 if (image->storage_class == PseudoClass)
cristy297e3a42012-08-26 21:27:29 +00006070 SetPixelChannelTraits(image,IndexPixelChannel,CopyPixelTrait);
cristy183a5c72012-01-30 01:40:35 +00006071 if (image->mask != MagickFalse)
cristy297e3a42012-08-26 21:27:29 +00006072 SetPixelChannelTraits(image,MaskPixelChannel,CopyPixelTrait);
cristy6dcb9b82011-10-23 23:21:25 +00006073 if (image->debug != MagickFalse)
6074 LogPixelChannels(image);
cristy2b9582a2011-07-04 17:38:56 +00006075}
6076
6077/*
6078%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6079% %
6080% %
6081% %
cristy322d07d2012-03-18 21:17:23 +00006082% S e t P i x e l M e t a C h a n n e l s %
6083% %
6084% %
6085% %
6086%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6087%
6088% SetPixelMetaChannels() sets the image meta channels.
6089%
6090% The format of the SetPixelMetaChannels method is:
6091%
6092% MagickBooleanType SetPixelMetaChannels(Image *image,
6093% const size_t number_meta_channels,ExceptionInfo *exception)
6094%
6095% A description of each parameter follows:
6096%
6097% o image: the image.
6098%
6099% o number_meta_channels: the number of meta channels.
6100%
6101% o exception: return any errors or warnings in this structure.
6102%
6103*/
6104MagickExport MagickBooleanType SetPixelMetaChannels(Image *image,
6105 const size_t number_meta_channels,ExceptionInfo *exception)
6106{
6107 image->number_meta_channels=number_meta_channels;
6108 return(SyncImagePixelCache(image,exception));
6109}