blob: 4a12bec6efcdad74d583c78389ad3a6ca9a10f85 [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/*
cristy4c08aed2011-07-01 19:47:50 +000074%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
75% %
76% %
77% %
cristyed231572011-07-14 02:18:59 +000078+ 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 +000079% %
80% %
81% %
82%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
83%
cristyed231572011-07-14 02:18:59 +000084% AcquirePixelChannelMap() acquires a pixel component map.
cristy4c08aed2011-07-01 19:47:50 +000085%
cristyed231572011-07-14 02:18:59 +000086% The format of the AcquirePixelChannelMap() method is:
cristy4c08aed2011-07-01 19:47:50 +000087%
cristybd5a96c2011-08-21 00:04:26 +000088% PixelChannelMap *AcquirePixelChannelMap(void)
cristy4c08aed2011-07-01 19:47:50 +000089%
90*/
cristybd5a96c2011-08-21 00:04:26 +000091MagickExport PixelChannelMap *AcquirePixelChannelMap(void)
cristy4c08aed2011-07-01 19:47:50 +000092{
cristyed231572011-07-14 02:18:59 +000093 PixelChannelMap
cristybd5a96c2011-08-21 00:04:26 +000094 *channel_map;
cristy4c08aed2011-07-01 19:47:50 +000095
96 register ssize_t
97 i;
98
cristybd5a96c2011-08-21 00:04:26 +000099 channel_map=(PixelChannelMap *) AcquireQuantumMemory(MaxPixelChannels,
100 sizeof(*channel_map));
101 if (channel_map == (PixelChannelMap *) NULL)
cristy4c08aed2011-07-01 19:47:50 +0000102 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
cristybd5a96c2011-08-21 00:04:26 +0000103 (void) ResetMagickMemory(channel_map,0,MaxPixelChannels*sizeof(*channel_map));
104 for (i=0; i < MaxPixelChannels; i++)
105 channel_map[i].channel=(PixelChannel) i;
cristyed231572011-07-14 02:18:59 +0000106 return(channel_map);
cristy4c08aed2011-07-01 19:47:50 +0000107}
108
109/*
110%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
111% %
112% %
113% %
cristyed231572011-07-14 02:18:59 +0000114+ 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 +0000115% %
116% %
117% %
118%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
119%
cristyed231572011-07-14 02:18:59 +0000120% ClonePixelChannelMap() clones a pixel component map.
cristy4c08aed2011-07-01 19:47:50 +0000121%
cristyed231572011-07-14 02:18:59 +0000122% The format of the ClonePixelChannelMap() method is:
cristy4c08aed2011-07-01 19:47:50 +0000123%
cristybd5a96c2011-08-21 00:04:26 +0000124% PixelChannelMap *ClonePixelChannelMap(PixelChannelMap *channel_map)
cristy4c08aed2011-07-01 19:47:50 +0000125%
126% A description of each parameter follows:
127%
cristyed231572011-07-14 02:18:59 +0000128% o channel_map: the pixel component map.
cristy4c08aed2011-07-01 19:47:50 +0000129%
130*/
cristybd5a96c2011-08-21 00:04:26 +0000131MagickExport PixelChannelMap *ClonePixelChannelMap(PixelChannelMap *channel_map)
cristy4c08aed2011-07-01 19:47:50 +0000132{
cristyed231572011-07-14 02:18:59 +0000133 PixelChannelMap
cristybd5a96c2011-08-21 00:04:26 +0000134 *clone_map;
cristy4c08aed2011-07-01 19:47:50 +0000135
cristybd5a96c2011-08-21 00:04:26 +0000136 assert(channel_map != (PixelChannelMap *) NULL);
cristyed231572011-07-14 02:18:59 +0000137 clone_map=AcquirePixelChannelMap();
cristybd5a96c2011-08-21 00:04:26 +0000138 if (clone_map == (PixelChannelMap *) NULL)
139 return((PixelChannelMap *) NULL);
140 (void) CopyMagickMemory(clone_map,channel_map,MaxPixelChannels*
141 sizeof(*channel_map));
cristy4c08aed2011-07-01 19:47:50 +0000142 return(clone_map);
143}
144
145/*
146%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
147% %
148% %
149% %
150+ C l o n e P i x e l I n f o %
151% %
152% %
153% %
154%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
155%
156% ClonePixelInfo() makes a duplicate of the given pixel info structure, or if
157% pixel info is NULL, a new one.
158%
159% The format of the ClonePixelInfo method is:
160%
161% PixelInfo *ClonePixelInfo(const PixelInfo *pixel_info)
162%
163% A description of each parameter follows:
164%
165% o pixel_info: the pixel info.
166%
167*/
168MagickExport PixelInfo *ClonePixelInfo(const PixelInfo *pixel)
169{
170 PixelInfo
171 *pixel_info;
172
cristya64b85d2011-09-14 01:02:31 +0000173 pixel_info=(PixelInfo *) AcquireQuantumMemory(1,sizeof(*pixel_info));
cristy4c08aed2011-07-01 19:47:50 +0000174 if (pixel_info == (PixelInfo *) NULL)
175 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
176 *pixel_info=(*pixel);
177 return(pixel_info);
178}
179
180/*
181%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
182% %
183% %
184% %
cristyc8aff842012-12-24 16:59:46 +0000185% D e c o d e P i x e l G a m m a %
186% %
187% %
188% %
189%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
190%
191% DecodePixelGamma() applies the expansive power-law nonlinearity to the pixel.
192%
cristy35060592013-04-17 14:10:20 +0000193% The format of the DecodePixelGamma method is:
cristyc8aff842012-12-24 16:59:46 +0000194%
195% double DecodePixelGamma(const MagickRealType pixel)
196%
197% A description of each parameter follows:
198%
199% o pixel: the pixel.
200%
201*/
cristyc29824a2013-04-17 21:52:56 +0000202
203static inline double DecodeGamma(const double x)
204{
205 div_t
206 quotient;
207
208 double
209 p,
210 term[9];
211
212 int
213 exponent;
214
215 static const double coefficient[] = /* terms for x^(7/5), x=1.5 */
216 {
217 1.7917488588043277509,
218 0.82045614371976854984,
219 0.027694100686325412819,
220 -0.00094244335181762134018,
221 0.000064355540911469709545,
222 -5.7224404636060757485e-06,
223 5.8767669437311184313e-07,
224 -6.6139920053589721168e-08,
225 7.9323242696227458163e-09
226 };
227
228 static const double powers_of_two[] = /* (2^x)^(7/5) */
229 {
230 1.0,
231 2.6390158215457883983,
232 6.9644045063689921093,
233 1.8379173679952558018e+01,
234 4.8502930128332728543e+01
235 };
236
237 /*
238 Compute x^2.4 == x*x^(7/5) == pow(x,2.4).
239 */
240 term[0]=1.0;
241 term[1]=4.0*frexp(x,&exponent)-3.0;
242 term[2]=2.0*term[1]*term[1]-term[0];
243 term[3]=2.0*term[1]*term[2]-term[1];
244 term[4]=2.0*term[1]*term[3]-term[2];
245 term[5]=2.0*term[1]*term[4]-term[3];
246 term[6]=2.0*term[1]*term[5]-term[4];
247 term[7]=2.0*term[1]*term[6]-term[5];
248 term[8]=2.0*term[1]*term[7]-term[6];
249 p=coefficient[0]*term[0]+coefficient[1]*term[1]+coefficient[2]*term[2]+
250 coefficient[3]*term[3]+coefficient[4]*term[4]+coefficient[5]*term[5]+
251 coefficient[6]*term[6]+coefficient[7]*term[7]+coefficient[8]*term[8];
252 quotient=div(exponent-1,5);
253 if (quotient.rem < 0)
254 {
255 quotient.quot-=1;
256 quotient.rem+=5;
257 }
258 return(x*ldexp(powers_of_two[quotient.rem]*p,7*quotient.quot));
259}
260
cristyc8aff842012-12-24 16:59:46 +0000261MagickExport MagickRealType DecodePixelGamma(const MagickRealType pixel)
262{
263 if (pixel <= (0.0404482362771076*QuantumRange))
264 return(pixel/12.92f);
cristyc29824a2013-04-17 21:52:56 +0000265 return((MagickRealType) (QuantumRange*DecodeGamma((double) (QuantumScale*
266 pixel+0.055)/1.055)));
cristyc8aff842012-12-24 16:59:46 +0000267}
268
269/*
270%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
271% %
272% %
273% %
cristyed231572011-07-14 02:18:59 +0000274+ 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 +0000275% %
276% %
277% %
278%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
279%
cristyed231572011-07-14 02:18:59 +0000280% DestroyPixelChannelMap() deallocates memory associated with the pixel
281% channel map.
cristy4c08aed2011-07-01 19:47:50 +0000282%
cristyed231572011-07-14 02:18:59 +0000283% The format of the DestroyPixelChannelMap() method is:
cristy4c08aed2011-07-01 19:47:50 +0000284%
cristybd5a96c2011-08-21 00:04:26 +0000285% PixelChannelMap *DestroyPixelChannelMap(PixelChannelMap *channel_map)
cristy4c08aed2011-07-01 19:47:50 +0000286%
287% A description of each parameter follows:
288%
cristyed231572011-07-14 02:18:59 +0000289% o channel_map: the pixel component map.
cristy4c08aed2011-07-01 19:47:50 +0000290%
291*/
cristybd5a96c2011-08-21 00:04:26 +0000292MagickExport PixelChannelMap *DestroyPixelChannelMap(
293 PixelChannelMap *channel_map)
cristy4c08aed2011-07-01 19:47:50 +0000294{
cristybd5a96c2011-08-21 00:04:26 +0000295 assert(channel_map != (PixelChannelMap *) NULL);
296 channel_map=(PixelChannelMap *) RelinquishMagickMemory(channel_map);
297 return((PixelChannelMap *) RelinquishMagickMemory(channel_map));
cristy4c08aed2011-07-01 19:47:50 +0000298}
299
300/*
301%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
302% %
303% %
304% %
cristyc8aff842012-12-24 16:59:46 +0000305+ E n c o d e P i x e l G a m m a %
306% %
307% %
308% %
309%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
310%
311% EncodePixelGamma() cancels any nonlinearity in the pixel.
312%
cristy35060592013-04-17 14:10:20 +0000313% The format of the EncodePixelGamma method is:
cristyc8aff842012-12-24 16:59:46 +0000314%
315% MagickRealType EncodePixelGamma(const double MagickRealType)
316%
317% A description of each parameter follows:
318%
319% o pixel: the pixel.
320%
321*/
cristyc29824a2013-04-17 21:52:56 +0000322
323static inline double EncodeGamma(const double x)
324{
325 div_t
326 quotient;
327
328 double
329 p,
330 term[9];
331
332 int
333 exponent;
334
335 static const double coefficient[] = /* Chebychevi poly: x^(5/12), x=1.5 */
336 {
337 1.1758200232996901923,
338 0.16665763094889061230,
339 -0.0083154894939042125035,
340 0.00075187976780420279038,
341 -0.000083240178519391795367,
342 0.000010229209410070008679,
343 -1.3400466409860246e-06,
344 1.8333422241635376682e-07,
345 -2.5878596761348859722e-08
346 };
347
348 static const double powers_of_two[] = /* (2^N)^(5/12) */
349 {
350 1.0,
351 1.3348398541700343678,
352 1.7817974362806785482,
353 2.3784142300054420538,
354 3.1748021039363991669,
355 4.2378523774371812394,
356 5.6568542494923805819,
357 7.5509945014535482244,
358 1.0079368399158985525e1,
359 1.3454342644059433809e1,
360 1.7959392772949968275e1,
361 2.3972913230026907883e1
362 };
363
364 /*
365 Compute x^(1/2.4) == x^(5/12) == pow(x,1.0/2.4).
366 */
367 term[0]=1.0;
368 term[1]=4.0*frexp(x,&exponent)-3.0;
369 term[2]=2.0*term[1]*term[1]-term[0];
370 term[3]=2.0*term[1]*term[2]-term[1];
371 term[4]=2.0*term[1]*term[3]-term[2];
372 term[5]=2.0*term[1]*term[4]-term[3];
373 term[6]=2.0*term[1]*term[5]-term[4];
374 term[7]=2.0*term[1]*term[6]-term[5];
375 term[8]=2.0*term[1]*term[7]-term[6];
376 p=coefficient[0]*term[0]+coefficient[1]*term[1]+coefficient[2]*term[2]+
377 coefficient[3]*term[3]+coefficient[4]*term[4]+coefficient[5]*term[5]+
378 coefficient[6]*term[6]+coefficient[7]*term[7]+coefficient[8]*term[8];
379 quotient=div(exponent-1,12);
380 if (quotient.rem < 0)
381 {
382 quotient.quot-=1;
383 quotient.rem+=12;
384 }
385 return(ldexp(powers_of_two[quotient.rem]*p,5*quotient.quot));
386}
387
cristyc8aff842012-12-24 16:59:46 +0000388MagickExport MagickRealType EncodePixelGamma(const MagickRealType pixel)
389{
390 if (pixel <= (0.0031306684425005883*QuantumRange))
391 return(12.92f*pixel);
cristyc29824a2013-04-17 21:52:56 +0000392 return((MagickRealType) QuantumRange*(1.055*EncodeGamma((double) QuantumScale*
cristy2a13aa62013-04-18 19:15:28 +0000393 pixel)-0.055));
cristyc8aff842012-12-24 16:59:46 +0000394}
395
396/*
397%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
398% %
399% %
400% %
cristy4c08aed2011-07-01 19:47:50 +0000401% E x p o r t I m a g e P i x e l s %
402% %
403% %
404% %
405%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
406%
407% ExportImagePixels() extracts pixel data from an image and returns it to you.
408% The method returns MagickTrue on success otherwise MagickFalse if an error is
cristyb5a45a32012-01-10 13:31:13 +0000409% encountered. The data is returned as char, short int, Quantum, unsigned int,
cristycafe0412012-01-10 13:29:58 +0000410% unsigned long long, float, or double in the order specified by map.
cristy4c08aed2011-07-01 19:47:50 +0000411%
412% Suppose you want to extract the first scanline of a 640x480 image as
413% character data in red-green-blue order:
414%
415% ExportImagePixels(image,0,0,640,1,"RGB",CharPixel,pixels,exception);
416%
417% The format of the ExportImagePixels method is:
418%
cristycafe0412012-01-10 13:29:58 +0000419% MagickBooleanType ExportImagePixels(const Image *image,const ssize_t x,
420% const ssize_t y,const size_t width,const size_t height,
421% const char *map,const StorageType type,void *pixels,
cristy46f4be22012-01-07 00:26:39 +0000422% ExceptionInfo *exception)
cristy4c08aed2011-07-01 19:47:50 +0000423%
424% A description of each parameter follows:
425%
426% o image: the image.
427%
cristycafe0412012-01-10 13:29:58 +0000428% o x,y,width,height: These values define the perimeter
cristy4c08aed2011-07-01 19:47:50 +0000429% of a region of pixels you want to extract.
430%
431% o map: This string reflects the expected ordering of the pixel array.
432% It can be any combination or order of R = red, G = green, B = blue,
433% A = alpha (0 is transparent), O = opacity (0 is opaque), C = cyan,
434% Y = yellow, M = magenta, K = black, I = intensity (for grayscale),
435% P = pad.
436%
437% o type: Define the data type of the pixels. Float and double types are
438% normalized to [0..1] otherwise [0..QuantumRange]. Choose from these
cristy6c9e1682012-01-07 21:37:44 +0000439% types: CharPixel (char *), DoublePixel (double *), FloatPixel (float *),
cristyff6834e2012-01-10 03:00:25 +0000440% LongPixel (unsigned int *), LongLongPixel (unsigned long long *),
cristy6c9e1682012-01-07 21:37:44 +0000441% QuantumPixel (Quantum *), or ShortPixel (unsigned short *).
cristy4c08aed2011-07-01 19:47:50 +0000442%
443% o pixels: This array of values contain the pixel components as defined by
444% map and type. You must preallocate this array where the expected
445% length varies depending on the values of width, height, map, and type.
446%
447% o exception: return any errors or warnings in this structure.
448%
449*/
cristye5370942012-01-06 03:49:31 +0000450
cristy2dc655d2012-07-05 13:16:28 +0000451static void ExportCharPixel(Image *image,const RectangleInfo *roi,
cristy46f4be22012-01-07 00:26:39 +0000452 const char *restrict map,const QuantumType *quantum_map,void *pixels,
453 ExceptionInfo *exception)
cristye5370942012-01-06 03:49:31 +0000454{
455 register const Quantum
456 *restrict p;
457
458 register ssize_t
459 x;
460
461 register unsigned char
cristy3fe11452012-01-09 01:27:42 +0000462 *restrict q;
cristye5370942012-01-06 03:49:31 +0000463
cristy14d71292012-05-20 16:48:13 +0000464 size_t
465 length;
466
cristye5370942012-01-06 03:49:31 +0000467 ssize_t
468 y;
469
cristy46f4be22012-01-07 00:26:39 +0000470 q=(unsigned char *) pixels;
cristye5370942012-01-06 03:49:31 +0000471 if (LocaleCompare(map,"BGR") == 0)
472 {
cristycafe0412012-01-10 13:29:58 +0000473 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +0000474 {
cristycafe0412012-01-10 13:29:58 +0000475 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +0000476 if (p == (const Quantum *) NULL)
477 break;
cristycafe0412012-01-10 13:29:58 +0000478 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +0000479 {
480 *q++=ScaleQuantumToChar(GetPixelBlue(image,p));
481 *q++=ScaleQuantumToChar(GetPixelGreen(image,p));
482 *q++=ScaleQuantumToChar(GetPixelRed(image,p));
483 p+=GetPixelChannels(image);
484 }
485 }
486 return;
487 }
488 if (LocaleCompare(map,"BGRA") == 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 {
497 *q++=ScaleQuantumToChar(GetPixelBlue(image,p));
498 *q++=ScaleQuantumToChar(GetPixelGreen(image,p));
499 *q++=ScaleQuantumToChar(GetPixelRed(image,p));
500 *q++=ScaleQuantumToChar(GetPixelAlpha(image,p));
501 p+=GetPixelChannels(image);
502 }
503 }
504 return;
505 }
506 if (LocaleCompare(map,"BGRP") == 0)
507 {
cristycafe0412012-01-10 13:29:58 +0000508 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +0000509 {
cristycafe0412012-01-10 13:29:58 +0000510 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +0000511 if (p == (const Quantum *) NULL)
512 break;
cristycafe0412012-01-10 13:29:58 +0000513 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +0000514 {
515 *q++=ScaleQuantumToChar(GetPixelBlue(image,p));
516 *q++=ScaleQuantumToChar(GetPixelGreen(image,p));
517 *q++=ScaleQuantumToChar(GetPixelRed(image,p));
518 *q++=ScaleQuantumToChar((Quantum) 0);
519 p+=GetPixelChannels(image);
520 }
521 }
522 return;
523 }
524 if (LocaleCompare(map,"I") == 0)
525 {
cristycafe0412012-01-10 13:29:58 +0000526 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +0000527 {
cristycafe0412012-01-10 13:29:58 +0000528 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +0000529 if (p == (const Quantum *) NULL)
530 break;
cristycafe0412012-01-10 13:29:58 +0000531 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +0000532 {
cristy70e9f682013-03-12 22:31:22 +0000533 *q++=ScaleQuantumToChar(ClampToQuantum(GetPixelIntensity(image,p)));
cristye5370942012-01-06 03:49:31 +0000534 p+=GetPixelChannels(image);
535 }
536 }
537 return;
538 }
539 if (LocaleCompare(map,"RGB") == 0)
540 {
cristycafe0412012-01-10 13:29:58 +0000541 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +0000542 {
cristycafe0412012-01-10 13:29:58 +0000543 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +0000544 if (p == (const Quantum *) NULL)
545 break;
cristycafe0412012-01-10 13:29:58 +0000546 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +0000547 {
548 *q++=ScaleQuantumToChar(GetPixelRed(image,p));
549 *q++=ScaleQuantumToChar(GetPixelGreen(image,p));
550 *q++=ScaleQuantumToChar(GetPixelBlue(image,p));
551 p+=GetPixelChannels(image);
552 }
553 }
554 return;
555 }
556 if (LocaleCompare(map,"RGBA") == 0)
557 {
cristycafe0412012-01-10 13:29:58 +0000558 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +0000559 {
cristycafe0412012-01-10 13:29:58 +0000560 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +0000561 if (p == (const Quantum *) NULL)
562 break;
cristycafe0412012-01-10 13:29:58 +0000563 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +0000564 {
565 *q++=ScaleQuantumToChar(GetPixelRed(image,p));
566 *q++=ScaleQuantumToChar(GetPixelGreen(image,p));
567 *q++=ScaleQuantumToChar(GetPixelBlue(image,p));
568 *q++=ScaleQuantumToChar(GetPixelAlpha(image,p));
569 p+=GetPixelChannels(image);
570 }
571 }
572 return;
573 }
574 if (LocaleCompare(map,"RGBP") == 0)
575 {
cristycafe0412012-01-10 13:29:58 +0000576 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +0000577 {
cristycafe0412012-01-10 13:29:58 +0000578 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +0000579 if (p == (const Quantum *) NULL)
580 break;
cristycafe0412012-01-10 13:29:58 +0000581 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +0000582 {
583 *q++=ScaleQuantumToChar(GetPixelRed(image,p));
584 *q++=ScaleQuantumToChar(GetPixelGreen(image,p));
585 *q++=ScaleQuantumToChar(GetPixelBlue(image,p));
586 *q++=ScaleQuantumToChar((Quantum) 0);
587 p+=GetPixelChannels(image);
588 }
589 }
590 return;
591 }
cristy14d71292012-05-20 16:48:13 +0000592 length=strlen(map);
cristycafe0412012-01-10 13:29:58 +0000593 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +0000594 {
cristycafe0412012-01-10 13:29:58 +0000595 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +0000596 if (p == (const Quantum *) NULL)
597 break;
cristycafe0412012-01-10 13:29:58 +0000598 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +0000599 {
600 register ssize_t
601 i;
602
cristy14d71292012-05-20 16:48:13 +0000603 for (i=0; i < (ssize_t) length; i++)
cristye5370942012-01-06 03:49:31 +0000604 {
605 *q=0;
606 switch (quantum_map[i])
607 {
608 case RedQuantum:
609 case CyanQuantum:
610 {
611 *q=ScaleQuantumToChar(GetPixelRed(image,p));
612 break;
613 }
614 case GreenQuantum:
615 case MagentaQuantum:
616 {
617 *q=ScaleQuantumToChar(GetPixelGreen(image,p));
618 break;
619 }
620 case BlueQuantum:
621 case YellowQuantum:
622 {
623 *q=ScaleQuantumToChar(GetPixelBlue(image,p));
624 break;
625 }
626 case AlphaQuantum:
627 {
628 *q=ScaleQuantumToChar(GetPixelAlpha(image,p));
629 break;
630 }
631 case OpacityQuantum:
632 {
633 *q=ScaleQuantumToChar(GetPixelAlpha(image,p));
634 break;
635 }
636 case BlackQuantum:
637 {
638 if (image->colorspace == CMYKColorspace)
639 *q=ScaleQuantumToChar(GetPixelBlack(image,p));
640 break;
641 }
642 case IndexQuantum:
643 {
cristy70e9f682013-03-12 22:31:22 +0000644 *q=ScaleQuantumToChar(ClampToQuantum(GetPixelIntensity(image,p)));
cristye5370942012-01-06 03:49:31 +0000645 break;
646 }
647 default:
648 break;
649 }
650 q++;
651 }
652 p+=GetPixelChannels(image);
653 }
654 }
655}
656
cristy2dc655d2012-07-05 13:16:28 +0000657static void ExportDoublePixel(Image *image,const RectangleInfo *roi,
cristy46f4be22012-01-07 00:26:39 +0000658 const char *restrict map,const QuantumType *quantum_map,void *pixels,
659 ExceptionInfo *exception)
cristye5370942012-01-06 03:49:31 +0000660{
661 register const Quantum
662 *restrict p;
663
664 register double
cristy3fe11452012-01-09 01:27:42 +0000665 *restrict q;
cristye5370942012-01-06 03:49:31 +0000666
667 register ssize_t
668 x;
669
cristy14d71292012-05-20 16:48:13 +0000670 size_t
671 length;
672
cristye5370942012-01-06 03:49:31 +0000673 ssize_t
674 y;
675
676 q=(double *) pixels;
677 if (LocaleCompare(map,"BGR") == 0)
678 {
cristycafe0412012-01-10 13:29:58 +0000679 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +0000680 {
cristycafe0412012-01-10 13:29:58 +0000681 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +0000682 if (p == (const Quantum *) NULL)
683 break;
cristycafe0412012-01-10 13:29:58 +0000684 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +0000685 {
686 *q++=(double) (QuantumScale*GetPixelBlue(image,p));
687 *q++=(double) (QuantumScale*GetPixelGreen(image,p));
688 *q++=(double) (QuantumScale*GetPixelRed(image,p));
689 p+=GetPixelChannels(image);
690 }
691 }
692 return;
693 }
694 if (LocaleCompare(map,"BGRA") == 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*GetPixelBlue(image,p));
704 *q++=(double) (QuantumScale*GetPixelGreen(image,p));
705 *q++=(double) (QuantumScale*GetPixelRed(image,p));
706 *q++=(double) (QuantumScale*GetPixelAlpha(image,p));
707 p+=GetPixelChannels(image);
708 }
709 }
710 return;
711 }
712 if (LocaleCompare(map,"BGRP") == 0)
713 {
cristycafe0412012-01-10 13:29:58 +0000714 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +0000715 {
cristycafe0412012-01-10 13:29:58 +0000716 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +0000717 if (p == (const Quantum *) NULL)
718 break;
cristycafe0412012-01-10 13:29:58 +0000719 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +0000720 {
721 *q++=(double) (QuantumScale*GetPixelBlue(image,p));
722 *q++=(double) (QuantumScale*GetPixelGreen(image,p));
723 *q++=(double) (QuantumScale*GetPixelRed(image,p));
724 *q++=0.0;
725 p+=GetPixelChannels(image);
726 }
727 }
728 return;
729 }
730 if (LocaleCompare(map,"I") == 0)
731 {
cristycafe0412012-01-10 13:29:58 +0000732 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +0000733 {
cristycafe0412012-01-10 13:29:58 +0000734 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +0000735 if (p == (const Quantum *) NULL)
736 break;
cristycafe0412012-01-10 13:29:58 +0000737 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +0000738 {
739 *q++=(double) (QuantumScale*GetPixelIntensity(image,p));
740 p+=GetPixelChannels(image);
741 }
742 }
743 return;
744 }
745 if (LocaleCompare(map,"RGB") == 0)
746 {
cristycafe0412012-01-10 13:29:58 +0000747 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +0000748 {
cristycafe0412012-01-10 13:29:58 +0000749 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +0000750 if (p == (const Quantum *) NULL)
751 break;
cristycafe0412012-01-10 13:29:58 +0000752 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +0000753 {
754 *q++=(double) (QuantumScale*GetPixelRed(image,p));
755 *q++=(double) (QuantumScale*GetPixelGreen(image,p));
756 *q++=(double) (QuantumScale*GetPixelBlue(image,p));
757 p+=GetPixelChannels(image);
758 }
759 }
760 return;
761 }
762 if (LocaleCompare(map,"RGBA") == 0)
763 {
cristycafe0412012-01-10 13:29:58 +0000764 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +0000765 {
cristycafe0412012-01-10 13:29:58 +0000766 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +0000767 if (p == (const Quantum *) NULL)
768 break;
cristycafe0412012-01-10 13:29:58 +0000769 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +0000770 {
771 *q++=(double) (QuantumScale*GetPixelRed(image,p));
772 *q++=(double) (QuantumScale*GetPixelGreen(image,p));
773 *q++=(double) (QuantumScale*GetPixelBlue(image,p));
774 *q++=(double) (QuantumScale*GetPixelAlpha(image,p));
775 p+=GetPixelChannels(image);
776 }
777 }
778 return;
779 }
780 if (LocaleCompare(map,"RGBP") == 0)
781 {
cristycafe0412012-01-10 13:29:58 +0000782 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +0000783 {
cristycafe0412012-01-10 13:29:58 +0000784 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +0000785 if (p == (const Quantum *) NULL)
786 break;
cristycafe0412012-01-10 13:29:58 +0000787 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +0000788 {
789 *q++=(double) (QuantumScale*GetPixelRed(image,p));
790 *q++=(double) (QuantumScale*GetPixelGreen(image,p));
791 *q++=(double) (QuantumScale*GetPixelBlue(image,p));
792 *q++=0.0;
793 p+=GetPixelChannels(image);
794 }
795 }
796 return;
797 }
cristy14d71292012-05-20 16:48:13 +0000798 length=strlen(map);
cristycafe0412012-01-10 13:29:58 +0000799 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +0000800 {
cristycafe0412012-01-10 13:29:58 +0000801 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +0000802 if (p == (const Quantum *) NULL)
803 break;
cristycafe0412012-01-10 13:29:58 +0000804 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +0000805 {
806 register ssize_t
807 i;
808
cristy14d71292012-05-20 16:48:13 +0000809 for (i=0; i < (ssize_t) length; i++)
cristye5370942012-01-06 03:49:31 +0000810 {
811 *q=0;
812 switch (quantum_map[i])
813 {
814 case RedQuantum:
815 case CyanQuantum:
816 {
817 *q=(double) (QuantumScale*GetPixelRed(image,p));
818 break;
819 }
820 case GreenQuantum:
821 case MagentaQuantum:
822 {
823 *q=(double) (QuantumScale*GetPixelGreen(image,p));
824 break;
825 }
826 case BlueQuantum:
827 case YellowQuantum:
828 {
829 *q=(double) (QuantumScale*GetPixelBlue(image,p));
830 break;
831 }
832 case AlphaQuantum:
833 {
834 *q=(double) (QuantumScale*GetPixelAlpha(image,p));
835 break;
836 }
837 case OpacityQuantum:
838 {
839 *q=(double) (QuantumScale*GetPixelAlpha(image,p));
840 break;
841 }
842 case BlackQuantum:
843 {
844 if (image->colorspace == CMYKColorspace)
845 *q=(double) (QuantumScale*
846 GetPixelBlack(image,p));
847 break;
848 }
849 case IndexQuantum:
850 {
851 *q=(double) (QuantumScale*GetPixelIntensity(image,p));
852 break;
853 }
854 default:
855 *q=0;
856 }
857 q++;
858 }
859 p+=GetPixelChannels(image);
860 }
861 }
862}
863
cristy2dc655d2012-07-05 13:16:28 +0000864static void ExportFloatPixel(Image *image,const RectangleInfo *roi,
cristy46f4be22012-01-07 00:26:39 +0000865 const char *restrict map,const QuantumType *quantum_map,void *pixels,
866 ExceptionInfo *exception)
cristye5370942012-01-06 03:49:31 +0000867{
868 register const Quantum
869 *restrict p;
870
871 register float
cristy3fe11452012-01-09 01:27:42 +0000872 *restrict q;
cristye5370942012-01-06 03:49:31 +0000873
874 register ssize_t
875 x;
876
cristy14d71292012-05-20 16:48:13 +0000877 size_t
878 length;
879
cristye5370942012-01-06 03:49:31 +0000880 ssize_t
881 y;
882
883 q=(float *) pixels;
884 if (LocaleCompare(map,"BGR") == 0)
885 {
cristycafe0412012-01-10 13:29:58 +0000886 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +0000887 {
cristycafe0412012-01-10 13:29:58 +0000888 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +0000889 if (p == (const Quantum *) NULL)
890 break;
cristycafe0412012-01-10 13:29:58 +0000891 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +0000892 {
893 *q++=(float) (QuantumScale*GetPixelBlue(image,p));
894 *q++=(float) (QuantumScale*GetPixelGreen(image,p));
895 *q++=(float) (QuantumScale*GetPixelRed(image,p));
896 p+=GetPixelChannels(image);
897 }
898 }
899 return;
900 }
901 if (LocaleCompare(map,"BGRA") == 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*GetPixelBlue(image,p));
911 *q++=(float) (QuantumScale*GetPixelGreen(image,p));
912 *q++=(float) (QuantumScale*GetPixelRed(image,p));
913 *q++=(float) (QuantumScale*GetPixelAlpha(image,p));
914 p+=GetPixelChannels(image);
915 }
916 }
917 return;
918 }
919 if (LocaleCompare(map,"BGRP") == 0)
920 {
cristycafe0412012-01-10 13:29:58 +0000921 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +0000922 {
cristycafe0412012-01-10 13:29:58 +0000923 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +0000924 if (p == (const Quantum *) NULL)
925 break;
cristycafe0412012-01-10 13:29:58 +0000926 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +0000927 {
928 *q++=(float) (QuantumScale*GetPixelBlue(image,p));
929 *q++=(float) (QuantumScale*GetPixelGreen(image,p));
930 *q++=(float) (QuantumScale*GetPixelRed(image,p));
931 *q++=0.0;
932 p+=GetPixelChannels(image);
933 }
934 }
935 return;
936 }
937 if (LocaleCompare(map,"I") == 0)
938 {
cristycafe0412012-01-10 13:29:58 +0000939 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +0000940 {
cristycafe0412012-01-10 13:29:58 +0000941 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +0000942 if (p == (const Quantum *) NULL)
943 break;
cristycafe0412012-01-10 13:29:58 +0000944 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +0000945 {
946 *q++=(float) (QuantumScale*GetPixelIntensity(image,p));
947 p+=GetPixelChannels(image);
948 }
949 }
950 return;
951 }
952 if (LocaleCompare(map,"RGB") == 0)
953 {
cristycafe0412012-01-10 13:29:58 +0000954 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +0000955 {
cristycafe0412012-01-10 13:29:58 +0000956 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +0000957 if (p == (const Quantum *) NULL)
958 break;
cristycafe0412012-01-10 13:29:58 +0000959 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +0000960 {
961 *q++=(float) (QuantumScale*GetPixelRed(image,p));
962 *q++=(float) (QuantumScale*GetPixelGreen(image,p));
963 *q++=(float) (QuantumScale*GetPixelBlue(image,p));
964 p+=GetPixelChannels(image);
965 }
966 }
967 return;
968 }
969 if (LocaleCompare(map,"RGBA") == 0)
970 {
cristycafe0412012-01-10 13:29:58 +0000971 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +0000972 {
cristycafe0412012-01-10 13:29:58 +0000973 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +0000974 if (p == (const Quantum *) NULL)
975 break;
cristycafe0412012-01-10 13:29:58 +0000976 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +0000977 {
978 *q++=(float) (QuantumScale*GetPixelRed(image,p));
979 *q++=(float) (QuantumScale*GetPixelGreen(image,p));
980 *q++=(float) (QuantumScale*GetPixelBlue(image,p));
981 *q++=(float) (QuantumScale*GetPixelAlpha(image,p));
982 p+=GetPixelChannels(image);
983 }
984 }
985 return;
986 }
987 if (LocaleCompare(map,"RGBP") == 0)
988 {
cristycafe0412012-01-10 13:29:58 +0000989 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +0000990 {
cristycafe0412012-01-10 13:29:58 +0000991 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +0000992 if (p == (const Quantum *) NULL)
993 break;
cristycafe0412012-01-10 13:29:58 +0000994 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +0000995 {
996 *q++=(float) (QuantumScale*GetPixelRed(image,p));
997 *q++=(float) (QuantumScale*GetPixelGreen(image,p));
998 *q++=(float) (QuantumScale*GetPixelBlue(image,p));
999 *q++=0.0;
1000 p+=GetPixelChannels(image);
1001 }
1002 }
1003 return;
1004 }
cristy14d71292012-05-20 16:48:13 +00001005 length=strlen(map);
cristycafe0412012-01-10 13:29:58 +00001006 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00001007 {
cristycafe0412012-01-10 13:29:58 +00001008 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00001009 if (p == (const Quantum *) NULL)
1010 break;
cristycafe0412012-01-10 13:29:58 +00001011 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00001012 {
1013 register ssize_t
1014 i;
1015
cristy14d71292012-05-20 16:48:13 +00001016 for (i=0; i < (ssize_t) length; i++)
cristye5370942012-01-06 03:49:31 +00001017 {
1018 *q=0;
1019 switch (quantum_map[i])
1020 {
1021 case RedQuantum:
1022 case CyanQuantum:
1023 {
1024 *q=(float) (QuantumScale*GetPixelRed(image,p));
1025 break;
1026 }
1027 case GreenQuantum:
1028 case MagentaQuantum:
1029 {
1030 *q=(float) (QuantumScale*GetPixelGreen(image,p));
1031 break;
1032 }
1033 case BlueQuantum:
1034 case YellowQuantum:
1035 {
1036 *q=(float) (QuantumScale*GetPixelBlue(image,p));
1037 break;
1038 }
1039 case AlphaQuantum:
1040 {
1041 *q=(float) (QuantumScale*((Quantum) (GetPixelAlpha(image,p))));
1042 break;
1043 }
1044 case OpacityQuantum:
1045 {
1046 *q=(float) (QuantumScale*GetPixelAlpha(image,p));
1047 break;
1048 }
1049 case BlackQuantum:
1050 {
1051 if (image->colorspace == CMYKColorspace)
1052 *q=(float) (QuantumScale* GetPixelBlack(image,p));
1053 break;
1054 }
1055 case IndexQuantum:
1056 {
1057 *q=(float) (QuantumScale*GetPixelIntensity(image,p));
1058 break;
1059 }
1060 default:
1061 *q=0;
1062 }
1063 q++;
1064 }
1065 p+=GetPixelChannels(image);
1066 }
1067 }
1068}
1069
cristy2dc655d2012-07-05 13:16:28 +00001070static void ExportLongPixel(Image *image,const RectangleInfo *roi,
cristy46f4be22012-01-07 00:26:39 +00001071 const char *restrict map,const QuantumType *quantum_map,void *pixels,
1072 ExceptionInfo *exception)
cristye5370942012-01-06 03:49:31 +00001073{
1074 register const Quantum
1075 *restrict p;
1076
1077 register ssize_t
1078 x;
1079
1080 register unsigned int
cristy3fe11452012-01-09 01:27:42 +00001081 *restrict q;
cristye5370942012-01-06 03:49:31 +00001082
cristy14d71292012-05-20 16:48:13 +00001083 size_t
1084 length;
1085
cristye5370942012-01-06 03:49:31 +00001086 ssize_t
1087 y;
1088
1089 q=(unsigned int *) pixels;
1090 if (LocaleCompare(map,"BGR") == 0)
1091 {
cristycafe0412012-01-10 13:29:58 +00001092 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00001093 {
cristycafe0412012-01-10 13:29:58 +00001094 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00001095 if (p == (const Quantum *) NULL)
1096 break;
cristycafe0412012-01-10 13:29:58 +00001097 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00001098 {
cristy6c9e1682012-01-07 21:37:44 +00001099 *q++=ScaleQuantumToLong(GetPixelBlue(image,p));
1100 *q++=ScaleQuantumToLong(GetPixelGreen(image,p));
1101 *q++=ScaleQuantumToLong(GetPixelRed(image,p));
cristye5370942012-01-06 03:49:31 +00001102 p+=GetPixelChannels(image);
1103 }
1104 }
1105 return;
1106 }
1107 if (LocaleCompare(map,"BGRA") == 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 {
cristy6c9e1682012-01-07 21:37:44 +00001116 *q++=ScaleQuantumToLong(GetPixelBlue(image,p));
1117 *q++=ScaleQuantumToLong(GetPixelGreen(image,p));
1118 *q++=ScaleQuantumToLong(GetPixelRed(image,p));
1119 *q++=ScaleQuantumToLong(GetPixelAlpha(image,p));
cristye5370942012-01-06 03:49:31 +00001120 p+=GetPixelChannels(image);
1121 }
1122 }
1123 return;
1124 }
1125 if (LocaleCompare(map,"BGRP") == 0)
1126 {
cristycafe0412012-01-10 13:29:58 +00001127 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00001128 {
cristycafe0412012-01-10 13:29:58 +00001129 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00001130 if (p == (const Quantum *) NULL)
1131 break;
cristycafe0412012-01-10 13:29:58 +00001132 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00001133 {
cristy6c9e1682012-01-07 21:37:44 +00001134 *q++=ScaleQuantumToLong(GetPixelBlue(image,p));
1135 *q++=ScaleQuantumToLong(GetPixelGreen(image,p));
1136 *q++=ScaleQuantumToLong(GetPixelRed(image,p));
1137 *q++=0;
cristye5370942012-01-06 03:49:31 +00001138 p+=GetPixelChannels(image);
1139 }
1140 }
1141 return;
1142 }
1143 if (LocaleCompare(map,"I") == 0)
1144 {
cristycafe0412012-01-10 13:29:58 +00001145 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00001146 {
cristycafe0412012-01-10 13:29:58 +00001147 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00001148 if (p == (const Quantum *) NULL)
1149 break;
cristycafe0412012-01-10 13:29:58 +00001150 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00001151 {
cristy70e9f682013-03-12 22:31:22 +00001152 *q++=ScaleQuantumToLong(ClampToQuantum(GetPixelIntensity(image,p)));
cristye5370942012-01-06 03:49:31 +00001153 p+=GetPixelChannels(image);
1154 }
1155 }
1156 return;
1157 }
1158 if (LocaleCompare(map,"RGB") == 0)
1159 {
cristycafe0412012-01-10 13:29:58 +00001160 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00001161 {
cristycafe0412012-01-10 13:29:58 +00001162 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00001163 if (p == (const Quantum *) NULL)
1164 break;
cristycafe0412012-01-10 13:29:58 +00001165 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00001166 {
cristy6c9e1682012-01-07 21:37:44 +00001167 *q++=ScaleQuantumToLong(GetPixelRed(image,p));
1168 *q++=ScaleQuantumToLong(GetPixelGreen(image,p));
1169 *q++=ScaleQuantumToLong(GetPixelBlue(image,p));
cristye5370942012-01-06 03:49:31 +00001170 p+=GetPixelChannels(image);
1171 }
1172 }
1173 return;
1174 }
1175 if (LocaleCompare(map,"RGBA") == 0)
1176 {
cristycafe0412012-01-10 13:29:58 +00001177 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00001178 {
cristycafe0412012-01-10 13:29:58 +00001179 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00001180 if (p == (const Quantum *) NULL)
1181 break;
cristycafe0412012-01-10 13:29:58 +00001182 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00001183 {
cristy6c9e1682012-01-07 21:37:44 +00001184 *q++=ScaleQuantumToLong(GetPixelRed(image,p));
1185 *q++=ScaleQuantumToLong(GetPixelGreen(image,p));
1186 *q++=ScaleQuantumToLong(GetPixelBlue(image,p));
1187 *q++=ScaleQuantumToLong(GetPixelAlpha(image,p));
cristye5370942012-01-06 03:49:31 +00001188 p+=GetPixelChannels(image);
1189 }
1190 }
1191 return;
1192 }
1193 if (LocaleCompare(map,"RGBP") == 0)
1194 {
cristycafe0412012-01-10 13:29:58 +00001195 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00001196 {
cristycafe0412012-01-10 13:29:58 +00001197 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00001198 if (p == (const Quantum *) NULL)
1199 break;
cristycafe0412012-01-10 13:29:58 +00001200 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00001201 {
cristy6c9e1682012-01-07 21:37:44 +00001202 *q++=ScaleQuantumToLong(GetPixelRed(image,p));
1203 *q++=ScaleQuantumToLong(GetPixelGreen(image,p));
1204 *q++=ScaleQuantumToLong(GetPixelBlue(image,p));
1205 *q++=0;
cristye5370942012-01-06 03:49:31 +00001206 p+=GetPixelChannels(image);
1207 }
1208 }
1209 return;
1210 }
cristy14d71292012-05-20 16:48:13 +00001211 length=strlen(map);
cristycafe0412012-01-10 13:29:58 +00001212 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00001213 {
cristycafe0412012-01-10 13:29:58 +00001214 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00001215 if (p == (const Quantum *) NULL)
1216 break;
cristycafe0412012-01-10 13:29:58 +00001217 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00001218 {
1219 register ssize_t
1220 i;
1221
cristy14d71292012-05-20 16:48:13 +00001222 for (i=0; i < (ssize_t) length; i++)
cristye5370942012-01-06 03:49:31 +00001223 {
1224 *q=0;
1225 switch (quantum_map[i])
1226 {
1227 case RedQuantum:
1228 case CyanQuantum:
1229 {
cristy6c9e1682012-01-07 21:37:44 +00001230 *q=ScaleQuantumToLong(GetPixelRed(image,p));
cristye5370942012-01-06 03:49:31 +00001231 break;
1232 }
1233 case GreenQuantum:
1234 case MagentaQuantum:
1235 {
cristy6c9e1682012-01-07 21:37:44 +00001236 *q=ScaleQuantumToLong(GetPixelGreen(image,p));
cristye5370942012-01-06 03:49:31 +00001237 break;
1238 }
1239 case BlueQuantum:
1240 case YellowQuantum:
1241 {
cristy6c9e1682012-01-07 21:37:44 +00001242 *q=ScaleQuantumToLong(GetPixelBlue(image,p));
cristye5370942012-01-06 03:49:31 +00001243 break;
1244 }
1245 case AlphaQuantum:
1246 {
cristy6c9e1682012-01-07 21:37:44 +00001247 *q=ScaleQuantumToLong(GetPixelAlpha(image,p));
cristye5370942012-01-06 03:49:31 +00001248 break;
1249 }
1250 case OpacityQuantum:
1251 {
cristy6c9e1682012-01-07 21:37:44 +00001252 *q=ScaleQuantumToLong(GetPixelAlpha(image,p));
cristye5370942012-01-06 03:49:31 +00001253 break;
1254 }
1255 case BlackQuantum:
1256 {
1257 if (image->colorspace == CMYKColorspace)
cristy6c9e1682012-01-07 21:37:44 +00001258 *q=ScaleQuantumToLong(GetPixelBlack(image,p));
cristye5370942012-01-06 03:49:31 +00001259 break;
1260 }
1261 case IndexQuantum:
1262 {
cristy70e9f682013-03-12 22:31:22 +00001263 *q=ScaleQuantumToLong(ClampToQuantum(GetPixelIntensity(image,p)));
cristye5370942012-01-06 03:49:31 +00001264 break;
1265 }
1266 default:
cristy6c9e1682012-01-07 21:37:44 +00001267 break;
cristye5370942012-01-06 03:49:31 +00001268 }
1269 q++;
1270 }
1271 p+=GetPixelChannels(image);
1272 }
1273 }
1274}
1275
cristy2dc655d2012-07-05 13:16:28 +00001276static void ExportLongLongPixel(Image *image,const RectangleInfo *roi,
cristy46f4be22012-01-07 00:26:39 +00001277 const char *restrict map,const QuantumType *quantum_map,void *pixels,
1278 ExceptionInfo *exception)
cristye5370942012-01-06 03:49:31 +00001279{
1280 register const Quantum
1281 *restrict p;
1282
1283 register ssize_t
1284 x;
1285
cristyb13e12a2012-01-06 21:48:27 +00001286 register MagickSizeType
cristy3fe11452012-01-09 01:27:42 +00001287 *restrict q;
cristye5370942012-01-06 03:49:31 +00001288
cristy14d71292012-05-20 16:48:13 +00001289 size_t
1290 length;
1291
cristye5370942012-01-06 03:49:31 +00001292 ssize_t
1293 y;
1294
cristyb13e12a2012-01-06 21:48:27 +00001295 q=(MagickSizeType *) pixels;
cristye5370942012-01-06 03:49:31 +00001296 if (LocaleCompare(map,"BGR") == 0)
1297 {
cristycafe0412012-01-10 13:29:58 +00001298 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00001299 {
cristycafe0412012-01-10 13:29:58 +00001300 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00001301 if (p == (const Quantum *) NULL)
1302 break;
cristycafe0412012-01-10 13:29:58 +00001303 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00001304 {
cristyb13e12a2012-01-06 21:48:27 +00001305 *q++=ScaleQuantumToLongLong(GetPixelBlue(image,p));
1306 *q++=ScaleQuantumToLongLong(GetPixelGreen(image,p));
1307 *q++=ScaleQuantumToLongLong(GetPixelRed(image,p));
cristye5370942012-01-06 03:49:31 +00001308 p+=GetPixelChannels(image);
1309 }
1310 }
1311 return;
1312 }
1313 if (LocaleCompare(map,"BGRA") == 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 {
cristyb13e12a2012-01-06 21:48:27 +00001322 *q++=ScaleQuantumToLongLong(GetPixelBlue(image,p));
1323 *q++=ScaleQuantumToLongLong(GetPixelGreen(image,p));
1324 *q++=ScaleQuantumToLongLong(GetPixelRed(image,p));
1325 *q++=ScaleQuantumToLongLong(GetPixelAlpha(image,p));
cristye5370942012-01-06 03:49:31 +00001326 p+=GetPixelChannels(image);
1327 }
1328 }
1329 return;
1330 }
1331 if (LocaleCompare(map,"BGRP") == 0)
1332 {
cristycafe0412012-01-10 13:29:58 +00001333 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00001334 {
cristycafe0412012-01-10 13:29:58 +00001335 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00001336 if (p == (const Quantum *) NULL)
1337 break;
cristycafe0412012-01-10 13:29:58 +00001338 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00001339 {
cristyb13e12a2012-01-06 21:48:27 +00001340 *q++=ScaleQuantumToLongLong(GetPixelBlue(image,p));
1341 *q++=ScaleQuantumToLongLong(GetPixelGreen(image,p));
1342 *q++=ScaleQuantumToLongLong(GetPixelRed(image,p));
cristye5370942012-01-06 03:49:31 +00001343 *q++=0;
1344 p+=GetPixelChannels(image);
1345 }
1346 }
1347 return;
1348 }
1349 if (LocaleCompare(map,"I") == 0)
1350 {
cristycafe0412012-01-10 13:29:58 +00001351 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00001352 {
cristycafe0412012-01-10 13:29:58 +00001353 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00001354 if (p == (const Quantum *) NULL)
1355 break;
cristycafe0412012-01-10 13:29:58 +00001356 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00001357 {
cristy70e9f682013-03-12 22:31:22 +00001358 *q++=ScaleQuantumToLongLong(ClampToQuantum(GetPixelIntensity(image,p)));
cristye5370942012-01-06 03:49:31 +00001359 p+=GetPixelChannels(image);
1360 }
1361 }
1362 return;
1363 }
1364 if (LocaleCompare(map,"RGB") == 0)
1365 {
cristycafe0412012-01-10 13:29:58 +00001366 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00001367 {
cristycafe0412012-01-10 13:29:58 +00001368 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00001369 if (p == (const Quantum *) NULL)
1370 break;
cristycafe0412012-01-10 13:29:58 +00001371 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00001372 {
cristyb13e12a2012-01-06 21:48:27 +00001373 *q++=ScaleQuantumToLongLong(GetPixelRed(image,p));
1374 *q++=ScaleQuantumToLongLong(GetPixelGreen(image,p));
1375 *q++=ScaleQuantumToLongLong(GetPixelBlue(image,p));
cristye5370942012-01-06 03:49:31 +00001376 p+=GetPixelChannels(image);
1377 }
1378 }
1379 return;
1380 }
1381 if (LocaleCompare(map,"RGBA") == 0)
1382 {
cristycafe0412012-01-10 13:29:58 +00001383 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00001384 {
cristycafe0412012-01-10 13:29:58 +00001385 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00001386 if (p == (const Quantum *) NULL)
1387 break;
cristycafe0412012-01-10 13:29:58 +00001388 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00001389 {
cristyb13e12a2012-01-06 21:48:27 +00001390 *q++=ScaleQuantumToLongLong(GetPixelRed(image,p));
1391 *q++=ScaleQuantumToLongLong(GetPixelGreen(image,p));
1392 *q++=ScaleQuantumToLongLong(GetPixelBlue(image,p));
1393 *q++=ScaleQuantumToLongLong(GetPixelAlpha(image,p));
cristye5370942012-01-06 03:49:31 +00001394 p+=GetPixelChannels(image);
1395 }
1396 }
1397 return;
1398 }
1399 if (LocaleCompare(map,"RGBP") == 0)
1400 {
cristycafe0412012-01-10 13:29:58 +00001401 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00001402 {
cristycafe0412012-01-10 13:29:58 +00001403 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00001404 if (p == (const Quantum *) NULL)
1405 break;
cristycafe0412012-01-10 13:29:58 +00001406 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00001407 {
cristyb13e12a2012-01-06 21:48:27 +00001408 *q++=ScaleQuantumToLongLong(GetPixelRed(image,p));
1409 *q++=ScaleQuantumToLongLong(GetPixelGreen(image,p));
1410 *q++=ScaleQuantumToLongLong(GetPixelBlue(image,p));
cristye5370942012-01-06 03:49:31 +00001411 *q++=0;
1412 p+=GetPixelChannels(image);
1413 }
1414 }
1415 return;
1416 }
cristy14d71292012-05-20 16:48:13 +00001417 length=strlen(map);
cristycafe0412012-01-10 13:29:58 +00001418 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00001419 {
cristycafe0412012-01-10 13:29:58 +00001420 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00001421 if (p == (const Quantum *) NULL)
1422 break;
cristycafe0412012-01-10 13:29:58 +00001423 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00001424 {
1425 register ssize_t
1426 i;
1427
cristy14d71292012-05-20 16:48:13 +00001428 for (i=0; i < (ssize_t) length; i++)
cristye5370942012-01-06 03:49:31 +00001429 {
1430 *q=0;
1431 switch (quantum_map[i])
1432 {
1433 case RedQuantum:
1434 case CyanQuantum:
1435 {
cristyb13e12a2012-01-06 21:48:27 +00001436 *q=ScaleQuantumToLongLong(GetPixelRed(image,p));
cristye5370942012-01-06 03:49:31 +00001437 break;
1438 }
1439 case GreenQuantum:
1440 case MagentaQuantum:
1441 {
cristyb13e12a2012-01-06 21:48:27 +00001442 *q=ScaleQuantumToLongLong(GetPixelGreen(image,p));
cristye5370942012-01-06 03:49:31 +00001443 break;
1444 }
1445 case BlueQuantum:
1446 case YellowQuantum:
1447 {
cristyb13e12a2012-01-06 21:48:27 +00001448 *q=ScaleQuantumToLongLong(GetPixelBlue(image,p));
cristye5370942012-01-06 03:49:31 +00001449 break;
1450 }
1451 case AlphaQuantum:
1452 {
cristyb13e12a2012-01-06 21:48:27 +00001453 *q=ScaleQuantumToLongLong(GetPixelAlpha(image,p));
cristye5370942012-01-06 03:49:31 +00001454 break;
1455 }
1456 case OpacityQuantum:
1457 {
cristyb13e12a2012-01-06 21:48:27 +00001458 *q=ScaleQuantumToLongLong(GetPixelAlpha(image,p));
cristye5370942012-01-06 03:49:31 +00001459 break;
1460 }
1461 case BlackQuantum:
1462 {
1463 if (image->colorspace == CMYKColorspace)
cristyb13e12a2012-01-06 21:48:27 +00001464 *q=ScaleQuantumToLongLong(GetPixelBlack(image,p));
cristye5370942012-01-06 03:49:31 +00001465 break;
1466 }
1467 case IndexQuantum:
1468 {
cristy70e9f682013-03-12 22:31:22 +00001469 *q=ScaleQuantumToLongLong(ClampToQuantum(GetPixelIntensity(image,p)));
cristye5370942012-01-06 03:49:31 +00001470 break;
1471 }
1472 default:
1473 break;
1474 }
1475 q++;
1476 }
1477 p+=GetPixelChannels(image);
1478 }
1479 }
1480}
1481
cristy2dc655d2012-07-05 13:16:28 +00001482static void ExportQuantumPixel(Image *image,const RectangleInfo *roi,
cristy46f4be22012-01-07 00:26:39 +00001483 const char *restrict map,const QuantumType *quantum_map,void *pixels,
1484 ExceptionInfo *exception)
cristye5370942012-01-06 03:49:31 +00001485{
1486 register const Quantum
1487 *restrict p;
1488
1489 register Quantum
cristy3fe11452012-01-09 01:27:42 +00001490 *restrict q;
cristye5370942012-01-06 03:49:31 +00001491
1492 register ssize_t
1493 x;
1494
cristy14d71292012-05-20 16:48:13 +00001495 size_t
1496 length;
1497
cristye5370942012-01-06 03:49:31 +00001498 ssize_t
1499 y;
1500
1501 q=(Quantum *) pixels;
1502 if (LocaleCompare(map,"BGR") == 0)
1503 {
cristycafe0412012-01-10 13:29:58 +00001504 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00001505 {
cristycafe0412012-01-10 13:29:58 +00001506 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00001507 if (p == (const Quantum *) NULL)
1508 break;
cristycafe0412012-01-10 13:29:58 +00001509 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00001510 {
1511 *q++=GetPixelBlue(image,p);
1512 *q++=GetPixelGreen(image,p);
1513 *q++=GetPixelRed(image,p);
1514 p+=GetPixelChannels(image);
1515 }
1516 }
1517 return;
1518 }
1519 if (LocaleCompare(map,"BGRA") == 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 {
1528 *q++=GetPixelBlue(image,p);
1529 *q++=GetPixelGreen(image,p);
1530 *q++=GetPixelRed(image,p);
1531 *q++=(Quantum) (GetPixelAlpha(image,p));
1532 p+=GetPixelChannels(image);
1533 }
1534 }
1535 return;
1536 }
1537 if (LocaleCompare(map,"BGRP") == 0)
1538 {
cristycafe0412012-01-10 13:29:58 +00001539 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00001540 {
cristycafe0412012-01-10 13:29:58 +00001541 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00001542 if (p == (const Quantum *) NULL)
1543 break;
cristycafe0412012-01-10 13:29:58 +00001544 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00001545 {
1546 *q++=GetPixelBlue(image,p);
1547 *q++=GetPixelGreen(image,p);
1548 *q++=GetPixelRed(image,p);
1549 *q++=(Quantum) 0;
1550 p+=GetPixelChannels(image);
1551 }
1552 }
1553 return;
1554 }
1555 if (LocaleCompare(map,"I") == 0)
1556 {
cristycafe0412012-01-10 13:29:58 +00001557 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00001558 {
cristycafe0412012-01-10 13:29:58 +00001559 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00001560 if (p == (const Quantum *) NULL)
1561 break;
cristycafe0412012-01-10 13:29:58 +00001562 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00001563 {
cristy70e9f682013-03-12 22:31:22 +00001564 *q++=ClampToQuantum(GetPixelIntensity(image,p));
cristye5370942012-01-06 03:49:31 +00001565 p+=GetPixelChannels(image);
1566 }
1567 }
1568 return;
1569 }
1570 if (LocaleCompare(map,"RGB") == 0)
1571 {
cristycafe0412012-01-10 13:29:58 +00001572 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00001573 {
cristycafe0412012-01-10 13:29:58 +00001574 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00001575 if (p == (const Quantum *) NULL)
1576 break;
cristycafe0412012-01-10 13:29:58 +00001577 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00001578 {
1579 *q++=GetPixelRed(image,p);
1580 *q++=GetPixelGreen(image,p);
1581 *q++=GetPixelBlue(image,p);
1582 p+=GetPixelChannels(image);
1583 }
1584 }
1585 return;
1586 }
1587 if (LocaleCompare(map,"RGBA") == 0)
1588 {
cristycafe0412012-01-10 13:29:58 +00001589 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00001590 {
cristycafe0412012-01-10 13:29:58 +00001591 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00001592 if (p == (const Quantum *) NULL)
1593 break;
cristycafe0412012-01-10 13:29:58 +00001594 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00001595 {
1596 *q++=GetPixelRed(image,p);
1597 *q++=GetPixelGreen(image,p);
1598 *q++=GetPixelBlue(image,p);
1599 *q++=(Quantum) (GetPixelAlpha(image,p));
1600 p+=GetPixelChannels(image);
1601 }
1602 }
1603 return;
1604 }
1605 if (LocaleCompare(map,"RGBP") == 0)
1606 {
cristycafe0412012-01-10 13:29:58 +00001607 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00001608 {
cristycafe0412012-01-10 13:29:58 +00001609 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00001610 if (p == (const Quantum *) NULL)
1611 break;
cristycafe0412012-01-10 13:29:58 +00001612 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00001613 {
1614 *q++=GetPixelRed(image,p);
1615 *q++=GetPixelGreen(image,p);
1616 *q++=GetPixelBlue(image,p);
1617 *q++=(Quantum) 0;
1618 p+=GetPixelChannels(image);
1619 }
1620 }
1621 return;
1622 }
cristy14d71292012-05-20 16:48:13 +00001623 length=strlen(map);
cristycafe0412012-01-10 13:29:58 +00001624 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00001625 {
cristycafe0412012-01-10 13:29:58 +00001626 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00001627 if (p == (const Quantum *) NULL)
1628 break;
cristycafe0412012-01-10 13:29:58 +00001629 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00001630 {
1631 register ssize_t
1632 i;
1633
cristy14d71292012-05-20 16:48:13 +00001634 for (i=0; i < (ssize_t) length; i++)
cristye5370942012-01-06 03:49:31 +00001635 {
1636 *q=(Quantum) 0;
1637 switch (quantum_map[i])
1638 {
1639 case RedQuantum:
1640 case CyanQuantum:
1641 {
1642 *q=GetPixelRed(image,p);
1643 break;
1644 }
1645 case GreenQuantum:
1646 case MagentaQuantum:
1647 {
1648 *q=GetPixelGreen(image,p);
1649 break;
1650 }
1651 case BlueQuantum:
1652 case YellowQuantum:
1653 {
1654 *q=GetPixelBlue(image,p);
1655 break;
1656 }
1657 case AlphaQuantum:
1658 {
1659 *q=GetPixelAlpha(image,p);
1660 break;
1661 }
1662 case OpacityQuantum:
1663 {
1664 *q=GetPixelAlpha(image,p);
1665 break;
1666 }
1667 case BlackQuantum:
1668 {
1669 if (image->colorspace == CMYKColorspace)
1670 *q=GetPixelBlack(image,p);
1671 break;
1672 }
1673 case IndexQuantum:
1674 {
cristy70e9f682013-03-12 22:31:22 +00001675 *q=ClampToQuantum(GetPixelIntensity(image,p));
cristye5370942012-01-06 03:49:31 +00001676 break;
1677 }
1678 default:
1679 {
1680 *q=(Quantum) 0;
1681 break;
1682 }
1683 }
1684 q++;
1685 }
1686 p+=GetPixelChannels(image);
1687 }
1688 }
1689}
1690
cristy2dc655d2012-07-05 13:16:28 +00001691static void ExportShortPixel(Image *image,const RectangleInfo *roi,
cristy46f4be22012-01-07 00:26:39 +00001692 const char *restrict map,const QuantumType *quantum_map,void *pixels,
1693 ExceptionInfo *exception)
cristye5370942012-01-06 03:49:31 +00001694{
1695 register const Quantum
1696 *restrict p;
1697
1698 register ssize_t
1699 x;
1700
cristye5370942012-01-06 03:49:31 +00001701 register unsigned short
cristy3fe11452012-01-09 01:27:42 +00001702 *restrict q;
cristye5370942012-01-06 03:49:31 +00001703
cristy14d71292012-05-20 16:48:13 +00001704 size_t
1705 length;
1706
1707 ssize_t
1708 y;
1709
cristye5370942012-01-06 03:49:31 +00001710 q=(unsigned short *) pixels;
1711 if (LocaleCompare(map,"BGR") == 0)
1712 {
cristycafe0412012-01-10 13:29:58 +00001713 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00001714 {
cristycafe0412012-01-10 13:29:58 +00001715 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00001716 if (p == (const Quantum *) NULL)
1717 break;
cristycafe0412012-01-10 13:29:58 +00001718 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00001719 {
1720 *q++=ScaleQuantumToShort(GetPixelBlue(image,p));
1721 *q++=ScaleQuantumToShort(GetPixelGreen(image,p));
1722 *q++=ScaleQuantumToShort(GetPixelRed(image,p));
1723 p+=GetPixelChannels(image);
1724 }
1725 }
1726 return;
1727 }
1728 if (LocaleCompare(map,"BGRA") == 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 {
1737 *q++=ScaleQuantumToShort(GetPixelBlue(image,p));
1738 *q++=ScaleQuantumToShort(GetPixelGreen(image,p));
1739 *q++=ScaleQuantumToShort(GetPixelRed(image,p));
1740 *q++=ScaleQuantumToShort(GetPixelAlpha(image,p));
1741 p+=GetPixelChannels(image);
1742 }
1743 }
1744 return;
1745 }
1746 if (LocaleCompare(map,"BGRP") == 0)
1747 {
cristycafe0412012-01-10 13:29:58 +00001748 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00001749 {
cristycafe0412012-01-10 13:29:58 +00001750 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00001751 if (p == (const Quantum *) NULL)
1752 break;
cristycafe0412012-01-10 13:29:58 +00001753 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00001754 {
1755 *q++=ScaleQuantumToShort(GetPixelBlue(image,p));
1756 *q++=ScaleQuantumToShort(GetPixelGreen(image,p));
1757 *q++=ScaleQuantumToShort(GetPixelRed(image,p));
1758 *q++=0;
1759 p+=GetPixelChannels(image);
1760 }
1761 }
1762 return;
1763 }
1764 if (LocaleCompare(map,"I") == 0)
1765 {
cristycafe0412012-01-10 13:29:58 +00001766 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00001767 {
cristycafe0412012-01-10 13:29:58 +00001768 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00001769 if (p == (const Quantum *) NULL)
1770 break;
cristycafe0412012-01-10 13:29:58 +00001771 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00001772 {
cristy70e9f682013-03-12 22:31:22 +00001773 *q++=ScaleQuantumToShort(ClampToQuantum(GetPixelIntensity(image,p)));
cristye5370942012-01-06 03:49:31 +00001774 p+=GetPixelChannels(image);
1775 }
1776 }
1777 return;
1778 }
1779 if (LocaleCompare(map,"RGB") == 0)
1780 {
cristycafe0412012-01-10 13:29:58 +00001781 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00001782 {
cristycafe0412012-01-10 13:29:58 +00001783 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00001784 if (p == (const Quantum *) NULL)
1785 break;
cristycafe0412012-01-10 13:29:58 +00001786 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00001787 {
1788 *q++=ScaleQuantumToShort(GetPixelRed(image,p));
1789 *q++=ScaleQuantumToShort(GetPixelGreen(image,p));
1790 *q++=ScaleQuantumToShort(GetPixelBlue(image,p));
1791 p+=GetPixelChannels(image);
1792 }
1793 }
1794 return;
1795 }
1796 if (LocaleCompare(map,"RGBA") == 0)
1797 {
cristycafe0412012-01-10 13:29:58 +00001798 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00001799 {
cristycafe0412012-01-10 13:29:58 +00001800 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00001801 if (p == (const Quantum *) NULL)
1802 break;
cristycafe0412012-01-10 13:29:58 +00001803 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00001804 {
1805 *q++=ScaleQuantumToShort(GetPixelRed(image,p));
1806 *q++=ScaleQuantumToShort(GetPixelGreen(image,p));
1807 *q++=ScaleQuantumToShort(GetPixelBlue(image,p));
1808 *q++=ScaleQuantumToShort(GetPixelAlpha(image,p));
1809 p+=GetPixelChannels(image);
1810 }
1811 }
1812 return;
1813 }
1814 if (LocaleCompare(map,"RGBP") == 0)
1815 {
cristycafe0412012-01-10 13:29:58 +00001816 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00001817 {
cristycafe0412012-01-10 13:29:58 +00001818 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00001819 if (p == (const Quantum *) NULL)
1820 break;
cristycafe0412012-01-10 13:29:58 +00001821 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00001822 {
1823 *q++=ScaleQuantumToShort(GetPixelRed(image,p));
1824 *q++=ScaleQuantumToShort(GetPixelGreen(image,p));
1825 *q++=ScaleQuantumToShort(GetPixelBlue(image,p));
1826 *q++=0;
1827 p+=GetPixelChannels(image);
1828 }
1829 }
1830 return;
1831 }
cristy14d71292012-05-20 16:48:13 +00001832 length=strlen(map);
cristycafe0412012-01-10 13:29:58 +00001833 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00001834 {
cristycafe0412012-01-10 13:29:58 +00001835 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00001836 if (p == (const Quantum *) NULL)
1837 break;
cristycafe0412012-01-10 13:29:58 +00001838 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00001839 {
1840 register ssize_t
1841 i;
1842
cristy14d71292012-05-20 16:48:13 +00001843 for (i=0; i < (ssize_t) length; i++)
cristye5370942012-01-06 03:49:31 +00001844 {
1845 *q=0;
1846 switch (quantum_map[i])
1847 {
1848 case RedQuantum:
1849 case CyanQuantum:
1850 {
1851 *q=ScaleQuantumToShort(GetPixelRed(image,p));
1852 break;
1853 }
1854 case GreenQuantum:
1855 case MagentaQuantum:
1856 {
1857 *q=ScaleQuantumToShort(GetPixelGreen(image,p));
1858 break;
1859 }
1860 case BlueQuantum:
1861 case YellowQuantum:
1862 {
1863 *q=ScaleQuantumToShort(GetPixelBlue(image,p));
1864 break;
1865 }
1866 case AlphaQuantum:
1867 {
1868 *q=ScaleQuantumToShort(GetPixelAlpha(image,p));
1869 break;
1870 }
1871 case OpacityQuantum:
1872 {
1873 *q=ScaleQuantumToShort(GetPixelAlpha(image,p));
1874 break;
1875 }
1876 case BlackQuantum:
1877 {
1878 if (image->colorspace == CMYKColorspace)
1879 *q=ScaleQuantumToShort(GetPixelBlack(image,p));
1880 break;
1881 }
1882 case IndexQuantum:
1883 {
cristy70e9f682013-03-12 22:31:22 +00001884 *q=ScaleQuantumToShort(ClampToQuantum(GetPixelIntensity(image,p)));
cristye5370942012-01-06 03:49:31 +00001885 break;
1886 }
1887 default:
1888 break;
1889 }
1890 q++;
1891 }
1892 p+=GetPixelChannels(image);
1893 }
1894 }
1895}
1896
cristy2dc655d2012-07-05 13:16:28 +00001897MagickExport MagickBooleanType ExportImagePixels(Image *image,
cristycafe0412012-01-10 13:29:58 +00001898 const ssize_t x,const ssize_t y,const size_t width,const size_t height,
1899 const char *map,const StorageType type,void *pixels,ExceptionInfo *exception)
cristy4c08aed2011-07-01 19:47:50 +00001900{
1901 QuantumType
1902 *quantum_map;
1903
cristycafe0412012-01-10 13:29:58 +00001904 RectangleInfo
1905 roi;
1906
cristy4c08aed2011-07-01 19:47:50 +00001907 register ssize_t
cristye5370942012-01-06 03:49:31 +00001908 i;
cristy4c08aed2011-07-01 19:47:50 +00001909
cristy14d71292012-05-20 16:48:13 +00001910 size_t
1911 length;
1912
cristy4c08aed2011-07-01 19:47:50 +00001913 assert(image != (Image *) NULL);
1914 assert(image->signature == MagickSignature);
1915 if (image->debug != MagickFalse)
1916 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
cristy14d71292012-05-20 16:48:13 +00001917 length=strlen(map);
1918 quantum_map=(QuantumType *) AcquireQuantumMemory(length,sizeof(*quantum_map));
cristy4c08aed2011-07-01 19:47:50 +00001919 if (quantum_map == (QuantumType *) NULL)
1920 {
1921 (void) ThrowMagickException(exception,GetMagickModule(),
cristyefe601c2013-01-05 17:51:12 +00001922 ResourceLimitError,"MemoryAllocationFailed","`%s'",image->filename);
cristy4c08aed2011-07-01 19:47:50 +00001923 return(MagickFalse);
1924 }
cristy14d71292012-05-20 16:48:13 +00001925 for (i=0; i < (ssize_t) length; i++)
cristy4c08aed2011-07-01 19:47:50 +00001926 {
1927 switch (map[i])
1928 {
1929 case 'A':
1930 case 'a':
1931 {
1932 quantum_map[i]=AlphaQuantum;
1933 break;
1934 }
1935 case 'B':
1936 case 'b':
1937 {
1938 quantum_map[i]=BlueQuantum;
1939 break;
1940 }
1941 case 'C':
1942 case 'c':
1943 {
1944 quantum_map[i]=CyanQuantum;
1945 if (image->colorspace == CMYKColorspace)
1946 break;
1947 quantum_map=(QuantumType *) RelinquishMagickMemory(quantum_map);
1948 (void) ThrowMagickException(exception,GetMagickModule(),ImageError,
cristyefe601c2013-01-05 17:51:12 +00001949 "ColorSeparatedImageRequired","`%s'",map);
cristy4c08aed2011-07-01 19:47:50 +00001950 return(MagickFalse);
1951 }
1952 case 'g':
1953 case 'G':
1954 {
1955 quantum_map[i]=GreenQuantum;
1956 break;
1957 }
1958 case 'I':
1959 case 'i':
1960 {
1961 quantum_map[i]=IndexQuantum;
1962 break;
1963 }
1964 case 'K':
1965 case 'k':
1966 {
1967 quantum_map[i]=BlackQuantum;
1968 if (image->colorspace == CMYKColorspace)
1969 break;
1970 quantum_map=(QuantumType *) RelinquishMagickMemory(quantum_map);
1971 (void) ThrowMagickException(exception,GetMagickModule(),ImageError,
cristyefe601c2013-01-05 17:51:12 +00001972 "ColorSeparatedImageRequired","`%s'",map);
cristy4c08aed2011-07-01 19:47:50 +00001973 return(MagickFalse);
1974 }
1975 case 'M':
1976 case 'm':
1977 {
1978 quantum_map[i]=MagentaQuantum;
1979 if (image->colorspace == CMYKColorspace)
1980 break;
1981 quantum_map=(QuantumType *) RelinquishMagickMemory(quantum_map);
1982 (void) ThrowMagickException(exception,GetMagickModule(),ImageError,
cristyefe601c2013-01-05 17:51:12 +00001983 "ColorSeparatedImageRequired","`%s'",map);
cristy4c08aed2011-07-01 19:47:50 +00001984 return(MagickFalse);
1985 }
1986 case 'o':
1987 case 'O':
1988 {
1989 quantum_map[i]=OpacityQuantum;
1990 break;
1991 }
1992 case 'P':
1993 case 'p':
1994 {
1995 quantum_map[i]=UndefinedQuantum;
1996 break;
1997 }
1998 case 'R':
1999 case 'r':
2000 {
2001 quantum_map[i]=RedQuantum;
2002 break;
2003 }
2004 case 'Y':
2005 case 'y':
2006 {
2007 quantum_map[i]=YellowQuantum;
2008 if (image->colorspace == CMYKColorspace)
2009 break;
2010 quantum_map=(QuantumType *) RelinquishMagickMemory(quantum_map);
2011 (void) ThrowMagickException(exception,GetMagickModule(),ImageError,
cristyefe601c2013-01-05 17:51:12 +00002012 "ColorSeparatedImageRequired","`%s'",map);
cristy4c08aed2011-07-01 19:47:50 +00002013 return(MagickFalse);
2014 }
2015 default:
2016 {
2017 quantum_map=(QuantumType *) RelinquishMagickMemory(quantum_map);
2018 (void) ThrowMagickException(exception,GetMagickModule(),OptionError,
cristyefe601c2013-01-05 17:51:12 +00002019 "UnrecognizedPixelMap","`%s'",map);
cristy4c08aed2011-07-01 19:47:50 +00002020 return(MagickFalse);
2021 }
2022 }
2023 }
cristycafe0412012-01-10 13:29:58 +00002024 roi.width=width;
2025 roi.height=height;
2026 roi.x=x;
2027 roi.y=y;
cristy4c08aed2011-07-01 19:47:50 +00002028 switch (type)
2029 {
2030 case CharPixel:
2031 {
cristycafe0412012-01-10 13:29:58 +00002032 ExportCharPixel(image,&roi,map,quantum_map,pixels,exception);
cristy4c08aed2011-07-01 19:47:50 +00002033 break;
2034 }
2035 case DoublePixel:
2036 {
cristycafe0412012-01-10 13:29:58 +00002037 ExportDoublePixel(image,&roi,map,quantum_map,pixels,exception);
cristy4c08aed2011-07-01 19:47:50 +00002038 break;
2039 }
2040 case FloatPixel:
2041 {
cristycafe0412012-01-10 13:29:58 +00002042 ExportFloatPixel(image,&roi,map,quantum_map,pixels,exception);
cristy4c08aed2011-07-01 19:47:50 +00002043 break;
2044 }
cristy4c08aed2011-07-01 19:47:50 +00002045 case LongPixel:
2046 {
cristycafe0412012-01-10 13:29:58 +00002047 ExportLongPixel(image,&roi,map,quantum_map,pixels,exception);
cristy4c08aed2011-07-01 19:47:50 +00002048 break;
2049 }
cristy6c9e1682012-01-07 21:37:44 +00002050 case LongLongPixel:
2051 {
cristycafe0412012-01-10 13:29:58 +00002052 ExportLongLongPixel(image,&roi,map,quantum_map,pixels,exception);
cristy6c9e1682012-01-07 21:37:44 +00002053 break;
2054 }
cristy4c08aed2011-07-01 19:47:50 +00002055 case QuantumPixel:
2056 {
cristycafe0412012-01-10 13:29:58 +00002057 ExportQuantumPixel(image,&roi,map,quantum_map,pixels,exception);
cristy4c08aed2011-07-01 19:47:50 +00002058 break;
2059 }
2060 case ShortPixel:
2061 {
cristycafe0412012-01-10 13:29:58 +00002062 ExportShortPixel(image,&roi,map,quantum_map,pixels,exception);
cristy4c08aed2011-07-01 19:47:50 +00002063 break;
2064 }
2065 default:
2066 {
2067 quantum_map=(QuantumType *) RelinquishMagickMemory(quantum_map);
2068 (void) ThrowMagickException(exception,GetMagickModule(),OptionError,
cristyefe601c2013-01-05 17:51:12 +00002069 "UnrecognizedPixelMap","`%s'",map);
cristy4c08aed2011-07-01 19:47:50 +00002070 break;
2071 }
2072 }
2073 quantum_map=(QuantumType *) RelinquishMagickMemory(quantum_map);
2074 return(MagickTrue);
2075}
2076
2077/*
2078%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2079% %
2080% %
2081% %
cristyaa8634f2011-10-01 13:25:12 +00002082% G e t P i x e l I n f o %
cristy4c08aed2011-07-01 19:47:50 +00002083% %
2084% %
2085% %
2086%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2087%
2088% GetPixelInfo() initializes the PixelInfo structure.
2089%
2090% The format of the GetPixelInfo method is:
2091%
2092% GetPixelInfo(const Image *image,PixelInfo *pixel)
2093%
2094% A description of each parameter follows:
2095%
anthonya322a832013-04-27 06:28:03 +00002096% o image: the image. (optional - may be NULL)
cristy4c08aed2011-07-01 19:47:50 +00002097%
cristy101ab702011-10-13 13:06:32 +00002098% o pixel: Specifies a pointer to a PixelInfo structure.
cristy4c08aed2011-07-01 19:47:50 +00002099%
2100*/
cristyaa8634f2011-10-01 13:25:12 +00002101MagickExport void GetPixelInfo(const Image *image,PixelInfo *pixel)
cristy4c08aed2011-07-01 19:47:50 +00002102{
2103 pixel->storage_class=DirectClass;
cristy7020ae62012-04-18 12:58:34 +00002104 pixel->colorspace=sRGBColorspace;
cristy8a46d822012-08-28 23:32:39 +00002105 pixel->alpha_trait=UndefinedPixelTrait;
cristy4c08aed2011-07-01 19:47:50 +00002106 pixel->fuzz=0.0;
2107 pixel->depth=MAGICKCORE_QUANTUM_DEPTH;
2108 pixel->red=0.0;
2109 pixel->green=0.0;
2110 pixel->blue=0.0;
2111 pixel->black=0.0;
cristya19f1d72012-08-07 18:24:38 +00002112 pixel->alpha=(double) OpaqueAlpha;
cristy4c08aed2011-07-01 19:47:50 +00002113 pixel->index=0.0;
2114 if (image == (const Image *) NULL)
2115 return;
2116 pixel->storage_class=image->storage_class;
2117 pixel->colorspace=image->colorspace;
cristy8a46d822012-08-28 23:32:39 +00002118 pixel->alpha_trait=image->alpha_trait;
cristy4c08aed2011-07-01 19:47:50 +00002119 pixel->depth=image->depth;
2120 pixel->fuzz=image->fuzz;
2121}
2122
2123/*
2124%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2125% %
2126% %
2127% %
cristy9731df72013-03-12 16:31:13 +00002128% G e t P i x e l I n t e n s i t y %
2129% %
2130% %
2131% %
2132%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2133%
cristy0c5c8892013-03-12 16:33:48 +00002134% GetPixelIntensity() returns a single sample intensity value from the red,
cristy70e9f682013-03-12 22:31:22 +00002135% green, and blue components of a pixel based on the selected method:
2136%
cristy2cf5d372013-03-13 12:03:11 +00002137% Rec601Luma 0.298839R' + 0.586811G' + 0.114350B'
2138% Rec601Luminance 0.298839R + 0.586811G + 0.114350B
2139% Rec709Luma 0.21260R' + 0.71520G' + 0.07220B'
2140% Rec709Luminance 0.21260R + 0.71520G + 0.07220B
2141% Brightness max(R, G, B)
2142% Lightness (min(R, G, B) + max(R, G, B)) / 2.0
2143% RMS (R'^2 + G'^2 + B'^2) / 3.0
2144% Average (R' + G' + B') / 3.0
cristy9731df72013-03-12 16:31:13 +00002145%
2146% The format of the GetPixelIntensity method is:
2147%
cristy2cf5d372013-03-13 12:03:11 +00002148% MagickRealType GetPixelIntensity(const Image *image,
2149% const Quantum *pixel)
cristy9731df72013-03-12 16:31:13 +00002150%
2151% A description of each parameter follows:
2152%
2153% o image: the image.
2154%
2155% o pixel: Specifies a pointer to a Quantum structure.
2156%
2157*/
cristy70e9f682013-03-12 22:31:22 +00002158
2159static inline MagickRealType MagickMax(const MagickRealType x,
2160 const MagickRealType y)
2161{
2162 if (x > y)
2163 return(x);
2164 return(y);
2165}
2166
2167static inline MagickRealType MagickMin(const MagickRealType x,
2168 const MagickRealType y)
2169{
2170 if (x < y)
2171 return(x);
2172 return(y);
2173}
2174
cristy9731df72013-03-12 16:31:13 +00002175MagickExport MagickRealType GetPixelIntensity(const Image *restrict image,
2176 const Quantum *restrict pixel)
2177{
2178 MagickRealType
2179 blue,
2180 green,
cristy70e9f682013-03-12 22:31:22 +00002181 red,
2182 intensity;
cristy9731df72013-03-12 16:31:13 +00002183
2184 if (image->colorspace == GRAYColorspace)
cristy592d6bb2013-04-07 15:20:37 +00002185 return((MagickRealType) GetPixelGray(image,pixel));
2186 red=(MagickRealType) GetPixelRed(image,pixel);
2187 green=(MagickRealType) GetPixelGreen(image,pixel);
2188 blue=(MagickRealType) GetPixelBlue(image,pixel);
cristy70e9f682013-03-12 22:31:22 +00002189 switch (image->intensity)
2190 {
cristybf02d732013-03-13 16:28:58 +00002191 case AveragePixelIntensityMethod:
2192 {
2193 intensity=(red+green+blue)/3.0;
2194 break;
2195 }
2196 case BrightnessPixelIntensityMethod:
2197 {
2198 intensity=MagickMax(MagickMax(red,green),blue);
2199 break;
2200 }
2201 case LightnessPixelIntensityMethod:
2202 {
2203 intensity=MagickMin(MagickMin(red,green),blue);
2204 break;
2205 }
cristy462c1ca2013-04-15 10:29:18 +00002206 case MSPixelIntensityMethod:
2207 {
2208 intensity=(MagickRealType) (((double) red*red+green*green+blue*blue)/
2209 (3.0*QuantumRange));
2210 break;
2211 }
cristy70e9f682013-03-12 22:31:22 +00002212 case Rec601LumaPixelIntensityMethod:
cristy70e9f682013-03-12 22:31:22 +00002213 {
cristy9e2436a2013-05-02 20:35:59 +00002214 intensity=0.298839*red+0.586811*green+0.114350*blue;
cristy2cf5d372013-03-13 12:03:11 +00002215 break;
2216 }
2217 case Rec601LuminancePixelIntensityMethod:
2218 {
cristy70e9f682013-03-12 22:31:22 +00002219 if (image->colorspace == sRGBColorspace)
2220 {
2221 red=DecodePixelGamma(red);
2222 green=DecodePixelGamma(green);
2223 blue=DecodePixelGamma(blue);
2224 }
cristy9e2436a2013-05-02 20:35:59 +00002225 intensity=0.298839*red+0.586811*green+0.114350*blue;
cristy70e9f682013-03-12 22:31:22 +00002226 break;
2227 }
2228 case Rec709LumaPixelIntensityMethod:
cristyc94210c2013-05-06 14:09:53 +00002229 default:
cristy70e9f682013-03-12 22:31:22 +00002230 {
cristy2cf5d372013-03-13 12:03:11 +00002231 intensity=0.21260f*red+0.71520f*green+0.07220f*blue;
2232 break;
2233 }
2234 case Rec709LuminancePixelIntensityMethod:
2235 {
cristy70e9f682013-03-12 22:31:22 +00002236 if (image->colorspace == sRGBColorspace)
2237 {
2238 red=DecodePixelGamma(red);
2239 green=DecodePixelGamma(green);
2240 blue=DecodePixelGamma(blue);
2241 }
2242 intensity=0.21260f*red+0.71520f*green+0.07220f*blue;
2243 break;
2244 }
cristy70e9f682013-03-12 22:31:22 +00002245 case RMSPixelIntensityMethod:
2246 {
cristy462c1ca2013-04-15 10:29:18 +00002247 intensity=(MagickRealType) (sqrt((double) red*red+green*green+blue*blue)/
2248 sqrt(3.0));
cristy70e9f682013-03-12 22:31:22 +00002249 break;
2250 }
cristy70e9f682013-03-12 22:31:22 +00002251 }
2252 return(intensity);
cristy9731df72013-03-12 16:31:13 +00002253}
cristy9731df72013-03-12 16:31:13 +00002254
2255/*
2256%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2257% %
2258% %
2259% %
cristy4c08aed2011-07-01 19:47:50 +00002260% I m p o r t I m a g e P i x e l s %
2261% %
2262% %
2263% %
2264%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2265%
2266% ImportImagePixels() accepts pixel data and stores in the image at the
2267% location you specify. The method returns MagickTrue on success otherwise
2268% MagickFalse if an error is encountered. The pixel data can be either char,
cristyb5a45a32012-01-10 13:31:13 +00002269% Quantum, short int, unsigned int, unsigned long long, float, or double in
2270% the order specified by map.
cristy4c08aed2011-07-01 19:47:50 +00002271%
2272% Suppose your want to upload the first scanline of a 640x480 image from
2273% character data in red-green-blue order:
2274%
2275% ImportImagePixels(image,0,0,640,1,"RGB",CharPixel,pixels);
2276%
2277% The format of the ImportImagePixels method is:
2278%
cristycafe0412012-01-10 13:29:58 +00002279% MagickBooleanType ImportImagePixels(Image *image,const ssize_t x,
2280% const ssize_t y,const size_t width,const size_t height,
2281% const char *map,const StorageType type,const void *pixels,
2282% ExceptionInfo *exception)
cristy4c08aed2011-07-01 19:47:50 +00002283%
2284% A description of each parameter follows:
2285%
2286% o image: the image.
2287%
cristycafe0412012-01-10 13:29:58 +00002288% o x,y,width,height: These values define the perimeter
cristy4c08aed2011-07-01 19:47:50 +00002289% of a region of pixels you want to define.
2290%
2291% o map: This string reflects the expected ordering of the pixel array.
2292% It can be any combination or order of R = red, G = green, B = blue,
2293% A = alpha (0 is transparent), O = opacity (0 is opaque), C = cyan,
2294% Y = yellow, M = magenta, K = black, I = intensity (for grayscale),
2295% P = pad.
2296%
2297% o type: Define the data type of the pixels. Float and double types are
2298% normalized to [0..1] otherwise [0..QuantumRange]. Choose from these
cristy6c9e1682012-01-07 21:37:44 +00002299% types: CharPixel (char *), DoublePixel (double *), FloatPixel (float *),
cristyff6834e2012-01-10 03:00:25 +00002300% LongPixel (unsigned int *), LongLongPixel (unsigned long long *),
cristy6c9e1682012-01-07 21:37:44 +00002301% QuantumPixel (Quantum *), or ShortPixel (unsigned short *).
cristy4c08aed2011-07-01 19:47:50 +00002302%
2303% o pixels: This array of values contain the pixel components as defined by
2304% map and type. You must preallocate this array where the expected
2305% length varies depending on the values of width, height, map, and type.
2306%
cristy018f07f2011-09-04 21:15:19 +00002307% o exception: return any errors or warnings in this structure.
2308%
cristy4c08aed2011-07-01 19:47:50 +00002309*/
cristye5370942012-01-06 03:49:31 +00002310
cristycafe0412012-01-10 13:29:58 +00002311static void ImportCharPixel(Image *image,const RectangleInfo *roi,
cristy46f4be22012-01-07 00:26:39 +00002312 const char *restrict map,const QuantumType *quantum_map,const void *pixels,
2313 ExceptionInfo *exception)
cristye5370942012-01-06 03:49:31 +00002314{
2315 register const unsigned char
2316 *restrict p;
2317
2318 register Quantum
cristy3fe11452012-01-09 01:27:42 +00002319 *restrict q;
cristye5370942012-01-06 03:49:31 +00002320
2321 register ssize_t
2322 x;
2323
cristy14d71292012-05-20 16:48:13 +00002324 size_t
2325 length;
2326
cristye5370942012-01-06 03:49:31 +00002327 ssize_t
2328 y;
2329
2330 p=(const unsigned char *) pixels;
2331 if (LocaleCompare(map,"BGR") == 0)
2332 {
cristycafe0412012-01-10 13:29:58 +00002333 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00002334 {
cristycafe0412012-01-10 13:29:58 +00002335 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00002336 if (q == (Quantum *) NULL)
2337 break;
cristycafe0412012-01-10 13:29:58 +00002338 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00002339 {
2340 SetPixelBlue(image,ScaleCharToQuantum(*p++),q);
2341 SetPixelGreen(image,ScaleCharToQuantum(*p++),q);
2342 SetPixelRed(image,ScaleCharToQuantum(*p++),q);
2343 q+=GetPixelChannels(image);
2344 }
2345 if (SyncAuthenticPixels(image,exception) == MagickFalse)
2346 break;
2347 }
2348 return;
2349 }
2350 if (LocaleCompare(map,"BGRA") == 0)
2351 {
cristycafe0412012-01-10 13:29:58 +00002352 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00002353 {
cristycafe0412012-01-10 13:29:58 +00002354 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00002355 if (q == (Quantum *) NULL)
2356 break;
cristycafe0412012-01-10 13:29:58 +00002357 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00002358 {
2359 SetPixelBlue(image,ScaleCharToQuantum(*p++),q);
2360 SetPixelGreen(image,ScaleCharToQuantum(*p++),q);
2361 SetPixelRed(image,ScaleCharToQuantum(*p++),q);
2362 SetPixelAlpha(image,ScaleCharToQuantum(*p++),q);
2363 q+=GetPixelChannels(image);
2364 }
2365 if (SyncAuthenticPixels(image,exception) == MagickFalse)
2366 break;
2367 }
2368 return;
2369 }
2370 if (LocaleCompare(map,"BGRO") == 0)
2371 {
cristycafe0412012-01-10 13:29:58 +00002372 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00002373 {
cristycafe0412012-01-10 13:29:58 +00002374 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00002375 if (q == (Quantum *) NULL)
2376 break;
cristycafe0412012-01-10 13:29:58 +00002377 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00002378 {
2379 SetPixelBlue(image,ScaleCharToQuantum(*p++),q);
2380 SetPixelGreen(image,ScaleCharToQuantum(*p++),q);
2381 SetPixelRed(image,ScaleCharToQuantum(*p++),q);
2382 SetPixelAlpha(image,ScaleCharToQuantum(*p++),q);
2383 q+=GetPixelChannels(image);
2384 }
2385 if (SyncAuthenticPixels(image,exception) == MagickFalse)
2386 break;
2387 }
2388 return;
2389 }
2390 if (LocaleCompare(map,"BGRP") == 0)
2391 {
cristycafe0412012-01-10 13:29:58 +00002392 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00002393 {
cristycafe0412012-01-10 13:29:58 +00002394 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00002395 if (q == (Quantum *) NULL)
2396 break;
cristycafe0412012-01-10 13:29:58 +00002397 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00002398 {
2399 SetPixelBlue(image,ScaleCharToQuantum(*p++),q);
2400 SetPixelGreen(image,ScaleCharToQuantum(*p++),q);
2401 SetPixelRed(image,ScaleCharToQuantum(*p++),q);
2402 p++;
2403 q+=GetPixelChannels(image);
2404 }
2405 if (SyncAuthenticPixels(image,exception) == MagickFalse)
2406 break;
2407 }
2408 return;
2409 }
2410 if (LocaleCompare(map,"I") == 0)
2411 {
cristycafe0412012-01-10 13:29:58 +00002412 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00002413 {
cristycafe0412012-01-10 13:29:58 +00002414 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00002415 if (q == (Quantum *) NULL)
2416 break;
cristycafe0412012-01-10 13:29:58 +00002417 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00002418 {
2419 SetPixelGray(image,ScaleCharToQuantum(*p++),q);
2420 q+=GetPixelChannels(image);
2421 }
2422 if (SyncAuthenticPixels(image,exception) == MagickFalse)
2423 break;
2424 }
2425 return;
2426 }
2427 if (LocaleCompare(map,"RGB") == 0)
2428 {
cristycafe0412012-01-10 13:29:58 +00002429 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00002430 {
cristycafe0412012-01-10 13:29:58 +00002431 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00002432 if (q == (Quantum *) NULL)
2433 break;
cristycafe0412012-01-10 13:29:58 +00002434 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00002435 {
2436 SetPixelRed(image,ScaleCharToQuantum(*p++),q);
2437 SetPixelGreen(image,ScaleCharToQuantum(*p++),q);
2438 SetPixelBlue(image,ScaleCharToQuantum(*p++),q);
2439 q+=GetPixelChannels(image);
2440 }
2441 if (SyncAuthenticPixels(image,exception) == MagickFalse)
2442 break;
2443 }
2444 return;
2445 }
2446 if (LocaleCompare(map,"RGBA") == 0)
2447 {
cristycafe0412012-01-10 13:29:58 +00002448 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00002449 {
cristycafe0412012-01-10 13:29:58 +00002450 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00002451 if (q == (Quantum *) NULL)
2452 break;
cristycafe0412012-01-10 13:29:58 +00002453 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00002454 {
2455 SetPixelRed(image,ScaleCharToQuantum(*p++),q);
2456 SetPixelGreen(image,ScaleCharToQuantum(*p++),q);
2457 SetPixelBlue(image,ScaleCharToQuantum(*p++),q);
2458 SetPixelAlpha(image,ScaleCharToQuantum(*p++),q);
2459 q+=GetPixelChannels(image);
2460 }
2461 if (SyncAuthenticPixels(image,exception) == MagickFalse)
2462 break;
2463 }
2464 return;
2465 }
2466 if (LocaleCompare(map,"RGBO") == 0)
2467 {
cristycafe0412012-01-10 13:29:58 +00002468 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00002469 {
cristycafe0412012-01-10 13:29:58 +00002470 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00002471 if (q == (Quantum *) NULL)
2472 break;
cristycafe0412012-01-10 13:29:58 +00002473 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00002474 {
2475 SetPixelRed(image,ScaleCharToQuantum(*p++),q);
2476 SetPixelGreen(image,ScaleCharToQuantum(*p++),q);
2477 SetPixelBlue(image,ScaleCharToQuantum(*p++),q);
2478 SetPixelAlpha(image,ScaleCharToQuantum(*p++),q);
2479 q+=GetPixelChannels(image);
2480 }
2481 if (SyncAuthenticPixels(image,exception) == MagickFalse)
2482 break;
2483 }
2484 return;
2485 }
2486 if (LocaleCompare(map,"RGBP") == 0)
2487 {
cristycafe0412012-01-10 13:29:58 +00002488 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00002489 {
cristycafe0412012-01-10 13:29:58 +00002490 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00002491 if (q == (Quantum *) NULL)
2492 break;
cristycafe0412012-01-10 13:29:58 +00002493 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00002494 {
2495 SetPixelRed(image,ScaleCharToQuantum(*p++),q);
2496 SetPixelGreen(image,ScaleCharToQuantum(*p++),q);
2497 SetPixelBlue(image,ScaleCharToQuantum(*p++),q);
2498 p++;
2499 q+=GetPixelChannels(image);
2500 }
2501 if (SyncAuthenticPixels(image,exception) == MagickFalse)
2502 break;
2503 }
2504 return;
2505 }
cristy14d71292012-05-20 16:48:13 +00002506 length=strlen(map);
cristycafe0412012-01-10 13:29:58 +00002507 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00002508 {
cristycafe0412012-01-10 13:29:58 +00002509 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00002510 if (q == (Quantum *) NULL)
2511 break;
cristycafe0412012-01-10 13:29:58 +00002512 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00002513 {
2514 register ssize_t
2515 i;
2516
cristy14d71292012-05-20 16:48:13 +00002517 for (i=0; i < (ssize_t) length; i++)
cristye5370942012-01-06 03:49:31 +00002518 {
2519 switch (quantum_map[i])
2520 {
2521 case RedQuantum:
2522 case CyanQuantum:
2523 {
2524 SetPixelRed(image,ScaleCharToQuantum(*p),q);
2525 break;
2526 }
2527 case GreenQuantum:
2528 case MagentaQuantum:
2529 {
2530 SetPixelGreen(image,ScaleCharToQuantum(*p),q);
2531 break;
2532 }
2533 case BlueQuantum:
2534 case YellowQuantum:
2535 {
2536 SetPixelBlue(image,ScaleCharToQuantum(*p),q);
2537 break;
2538 }
2539 case AlphaQuantum:
2540 {
2541 SetPixelAlpha(image,ScaleCharToQuantum(*p),q);
2542 break;
2543 }
2544 case OpacityQuantum:
2545 {
2546 SetPixelAlpha(image,ScaleCharToQuantum(*p),q);
2547 break;
2548 }
2549 case BlackQuantum:
2550 {
2551 SetPixelBlack(image,ScaleCharToQuantum(*p),q);
2552 break;
2553 }
2554 case IndexQuantum:
2555 {
2556 SetPixelGray(image,ScaleCharToQuantum(*p),q);
2557 break;
2558 }
2559 default:
2560 break;
2561 }
2562 p++;
2563 }
2564 q+=GetPixelChannels(image);
2565 }
2566 if (SyncAuthenticPixels(image,exception) == MagickFalse)
2567 break;
2568 }
2569}
2570
cristycafe0412012-01-10 13:29:58 +00002571static void ImportDoublePixel(Image *image,const RectangleInfo *roi,
cristy46f4be22012-01-07 00:26:39 +00002572 const char *restrict map,const QuantumType *quantum_map,const void *pixels,
2573 ExceptionInfo *exception)
cristye5370942012-01-06 03:49:31 +00002574{
2575 register const double
2576 *restrict p;
2577
2578 register Quantum
cristy3fe11452012-01-09 01:27:42 +00002579 *restrict q;
cristye5370942012-01-06 03:49:31 +00002580
2581 register ssize_t
2582 x;
2583
cristy14d71292012-05-20 16:48:13 +00002584 size_t
2585 length;
2586
cristye5370942012-01-06 03:49:31 +00002587 ssize_t
2588 y;
2589
2590 p=(const double *) pixels;
2591 if (LocaleCompare(map,"BGR") == 0)
2592 {
cristycafe0412012-01-10 13:29:58 +00002593 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00002594 {
cristycafe0412012-01-10 13:29:58 +00002595 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00002596 if (q == (Quantum *) NULL)
2597 break;
cristycafe0412012-01-10 13:29:58 +00002598 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00002599 {
cristy8cd03c32012-07-07 18:57:59 +00002600 SetPixelBlue(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002601 p++;
cristy8cd03c32012-07-07 18:57:59 +00002602 SetPixelGreen(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002603 p++;
cristy8cd03c32012-07-07 18:57:59 +00002604 SetPixelRed(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002605 p++;
2606 q+=GetPixelChannels(image);
2607 }
2608 if (SyncAuthenticPixels(image,exception) == MagickFalse)
2609 break;
2610 }
2611 return;
2612 }
2613 if (LocaleCompare(map,"BGRA") == 0)
2614 {
cristycafe0412012-01-10 13:29:58 +00002615 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00002616 {
cristycafe0412012-01-10 13:29:58 +00002617 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00002618 if (q == (Quantum *) NULL)
2619 break;
cristycafe0412012-01-10 13:29:58 +00002620 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00002621 {
cristy8cd03c32012-07-07 18:57:59 +00002622 SetPixelBlue(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002623 p++;
cristy8cd03c32012-07-07 18:57:59 +00002624 SetPixelGreen(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002625 p++;
cristy8cd03c32012-07-07 18:57:59 +00002626 SetPixelRed(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002627 p++;
cristy8cd03c32012-07-07 18:57:59 +00002628 SetPixelAlpha(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002629 p++;
2630 q+=GetPixelChannels(image);
2631 }
2632 if (SyncAuthenticPixels(image,exception) == MagickFalse)
2633 break;
2634 }
2635 return;
2636 }
2637 if (LocaleCompare(map,"BGRP") == 0)
2638 {
cristycafe0412012-01-10 13:29:58 +00002639 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00002640 {
cristycafe0412012-01-10 13:29:58 +00002641 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00002642 if (q == (Quantum *) NULL)
2643 break;
cristycafe0412012-01-10 13:29:58 +00002644 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00002645 {
cristy8cd03c32012-07-07 18:57:59 +00002646 SetPixelBlue(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002647 p++;
cristy8cd03c32012-07-07 18:57:59 +00002648 SetPixelGreen(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002649 p++;
cristy8cd03c32012-07-07 18:57:59 +00002650 SetPixelRed(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002651 p++;
2652 p++;
2653 q+=GetPixelChannels(image);
2654 }
2655 if (SyncAuthenticPixels(image,exception) == MagickFalse)
2656 break;
2657 }
2658 return;
2659 }
2660 if (LocaleCompare(map,"I") == 0)
2661 {
cristycafe0412012-01-10 13:29:58 +00002662 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00002663 {
cristycafe0412012-01-10 13:29:58 +00002664 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00002665 if (q == (Quantum *) NULL)
2666 break;
cristycafe0412012-01-10 13:29:58 +00002667 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00002668 {
cristy8cd03c32012-07-07 18:57:59 +00002669 SetPixelGray(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002670 p++;
2671 q+=GetPixelChannels(image);
2672 }
2673 if (SyncAuthenticPixels(image,exception) == MagickFalse)
2674 break;
2675 }
2676 return;
2677 }
2678 if (LocaleCompare(map,"RGB") == 0)
2679 {
cristycafe0412012-01-10 13:29:58 +00002680 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00002681 {
cristycafe0412012-01-10 13:29:58 +00002682 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00002683 if (q == (Quantum *) NULL)
2684 break;
cristycafe0412012-01-10 13:29:58 +00002685 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00002686 {
cristy8cd03c32012-07-07 18:57:59 +00002687 SetPixelRed(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002688 p++;
cristy8cd03c32012-07-07 18:57:59 +00002689 SetPixelGreen(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002690 p++;
cristy8cd03c32012-07-07 18:57:59 +00002691 SetPixelBlue(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002692 p++;
2693 q+=GetPixelChannels(image);
2694 }
2695 if (SyncAuthenticPixels(image,exception) == MagickFalse)
2696 break;
2697 }
2698 return;
2699 }
2700 if (LocaleCompare(map,"RGBA") == 0)
2701 {
cristycafe0412012-01-10 13:29:58 +00002702 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00002703 {
cristycafe0412012-01-10 13:29:58 +00002704 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00002705 if (q == (Quantum *) NULL)
2706 break;
cristycafe0412012-01-10 13:29:58 +00002707 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00002708 {
cristy8cd03c32012-07-07 18:57:59 +00002709 SetPixelRed(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002710 p++;
cristy8cd03c32012-07-07 18:57:59 +00002711 SetPixelGreen(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002712 p++;
cristy8cd03c32012-07-07 18:57:59 +00002713 SetPixelBlue(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002714 p++;
cristy8cd03c32012-07-07 18:57:59 +00002715 SetPixelAlpha(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002716 p++;
2717 q+=GetPixelChannels(image);
2718 }
2719 if (SyncAuthenticPixels(image,exception) == MagickFalse)
2720 break;
2721 }
2722 return;
2723 }
2724 if (LocaleCompare(map,"RGBP") == 0)
2725 {
cristycafe0412012-01-10 13:29:58 +00002726 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00002727 {
cristycafe0412012-01-10 13:29:58 +00002728 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00002729 if (q == (Quantum *) NULL)
2730 break;
cristycafe0412012-01-10 13:29:58 +00002731 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00002732 {
cristy8cd03c32012-07-07 18:57:59 +00002733 SetPixelRed(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002734 p++;
cristy8cd03c32012-07-07 18:57:59 +00002735 SetPixelGreen(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002736 p++;
cristy8cd03c32012-07-07 18:57:59 +00002737 SetPixelBlue(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002738 p++;
2739 q+=GetPixelChannels(image);
2740 }
2741 if (SyncAuthenticPixels(image,exception) == MagickFalse)
2742 break;
2743 }
2744 return;
2745 }
cristy14d71292012-05-20 16:48:13 +00002746 length=strlen(map);
cristycafe0412012-01-10 13:29:58 +00002747 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00002748 {
cristycafe0412012-01-10 13:29:58 +00002749 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00002750 if (q == (Quantum *) NULL)
2751 break;
cristycafe0412012-01-10 13:29:58 +00002752 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00002753 {
2754 register ssize_t
2755 i;
2756
cristy14d71292012-05-20 16:48:13 +00002757 for (i=0; i < (ssize_t) length; i++)
cristye5370942012-01-06 03:49:31 +00002758 {
2759 switch (quantum_map[i])
2760 {
2761 case RedQuantum:
2762 case CyanQuantum:
2763 {
cristy8cd03c32012-07-07 18:57:59 +00002764 SetPixelRed(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002765 break;
2766 }
2767 case GreenQuantum:
2768 case MagentaQuantum:
2769 {
cristy8cd03c32012-07-07 18:57:59 +00002770 SetPixelGreen(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002771 break;
2772 }
2773 case BlueQuantum:
2774 case YellowQuantum:
2775 {
cristy8cd03c32012-07-07 18:57:59 +00002776 SetPixelBlue(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002777 break;
2778 }
2779 case AlphaQuantum:
2780 {
cristy8cd03c32012-07-07 18:57:59 +00002781 SetPixelAlpha(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002782 break;
2783 }
2784 case OpacityQuantum:
2785 {
cristy8cd03c32012-07-07 18:57:59 +00002786 SetPixelAlpha(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002787 break;
2788 }
2789 case BlackQuantum:
2790 {
cristy8cd03c32012-07-07 18:57:59 +00002791 SetPixelBlack(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002792 break;
2793 }
2794 case IndexQuantum:
2795 {
cristy8cd03c32012-07-07 18:57:59 +00002796 SetPixelGray(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002797 break;
2798 }
2799 default:
2800 break;
2801 }
2802 p++;
2803 }
2804 q+=GetPixelChannels(image);
2805 }
2806 if (SyncAuthenticPixels(image,exception) == MagickFalse)
2807 break;
2808 }
2809}
2810
cristycafe0412012-01-10 13:29:58 +00002811static void ImportFloatPixel(Image *image,const RectangleInfo *roi,
cristy46f4be22012-01-07 00:26:39 +00002812 const char *restrict map,const QuantumType *quantum_map,const void *pixels,
2813 ExceptionInfo *exception)
cristye5370942012-01-06 03:49:31 +00002814{
2815 register const float
2816 *restrict p;
2817
2818 register Quantum
cristy3fe11452012-01-09 01:27:42 +00002819 *restrict q;
cristye5370942012-01-06 03:49:31 +00002820
2821 register ssize_t
2822 x;
2823
cristy14d71292012-05-20 16:48:13 +00002824 size_t
2825 length;
2826
cristye5370942012-01-06 03:49:31 +00002827 ssize_t
2828 y;
2829
2830 p=(const float *) pixels;
2831 if (LocaleCompare(map,"BGR") == 0)
2832 {
cristycafe0412012-01-10 13:29:58 +00002833 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00002834 {
cristycafe0412012-01-10 13:29:58 +00002835 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00002836 if (q == (Quantum *) NULL)
2837 break;
cristycafe0412012-01-10 13:29:58 +00002838 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00002839 {
cristy8cd03c32012-07-07 18:57:59 +00002840 SetPixelBlue(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002841 p++;
cristy8cd03c32012-07-07 18:57:59 +00002842 SetPixelGreen(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002843 p++;
cristy8cd03c32012-07-07 18:57:59 +00002844 SetPixelRed(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002845 p++;
2846 q+=GetPixelChannels(image);
2847 }
2848 if (SyncAuthenticPixels(image,exception) == MagickFalse)
2849 break;
2850 }
2851 return;
2852 }
2853 if (LocaleCompare(map,"BGRA") == 0)
2854 {
cristycafe0412012-01-10 13:29:58 +00002855 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00002856 {
cristycafe0412012-01-10 13:29:58 +00002857 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00002858 if (q == (Quantum *) NULL)
2859 break;
cristycafe0412012-01-10 13:29:58 +00002860 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00002861 {
cristy8cd03c32012-07-07 18:57:59 +00002862 SetPixelBlue(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002863 p++;
cristy8cd03c32012-07-07 18:57:59 +00002864 SetPixelGreen(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002865 p++;
cristy8cd03c32012-07-07 18:57:59 +00002866 SetPixelRed(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002867 p++;
cristy8cd03c32012-07-07 18:57:59 +00002868 SetPixelAlpha(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002869 p++;
2870 q+=GetPixelChannels(image);
2871 }
2872 if (SyncAuthenticPixels(image,exception) == MagickFalse)
2873 break;
2874 }
2875 return;
2876 }
2877 if (LocaleCompare(map,"BGRP") == 0)
2878 {
cristycafe0412012-01-10 13:29:58 +00002879 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00002880 {
cristycafe0412012-01-10 13:29:58 +00002881 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00002882 if (q == (Quantum *) NULL)
2883 break;
cristycafe0412012-01-10 13:29:58 +00002884 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00002885 {
cristy8cd03c32012-07-07 18:57:59 +00002886 SetPixelBlue(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002887 p++;
cristy8cd03c32012-07-07 18:57:59 +00002888 SetPixelGreen(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002889 p++;
cristy8cd03c32012-07-07 18:57:59 +00002890 SetPixelRed(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002891 p++;
2892 p++;
2893 q+=GetPixelChannels(image);
2894 }
2895 if (SyncAuthenticPixels(image,exception) == MagickFalse)
2896 break;
2897 }
2898 return;
2899 }
2900 if (LocaleCompare(map,"I") == 0)
2901 {
cristycafe0412012-01-10 13:29:58 +00002902 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00002903 {
cristycafe0412012-01-10 13:29:58 +00002904 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00002905 if (q == (Quantum *) NULL)
2906 break;
cristycafe0412012-01-10 13:29:58 +00002907 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00002908 {
cristy8cd03c32012-07-07 18:57:59 +00002909 SetPixelGray(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002910 p++;
2911 q+=GetPixelChannels(image);
2912 }
2913 if (SyncAuthenticPixels(image,exception) == MagickFalse)
2914 break;
2915 }
2916 return;
2917 }
2918 if (LocaleCompare(map,"RGB") == 0)
2919 {
cristycafe0412012-01-10 13:29:58 +00002920 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00002921 {
cristycafe0412012-01-10 13:29:58 +00002922 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00002923 if (q == (Quantum *) NULL)
2924 break;
cristycafe0412012-01-10 13:29:58 +00002925 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00002926 {
cristy8cd03c32012-07-07 18:57:59 +00002927 SetPixelRed(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002928 p++;
cristy8cd03c32012-07-07 18:57:59 +00002929 SetPixelGreen(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002930 p++;
cristy8cd03c32012-07-07 18:57:59 +00002931 SetPixelBlue(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002932 p++;
2933 q+=GetPixelChannels(image);
2934 }
2935 if (SyncAuthenticPixels(image,exception) == MagickFalse)
2936 break;
2937 }
2938 return;
2939 }
2940 if (LocaleCompare(map,"RGBA") == 0)
2941 {
cristycafe0412012-01-10 13:29:58 +00002942 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00002943 {
cristycafe0412012-01-10 13:29:58 +00002944 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00002945 if (q == (Quantum *) NULL)
2946 break;
cristycafe0412012-01-10 13:29:58 +00002947 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00002948 {
cristy8cd03c32012-07-07 18:57:59 +00002949 SetPixelRed(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002950 p++;
cristy8cd03c32012-07-07 18:57:59 +00002951 SetPixelGreen(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002952 p++;
cristy8cd03c32012-07-07 18:57:59 +00002953 SetPixelBlue(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002954 p++;
cristy8cd03c32012-07-07 18:57:59 +00002955 SetPixelAlpha(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002956 p++;
2957 q+=GetPixelChannels(image);
2958 }
2959 if (SyncAuthenticPixels(image,exception) == MagickFalse)
2960 break;
2961 }
2962 return;
2963 }
2964 if (LocaleCompare(map,"RGBP") == 0)
2965 {
cristycafe0412012-01-10 13:29:58 +00002966 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00002967 {
cristycafe0412012-01-10 13:29:58 +00002968 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00002969 if (q == (Quantum *) NULL)
2970 break;
cristycafe0412012-01-10 13:29:58 +00002971 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00002972 {
cristy8cd03c32012-07-07 18:57:59 +00002973 SetPixelRed(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002974 p++;
cristy8cd03c32012-07-07 18:57:59 +00002975 SetPixelGreen(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002976 p++;
cristy8cd03c32012-07-07 18:57:59 +00002977 SetPixelBlue(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002978 p++;
2979 q+=GetPixelChannels(image);
2980 }
2981 if (SyncAuthenticPixels(image,exception) == MagickFalse)
2982 break;
2983 }
2984 return;
2985 }
cristy14d71292012-05-20 16:48:13 +00002986 length=strlen(map);
cristycafe0412012-01-10 13:29:58 +00002987 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00002988 {
cristycafe0412012-01-10 13:29:58 +00002989 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00002990 if (q == (Quantum *) NULL)
2991 break;
cristycafe0412012-01-10 13:29:58 +00002992 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00002993 {
2994 register ssize_t
2995 i;
2996
cristy14d71292012-05-20 16:48:13 +00002997 for (i=0; i < (ssize_t) length; i++)
cristye5370942012-01-06 03:49:31 +00002998 {
2999 switch (quantum_map[i])
3000 {
3001 case RedQuantum:
3002 case CyanQuantum:
3003 {
cristy8cd03c32012-07-07 18:57:59 +00003004 SetPixelRed(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00003005 break;
3006 }
3007 case GreenQuantum:
3008 case MagentaQuantum:
3009 {
cristy8cd03c32012-07-07 18:57:59 +00003010 SetPixelGreen(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00003011 break;
3012 }
3013 case BlueQuantum:
3014 case YellowQuantum:
3015 {
cristy8cd03c32012-07-07 18:57:59 +00003016 SetPixelBlue(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00003017 break;
3018 }
3019 case AlphaQuantum:
3020 {
cristy8cd03c32012-07-07 18:57:59 +00003021 SetPixelAlpha(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00003022 break;
3023 }
3024 case OpacityQuantum:
3025 {
cristy8cd03c32012-07-07 18:57:59 +00003026 SetPixelAlpha(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00003027 break;
3028 }
3029 case BlackQuantum:
3030 {
cristy8cd03c32012-07-07 18:57:59 +00003031 SetPixelBlack(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00003032 break;
3033 }
3034 case IndexQuantum:
3035 {
cristy8cd03c32012-07-07 18:57:59 +00003036 SetPixelGray(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00003037 break;
3038 }
3039 default:
3040 break;
3041 }
3042 p++;
3043 }
3044 q+=GetPixelChannels(image);
3045 }
3046 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3047 break;
3048 }
3049}
3050
cristycafe0412012-01-10 13:29:58 +00003051static void ImportLongPixel(Image *image,const RectangleInfo *roi,
cristy46f4be22012-01-07 00:26:39 +00003052 const char *restrict map,const QuantumType *quantum_map,const void *pixels,
3053 ExceptionInfo *exception)
cristye5370942012-01-06 03:49:31 +00003054{
3055 register const unsigned int
3056 *restrict p;
3057
3058 register Quantum
cristy3fe11452012-01-09 01:27:42 +00003059 *restrict q;
cristye5370942012-01-06 03:49:31 +00003060
3061 register ssize_t
3062 x;
3063
cristy14d71292012-05-20 16:48:13 +00003064 size_t
3065 length;
3066
cristye5370942012-01-06 03:49:31 +00003067 ssize_t
3068 y;
3069
3070 p=(const unsigned int *) pixels;
3071 if (LocaleCompare(map,"BGR") == 0)
3072 {
cristycafe0412012-01-10 13:29:58 +00003073 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00003074 {
cristycafe0412012-01-10 13:29:58 +00003075 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00003076 if (q == (Quantum *) NULL)
3077 break;
cristycafe0412012-01-10 13:29:58 +00003078 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00003079 {
3080 SetPixelBlue(image,ScaleLongToQuantum(*p++),q);
3081 SetPixelGreen(image,ScaleLongToQuantum(*p++),q);
3082 SetPixelRed(image,ScaleLongToQuantum(*p++),q);
3083 q+=GetPixelChannels(image);
3084 }
3085 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3086 break;
3087 }
3088 return;
3089 }
3090 if (LocaleCompare(map,"BGRA") == 0)
3091 {
cristycafe0412012-01-10 13:29:58 +00003092 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00003093 {
cristycafe0412012-01-10 13:29:58 +00003094 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00003095 if (q == (Quantum *) NULL)
3096 break;
cristycafe0412012-01-10 13:29:58 +00003097 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00003098 {
3099 SetPixelBlue(image,ScaleLongToQuantum(*p++),q);
3100 SetPixelGreen(image,ScaleLongToQuantum(*p++),q);
3101 SetPixelRed(image,ScaleLongToQuantum(*p++),q);
3102 SetPixelAlpha(image,ScaleLongToQuantum(*p++),q);
3103 q+=GetPixelChannels(image);
3104 }
3105 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3106 break;
3107 }
3108 return;
3109 }
3110 if (LocaleCompare(map,"BGRP") == 0)
3111 {
cristycafe0412012-01-10 13:29:58 +00003112 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00003113 {
cristycafe0412012-01-10 13:29:58 +00003114 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00003115 if (q == (Quantum *) NULL)
3116 break;
cristycafe0412012-01-10 13:29:58 +00003117 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00003118 {
3119 SetPixelBlue(image,ScaleLongToQuantum(*p++),q);
3120 SetPixelGreen(image,ScaleLongToQuantum(*p++),q);
3121 SetPixelRed(image,ScaleLongToQuantum(*p++),q);
3122 p++;
3123 q+=GetPixelChannels(image);
3124 }
3125 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3126 break;
3127 }
3128 return;
3129 }
3130 if (LocaleCompare(map,"I") == 0)
3131 {
cristycafe0412012-01-10 13:29:58 +00003132 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00003133 {
cristycafe0412012-01-10 13:29:58 +00003134 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00003135 if (q == (Quantum *) NULL)
3136 break;
cristycafe0412012-01-10 13:29:58 +00003137 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00003138 {
3139 SetPixelGray(image,ScaleLongToQuantum(*p++),q);
3140 q+=GetPixelChannels(image);
3141 }
3142 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3143 break;
3144 }
3145 return;
3146 }
3147 if (LocaleCompare(map,"RGB") == 0)
3148 {
cristycafe0412012-01-10 13:29:58 +00003149 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00003150 {
cristycafe0412012-01-10 13:29:58 +00003151 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00003152 if (q == (Quantum *) NULL)
3153 break;
cristycafe0412012-01-10 13:29:58 +00003154 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00003155 {
3156 SetPixelRed(image,ScaleLongToQuantum(*p++),q);
3157 SetPixelGreen(image,ScaleLongToQuantum(*p++),q);
3158 SetPixelBlue(image,ScaleLongToQuantum(*p++),q);
3159 q+=GetPixelChannels(image);
3160 }
3161 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3162 break;
3163 }
3164 return;
3165 }
3166 if (LocaleCompare(map,"RGBA") == 0)
3167 {
cristycafe0412012-01-10 13:29:58 +00003168 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00003169 {
cristycafe0412012-01-10 13:29:58 +00003170 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00003171 if (q == (Quantum *) NULL)
3172 break;
cristycafe0412012-01-10 13:29:58 +00003173 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00003174 {
3175 SetPixelRed(image,ScaleLongToQuantum(*p++),q);
3176 SetPixelGreen(image,ScaleLongToQuantum(*p++),q);
3177 SetPixelBlue(image,ScaleLongToQuantum(*p++),q);
3178 SetPixelAlpha(image,ScaleLongToQuantum(*p++),q);
3179 q+=GetPixelChannels(image);
3180 }
3181 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3182 break;
3183 }
3184 return;
3185 }
3186 if (LocaleCompare(map,"RGBP") == 0)
3187 {
cristycafe0412012-01-10 13:29:58 +00003188 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00003189 {
cristycafe0412012-01-10 13:29:58 +00003190 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00003191 if (q == (Quantum *) NULL)
3192 break;
cristycafe0412012-01-10 13:29:58 +00003193 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00003194 {
3195 SetPixelRed(image,ScaleLongToQuantum(*p++),q);
3196 SetPixelGreen(image,ScaleLongToQuantum(*p++),q);
3197 SetPixelBlue(image,ScaleLongToQuantum(*p++),q);
3198 p++;
3199 q+=GetPixelChannels(image);
3200 }
3201 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3202 break;
3203 }
3204 return;
3205 }
cristy14d71292012-05-20 16:48:13 +00003206 length=strlen(map);
cristycafe0412012-01-10 13:29:58 +00003207 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00003208 {
cristycafe0412012-01-10 13:29:58 +00003209 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00003210 if (q == (Quantum *) NULL)
3211 break;
cristycafe0412012-01-10 13:29:58 +00003212 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00003213 {
3214 register ssize_t
3215 i;
3216
cristy14d71292012-05-20 16:48:13 +00003217 for (i=0; i < (ssize_t) length; i++)
cristye5370942012-01-06 03:49:31 +00003218 {
3219 switch (quantum_map[i])
3220 {
3221 case RedQuantum:
3222 case CyanQuantum:
3223 {
3224 SetPixelRed(image,ScaleLongToQuantum(*p),q);
3225 break;
3226 }
3227 case GreenQuantum:
3228 case MagentaQuantum:
3229 {
3230 SetPixelGreen(image,ScaleLongToQuantum(*p),q);
3231 break;
3232 }
3233 case BlueQuantum:
3234 case YellowQuantum:
3235 {
3236 SetPixelBlue(image,ScaleLongToQuantum(*p),q);
3237 break;
3238 }
3239 case AlphaQuantum:
3240 {
3241 SetPixelAlpha(image,ScaleLongToQuantum(*p),q);
3242 break;
3243 }
3244 case OpacityQuantum:
3245 {
3246 SetPixelAlpha(image,ScaleLongToQuantum(*p),q);
3247 break;
3248 }
3249 case BlackQuantum:
3250 {
3251 SetPixelBlack(image,ScaleLongToQuantum(*p),q);
3252 break;
3253 }
3254 case IndexQuantum:
3255 {
3256 SetPixelGray(image,ScaleLongToQuantum(*p),q);
3257 break;
3258 }
3259 default:
3260 break;
3261 }
3262 p++;
3263 }
3264 q+=GetPixelChannels(image);
3265 }
3266 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3267 break;
3268 }
3269}
3270
cristycafe0412012-01-10 13:29:58 +00003271static void ImportLongLongPixel(Image *image,const RectangleInfo *roi,
cristy46f4be22012-01-07 00:26:39 +00003272 const char *restrict map,const QuantumType *quantum_map,const void *pixels,
3273 ExceptionInfo *exception)
cristye5370942012-01-06 03:49:31 +00003274{
cristyb13e12a2012-01-06 21:48:27 +00003275 register const MagickSizeType
cristye5370942012-01-06 03:49:31 +00003276 *restrict p;
3277
3278 register Quantum
cristy3fe11452012-01-09 01:27:42 +00003279 *restrict q;
cristye5370942012-01-06 03:49:31 +00003280
3281 register ssize_t
3282 x;
3283
cristy14d71292012-05-20 16:48:13 +00003284 size_t
3285 length;
3286
cristye5370942012-01-06 03:49:31 +00003287 ssize_t
3288 y;
3289
cristyb13e12a2012-01-06 21:48:27 +00003290 p=(const MagickSizeType *) pixels;
cristye5370942012-01-06 03:49:31 +00003291 if (LocaleCompare(map,"BGR") == 0)
3292 {
cristycafe0412012-01-10 13:29:58 +00003293 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00003294 {
cristycafe0412012-01-10 13:29:58 +00003295 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00003296 if (q == (Quantum *) NULL)
3297 break;
cristycafe0412012-01-10 13:29:58 +00003298 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00003299 {
cristyb13e12a2012-01-06 21:48:27 +00003300 SetPixelBlue(image,ScaleLongLongToQuantum(*p++),q);
3301 SetPixelGreen(image,ScaleLongLongToQuantum(*p++),q);
3302 SetPixelRed(image,ScaleLongLongToQuantum(*p++),q);
cristye5370942012-01-06 03:49:31 +00003303 q+=GetPixelChannels(image);
3304 }
3305 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3306 break;
3307 }
3308 return;
3309 }
3310 if (LocaleCompare(map,"BGRA") == 0)
3311 {
cristycafe0412012-01-10 13:29:58 +00003312 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00003313 {
cristycafe0412012-01-10 13:29:58 +00003314 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00003315 if (q == (Quantum *) NULL)
3316 break;
cristycafe0412012-01-10 13:29:58 +00003317 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00003318 {
cristyb13e12a2012-01-06 21:48:27 +00003319 SetPixelBlue(image,ScaleLongLongToQuantum(*p++),q);
3320 SetPixelGreen(image,ScaleLongLongToQuantum(*p++),q);
3321 SetPixelRed(image,ScaleLongLongToQuantum(*p++),q);
3322 SetPixelAlpha(image,ScaleLongLongToQuantum(*p++),q);
cristye5370942012-01-06 03:49:31 +00003323 q+=GetPixelChannels(image);
3324 }
3325 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3326 break;
3327 }
3328 return;
3329 }
3330 if (LocaleCompare(map,"BGRP") == 0)
3331 {
cristycafe0412012-01-10 13:29:58 +00003332 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00003333 {
cristycafe0412012-01-10 13:29:58 +00003334 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00003335 if (q == (Quantum *) NULL)
3336 break;
cristycafe0412012-01-10 13:29:58 +00003337 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00003338 {
cristyb13e12a2012-01-06 21:48:27 +00003339 SetPixelBlue(image,ScaleLongLongToQuantum(*p++),q);
3340 SetPixelGreen(image,ScaleLongLongToQuantum(*p++),q);
3341 SetPixelRed(image,ScaleLongLongToQuantum(*p++),q);
cristye5370942012-01-06 03:49:31 +00003342 p++;
3343 q+=GetPixelChannels(image);
3344 }
3345 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3346 break;
3347 }
3348 return;
3349 }
3350 if (LocaleCompare(map,"I") == 0)
3351 {
cristycafe0412012-01-10 13:29:58 +00003352 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00003353 {
cristycafe0412012-01-10 13:29:58 +00003354 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00003355 if (q == (Quantum *) NULL)
3356 break;
cristycafe0412012-01-10 13:29:58 +00003357 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00003358 {
cristyb13e12a2012-01-06 21:48:27 +00003359 SetPixelGray(image,ScaleLongLongToQuantum(*p++),q);
cristye5370942012-01-06 03:49:31 +00003360 q+=GetPixelChannels(image);
3361 }
3362 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3363 break;
3364 }
3365 return;
3366 }
3367 if (LocaleCompare(map,"RGB") == 0)
3368 {
cristycafe0412012-01-10 13:29:58 +00003369 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00003370 {
cristycafe0412012-01-10 13:29:58 +00003371 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00003372 if (q == (Quantum *) NULL)
3373 break;
cristycafe0412012-01-10 13:29:58 +00003374 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00003375 {
cristyb13e12a2012-01-06 21:48:27 +00003376 SetPixelRed(image,ScaleLongLongToQuantum(*p++),q);
3377 SetPixelGreen(image,ScaleLongLongToQuantum(*p++),q);
3378 SetPixelBlue(image,ScaleLongLongToQuantum(*p++),q);
cristye5370942012-01-06 03:49:31 +00003379 q+=GetPixelChannels(image);
3380 }
3381 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3382 break;
3383 }
3384 return;
3385 }
3386 if (LocaleCompare(map,"RGBA") == 0)
3387 {
cristycafe0412012-01-10 13:29:58 +00003388 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00003389 {
cristycafe0412012-01-10 13:29:58 +00003390 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00003391 if (q == (Quantum *) NULL)
3392 break;
cristycafe0412012-01-10 13:29:58 +00003393 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00003394 {
cristyb13e12a2012-01-06 21:48:27 +00003395 SetPixelRed(image,ScaleLongLongToQuantum(*p++),q);
3396 SetPixelGreen(image,ScaleLongLongToQuantum(*p++),q);
3397 SetPixelBlue(image,ScaleLongLongToQuantum(*p++),q);
3398 SetPixelAlpha(image,ScaleLongLongToQuantum(*p++),q);
cristye5370942012-01-06 03:49:31 +00003399 q+=GetPixelChannels(image);
3400 }
3401 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3402 break;
3403 }
3404 return;
3405 }
3406 if (LocaleCompare(map,"RGBP") == 0)
3407 {
cristycafe0412012-01-10 13:29:58 +00003408 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00003409 {
cristycafe0412012-01-10 13:29:58 +00003410 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00003411 if (q == (Quantum *) NULL)
3412 break;
cristycafe0412012-01-10 13:29:58 +00003413 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00003414 {
cristyb13e12a2012-01-06 21:48:27 +00003415 SetPixelRed(image,ScaleLongLongToQuantum(*p++),q);
3416 SetPixelGreen(image,ScaleLongLongToQuantum(*p++),q);
3417 SetPixelBlue(image,ScaleLongLongToQuantum(*p++),q);
cristye5370942012-01-06 03:49:31 +00003418 p++;
3419 q+=GetPixelChannels(image);
3420 }
3421 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3422 break;
3423 }
3424 return;
3425 }
cristy14d71292012-05-20 16:48:13 +00003426 length=strlen(map);
cristycafe0412012-01-10 13:29:58 +00003427 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00003428 {
cristycafe0412012-01-10 13:29:58 +00003429 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00003430 if (q == (Quantum *) NULL)
3431 break;
cristycafe0412012-01-10 13:29:58 +00003432 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00003433 {
3434 register ssize_t
3435 i;
3436
cristy14d71292012-05-20 16:48:13 +00003437 for (i=0; i < (ssize_t) length; i++)
cristye5370942012-01-06 03:49:31 +00003438 {
3439 switch (quantum_map[i])
3440 {
3441 case RedQuantum:
3442 case CyanQuantum:
3443 {
cristyb13e12a2012-01-06 21:48:27 +00003444 SetPixelRed(image,ScaleLongLongToQuantum(*p),q);
cristye5370942012-01-06 03:49:31 +00003445 break;
3446 }
3447 case GreenQuantum:
3448 case MagentaQuantum:
3449 {
cristyb13e12a2012-01-06 21:48:27 +00003450 SetPixelGreen(image,ScaleLongLongToQuantum(*p),q);
cristye5370942012-01-06 03:49:31 +00003451 break;
3452 }
3453 case BlueQuantum:
3454 case YellowQuantum:
3455 {
cristyb13e12a2012-01-06 21:48:27 +00003456 SetPixelBlue(image,ScaleLongLongToQuantum(*p),q);
cristye5370942012-01-06 03:49:31 +00003457 break;
3458 }
3459 case AlphaQuantum:
3460 {
cristyb13e12a2012-01-06 21:48:27 +00003461 SetPixelAlpha(image,ScaleLongLongToQuantum(*p),q);
cristye5370942012-01-06 03:49:31 +00003462 break;
3463 }
3464 case OpacityQuantum:
3465 {
cristyb13e12a2012-01-06 21:48:27 +00003466 SetPixelAlpha(image,ScaleLongLongToQuantum(*p),q);
cristye5370942012-01-06 03:49:31 +00003467 break;
3468 }
3469 case BlackQuantum:
3470 {
cristyb13e12a2012-01-06 21:48:27 +00003471 SetPixelBlack(image,ScaleLongLongToQuantum(*p),q);
cristye5370942012-01-06 03:49:31 +00003472 break;
3473 }
3474 case IndexQuantum:
3475 {
cristyb13e12a2012-01-06 21:48:27 +00003476 SetPixelGray(image,ScaleLongLongToQuantum(*p),q);
cristye5370942012-01-06 03:49:31 +00003477 break;
3478 }
3479 default:
3480 break;
3481 }
3482 p++;
3483 }
3484 q+=GetPixelChannels(image);
3485 }
3486 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3487 break;
3488 }
3489}
3490
cristycafe0412012-01-10 13:29:58 +00003491static void ImportQuantumPixel(Image *image,const RectangleInfo *roi,
cristy46f4be22012-01-07 00:26:39 +00003492 const char *restrict map,const QuantumType *quantum_map,const void *pixels,
3493 ExceptionInfo *exception)
cristye5370942012-01-06 03:49:31 +00003494{
3495 register const Quantum
3496 *restrict p;
3497
3498 register Quantum
cristy3fe11452012-01-09 01:27:42 +00003499 *restrict q;
cristye5370942012-01-06 03:49:31 +00003500
3501 register ssize_t
3502 x;
3503
cristy14d71292012-05-20 16:48:13 +00003504 size_t
3505 length;
3506
cristye5370942012-01-06 03:49:31 +00003507 ssize_t
3508 y;
3509
3510 p=(const Quantum *) pixels;
3511 if (LocaleCompare(map,"BGR") == 0)
3512 {
cristycafe0412012-01-10 13:29:58 +00003513 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00003514 {
cristycafe0412012-01-10 13:29:58 +00003515 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00003516 if (q == (Quantum *) NULL)
3517 break;
cristycafe0412012-01-10 13:29:58 +00003518 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00003519 {
3520 SetPixelBlue(image,*p++,q);
3521 SetPixelGreen(image,*p++,q);
3522 SetPixelRed(image,*p++,q);
3523 q+=GetPixelChannels(image);
3524 }
3525 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3526 break;
3527 }
3528 return;
3529 }
3530 if (LocaleCompare(map,"BGRA") == 0)
3531 {
cristycafe0412012-01-10 13:29:58 +00003532 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00003533 {
cristycafe0412012-01-10 13:29:58 +00003534 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00003535 if (q == (Quantum *) NULL)
3536 break;
cristycafe0412012-01-10 13:29:58 +00003537 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00003538 {
3539 SetPixelBlue(image,*p++,q);
3540 SetPixelGreen(image,*p++,q);
3541 SetPixelRed(image,*p++,q);
3542 SetPixelAlpha(image,*p++,q);
3543 q+=GetPixelChannels(image);
3544 }
3545 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3546 break;
3547 }
3548 return;
3549 }
3550 if (LocaleCompare(map,"BGRP") == 0)
3551 {
cristycafe0412012-01-10 13:29:58 +00003552 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00003553 {
cristycafe0412012-01-10 13:29:58 +00003554 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00003555 if (q == (Quantum *) NULL)
3556 break;
cristycafe0412012-01-10 13:29:58 +00003557 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00003558 {
3559 SetPixelBlue(image,*p++,q);
3560 SetPixelGreen(image,*p++,q);
3561 SetPixelRed(image,*p++,q);
3562 p++;
3563 q+=GetPixelChannels(image);
3564 }
3565 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3566 break;
3567 }
3568 return;
3569 }
3570 if (LocaleCompare(map,"I") == 0)
3571 {
cristycafe0412012-01-10 13:29:58 +00003572 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00003573 {
cristycafe0412012-01-10 13:29:58 +00003574 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00003575 if (q == (Quantum *) NULL)
3576 break;
cristycafe0412012-01-10 13:29:58 +00003577 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00003578 {
3579 SetPixelGray(image,*p++,q);
3580 q+=GetPixelChannels(image);
3581 }
3582 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3583 break;
3584 }
3585 return;
3586 }
3587 if (LocaleCompare(map,"RGB") == 0)
3588 {
cristycafe0412012-01-10 13:29:58 +00003589 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00003590 {
cristycafe0412012-01-10 13:29:58 +00003591 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00003592 if (q == (Quantum *) NULL)
3593 break;
cristycafe0412012-01-10 13:29:58 +00003594 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00003595 {
3596 SetPixelRed(image,*p++,q);
3597 SetPixelGreen(image,*p++,q);
3598 SetPixelBlue(image,*p++,q);
3599 q+=GetPixelChannels(image);
3600 }
3601 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3602 break;
3603 }
3604 return;
3605 }
3606 if (LocaleCompare(map,"RGBA") == 0)
3607 {
cristycafe0412012-01-10 13:29:58 +00003608 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00003609 {
cristycafe0412012-01-10 13:29:58 +00003610 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00003611 if (q == (Quantum *) NULL)
3612 break;
cristycafe0412012-01-10 13:29:58 +00003613 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00003614 {
3615 SetPixelRed(image,*p++,q);
3616 SetPixelGreen(image,*p++,q);
3617 SetPixelBlue(image,*p++,q);
3618 SetPixelAlpha(image,*p++,q);
3619 q+=GetPixelChannels(image);
3620 }
3621 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3622 break;
3623 }
3624 return;
3625 }
3626 if (LocaleCompare(map,"RGBP") == 0)
3627 {
cristycafe0412012-01-10 13:29:58 +00003628 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00003629 {
cristycafe0412012-01-10 13:29:58 +00003630 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00003631 if (q == (Quantum *) NULL)
3632 break;
cristycafe0412012-01-10 13:29:58 +00003633 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00003634 {
3635 SetPixelRed(image,*p++,q);
3636 SetPixelGreen(image,*p++,q);
3637 SetPixelBlue(image,*p++,q);
3638 p++;
3639 q+=GetPixelChannels(image);
3640 }
3641 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3642 break;
3643 }
3644 return;
3645 }
cristy14d71292012-05-20 16:48:13 +00003646 length=strlen(map);
cristycafe0412012-01-10 13:29:58 +00003647 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00003648 {
cristycafe0412012-01-10 13:29:58 +00003649 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00003650 if (q == (Quantum *) NULL)
3651 break;
cristycafe0412012-01-10 13:29:58 +00003652 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00003653 {
3654 register ssize_t
3655 i;
3656
cristy14d71292012-05-20 16:48:13 +00003657 for (i=0; i < (ssize_t) length; i++)
cristye5370942012-01-06 03:49:31 +00003658 {
3659 switch (quantum_map[i])
3660 {
3661 case RedQuantum:
3662 case CyanQuantum:
3663 {
3664 SetPixelRed(image,*p,q);
3665 break;
3666 }
3667 case GreenQuantum:
3668 case MagentaQuantum:
3669 {
3670 SetPixelGreen(image,*p,q);
3671 break;
3672 }
3673 case BlueQuantum:
3674 case YellowQuantum:
3675 {
3676 SetPixelBlue(image,*p,q);
3677 break;
3678 }
3679 case AlphaQuantum:
3680 {
3681 SetPixelAlpha(image,*p,q);
3682 break;
3683 }
3684 case OpacityQuantum:
3685 {
3686 SetPixelAlpha(image,*p,q);
3687 break;
3688 }
3689 case BlackQuantum:
3690 {
3691 SetPixelBlack(image,*p,q);
3692 break;
3693 }
3694 case IndexQuantum:
3695 {
3696 SetPixelGray(image,*p,q);
3697 break;
3698 }
3699 default:
3700 break;
3701 }
3702 p++;
3703 }
3704 q+=GetPixelChannels(image);
3705 }
3706 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3707 break;
3708 }
3709}
3710
cristycafe0412012-01-10 13:29:58 +00003711static void ImportShortPixel(Image *image,const RectangleInfo *roi,
cristy46f4be22012-01-07 00:26:39 +00003712 const char *restrict map,const QuantumType *quantum_map,const void *pixels,
3713 ExceptionInfo *exception)
cristye5370942012-01-06 03:49:31 +00003714{
3715 register const unsigned short
3716 *restrict p;
3717
3718 register Quantum
cristy3fe11452012-01-09 01:27:42 +00003719 *restrict q;
cristye5370942012-01-06 03:49:31 +00003720
3721 register ssize_t
3722 x;
3723
cristy14d71292012-05-20 16:48:13 +00003724 size_t
3725 length;
3726
cristye5370942012-01-06 03:49:31 +00003727 ssize_t
3728 y;
3729
3730 p=(const unsigned short *) pixels;
3731 if (LocaleCompare(map,"BGR") == 0)
3732 {
cristycafe0412012-01-10 13:29:58 +00003733 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00003734 {
cristycafe0412012-01-10 13:29:58 +00003735 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00003736 if (q == (Quantum *) NULL)
3737 break;
cristycafe0412012-01-10 13:29:58 +00003738 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00003739 {
3740 SetPixelBlue(image,ScaleShortToQuantum(*p++),q);
3741 SetPixelGreen(image,ScaleShortToQuantum(*p++),q);
3742 SetPixelRed(image,ScaleShortToQuantum(*p++),q);
3743 q+=GetPixelChannels(image);
3744 }
3745 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3746 break;
3747 }
3748 return;
3749 }
3750 if (LocaleCompare(map,"BGRA") == 0)
3751 {
cristycafe0412012-01-10 13:29:58 +00003752 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00003753 {
cristycafe0412012-01-10 13:29:58 +00003754 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00003755 if (q == (Quantum *) NULL)
3756 break;
cristycafe0412012-01-10 13:29:58 +00003757 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00003758 {
3759 SetPixelBlue(image,ScaleShortToQuantum(*p++),q);
3760 SetPixelGreen(image,ScaleShortToQuantum(*p++),q);
3761 SetPixelRed(image,ScaleShortToQuantum(*p++),q);
3762 SetPixelAlpha(image,ScaleShortToQuantum(*p++),q);
3763 q+=GetPixelChannels(image);
3764 }
3765 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3766 break;
3767 }
3768 return;
3769 }
3770 if (LocaleCompare(map,"BGRP") == 0)
3771 {
cristycafe0412012-01-10 13:29:58 +00003772 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00003773 {
cristycafe0412012-01-10 13:29:58 +00003774 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00003775 if (q == (Quantum *) NULL)
3776 break;
cristycafe0412012-01-10 13:29:58 +00003777 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00003778 {
3779 SetPixelBlue(image,ScaleShortToQuantum(*p++),q);
3780 SetPixelGreen(image,ScaleShortToQuantum(*p++),q);
3781 SetPixelRed(image,ScaleShortToQuantum(*p++),q);
3782 p++;
3783 q+=GetPixelChannels(image);
3784 }
3785 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3786 break;
3787 }
3788 return;
3789 }
3790 if (LocaleCompare(map,"I") == 0)
3791 {
cristycafe0412012-01-10 13:29:58 +00003792 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00003793 {
cristycafe0412012-01-10 13:29:58 +00003794 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00003795 if (q == (Quantum *) NULL)
3796 break;
cristycafe0412012-01-10 13:29:58 +00003797 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00003798 {
3799 SetPixelGray(image,ScaleShortToQuantum(*p++),q);
3800 q+=GetPixelChannels(image);
3801 }
3802 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3803 break;
3804 }
3805 return;
3806 }
3807 if (LocaleCompare(map,"RGB") == 0)
3808 {
cristycafe0412012-01-10 13:29:58 +00003809 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00003810 {
cristycafe0412012-01-10 13:29:58 +00003811 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00003812 if (q == (Quantum *) NULL)
3813 break;
cristycafe0412012-01-10 13:29:58 +00003814 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00003815 {
3816 SetPixelRed(image,ScaleShortToQuantum(*p++),q);
3817 SetPixelGreen(image,ScaleShortToQuantum(*p++),q);
3818 SetPixelBlue(image,ScaleShortToQuantum(*p++),q);
3819 q+=GetPixelChannels(image);
3820 }
3821 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3822 break;
3823 }
3824 return;
3825 }
3826 if (LocaleCompare(map,"RGBA") == 0)
3827 {
cristycafe0412012-01-10 13:29:58 +00003828 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00003829 {
cristycafe0412012-01-10 13:29:58 +00003830 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00003831 if (q == (Quantum *) NULL)
3832 break;
cristycafe0412012-01-10 13:29:58 +00003833 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00003834 {
3835 SetPixelRed(image,ScaleShortToQuantum(*p++),q);
3836 SetPixelGreen(image,ScaleShortToQuantum(*p++),q);
3837 SetPixelBlue(image,ScaleShortToQuantum(*p++),q);
3838 SetPixelAlpha(image,ScaleShortToQuantum(*p++),q);
3839 q+=GetPixelChannels(image);
3840 }
3841 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3842 break;
3843 }
3844 return;
3845 }
3846 if (LocaleCompare(map,"RGBP") == 0)
3847 {
cristycafe0412012-01-10 13:29:58 +00003848 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00003849 {
cristycafe0412012-01-10 13:29:58 +00003850 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00003851 if (q == (Quantum *) NULL)
3852 break;
cristycafe0412012-01-10 13:29:58 +00003853 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00003854 {
3855 SetPixelRed(image,ScaleShortToQuantum(*p++),q);
3856 SetPixelGreen(image,ScaleShortToQuantum(*p++),q);
3857 SetPixelBlue(image,ScaleShortToQuantum(*p++),q);
3858 p++;
3859 q+=GetPixelChannels(image);
3860 }
3861 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3862 break;
3863 }
3864 return;
3865 }
cristy14d71292012-05-20 16:48:13 +00003866 length=strlen(map);
cristycafe0412012-01-10 13:29:58 +00003867 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00003868 {
cristycafe0412012-01-10 13:29:58 +00003869 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00003870 if (q == (Quantum *) NULL)
3871 break;
cristycafe0412012-01-10 13:29:58 +00003872 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00003873 {
3874 register ssize_t
3875 i;
3876
cristy14d71292012-05-20 16:48:13 +00003877 for (i=0; i < (ssize_t) length; i++)
cristye5370942012-01-06 03:49:31 +00003878 {
3879 switch (quantum_map[i])
3880 {
3881 case RedQuantum:
3882 case CyanQuantum:
3883 {
3884 SetPixelRed(image,ScaleShortToQuantum(*p),q);
3885 break;
3886 }
3887 case GreenQuantum:
3888 case MagentaQuantum:
3889 {
3890 SetPixelGreen(image,ScaleShortToQuantum(*p),q);
3891 break;
3892 }
3893 case BlueQuantum:
3894 case YellowQuantum:
3895 {
3896 SetPixelBlue(image,ScaleShortToQuantum(*p),q);
3897 break;
3898 }
3899 case AlphaQuantum:
3900 {
3901 SetPixelAlpha(image,ScaleShortToQuantum(*p),q);
3902 break;
3903 }
3904 case OpacityQuantum:
3905 {
3906 SetPixelAlpha(image,ScaleShortToQuantum(*p),q);
3907 break;
3908 }
3909 case BlackQuantum:
3910 {
3911 SetPixelBlack(image,ScaleShortToQuantum(*p),q);
3912 break;
3913 }
3914 case IndexQuantum:
3915 {
3916 SetPixelGray(image,ScaleShortToQuantum(*p),q);
3917 break;
3918 }
3919 default:
3920 break;
3921 }
3922 p++;
3923 }
3924 q+=GetPixelChannels(image);
3925 }
3926 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3927 break;
3928 }
3929}
3930
cristycafe0412012-01-10 13:29:58 +00003931MagickExport MagickBooleanType ImportImagePixels(Image *image,const ssize_t x,
3932 const ssize_t y,const size_t width,const size_t height,const char *map,
3933 const StorageType type,const void *pixels,ExceptionInfo *exception)
cristy4c08aed2011-07-01 19:47:50 +00003934{
cristy4c08aed2011-07-01 19:47:50 +00003935 QuantumType
3936 *quantum_map;
3937
cristycafe0412012-01-10 13:29:58 +00003938 RectangleInfo
3939 roi;
3940
cristy4c08aed2011-07-01 19:47:50 +00003941 register ssize_t
cristye5370942012-01-06 03:49:31 +00003942 i;
cristy4c08aed2011-07-01 19:47:50 +00003943
cristy14d71292012-05-20 16:48:13 +00003944 size_t
3945 length;
3946
cristy4c08aed2011-07-01 19:47:50 +00003947 /*
3948 Allocate image structure.
3949 */
3950 assert(image != (Image *) NULL);
3951 assert(image->signature == MagickSignature);
3952 if (image->debug != MagickFalse)
3953 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
cristy14d71292012-05-20 16:48:13 +00003954 length=strlen(map);
3955 quantum_map=(QuantumType *) AcquireQuantumMemory(length,sizeof(*quantum_map));
cristy4c08aed2011-07-01 19:47:50 +00003956 if (quantum_map == (QuantumType *) NULL)
3957 ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
3958 image->filename);
cristy14d71292012-05-20 16:48:13 +00003959 for (i=0; i < (ssize_t) length; i++)
cristy4c08aed2011-07-01 19:47:50 +00003960 {
3961 switch (map[i])
3962 {
3963 case 'a':
3964 case 'A':
3965 {
3966 quantum_map[i]=AlphaQuantum;
cristy8a46d822012-08-28 23:32:39 +00003967 image->alpha_trait=BlendPixelTrait;
cristy4c08aed2011-07-01 19:47:50 +00003968 break;
3969 }
3970 case 'B':
3971 case 'b':
3972 {
3973 quantum_map[i]=BlueQuantum;
3974 break;
3975 }
3976 case 'C':
3977 case 'c':
3978 {
3979 quantum_map[i]=CyanQuantum;
cristy63240882011-08-05 19:05:27 +00003980 (void) SetImageColorspace(image,CMYKColorspace,exception);
cristy4c08aed2011-07-01 19:47:50 +00003981 break;
3982 }
3983 case 'g':
3984 case 'G':
3985 {
3986 quantum_map[i]=GreenQuantum;
3987 break;
3988 }
3989 case 'K':
3990 case 'k':
3991 {
3992 quantum_map[i]=BlackQuantum;
cristy63240882011-08-05 19:05:27 +00003993 (void) SetImageColorspace(image,CMYKColorspace,exception);
cristy4c08aed2011-07-01 19:47:50 +00003994 break;
3995 }
3996 case 'I':
3997 case 'i':
3998 {
3999 quantum_map[i]=IndexQuantum;
cristyb7b3da62012-07-05 15:43:37 +00004000 (void) SetImageColorspace(image,GRAYColorspace,exception);
cristy4c08aed2011-07-01 19:47:50 +00004001 break;
4002 }
4003 case 'm':
4004 case 'M':
4005 {
4006 quantum_map[i]=MagentaQuantum;
cristy63240882011-08-05 19:05:27 +00004007 (void) SetImageColorspace(image,CMYKColorspace,exception);
cristy4c08aed2011-07-01 19:47:50 +00004008 break;
4009 }
4010 case 'O':
4011 case 'o':
4012 {
4013 quantum_map[i]=OpacityQuantum;
cristy8a46d822012-08-28 23:32:39 +00004014 image->alpha_trait=BlendPixelTrait;
cristy4c08aed2011-07-01 19:47:50 +00004015 break;
4016 }
4017 case 'P':
4018 case 'p':
4019 {
4020 quantum_map[i]=UndefinedQuantum;
4021 break;
4022 }
4023 case 'R':
4024 case 'r':
4025 {
4026 quantum_map[i]=RedQuantum;
4027 break;
4028 }
4029 case 'Y':
4030 case 'y':
4031 {
4032 quantum_map[i]=YellowQuantum;
cristy63240882011-08-05 19:05:27 +00004033 (void) SetImageColorspace(image,CMYKColorspace,exception);
cristy4c08aed2011-07-01 19:47:50 +00004034 break;
4035 }
4036 default:
4037 {
4038 quantum_map=(QuantumType *) RelinquishMagickMemory(quantum_map);
cristy63240882011-08-05 19:05:27 +00004039 (void) ThrowMagickException(exception,GetMagickModule(),OptionError,
cristyefe601c2013-01-05 17:51:12 +00004040 "UnrecognizedPixelMap","`%s'",map);
cristy4c08aed2011-07-01 19:47:50 +00004041 return(MagickFalse);
4042 }
4043 }
4044 }
cristy63240882011-08-05 19:05:27 +00004045 if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
cristy4c08aed2011-07-01 19:47:50 +00004046 return(MagickFalse);
4047 /*
cristye5370942012-01-06 03:49:31 +00004048 Transfer the pixels from the pixel data to the image.
cristy4c08aed2011-07-01 19:47:50 +00004049 */
cristycafe0412012-01-10 13:29:58 +00004050 roi.width=width;
4051 roi.height=height;
4052 roi.x=x;
4053 roi.y=y;
cristy4c08aed2011-07-01 19:47:50 +00004054 switch (type)
4055 {
4056 case CharPixel:
4057 {
cristycafe0412012-01-10 13:29:58 +00004058 ImportCharPixel(image,&roi,map,quantum_map,pixels,exception);
cristy4c08aed2011-07-01 19:47:50 +00004059 break;
4060 }
4061 case DoublePixel:
4062 {
cristycafe0412012-01-10 13:29:58 +00004063 ImportDoublePixel(image,&roi,map,quantum_map,pixels,exception);
cristy4c08aed2011-07-01 19:47:50 +00004064 break;
4065 }
4066 case FloatPixel:
4067 {
cristycafe0412012-01-10 13:29:58 +00004068 ImportFloatPixel(image,&roi,map,quantum_map,pixels,exception);
cristy4c08aed2011-07-01 19:47:50 +00004069 break;
4070 }
cristy4c08aed2011-07-01 19:47:50 +00004071 case LongPixel:
4072 {
cristycafe0412012-01-10 13:29:58 +00004073 ImportLongPixel(image,&roi,map,quantum_map,pixels,exception);
cristy4c08aed2011-07-01 19:47:50 +00004074 break;
4075 }
cristy6c9e1682012-01-07 21:37:44 +00004076 case LongLongPixel:
4077 {
cristycafe0412012-01-10 13:29:58 +00004078 ImportLongLongPixel(image,&roi,map,quantum_map,pixels,exception);
cristy6c9e1682012-01-07 21:37:44 +00004079 break;
4080 }
cristy4c08aed2011-07-01 19:47:50 +00004081 case QuantumPixel:
4082 {
cristycafe0412012-01-10 13:29:58 +00004083 ImportQuantumPixel(image,&roi,map,quantum_map,pixels,exception);
cristy4c08aed2011-07-01 19:47:50 +00004084 break;
4085 }
4086 case ShortPixel:
4087 {
cristycafe0412012-01-10 13:29:58 +00004088 ImportShortPixel(image,&roi,map,quantum_map,pixels,exception);
cristy4c08aed2011-07-01 19:47:50 +00004089 break;
4090 }
4091 default:
4092 {
4093 quantum_map=(QuantumType *) RelinquishMagickMemory(quantum_map);
cristyc82a27b2011-10-21 01:07:16 +00004094 (void) ThrowMagickException(exception,GetMagickModule(),OptionError,
cristyefe601c2013-01-05 17:51:12 +00004095 "UnrecognizedPixelMap","`%s'",map);
cristy4c08aed2011-07-01 19:47:50 +00004096 break;
4097 }
4098 }
4099 quantum_map=(QuantumType *) RelinquishMagickMemory(quantum_map);
4100 return(MagickTrue);
4101}
4102
4103/*
4104%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4105% %
4106% %
4107% %
cristybd5a96c2011-08-21 00:04:26 +00004108+ 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 %
4109% %
4110% %
4111% %
4112%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4113%
4114% InitializePixelChannelMap() defines the standard pixel component map.
4115%
4116% The format of the InitializePixelChannelMap() method is:
4117%
4118% void InitializePixelChannelMap(Image *image)
4119%
4120% A description of each parameter follows:
4121%
4122% o image: the image.
4123%
4124*/
cristy021216a2013-05-20 16:25:51 +00004125
4126static void LogPixelChannels(const Image *image)
4127{
4128 register ssize_t
4129 i;
4130
4131 (void) LogMagickEvent(PixelEvent,GetMagickModule(),"%s[%.20g]",
4132 image->filename,(double) image->number_channels);
4133 for (i=0; i < (ssize_t) image->number_channels; i++)
4134 {
4135 char
4136 traits[MaxTextExtent];
4137
4138 const char
4139 *name;
4140
4141 PixelChannel
4142 channel;
4143
4144 switch (GetPixelChannelChannel(image,i))
4145 {
4146 case RedPixelChannel:
4147 {
4148 name="red";
4149 if (image->colorspace == CMYKColorspace)
4150 name="cyan";
4151 if (image->colorspace == GRAYColorspace)
4152 name="gray";
4153 break;
4154 }
4155 case GreenPixelChannel:
4156 {
4157 name="green";
4158 if (image->colorspace == CMYKColorspace)
4159 name="magenta";
4160 break;
4161 }
4162 case BluePixelChannel:
4163 {
4164 name="blue";
4165 if (image->colorspace == CMYKColorspace)
4166 name="yellow";
4167 break;
4168 }
4169 case BlackPixelChannel:
4170 {
4171 name="black";
4172 if (image->storage_class == PseudoClass)
4173 name="index";
4174 break;
4175 }
4176 case IndexPixelChannel:
4177 {
4178 name="index";
4179 break;
4180 }
4181 case AlphaPixelChannel:
4182 {
4183 name="alpha";
4184 break;
4185 }
4186 case ReadMaskPixelChannel:
4187 {
cristy04817142013-05-20 17:14:03 +00004188 name="read-mask";
cristy021216a2013-05-20 16:25:51 +00004189 break;
4190 }
4191 case WriteMaskPixelChannel:
4192 {
cristy04817142013-05-20 17:14:03 +00004193 name="write-mask";
cristy021216a2013-05-20 16:25:51 +00004194 break;
4195 }
4196 case MetaPixelChannel:
4197 {
4198 name="meta";
4199 break;
4200 }
4201 default:
4202 name="undefined";
4203 }
4204 channel=GetPixelChannelChannel(image,i);
4205 *traits='\0';
4206 if ((GetPixelChannelTraits(image,channel) & UpdatePixelTrait) != 0)
4207 (void) ConcatenateMagickString(traits,"update,",MaxTextExtent);
4208 if ((GetPixelChannelTraits(image,channel) & BlendPixelTrait) != 0)
4209 (void) ConcatenateMagickString(traits,"blend,",MaxTextExtent);
4210 if ((GetPixelChannelTraits(image,channel) & CopyPixelTrait) != 0)
4211 (void) ConcatenateMagickString(traits,"copy,",MaxTextExtent);
4212 if (*traits == '\0')
4213 (void) ConcatenateMagickString(traits,"undefined,",MaxTextExtent);
4214 traits[strlen(traits)-1]='\0';
4215 (void) LogMagickEvent(PixelEvent,GetMagickModule()," %.20g: %s (%s)",
4216 (double) i,name,traits);
4217 }
4218}
4219
cristye2a912b2011-12-05 20:02:07 +00004220MagickExport void InitializePixelChannelMap(Image *image)
cristy77c30f52011-10-24 18:56:57 +00004221{
cristye2a912b2011-12-05 20:02:07 +00004222 PixelTrait
4223 trait;
4224
cristy77c30f52011-10-24 18:56:57 +00004225 register ssize_t
4226 i;
4227
cristyd26338f2011-12-14 02:39:30 +00004228 ssize_t
cristy77c30f52011-10-24 18:56:57 +00004229 n;
4230
4231 assert(image != (Image *) NULL);
4232 assert(image->signature == MagickSignature);
cristye2a912b2011-12-05 20:02:07 +00004233 (void) ResetMagickMemory(image->channel_map,0,MaxPixelChannels*
4234 sizeof(*image->channel_map));
4235 trait=UpdatePixelTrait;
cristy8a46d822012-08-28 23:32:39 +00004236 if (image->alpha_trait == BlendPixelTrait)
cristy61f18ad2011-12-08 21:12:37 +00004237 trait=(PixelTrait) (trait | BlendPixelTrait);
cristy77c30f52011-10-24 18:56:57 +00004238 n=0;
cristyc06c5802011-12-31 23:36:16 +00004239 if (image->colorspace == GRAYColorspace)
cristy77c30f52011-10-24 18:56:57 +00004240 {
cristycf1296e2012-08-26 23:40:49 +00004241 SetPixelChannelAttributes(image,BluePixelChannel,trait,n);
4242 SetPixelChannelAttributes(image,GreenPixelChannel,trait,n);
4243 SetPixelChannelAttributes(image,RedPixelChannel,trait,n++);
cristy3c316282011-12-15 15:43:24 +00004244 }
4245 else
4246 {
cristycf1296e2012-08-26 23:40:49 +00004247 SetPixelChannelAttributes(image,RedPixelChannel,trait,n++);
4248 SetPixelChannelAttributes(image,GreenPixelChannel,trait,n++);
4249 SetPixelChannelAttributes(image,BluePixelChannel,trait,n++);
cristy77c30f52011-10-24 18:56:57 +00004250 }
4251 if (image->colorspace == CMYKColorspace)
cristycf1296e2012-08-26 23:40:49 +00004252 SetPixelChannelAttributes(image,BlackPixelChannel,trait,n++);
cristy8a46d822012-08-28 23:32:39 +00004253 if (image->alpha_trait != UndefinedPixelTrait)
cristycf1296e2012-08-26 23:40:49 +00004254 SetPixelChannelAttributes(image,AlphaPixelChannel,CopyPixelTrait,n++);
cristye2a912b2011-12-05 20:02:07 +00004255 if (image->storage_class == PseudoClass)
cristycf1296e2012-08-26 23:40:49 +00004256 SetPixelChannelAttributes(image,IndexPixelChannel,CopyPixelTrait,n++);
cristy883fde12013-04-08 00:50:13 +00004257 if (image->read_mask != MagickFalse)
4258 SetPixelChannelAttributes(image,ReadMaskPixelChannel,CopyPixelTrait,n++);
4259 if (image->write_mask != MagickFalse)
4260 SetPixelChannelAttributes(image,WriteMaskPixelChannel,CopyPixelTrait,n++);
cristye2a912b2011-12-05 20:02:07 +00004261 assert((n+image->number_meta_channels) < MaxPixelChannels);
4262 for (i=0; i < (ssize_t) image->number_meta_channels; i++)
cristycf1296e2012-08-26 23:40:49 +00004263 SetPixelChannelAttributes(image,(PixelChannel) (MetaPixelChannel+i),
4264 CopyPixelTrait,n++);
cristyd26338f2011-12-14 02:39:30 +00004265 image->number_channels=(size_t) n;
cristy77c30f52011-10-24 18:56:57 +00004266 if (image->debug != MagickFalse)
4267 LogPixelChannels(image);
cristycf1296e2012-08-26 23:40:49 +00004268 (void) SetImageChannelMask(image,image->channel_mask);
cristy77c30f52011-10-24 18:56:57 +00004269}
cristybd5a96c2011-08-21 00:04:26 +00004270
4271/*
4272%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4273% %
4274% %
4275% %
cristya085a432011-07-30 01:39:32 +00004276% I n t e r p o l a t e P i x e l C h a n n e l %
4277% %
4278% %
4279% %
4280%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4281%
cristy884f6002011-07-31 00:51:45 +00004282% InterpolatePixelChannel() applies a pixel interpolation method between a
4283% floating point coordinate and the pixels surrounding that coordinate. No
4284% pixel area resampling, or scaling of the result is performed.
cristya085a432011-07-30 01:39:32 +00004285%
anthonycf4e33d2012-06-08 07:33:23 +00004286% Interpolation is restricted to just the specified channel.
4287%
cristya085a432011-07-30 01:39:32 +00004288% The format of the InterpolatePixelChannel method is:
4289%
4290% MagickBooleanType InterpolatePixelChannel(const Image *image,
cristy444eda62011-08-10 02:07:46 +00004291% const CacheView *image_view,const PixelChannel channel,
cristy5c4e2582011-09-11 19:21:03 +00004292% const PixelInterpolateMethod method,const double x,const double y,
cristya085a432011-07-30 01:39:32 +00004293% double *pixel,ExceptionInfo *exception)
4294%
4295% A description of each parameter follows:
4296%
4297% o image: the image.
4298%
4299% o image_view: the image view.
4300%
4301% o channel: the pixel channel to interpolate.
4302%
4303% o method: the pixel color interpolation method.
4304%
4305% o x,y: A double representing the current (x,y) position of the pixel.
4306%
4307% o pixel: return the interpolated pixel here.
4308%
4309% o exception: return any errors or warnings in this structure.
4310%
4311*/
cristy94ea1632011-07-30 20:40:25 +00004312
cristyb0a657e2012-08-29 00:45:37 +00004313static inline void CatromWeights(const double x,double (*weights)[4])
cristy884f6002011-07-31 00:51:45 +00004314{
cristya19f1d72012-08-07 18:24:38 +00004315 double
cristy884f6002011-07-31 00:51:45 +00004316 alpha,
nicolasd32d5e52012-06-12 15:34:10 +00004317 beta,
cristy884f6002011-07-31 00:51:45 +00004318 gamma;
4319
cristy5a5e4d92012-08-29 00:06:25 +00004320 /*
4321 Nicolas Robidoux' 10 flops (4* + 5- + 1+) refactoring of the computation
4322 of the standard four 1D Catmull-Rom weights. The sampling location is
4323 assumed between the second and third input pixel locations, and x is the
4324 position relative to the second input pixel location. Formulas originally
4325 derived for the VIPS (Virtual Image Processing System) library.
4326 */
cristya19f1d72012-08-07 18:24:38 +00004327 alpha=(double) 1.0-x;
4328 beta=(double) (-0.5)*x*alpha;
nicolasd32d5e52012-06-12 15:34:10 +00004329 (*weights)[0]=alpha*beta;
4330 (*weights)[3]=x*beta;
4331 /*
cristy5a5e4d92012-08-29 00:06:25 +00004332 The following computation of the inner weights from the outer ones work
4333 for all Keys cubics.
nicolasd32d5e52012-06-12 15:34:10 +00004334 */
4335 gamma=(*weights)[3]-(*weights)[0];
4336 (*weights)[1]=alpha-(*weights)[0]+gamma;
4337 (*weights)[2]=x-(*weights)[3]-gamma;
4338}
4339
cristyb0a657e2012-08-29 00:45:37 +00004340static inline void SplineWeights(const double x,double (*weights)[4])
nicolasd32d5e52012-06-12 15:34:10 +00004341{
cristy5a5e4d92012-08-29 00:06:25 +00004342 double
4343 alpha,
4344 beta;
4345
nicolasd32d5e52012-06-12 15:34:10 +00004346 /*
4347 Nicolas Robidoux' 12 flops (6* + 5- + 1+) refactoring of the
4348 computation of the standard four 1D cubic B-spline smoothing
4349 weights. The sampling location is assumed between the second and
4350 third input pixel locations, and x is the position relative to the
4351 second input pixel location.
4352 */
cristya19f1d72012-08-07 18:24:38 +00004353 alpha=(double) 1.0-x;
4354 (*weights)[3]=(double) (1.0/6.0)*x*x*x;
4355 (*weights)[0]=(double) (1.0/6.0)*alpha*alpha*alpha;
nicolasd32d5e52012-06-12 15:34:10 +00004356 beta=(*weights)[3]-(*weights)[0];
4357 (*weights)[1]=alpha-(*weights)[0]+beta;
4358 (*weights)[2]=x-(*weights)[3]-beta;
cristy884f6002011-07-31 00:51:45 +00004359}
4360
cristy94ea1632011-07-30 20:40:25 +00004361static inline double MeshInterpolate(const PointInfo *delta,const double p,
4362 const double x,const double y)
4363{
4364 return(delta->x*x+delta->y*y+(1.0-delta->x-delta->y)*p);
4365}
4366
anthonycf4e33d2012-06-08 07:33:23 +00004367/*
cristya19f1d72012-08-07 18:24:38 +00004368static inline ssize_t NearestNeighbor(const double x)
cristy884f6002011-07-31 00:51:45 +00004369{
4370 if (x >= 0.0)
4371 return((ssize_t) (x+0.5));
4372 return((ssize_t) (x-0.5));
4373}
anthonycf4e33d2012-06-08 07:33:23 +00004374*/
cristy884f6002011-07-31 00:51:45 +00004375
cristya085a432011-07-30 01:39:32 +00004376MagickExport MagickBooleanType InterpolatePixelChannel(const Image *image,
4377 const CacheView *image_view,const PixelChannel channel,
cristy5c4e2582011-09-11 19:21:03 +00004378 const PixelInterpolateMethod method,const double x,const double y,
cristya085a432011-07-30 01:39:32 +00004379 double *pixel,ExceptionInfo *exception)
4380{
4381 MagickBooleanType
4382 status;
4383
cristya19f1d72012-08-07 18:24:38 +00004384 double
cristy94ea1632011-07-30 20:40:25 +00004385 alpha[16],
cristy884f6002011-07-31 00:51:45 +00004386 gamma,
4387 pixels[16];
cristy94ea1632011-07-30 20:40:25 +00004388
4389 PixelTrait
4390 traits;
4391
cristy94ea1632011-07-30 20:40:25 +00004392 register const Quantum
4393 *p;
4394
cristy50e64b82012-06-22 17:46:19 +00004395 register ssize_t
cristy94ea1632011-07-30 20:40:25 +00004396 i;
4397
cristya085a432011-07-30 01:39:32 +00004398 ssize_t
4399 x_offset,
4400 y_offset;
4401
anthonycf4e33d2012-06-08 07:33:23 +00004402 PixelInterpolateMethod
4403 interpolate;
4404
cristya085a432011-07-30 01:39:32 +00004405 assert(image != (Image *) NULL);
4406 assert(image != (Image *) NULL);
4407 assert(image->signature == MagickSignature);
4408 assert(image_view != (CacheView *) NULL);
4409 status=MagickTrue;
cristy884f6002011-07-31 00:51:45 +00004410 *pixel=0.0;
cristycf1296e2012-08-26 23:40:49 +00004411 traits=GetPixelChannelTraits(image,channel);
cristya085a432011-07-30 01:39:32 +00004412 x_offset=(ssize_t) floor(x);
4413 y_offset=(ssize_t) floor(y);
anthonycf4e33d2012-06-08 07:33:23 +00004414 interpolate = method;
4415 if ( interpolate == UndefinedInterpolatePixel )
4416 interpolate = image->interpolate;
4417 switch (interpolate)
cristya085a432011-07-30 01:39:32 +00004418 {
anthonycf4e33d2012-06-08 07:33:23 +00004419 case AverageInterpolatePixel: /* nearest 4 neighbours */
4420 case Average9InterpolatePixel: /* nearest 9 neighbours */
4421 case Average16InterpolatePixel: /* nearest 16 neighbours */
cristy884f6002011-07-31 00:51:45 +00004422 {
cristyfb122372012-10-17 23:31:21 +00004423 ssize_t
4424 count;
anthonycf4e33d2012-06-08 07:33:23 +00004425
cristyfb122372012-10-17 23:31:21 +00004426 count=2; /* size of the area to average - default nearest 4 */
anthonycf4e33d2012-06-08 07:33:23 +00004427 if (interpolate == Average9InterpolatePixel)
4428 {
4429 count=3;
4430 x_offset=(ssize_t) (floor(x+0.5)-1);
4431 y_offset=(ssize_t) (floor(y+0.5)-1);
4432 }
cristyfb122372012-10-17 23:31:21 +00004433 else
4434 if (interpolate == Average16InterpolatePixel)
4435 {
4436 count=4;
4437 x_offset--;
4438 y_offset--;
4439 }
cristy021216a2013-05-20 16:25:51 +00004440 p=GetCacheViewVirtualPixels(image_view,x_offset,y_offset,(size_t) count,
4441 (size_t) count,exception);
cristy884f6002011-07-31 00:51:45 +00004442 if (p == (const Quantum *) NULL)
4443 {
4444 status=MagickFalse;
4445 break;
4446 }
anthonycf4e33d2012-06-08 07:33:23 +00004447 count*=count; /* Number of pixels to Average */
cristy222b19c2011-08-04 01:35:11 +00004448 if ((traits & BlendPixelTrait) == 0)
cristy50e64b82012-06-22 17:46:19 +00004449 for (i=0; i < (ssize_t) count; i++)
cristy884f6002011-07-31 00:51:45 +00004450 {
4451 alpha[i]=1.0;
cristya19f1d72012-08-07 18:24:38 +00004452 pixels[i]=(double) p[i*GetPixelChannels(image)+channel];
cristy884f6002011-07-31 00:51:45 +00004453 }
4454 else
cristy50e64b82012-06-22 17:46:19 +00004455 for (i=0; i < (ssize_t) count; i++)
cristy884f6002011-07-31 00:51:45 +00004456 {
4457 alpha[i]=QuantumScale*GetPixelAlpha(image,p+i*
4458 GetPixelChannels(image));
4459 pixels[i]=alpha[i]*p[i*GetPixelChannels(image)+channel];
4460 }
cristy50e64b82012-06-22 17:46:19 +00004461 for (i=0; i < (ssize_t) count; i++)
cristy884f6002011-07-31 00:51:45 +00004462 {
cristy3e3ec3a2012-11-03 23:11:06 +00004463 gamma=PerceptibleReciprocal(alpha[i])/count;
anthonycf4e33d2012-06-08 07:33:23 +00004464 *pixel+=gamma*pixels[i];
cristy884f6002011-07-31 00:51:45 +00004465 }
4466 break;
4467 }
anthonycf4e33d2012-06-08 07:33:23 +00004468 case BilinearInterpolatePixel:
4469 default:
4470 {
4471 PointInfo
4472 delta,
4473 epsilon;
4474
4475 p=GetCacheViewVirtualPixels(image_view,x_offset,y_offset,2,2,exception);
4476 if (p == (const Quantum *) NULL)
4477 {
4478 status=MagickFalse;
4479 break;
4480 }
4481 if ((traits & BlendPixelTrait) == 0)
4482 for (i=0; i < 4; i++)
4483 {
4484 alpha[i]=1.0;
cristya19f1d72012-08-07 18:24:38 +00004485 pixels[i]=(double) p[i*GetPixelChannels(image)+channel];
anthonycf4e33d2012-06-08 07:33:23 +00004486 }
4487 else
4488 for (i=0; i < 4; i++)
4489 {
4490 alpha[i]=QuantumScale*GetPixelAlpha(image,p+i*
4491 GetPixelChannels(image));
4492 pixels[i]=alpha[i]*p[i*GetPixelChannels(image)+channel];
4493 }
4494 delta.x=x-x_offset;
4495 delta.y=y-y_offset;
4496 epsilon.x=1.0-delta.x;
4497 epsilon.y=1.0-delta.y;
4498 gamma=((epsilon.y*(epsilon.x*alpha[0]+delta.x*alpha[1])+delta.y*
4499 (epsilon.x*alpha[2]+delta.x*alpha[3])));
cristy3e3ec3a2012-11-03 23:11:06 +00004500 gamma=PerceptibleReciprocal(gamma);
anthonycf4e33d2012-06-08 07:33:23 +00004501 *pixel=gamma*(epsilon.y*(epsilon.x*pixels[0]+delta.x*pixels[1])+delta.y*
4502 (epsilon.x*pixels[2]+delta.x*pixels[3]));
4503 break;
4504 }
anthony5f78bca2012-10-05 06:51:00 +00004505 case BlendInterpolatePixel:
4506 {
4507 p=GetCacheViewVirtualPixels(image_view,x_offset,y_offset,2,2,exception);
4508 if (p == (const Quantum *) NULL)
4509 {
4510 status=MagickFalse;
4511 break;
4512 }
4513 if ((traits & BlendPixelTrait) == 0)
4514 for (i=0; i < 4; i++)
4515 {
4516 alpha[i]=1.0;
4517 pixels[i]=(MagickRealType) p[i*GetPixelChannels(image)+channel];
4518 }
4519 else
4520 for (i=0; i < 4; i++)
4521 {
4522 alpha[i]=QuantumScale*GetPixelAlpha(image,p+i*
4523 GetPixelChannels(image));
4524 pixels[i]=alpha[i]*p[i*GetPixelChannels(image)+channel];
4525 }
4526 gamma=1.0; /* number of pixels blended together (its variable) */
4527 for (i=0; i <= 1L; i++) {
cristyfb122372012-10-17 23:31:21 +00004528 if ((y-y_offset) >= 0.75)
4529 {
4530 alpha[i]=alpha[i+2]; /* take right pixels */
4531 pixels[i]=pixels[i+2];
4532 }
4533 else
4534 if ((y-y_offset) > 0.25)
4535 {
4536 gamma=2.0; /* blend both pixels in row */
4537 alpha[i]+=alpha[i+2]; /* add up alpha weights */
4538 pixels[i]+=pixels[i+2];
4539 }
4540 }
4541 if ((x-x_offset) >= 0.75)
4542 {
4543 alpha[0]=alpha[1]; /* take bottom row blend */
4544 pixels[0]=pixels[1];
anthony5f78bca2012-10-05 06:51:00 +00004545 }
cristyfb122372012-10-17 23:31:21 +00004546 else
4547 if ((x-x_offset) > 0.25)
4548 {
4549 gamma*=2.0; /* blend both rows */
4550 alpha[0]+=alpha[1]; /* add up alpha weights */
4551 pixels[0]+=pixels[1];
4552 }
anthony5f78bca2012-10-05 06:51:00 +00004553 if (channel != AlphaPixelChannel)
cristy3e3ec3a2012-11-03 23:11:06 +00004554 gamma=PerceptibleReciprocal(alpha[0]); /* (color) 1/alpha_weights */
anthony5f78bca2012-10-05 06:51:00 +00004555 else
cristy3e3ec3a2012-11-03 23:11:06 +00004556 gamma=PerceptibleReciprocal(gamma); /* (alpha) 1/number_of_pixels */
anthony5f78bca2012-10-05 06:51:00 +00004557 *pixel=gamma*pixels[0];
4558 break;
4559 }
anthonycf4e33d2012-06-08 07:33:23 +00004560 case CatromInterpolatePixel:
cristy884f6002011-07-31 00:51:45 +00004561 {
cristya19f1d72012-08-07 18:24:38 +00004562 double
cristy380a11c2012-06-02 15:15:22 +00004563 cx[4],
nicolas6676f5a2012-06-12 16:01:15 +00004564 cy[4];
cristy884f6002011-07-31 00:51:45 +00004565
cristy884f6002011-07-31 00:51:45 +00004566 p=GetCacheViewVirtualPixels(image_view,x_offset-1,y_offset-1,4,4,
4567 exception);
4568 if (p == (const Quantum *) NULL)
4569 {
4570 status=MagickFalse;
4571 break;
4572 }
cristy222b19c2011-08-04 01:35:11 +00004573 if ((traits & BlendPixelTrait) == 0)
cristy884f6002011-07-31 00:51:45 +00004574 for (i=0; i < 16; i++)
4575 {
4576 alpha[i]=1.0;
cristya19f1d72012-08-07 18:24:38 +00004577 pixels[i]=(double) p[i*GetPixelChannels(image)+channel];
cristy884f6002011-07-31 00:51:45 +00004578 }
4579 else
4580 for (i=0; i < 16; i++)
4581 {
4582 alpha[i]=QuantumScale*GetPixelAlpha(image,p+i*
4583 GetPixelChannels(image));
4584 pixels[i]=alpha[i]*p[i*GetPixelChannels(image)+channel];
4585 }
cristya19f1d72012-08-07 18:24:38 +00004586 CatromWeights((double) (x-x_offset),&cx);
4587 CatromWeights((double) (y-y_offset),&cy);
4588 gamma=(channel == AlphaPixelChannel ? (double) 1.0 :
cristy3e3ec3a2012-11-03 23:11:06 +00004589 PerceptibleReciprocal(cy[0]*(cx[0]*alpha[0]+cx[1]*alpha[1]+cx[2]*
nicolasd32d5e52012-06-12 15:34:10 +00004590 alpha[2]+cx[3]*alpha[3])+cy[1]*(cx[0]*alpha[4]+cx[1]*alpha[5]+cx[2]*
4591 alpha[6]+cx[3]*alpha[7])+cy[2]*(cx[0]*alpha[8]+cx[1]*alpha[9]+cx[2]*
4592 alpha[10]+cx[3]*alpha[11])+cy[3]*(cx[0]*alpha[12]+cx[1]*alpha[13]+
4593 cx[2]*alpha[14]+cx[3]*alpha[15])));
cristy380a11c2012-06-02 15:15:22 +00004594 *pixel=gamma*(cy[0]*(cx[0]*pixels[0]+cx[1]*pixels[1]+cx[2]*pixels[2]+
nicolasd32d5e52012-06-12 15:34:10 +00004595 cx[3]*pixels[3])+cy[1]*(cx[0]*pixels[4]+cx[1]*pixels[5]+cx[2]*
4596 pixels[6]+cx[3]*pixels[7])+cy[2]*(cx[0]*pixels[8]+cx[1]*pixels[9]+
4597 cx[2]*pixels[10]+cx[3]*pixels[11])+cy[3]*(cx[0]*pixels[12]+cx[1]*
4598 pixels[13]+cx[2]*pixels[14]+cx[3]*pixels[15]));
cristy884f6002011-07-31 00:51:45 +00004599 break;
4600 }
cristy884f6002011-07-31 00:51:45 +00004601 case IntegerInterpolatePixel:
4602 {
4603 p=GetCacheViewVirtualPixels(image_view,x_offset,y_offset,1,1,exception);
4604 if (p == (const Quantum *) NULL)
4605 {
4606 status=MagickFalse;
4607 break;
4608 }
cristy0beccfa2011-09-25 20:47:53 +00004609 *pixel=(double) GetPixelChannel(image,channel,p);
cristy884f6002011-07-31 00:51:45 +00004610 break;
4611 }
anthonycf4e33d2012-06-08 07:33:23 +00004612 case NearestInterpolatePixel:
cristy884f6002011-07-31 00:51:45 +00004613 {
anthonycf4e33d2012-06-08 07:33:23 +00004614 x_offset=(ssize_t) floor(x+0.5);
4615 y_offset=(ssize_t) floor(y+0.5);
4616 p=GetCacheViewVirtualPixels(image_view,x_offset,y_offset,1,1,exception);
cristy884f6002011-07-31 00:51:45 +00004617 if (p == (const Quantum *) NULL)
4618 {
4619 status=MagickFalse;
4620 break;
4621 }
cristy0beccfa2011-09-25 20:47:53 +00004622 *pixel=(double) GetPixelChannel(image,channel,p);
cristy884f6002011-07-31 00:51:45 +00004623 break;
4624 }
4625 case MeshInterpolatePixel:
4626 {
4627 PointInfo
4628 delta,
cristy94ea1632011-07-30 20:40:25 +00004629 luminance;
4630
4631 p=GetCacheViewVirtualPixels(image_view,x_offset,y_offset,2,2,exception);
4632 if (p == (const Quantum *) NULL)
4633 {
4634 status=MagickFalse;
4635 break;
4636 }
cristy222b19c2011-08-04 01:35:11 +00004637 if ((traits & BlendPixelTrait) == 0)
cristy94ea1632011-07-30 20:40:25 +00004638 for (i=0; i < 4; i++)
4639 {
4640 alpha[i]=1.0;
cristya19f1d72012-08-07 18:24:38 +00004641 pixels[i]=(double) p[i*GetPixelChannels(image)+channel];
cristy94ea1632011-07-30 20:40:25 +00004642 }
4643 else
4644 for (i=0; i < 4; i++)
4645 {
4646 alpha[i]=QuantumScale*GetPixelAlpha(image,p+i*
4647 GetPixelChannels(image));
4648 pixels[i]=alpha[i]*p[i*GetPixelChannels(image)+channel];
4649 }
cristy884f6002011-07-31 00:51:45 +00004650 delta.x=x-x_offset;
4651 delta.y=y-y_offset;
4652 luminance.x=GetPixelLuminance(image,p)-(double)
4653 GetPixelLuminance(image,p+3*GetPixelChannels(image));
cristy28474bf2011-09-11 23:32:52 +00004654 luminance.y=GetPixelLuminance(image,p+GetPixelChannels(image))-(double)
cristy884f6002011-07-31 00:51:45 +00004655 GetPixelLuminance(image,p+2*GetPixelChannels(image));
cristy94ea1632011-07-30 20:40:25 +00004656 if (fabs(luminance.x) < fabs(luminance.y))
4657 {
4658 /*
4659 Diagonal 0-3 NW-SE.
4660 */
4661 if (delta.x <= delta.y)
4662 {
4663 /*
4664 Bottom-left triangle (pixel: 2, diagonal: 0-3).
4665 */
4666 delta.y=1.0-delta.y;
4667 gamma=MeshInterpolate(&delta,alpha[2],alpha[3],alpha[0]);
cristy3e3ec3a2012-11-03 23:11:06 +00004668 gamma=PerceptibleReciprocal(gamma);
cristy94ea1632011-07-30 20:40:25 +00004669 *pixel=gamma*MeshInterpolate(&delta,pixels[2],pixels[3],
4670 pixels[0]);
4671 }
4672 else
4673 {
4674 /*
4675 Top-right triangle (pixel: 1, diagonal: 0-3).
4676 */
4677 delta.x=1.0-delta.x;
4678 gamma=MeshInterpolate(&delta,alpha[1],alpha[0],alpha[3]);
cristy3e3ec3a2012-11-03 23:11:06 +00004679 gamma=PerceptibleReciprocal(gamma);
cristy94ea1632011-07-30 20:40:25 +00004680 *pixel=gamma*MeshInterpolate(&delta,pixels[1],pixels[0],
4681 pixels[3]);
4682 }
4683 }
4684 else
4685 {
4686 /*
4687 Diagonal 1-2 NE-SW.
4688 */
4689 if (delta.x <= (1.0-delta.y))
4690 {
4691 /*
4692 Top-left triangle (pixel: 0, diagonal: 1-2).
4693 */
4694 gamma=MeshInterpolate(&delta,alpha[0],alpha[1],alpha[2]);
cristy3e3ec3a2012-11-03 23:11:06 +00004695 gamma=PerceptibleReciprocal(gamma);
cristy94ea1632011-07-30 20:40:25 +00004696 *pixel=gamma*MeshInterpolate(&delta,pixels[0],pixels[1],
4697 pixels[2]);
4698 }
4699 else
4700 {
4701 /*
4702 Bottom-right triangle (pixel: 3, diagonal: 1-2).
4703 */
4704 delta.x=1.0-delta.x;
4705 delta.y=1.0-delta.y;
4706 gamma=MeshInterpolate(&delta,alpha[3],alpha[2],alpha[1]);
cristy3e3ec3a2012-11-03 23:11:06 +00004707 gamma=PerceptibleReciprocal(gamma);
cristy94ea1632011-07-30 20:40:25 +00004708 *pixel=gamma*MeshInterpolate(&delta,pixels[3],pixels[2],
4709 pixels[1]);
4710 }
4711 }
cristya085a432011-07-30 01:39:32 +00004712 break;
4713 }
cristy884f6002011-07-31 00:51:45 +00004714 case SplineInterpolatePixel:
4715 {
cristya19f1d72012-08-07 18:24:38 +00004716 double
nicolasd32d5e52012-06-12 15:34:10 +00004717 cx[4],
nicolas6676f5a2012-06-12 16:01:15 +00004718 cy[4];
cristy884f6002011-07-31 00:51:45 +00004719
4720 p=GetCacheViewVirtualPixels(image_view,x_offset-1,y_offset-1,4,4,
4721 exception);
4722 if (p == (const Quantum *) NULL)
4723 {
4724 status=MagickFalse;
4725 break;
4726 }
cristy222b19c2011-08-04 01:35:11 +00004727 if ((traits & BlendPixelTrait) == 0)
cristy884f6002011-07-31 00:51:45 +00004728 for (i=0; i < 16; i++)
4729 {
4730 alpha[i]=1.0;
cristya19f1d72012-08-07 18:24:38 +00004731 pixels[i]=(double) p[i*GetPixelChannels(image)+channel];
cristy884f6002011-07-31 00:51:45 +00004732 }
4733 else
4734 for (i=0; i < 16; i++)
4735 {
4736 alpha[i]=QuantumScale*GetPixelAlpha(image,p+i*
4737 GetPixelChannels(image));
4738 pixels[i]=alpha[i]*p[i*GetPixelChannels(image)+channel];
4739 }
cristya19f1d72012-08-07 18:24:38 +00004740 SplineWeights((double) (x-x_offset),&cx);
4741 SplineWeights((double) (y-y_offset),&cy);
4742 gamma=(channel == AlphaPixelChannel ? (double) 1.0 :
cristy3e3ec3a2012-11-03 23:11:06 +00004743 PerceptibleReciprocal(cy[0]*(cx[0]*alpha[0]+cx[1]*alpha[1]+cx[2]*
nicolasd32d5e52012-06-12 15:34:10 +00004744 alpha[2]+cx[3]*alpha[3])+cy[1]*(cx[0]*alpha[4]+cx[1]*alpha[5]+cx[2]*
4745 alpha[6]+cx[3]*alpha[7])+cy[2]*(cx[0]*alpha[8]+cx[1]*alpha[9]+cx[2]*
4746 alpha[10]+cx[3]*alpha[11])+cy[3]*(cx[0]*alpha[12]+cx[1]*alpha[13]+
4747 cx[2]*alpha[14]+cx[3]*alpha[15])));
4748 *pixel=gamma*(cy[0]*(cx[0]*pixels[0]+cx[1]*pixels[1]+cx[2]*pixels[2]+
4749 cx[3]*pixels[3])+cy[1]*(cx[0]*pixels[4]+cx[1]*pixels[5]+cx[2]*
4750 pixels[6]+cx[3]*pixels[7])+cy[2]*(cx[0]*pixels[8]+cx[1]*pixels[9]+
4751 cx[2]*pixels[10]+cx[3]*pixels[11])+cy[3]*(cx[0]*pixels[12]+cx[1]*
4752 pixels[13]+cx[2]*pixels[14]+cx[3]*pixels[15]));
cristy884f6002011-07-31 00:51:45 +00004753 break;
4754 }
cristya085a432011-07-30 01:39:32 +00004755 }
4756 return(status);
4757}
4758
4759/*
4760%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4761% %
4762% %
4763% %
cristy5c4e2582011-09-11 19:21:03 +00004764% I n t e r p o l a t e P i x e l C h a n n e l s %
4765% %
4766% %
4767% %
4768%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4769%
4770% InterpolatePixelChannels() applies a pixel interpolation method between a
4771% floating point coordinate and the pixels surrounding that coordinate. No
4772% pixel area resampling, or scaling of the result is performed.
4773%
anthonycf4e33d2012-06-08 07:33:23 +00004774% Interpolation is restricted to just the current channel setting of the
4775% destination image into which the color is to be stored
4776%
cristy5c4e2582011-09-11 19:21:03 +00004777% The format of the InterpolatePixelChannels method is:
4778%
4779% MagickBooleanType InterpolatePixelChannels(const Image *source,
4780% const CacheView *source_view,const Image *destination,
4781% const PixelInterpolateMethod method,const double x,const double y,
4782% Quantum *pixel,ExceptionInfo *exception)
4783%
4784% A description of each parameter follows:
4785%
4786% o source: the source.
4787%
4788% o source_view: the source view.
4789%
anthonycf4e33d2012-06-08 07:33:23 +00004790% o destination: the destination image, for the interpolated color
cristy5c4e2582011-09-11 19:21:03 +00004791%
4792% o method: the pixel color interpolation method.
4793%
4794% o x,y: A double representing the current (x,y) position of the pixel.
4795%
4796% o pixel: return the interpolated pixel here.
4797%
4798% o exception: return any errors or warnings in this structure.
4799%
4800*/
4801MagickExport MagickBooleanType InterpolatePixelChannels(const Image *source,
4802 const CacheView *source_view,const Image *destination,
4803 const PixelInterpolateMethod method,const double x,const double y,
4804 Quantum *pixel,ExceptionInfo *exception)
4805{
4806 MagickBooleanType
4807 status;
4808
cristya19f1d72012-08-07 18:24:38 +00004809 double
cristy5c4e2582011-09-11 19:21:03 +00004810 alpha[16],
4811 gamma,
4812 pixels[16];
4813
cristy5c4e2582011-09-11 19:21:03 +00004814 register const Quantum
4815 *p;
4816
cristy50e64b82012-06-22 17:46:19 +00004817 register ssize_t
cristy5c4e2582011-09-11 19:21:03 +00004818 i;
4819
4820 ssize_t
4821 x_offset,
4822 y_offset;
4823
anthonycf4e33d2012-06-08 07:33:23 +00004824 PixelInterpolateMethod
4825 interpolate;
4826
cristy5c4e2582011-09-11 19:21:03 +00004827 assert(source != (Image *) NULL);
4828 assert(source != (Image *) NULL);
4829 assert(source->signature == MagickSignature);
4830 assert(source_view != (CacheView *) NULL);
4831 status=MagickTrue;
4832 x_offset=(ssize_t) floor(x);
4833 y_offset=(ssize_t) floor(y);
anthonycf4e33d2012-06-08 07:33:23 +00004834 interpolate = method;
4835 if ( interpolate == UndefinedInterpolatePixel )
4836 interpolate = source->interpolate;
4837 switch (interpolate)
cristy5c4e2582011-09-11 19:21:03 +00004838 {
anthonycf4e33d2012-06-08 07:33:23 +00004839 case AverageInterpolatePixel: /* nearest 4 neighbours */
4840 case Average9InterpolatePixel: /* nearest 9 neighbours */
4841 case Average16InterpolatePixel: /* nearest 16 neighbours */
cristy5c4e2582011-09-11 19:21:03 +00004842 {
cristyfb122372012-10-17 23:31:21 +00004843 ssize_t
4844 count;
anthonycf4e33d2012-06-08 07:33:23 +00004845
cristyfb122372012-10-17 23:31:21 +00004846 count=2; /* size of the area to average - default nearest 4 */
anthonycf4e33d2012-06-08 07:33:23 +00004847 if (interpolate == Average9InterpolatePixel)
4848 {
4849 count=3;
4850 x_offset=(ssize_t) (floor(x+0.5)-1);
4851 y_offset=(ssize_t) (floor(y+0.5)-1);
4852 }
cristyfb122372012-10-17 23:31:21 +00004853 else
4854 if (interpolate == Average16InterpolatePixel)
4855 {
4856 count=4;
4857 x_offset--;
4858 y_offset--;
4859 }
cristy1b72b812013-04-19 00:57:44 +00004860 p=GetCacheViewVirtualPixels(source_view,x_offset,y_offset,(size_t) count,
4861 (size_t) count,exception);
cristy5c4e2582011-09-11 19:21:03 +00004862 if (p == (const Quantum *) NULL)
4863 {
4864 status=MagickFalse;
4865 break;
4866 }
cristyfb122372012-10-17 23:31:21 +00004867 count*=count; /* Number of pixels to Average */
cristy50e64b82012-06-22 17:46:19 +00004868 for (i=0; i < (ssize_t) GetPixelChannels(source); i++)
cristy5c4e2582011-09-11 19:21:03 +00004869 {
4870 double
4871 sum;
4872
cristy50e64b82012-06-22 17:46:19 +00004873 register ssize_t
cristy5c4e2582011-09-11 19:21:03 +00004874 j;
4875
cristy5a23c552013-02-13 14:34:28 +00004876 PixelChannel channel=GetPixelChannelChannel(source,i);
4877 PixelTrait traits=GetPixelChannelTraits(source,channel);
4878 PixelTrait destination_traits=GetPixelChannelTraits(destination,
4879 channel);
cristy5c4e2582011-09-11 19:21:03 +00004880 if ((traits == UndefinedPixelTrait) ||
4881 (destination_traits == UndefinedPixelTrait))
4882 continue;
cristy50e64b82012-06-22 17:46:19 +00004883 for (j=0; j < (ssize_t) count; j++)
cristya19f1d72012-08-07 18:24:38 +00004884 pixels[j]=(double) p[j*GetPixelChannels(source)+i];
cristy4a7ae692011-12-14 12:24:11 +00004885 sum=0.0;
cristy5c4e2582011-09-11 19:21:03 +00004886 if ((traits & BlendPixelTrait) == 0)
4887 {
cristy50e64b82012-06-22 17:46:19 +00004888 for (j=0; j < (ssize_t) count; j++)
anthonycf4e33d2012-06-08 07:33:23 +00004889 sum+=pixels[j];
4890 sum/=count;
cristy4a7ae692011-12-14 12:24:11 +00004891 SetPixelChannel(destination,channel,ClampToQuantum(sum),pixel);
cristy5c4e2582011-09-11 19:21:03 +00004892 continue;
4893 }
cristy50e64b82012-06-22 17:46:19 +00004894 for (j=0; j < (ssize_t) count; j++)
cristy5c4e2582011-09-11 19:21:03 +00004895 {
4896 alpha[j]=QuantumScale*GetPixelAlpha(source,p+j*
4897 GetPixelChannels(source));
4898 pixels[j]*=alpha[j];
cristy3e3ec3a2012-11-03 23:11:06 +00004899 gamma=PerceptibleReciprocal(alpha[j]);
anthonycf4e33d2012-06-08 07:33:23 +00004900 sum+=gamma*pixels[j];
cristy5c4e2582011-09-11 19:21:03 +00004901 }
anthonycf4e33d2012-06-08 07:33:23 +00004902 sum/=count;
cristy4a7ae692011-12-14 12:24:11 +00004903 SetPixelChannel(destination,channel,ClampToQuantum(sum),pixel);
cristy5c4e2582011-09-11 19:21:03 +00004904 }
4905 break;
4906 }
anthonycf4e33d2012-06-08 07:33:23 +00004907 case BilinearInterpolatePixel:
4908 default:
4909 {
4910 p=GetCacheViewVirtualPixels(source_view,x_offset,y_offset,2,2,exception);
4911 if (p == (const Quantum *) NULL)
4912 {
4913 status=MagickFalse;
4914 break;
4915 }
cristy50e64b82012-06-22 17:46:19 +00004916 for (i=0; i < (ssize_t) GetPixelChannels(source); i++)
anthonycf4e33d2012-06-08 07:33:23 +00004917 {
4918 PointInfo
4919 delta,
4920 epsilon;
4921
cristy5a23c552013-02-13 14:34:28 +00004922 PixelChannel channel=GetPixelChannelChannel(source,i);
4923 PixelTrait traits=GetPixelChannelTraits(source,channel);
4924 PixelTrait destination_traits=GetPixelChannelTraits(destination,
4925 channel);
anthonycf4e33d2012-06-08 07:33:23 +00004926 if ((traits == UndefinedPixelTrait) ||
4927 (destination_traits == UndefinedPixelTrait))
4928 continue;
4929 delta.x=x-x_offset;
4930 delta.y=y-y_offset;
4931 epsilon.x=1.0-delta.x;
4932 epsilon.y=1.0-delta.y;
cristya19f1d72012-08-07 18:24:38 +00004933 pixels[0]=(double) p[i];
4934 pixels[1]=(double) p[GetPixelChannels(source)+i];
4935 pixels[2]=(double) p[2*GetPixelChannels(source)+i];
4936 pixels[3]=(double) p[3*GetPixelChannels(source)+i];
anthonycf4e33d2012-06-08 07:33:23 +00004937 if ((traits & BlendPixelTrait) == 0)
4938 {
4939 gamma=((epsilon.y*(epsilon.x+delta.x)+delta.y*(epsilon.x+delta.x)));
cristy3e3ec3a2012-11-03 23:11:06 +00004940 gamma=PerceptibleReciprocal(gamma);
anthonycf4e33d2012-06-08 07:33:23 +00004941 SetPixelChannel(destination,channel,ClampToQuantum(gamma*(epsilon.y*
4942 (epsilon.x*pixels[0]+delta.x*pixels[1])+delta.y*(epsilon.x*
4943 pixels[2]+delta.x*pixels[3]))),pixel);
4944 continue;
4945 }
4946 alpha[0]=QuantumScale*GetPixelAlpha(source,p);
4947 alpha[1]=QuantumScale*GetPixelAlpha(source,p+GetPixelChannels(source));
4948 alpha[2]=QuantumScale*GetPixelAlpha(source,p+2*
4949 GetPixelChannels(source));
4950 alpha[3]=QuantumScale*GetPixelAlpha(source,p+3*
4951 GetPixelChannels(source));
4952 pixels[0]*=alpha[0];
4953 pixels[1]*=alpha[1];
4954 pixels[2]*=alpha[2];
4955 pixels[3]*=alpha[3];
4956 gamma=((epsilon.y*(epsilon.x*alpha[0]+delta.x*alpha[1])+delta.y*
4957 (epsilon.x*alpha[2]+delta.x*alpha[3])));
cristy3e3ec3a2012-11-03 23:11:06 +00004958 gamma=PerceptibleReciprocal(gamma);
anthonycf4e33d2012-06-08 07:33:23 +00004959 SetPixelChannel(destination,channel,ClampToQuantum(gamma*(epsilon.y*
4960 (epsilon.x*pixels[0]+delta.x*pixels[1])+delta.y*(epsilon.x*pixels[2]+
4961 delta.x*pixels[3]))),pixel);
4962 }
4963 break;
4964 }
anthony5f78bca2012-10-05 06:51:00 +00004965 case BlendInterpolatePixel:
4966 {
4967 p=GetCacheViewVirtualPixels(source_view,x_offset,y_offset,2,2,exception);
4968 if (p == (const Quantum *) NULL)
4969 {
4970 status=MagickFalse;
4971 break;
4972 }
4973 for (i=0; i < (ssize_t) GetPixelChannels(source); i++)
4974 {
4975 register ssize_t
4976 j;
4977
cristy5a23c552013-02-13 14:34:28 +00004978 PixelChannel channel=GetPixelChannelChannel(source,i);
4979 PixelTrait traits=GetPixelChannelTraits(source,channel);
4980 PixelTrait destination_traits=GetPixelChannelTraits(destination,
4981 channel);
anthony5f78bca2012-10-05 06:51:00 +00004982 if ((traits == UndefinedPixelTrait) ||
4983 (destination_traits == UndefinedPixelTrait))
4984 continue;
4985 if ((traits & BlendPixelTrait) == 0)
4986 for (j=0; j < 4; j++)
4987 {
4988 alpha[j]=1.0;
4989 pixels[j]=(MagickRealType) p[j*GetPixelChannels(source)+channel];
4990 }
4991 else
4992 for (j=0; j < 4; j++)
4993 {
4994 alpha[j]=QuantumScale*GetPixelAlpha(source,p+j*
4995 GetPixelChannels(source));
4996 pixels[j]=alpha[j]*p[j*GetPixelChannels(source)+channel];
4997 }
cristyfb122372012-10-17 23:31:21 +00004998 gamma=1.0; /* number of pixels blended together (its variable) */
4999 for (j=0; j <= 1L; j++)
5000 {
5001 if ((y-y_offset) >= 0.75)
5002 {
5003 alpha[j]=alpha[j+2]; /* take right pixels */
5004 pixels[j]=pixels[j+2];
5005 }
5006 else
5007 if ((y-y_offset) > 0.25)
5008 {
5009 gamma=2.0; /* blend both pixels in row */
5010 alpha[j]+=alpha[j+2]; /* add up alpha weights */
5011 pixels[j]+=pixels[j+2];
5012 }
5013 }
5014 if ((x-x_offset) >= 0.75)
5015 {
5016 alpha[0]=alpha[1]; /* take bottom row blend */
5017 pixels[0]=pixels[1];
anthony5f78bca2012-10-05 06:51:00 +00005018 }
cristyfb122372012-10-17 23:31:21 +00005019 else
5020 if ((x-x_offset) > 0.25)
5021 {
5022 gamma*=2.0; /* blend both rows */
5023 alpha[0]+=alpha[1]; /* add up alpha weights */
5024 pixels[0]+=pixels[1];
5025 }
anthony5f78bca2012-10-05 06:51:00 +00005026 if ((traits & BlendPixelTrait) == 0)
cristy3e3ec3a2012-11-03 23:11:06 +00005027 gamma=PerceptibleReciprocal(alpha[0]); /* (color) 1/alpha_weights */
anthony5f78bca2012-10-05 06:51:00 +00005028 else
cristy3e3ec3a2012-11-03 23:11:06 +00005029 gamma=PerceptibleReciprocal(gamma); /* (alpha) 1/number_of_pixels */
anthony5f78bca2012-10-05 06:51:00 +00005030 SetPixelChannel(destination,channel,ClampToQuantum(gamma*pixels[0]),
cristyfb122372012-10-17 23:31:21 +00005031 pixel);
anthony5f78bca2012-10-05 06:51:00 +00005032 }
5033 break;
5034 }
anthonycf4e33d2012-06-08 07:33:23 +00005035 case CatromInterpolatePixel:
cristy5c4e2582011-09-11 19:21:03 +00005036 {
cristya19f1d72012-08-07 18:24:38 +00005037 double
cristy380a11c2012-06-02 15:15:22 +00005038 cx[4],
5039 cy[4];
cristy5c4e2582011-09-11 19:21:03 +00005040
cristy5c4e2582011-09-11 19:21:03 +00005041 p=GetCacheViewVirtualPixels(source_view,x_offset-1,y_offset-1,4,4,
5042 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 {
5050 register ssize_t
5051 j;
5052
cristy5a23c552013-02-13 14:34:28 +00005053 PixelChannel channel=GetPixelChannelChannel(source,i);
5054 PixelTrait traits=GetPixelChannelTraits(source,channel);
5055 PixelTrait destination_traits=GetPixelChannelTraits(destination,
5056 channel);
cristy5c4e2582011-09-11 19:21:03 +00005057 if ((traits == UndefinedPixelTrait) ||
5058 (destination_traits == UndefinedPixelTrait))
5059 continue;
5060 if ((traits & BlendPixelTrait) == 0)
5061 for (j=0; j < 16; j++)
5062 {
5063 alpha[j]=1.0;
cristya19f1d72012-08-07 18:24:38 +00005064 pixels[j]=(double) p[j*GetPixelChannels(source)+i];
cristy5c4e2582011-09-11 19:21:03 +00005065 }
5066 else
5067 for (j=0; j < 16; j++)
5068 {
5069 alpha[j]=QuantumScale*GetPixelAlpha(source,p+j*
5070 GetPixelChannels(source));
5071 pixels[j]=alpha[j]*p[j*GetPixelChannels(source)+i];
5072 }
cristya19f1d72012-08-07 18:24:38 +00005073 CatromWeights((double) (x-x_offset),&cx);
5074 CatromWeights((double) (y-y_offset),&cy);
5075 gamma=((traits & BlendPixelTrait) ? (double) (1.0) :
cristy3e3ec3a2012-11-03 23:11:06 +00005076 PerceptibleReciprocal(cy[0]*(cx[0]*alpha[0]+cx[1]*alpha[1]+cx[2]*
nicolasd32d5e52012-06-12 15:34:10 +00005077 alpha[2]+cx[3]*alpha[3])+cy[1]*(cx[0]*alpha[4]+cx[1]*alpha[5]+cx[2]*
5078 alpha[6]+cx[3]*alpha[7])+cy[2]*(cx[0]*alpha[8]+cx[1]*alpha[9]+cx[2]*
5079 alpha[10]+cx[3]*alpha[11])+cy[3]*(cx[0]*alpha[12]+cx[1]*alpha[13]+
5080 cx[2]*alpha[14]+cx[3]*alpha[15])));
cristy380a11c2012-06-02 15:15:22 +00005081 SetPixelChannel(destination,channel,ClampToQuantum(gamma*(cy[0]*(cx[0]*
5082 pixels[0]+cx[1]*pixels[1]+cx[2]*pixels[2]+cx[3]*pixels[3])+cy[1]*
5083 (cx[0]*pixels[4]+cx[1]*pixels[5]+cx[2]*pixels[6]+cx[3]*pixels[7])+
5084 cy[2]*(cx[0]*pixels[8]+cx[1]*pixels[9]+cx[2]*pixels[10]+cx[3]*
nicolasd32d5e52012-06-12 15:34:10 +00005085 pixels[11])+cy[3]*(cx[0]*pixels[12]+cx[1]*pixels[13]+cx[2]*
5086 pixels[14]+cx[3]*pixels[15]))),pixel);
cristy5c4e2582011-09-11 19:21:03 +00005087 }
5088 break;
5089 }
cristy5c4e2582011-09-11 19:21:03 +00005090 case IntegerInterpolatePixel:
5091 {
5092 p=GetCacheViewVirtualPixels(source_view,x_offset,y_offset,1,1,exception);
5093 if (p == (const Quantum *) NULL)
5094 {
5095 status=MagickFalse;
5096 break;
5097 }
cristy50e64b82012-06-22 17:46:19 +00005098 for (i=0; i < (ssize_t) GetPixelChannels(source); i++)
cristy5c4e2582011-09-11 19:21:03 +00005099 {
cristy5a23c552013-02-13 14:34:28 +00005100 PixelChannel channel=GetPixelChannelChannel(source,i);
5101 PixelTrait traits=GetPixelChannelTraits(source,channel);
5102 PixelTrait destination_traits=GetPixelChannelTraits(destination,
5103 channel);
cristy5c4e2582011-09-11 19:21:03 +00005104 if ((traits == UndefinedPixelTrait) ||
5105 (destination_traits == UndefinedPixelTrait))
5106 continue;
cristy4a7ae692011-12-14 12:24:11 +00005107 SetPixelChannel(destination,channel,p[i],pixel);
cristy5c4e2582011-09-11 19:21:03 +00005108 }
5109 break;
5110 }
anthonycf4e33d2012-06-08 07:33:23 +00005111 case NearestInterpolatePixel:
cristy5c4e2582011-09-11 19:21:03 +00005112 {
anthonycf4e33d2012-06-08 07:33:23 +00005113 x_offset=(ssize_t) floor(x+0.5);
5114 y_offset=(ssize_t) floor(y+0.5);
5115 p=GetCacheViewVirtualPixels(source_view,x_offset,y_offset,1,1,exception);
cristy5c4e2582011-09-11 19:21:03 +00005116 if (p == (const Quantum *) NULL)
5117 {
5118 status=MagickFalse;
5119 break;
5120 }
cristy50e64b82012-06-22 17:46:19 +00005121 for (i=0; i < (ssize_t) GetPixelChannels(source); i++)
cristy5c4e2582011-09-11 19:21:03 +00005122 {
cristy5a23c552013-02-13 14:34:28 +00005123 PixelChannel channel=GetPixelChannelChannel(source,i);
5124 PixelTrait traits=GetPixelChannelTraits(source,channel);
5125 PixelTrait destination_traits=GetPixelChannelTraits(destination,
5126 channel);
cristy5c4e2582011-09-11 19:21:03 +00005127 if ((traits == UndefinedPixelTrait) ||
5128 (destination_traits == UndefinedPixelTrait))
5129 continue;
cristy4a7ae692011-12-14 12:24:11 +00005130 SetPixelChannel(destination,channel,p[i],pixel);
cristy5c4e2582011-09-11 19:21:03 +00005131 }
5132 break;
5133 }
5134 case MeshInterpolatePixel:
5135 {
5136 p=GetCacheViewVirtualPixels(source_view,x_offset,y_offset,2,2,exception);
5137 if (p == (const Quantum *) NULL)
5138 {
5139 status=MagickFalse;
5140 break;
5141 }
cristy50e64b82012-06-22 17:46:19 +00005142 for (i=0; i < (ssize_t) GetPixelChannels(source); i++)
cristy5c4e2582011-09-11 19:21:03 +00005143 {
5144 PointInfo
5145 delta,
5146 luminance;
5147
cristy5a23c552013-02-13 14:34:28 +00005148 PixelChannel channel=GetPixelChannelChannel(source,i);
5149 PixelTrait traits=GetPixelChannelTraits(source,channel);
5150 PixelTrait destination_traits=GetPixelChannelTraits(destination,
5151 channel);
cristy5c4e2582011-09-11 19:21:03 +00005152 if ((traits == UndefinedPixelTrait) ||
5153 (destination_traits == UndefinedPixelTrait))
5154 continue;
cristya19f1d72012-08-07 18:24:38 +00005155 pixels[0]=(double) p[i];
5156 pixels[1]=(double) p[GetPixelChannels(source)+i];
5157 pixels[2]=(double) p[2*GetPixelChannels(source)+i];
5158 pixels[3]=(double) p[3*GetPixelChannels(source)+i];
cristy1861c902011-12-14 02:30:00 +00005159 if ((traits & BlendPixelTrait) == 0)
5160 {
5161 alpha[0]=1.0;
5162 alpha[1]=1.0;
5163 alpha[2]=1.0;
5164 alpha[3]=1.0;
5165 }
5166 else
5167 {
5168 alpha[0]=QuantumScale*GetPixelAlpha(source,p);
5169 alpha[1]=QuantumScale*GetPixelAlpha(source,p+
5170 GetPixelChannels(source));
5171 alpha[2]=QuantumScale*GetPixelAlpha(source,p+2*
5172 GetPixelChannels(source));
5173 alpha[3]=QuantumScale*GetPixelAlpha(source,p+3*
5174 GetPixelChannels(source));
5175 }
5176 delta.x=x-x_offset;
5177 delta.y=y-y_offset;
cristyfb122372012-10-17 23:31:21 +00005178 luminance.x=fabs((double) (GetPixelLuminance(source,p)-
5179 GetPixelLuminance(source,p+3*GetPixelChannels(source))));
5180 luminance.y=fabs((double) (GetPixelLuminance(source,p+
5181 GetPixelChannels(source))-GetPixelLuminance(source,p+2*
5182 GetPixelChannels(source))));
anthonycf4e33d2012-06-08 07:33:23 +00005183 if (luminance.x < luminance.y)
cristy1861c902011-12-14 02:30:00 +00005184 {
5185 /*
5186 Diagonal 0-3 NW-SE.
5187 */
5188 if (delta.x <= delta.y)
5189 {
5190 /*
5191 Bottom-left triangle (pixel: 2, diagonal: 0-3).
5192 */
5193 delta.y=1.0-delta.y;
5194 gamma=MeshInterpolate(&delta,alpha[2],alpha[3],alpha[0]);
cristy3e3ec3a2012-11-03 23:11:06 +00005195 gamma=PerceptibleReciprocal(gamma);
cristy4a7ae692011-12-14 12:24:11 +00005196 SetPixelChannel(destination,channel,ClampToQuantum(gamma*
5197 MeshInterpolate(&delta,pixels[2],pixels[3],pixels[0])),pixel);
cristy1861c902011-12-14 02:30:00 +00005198 }
5199 else
5200 {
5201 /*
5202 Top-right triangle (pixel: 1, diagonal: 0-3).
5203 */
5204 delta.x=1.0-delta.x;
5205 gamma=MeshInterpolate(&delta,alpha[1],alpha[0],alpha[3]);
cristy3e3ec3a2012-11-03 23:11:06 +00005206 gamma=PerceptibleReciprocal(gamma);
cristy4a7ae692011-12-14 12:24:11 +00005207 SetPixelChannel(destination,channel,ClampToQuantum(gamma*
5208 MeshInterpolate(&delta,pixels[1],pixels[0],pixels[3])),pixel);
cristy1861c902011-12-14 02:30:00 +00005209 }
5210 }
5211 else
5212 {
5213 /*
5214 Diagonal 1-2 NE-SW.
5215 */
5216 if (delta.x <= (1.0-delta.y))
5217 {
5218 /*
5219 Top-left triangle (pixel: 0, diagonal: 1-2).
5220 */
5221 gamma=MeshInterpolate(&delta,alpha[0],alpha[1],alpha[2]);
cristy3e3ec3a2012-11-03 23:11:06 +00005222 gamma=PerceptibleReciprocal(gamma);
cristy4a7ae692011-12-14 12:24:11 +00005223 SetPixelChannel(destination,channel,ClampToQuantum(gamma*
5224 MeshInterpolate(&delta,pixels[0],pixels[1],pixels[2])),pixel);
cristy1861c902011-12-14 02:30:00 +00005225 }
5226 else
5227 {
5228 /*
5229 Bottom-right triangle (pixel: 3, diagonal: 1-2).
5230 */
5231 delta.x=1.0-delta.x;
5232 delta.y=1.0-delta.y;
5233 gamma=MeshInterpolate(&delta,alpha[3],alpha[2],alpha[1]);
cristy3e3ec3a2012-11-03 23:11:06 +00005234 gamma=PerceptibleReciprocal(gamma);
cristy4a7ae692011-12-14 12:24:11 +00005235 SetPixelChannel(destination,channel,ClampToQuantum(gamma*
5236 MeshInterpolate(&delta,pixels[3],pixels[2],pixels[1])),pixel);
cristy1861c902011-12-14 02:30:00 +00005237 }
5238 }
cristy5c4e2582011-09-11 19:21:03 +00005239 }
5240 break;
5241 }
5242 case SplineInterpolatePixel:
5243 {
cristya19f1d72012-08-07 18:24:38 +00005244 double
nicolasd32d5e52012-06-12 15:34:10 +00005245 cx[4],
5246 cy[4];
5247
cristy5c4e2582011-09-11 19:21:03 +00005248 p=GetCacheViewVirtualPixels(source_view,x_offset-1,y_offset-1,4,4,
5249 exception);
5250 if (p == (const Quantum *) NULL)
5251 {
5252 status=MagickFalse;
5253 break;
5254 }
cristy50e64b82012-06-22 17:46:19 +00005255 for (i=0; i < (ssize_t) GetPixelChannels(source); i++)
cristy5c4e2582011-09-11 19:21:03 +00005256 {
cristy5c4e2582011-09-11 19:21:03 +00005257 register ssize_t
5258 j;
5259
cristy5a23c552013-02-13 14:34:28 +00005260 PixelChannel channel=GetPixelChannelChannel(source,i);
5261 PixelTrait traits=GetPixelChannelTraits(source,channel);
5262 PixelTrait destination_traits=GetPixelChannelTraits(destination,
5263 channel);
cristy5c4e2582011-09-11 19:21:03 +00005264 if ((traits == UndefinedPixelTrait) ||
5265 (destination_traits == UndefinedPixelTrait))
5266 continue;
5267 if ((traits & BlendPixelTrait) == 0)
5268 for (j=0; j < 16; j++)
5269 {
5270 alpha[j]=1.0;
cristya19f1d72012-08-07 18:24:38 +00005271 pixels[j]=(double) p[j*GetPixelChannels(source)+i];
cristy5c4e2582011-09-11 19:21:03 +00005272 }
5273 else
5274 for (j=0; j < 16; j++)
5275 {
5276 alpha[j]=QuantumScale*GetPixelAlpha(source,p+j*
5277 GetPixelChannels(source));
5278 pixels[j]=alpha[j]*p[j*GetPixelChannels(source)+i];
5279 }
cristya19f1d72012-08-07 18:24:38 +00005280 SplineWeights((double) (x-x_offset),&cx);
5281 SplineWeights((double) (y-y_offset),&cy);
5282 gamma=((traits & BlendPixelTrait) ? (double) (1.0) :
cristy3e3ec3a2012-11-03 23:11:06 +00005283 PerceptibleReciprocal(cy[0]*(cx[0]*alpha[0]+cx[1]*alpha[1]+cx[2]*
nicolasd32d5e52012-06-12 15:34:10 +00005284 alpha[2]+cx[3]*alpha[3])+cy[1]*(cx[0]*alpha[4]+cx[1]*alpha[5]+cx[2]*
5285 alpha[6]+cx[3]*alpha[7])+cy[2]*(cx[0]*alpha[8]+cx[1]*alpha[9]+cx[2]*
5286 alpha[10]+cx[3]*alpha[11])+cy[3]*(cx[0]*alpha[12]+cx[1]*alpha[13]+
5287 cx[2]*alpha[14]+cx[3]*alpha[15])));
5288 SetPixelChannel(destination,channel,ClampToQuantum(gamma*(cy[0]*(cx[0]*
5289 pixels[0]+cx[1]*pixels[1]+cx[2]*pixels[2]+cx[3]*pixels[3])+cy[1]*
5290 (cx[0]*pixels[4]+cx[1]*pixels[5]+cx[2]*pixels[6]+cx[3]*pixels[7])+
5291 cy[2]*(cx[0]*pixels[8]+cx[1]*pixels[9]+cx[2]*pixels[10]+cx[3]*
5292 pixels[11])+cy[3]*(cx[0]*pixels[12]+cx[1]*pixels[13]+cx[2]*
5293 pixels[14]+cx[3]*pixels[15]))),pixel);
cristy5c4e2582011-09-11 19:21:03 +00005294 }
5295 break;
5296 }
5297 }
5298 return(status);
5299}
5300
5301/*
5302%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5303% %
5304% %
5305% %
cristy9075cdb2011-07-30 01:06:23 +00005306% 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 +00005307% %
5308% %
5309% %
5310%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5311%
cristy884f6002011-07-31 00:51:45 +00005312% InterpolatePixelInfo() applies a pixel interpolation method between a
5313% floating point coordinate and the pixels surrounding that coordinate. No
5314% pixel area resampling, or scaling of the result is performed.
cristy4c08aed2011-07-01 19:47:50 +00005315%
anthonycf4e33d2012-06-08 07:33:23 +00005316% Interpolation is restricted to just RGBKA channels.
5317%
cristy4c08aed2011-07-01 19:47:50 +00005318% The format of the InterpolatePixelInfo method is:
5319%
5320% MagickBooleanType InterpolatePixelInfo(const Image *image,
cristy5c4e2582011-09-11 19:21:03 +00005321% const CacheView *image_view,const PixelInterpolateMethod method,
cristy4c08aed2011-07-01 19:47:50 +00005322% const double x,const double y,PixelInfo *pixel,
5323% ExceptionInfo *exception)
5324%
5325% A description of each parameter follows:
5326%
5327% o image: the image.
5328%
5329% o image_view: the image view.
5330%
5331% o method: the pixel color interpolation method.
5332%
5333% o x,y: A double representing the current (x,y) position of the pixel.
5334%
5335% o pixel: return the interpolated pixel here.
5336%
5337% o exception: return any errors or warnings in this structure.
5338%
5339*/
5340
5341static inline void AlphaBlendPixelInfo(const Image *image,
cristya19f1d72012-08-07 18:24:38 +00005342 const Quantum *pixel,PixelInfo *pixel_info,double *alpha)
cristy4c08aed2011-07-01 19:47:50 +00005343{
cristy8a46d822012-08-28 23:32:39 +00005344 if (image->alpha_trait != BlendPixelTrait)
cristy4c08aed2011-07-01 19:47:50 +00005345 {
5346 *alpha=1.0;
cristya19f1d72012-08-07 18:24:38 +00005347 pixel_info->red=(double) GetPixelRed(image,pixel);
5348 pixel_info->green=(double) GetPixelGreen(image,pixel);
5349 pixel_info->blue=(double) GetPixelBlue(image,pixel);
cristy4c08aed2011-07-01 19:47:50 +00005350 pixel_info->black=0.0;
5351 if (image->colorspace == CMYKColorspace)
cristya19f1d72012-08-07 18:24:38 +00005352 pixel_info->black=(double) GetPixelBlack(image,pixel);
5353 pixel_info->alpha=(double) GetPixelAlpha(image,pixel);
cristy4c08aed2011-07-01 19:47:50 +00005354 return;
5355 }
5356 *alpha=QuantumScale*GetPixelAlpha(image,pixel);
5357 pixel_info->red=(*alpha*GetPixelRed(image,pixel));
5358 pixel_info->green=(*alpha*GetPixelGreen(image,pixel));
5359 pixel_info->blue=(*alpha*GetPixelBlue(image,pixel));
5360 pixel_info->black=0.0;
5361 if (image->colorspace == CMYKColorspace)
5362 pixel_info->black=(*alpha*GetPixelBlack(image,pixel));
cristya19f1d72012-08-07 18:24:38 +00005363 pixel_info->alpha=(double) GetPixelAlpha(image,pixel);
cristy4c08aed2011-07-01 19:47:50 +00005364}
5365
cristy4c08aed2011-07-01 19:47:50 +00005366MagickExport MagickBooleanType InterpolatePixelInfo(const Image *image,
cristy5c4e2582011-09-11 19:21:03 +00005367 const CacheView *image_view,const PixelInterpolateMethod method,
cristy4c08aed2011-07-01 19:47:50 +00005368 const double x,const double y,PixelInfo *pixel,ExceptionInfo *exception)
5369{
5370 MagickBooleanType
5371 status;
5372
cristya19f1d72012-08-07 18:24:38 +00005373 double
cristy4c08aed2011-07-01 19:47:50 +00005374 alpha[16],
5375 gamma;
5376
cristy865d58d2011-07-09 00:44:52 +00005377 PixelInfo
5378 pixels[16];
5379
cristy4c08aed2011-07-01 19:47:50 +00005380 register const Quantum
5381 *p;
5382
cristy50e64b82012-06-22 17:46:19 +00005383 register ssize_t
cristy4c08aed2011-07-01 19:47:50 +00005384 i;
5385
5386 ssize_t
5387 x_offset,
5388 y_offset;
5389
anthonycf4e33d2012-06-08 07:33:23 +00005390 PixelInterpolateMethod
5391 interpolate;
5392
cristy4c08aed2011-07-01 19:47:50 +00005393 assert(image != (Image *) NULL);
5394 assert(image->signature == MagickSignature);
5395 assert(image_view != (CacheView *) NULL);
5396 status=MagickTrue;
5397 x_offset=(ssize_t) floor(x);
5398 y_offset=(ssize_t) floor(y);
anthonycf4e33d2012-06-08 07:33:23 +00005399 interpolate = method;
5400 if ( interpolate == UndefinedInterpolatePixel )
5401 interpolate = image->interpolate;
5402 switch (interpolate)
cristy4c08aed2011-07-01 19:47:50 +00005403 {
anthonycf4e33d2012-06-08 07:33:23 +00005404 case AverageInterpolatePixel: /* nearest 4 neighbours */
5405 case Average9InterpolatePixel: /* nearest 9 neighbours */
5406 case Average16InterpolatePixel: /* nearest 16 neighbours */
cristy4c08aed2011-07-01 19:47:50 +00005407 {
cristyfb122372012-10-17 23:31:21 +00005408 ssize_t
5409 count;
anthonycf4e33d2012-06-08 07:33:23 +00005410
cristyfb122372012-10-17 23:31:21 +00005411 count=2; /* size of the area to average - default nearest 4 */
anthonycf4e33d2012-06-08 07:33:23 +00005412 if (interpolate == Average9InterpolatePixel)
5413 {
5414 count=3;
5415 x_offset=(ssize_t) (floor(x+0.5)-1);
5416 y_offset=(ssize_t) (floor(y+0.5)-1);
5417 }
5418 else if (interpolate == Average16InterpolatePixel)
5419 {
5420 count=4;
5421 x_offset--;
5422 y_offset--;
5423 }
cristy021216a2013-05-20 16:25:51 +00005424 p=GetCacheViewVirtualPixels(image_view,x_offset,y_offset,(size_t) count,
5425 (size_t) count,exception);
cristy4c08aed2011-07-01 19:47:50 +00005426 if (p == (const Quantum *) NULL)
5427 {
5428 status=MagickFalse;
5429 break;
5430 }
cristy4c08aed2011-07-01 19:47:50 +00005431 pixel->red=0.0;
5432 pixel->green=0.0;
5433 pixel->blue=0.0;
cristy4c08aed2011-07-01 19:47:50 +00005434 pixel->black=0.0;
cristy865d58d2011-07-09 00:44:52 +00005435 pixel->alpha=0.0;
anthonycf4e33d2012-06-08 07:33:23 +00005436 count*=count; /* number of pixels - square of size */
cristy50e64b82012-06-22 17:46:19 +00005437 for (i=0; i < (ssize_t) count; i++)
cristy4c08aed2011-07-01 19:47:50 +00005438 {
anthonycf4e33d2012-06-08 07:33:23 +00005439 AlphaBlendPixelInfo(image,p,pixels,alpha);
cristy3e3ec3a2012-11-03 23:11:06 +00005440 gamma=PerceptibleReciprocal(alpha[0]);
cristyfb122372012-10-17 23:31:21 +00005441 pixel->red+=gamma*pixels[0].red;
5442 pixel->green+=gamma*pixels[0].green;
5443 pixel->blue+=gamma*pixels[0].blue;
5444 pixel->black+=gamma*pixels[0].black;
5445 pixel->alpha+=pixels[0].alpha;
anthonycf4e33d2012-06-08 07:33:23 +00005446 p += GetPixelChannels(image);
cristy4c08aed2011-07-01 19:47:50 +00005447 }
anthonycf4e33d2012-06-08 07:33:23 +00005448 gamma=1.0/count; /* average weighting of each pixel in area */
cristyfb122372012-10-17 23:31:21 +00005449 pixel->red*=gamma;
5450 pixel->green*=gamma;
5451 pixel->blue*=gamma;
5452 pixel->black*=gamma;
5453 pixel->alpha*=gamma;
cristy4c08aed2011-07-01 19:47:50 +00005454 break;
5455 }
anthonycf4e33d2012-06-08 07:33:23 +00005456 case BackgroundInterpolatePixel:
5457 {
cristyfb122372012-10-17 23:31:21 +00005458 *pixel=image->background_color; /* Copy PixelInfo Structure */
anthonycf4e33d2012-06-08 07:33:23 +00005459 break;
5460 }
5461 case BilinearInterpolatePixel:
5462 default:
5463 {
5464 PointInfo
5465 delta,
5466 epsilon;
5467
5468 p=GetCacheViewVirtualPixels(image_view,x_offset,y_offset,2,2,exception);
5469 if (p == (const Quantum *) NULL)
5470 {
5471 status=MagickFalse;
5472 break;
5473 }
5474 for (i=0; i < 4L; i++)
5475 AlphaBlendPixelInfo(image,p+i*GetPixelChannels(image),pixels+i,alpha+i);
5476 delta.x=x-x_offset;
5477 delta.y=y-y_offset;
5478 epsilon.x=1.0-delta.x;
5479 epsilon.y=1.0-delta.y;
5480 gamma=((epsilon.y*(epsilon.x*alpha[0]+delta.x*alpha[1])+delta.y*
5481 (epsilon.x*alpha[2]+delta.x*alpha[3])));
cristy3e3ec3a2012-11-03 23:11:06 +00005482 gamma=PerceptibleReciprocal(gamma);
anthonycf4e33d2012-06-08 07:33:23 +00005483 pixel->red=gamma*(epsilon.y*(epsilon.x*pixels[0].red+delta.x*
5484 pixels[1].red)+delta.y*(epsilon.x*pixels[2].red+delta.x*pixels[3].red));
5485 pixel->green=gamma*(epsilon.y*(epsilon.x*pixels[0].green+delta.x*
5486 pixels[1].green)+delta.y*(epsilon.x*pixels[2].green+delta.x*
5487 pixels[3].green));
5488 pixel->blue=gamma*(epsilon.y*(epsilon.x*pixels[0].blue+delta.x*
5489 pixels[1].blue)+delta.y*(epsilon.x*pixels[2].blue+delta.x*
5490 pixels[3].blue));
5491 if (image->colorspace == CMYKColorspace)
5492 pixel->black=gamma*(epsilon.y*(epsilon.x*pixels[0].black+delta.x*
5493 pixels[1].black)+delta.y*(epsilon.x*pixels[2].black+delta.x*
5494 pixels[3].black));
5495 gamma=((epsilon.y*(epsilon.x+delta.x)+delta.y*(epsilon.x+delta.x)));
cristy3e3ec3a2012-11-03 23:11:06 +00005496 gamma=PerceptibleReciprocal(gamma);
anthonycf4e33d2012-06-08 07:33:23 +00005497 pixel->alpha=(epsilon.y*(epsilon.x*pixels[0].alpha+delta.x*
5498 pixels[1].alpha)+delta.y*(epsilon.x*pixels[2].alpha+delta.x*
5499 pixels[3].alpha));
5500 break;
5501 }
5502 case BlendInterpolatePixel:
5503 {
5504 p=GetCacheViewVirtualPixels(image_view,x_offset,y_offset,2,2,exception);
5505 if (p == (const Quantum *) NULL)
5506 {
5507 status=MagickFalse;
5508 break;
5509 }
5510 for (i=0; i < 4L; i++)
5511 AlphaBlendPixelInfo(image,p+i*GetPixelChannels(image),pixels+i,alpha+i);
cristyfb122372012-10-17 23:31:21 +00005512 gamma=1.0; /* number of pixels blended together (its variable) */
5513 for (i=0; i <= 1L; i++)
5514 {
5515 if ((y-y_offset) >= 0.75)
5516 {
5517 alpha[i]=alpha[i+2]; /* take right pixels */
5518 pixels[i]=pixels[i+2];
5519 }
5520 else
5521 if ((y-y_offset) > 0.25)
5522 {
5523 gamma=2.0; /* blend both pixels in row */
5524 alpha[i]+=alpha[i+2]; /* add up alpha weights */
5525 pixels[i].red+=pixels[i+2].red;
5526 pixels[i].green+=pixels[i+2].green;
5527 pixels[i].blue+=pixels[i+2].blue;
5528 pixels[i].black+=pixels[i+2].black;
5529 pixels[i].alpha+=pixels[i+2].alpha;
5530 }
5531 }
5532 if ((x-x_offset) >= 0.75)
5533 {
5534 alpha[0]=alpha[1];
5535 pixels[0]=pixels[1];
anthonycf4e33d2012-06-08 07:33:23 +00005536 }
cristyfb122372012-10-17 23:31:21 +00005537 else
5538 if ((x-x_offset) > 0.25)
5539 {
5540 gamma*=2.0; /* blend both rows */
5541 alpha[0]+= alpha[1]; /* add up alpha weights */
5542 pixels[0].red+=pixels[1].red;
5543 pixels[0].green+=pixels[1].green;
5544 pixels[0].blue+=pixels[1].blue;
5545 pixels[0].black+=pixels[1].black;
5546 pixels[0].alpha+=pixels[1].alpha;
5547 }
5548 gamma=1.0/gamma;
cristy3e3ec3a2012-11-03 23:11:06 +00005549 alpha[0]=PerceptibleReciprocal(alpha[0]);
cristyfb122372012-10-17 23:31:21 +00005550 pixel->red=alpha[0]*pixels[0].red;
5551 pixel->green=alpha[0]*pixels[0].green; /* divide by sum of alpha */
5552 pixel->blue=alpha[0]*pixels[0].blue;
5553 pixel->black=alpha[0]*pixels[0].black;
5554 pixel->alpha=gamma*pixels[0].alpha; /* divide by number of pixels */
anthonycf4e33d2012-06-08 07:33:23 +00005555 break;
5556 }
5557 case CatromInterpolatePixel:
cristy4c08aed2011-07-01 19:47:50 +00005558 {
cristya19f1d72012-08-07 18:24:38 +00005559 double
cristy380a11c2012-06-02 15:15:22 +00005560 cx[4],
5561 cy[4];
cristy4c08aed2011-07-01 19:47:50 +00005562
cristy4c08aed2011-07-01 19:47:50 +00005563 p=GetCacheViewVirtualPixels(image_view,x_offset-1,y_offset-1,4,4,
5564 exception);
5565 if (p == (const Quantum *) NULL)
5566 {
5567 status=MagickFalse;
5568 break;
5569 }
anthonycf4e33d2012-06-08 07:33:23 +00005570 for (i=0; i < 16L; i++)
5571 AlphaBlendPixelInfo(image,p+i*GetPixelChannels(image),pixels+i,alpha+i);
cristya19f1d72012-08-07 18:24:38 +00005572 CatromWeights((double) (x-x_offset),&cx);
5573 CatromWeights((double) (y-y_offset),&cy);
cristyfb122372012-10-17 23:31:21 +00005574 pixel->red=(cy[0]*(cx[0]*pixels[0].red+cx[1]*pixels[1].red+cx[2]*
5575 pixels[2].red+cx[3]*pixels[3].red)+cy[1]*(cx[0]*pixels[4].red+cx[1]*
5576 pixels[5].red+cx[2]*pixels[6].red+cx[3]*pixels[7].red)+cy[2]*(cx[0]*
5577 pixels[8].red+cx[1]*pixels[9].red+cx[2]*pixels[10].red+cx[3]*
5578 pixels[11].red)+cy[3]*(cx[0]*pixels[12].red+cx[1]*pixels[13].red+cx[2]*
5579 pixels[14].red+cx[3]*pixels[15].red));
5580 pixel->green=(cy[0]*(cx[0]*pixels[0].green+cx[1]*pixels[1].green+cx[2]*
5581 pixels[2].green+cx[3]*pixels[3].green)+cy[1]*(cx[0]*pixels[4].green+
5582 cx[1]*pixels[5].green+cx[2]*pixels[6].green+cx[3]*pixels[7].green)+
5583 cy[2]*(cx[0]*pixels[8].green+cx[1]*pixels[9].green+cx[2]*
5584 pixels[10].green+cx[3]*pixels[11].green)+cy[3]*(cx[0]*
5585 pixels[12].green+cx[1]*pixels[13].green+cx[2]*pixels[14].green+cx[3]*
5586 pixels[15].green));
5587 pixel->blue=(cy[0]*(cx[0]*pixels[0].blue+cx[1]*pixels[1].blue+cx[2]*
5588 pixels[2].blue+cx[3]*pixels[3].blue)+cy[1]*(cx[0]*pixels[4].blue+cx[1]*
5589 pixels[5].blue+cx[2]*pixels[6].blue+cx[3]*pixels[7].blue)+cy[2]*(cx[0]*
5590 pixels[8].blue+cx[1]*pixels[9].blue+cx[2]*pixels[10].blue+cx[3]*
5591 pixels[11].blue)+cy[3]*(cx[0]*pixels[12].blue+cx[1]*pixels[13].blue+
5592 cx[2]*pixels[14].blue+cx[3]*pixels[15].blue));
cristy380a11c2012-06-02 15:15:22 +00005593 if (image->colorspace == CMYKColorspace)
cristyfb122372012-10-17 23:31:21 +00005594 pixel->black=(cy[0]*(cx[0]*pixels[0].black+cx[1]*pixels[1].black+cx[2]*
5595 pixels[2].black+cx[3]*pixels[3].black)+cy[1]*(cx[0]*pixels[4].black+
5596 cx[1]*pixels[5].black+cx[2]*pixels[6].black+cx[3]*pixels[7].black)+
5597 cy[2]*(cx[0]*pixels[8].black+cx[1]*pixels[9].black+cx[2]*
5598 pixels[10].black+cx[3]*pixels[11].black)+cy[3]*(cx[0]*
5599 pixels[12].black+cx[1]*pixels[13].black+cx[2]*pixels[14].black+cx[3]*
5600 pixels[15].black));
5601 pixel->alpha=(cy[0]*(cx[0]*pixels[0].alpha+cx[1]*pixels[1].alpha+cx[2]*
5602 pixels[2].alpha+cx[3]*pixels[3].alpha)+cy[1]*(cx[0]*pixels[4].alpha+
5603 cx[1]*pixels[5].alpha+cx[2]*pixels[6].alpha+cx[3]*pixels[7].alpha)+
5604 cy[2]*(cx[0]*pixels[8].alpha+cx[1]*pixels[9].alpha+cx[2]*
5605 pixels[10].alpha+cx[3]*pixels[11].alpha)+cy[3]*(cx[0]*pixels[12].alpha+
5606 cx[1]*pixels[13].alpha+cx[2]*pixels[14].alpha+cx[3]*pixels[15].alpha));
cristy4c08aed2011-07-01 19:47:50 +00005607 break;
5608 }
cristy4c08aed2011-07-01 19:47:50 +00005609 case IntegerInterpolatePixel:
5610 {
5611 p=GetCacheViewVirtualPixels(image_view,x_offset,y_offset,1,1,exception);
5612 if (p == (const Quantum *) NULL)
5613 {
5614 status=MagickFalse;
5615 break;
5616 }
cristy803640d2011-11-17 02:11:32 +00005617 GetPixelInfoPixel(image,p,pixel);
cristy4c08aed2011-07-01 19:47:50 +00005618 break;
5619 }
5620 case MeshInterpolatePixel:
5621 {
5622 PointInfo
5623 delta,
5624 luminance;
5625
cristy94ea1632011-07-30 20:40:25 +00005626 p=GetCacheViewVirtualPixels(image_view,x_offset,y_offset,2,2,exception);
cristy4c08aed2011-07-01 19:47:50 +00005627 if (p == (const Quantum *) NULL)
5628 {
5629 status=MagickFalse;
5630 break;
5631 }
cristy94ea1632011-07-30 20:40:25 +00005632 delta.x=x-x_offset;
5633 delta.y=y-y_offset;
cristy884f6002011-07-31 00:51:45 +00005634 luminance.x=GetPixelLuminance(image,p)-(double)
cristy94ea1632011-07-30 20:40:25 +00005635 GetPixelLuminance(image,p+3*GetPixelChannels(image));
cristy28474bf2011-09-11 23:32:52 +00005636 luminance.y=GetPixelLuminance(image,p+GetPixelChannels(image))-(double)
cristy94ea1632011-07-30 20:40:25 +00005637 GetPixelLuminance(image,p+2*GetPixelChannels(image));
cristy5ce8df82011-07-07 14:52:23 +00005638 AlphaBlendPixelInfo(image,p,pixels+0,alpha+0);
cristy28474bf2011-09-11 23:32:52 +00005639 AlphaBlendPixelInfo(image,p+GetPixelChannels(image),pixels+1,alpha+1);
cristyed231572011-07-14 02:18:59 +00005640 AlphaBlendPixelInfo(image,p+2*GetPixelChannels(image),pixels+2,alpha+2);
5641 AlphaBlendPixelInfo(image,p+3*GetPixelChannels(image),pixels+3,alpha+3);
cristy4c08aed2011-07-01 19:47:50 +00005642 if (fabs(luminance.x) < fabs(luminance.y))
5643 {
5644 /*
5645 Diagonal 0-3 NW-SE.
5646 */
5647 if (delta.x <= delta.y)
5648 {
5649 /*
cristy94ea1632011-07-30 20:40:25 +00005650 Bottom-left triangle (pixel: 2, diagonal: 0-3).
cristy4c08aed2011-07-01 19:47:50 +00005651 */
5652 delta.y=1.0-delta.y;
5653 gamma=MeshInterpolate(&delta,alpha[2],alpha[3],alpha[0]);
cristy3e3ec3a2012-11-03 23:11:06 +00005654 gamma=PerceptibleReciprocal(gamma);
cristy4c08aed2011-07-01 19:47:50 +00005655 pixel->red=gamma*MeshInterpolate(&delta,pixels[2].red,
5656 pixels[3].red,pixels[0].red);
5657 pixel->green=gamma*MeshInterpolate(&delta,pixels[2].green,
5658 pixels[3].green,pixels[0].green);
5659 pixel->blue=gamma*MeshInterpolate(&delta,pixels[2].blue,
5660 pixels[3].blue,pixels[0].blue);
cristy4c08aed2011-07-01 19:47:50 +00005661 if (image->colorspace == CMYKColorspace)
5662 pixel->black=gamma*MeshInterpolate(&delta,pixels[2].black,
5663 pixels[3].black,pixels[0].black);
cristy94ea1632011-07-30 20:40:25 +00005664 gamma=MeshInterpolate(&delta,1.0,1.0,1.0);
cristy865d58d2011-07-09 00:44:52 +00005665 pixel->alpha=gamma*MeshInterpolate(&delta,pixels[2].alpha,
5666 pixels[3].alpha,pixels[0].alpha);
cristy4c08aed2011-07-01 19:47:50 +00005667 }
5668 else
5669 {
5670 /*
cristy94ea1632011-07-30 20:40:25 +00005671 Top-right triangle (pixel:1 , diagonal: 0-3).
cristy4c08aed2011-07-01 19:47:50 +00005672 */
5673 delta.x=1.0-delta.x;
5674 gamma=MeshInterpolate(&delta,alpha[1],alpha[0],alpha[3]);
cristy3e3ec3a2012-11-03 23:11:06 +00005675 gamma=PerceptibleReciprocal(gamma);
cristy4c08aed2011-07-01 19:47:50 +00005676 pixel->red=gamma*MeshInterpolate(&delta,pixels[1].red,
5677 pixels[0].red,pixels[3].red);
5678 pixel->green=gamma*MeshInterpolate(&delta,pixels[1].green,
5679 pixels[0].green,pixels[3].green);
5680 pixel->blue=gamma*MeshInterpolate(&delta,pixels[1].blue,
5681 pixels[0].blue,pixels[3].blue);
cristy4c08aed2011-07-01 19:47:50 +00005682 if (image->colorspace == CMYKColorspace)
5683 pixel->black=gamma*MeshInterpolate(&delta,pixels[1].black,
5684 pixels[0].black,pixels[3].black);
cristy94ea1632011-07-30 20:40:25 +00005685 gamma=MeshInterpolate(&delta,1.0,1.0,1.0);
cristy865d58d2011-07-09 00:44:52 +00005686 pixel->alpha=gamma*MeshInterpolate(&delta,pixels[1].alpha,
5687 pixels[0].alpha,pixels[3].alpha);
cristy4c08aed2011-07-01 19:47:50 +00005688 }
5689 }
5690 else
5691 {
5692 /*
5693 Diagonal 1-2 NE-SW.
5694 */
5695 if (delta.x <= (1.0-delta.y))
5696 {
5697 /*
cristy94ea1632011-07-30 20:40:25 +00005698 Top-left triangle (pixel: 0, diagonal: 1-2).
cristy4c08aed2011-07-01 19:47:50 +00005699 */
5700 gamma=MeshInterpolate(&delta,alpha[0],alpha[1],alpha[2]);
cristy3e3ec3a2012-11-03 23:11:06 +00005701 gamma=PerceptibleReciprocal(gamma);
cristy4c08aed2011-07-01 19:47:50 +00005702 pixel->red=gamma*MeshInterpolate(&delta,pixels[0].red,
5703 pixels[1].red,pixels[2].red);
5704 pixel->green=gamma*MeshInterpolate(&delta,pixels[0].green,
5705 pixels[1].green,pixels[2].green);
5706 pixel->blue=gamma*MeshInterpolate(&delta,pixels[0].blue,
5707 pixels[1].blue,pixels[2].blue);
cristy4c08aed2011-07-01 19:47:50 +00005708 if (image->colorspace == CMYKColorspace)
5709 pixel->black=gamma*MeshInterpolate(&delta,pixels[0].black,
5710 pixels[1].black,pixels[2].black);
cristy94ea1632011-07-30 20:40:25 +00005711 gamma=MeshInterpolate(&delta,1.0,1.0,1.0);
cristy865d58d2011-07-09 00:44:52 +00005712 pixel->alpha=gamma*MeshInterpolate(&delta,pixels[0].alpha,
5713 pixels[1].alpha,pixels[2].alpha);
cristy4c08aed2011-07-01 19:47:50 +00005714 }
5715 else
5716 {
5717 /*
5718 Bottom-right triangle (pixel: 3, diagonal: 1-2).
5719 */
5720 delta.x=1.0-delta.x;
5721 delta.y=1.0-delta.y;
5722 gamma=MeshInterpolate(&delta,alpha[3],alpha[2],alpha[1]);
cristy3e3ec3a2012-11-03 23:11:06 +00005723 gamma=PerceptibleReciprocal(gamma);
cristy4c08aed2011-07-01 19:47:50 +00005724 pixel->red=gamma*MeshInterpolate(&delta,pixels[3].red,
5725 pixels[2].red,pixels[1].red);
5726 pixel->green=gamma*MeshInterpolate(&delta,pixels[3].green,
5727 pixels[2].green,pixels[1].green);
5728 pixel->blue=gamma*MeshInterpolate(&delta,pixels[3].blue,
5729 pixels[2].blue,pixels[1].blue);
cristy4c08aed2011-07-01 19:47:50 +00005730 if (image->colorspace == CMYKColorspace)
5731 pixel->black=gamma*MeshInterpolate(&delta,pixels[3].black,
5732 pixels[2].black,pixels[1].black);
cristy94ea1632011-07-30 20:40:25 +00005733 gamma=MeshInterpolate(&delta,1.0,1.0,1.0);
cristy865d58d2011-07-09 00:44:52 +00005734 pixel->alpha=gamma*MeshInterpolate(&delta,pixels[3].alpha,
5735 pixels[2].alpha,pixels[1].alpha);
cristy4c08aed2011-07-01 19:47:50 +00005736 }
5737 }
5738 break;
5739 }
anthonycf4e33d2012-06-08 07:33:23 +00005740 case NearestInterpolatePixel:
cristy4c08aed2011-07-01 19:47:50 +00005741 {
anthonycf4e33d2012-06-08 07:33:23 +00005742 x_offset=(ssize_t) floor(x+0.5);
5743 y_offset=(ssize_t) floor(y+0.5);
5744 p=GetCacheViewVirtualPixels(image_view,x_offset,y_offset,1,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00005745 if (p == (const Quantum *) NULL)
5746 {
5747 status=MagickFalse;
5748 break;
5749 }
cristy803640d2011-11-17 02:11:32 +00005750 GetPixelInfoPixel(image,p,pixel);
cristy4c08aed2011-07-01 19:47:50 +00005751 break;
5752 }
5753 case SplineInterpolatePixel:
5754 {
cristya19f1d72012-08-07 18:24:38 +00005755 double
nicolasd32d5e52012-06-12 15:34:10 +00005756 cx[4],
5757 cy[4];
cristy4c08aed2011-07-01 19:47:50 +00005758
5759 p=GetCacheViewVirtualPixels(image_view,x_offset-1,y_offset-1,4,4,
5760 exception);
5761 if (p == (const Quantum *) NULL)
5762 {
5763 status=MagickFalse;
5764 break;
5765 }
anthonycf4e33d2012-06-08 07:33:23 +00005766 for (i=0; i < 16L; i++)
5767 AlphaBlendPixelInfo(image,p+i*GetPixelChannels(image),pixels+i,alpha+i);
cristya19f1d72012-08-07 18:24:38 +00005768 SplineWeights((double) (x-x_offset),&cx);
5769 SplineWeights((double) (y-y_offset),&cy);
cristyfb122372012-10-17 23:31:21 +00005770 pixel->red=(cy[0]*(cx[0]*pixels[0].red+cx[1]*pixels[1].red+cx[2]*
5771 pixels[2].red+cx[3]*pixels[3].red)+cy[1]*(cx[0]*pixels[4].red+cx[1]*
5772 pixels[5].red+cx[2]*pixels[6].red+cx[3]*pixels[7].red)+cy[2]*(cx[0]*
5773 pixels[8].red+cx[1]*pixels[9].red+cx[2]*pixels[10].red+cx[3]*
5774 pixels[11].red)+cy[3]*(cx[0]*pixels[12].red+cx[1]*pixels[13].red+cx[2]*
5775 pixels[14].red+cx[3]*pixels[15].red));
5776 pixel->green=(cy[0]*(cx[0]*pixels[0].green+cx[1]*pixels[1].green+cx[2]*
5777 pixels[2].green+cx[3]*pixels[3].green)+cy[1]*(cx[0]*pixels[4].green+
5778 cx[1]*pixels[5].green+cx[2]*pixels[6].green+cx[3]*pixels[7].green)+
5779 cy[2]*(cx[0]*pixels[8].green+cx[1]*pixels[9].green+cx[2]*
5780 pixels[10].green+cx[3]*pixels[11].green)+cy[3]*(cx[0]*pixels[12].green+
5781 cx[1]*pixels[13].green+cx[2]*pixels[14].green+cx[3]*pixels[15].green));
5782 pixel->blue=(cy[0]*(cx[0]*pixels[0].blue+cx[1]*pixels[1].blue+cx[2]*
5783 pixels[2].blue+cx[3]*pixels[3].blue)+cy[1]*(cx[0]*pixels[4].blue+cx[1]*
5784 pixels[5].blue+cx[2]*pixels[6].blue+cx[3]*pixels[7].blue)+cy[2]*(cx[0]*
5785 pixels[8].blue+cx[1]*pixels[9].blue+cx[2]*pixels[10].blue+cx[3]*
5786 pixels[11].blue)+cy[3]*(cx[0]*pixels[12].blue+cx[1]*pixels[13].blue+
5787 cx[2]*pixels[14].blue+cx[3]*pixels[15].blue));
nicolasd32d5e52012-06-12 15:34:10 +00005788 if (image->colorspace == CMYKColorspace)
cristyfb122372012-10-17 23:31:21 +00005789 pixel->black=(cy[0]*(cx[0]*pixels[0].black+cx[1]*pixels[1].black+cx[2]*
5790 pixels[2].black+cx[3]*pixels[3].black)+cy[1]*(cx[0]*pixels[4].black+
5791 cx[1]*pixels[5].black+cx[2]*pixels[6].black+cx[3]*pixels[7].black)+
5792 cy[2]*(cx[0]*pixels[8].black+cx[1]*pixels[9].black+cx[2]*
5793 pixels[10].black+cx[3]*pixels[11].black)+cy[3]*(cx[0]*
5794 pixels[12].black+cx[1]*pixels[13].black+cx[2]*pixels[14].black+cx[3]*
5795 pixels[15].black));
5796 pixel->alpha=(cy[0]*(cx[0]*pixels[0].alpha+cx[1]*pixels[1].alpha+cx[2]*
5797 pixels[2].alpha+cx[3]*pixels[3].alpha)+cy[1]*(cx[0]*pixels[4].alpha+
5798 cx[1]*pixels[5].alpha+cx[2]*pixels[6].alpha+cx[3]*pixels[7].alpha)+
5799 cy[2]*(cx[0]*pixels[8].alpha+cx[1]*pixels[9].alpha+cx[2]*
5800 pixels[10].alpha+cx[3]*pixels[11].alpha)+cy[3]*(cx[0]*pixels[12].alpha+
5801 cx[1]*pixels[13].alpha+cx[2]*pixels[14].alpha+cx[3]*pixels[15].alpha));
cristy4c08aed2011-07-01 19:47:50 +00005802 break;
5803 }
5804 }
5805 return(status);
5806}
5807
5808/*
5809%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5810% %
5811% %
5812% %
5813+ I s F u z z y E q u i v a l e n c e P i x e l %
5814% %
5815% %
5816% %
5817%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5818%
5819% IsFuzzyEquivalencePixel() returns MagickTrue if the distance between two
5820% pixels is less than the specified distance in a linear three (or four)u
5821% dimensional color space.
5822%
5823% The format of the IsFuzzyEquivalencePixel method is:
5824%
cristye4a40472011-12-22 02:56:19 +00005825% void IsFuzzyEquivalencePixel(const Image *source,const Quantum *p,
5826% const Image *destination,const Quantum *q)
cristy4c08aed2011-07-01 19:47:50 +00005827%
5828% A description of each parameter follows:
5829%
cristye4a40472011-12-22 02:56:19 +00005830% o source: the source image.
cristy4c08aed2011-07-01 19:47:50 +00005831%
5832% o p: Pixel p.
5833%
cristye4a40472011-12-22 02:56:19 +00005834% o destination: the destination image.
5835%
cristy4c08aed2011-07-01 19:47:50 +00005836% o q: Pixel q.
5837%
5838*/
cristye4a40472011-12-22 02:56:19 +00005839MagickExport MagickBooleanType IsFuzzyEquivalencePixel(const Image *source,
5840 const Quantum *p,const Image *destination,const Quantum *q)
cristy4c08aed2011-07-01 19:47:50 +00005841{
cristya19f1d72012-08-07 18:24:38 +00005842 double
cristy4c08aed2011-07-01 19:47:50 +00005843 fuzz,
5844 pixel;
5845
cristya19f1d72012-08-07 18:24:38 +00005846 register double
cristy4c08aed2011-07-01 19:47:50 +00005847 distance,
5848 scale;
5849
cristya19f1d72012-08-07 18:24:38 +00005850 fuzz=MagickMax(source->fuzz,(double) MagickSQ1_2)*MagickMax(
5851 destination->fuzz,(double) MagickSQ1_2);
cristy4c08aed2011-07-01 19:47:50 +00005852 scale=1.0;
5853 distance=0.0;
cristy8a46d822012-08-28 23:32:39 +00005854 if (source->alpha_trait == BlendPixelTrait)
cristy4c08aed2011-07-01 19:47:50 +00005855 {
5856 /*
5857 Transparencies are involved - set alpha distance
5858 */
cristy70e9f682013-03-12 22:31:22 +00005859 pixel=GetPixelAlpha(source,p)-(double) GetPixelAlpha(destination,q);
cristy4c08aed2011-07-01 19:47:50 +00005860 distance=pixel*pixel;
5861 if (distance > fuzz)
5862 return(MagickFalse);
5863 /*
5864 Generate a alpha scaling factor to generate a 4D cone on colorspace
5865 Note that if one color is transparent, distance has no color component.
5866 */
cristye4a40472011-12-22 02:56:19 +00005867 scale=QuantumScale*GetPixelAlpha(source,p);
5868 scale*=QuantumScale*GetPixelAlpha(destination,q);
cristy4c08aed2011-07-01 19:47:50 +00005869 if (scale <= MagickEpsilon)
5870 return(MagickTrue);
5871 }
5872 /*
5873 RGB or CMY color cube
5874 */
5875 distance*=3.0; /* rescale appropriately */
5876 fuzz*=3.0;
cristya19f1d72012-08-07 18:24:38 +00005877 pixel=GetPixelRed(source,p)-(double) GetPixelRed(destination,q);
cristye4a40472011-12-22 02:56:19 +00005878 if ((source->colorspace == HSLColorspace) ||
5879 (source->colorspace == HSBColorspace) ||
5880 (source->colorspace == HWBColorspace))
cristy4c08aed2011-07-01 19:47:50 +00005881 {
5882 /*
5883 Compute an arc distance for hue. It should be a vector angle of
5884 'S'/'W' length with 'L'/'B' forming appropriate cones.
5885 */
5886 if (fabs((double) pixel) > (QuantumRange/2))
5887 pixel-=QuantumRange;
5888 pixel*=2;
5889 }
5890 distance+=scale*pixel*pixel;
5891 if (distance > fuzz)
5892 return(MagickFalse);
cristya19f1d72012-08-07 18:24:38 +00005893 pixel=GetPixelGreen(source,p)-(double) GetPixelGreen(destination,q);
cristy4c08aed2011-07-01 19:47:50 +00005894 distance+=scale*pixel*pixel;
5895 if (distance > fuzz)
5896 return(MagickFalse);
cristya19f1d72012-08-07 18:24:38 +00005897 pixel=GetPixelBlue(source,p)-(double) GetPixelBlue(destination,q);
cristy4c08aed2011-07-01 19:47:50 +00005898 distance+=scale*pixel*pixel;
5899 if (distance > fuzz)
5900 return(MagickFalse);
5901 return(MagickTrue);
5902}
5903
5904/*
5905%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5906% %
5907% %
5908% %
5909+ 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 %
5910% %
5911% %
5912% %
5913%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5914%
5915% IsFuzzyEquivalencePixelInfo() returns true if the distance between two
5916% colors is less than the specified distance in a linear three (or four)
5917% dimensional color space.
5918%
cristy5f95f4f2011-10-23 01:01:01 +00005919% This implements the equivalent of:
5920% fuzz < sqrt(color_distance^2 * u.a*v.a + alpha_distance^2)
cristy4c08aed2011-07-01 19:47:50 +00005921%
5922% Which produces a multi-dimensional cone for that colorspace along the
5923% transparency vector.
5924%
cristy5f95f4f2011-10-23 01:01:01 +00005925% For example for an RGB:
cristy4c08aed2011-07-01 19:47:50 +00005926% color_distance^2 = ( (u.r-v.r)^2 + (u.g-v.g)^2 + (u.b-v.b)^2 ) / 3
5927%
5928% See http://www.imagemagick.org/Usage/bugs/fuzz_distance/
5929%
5930% Hue colorspace distances need more work. Hue is not a distance, it is an
5931% angle!
5932%
5933% A check that q is in the same color space as p should be made and the
5934% appropriate mapping made. -- Anthony Thyssen 8 December 2010
5935%
5936% The format of the IsFuzzyEquivalencePixelInfo method is:
5937%
5938% MagickBooleanType IsFuzzyEquivalencePixelInfo(const PixelInfo *p,
5939% const PixelInfo *q)
5940%
5941% A description of each parameter follows:
5942%
5943% o p: Pixel p.
5944%
5945% o q: Pixel q.
5946%
5947*/
5948MagickExport MagickBooleanType IsFuzzyEquivalencePixelInfo(const PixelInfo *p,
5949 const PixelInfo *q)
5950{
cristya19f1d72012-08-07 18:24:38 +00005951 double
cristy4c08aed2011-07-01 19:47:50 +00005952 fuzz,
5953 pixel;
5954
cristya19f1d72012-08-07 18:24:38 +00005955 register double
cristy4c08aed2011-07-01 19:47:50 +00005956 scale,
5957 distance;
5958
5959 if ((p->fuzz == 0.0) && (q->fuzz == 0.0))
5960 return(IsPixelInfoEquivalent(p,q));
5961 if (p->fuzz == 0.0)
cristy24dc9722013-05-20 16:02:22 +00005962 fuzz=MagickMax(q->fuzz,(double) MagickSQ1_2)*MagickMax(q->fuzz,MagickSQ1_2);
cristy4c08aed2011-07-01 19:47:50 +00005963 else if (q->fuzz == 0.0)
cristy24dc9722013-05-20 16:02:22 +00005964 fuzz=MagickMax(p->fuzz,(double) MagickSQ1_2)*MagickMax(p->fuzz,MagickSQ1_2);
cristy4c08aed2011-07-01 19:47:50 +00005965 else
cristy24dc9722013-05-20 16:02:22 +00005966 fuzz=MagickMax(p->fuzz,(double) MagickSQ1_2)*MagickMax(q->fuzz,MagickSQ1_2);
cristy4c08aed2011-07-01 19:47:50 +00005967 scale=1.0;
5968 distance=0.0;
cristy24dc9722013-05-20 16:02:22 +00005969 if ((p->alpha_trait == BlendPixelTrait) ||
5970 (q->alpha_trait == BlendPixelTrait))
cristy4c08aed2011-07-01 19:47:50 +00005971 {
5972 /*
5973 Transparencies are involved - set alpha distance.
5974 */
cristy8a46d822012-08-28 23:32:39 +00005975 pixel=(p->alpha_trait == BlendPixelTrait ? p->alpha : OpaqueAlpha)-
5976 (q->alpha_trait == BlendPixelTrait ? q->alpha : OpaqueAlpha);
cristy4c08aed2011-07-01 19:47:50 +00005977 distance=pixel*pixel;
5978 if (distance > fuzz)
5979 return(MagickFalse);
5980 /*
5981 Generate a alpha scaling factor to generate a 4D cone on colorspace.
cristy5f95f4f2011-10-23 01:01:01 +00005982 If one color is transparent, distance has no color component.
cristy4c08aed2011-07-01 19:47:50 +00005983 */
cristy8a46d822012-08-28 23:32:39 +00005984 if (p->alpha_trait == BlendPixelTrait)
cristy4c08aed2011-07-01 19:47:50 +00005985 scale=(QuantumScale*p->alpha);
cristy8a46d822012-08-28 23:32:39 +00005986 if (q->alpha_trait == BlendPixelTrait)
cristy4c08aed2011-07-01 19:47:50 +00005987 scale*=(QuantumScale*q->alpha);
5988 if (scale <= MagickEpsilon )
5989 return(MagickTrue);
5990 }
5991 /*
5992 CMYK create a CMY cube with a multi-dimensional cone toward black.
5993 */
5994 if (p->colorspace == CMYKColorspace)
5995 {
5996 pixel=p->black-q->black;
5997 distance+=pixel*pixel*scale;
5998 if (distance > fuzz)
5999 return(MagickFalse);
cristya19f1d72012-08-07 18:24:38 +00006000 scale*=(double) (QuantumScale*(QuantumRange-p->black));
6001 scale*=(double) (QuantumScale*(QuantumRange-q->black));
cristy4c08aed2011-07-01 19:47:50 +00006002 }
6003 /*
6004 RGB or CMY color cube.
6005 */
6006 distance*=3.0; /* rescale appropriately */
6007 fuzz*=3.0;
6008 pixel=p->red-q->red;
6009 if ((p->colorspace == HSLColorspace) || (p->colorspace == HSBColorspace) ||
6010 (p->colorspace == HWBColorspace))
6011 {
cristy5f95f4f2011-10-23 01:01:01 +00006012 /*
6013 This calculates a arc distance for hue-- it should be a vector angle
6014 of 'S'/'W' length with 'L'/'B' forming appropriate cones. In other
6015 words this is a hack - Anthony.
cristy4c08aed2011-07-01 19:47:50 +00006016 */
6017 if (fabs((double) pixel) > (QuantumRange/2))
6018 pixel-=QuantumRange;
6019 pixel*=2;
6020 }
6021 distance+=pixel*pixel*scale;
6022 if (distance > fuzz)
6023 return(MagickFalse);
6024 pixel=p->green-q->green;
6025 distance+=pixel*pixel*scale;
6026 if (distance > fuzz)
6027 return(MagickFalse);
6028 pixel=p->blue-q->blue;
6029 distance+=pixel*pixel*scale;
6030 if (distance > fuzz)
6031 return(MagickFalse);
6032 return(MagickTrue);
6033}
6034
6035/*
6036%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6037% %
6038% %
6039% %
cristy7ae16542013-05-15 22:41:24 +00006040% S e t P i x e l C h a n n e l M a s k %
cristy2b9582a2011-07-04 17:38:56 +00006041% %
6042% %
6043% %
6044%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6045%
cristy7ae16542013-05-15 22:41:24 +00006046% SetPixelChannelMask() sets the pixel channel map from the specified channel
6047% mask.
cristy2b9582a2011-07-04 17:38:56 +00006048%
cristycf1296e2012-08-26 23:40:49 +00006049% The format of the SetPixelChannelMask method is:
cristy2b9582a2011-07-04 17:38:56 +00006050%
cristycf1296e2012-08-26 23:40:49 +00006051% void SetPixelChannelMask(Image *image,const ChannelType channel_mask)
cristy2b9582a2011-07-04 17:38:56 +00006052%
6053% A description of each parameter follows:
6054%
6055% o image: the image.
6056%
cristydfdb19e2012-03-21 22:22:24 +00006057% o channel_mask: the channel mask.
cristy2b9582a2011-07-04 17:38:56 +00006058%
6059*/
cristycf1296e2012-08-26 23:40:49 +00006060MagickExport void SetPixelChannelMask(Image *image,
cristy07a67852011-08-26 13:25:03 +00006061 const ChannelType channel_mask)
cristy2b9582a2011-07-04 17:38:56 +00006062{
cristy6a917d62011-08-24 17:31:30 +00006063#define GetChannelBit(mask,bit) (((size_t) (mask) >> (size_t) (bit)) & 0x01)
cristydafd2872011-07-24 22:06:13 +00006064
cristy2b9582a2011-07-04 17:38:56 +00006065 register ssize_t
6066 i;
6067
cristy177e41c2012-04-15 15:08:25 +00006068 if (image->debug != MagickFalse)
6069 (void) LogMagickEvent(PixelEvent,GetMagickModule(),"%s[%08x]", \
6070 image->filename,channel_mask); \
cristy3c309812011-11-08 02:40:43 +00006071 image->channel_mask=channel_mask;
cristydafd2872011-07-24 22:06:13 +00006072 for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
cristye2a912b2011-12-05 20:02:07 +00006073 {
cristy5a23c552013-02-13 14:34:28 +00006074 PixelChannel channel=GetPixelChannelChannel(image,i);
cristy297e3a42012-08-26 21:27:29 +00006075 SetPixelChannelTraits(image,channel,
cristye2a912b2011-12-05 20:02:07 +00006076 GetChannelBit(channel_mask,channel) == 0 ? CopyPixelTrait :
cristy8a46d822012-08-28 23:32:39 +00006077 image->alpha_trait != BlendPixelTrait || (channel == AlphaPixelChannel) ?
6078 UpdatePixelTrait : (PixelTrait) (UpdatePixelTrait | image->alpha_trait));
cristye2a912b2011-12-05 20:02:07 +00006079 }
cristy1685e722011-09-06 00:04:19 +00006080 if (image->storage_class == PseudoClass)
cristy297e3a42012-08-26 21:27:29 +00006081 SetPixelChannelTraits(image,IndexPixelChannel,CopyPixelTrait);
cristy883fde12013-04-08 00:50:13 +00006082 if (image->read_mask != MagickFalse)
6083 SetPixelChannelTraits(image,ReadMaskPixelChannel,CopyPixelTrait);
6084 if (image->write_mask != MagickFalse)
6085 SetPixelChannelTraits(image,WriteMaskPixelChannel,CopyPixelTrait);
cristy6dcb9b82011-10-23 23:21:25 +00006086 if (image->debug != MagickFalse)
6087 LogPixelChannels(image);
cristy2b9582a2011-07-04 17:38:56 +00006088}
6089
6090/*
6091%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6092% %
6093% %
6094% %
cristy322d07d2012-03-18 21:17:23 +00006095% S e t P i x e l M e t a C h a n n e l s %
6096% %
6097% %
6098% %
6099%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6100%
6101% SetPixelMetaChannels() sets the image meta channels.
6102%
6103% The format of the SetPixelMetaChannels method is:
6104%
6105% MagickBooleanType SetPixelMetaChannels(Image *image,
6106% const size_t number_meta_channels,ExceptionInfo *exception)
6107%
6108% A description of each parameter follows:
6109%
6110% o image: the image.
6111%
6112% o number_meta_channels: the number of meta channels.
6113%
6114% o exception: return any errors or warnings in this structure.
6115%
6116*/
6117MagickExport MagickBooleanType SetPixelMetaChannels(Image *image,
6118 const size_t number_meta_channels,ExceptionInfo *exception)
6119{
6120 image->number_meta_channels=number_meta_channels;
6121 return(SyncImagePixelCache(image,exception));
6122}