blob: 14d2523a11fb77e97883595032d3e2ef56e7789f [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 %
cristyde984cd2013-12-01 14:49:27 +000015% Cristy %
cristy4c08aed2011-07-01 19:47:50 +000016% October 1998 %
17% %
18% %
cristyfe676ee2013-11-18 13:03:38 +000019% Copyright 1999-2014 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 {
cristy58ee5012013-05-26 23:58:44 +00001469 *q=ScaleQuantumToLongLong(ClampToQuantum(
1470 GetPixelIntensity(image,p)));
cristye5370942012-01-06 03:49:31 +00001471 break;
1472 }
1473 default:
1474 break;
1475 }
1476 q++;
1477 }
1478 p+=GetPixelChannels(image);
1479 }
1480 }
1481}
1482
cristy2dc655d2012-07-05 13:16:28 +00001483static void ExportQuantumPixel(Image *image,const RectangleInfo *roi,
cristy46f4be22012-01-07 00:26:39 +00001484 const char *restrict map,const QuantumType *quantum_map,void *pixels,
1485 ExceptionInfo *exception)
cristye5370942012-01-06 03:49:31 +00001486{
1487 register const Quantum
1488 *restrict p;
1489
1490 register Quantum
cristy3fe11452012-01-09 01:27:42 +00001491 *restrict q;
cristye5370942012-01-06 03:49:31 +00001492
1493 register ssize_t
1494 x;
1495
cristy14d71292012-05-20 16:48:13 +00001496 size_t
1497 length;
1498
cristye5370942012-01-06 03:49:31 +00001499 ssize_t
1500 y;
1501
1502 q=(Quantum *) pixels;
1503 if (LocaleCompare(map,"BGR") == 0)
1504 {
cristycafe0412012-01-10 13:29:58 +00001505 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00001506 {
cristycafe0412012-01-10 13:29:58 +00001507 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00001508 if (p == (const Quantum *) NULL)
1509 break;
cristycafe0412012-01-10 13:29:58 +00001510 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00001511 {
1512 *q++=GetPixelBlue(image,p);
1513 *q++=GetPixelGreen(image,p);
1514 *q++=GetPixelRed(image,p);
1515 p+=GetPixelChannels(image);
1516 }
1517 }
1518 return;
1519 }
1520 if (LocaleCompare(map,"BGRA") == 0)
1521 {
cristycafe0412012-01-10 13:29:58 +00001522 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00001523 {
cristycafe0412012-01-10 13:29:58 +00001524 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00001525 if (p == (const Quantum *) NULL)
1526 break;
cristycafe0412012-01-10 13:29:58 +00001527 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00001528 {
1529 *q++=GetPixelBlue(image,p);
1530 *q++=GetPixelGreen(image,p);
1531 *q++=GetPixelRed(image,p);
1532 *q++=(Quantum) (GetPixelAlpha(image,p));
1533 p+=GetPixelChannels(image);
1534 }
1535 }
1536 return;
1537 }
1538 if (LocaleCompare(map,"BGRP") == 0)
1539 {
cristycafe0412012-01-10 13:29:58 +00001540 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00001541 {
cristycafe0412012-01-10 13:29:58 +00001542 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00001543 if (p == (const Quantum *) NULL)
1544 break;
cristycafe0412012-01-10 13:29:58 +00001545 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00001546 {
1547 *q++=GetPixelBlue(image,p);
1548 *q++=GetPixelGreen(image,p);
1549 *q++=GetPixelRed(image,p);
1550 *q++=(Quantum) 0;
1551 p+=GetPixelChannels(image);
1552 }
1553 }
1554 return;
1555 }
1556 if (LocaleCompare(map,"I") == 0)
1557 {
cristycafe0412012-01-10 13:29:58 +00001558 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00001559 {
cristycafe0412012-01-10 13:29:58 +00001560 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00001561 if (p == (const Quantum *) NULL)
1562 break;
cristycafe0412012-01-10 13:29:58 +00001563 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00001564 {
cristy70e9f682013-03-12 22:31:22 +00001565 *q++=ClampToQuantum(GetPixelIntensity(image,p));
cristye5370942012-01-06 03:49:31 +00001566 p+=GetPixelChannels(image);
1567 }
1568 }
1569 return;
1570 }
1571 if (LocaleCompare(map,"RGB") == 0)
1572 {
cristycafe0412012-01-10 13:29:58 +00001573 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00001574 {
cristycafe0412012-01-10 13:29:58 +00001575 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00001576 if (p == (const Quantum *) NULL)
1577 break;
cristycafe0412012-01-10 13:29:58 +00001578 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00001579 {
1580 *q++=GetPixelRed(image,p);
1581 *q++=GetPixelGreen(image,p);
1582 *q++=GetPixelBlue(image,p);
1583 p+=GetPixelChannels(image);
1584 }
1585 }
1586 return;
1587 }
1588 if (LocaleCompare(map,"RGBA") == 0)
1589 {
cristycafe0412012-01-10 13:29:58 +00001590 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00001591 {
cristycafe0412012-01-10 13:29:58 +00001592 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00001593 if (p == (const Quantum *) NULL)
1594 break;
cristycafe0412012-01-10 13:29:58 +00001595 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00001596 {
1597 *q++=GetPixelRed(image,p);
1598 *q++=GetPixelGreen(image,p);
1599 *q++=GetPixelBlue(image,p);
1600 *q++=(Quantum) (GetPixelAlpha(image,p));
1601 p+=GetPixelChannels(image);
1602 }
1603 }
1604 return;
1605 }
1606 if (LocaleCompare(map,"RGBP") == 0)
1607 {
cristycafe0412012-01-10 13:29:58 +00001608 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00001609 {
cristycafe0412012-01-10 13:29:58 +00001610 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00001611 if (p == (const Quantum *) NULL)
1612 break;
cristycafe0412012-01-10 13:29:58 +00001613 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00001614 {
1615 *q++=GetPixelRed(image,p);
1616 *q++=GetPixelGreen(image,p);
1617 *q++=GetPixelBlue(image,p);
1618 *q++=(Quantum) 0;
1619 p+=GetPixelChannels(image);
1620 }
1621 }
1622 return;
1623 }
cristy14d71292012-05-20 16:48:13 +00001624 length=strlen(map);
cristycafe0412012-01-10 13:29:58 +00001625 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00001626 {
cristycafe0412012-01-10 13:29:58 +00001627 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00001628 if (p == (const Quantum *) NULL)
1629 break;
cristycafe0412012-01-10 13:29:58 +00001630 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00001631 {
1632 register ssize_t
1633 i;
1634
cristy14d71292012-05-20 16:48:13 +00001635 for (i=0; i < (ssize_t) length; i++)
cristye5370942012-01-06 03:49:31 +00001636 {
1637 *q=(Quantum) 0;
1638 switch (quantum_map[i])
1639 {
1640 case RedQuantum:
1641 case CyanQuantum:
1642 {
1643 *q=GetPixelRed(image,p);
1644 break;
1645 }
1646 case GreenQuantum:
1647 case MagentaQuantum:
1648 {
1649 *q=GetPixelGreen(image,p);
1650 break;
1651 }
1652 case BlueQuantum:
1653 case YellowQuantum:
1654 {
1655 *q=GetPixelBlue(image,p);
1656 break;
1657 }
1658 case AlphaQuantum:
1659 {
1660 *q=GetPixelAlpha(image,p);
1661 break;
1662 }
1663 case OpacityQuantum:
1664 {
1665 *q=GetPixelAlpha(image,p);
1666 break;
1667 }
1668 case BlackQuantum:
1669 {
1670 if (image->colorspace == CMYKColorspace)
1671 *q=GetPixelBlack(image,p);
1672 break;
1673 }
1674 case IndexQuantum:
1675 {
cristy70e9f682013-03-12 22:31:22 +00001676 *q=ClampToQuantum(GetPixelIntensity(image,p));
cristye5370942012-01-06 03:49:31 +00001677 break;
1678 }
1679 default:
1680 {
1681 *q=(Quantum) 0;
1682 break;
1683 }
1684 }
1685 q++;
1686 }
1687 p+=GetPixelChannels(image);
1688 }
1689 }
1690}
1691
cristy2dc655d2012-07-05 13:16:28 +00001692static void ExportShortPixel(Image *image,const RectangleInfo *roi,
cristy46f4be22012-01-07 00:26:39 +00001693 const char *restrict map,const QuantumType *quantum_map,void *pixels,
1694 ExceptionInfo *exception)
cristye5370942012-01-06 03:49:31 +00001695{
1696 register const Quantum
1697 *restrict p;
1698
1699 register ssize_t
1700 x;
1701
cristye5370942012-01-06 03:49:31 +00001702 register unsigned short
cristy3fe11452012-01-09 01:27:42 +00001703 *restrict q;
cristye5370942012-01-06 03:49:31 +00001704
cristy14d71292012-05-20 16:48:13 +00001705 size_t
1706 length;
1707
1708 ssize_t
1709 y;
1710
cristye5370942012-01-06 03:49:31 +00001711 q=(unsigned short *) pixels;
1712 if (LocaleCompare(map,"BGR") == 0)
1713 {
cristycafe0412012-01-10 13:29:58 +00001714 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00001715 {
cristycafe0412012-01-10 13:29:58 +00001716 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00001717 if (p == (const Quantum *) NULL)
1718 break;
cristycafe0412012-01-10 13:29:58 +00001719 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00001720 {
1721 *q++=ScaleQuantumToShort(GetPixelBlue(image,p));
1722 *q++=ScaleQuantumToShort(GetPixelGreen(image,p));
1723 *q++=ScaleQuantumToShort(GetPixelRed(image,p));
1724 p+=GetPixelChannels(image);
1725 }
1726 }
1727 return;
1728 }
1729 if (LocaleCompare(map,"BGRA") == 0)
1730 {
cristycafe0412012-01-10 13:29:58 +00001731 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00001732 {
cristycafe0412012-01-10 13:29:58 +00001733 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00001734 if (p == (const Quantum *) NULL)
1735 break;
cristycafe0412012-01-10 13:29:58 +00001736 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00001737 {
1738 *q++=ScaleQuantumToShort(GetPixelBlue(image,p));
1739 *q++=ScaleQuantumToShort(GetPixelGreen(image,p));
1740 *q++=ScaleQuantumToShort(GetPixelRed(image,p));
1741 *q++=ScaleQuantumToShort(GetPixelAlpha(image,p));
1742 p+=GetPixelChannels(image);
1743 }
1744 }
1745 return;
1746 }
1747 if (LocaleCompare(map,"BGRP") == 0)
1748 {
cristycafe0412012-01-10 13:29:58 +00001749 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00001750 {
cristycafe0412012-01-10 13:29:58 +00001751 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00001752 if (p == (const Quantum *) NULL)
1753 break;
cristycafe0412012-01-10 13:29:58 +00001754 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00001755 {
1756 *q++=ScaleQuantumToShort(GetPixelBlue(image,p));
1757 *q++=ScaleQuantumToShort(GetPixelGreen(image,p));
1758 *q++=ScaleQuantumToShort(GetPixelRed(image,p));
1759 *q++=0;
1760 p+=GetPixelChannels(image);
1761 }
1762 }
1763 return;
1764 }
1765 if (LocaleCompare(map,"I") == 0)
1766 {
cristycafe0412012-01-10 13:29:58 +00001767 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00001768 {
cristycafe0412012-01-10 13:29:58 +00001769 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00001770 if (p == (const Quantum *) NULL)
1771 break;
cristycafe0412012-01-10 13:29:58 +00001772 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00001773 {
cristy70e9f682013-03-12 22:31:22 +00001774 *q++=ScaleQuantumToShort(ClampToQuantum(GetPixelIntensity(image,p)));
cristye5370942012-01-06 03:49:31 +00001775 p+=GetPixelChannels(image);
1776 }
1777 }
1778 return;
1779 }
1780 if (LocaleCompare(map,"RGB") == 0)
1781 {
cristycafe0412012-01-10 13:29:58 +00001782 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00001783 {
cristycafe0412012-01-10 13:29:58 +00001784 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00001785 if (p == (const Quantum *) NULL)
1786 break;
cristycafe0412012-01-10 13:29:58 +00001787 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00001788 {
1789 *q++=ScaleQuantumToShort(GetPixelRed(image,p));
1790 *q++=ScaleQuantumToShort(GetPixelGreen(image,p));
1791 *q++=ScaleQuantumToShort(GetPixelBlue(image,p));
1792 p+=GetPixelChannels(image);
1793 }
1794 }
1795 return;
1796 }
1797 if (LocaleCompare(map,"RGBA") == 0)
1798 {
cristycafe0412012-01-10 13:29:58 +00001799 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00001800 {
cristycafe0412012-01-10 13:29:58 +00001801 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00001802 if (p == (const Quantum *) NULL)
1803 break;
cristycafe0412012-01-10 13:29:58 +00001804 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00001805 {
1806 *q++=ScaleQuantumToShort(GetPixelRed(image,p));
1807 *q++=ScaleQuantumToShort(GetPixelGreen(image,p));
1808 *q++=ScaleQuantumToShort(GetPixelBlue(image,p));
1809 *q++=ScaleQuantumToShort(GetPixelAlpha(image,p));
1810 p+=GetPixelChannels(image);
1811 }
1812 }
1813 return;
1814 }
1815 if (LocaleCompare(map,"RGBP") == 0)
1816 {
cristycafe0412012-01-10 13:29:58 +00001817 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00001818 {
cristycafe0412012-01-10 13:29:58 +00001819 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00001820 if (p == (const Quantum *) NULL)
1821 break;
cristycafe0412012-01-10 13:29:58 +00001822 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00001823 {
1824 *q++=ScaleQuantumToShort(GetPixelRed(image,p));
1825 *q++=ScaleQuantumToShort(GetPixelGreen(image,p));
1826 *q++=ScaleQuantumToShort(GetPixelBlue(image,p));
1827 *q++=0;
1828 p+=GetPixelChannels(image);
1829 }
1830 }
1831 return;
1832 }
cristy14d71292012-05-20 16:48:13 +00001833 length=strlen(map);
cristycafe0412012-01-10 13:29:58 +00001834 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00001835 {
cristycafe0412012-01-10 13:29:58 +00001836 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00001837 if (p == (const Quantum *) NULL)
1838 break;
cristycafe0412012-01-10 13:29:58 +00001839 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00001840 {
1841 register ssize_t
1842 i;
1843
cristy14d71292012-05-20 16:48:13 +00001844 for (i=0; i < (ssize_t) length; i++)
cristye5370942012-01-06 03:49:31 +00001845 {
1846 *q=0;
1847 switch (quantum_map[i])
1848 {
1849 case RedQuantum:
1850 case CyanQuantum:
1851 {
1852 *q=ScaleQuantumToShort(GetPixelRed(image,p));
1853 break;
1854 }
1855 case GreenQuantum:
1856 case MagentaQuantum:
1857 {
1858 *q=ScaleQuantumToShort(GetPixelGreen(image,p));
1859 break;
1860 }
1861 case BlueQuantum:
1862 case YellowQuantum:
1863 {
1864 *q=ScaleQuantumToShort(GetPixelBlue(image,p));
1865 break;
1866 }
1867 case AlphaQuantum:
1868 {
1869 *q=ScaleQuantumToShort(GetPixelAlpha(image,p));
1870 break;
1871 }
1872 case OpacityQuantum:
1873 {
1874 *q=ScaleQuantumToShort(GetPixelAlpha(image,p));
1875 break;
1876 }
1877 case BlackQuantum:
1878 {
1879 if (image->colorspace == CMYKColorspace)
1880 *q=ScaleQuantumToShort(GetPixelBlack(image,p));
1881 break;
1882 }
1883 case IndexQuantum:
1884 {
cristy70e9f682013-03-12 22:31:22 +00001885 *q=ScaleQuantumToShort(ClampToQuantum(GetPixelIntensity(image,p)));
cristye5370942012-01-06 03:49:31 +00001886 break;
1887 }
1888 default:
1889 break;
1890 }
1891 q++;
1892 }
1893 p+=GetPixelChannels(image);
1894 }
1895 }
1896}
1897
cristy58ee5012013-05-26 23:58:44 +00001898MagickExport MagickBooleanType ExportImagePixels(Image *image,const ssize_t x,
1899 const ssize_t y,const size_t width,const size_t height,const char *map,
1900 const StorageType type,void *pixels,ExceptionInfo *exception)
cristy4c08aed2011-07-01 19:47:50 +00001901{
1902 QuantumType
1903 *quantum_map;
1904
cristycafe0412012-01-10 13:29:58 +00001905 RectangleInfo
1906 roi;
1907
cristy4c08aed2011-07-01 19:47:50 +00001908 register ssize_t
cristye5370942012-01-06 03:49:31 +00001909 i;
cristy4c08aed2011-07-01 19:47:50 +00001910
cristy14d71292012-05-20 16:48:13 +00001911 size_t
1912 length;
1913
cristy4c08aed2011-07-01 19:47:50 +00001914 assert(image != (Image *) NULL);
1915 assert(image->signature == MagickSignature);
1916 if (image->debug != MagickFalse)
1917 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
cristy14d71292012-05-20 16:48:13 +00001918 length=strlen(map);
1919 quantum_map=(QuantumType *) AcquireQuantumMemory(length,sizeof(*quantum_map));
cristy4c08aed2011-07-01 19:47:50 +00001920 if (quantum_map == (QuantumType *) NULL)
1921 {
1922 (void) ThrowMagickException(exception,GetMagickModule(),
cristyefe601c2013-01-05 17:51:12 +00001923 ResourceLimitError,"MemoryAllocationFailed","`%s'",image->filename);
cristy4c08aed2011-07-01 19:47:50 +00001924 return(MagickFalse);
1925 }
cristy14d71292012-05-20 16:48:13 +00001926 for (i=0; i < (ssize_t) length; i++)
cristy4c08aed2011-07-01 19:47:50 +00001927 {
1928 switch (map[i])
1929 {
1930 case 'A':
1931 case 'a':
1932 {
1933 quantum_map[i]=AlphaQuantum;
1934 break;
1935 }
1936 case 'B':
1937 case 'b':
1938 {
1939 quantum_map[i]=BlueQuantum;
1940 break;
1941 }
1942 case 'C':
1943 case 'c':
1944 {
1945 quantum_map[i]=CyanQuantum;
1946 if (image->colorspace == CMYKColorspace)
1947 break;
1948 quantum_map=(QuantumType *) RelinquishMagickMemory(quantum_map);
1949 (void) ThrowMagickException(exception,GetMagickModule(),ImageError,
cristyefe601c2013-01-05 17:51:12 +00001950 "ColorSeparatedImageRequired","`%s'",map);
cristy4c08aed2011-07-01 19:47:50 +00001951 return(MagickFalse);
1952 }
1953 case 'g':
1954 case 'G':
1955 {
1956 quantum_map[i]=GreenQuantum;
1957 break;
1958 }
1959 case 'I':
1960 case 'i':
1961 {
1962 quantum_map[i]=IndexQuantum;
1963 break;
1964 }
1965 case 'K':
1966 case 'k':
1967 {
1968 quantum_map[i]=BlackQuantum;
1969 if (image->colorspace == CMYKColorspace)
1970 break;
1971 quantum_map=(QuantumType *) RelinquishMagickMemory(quantum_map);
1972 (void) ThrowMagickException(exception,GetMagickModule(),ImageError,
cristyefe601c2013-01-05 17:51:12 +00001973 "ColorSeparatedImageRequired","`%s'",map);
cristy4c08aed2011-07-01 19:47:50 +00001974 return(MagickFalse);
1975 }
1976 case 'M':
1977 case 'm':
1978 {
1979 quantum_map[i]=MagentaQuantum;
1980 if (image->colorspace == CMYKColorspace)
1981 break;
1982 quantum_map=(QuantumType *) RelinquishMagickMemory(quantum_map);
1983 (void) ThrowMagickException(exception,GetMagickModule(),ImageError,
cristyefe601c2013-01-05 17:51:12 +00001984 "ColorSeparatedImageRequired","`%s'",map);
cristy4c08aed2011-07-01 19:47:50 +00001985 return(MagickFalse);
1986 }
1987 case 'o':
1988 case 'O':
1989 {
1990 quantum_map[i]=OpacityQuantum;
1991 break;
1992 }
1993 case 'P':
1994 case 'p':
1995 {
1996 quantum_map[i]=UndefinedQuantum;
1997 break;
1998 }
1999 case 'R':
2000 case 'r':
2001 {
2002 quantum_map[i]=RedQuantum;
2003 break;
2004 }
2005 case 'Y':
2006 case 'y':
2007 {
2008 quantum_map[i]=YellowQuantum;
2009 if (image->colorspace == CMYKColorspace)
2010 break;
2011 quantum_map=(QuantumType *) RelinquishMagickMemory(quantum_map);
2012 (void) ThrowMagickException(exception,GetMagickModule(),ImageError,
cristyefe601c2013-01-05 17:51:12 +00002013 "ColorSeparatedImageRequired","`%s'",map);
cristy4c08aed2011-07-01 19:47:50 +00002014 return(MagickFalse);
2015 }
2016 default:
2017 {
2018 quantum_map=(QuantumType *) RelinquishMagickMemory(quantum_map);
2019 (void) ThrowMagickException(exception,GetMagickModule(),OptionError,
cristyefe601c2013-01-05 17:51:12 +00002020 "UnrecognizedPixelMap","`%s'",map);
cristy4c08aed2011-07-01 19:47:50 +00002021 return(MagickFalse);
2022 }
2023 }
2024 }
cristycafe0412012-01-10 13:29:58 +00002025 roi.width=width;
2026 roi.height=height;
2027 roi.x=x;
2028 roi.y=y;
cristy4c08aed2011-07-01 19:47:50 +00002029 switch (type)
2030 {
2031 case CharPixel:
2032 {
cristycafe0412012-01-10 13:29:58 +00002033 ExportCharPixel(image,&roi,map,quantum_map,pixels,exception);
cristy4c08aed2011-07-01 19:47:50 +00002034 break;
2035 }
2036 case DoublePixel:
2037 {
cristycafe0412012-01-10 13:29:58 +00002038 ExportDoublePixel(image,&roi,map,quantum_map,pixels,exception);
cristy4c08aed2011-07-01 19:47:50 +00002039 break;
2040 }
2041 case FloatPixel:
2042 {
cristycafe0412012-01-10 13:29:58 +00002043 ExportFloatPixel(image,&roi,map,quantum_map,pixels,exception);
cristy4c08aed2011-07-01 19:47:50 +00002044 break;
2045 }
cristy4c08aed2011-07-01 19:47:50 +00002046 case LongPixel:
2047 {
cristycafe0412012-01-10 13:29:58 +00002048 ExportLongPixel(image,&roi,map,quantum_map,pixels,exception);
cristy4c08aed2011-07-01 19:47:50 +00002049 break;
2050 }
cristy6c9e1682012-01-07 21:37:44 +00002051 case LongLongPixel:
2052 {
cristycafe0412012-01-10 13:29:58 +00002053 ExportLongLongPixel(image,&roi,map,quantum_map,pixels,exception);
cristy6c9e1682012-01-07 21:37:44 +00002054 break;
2055 }
cristy4c08aed2011-07-01 19:47:50 +00002056 case QuantumPixel:
2057 {
cristycafe0412012-01-10 13:29:58 +00002058 ExportQuantumPixel(image,&roi,map,quantum_map,pixels,exception);
cristy4c08aed2011-07-01 19:47:50 +00002059 break;
2060 }
2061 case ShortPixel:
2062 {
cristycafe0412012-01-10 13:29:58 +00002063 ExportShortPixel(image,&roi,map,quantum_map,pixels,exception);
cristy4c08aed2011-07-01 19:47:50 +00002064 break;
2065 }
2066 default:
2067 {
2068 quantum_map=(QuantumType *) RelinquishMagickMemory(quantum_map);
2069 (void) ThrowMagickException(exception,GetMagickModule(),OptionError,
cristyefe601c2013-01-05 17:51:12 +00002070 "UnrecognizedPixelMap","`%s'",map);
cristy4c08aed2011-07-01 19:47:50 +00002071 break;
2072 }
2073 }
2074 quantum_map=(QuantumType *) RelinquishMagickMemory(quantum_map);
2075 return(MagickTrue);
2076}
2077
2078/*
2079%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2080% %
2081% %
2082% %
cristyaa8634f2011-10-01 13:25:12 +00002083% G e t P i x e l I n f o %
cristy4c08aed2011-07-01 19:47:50 +00002084% %
2085% %
2086% %
2087%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2088%
2089% GetPixelInfo() initializes the PixelInfo structure.
2090%
2091% The format of the GetPixelInfo method is:
2092%
2093% GetPixelInfo(const Image *image,PixelInfo *pixel)
2094%
2095% A description of each parameter follows:
2096%
anthonya322a832013-04-27 06:28:03 +00002097% o image: the image. (optional - may be NULL)
cristy4c08aed2011-07-01 19:47:50 +00002098%
cristy101ab702011-10-13 13:06:32 +00002099% o pixel: Specifies a pointer to a PixelInfo structure.
cristy4c08aed2011-07-01 19:47:50 +00002100%
2101*/
cristyaa8634f2011-10-01 13:25:12 +00002102MagickExport void GetPixelInfo(const Image *image,PixelInfo *pixel)
cristy4c08aed2011-07-01 19:47:50 +00002103{
2104 pixel->storage_class=DirectClass;
cristy7020ae62012-04-18 12:58:34 +00002105 pixel->colorspace=sRGBColorspace;
cristy8a46d822012-08-28 23:32:39 +00002106 pixel->alpha_trait=UndefinedPixelTrait;
cristy4c08aed2011-07-01 19:47:50 +00002107 pixel->fuzz=0.0;
2108 pixel->depth=MAGICKCORE_QUANTUM_DEPTH;
2109 pixel->red=0.0;
2110 pixel->green=0.0;
2111 pixel->blue=0.0;
2112 pixel->black=0.0;
cristya19f1d72012-08-07 18:24:38 +00002113 pixel->alpha=(double) OpaqueAlpha;
cristy4c08aed2011-07-01 19:47:50 +00002114 pixel->index=0.0;
cristyf2a82ee2014-05-26 17:49:54 +00002115 pixel->count=0;
2116 pixel->fuzz=0.0;
cristy4c08aed2011-07-01 19:47:50 +00002117 if (image == (const Image *) NULL)
2118 return;
2119 pixel->storage_class=image->storage_class;
2120 pixel->colorspace=image->colorspace;
cristy8a46d822012-08-28 23:32:39 +00002121 pixel->alpha_trait=image->alpha_trait;
cristy4c08aed2011-07-01 19:47:50 +00002122 pixel->depth=image->depth;
2123 pixel->fuzz=image->fuzz;
2124}
2125
2126/*
2127%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2128% %
2129% %
2130% %
cristy9731df72013-03-12 16:31:13 +00002131% G e t P i x e l I n t e n s i t y %
2132% %
2133% %
2134% %
2135%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2136%
cristy0c5c8892013-03-12 16:33:48 +00002137% GetPixelIntensity() returns a single sample intensity value from the red,
cristy70e9f682013-03-12 22:31:22 +00002138% green, and blue components of a pixel based on the selected method:
2139%
cristy2cf5d372013-03-13 12:03:11 +00002140% Rec601Luma 0.298839R' + 0.586811G' + 0.114350B'
2141% Rec601Luminance 0.298839R + 0.586811G + 0.114350B
cristy1352acf2013-06-10 17:16:17 +00002142% Rec709Luma 0.212656R' + 0.715158G' + 0.072186B'
2143% Rec709Luminance 0.212656R + 0.715158G + 0.072186B
cristy09bb0432013-06-01 13:39:18 +00002144% Brightness max(R', G', B')
2145% Lightness (min(R', G', B') + max(R', G', B')) / 2.0
2146%
2147% MS (R^2 + G^2 + B^2) / 3.0
2148% RMS sqrt((R^2 + G^2 + B^2) / 3.0
2149% Average (R + G + B') / 3.0
cristy9731df72013-03-12 16:31:13 +00002150%
2151% The format of the GetPixelIntensity method is:
2152%
cristy2cf5d372013-03-13 12:03:11 +00002153% MagickRealType GetPixelIntensity(const Image *image,
2154% const Quantum *pixel)
cristy9731df72013-03-12 16:31:13 +00002155%
2156% A description of each parameter follows:
2157%
2158% o image: the image.
2159%
2160% o pixel: Specifies a pointer to a Quantum structure.
2161%
2162*/
cristy70e9f682013-03-12 22:31:22 +00002163
2164static inline MagickRealType MagickMax(const MagickRealType x,
2165 const MagickRealType y)
2166{
2167 if (x > y)
2168 return(x);
2169 return(y);
2170}
2171
2172static inline MagickRealType MagickMin(const MagickRealType x,
2173 const MagickRealType y)
2174{
2175 if (x < y)
2176 return(x);
2177 return(y);
2178}
2179
cristy9731df72013-03-12 16:31:13 +00002180MagickExport MagickRealType GetPixelIntensity(const Image *restrict image,
2181 const Quantum *restrict pixel)
2182{
2183 MagickRealType
2184 blue,
2185 green,
cristy70e9f682013-03-12 22:31:22 +00002186 red,
2187 intensity;
cristy9731df72013-03-12 16:31:13 +00002188
2189 if (image->colorspace == GRAYColorspace)
cristy592d6bb2013-04-07 15:20:37 +00002190 return((MagickRealType) GetPixelGray(image,pixel));
2191 red=(MagickRealType) GetPixelRed(image,pixel);
2192 green=(MagickRealType) GetPixelGreen(image,pixel);
2193 blue=(MagickRealType) GetPixelBlue(image,pixel);
cristy70e9f682013-03-12 22:31:22 +00002194 switch (image->intensity)
2195 {
cristybf02d732013-03-13 16:28:58 +00002196 case AveragePixelIntensityMethod:
2197 {
2198 intensity=(red+green+blue)/3.0;
2199 break;
2200 }
2201 case BrightnessPixelIntensityMethod:
2202 {
2203 intensity=MagickMax(MagickMax(red,green),blue);
2204 break;
2205 }
2206 case LightnessPixelIntensityMethod:
2207 {
cristy09bb0432013-06-01 13:39:18 +00002208 intensity=(MagickMin(MagickMin(red,green),blue)+
cristyce326722013-06-01 13:40:28 +00002209 MagickMax(MagickMax(red,green),blue))/2.0;
cristybf02d732013-03-13 16:28:58 +00002210 break;
2211 }
cristy462c1ca2013-04-15 10:29:18 +00002212 case MSPixelIntensityMethod:
2213 {
2214 intensity=(MagickRealType) (((double) red*red+green*green+blue*blue)/
2215 (3.0*QuantumRange));
2216 break;
2217 }
cristy70e9f682013-03-12 22:31:22 +00002218 case Rec601LumaPixelIntensityMethod:
cristy70e9f682013-03-12 22:31:22 +00002219 {
cristy09bb0432013-06-01 13:39:18 +00002220 if (image->colorspace == RGBColorspace)
2221 {
2222 red=EncodePixelGamma(red);
2223 green=EncodePixelGamma(green);
2224 blue=EncodePixelGamma(blue);
2225 }
cristy9e2436a2013-05-02 20:35:59 +00002226 intensity=0.298839*red+0.586811*green+0.114350*blue;
cristy2cf5d372013-03-13 12:03:11 +00002227 break;
2228 }
2229 case Rec601LuminancePixelIntensityMethod:
2230 {
cristy70e9f682013-03-12 22:31:22 +00002231 if (image->colorspace == sRGBColorspace)
2232 {
2233 red=DecodePixelGamma(red);
2234 green=DecodePixelGamma(green);
2235 blue=DecodePixelGamma(blue);
2236 }
cristy9e2436a2013-05-02 20:35:59 +00002237 intensity=0.298839*red+0.586811*green+0.114350*blue;
cristy70e9f682013-03-12 22:31:22 +00002238 break;
2239 }
2240 case Rec709LumaPixelIntensityMethod:
cristyc94210c2013-05-06 14:09:53 +00002241 default:
cristy70e9f682013-03-12 22:31:22 +00002242 {
cristy09bb0432013-06-01 13:39:18 +00002243 if (image->colorspace == RGBColorspace)
2244 {
2245 red=EncodePixelGamma(red);
2246 green=EncodePixelGamma(green);
2247 blue=EncodePixelGamma(blue);
2248 }
cristy1352acf2013-06-10 17:16:17 +00002249 intensity=0.212656*red+0.715158*green+0.072186*blue;
cristy2cf5d372013-03-13 12:03:11 +00002250 break;
2251 }
2252 case Rec709LuminancePixelIntensityMethod:
2253 {
cristy70e9f682013-03-12 22:31:22 +00002254 if (image->colorspace == sRGBColorspace)
2255 {
2256 red=DecodePixelGamma(red);
2257 green=DecodePixelGamma(green);
2258 blue=DecodePixelGamma(blue);
2259 }
cristy1352acf2013-06-10 17:16:17 +00002260 intensity=0.212656*red+0.715158*green+0.072186*blue;
cristy70e9f682013-03-12 22:31:22 +00002261 break;
2262 }
cristy70e9f682013-03-12 22:31:22 +00002263 case RMSPixelIntensityMethod:
2264 {
cristy462c1ca2013-04-15 10:29:18 +00002265 intensity=(MagickRealType) (sqrt((double) red*red+green*green+blue*blue)/
2266 sqrt(3.0));
cristy70e9f682013-03-12 22:31:22 +00002267 break;
2268 }
cristy70e9f682013-03-12 22:31:22 +00002269 }
2270 return(intensity);
cristy9731df72013-03-12 16:31:13 +00002271}
cristy9731df72013-03-12 16:31:13 +00002272
2273/*
2274%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2275% %
2276% %
2277% %
cristy4c08aed2011-07-01 19:47:50 +00002278% I m p o r t I m a g e P i x e l s %
2279% %
2280% %
2281% %
2282%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2283%
2284% ImportImagePixels() accepts pixel data and stores in the image at the
2285% location you specify. The method returns MagickTrue on success otherwise
2286% MagickFalse if an error is encountered. The pixel data can be either char,
cristyb5a45a32012-01-10 13:31:13 +00002287% Quantum, short int, unsigned int, unsigned long long, float, or double in
2288% the order specified by map.
cristy4c08aed2011-07-01 19:47:50 +00002289%
2290% Suppose your want to upload the first scanline of a 640x480 image from
2291% character data in red-green-blue order:
2292%
2293% ImportImagePixels(image,0,0,640,1,"RGB",CharPixel,pixels);
2294%
2295% The format of the ImportImagePixels method is:
2296%
cristycafe0412012-01-10 13:29:58 +00002297% MagickBooleanType ImportImagePixels(Image *image,const ssize_t x,
2298% const ssize_t y,const size_t width,const size_t height,
2299% const char *map,const StorageType type,const void *pixels,
2300% ExceptionInfo *exception)
cristy4c08aed2011-07-01 19:47:50 +00002301%
2302% A description of each parameter follows:
2303%
2304% o image: the image.
2305%
cristycafe0412012-01-10 13:29:58 +00002306% o x,y,width,height: These values define the perimeter
cristy4c08aed2011-07-01 19:47:50 +00002307% of a region of pixels you want to define.
2308%
2309% o map: This string reflects the expected ordering of the pixel array.
2310% It can be any combination or order of R = red, G = green, B = blue,
2311% A = alpha (0 is transparent), O = opacity (0 is opaque), C = cyan,
2312% Y = yellow, M = magenta, K = black, I = intensity (for grayscale),
2313% P = pad.
2314%
2315% o type: Define the data type of the pixels. Float and double types are
2316% normalized to [0..1] otherwise [0..QuantumRange]. Choose from these
cristy6c9e1682012-01-07 21:37:44 +00002317% types: CharPixel (char *), DoublePixel (double *), FloatPixel (float *),
cristyff6834e2012-01-10 03:00:25 +00002318% LongPixel (unsigned int *), LongLongPixel (unsigned long long *),
cristy6c9e1682012-01-07 21:37:44 +00002319% QuantumPixel (Quantum *), or ShortPixel (unsigned short *).
cristy4c08aed2011-07-01 19:47:50 +00002320%
2321% o pixels: This array of values contain the pixel components as defined by
2322% map and type. You must preallocate this array where the expected
2323% length varies depending on the values of width, height, map, and type.
2324%
cristy018f07f2011-09-04 21:15:19 +00002325% o exception: return any errors or warnings in this structure.
2326%
cristy4c08aed2011-07-01 19:47:50 +00002327*/
cristye5370942012-01-06 03:49:31 +00002328
cristycafe0412012-01-10 13:29:58 +00002329static void ImportCharPixel(Image *image,const RectangleInfo *roi,
cristy46f4be22012-01-07 00:26:39 +00002330 const char *restrict map,const QuantumType *quantum_map,const void *pixels,
2331 ExceptionInfo *exception)
cristye5370942012-01-06 03:49:31 +00002332{
2333 register const unsigned char
2334 *restrict p;
2335
2336 register Quantum
cristy3fe11452012-01-09 01:27:42 +00002337 *restrict q;
cristye5370942012-01-06 03:49:31 +00002338
2339 register ssize_t
2340 x;
2341
cristy14d71292012-05-20 16:48:13 +00002342 size_t
2343 length;
2344
cristye5370942012-01-06 03:49:31 +00002345 ssize_t
2346 y;
2347
2348 p=(const unsigned char *) pixels;
2349 if (LocaleCompare(map,"BGR") == 0)
2350 {
cristycafe0412012-01-10 13:29:58 +00002351 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00002352 {
cristycafe0412012-01-10 13:29:58 +00002353 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00002354 if (q == (Quantum *) NULL)
2355 break;
cristycafe0412012-01-10 13:29:58 +00002356 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00002357 {
2358 SetPixelBlue(image,ScaleCharToQuantum(*p++),q);
2359 SetPixelGreen(image,ScaleCharToQuantum(*p++),q);
2360 SetPixelRed(image,ScaleCharToQuantum(*p++),q);
2361 q+=GetPixelChannels(image);
2362 }
2363 if (SyncAuthenticPixels(image,exception) == MagickFalse)
2364 break;
2365 }
2366 return;
2367 }
2368 if (LocaleCompare(map,"BGRA") == 0)
2369 {
cristycafe0412012-01-10 13:29:58 +00002370 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00002371 {
cristycafe0412012-01-10 13:29:58 +00002372 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00002373 if (q == (Quantum *) NULL)
2374 break;
cristycafe0412012-01-10 13:29:58 +00002375 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00002376 {
2377 SetPixelBlue(image,ScaleCharToQuantum(*p++),q);
2378 SetPixelGreen(image,ScaleCharToQuantum(*p++),q);
2379 SetPixelRed(image,ScaleCharToQuantum(*p++),q);
2380 SetPixelAlpha(image,ScaleCharToQuantum(*p++),q);
2381 q+=GetPixelChannels(image);
2382 }
2383 if (SyncAuthenticPixels(image,exception) == MagickFalse)
2384 break;
2385 }
2386 return;
2387 }
2388 if (LocaleCompare(map,"BGRO") == 0)
2389 {
cristycafe0412012-01-10 13:29:58 +00002390 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00002391 {
cristycafe0412012-01-10 13:29:58 +00002392 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00002393 if (q == (Quantum *) NULL)
2394 break;
cristycafe0412012-01-10 13:29:58 +00002395 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00002396 {
2397 SetPixelBlue(image,ScaleCharToQuantum(*p++),q);
2398 SetPixelGreen(image,ScaleCharToQuantum(*p++),q);
2399 SetPixelRed(image,ScaleCharToQuantum(*p++),q);
2400 SetPixelAlpha(image,ScaleCharToQuantum(*p++),q);
2401 q+=GetPixelChannels(image);
2402 }
2403 if (SyncAuthenticPixels(image,exception) == MagickFalse)
2404 break;
2405 }
2406 return;
2407 }
2408 if (LocaleCompare(map,"BGRP") == 0)
2409 {
cristycafe0412012-01-10 13:29:58 +00002410 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00002411 {
cristycafe0412012-01-10 13:29:58 +00002412 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00002413 if (q == (Quantum *) NULL)
2414 break;
cristycafe0412012-01-10 13:29:58 +00002415 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00002416 {
2417 SetPixelBlue(image,ScaleCharToQuantum(*p++),q);
2418 SetPixelGreen(image,ScaleCharToQuantum(*p++),q);
2419 SetPixelRed(image,ScaleCharToQuantum(*p++),q);
2420 p++;
2421 q+=GetPixelChannels(image);
2422 }
2423 if (SyncAuthenticPixels(image,exception) == MagickFalse)
2424 break;
2425 }
2426 return;
2427 }
2428 if (LocaleCompare(map,"I") == 0)
2429 {
cristycafe0412012-01-10 13:29:58 +00002430 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00002431 {
cristycafe0412012-01-10 13:29:58 +00002432 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00002433 if (q == (Quantum *) NULL)
2434 break;
cristycafe0412012-01-10 13:29:58 +00002435 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00002436 {
2437 SetPixelGray(image,ScaleCharToQuantum(*p++),q);
2438 q+=GetPixelChannels(image);
2439 }
2440 if (SyncAuthenticPixels(image,exception) == MagickFalse)
2441 break;
2442 }
2443 return;
2444 }
2445 if (LocaleCompare(map,"RGB") == 0)
2446 {
cristycafe0412012-01-10 13:29:58 +00002447 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00002448 {
cristycafe0412012-01-10 13:29:58 +00002449 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00002450 if (q == (Quantum *) NULL)
2451 break;
cristycafe0412012-01-10 13:29:58 +00002452 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00002453 {
2454 SetPixelRed(image,ScaleCharToQuantum(*p++),q);
2455 SetPixelGreen(image,ScaleCharToQuantum(*p++),q);
2456 SetPixelBlue(image,ScaleCharToQuantum(*p++),q);
2457 q+=GetPixelChannels(image);
2458 }
2459 if (SyncAuthenticPixels(image,exception) == MagickFalse)
2460 break;
2461 }
2462 return;
2463 }
2464 if (LocaleCompare(map,"RGBA") == 0)
2465 {
cristycafe0412012-01-10 13:29:58 +00002466 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00002467 {
cristycafe0412012-01-10 13:29:58 +00002468 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00002469 if (q == (Quantum *) NULL)
2470 break;
cristycafe0412012-01-10 13:29:58 +00002471 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00002472 {
2473 SetPixelRed(image,ScaleCharToQuantum(*p++),q);
2474 SetPixelGreen(image,ScaleCharToQuantum(*p++),q);
2475 SetPixelBlue(image,ScaleCharToQuantum(*p++),q);
2476 SetPixelAlpha(image,ScaleCharToQuantum(*p++),q);
2477 q+=GetPixelChannels(image);
2478 }
2479 if (SyncAuthenticPixels(image,exception) == MagickFalse)
2480 break;
2481 }
2482 return;
2483 }
2484 if (LocaleCompare(map,"RGBO") == 0)
2485 {
cristycafe0412012-01-10 13:29:58 +00002486 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00002487 {
cristycafe0412012-01-10 13:29:58 +00002488 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00002489 if (q == (Quantum *) NULL)
2490 break;
cristycafe0412012-01-10 13:29:58 +00002491 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00002492 {
2493 SetPixelRed(image,ScaleCharToQuantum(*p++),q);
2494 SetPixelGreen(image,ScaleCharToQuantum(*p++),q);
2495 SetPixelBlue(image,ScaleCharToQuantum(*p++),q);
2496 SetPixelAlpha(image,ScaleCharToQuantum(*p++),q);
2497 q+=GetPixelChannels(image);
2498 }
2499 if (SyncAuthenticPixels(image,exception) == MagickFalse)
2500 break;
2501 }
2502 return;
2503 }
2504 if (LocaleCompare(map,"RGBP") == 0)
2505 {
cristycafe0412012-01-10 13:29:58 +00002506 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00002507 {
cristycafe0412012-01-10 13:29:58 +00002508 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00002509 if (q == (Quantum *) NULL)
2510 break;
cristycafe0412012-01-10 13:29:58 +00002511 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00002512 {
2513 SetPixelRed(image,ScaleCharToQuantum(*p++),q);
2514 SetPixelGreen(image,ScaleCharToQuantum(*p++),q);
2515 SetPixelBlue(image,ScaleCharToQuantum(*p++),q);
2516 p++;
2517 q+=GetPixelChannels(image);
2518 }
2519 if (SyncAuthenticPixels(image,exception) == MagickFalse)
2520 break;
2521 }
2522 return;
2523 }
cristy14d71292012-05-20 16:48:13 +00002524 length=strlen(map);
cristycafe0412012-01-10 13:29:58 +00002525 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00002526 {
cristycafe0412012-01-10 13:29:58 +00002527 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00002528 if (q == (Quantum *) NULL)
2529 break;
cristycafe0412012-01-10 13:29:58 +00002530 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00002531 {
2532 register ssize_t
2533 i;
2534
cristy14d71292012-05-20 16:48:13 +00002535 for (i=0; i < (ssize_t) length; i++)
cristye5370942012-01-06 03:49:31 +00002536 {
2537 switch (quantum_map[i])
2538 {
2539 case RedQuantum:
2540 case CyanQuantum:
2541 {
2542 SetPixelRed(image,ScaleCharToQuantum(*p),q);
2543 break;
2544 }
2545 case GreenQuantum:
2546 case MagentaQuantum:
2547 {
2548 SetPixelGreen(image,ScaleCharToQuantum(*p),q);
2549 break;
2550 }
2551 case BlueQuantum:
2552 case YellowQuantum:
2553 {
2554 SetPixelBlue(image,ScaleCharToQuantum(*p),q);
2555 break;
2556 }
2557 case AlphaQuantum:
2558 {
2559 SetPixelAlpha(image,ScaleCharToQuantum(*p),q);
2560 break;
2561 }
2562 case OpacityQuantum:
2563 {
2564 SetPixelAlpha(image,ScaleCharToQuantum(*p),q);
2565 break;
2566 }
2567 case BlackQuantum:
2568 {
2569 SetPixelBlack(image,ScaleCharToQuantum(*p),q);
2570 break;
2571 }
2572 case IndexQuantum:
2573 {
2574 SetPixelGray(image,ScaleCharToQuantum(*p),q);
2575 break;
2576 }
2577 default:
2578 break;
2579 }
2580 p++;
2581 }
2582 q+=GetPixelChannels(image);
2583 }
2584 if (SyncAuthenticPixels(image,exception) == MagickFalse)
2585 break;
2586 }
2587}
2588
cristycafe0412012-01-10 13:29:58 +00002589static void ImportDoublePixel(Image *image,const RectangleInfo *roi,
cristy46f4be22012-01-07 00:26:39 +00002590 const char *restrict map,const QuantumType *quantum_map,const void *pixels,
2591 ExceptionInfo *exception)
cristye5370942012-01-06 03:49:31 +00002592{
2593 register const double
2594 *restrict p;
2595
2596 register Quantum
cristy3fe11452012-01-09 01:27:42 +00002597 *restrict q;
cristye5370942012-01-06 03:49:31 +00002598
2599 register ssize_t
2600 x;
2601
cristy14d71292012-05-20 16:48:13 +00002602 size_t
2603 length;
2604
cristye5370942012-01-06 03:49:31 +00002605 ssize_t
2606 y;
2607
2608 p=(const double *) pixels;
2609 if (LocaleCompare(map,"BGR") == 0)
2610 {
cristycafe0412012-01-10 13:29:58 +00002611 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00002612 {
cristycafe0412012-01-10 13:29:58 +00002613 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00002614 if (q == (Quantum *) NULL)
2615 break;
cristycafe0412012-01-10 13:29:58 +00002616 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00002617 {
cristy8cd03c32012-07-07 18:57:59 +00002618 SetPixelBlue(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002619 p++;
cristy8cd03c32012-07-07 18:57:59 +00002620 SetPixelGreen(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002621 p++;
cristy8cd03c32012-07-07 18:57:59 +00002622 SetPixelRed(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002623 p++;
2624 q+=GetPixelChannels(image);
2625 }
2626 if (SyncAuthenticPixels(image,exception) == MagickFalse)
2627 break;
2628 }
2629 return;
2630 }
2631 if (LocaleCompare(map,"BGRA") == 0)
2632 {
cristycafe0412012-01-10 13:29:58 +00002633 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00002634 {
cristycafe0412012-01-10 13:29:58 +00002635 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00002636 if (q == (Quantum *) NULL)
2637 break;
cristycafe0412012-01-10 13:29:58 +00002638 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00002639 {
cristy8cd03c32012-07-07 18:57:59 +00002640 SetPixelBlue(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002641 p++;
cristy8cd03c32012-07-07 18:57:59 +00002642 SetPixelGreen(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002643 p++;
cristy8cd03c32012-07-07 18:57:59 +00002644 SetPixelRed(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002645 p++;
cristy8cd03c32012-07-07 18:57:59 +00002646 SetPixelAlpha(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002647 p++;
2648 q+=GetPixelChannels(image);
2649 }
2650 if (SyncAuthenticPixels(image,exception) == MagickFalse)
2651 break;
2652 }
2653 return;
2654 }
2655 if (LocaleCompare(map,"BGRP") == 0)
2656 {
cristycafe0412012-01-10 13:29:58 +00002657 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00002658 {
cristycafe0412012-01-10 13:29:58 +00002659 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00002660 if (q == (Quantum *) NULL)
2661 break;
cristycafe0412012-01-10 13:29:58 +00002662 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00002663 {
cristy8cd03c32012-07-07 18:57:59 +00002664 SetPixelBlue(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002665 p++;
cristy8cd03c32012-07-07 18:57:59 +00002666 SetPixelGreen(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002667 p++;
cristy8cd03c32012-07-07 18:57:59 +00002668 SetPixelRed(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002669 p++;
2670 p++;
2671 q+=GetPixelChannels(image);
2672 }
2673 if (SyncAuthenticPixels(image,exception) == MagickFalse)
2674 break;
2675 }
2676 return;
2677 }
2678 if (LocaleCompare(map,"I") == 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 SetPixelGray(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002688 p++;
2689 q+=GetPixelChannels(image);
2690 }
2691 if (SyncAuthenticPixels(image,exception) == MagickFalse)
2692 break;
2693 }
2694 return;
2695 }
2696 if (LocaleCompare(map,"RGB") == 0)
2697 {
cristycafe0412012-01-10 13:29:58 +00002698 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00002699 {
cristycafe0412012-01-10 13:29:58 +00002700 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00002701 if (q == (Quantum *) NULL)
2702 break;
cristycafe0412012-01-10 13:29:58 +00002703 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00002704 {
cristy8cd03c32012-07-07 18:57:59 +00002705 SetPixelRed(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002706 p++;
cristy8cd03c32012-07-07 18:57:59 +00002707 SetPixelGreen(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002708 p++;
cristy8cd03c32012-07-07 18:57:59 +00002709 SetPixelBlue(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002710 p++;
2711 q+=GetPixelChannels(image);
2712 }
2713 if (SyncAuthenticPixels(image,exception) == MagickFalse)
2714 break;
2715 }
2716 return;
2717 }
2718 if (LocaleCompare(map,"RGBA") == 0)
2719 {
cristycafe0412012-01-10 13:29:58 +00002720 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00002721 {
cristycafe0412012-01-10 13:29:58 +00002722 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00002723 if (q == (Quantum *) NULL)
2724 break;
cristycafe0412012-01-10 13:29:58 +00002725 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00002726 {
cristy8cd03c32012-07-07 18:57:59 +00002727 SetPixelRed(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002728 p++;
cristy8cd03c32012-07-07 18:57:59 +00002729 SetPixelGreen(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002730 p++;
cristy8cd03c32012-07-07 18:57:59 +00002731 SetPixelBlue(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002732 p++;
cristy8cd03c32012-07-07 18:57:59 +00002733 SetPixelAlpha(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002734 p++;
2735 q+=GetPixelChannels(image);
2736 }
2737 if (SyncAuthenticPixels(image,exception) == MagickFalse)
2738 break;
2739 }
2740 return;
2741 }
2742 if (LocaleCompare(map,"RGBP") == 0)
2743 {
cristycafe0412012-01-10 13:29:58 +00002744 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00002745 {
cristycafe0412012-01-10 13:29:58 +00002746 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00002747 if (q == (Quantum *) NULL)
2748 break;
cristycafe0412012-01-10 13:29:58 +00002749 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00002750 {
cristy8cd03c32012-07-07 18:57:59 +00002751 SetPixelRed(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002752 p++;
cristy8cd03c32012-07-07 18:57:59 +00002753 SetPixelGreen(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002754 p++;
cristy8cd03c32012-07-07 18:57:59 +00002755 SetPixelBlue(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002756 p++;
2757 q+=GetPixelChannels(image);
2758 }
2759 if (SyncAuthenticPixels(image,exception) == MagickFalse)
2760 break;
2761 }
2762 return;
2763 }
cristy14d71292012-05-20 16:48:13 +00002764 length=strlen(map);
cristycafe0412012-01-10 13:29:58 +00002765 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00002766 {
cristycafe0412012-01-10 13:29:58 +00002767 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00002768 if (q == (Quantum *) NULL)
2769 break;
cristycafe0412012-01-10 13:29:58 +00002770 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00002771 {
2772 register ssize_t
2773 i;
2774
cristy14d71292012-05-20 16:48:13 +00002775 for (i=0; i < (ssize_t) length; i++)
cristye5370942012-01-06 03:49:31 +00002776 {
2777 switch (quantum_map[i])
2778 {
2779 case RedQuantum:
2780 case CyanQuantum:
2781 {
cristy8cd03c32012-07-07 18:57:59 +00002782 SetPixelRed(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002783 break;
2784 }
2785 case GreenQuantum:
2786 case MagentaQuantum:
2787 {
cristy8cd03c32012-07-07 18:57:59 +00002788 SetPixelGreen(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002789 break;
2790 }
2791 case BlueQuantum:
2792 case YellowQuantum:
2793 {
cristy8cd03c32012-07-07 18:57:59 +00002794 SetPixelBlue(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002795 break;
2796 }
2797 case AlphaQuantum:
2798 {
cristy8cd03c32012-07-07 18:57:59 +00002799 SetPixelAlpha(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002800 break;
2801 }
2802 case OpacityQuantum:
2803 {
cristy8cd03c32012-07-07 18:57:59 +00002804 SetPixelAlpha(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002805 break;
2806 }
2807 case BlackQuantum:
2808 {
cristy8cd03c32012-07-07 18:57:59 +00002809 SetPixelBlack(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002810 break;
2811 }
2812 case IndexQuantum:
2813 {
cristy8cd03c32012-07-07 18:57:59 +00002814 SetPixelGray(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002815 break;
2816 }
2817 default:
2818 break;
2819 }
2820 p++;
2821 }
2822 q+=GetPixelChannels(image);
2823 }
2824 if (SyncAuthenticPixels(image,exception) == MagickFalse)
2825 break;
2826 }
2827}
2828
cristycafe0412012-01-10 13:29:58 +00002829static void ImportFloatPixel(Image *image,const RectangleInfo *roi,
cristy46f4be22012-01-07 00:26:39 +00002830 const char *restrict map,const QuantumType *quantum_map,const void *pixels,
2831 ExceptionInfo *exception)
cristye5370942012-01-06 03:49:31 +00002832{
2833 register const float
2834 *restrict p;
2835
2836 register Quantum
cristy3fe11452012-01-09 01:27:42 +00002837 *restrict q;
cristye5370942012-01-06 03:49:31 +00002838
2839 register ssize_t
2840 x;
2841
cristy14d71292012-05-20 16:48:13 +00002842 size_t
2843 length;
2844
cristye5370942012-01-06 03:49:31 +00002845 ssize_t
2846 y;
2847
2848 p=(const float *) pixels;
2849 if (LocaleCompare(map,"BGR") == 0)
2850 {
cristycafe0412012-01-10 13:29:58 +00002851 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00002852 {
cristycafe0412012-01-10 13:29:58 +00002853 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00002854 if (q == (Quantum *) NULL)
2855 break;
cristycafe0412012-01-10 13:29:58 +00002856 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00002857 {
cristy8cd03c32012-07-07 18:57:59 +00002858 SetPixelBlue(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002859 p++;
cristy8cd03c32012-07-07 18:57:59 +00002860 SetPixelGreen(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002861 p++;
cristy8cd03c32012-07-07 18:57:59 +00002862 SetPixelRed(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002863 p++;
2864 q+=GetPixelChannels(image);
2865 }
2866 if (SyncAuthenticPixels(image,exception) == MagickFalse)
2867 break;
2868 }
2869 return;
2870 }
2871 if (LocaleCompare(map,"BGRA") == 0)
2872 {
cristycafe0412012-01-10 13:29:58 +00002873 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00002874 {
cristycafe0412012-01-10 13:29:58 +00002875 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00002876 if (q == (Quantum *) NULL)
2877 break;
cristycafe0412012-01-10 13:29:58 +00002878 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00002879 {
cristy8cd03c32012-07-07 18:57:59 +00002880 SetPixelBlue(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002881 p++;
cristy8cd03c32012-07-07 18:57:59 +00002882 SetPixelGreen(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002883 p++;
cristy8cd03c32012-07-07 18:57:59 +00002884 SetPixelRed(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002885 p++;
cristy8cd03c32012-07-07 18:57:59 +00002886 SetPixelAlpha(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002887 p++;
2888 q+=GetPixelChannels(image);
2889 }
2890 if (SyncAuthenticPixels(image,exception) == MagickFalse)
2891 break;
2892 }
2893 return;
2894 }
2895 if (LocaleCompare(map,"BGRP") == 0)
2896 {
cristycafe0412012-01-10 13:29:58 +00002897 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00002898 {
cristycafe0412012-01-10 13:29:58 +00002899 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00002900 if (q == (Quantum *) NULL)
2901 break;
cristycafe0412012-01-10 13:29:58 +00002902 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00002903 {
cristy8cd03c32012-07-07 18:57:59 +00002904 SetPixelBlue(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002905 p++;
cristy8cd03c32012-07-07 18:57:59 +00002906 SetPixelGreen(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002907 p++;
cristy8cd03c32012-07-07 18:57:59 +00002908 SetPixelRed(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002909 p++;
2910 p++;
2911 q+=GetPixelChannels(image);
2912 }
2913 if (SyncAuthenticPixels(image,exception) == MagickFalse)
2914 break;
2915 }
2916 return;
2917 }
2918 if (LocaleCompare(map,"I") == 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 SetPixelGray(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002928 p++;
2929 q+=GetPixelChannels(image);
2930 }
2931 if (SyncAuthenticPixels(image,exception) == MagickFalse)
2932 break;
2933 }
2934 return;
2935 }
2936 if (LocaleCompare(map,"RGB") == 0)
2937 {
cristycafe0412012-01-10 13:29:58 +00002938 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00002939 {
cristycafe0412012-01-10 13:29:58 +00002940 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00002941 if (q == (Quantum *) NULL)
2942 break;
cristycafe0412012-01-10 13:29:58 +00002943 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00002944 {
cristy8cd03c32012-07-07 18:57:59 +00002945 SetPixelRed(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002946 p++;
cristy8cd03c32012-07-07 18:57:59 +00002947 SetPixelGreen(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002948 p++;
cristy8cd03c32012-07-07 18:57:59 +00002949 SetPixelBlue(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002950 p++;
2951 q+=GetPixelChannels(image);
2952 }
2953 if (SyncAuthenticPixels(image,exception) == MagickFalse)
2954 break;
2955 }
2956 return;
2957 }
2958 if (LocaleCompare(map,"RGBA") == 0)
2959 {
cristycafe0412012-01-10 13:29:58 +00002960 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00002961 {
cristycafe0412012-01-10 13:29:58 +00002962 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00002963 if (q == (Quantum *) NULL)
2964 break;
cristycafe0412012-01-10 13:29:58 +00002965 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00002966 {
cristy8cd03c32012-07-07 18:57:59 +00002967 SetPixelRed(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002968 p++;
cristy8cd03c32012-07-07 18:57:59 +00002969 SetPixelGreen(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002970 p++;
cristy8cd03c32012-07-07 18:57:59 +00002971 SetPixelBlue(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002972 p++;
cristy8cd03c32012-07-07 18:57:59 +00002973 SetPixelAlpha(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002974 p++;
2975 q+=GetPixelChannels(image);
2976 }
2977 if (SyncAuthenticPixels(image,exception) == MagickFalse)
2978 break;
2979 }
2980 return;
2981 }
2982 if (LocaleCompare(map,"RGBP") == 0)
2983 {
cristycafe0412012-01-10 13:29:58 +00002984 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00002985 {
cristycafe0412012-01-10 13:29:58 +00002986 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00002987 if (q == (Quantum *) NULL)
2988 break;
cristycafe0412012-01-10 13:29:58 +00002989 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00002990 {
cristy8cd03c32012-07-07 18:57:59 +00002991 SetPixelRed(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002992 p++;
cristy8cd03c32012-07-07 18:57:59 +00002993 SetPixelGreen(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002994 p++;
cristy8cd03c32012-07-07 18:57:59 +00002995 SetPixelBlue(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002996 p++;
2997 q+=GetPixelChannels(image);
2998 }
2999 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3000 break;
3001 }
3002 return;
3003 }
cristy14d71292012-05-20 16:48:13 +00003004 length=strlen(map);
cristycafe0412012-01-10 13:29:58 +00003005 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00003006 {
cristycafe0412012-01-10 13:29:58 +00003007 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00003008 if (q == (Quantum *) NULL)
3009 break;
cristycafe0412012-01-10 13:29:58 +00003010 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00003011 {
3012 register ssize_t
3013 i;
3014
cristy14d71292012-05-20 16:48:13 +00003015 for (i=0; i < (ssize_t) length; i++)
cristye5370942012-01-06 03:49:31 +00003016 {
3017 switch (quantum_map[i])
3018 {
3019 case RedQuantum:
3020 case CyanQuantum:
3021 {
cristy8cd03c32012-07-07 18:57:59 +00003022 SetPixelRed(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00003023 break;
3024 }
3025 case GreenQuantum:
3026 case MagentaQuantum:
3027 {
cristy8cd03c32012-07-07 18:57:59 +00003028 SetPixelGreen(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00003029 break;
3030 }
3031 case BlueQuantum:
3032 case YellowQuantum:
3033 {
cristy8cd03c32012-07-07 18:57:59 +00003034 SetPixelBlue(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00003035 break;
3036 }
3037 case AlphaQuantum:
3038 {
cristy8cd03c32012-07-07 18:57:59 +00003039 SetPixelAlpha(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00003040 break;
3041 }
3042 case OpacityQuantum:
3043 {
cristy8cd03c32012-07-07 18:57:59 +00003044 SetPixelAlpha(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00003045 break;
3046 }
3047 case BlackQuantum:
3048 {
cristy8cd03c32012-07-07 18:57:59 +00003049 SetPixelBlack(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00003050 break;
3051 }
3052 case IndexQuantum:
3053 {
cristy8cd03c32012-07-07 18:57:59 +00003054 SetPixelGray(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00003055 break;
3056 }
3057 default:
3058 break;
3059 }
3060 p++;
3061 }
3062 q+=GetPixelChannels(image);
3063 }
3064 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3065 break;
3066 }
3067}
3068
cristycafe0412012-01-10 13:29:58 +00003069static void ImportLongPixel(Image *image,const RectangleInfo *roi,
cristy46f4be22012-01-07 00:26:39 +00003070 const char *restrict map,const QuantumType *quantum_map,const void *pixels,
3071 ExceptionInfo *exception)
cristye5370942012-01-06 03:49:31 +00003072{
3073 register const unsigned int
3074 *restrict p;
3075
3076 register Quantum
cristy3fe11452012-01-09 01:27:42 +00003077 *restrict q;
cristye5370942012-01-06 03:49:31 +00003078
3079 register ssize_t
3080 x;
3081
cristy14d71292012-05-20 16:48:13 +00003082 size_t
3083 length;
3084
cristye5370942012-01-06 03:49:31 +00003085 ssize_t
3086 y;
3087
3088 p=(const unsigned int *) pixels;
3089 if (LocaleCompare(map,"BGR") == 0)
3090 {
cristycafe0412012-01-10 13:29:58 +00003091 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00003092 {
cristycafe0412012-01-10 13:29:58 +00003093 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00003094 if (q == (Quantum *) NULL)
3095 break;
cristycafe0412012-01-10 13:29:58 +00003096 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00003097 {
3098 SetPixelBlue(image,ScaleLongToQuantum(*p++),q);
3099 SetPixelGreen(image,ScaleLongToQuantum(*p++),q);
3100 SetPixelRed(image,ScaleLongToQuantum(*p++),q);
3101 q+=GetPixelChannels(image);
3102 }
3103 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3104 break;
3105 }
3106 return;
3107 }
3108 if (LocaleCompare(map,"BGRA") == 0)
3109 {
cristycafe0412012-01-10 13:29:58 +00003110 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00003111 {
cristycafe0412012-01-10 13:29:58 +00003112 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00003113 if (q == (Quantum *) NULL)
3114 break;
cristycafe0412012-01-10 13:29:58 +00003115 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00003116 {
3117 SetPixelBlue(image,ScaleLongToQuantum(*p++),q);
3118 SetPixelGreen(image,ScaleLongToQuantum(*p++),q);
3119 SetPixelRed(image,ScaleLongToQuantum(*p++),q);
3120 SetPixelAlpha(image,ScaleLongToQuantum(*p++),q);
3121 q+=GetPixelChannels(image);
3122 }
3123 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3124 break;
3125 }
3126 return;
3127 }
3128 if (LocaleCompare(map,"BGRP") == 0)
3129 {
cristycafe0412012-01-10 13:29:58 +00003130 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00003131 {
cristycafe0412012-01-10 13:29:58 +00003132 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00003133 if (q == (Quantum *) NULL)
3134 break;
cristycafe0412012-01-10 13:29:58 +00003135 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00003136 {
3137 SetPixelBlue(image,ScaleLongToQuantum(*p++),q);
3138 SetPixelGreen(image,ScaleLongToQuantum(*p++),q);
3139 SetPixelRed(image,ScaleLongToQuantum(*p++),q);
3140 p++;
3141 q+=GetPixelChannels(image);
3142 }
3143 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3144 break;
3145 }
3146 return;
3147 }
3148 if (LocaleCompare(map,"I") == 0)
3149 {
cristycafe0412012-01-10 13:29:58 +00003150 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00003151 {
cristycafe0412012-01-10 13:29:58 +00003152 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00003153 if (q == (Quantum *) NULL)
3154 break;
cristycafe0412012-01-10 13:29:58 +00003155 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00003156 {
3157 SetPixelGray(image,ScaleLongToQuantum(*p++),q);
3158 q+=GetPixelChannels(image);
3159 }
3160 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3161 break;
3162 }
3163 return;
3164 }
3165 if (LocaleCompare(map,"RGB") == 0)
3166 {
cristycafe0412012-01-10 13:29:58 +00003167 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00003168 {
cristycafe0412012-01-10 13:29:58 +00003169 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00003170 if (q == (Quantum *) NULL)
3171 break;
cristycafe0412012-01-10 13:29:58 +00003172 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00003173 {
3174 SetPixelRed(image,ScaleLongToQuantum(*p++),q);
3175 SetPixelGreen(image,ScaleLongToQuantum(*p++),q);
3176 SetPixelBlue(image,ScaleLongToQuantum(*p++),q);
3177 q+=GetPixelChannels(image);
3178 }
3179 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3180 break;
3181 }
3182 return;
3183 }
3184 if (LocaleCompare(map,"RGBA") == 0)
3185 {
cristycafe0412012-01-10 13:29:58 +00003186 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00003187 {
cristycafe0412012-01-10 13:29:58 +00003188 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00003189 if (q == (Quantum *) NULL)
3190 break;
cristycafe0412012-01-10 13:29:58 +00003191 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00003192 {
3193 SetPixelRed(image,ScaleLongToQuantum(*p++),q);
3194 SetPixelGreen(image,ScaleLongToQuantum(*p++),q);
3195 SetPixelBlue(image,ScaleLongToQuantum(*p++),q);
3196 SetPixelAlpha(image,ScaleLongToQuantum(*p++),q);
3197 q+=GetPixelChannels(image);
3198 }
3199 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3200 break;
3201 }
3202 return;
3203 }
3204 if (LocaleCompare(map,"RGBP") == 0)
3205 {
cristycafe0412012-01-10 13:29:58 +00003206 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00003207 {
cristycafe0412012-01-10 13:29:58 +00003208 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00003209 if (q == (Quantum *) NULL)
3210 break;
cristycafe0412012-01-10 13:29:58 +00003211 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00003212 {
3213 SetPixelRed(image,ScaleLongToQuantum(*p++),q);
3214 SetPixelGreen(image,ScaleLongToQuantum(*p++),q);
3215 SetPixelBlue(image,ScaleLongToQuantum(*p++),q);
3216 p++;
3217 q+=GetPixelChannels(image);
3218 }
3219 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3220 break;
3221 }
3222 return;
3223 }
cristy14d71292012-05-20 16:48:13 +00003224 length=strlen(map);
cristycafe0412012-01-10 13:29:58 +00003225 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00003226 {
cristycafe0412012-01-10 13:29:58 +00003227 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00003228 if (q == (Quantum *) NULL)
3229 break;
cristycafe0412012-01-10 13:29:58 +00003230 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00003231 {
3232 register ssize_t
3233 i;
3234
cristy14d71292012-05-20 16:48:13 +00003235 for (i=0; i < (ssize_t) length; i++)
cristye5370942012-01-06 03:49:31 +00003236 {
3237 switch (quantum_map[i])
3238 {
3239 case RedQuantum:
3240 case CyanQuantum:
3241 {
3242 SetPixelRed(image,ScaleLongToQuantum(*p),q);
3243 break;
3244 }
3245 case GreenQuantum:
3246 case MagentaQuantum:
3247 {
3248 SetPixelGreen(image,ScaleLongToQuantum(*p),q);
3249 break;
3250 }
3251 case BlueQuantum:
3252 case YellowQuantum:
3253 {
3254 SetPixelBlue(image,ScaleLongToQuantum(*p),q);
3255 break;
3256 }
3257 case AlphaQuantum:
3258 {
3259 SetPixelAlpha(image,ScaleLongToQuantum(*p),q);
3260 break;
3261 }
3262 case OpacityQuantum:
3263 {
3264 SetPixelAlpha(image,ScaleLongToQuantum(*p),q);
3265 break;
3266 }
3267 case BlackQuantum:
3268 {
3269 SetPixelBlack(image,ScaleLongToQuantum(*p),q);
3270 break;
3271 }
3272 case IndexQuantum:
3273 {
3274 SetPixelGray(image,ScaleLongToQuantum(*p),q);
3275 break;
3276 }
3277 default:
3278 break;
3279 }
3280 p++;
3281 }
3282 q+=GetPixelChannels(image);
3283 }
3284 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3285 break;
3286 }
3287}
3288
cristycafe0412012-01-10 13:29:58 +00003289static void ImportLongLongPixel(Image *image,const RectangleInfo *roi,
cristy46f4be22012-01-07 00:26:39 +00003290 const char *restrict map,const QuantumType *quantum_map,const void *pixels,
3291 ExceptionInfo *exception)
cristye5370942012-01-06 03:49:31 +00003292{
cristyb13e12a2012-01-06 21:48:27 +00003293 register const MagickSizeType
cristye5370942012-01-06 03:49:31 +00003294 *restrict p;
3295
3296 register Quantum
cristy3fe11452012-01-09 01:27:42 +00003297 *restrict q;
cristye5370942012-01-06 03:49:31 +00003298
3299 register ssize_t
3300 x;
3301
cristy14d71292012-05-20 16:48:13 +00003302 size_t
3303 length;
3304
cristye5370942012-01-06 03:49:31 +00003305 ssize_t
3306 y;
3307
cristyb13e12a2012-01-06 21:48:27 +00003308 p=(const MagickSizeType *) pixels;
cristye5370942012-01-06 03:49:31 +00003309 if (LocaleCompare(map,"BGR") == 0)
3310 {
cristycafe0412012-01-10 13:29:58 +00003311 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00003312 {
cristycafe0412012-01-10 13:29:58 +00003313 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00003314 if (q == (Quantum *) NULL)
3315 break;
cristycafe0412012-01-10 13:29:58 +00003316 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00003317 {
cristyb13e12a2012-01-06 21:48:27 +00003318 SetPixelBlue(image,ScaleLongLongToQuantum(*p++),q);
3319 SetPixelGreen(image,ScaleLongLongToQuantum(*p++),q);
3320 SetPixelRed(image,ScaleLongLongToQuantum(*p++),q);
cristye5370942012-01-06 03:49:31 +00003321 q+=GetPixelChannels(image);
3322 }
3323 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3324 break;
3325 }
3326 return;
3327 }
3328 if (LocaleCompare(map,"BGRA") == 0)
3329 {
cristycafe0412012-01-10 13:29:58 +00003330 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00003331 {
cristycafe0412012-01-10 13:29:58 +00003332 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00003333 if (q == (Quantum *) NULL)
3334 break;
cristycafe0412012-01-10 13:29:58 +00003335 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00003336 {
cristyb13e12a2012-01-06 21:48:27 +00003337 SetPixelBlue(image,ScaleLongLongToQuantum(*p++),q);
3338 SetPixelGreen(image,ScaleLongLongToQuantum(*p++),q);
3339 SetPixelRed(image,ScaleLongLongToQuantum(*p++),q);
3340 SetPixelAlpha(image,ScaleLongLongToQuantum(*p++),q);
cristye5370942012-01-06 03:49:31 +00003341 q+=GetPixelChannels(image);
3342 }
3343 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3344 break;
3345 }
3346 return;
3347 }
3348 if (LocaleCompare(map,"BGRP") == 0)
3349 {
cristycafe0412012-01-10 13:29:58 +00003350 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00003351 {
cristycafe0412012-01-10 13:29:58 +00003352 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00003353 if (q == (Quantum *) NULL)
3354 break;
cristycafe0412012-01-10 13:29:58 +00003355 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00003356 {
cristyb13e12a2012-01-06 21:48:27 +00003357 SetPixelBlue(image,ScaleLongLongToQuantum(*p++),q);
3358 SetPixelGreen(image,ScaleLongLongToQuantum(*p++),q);
3359 SetPixelRed(image,ScaleLongLongToQuantum(*p++),q);
cristye5370942012-01-06 03:49:31 +00003360 p++;
3361 q+=GetPixelChannels(image);
3362 }
3363 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3364 break;
3365 }
3366 return;
3367 }
3368 if (LocaleCompare(map,"I") == 0)
3369 {
cristycafe0412012-01-10 13:29:58 +00003370 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00003371 {
cristycafe0412012-01-10 13:29:58 +00003372 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00003373 if (q == (Quantum *) NULL)
3374 break;
cristycafe0412012-01-10 13:29:58 +00003375 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00003376 {
cristyb13e12a2012-01-06 21:48:27 +00003377 SetPixelGray(image,ScaleLongLongToQuantum(*p++),q);
cristye5370942012-01-06 03:49:31 +00003378 q+=GetPixelChannels(image);
3379 }
3380 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3381 break;
3382 }
3383 return;
3384 }
3385 if (LocaleCompare(map,"RGB") == 0)
3386 {
cristycafe0412012-01-10 13:29:58 +00003387 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00003388 {
cristycafe0412012-01-10 13:29:58 +00003389 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00003390 if (q == (Quantum *) NULL)
3391 break;
cristycafe0412012-01-10 13:29:58 +00003392 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00003393 {
cristyb13e12a2012-01-06 21:48:27 +00003394 SetPixelRed(image,ScaleLongLongToQuantum(*p++),q);
3395 SetPixelGreen(image,ScaleLongLongToQuantum(*p++),q);
3396 SetPixelBlue(image,ScaleLongLongToQuantum(*p++),q);
cristye5370942012-01-06 03:49:31 +00003397 q+=GetPixelChannels(image);
3398 }
3399 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3400 break;
3401 }
3402 return;
3403 }
3404 if (LocaleCompare(map,"RGBA") == 0)
3405 {
cristycafe0412012-01-10 13:29:58 +00003406 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00003407 {
cristycafe0412012-01-10 13:29:58 +00003408 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00003409 if (q == (Quantum *) NULL)
3410 break;
cristycafe0412012-01-10 13:29:58 +00003411 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00003412 {
cristyb13e12a2012-01-06 21:48:27 +00003413 SetPixelRed(image,ScaleLongLongToQuantum(*p++),q);
3414 SetPixelGreen(image,ScaleLongLongToQuantum(*p++),q);
3415 SetPixelBlue(image,ScaleLongLongToQuantum(*p++),q);
3416 SetPixelAlpha(image,ScaleLongLongToQuantum(*p++),q);
cristye5370942012-01-06 03:49:31 +00003417 q+=GetPixelChannels(image);
3418 }
3419 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3420 break;
3421 }
3422 return;
3423 }
3424 if (LocaleCompare(map,"RGBP") == 0)
3425 {
cristycafe0412012-01-10 13:29:58 +00003426 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00003427 {
cristycafe0412012-01-10 13:29:58 +00003428 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00003429 if (q == (Quantum *) NULL)
3430 break;
cristycafe0412012-01-10 13:29:58 +00003431 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00003432 {
cristyb13e12a2012-01-06 21:48:27 +00003433 SetPixelRed(image,ScaleLongLongToQuantum(*p++),q);
3434 SetPixelGreen(image,ScaleLongLongToQuantum(*p++),q);
3435 SetPixelBlue(image,ScaleLongLongToQuantum(*p++),q);
cristye5370942012-01-06 03:49:31 +00003436 p++;
3437 q+=GetPixelChannels(image);
3438 }
3439 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3440 break;
3441 }
3442 return;
3443 }
cristy14d71292012-05-20 16:48:13 +00003444 length=strlen(map);
cristycafe0412012-01-10 13:29:58 +00003445 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00003446 {
cristycafe0412012-01-10 13:29:58 +00003447 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00003448 if (q == (Quantum *) NULL)
3449 break;
cristycafe0412012-01-10 13:29:58 +00003450 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00003451 {
3452 register ssize_t
3453 i;
3454
cristy14d71292012-05-20 16:48:13 +00003455 for (i=0; i < (ssize_t) length; i++)
cristye5370942012-01-06 03:49:31 +00003456 {
3457 switch (quantum_map[i])
3458 {
3459 case RedQuantum:
3460 case CyanQuantum:
3461 {
cristyb13e12a2012-01-06 21:48:27 +00003462 SetPixelRed(image,ScaleLongLongToQuantum(*p),q);
cristye5370942012-01-06 03:49:31 +00003463 break;
3464 }
3465 case GreenQuantum:
3466 case MagentaQuantum:
3467 {
cristyb13e12a2012-01-06 21:48:27 +00003468 SetPixelGreen(image,ScaleLongLongToQuantum(*p),q);
cristye5370942012-01-06 03:49:31 +00003469 break;
3470 }
3471 case BlueQuantum:
3472 case YellowQuantum:
3473 {
cristyb13e12a2012-01-06 21:48:27 +00003474 SetPixelBlue(image,ScaleLongLongToQuantum(*p),q);
cristye5370942012-01-06 03:49:31 +00003475 break;
3476 }
3477 case AlphaQuantum:
3478 {
cristyb13e12a2012-01-06 21:48:27 +00003479 SetPixelAlpha(image,ScaleLongLongToQuantum(*p),q);
cristye5370942012-01-06 03:49:31 +00003480 break;
3481 }
3482 case OpacityQuantum:
3483 {
cristyb13e12a2012-01-06 21:48:27 +00003484 SetPixelAlpha(image,ScaleLongLongToQuantum(*p),q);
cristye5370942012-01-06 03:49:31 +00003485 break;
3486 }
3487 case BlackQuantum:
3488 {
cristyb13e12a2012-01-06 21:48:27 +00003489 SetPixelBlack(image,ScaleLongLongToQuantum(*p),q);
cristye5370942012-01-06 03:49:31 +00003490 break;
3491 }
3492 case IndexQuantum:
3493 {
cristyb13e12a2012-01-06 21:48:27 +00003494 SetPixelGray(image,ScaleLongLongToQuantum(*p),q);
cristye5370942012-01-06 03:49:31 +00003495 break;
3496 }
3497 default:
3498 break;
3499 }
3500 p++;
3501 }
3502 q+=GetPixelChannels(image);
3503 }
3504 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3505 break;
3506 }
3507}
3508
cristycafe0412012-01-10 13:29:58 +00003509static void ImportQuantumPixel(Image *image,const RectangleInfo *roi,
cristy46f4be22012-01-07 00:26:39 +00003510 const char *restrict map,const QuantumType *quantum_map,const void *pixels,
3511 ExceptionInfo *exception)
cristye5370942012-01-06 03:49:31 +00003512{
3513 register const Quantum
3514 *restrict p;
3515
3516 register Quantum
cristy3fe11452012-01-09 01:27:42 +00003517 *restrict q;
cristye5370942012-01-06 03:49:31 +00003518
3519 register ssize_t
3520 x;
3521
cristy14d71292012-05-20 16:48:13 +00003522 size_t
3523 length;
3524
cristye5370942012-01-06 03:49:31 +00003525 ssize_t
3526 y;
3527
3528 p=(const Quantum *) pixels;
3529 if (LocaleCompare(map,"BGR") == 0)
3530 {
cristycafe0412012-01-10 13:29:58 +00003531 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00003532 {
cristycafe0412012-01-10 13:29:58 +00003533 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00003534 if (q == (Quantum *) NULL)
3535 break;
cristycafe0412012-01-10 13:29:58 +00003536 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00003537 {
3538 SetPixelBlue(image,*p++,q);
3539 SetPixelGreen(image,*p++,q);
3540 SetPixelRed(image,*p++,q);
3541 q+=GetPixelChannels(image);
3542 }
3543 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3544 break;
3545 }
3546 return;
3547 }
3548 if (LocaleCompare(map,"BGRA") == 0)
3549 {
cristycafe0412012-01-10 13:29:58 +00003550 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00003551 {
cristycafe0412012-01-10 13:29:58 +00003552 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00003553 if (q == (Quantum *) NULL)
3554 break;
cristycafe0412012-01-10 13:29:58 +00003555 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00003556 {
3557 SetPixelBlue(image,*p++,q);
3558 SetPixelGreen(image,*p++,q);
3559 SetPixelRed(image,*p++,q);
3560 SetPixelAlpha(image,*p++,q);
3561 q+=GetPixelChannels(image);
3562 }
3563 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3564 break;
3565 }
3566 return;
3567 }
3568 if (LocaleCompare(map,"BGRP") == 0)
3569 {
cristycafe0412012-01-10 13:29:58 +00003570 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00003571 {
cristycafe0412012-01-10 13:29:58 +00003572 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00003573 if (q == (Quantum *) NULL)
3574 break;
cristycafe0412012-01-10 13:29:58 +00003575 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00003576 {
3577 SetPixelBlue(image,*p++,q);
3578 SetPixelGreen(image,*p++,q);
3579 SetPixelRed(image,*p++,q);
3580 p++;
3581 q+=GetPixelChannels(image);
3582 }
3583 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3584 break;
3585 }
3586 return;
3587 }
3588 if (LocaleCompare(map,"I") == 0)
3589 {
cristycafe0412012-01-10 13:29:58 +00003590 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00003591 {
cristycafe0412012-01-10 13:29:58 +00003592 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00003593 if (q == (Quantum *) NULL)
3594 break;
cristycafe0412012-01-10 13:29:58 +00003595 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00003596 {
3597 SetPixelGray(image,*p++,q);
3598 q+=GetPixelChannels(image);
3599 }
3600 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3601 break;
3602 }
3603 return;
3604 }
3605 if (LocaleCompare(map,"RGB") == 0)
3606 {
cristycafe0412012-01-10 13:29:58 +00003607 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00003608 {
cristycafe0412012-01-10 13:29:58 +00003609 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00003610 if (q == (Quantum *) NULL)
3611 break;
cristycafe0412012-01-10 13:29:58 +00003612 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00003613 {
3614 SetPixelRed(image,*p++,q);
3615 SetPixelGreen(image,*p++,q);
3616 SetPixelBlue(image,*p++,q);
3617 q+=GetPixelChannels(image);
3618 }
3619 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3620 break;
3621 }
3622 return;
3623 }
3624 if (LocaleCompare(map,"RGBA") == 0)
3625 {
cristycafe0412012-01-10 13:29:58 +00003626 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00003627 {
cristycafe0412012-01-10 13:29:58 +00003628 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00003629 if (q == (Quantum *) NULL)
3630 break;
cristycafe0412012-01-10 13:29:58 +00003631 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00003632 {
3633 SetPixelRed(image,*p++,q);
3634 SetPixelGreen(image,*p++,q);
3635 SetPixelBlue(image,*p++,q);
3636 SetPixelAlpha(image,*p++,q);
3637 q+=GetPixelChannels(image);
3638 }
3639 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3640 break;
3641 }
3642 return;
3643 }
3644 if (LocaleCompare(map,"RGBP") == 0)
3645 {
cristycafe0412012-01-10 13:29:58 +00003646 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00003647 {
cristycafe0412012-01-10 13:29:58 +00003648 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00003649 if (q == (Quantum *) NULL)
3650 break;
cristycafe0412012-01-10 13:29:58 +00003651 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00003652 {
3653 SetPixelRed(image,*p++,q);
3654 SetPixelGreen(image,*p++,q);
3655 SetPixelBlue(image,*p++,q);
3656 p++;
3657 q+=GetPixelChannels(image);
3658 }
3659 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3660 break;
3661 }
3662 return;
3663 }
cristy14d71292012-05-20 16:48:13 +00003664 length=strlen(map);
cristycafe0412012-01-10 13:29:58 +00003665 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00003666 {
cristycafe0412012-01-10 13:29:58 +00003667 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00003668 if (q == (Quantum *) NULL)
3669 break;
cristycafe0412012-01-10 13:29:58 +00003670 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00003671 {
3672 register ssize_t
3673 i;
3674
cristy14d71292012-05-20 16:48:13 +00003675 for (i=0; i < (ssize_t) length; i++)
cristye5370942012-01-06 03:49:31 +00003676 {
3677 switch (quantum_map[i])
3678 {
3679 case RedQuantum:
3680 case CyanQuantum:
3681 {
3682 SetPixelRed(image,*p,q);
3683 break;
3684 }
3685 case GreenQuantum:
3686 case MagentaQuantum:
3687 {
3688 SetPixelGreen(image,*p,q);
3689 break;
3690 }
3691 case BlueQuantum:
3692 case YellowQuantum:
3693 {
3694 SetPixelBlue(image,*p,q);
3695 break;
3696 }
3697 case AlphaQuantum:
3698 {
3699 SetPixelAlpha(image,*p,q);
3700 break;
3701 }
3702 case OpacityQuantum:
3703 {
3704 SetPixelAlpha(image,*p,q);
3705 break;
3706 }
3707 case BlackQuantum:
3708 {
3709 SetPixelBlack(image,*p,q);
3710 break;
3711 }
3712 case IndexQuantum:
3713 {
3714 SetPixelGray(image,*p,q);
3715 break;
3716 }
3717 default:
3718 break;
3719 }
3720 p++;
3721 }
3722 q+=GetPixelChannels(image);
3723 }
3724 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3725 break;
3726 }
3727}
3728
cristycafe0412012-01-10 13:29:58 +00003729static void ImportShortPixel(Image *image,const RectangleInfo *roi,
cristy46f4be22012-01-07 00:26:39 +00003730 const char *restrict map,const QuantumType *quantum_map,const void *pixels,
3731 ExceptionInfo *exception)
cristye5370942012-01-06 03:49:31 +00003732{
3733 register const unsigned short
3734 *restrict p;
3735
3736 register Quantum
cristy3fe11452012-01-09 01:27:42 +00003737 *restrict q;
cristye5370942012-01-06 03:49:31 +00003738
3739 register ssize_t
3740 x;
3741
cristy14d71292012-05-20 16:48:13 +00003742 size_t
3743 length;
3744
cristye5370942012-01-06 03:49:31 +00003745 ssize_t
3746 y;
3747
3748 p=(const unsigned short *) pixels;
3749 if (LocaleCompare(map,"BGR") == 0)
3750 {
cristycafe0412012-01-10 13:29:58 +00003751 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00003752 {
cristycafe0412012-01-10 13:29:58 +00003753 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00003754 if (q == (Quantum *) NULL)
3755 break;
cristycafe0412012-01-10 13:29:58 +00003756 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00003757 {
3758 SetPixelBlue(image,ScaleShortToQuantum(*p++),q);
3759 SetPixelGreen(image,ScaleShortToQuantum(*p++),q);
3760 SetPixelRed(image,ScaleShortToQuantum(*p++),q);
3761 q+=GetPixelChannels(image);
3762 }
3763 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3764 break;
3765 }
3766 return;
3767 }
3768 if (LocaleCompare(map,"BGRA") == 0)
3769 {
cristycafe0412012-01-10 13:29:58 +00003770 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00003771 {
cristycafe0412012-01-10 13:29:58 +00003772 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00003773 if (q == (Quantum *) NULL)
3774 break;
cristycafe0412012-01-10 13:29:58 +00003775 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00003776 {
3777 SetPixelBlue(image,ScaleShortToQuantum(*p++),q);
3778 SetPixelGreen(image,ScaleShortToQuantum(*p++),q);
3779 SetPixelRed(image,ScaleShortToQuantum(*p++),q);
3780 SetPixelAlpha(image,ScaleShortToQuantum(*p++),q);
3781 q+=GetPixelChannels(image);
3782 }
3783 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3784 break;
3785 }
3786 return;
3787 }
3788 if (LocaleCompare(map,"BGRP") == 0)
3789 {
cristycafe0412012-01-10 13:29:58 +00003790 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00003791 {
cristycafe0412012-01-10 13:29:58 +00003792 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00003793 if (q == (Quantum *) NULL)
3794 break;
cristycafe0412012-01-10 13:29:58 +00003795 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00003796 {
3797 SetPixelBlue(image,ScaleShortToQuantum(*p++),q);
3798 SetPixelGreen(image,ScaleShortToQuantum(*p++),q);
3799 SetPixelRed(image,ScaleShortToQuantum(*p++),q);
3800 p++;
3801 q+=GetPixelChannels(image);
3802 }
3803 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3804 break;
3805 }
3806 return;
3807 }
3808 if (LocaleCompare(map,"I") == 0)
3809 {
cristycafe0412012-01-10 13:29:58 +00003810 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00003811 {
cristycafe0412012-01-10 13:29:58 +00003812 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00003813 if (q == (Quantum *) NULL)
3814 break;
cristycafe0412012-01-10 13:29:58 +00003815 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00003816 {
3817 SetPixelGray(image,ScaleShortToQuantum(*p++),q);
3818 q+=GetPixelChannels(image);
3819 }
3820 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3821 break;
3822 }
3823 return;
3824 }
3825 if (LocaleCompare(map,"RGB") == 0)
3826 {
cristycafe0412012-01-10 13:29:58 +00003827 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00003828 {
cristycafe0412012-01-10 13:29:58 +00003829 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00003830 if (q == (Quantum *) NULL)
3831 break;
cristycafe0412012-01-10 13:29:58 +00003832 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00003833 {
3834 SetPixelRed(image,ScaleShortToQuantum(*p++),q);
3835 SetPixelGreen(image,ScaleShortToQuantum(*p++),q);
3836 SetPixelBlue(image,ScaleShortToQuantum(*p++),q);
3837 q+=GetPixelChannels(image);
3838 }
3839 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3840 break;
3841 }
3842 return;
3843 }
3844 if (LocaleCompare(map,"RGBA") == 0)
3845 {
cristycafe0412012-01-10 13:29:58 +00003846 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00003847 {
cristycafe0412012-01-10 13:29:58 +00003848 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00003849 if (q == (Quantum *) NULL)
3850 break;
cristycafe0412012-01-10 13:29:58 +00003851 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00003852 {
3853 SetPixelRed(image,ScaleShortToQuantum(*p++),q);
3854 SetPixelGreen(image,ScaleShortToQuantum(*p++),q);
3855 SetPixelBlue(image,ScaleShortToQuantum(*p++),q);
3856 SetPixelAlpha(image,ScaleShortToQuantum(*p++),q);
3857 q+=GetPixelChannels(image);
3858 }
3859 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3860 break;
3861 }
3862 return;
3863 }
3864 if (LocaleCompare(map,"RGBP") == 0)
3865 {
cristycafe0412012-01-10 13:29:58 +00003866 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00003867 {
cristycafe0412012-01-10 13:29:58 +00003868 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00003869 if (q == (Quantum *) NULL)
3870 break;
cristycafe0412012-01-10 13:29:58 +00003871 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00003872 {
3873 SetPixelRed(image,ScaleShortToQuantum(*p++),q);
3874 SetPixelGreen(image,ScaleShortToQuantum(*p++),q);
3875 SetPixelBlue(image,ScaleShortToQuantum(*p++),q);
3876 p++;
3877 q+=GetPixelChannels(image);
3878 }
3879 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3880 break;
3881 }
3882 return;
3883 }
cristy14d71292012-05-20 16:48:13 +00003884 length=strlen(map);
cristycafe0412012-01-10 13:29:58 +00003885 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00003886 {
cristycafe0412012-01-10 13:29:58 +00003887 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00003888 if (q == (Quantum *) NULL)
3889 break;
cristycafe0412012-01-10 13:29:58 +00003890 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00003891 {
3892 register ssize_t
3893 i;
3894
cristy14d71292012-05-20 16:48:13 +00003895 for (i=0; i < (ssize_t) length; i++)
cristye5370942012-01-06 03:49:31 +00003896 {
3897 switch (quantum_map[i])
3898 {
3899 case RedQuantum:
3900 case CyanQuantum:
3901 {
3902 SetPixelRed(image,ScaleShortToQuantum(*p),q);
3903 break;
3904 }
3905 case GreenQuantum:
3906 case MagentaQuantum:
3907 {
3908 SetPixelGreen(image,ScaleShortToQuantum(*p),q);
3909 break;
3910 }
3911 case BlueQuantum:
3912 case YellowQuantum:
3913 {
3914 SetPixelBlue(image,ScaleShortToQuantum(*p),q);
3915 break;
3916 }
3917 case AlphaQuantum:
3918 {
3919 SetPixelAlpha(image,ScaleShortToQuantum(*p),q);
3920 break;
3921 }
3922 case OpacityQuantum:
3923 {
3924 SetPixelAlpha(image,ScaleShortToQuantum(*p),q);
3925 break;
3926 }
3927 case BlackQuantum:
3928 {
3929 SetPixelBlack(image,ScaleShortToQuantum(*p),q);
3930 break;
3931 }
3932 case IndexQuantum:
3933 {
3934 SetPixelGray(image,ScaleShortToQuantum(*p),q);
3935 break;
3936 }
3937 default:
3938 break;
3939 }
3940 p++;
3941 }
3942 q+=GetPixelChannels(image);
3943 }
3944 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3945 break;
3946 }
3947}
3948
cristycafe0412012-01-10 13:29:58 +00003949MagickExport MagickBooleanType ImportImagePixels(Image *image,const ssize_t x,
3950 const ssize_t y,const size_t width,const size_t height,const char *map,
3951 const StorageType type,const void *pixels,ExceptionInfo *exception)
cristy4c08aed2011-07-01 19:47:50 +00003952{
cristy4c08aed2011-07-01 19:47:50 +00003953 QuantumType
3954 *quantum_map;
3955
cristycafe0412012-01-10 13:29:58 +00003956 RectangleInfo
3957 roi;
3958
cristy4c08aed2011-07-01 19:47:50 +00003959 register ssize_t
cristye5370942012-01-06 03:49:31 +00003960 i;
cristy4c08aed2011-07-01 19:47:50 +00003961
cristy14d71292012-05-20 16:48:13 +00003962 size_t
3963 length;
3964
cristy4c08aed2011-07-01 19:47:50 +00003965 /*
3966 Allocate image structure.
3967 */
3968 assert(image != (Image *) NULL);
3969 assert(image->signature == MagickSignature);
3970 if (image->debug != MagickFalse)
3971 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
cristy14d71292012-05-20 16:48:13 +00003972 length=strlen(map);
3973 quantum_map=(QuantumType *) AcquireQuantumMemory(length,sizeof(*quantum_map));
cristy4c08aed2011-07-01 19:47:50 +00003974 if (quantum_map == (QuantumType *) NULL)
3975 ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
3976 image->filename);
cristy14d71292012-05-20 16:48:13 +00003977 for (i=0; i < (ssize_t) length; i++)
cristy4c08aed2011-07-01 19:47:50 +00003978 {
3979 switch (map[i])
3980 {
3981 case 'a':
3982 case 'A':
3983 {
3984 quantum_map[i]=AlphaQuantum;
cristy8a46d822012-08-28 23:32:39 +00003985 image->alpha_trait=BlendPixelTrait;
cristy4c08aed2011-07-01 19:47:50 +00003986 break;
3987 }
3988 case 'B':
3989 case 'b':
3990 {
3991 quantum_map[i]=BlueQuantum;
3992 break;
3993 }
3994 case 'C':
3995 case 'c':
3996 {
3997 quantum_map[i]=CyanQuantum;
cristy63240882011-08-05 19:05:27 +00003998 (void) SetImageColorspace(image,CMYKColorspace,exception);
cristy4c08aed2011-07-01 19:47:50 +00003999 break;
4000 }
4001 case 'g':
4002 case 'G':
4003 {
4004 quantum_map[i]=GreenQuantum;
4005 break;
4006 }
4007 case 'K':
4008 case 'k':
4009 {
4010 quantum_map[i]=BlackQuantum;
cristy63240882011-08-05 19:05:27 +00004011 (void) SetImageColorspace(image,CMYKColorspace,exception);
cristy4c08aed2011-07-01 19:47:50 +00004012 break;
4013 }
4014 case 'I':
4015 case 'i':
4016 {
4017 quantum_map[i]=IndexQuantum;
cristyb7b3da62012-07-05 15:43:37 +00004018 (void) SetImageColorspace(image,GRAYColorspace,exception);
cristy4c08aed2011-07-01 19:47:50 +00004019 break;
4020 }
4021 case 'm':
4022 case 'M':
4023 {
4024 quantum_map[i]=MagentaQuantum;
cristy63240882011-08-05 19:05:27 +00004025 (void) SetImageColorspace(image,CMYKColorspace,exception);
cristy4c08aed2011-07-01 19:47:50 +00004026 break;
4027 }
4028 case 'O':
4029 case 'o':
4030 {
4031 quantum_map[i]=OpacityQuantum;
cristy8a46d822012-08-28 23:32:39 +00004032 image->alpha_trait=BlendPixelTrait;
cristy4c08aed2011-07-01 19:47:50 +00004033 break;
4034 }
4035 case 'P':
4036 case 'p':
4037 {
4038 quantum_map[i]=UndefinedQuantum;
4039 break;
4040 }
4041 case 'R':
4042 case 'r':
4043 {
4044 quantum_map[i]=RedQuantum;
4045 break;
4046 }
4047 case 'Y':
4048 case 'y':
4049 {
4050 quantum_map[i]=YellowQuantum;
cristy63240882011-08-05 19:05:27 +00004051 (void) SetImageColorspace(image,CMYKColorspace,exception);
cristy4c08aed2011-07-01 19:47:50 +00004052 break;
4053 }
4054 default:
4055 {
4056 quantum_map=(QuantumType *) RelinquishMagickMemory(quantum_map);
cristy63240882011-08-05 19:05:27 +00004057 (void) ThrowMagickException(exception,GetMagickModule(),OptionError,
cristyefe601c2013-01-05 17:51:12 +00004058 "UnrecognizedPixelMap","`%s'",map);
cristy4c08aed2011-07-01 19:47:50 +00004059 return(MagickFalse);
4060 }
4061 }
4062 }
cristy63240882011-08-05 19:05:27 +00004063 if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
cristy4c08aed2011-07-01 19:47:50 +00004064 return(MagickFalse);
4065 /*
cristye5370942012-01-06 03:49:31 +00004066 Transfer the pixels from the pixel data to the image.
cristy4c08aed2011-07-01 19:47:50 +00004067 */
cristycafe0412012-01-10 13:29:58 +00004068 roi.width=width;
4069 roi.height=height;
4070 roi.x=x;
4071 roi.y=y;
cristy4c08aed2011-07-01 19:47:50 +00004072 switch (type)
4073 {
4074 case CharPixel:
4075 {
cristycafe0412012-01-10 13:29:58 +00004076 ImportCharPixel(image,&roi,map,quantum_map,pixels,exception);
cristy4c08aed2011-07-01 19:47:50 +00004077 break;
4078 }
4079 case DoublePixel:
4080 {
cristycafe0412012-01-10 13:29:58 +00004081 ImportDoublePixel(image,&roi,map,quantum_map,pixels,exception);
cristy4c08aed2011-07-01 19:47:50 +00004082 break;
4083 }
4084 case FloatPixel:
4085 {
cristycafe0412012-01-10 13:29:58 +00004086 ImportFloatPixel(image,&roi,map,quantum_map,pixels,exception);
cristy4c08aed2011-07-01 19:47:50 +00004087 break;
4088 }
cristy4c08aed2011-07-01 19:47:50 +00004089 case LongPixel:
4090 {
cristycafe0412012-01-10 13:29:58 +00004091 ImportLongPixel(image,&roi,map,quantum_map,pixels,exception);
cristy4c08aed2011-07-01 19:47:50 +00004092 break;
4093 }
cristy6c9e1682012-01-07 21:37:44 +00004094 case LongLongPixel:
4095 {
cristycafe0412012-01-10 13:29:58 +00004096 ImportLongLongPixel(image,&roi,map,quantum_map,pixels,exception);
cristy6c9e1682012-01-07 21:37:44 +00004097 break;
4098 }
cristy4c08aed2011-07-01 19:47:50 +00004099 case QuantumPixel:
4100 {
cristycafe0412012-01-10 13:29:58 +00004101 ImportQuantumPixel(image,&roi,map,quantum_map,pixels,exception);
cristy4c08aed2011-07-01 19:47:50 +00004102 break;
4103 }
4104 case ShortPixel:
4105 {
cristycafe0412012-01-10 13:29:58 +00004106 ImportShortPixel(image,&roi,map,quantum_map,pixels,exception);
cristy4c08aed2011-07-01 19:47:50 +00004107 break;
4108 }
4109 default:
4110 {
4111 quantum_map=(QuantumType *) RelinquishMagickMemory(quantum_map);
cristyc82a27b2011-10-21 01:07:16 +00004112 (void) ThrowMagickException(exception,GetMagickModule(),OptionError,
dirk94db6c12013-08-18 21:00:02 +00004113 "UnrecognizedStorageType","`%d'",type);
cristy4c08aed2011-07-01 19:47:50 +00004114 break;
4115 }
4116 }
4117 quantum_map=(QuantumType *) RelinquishMagickMemory(quantum_map);
4118 return(MagickTrue);
4119}
4120
4121/*
4122%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4123% %
4124% %
4125% %
cristybd5a96c2011-08-21 00:04:26 +00004126+ 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 %
4127% %
4128% %
4129% %
4130%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4131%
4132% InitializePixelChannelMap() defines the standard pixel component map.
4133%
4134% The format of the InitializePixelChannelMap() method is:
4135%
4136% void InitializePixelChannelMap(Image *image)
4137%
4138% A description of each parameter follows:
4139%
4140% o image: the image.
4141%
4142*/
cristy021216a2013-05-20 16:25:51 +00004143
4144static void LogPixelChannels(const Image *image)
4145{
4146 register ssize_t
4147 i;
4148
4149 (void) LogMagickEvent(PixelEvent,GetMagickModule(),"%s[%.20g]",
4150 image->filename,(double) image->number_channels);
4151 for (i=0; i < (ssize_t) image->number_channels; i++)
4152 {
4153 char
4154 traits[MaxTextExtent];
4155
4156 const char
4157 *name;
4158
4159 PixelChannel
4160 channel;
4161
4162 switch (GetPixelChannelChannel(image,i))
4163 {
4164 case RedPixelChannel:
4165 {
4166 name="red";
4167 if (image->colorspace == CMYKColorspace)
4168 name="cyan";
4169 if (image->colorspace == GRAYColorspace)
4170 name="gray";
4171 break;
4172 }
4173 case GreenPixelChannel:
4174 {
4175 name="green";
4176 if (image->colorspace == CMYKColorspace)
4177 name="magenta";
4178 break;
4179 }
4180 case BluePixelChannel:
4181 {
4182 name="blue";
4183 if (image->colorspace == CMYKColorspace)
4184 name="yellow";
4185 break;
4186 }
4187 case BlackPixelChannel:
4188 {
4189 name="black";
4190 if (image->storage_class == PseudoClass)
4191 name="index";
4192 break;
4193 }
4194 case IndexPixelChannel:
4195 {
4196 name="index";
4197 break;
4198 }
4199 case AlphaPixelChannel:
4200 {
4201 name="alpha";
4202 break;
4203 }
4204 case ReadMaskPixelChannel:
4205 {
cristy04817142013-05-20 17:14:03 +00004206 name="read-mask";
cristy021216a2013-05-20 16:25:51 +00004207 break;
4208 }
4209 case WriteMaskPixelChannel:
4210 {
cristy04817142013-05-20 17:14:03 +00004211 name="write-mask";
cristy021216a2013-05-20 16:25:51 +00004212 break;
4213 }
4214 case MetaPixelChannel:
4215 {
4216 name="meta";
4217 break;
4218 }
4219 default:
4220 name="undefined";
4221 }
4222 channel=GetPixelChannelChannel(image,i);
4223 *traits='\0';
4224 if ((GetPixelChannelTraits(image,channel) & UpdatePixelTrait) != 0)
4225 (void) ConcatenateMagickString(traits,"update,",MaxTextExtent);
4226 if ((GetPixelChannelTraits(image,channel) & BlendPixelTrait) != 0)
4227 (void) ConcatenateMagickString(traits,"blend,",MaxTextExtent);
4228 if ((GetPixelChannelTraits(image,channel) & CopyPixelTrait) != 0)
4229 (void) ConcatenateMagickString(traits,"copy,",MaxTextExtent);
4230 if (*traits == '\0')
4231 (void) ConcatenateMagickString(traits,"undefined,",MaxTextExtent);
4232 traits[strlen(traits)-1]='\0';
4233 (void) LogMagickEvent(PixelEvent,GetMagickModule()," %.20g: %s (%s)",
4234 (double) i,name,traits);
4235 }
4236}
4237
cristye2a912b2011-12-05 20:02:07 +00004238MagickExport void InitializePixelChannelMap(Image *image)
cristy77c30f52011-10-24 18:56:57 +00004239{
cristye2a912b2011-12-05 20:02:07 +00004240 PixelTrait
4241 trait;
4242
cristy77c30f52011-10-24 18:56:57 +00004243 register ssize_t
4244 i;
4245
cristyd26338f2011-12-14 02:39:30 +00004246 ssize_t
cristy77c30f52011-10-24 18:56:57 +00004247 n;
4248
4249 assert(image != (Image *) NULL);
4250 assert(image->signature == MagickSignature);
cristye2a912b2011-12-05 20:02:07 +00004251 (void) ResetMagickMemory(image->channel_map,0,MaxPixelChannels*
4252 sizeof(*image->channel_map));
4253 trait=UpdatePixelTrait;
cristy8a46d822012-08-28 23:32:39 +00004254 if (image->alpha_trait == BlendPixelTrait)
cristy61f18ad2011-12-08 21:12:37 +00004255 trait=(PixelTrait) (trait | BlendPixelTrait);
cristy77c30f52011-10-24 18:56:57 +00004256 n=0;
cristyc06c5802011-12-31 23:36:16 +00004257 if (image->colorspace == GRAYColorspace)
cristy77c30f52011-10-24 18:56:57 +00004258 {
cristycf1296e2012-08-26 23:40:49 +00004259 SetPixelChannelAttributes(image,BluePixelChannel,trait,n);
4260 SetPixelChannelAttributes(image,GreenPixelChannel,trait,n);
4261 SetPixelChannelAttributes(image,RedPixelChannel,trait,n++);
cristy3c316282011-12-15 15:43:24 +00004262 }
4263 else
4264 {
cristycf1296e2012-08-26 23:40:49 +00004265 SetPixelChannelAttributes(image,RedPixelChannel,trait,n++);
4266 SetPixelChannelAttributes(image,GreenPixelChannel,trait,n++);
4267 SetPixelChannelAttributes(image,BluePixelChannel,trait,n++);
cristy77c30f52011-10-24 18:56:57 +00004268 }
4269 if (image->colorspace == CMYKColorspace)
cristycf1296e2012-08-26 23:40:49 +00004270 SetPixelChannelAttributes(image,BlackPixelChannel,trait,n++);
cristy8a46d822012-08-28 23:32:39 +00004271 if (image->alpha_trait != UndefinedPixelTrait)
cristycf1296e2012-08-26 23:40:49 +00004272 SetPixelChannelAttributes(image,AlphaPixelChannel,CopyPixelTrait,n++);
cristye2a912b2011-12-05 20:02:07 +00004273 if (image->storage_class == PseudoClass)
cristycf1296e2012-08-26 23:40:49 +00004274 SetPixelChannelAttributes(image,IndexPixelChannel,CopyPixelTrait,n++);
cristy883fde12013-04-08 00:50:13 +00004275 if (image->read_mask != MagickFalse)
4276 SetPixelChannelAttributes(image,ReadMaskPixelChannel,CopyPixelTrait,n++);
4277 if (image->write_mask != MagickFalse)
4278 SetPixelChannelAttributes(image,WriteMaskPixelChannel,CopyPixelTrait,n++);
cristye2a912b2011-12-05 20:02:07 +00004279 assert((n+image->number_meta_channels) < MaxPixelChannels);
4280 for (i=0; i < (ssize_t) image->number_meta_channels; i++)
cristycf1296e2012-08-26 23:40:49 +00004281 SetPixelChannelAttributes(image,(PixelChannel) (MetaPixelChannel+i),
4282 CopyPixelTrait,n++);
cristyd26338f2011-12-14 02:39:30 +00004283 image->number_channels=(size_t) n;
cristy77c30f52011-10-24 18:56:57 +00004284 if (image->debug != MagickFalse)
4285 LogPixelChannels(image);
cristycf1296e2012-08-26 23:40:49 +00004286 (void) SetImageChannelMask(image,image->channel_mask);
cristy77c30f52011-10-24 18:56:57 +00004287}
cristybd5a96c2011-08-21 00:04:26 +00004288
4289/*
4290%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4291% %
4292% %
4293% %
cristya085a432011-07-30 01:39:32 +00004294% I n t e r p o l a t e P i x e l C h a n n e l %
4295% %
4296% %
4297% %
4298%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4299%
cristy884f6002011-07-31 00:51:45 +00004300% InterpolatePixelChannel() applies a pixel interpolation method between a
4301% floating point coordinate and the pixels surrounding that coordinate. No
4302% pixel area resampling, or scaling of the result is performed.
cristya085a432011-07-30 01:39:32 +00004303%
anthonycf4e33d2012-06-08 07:33:23 +00004304% Interpolation is restricted to just the specified channel.
4305%
cristya085a432011-07-30 01:39:32 +00004306% The format of the InterpolatePixelChannel method is:
4307%
4308% MagickBooleanType InterpolatePixelChannel(const Image *image,
cristy444eda62011-08-10 02:07:46 +00004309% const CacheView *image_view,const PixelChannel channel,
cristy5c4e2582011-09-11 19:21:03 +00004310% const PixelInterpolateMethod method,const double x,const double y,
cristya085a432011-07-30 01:39:32 +00004311% double *pixel,ExceptionInfo *exception)
4312%
4313% A description of each parameter follows:
4314%
4315% o image: the image.
4316%
4317% o image_view: the image view.
4318%
4319% o channel: the pixel channel to interpolate.
4320%
4321% o method: the pixel color interpolation method.
4322%
4323% o x,y: A double representing the current (x,y) position of the pixel.
4324%
4325% o pixel: return the interpolated pixel here.
4326%
4327% o exception: return any errors or warnings in this structure.
4328%
4329*/
cristy94ea1632011-07-30 20:40:25 +00004330
cristyb0a657e2012-08-29 00:45:37 +00004331static inline void CatromWeights(const double x,double (*weights)[4])
cristy884f6002011-07-31 00:51:45 +00004332{
cristya19f1d72012-08-07 18:24:38 +00004333 double
cristy884f6002011-07-31 00:51:45 +00004334 alpha,
nicolasd32d5e52012-06-12 15:34:10 +00004335 beta,
cristy884f6002011-07-31 00:51:45 +00004336 gamma;
4337
cristy5a5e4d92012-08-29 00:06:25 +00004338 /*
4339 Nicolas Robidoux' 10 flops (4* + 5- + 1+) refactoring of the computation
4340 of the standard four 1D Catmull-Rom weights. The sampling location is
4341 assumed between the second and third input pixel locations, and x is the
4342 position relative to the second input pixel location. Formulas originally
4343 derived for the VIPS (Virtual Image Processing System) library.
4344 */
cristya19f1d72012-08-07 18:24:38 +00004345 alpha=(double) 1.0-x;
4346 beta=(double) (-0.5)*x*alpha;
nicolasd32d5e52012-06-12 15:34:10 +00004347 (*weights)[0]=alpha*beta;
4348 (*weights)[3]=x*beta;
4349 /*
cristy5a5e4d92012-08-29 00:06:25 +00004350 The following computation of the inner weights from the outer ones work
4351 for all Keys cubics.
nicolasd32d5e52012-06-12 15:34:10 +00004352 */
4353 gamma=(*weights)[3]-(*weights)[0];
4354 (*weights)[1]=alpha-(*weights)[0]+gamma;
4355 (*weights)[2]=x-(*weights)[3]-gamma;
4356}
4357
cristyb0a657e2012-08-29 00:45:37 +00004358static inline void SplineWeights(const double x,double (*weights)[4])
nicolasd32d5e52012-06-12 15:34:10 +00004359{
cristy5a5e4d92012-08-29 00:06:25 +00004360 double
4361 alpha,
4362 beta;
4363
nicolasd32d5e52012-06-12 15:34:10 +00004364 /*
cristy58ee5012013-05-26 23:58:44 +00004365 Nicolas Robidoux' 12 flops (6* + 5- + 1+) refactoring of the computation
4366 of the standard four 1D cubic B-spline smoothing weights. The sampling
4367 location is assumed between the second and third input pixel locations,
4368 and x is the position relative to the second input pixel location.
nicolasd32d5e52012-06-12 15:34:10 +00004369 */
cristya19f1d72012-08-07 18:24:38 +00004370 alpha=(double) 1.0-x;
4371 (*weights)[3]=(double) (1.0/6.0)*x*x*x;
4372 (*weights)[0]=(double) (1.0/6.0)*alpha*alpha*alpha;
nicolasd32d5e52012-06-12 15:34:10 +00004373 beta=(*weights)[3]-(*weights)[0];
4374 (*weights)[1]=alpha-(*weights)[0]+beta;
4375 (*weights)[2]=x-(*weights)[3]-beta;
cristy884f6002011-07-31 00:51:45 +00004376}
4377
cristy94ea1632011-07-30 20:40:25 +00004378static inline double MeshInterpolate(const PointInfo *delta,const double p,
4379 const double x,const double y)
4380{
4381 return(delta->x*x+delta->y*y+(1.0-delta->x-delta->y)*p);
4382}
4383
anthonycf4e33d2012-06-08 07:33:23 +00004384/*
cristya19f1d72012-08-07 18:24:38 +00004385static inline ssize_t NearestNeighbor(const double x)
cristy884f6002011-07-31 00:51:45 +00004386{
4387 if (x >= 0.0)
4388 return((ssize_t) (x+0.5));
4389 return((ssize_t) (x-0.5));
4390}
anthonycf4e33d2012-06-08 07:33:23 +00004391*/
cristy884f6002011-07-31 00:51:45 +00004392
cristya085a432011-07-30 01:39:32 +00004393MagickExport MagickBooleanType InterpolatePixelChannel(const Image *image,
4394 const CacheView *image_view,const PixelChannel channel,
cristy5c4e2582011-09-11 19:21:03 +00004395 const PixelInterpolateMethod method,const double x,const double y,
cristya085a432011-07-30 01:39:32 +00004396 double *pixel,ExceptionInfo *exception)
4397{
cristya19f1d72012-08-07 18:24:38 +00004398 double
cristy94ea1632011-07-30 20:40:25 +00004399 alpha[16],
cristy884f6002011-07-31 00:51:45 +00004400 gamma,
4401 pixels[16];
cristy94ea1632011-07-30 20:40:25 +00004402
cristy58ee5012013-05-26 23:58:44 +00004403 MagickBooleanType
4404 status;
4405
4406 PixelInterpolateMethod
4407 interpolate;
4408
cristy94ea1632011-07-30 20:40:25 +00004409 PixelTrait
4410 traits;
4411
cristy94ea1632011-07-30 20:40:25 +00004412 register const Quantum
4413 *p;
4414
cristy50e64b82012-06-22 17:46:19 +00004415 register ssize_t
cristy94ea1632011-07-30 20:40:25 +00004416 i;
4417
cristya085a432011-07-30 01:39:32 +00004418 ssize_t
4419 x_offset,
4420 y_offset;
4421
4422 assert(image != (Image *) NULL);
4423 assert(image != (Image *) NULL);
4424 assert(image->signature == MagickSignature);
4425 assert(image_view != (CacheView *) NULL);
4426 status=MagickTrue;
cristy884f6002011-07-31 00:51:45 +00004427 *pixel=0.0;
cristycf1296e2012-08-26 23:40:49 +00004428 traits=GetPixelChannelTraits(image,channel);
cristya085a432011-07-30 01:39:32 +00004429 x_offset=(ssize_t) floor(x);
4430 y_offset=(ssize_t) floor(y);
anthonycf4e33d2012-06-08 07:33:23 +00004431 interpolate = method;
4432 if ( interpolate == UndefinedInterpolatePixel )
4433 interpolate = image->interpolate;
4434 switch (interpolate)
cristya085a432011-07-30 01:39:32 +00004435 {
cristy58ee5012013-05-26 23:58:44 +00004436 case AverageInterpolatePixel: /* nearest 4 neighbours */
4437 case Average9InterpolatePixel: /* nearest 9 neighbours */
4438 case Average16InterpolatePixel: /* nearest 16 neighbours */
cristy884f6002011-07-31 00:51:45 +00004439 {
cristyfb122372012-10-17 23:31:21 +00004440 ssize_t
4441 count;
anthonycf4e33d2012-06-08 07:33:23 +00004442
cristyfb122372012-10-17 23:31:21 +00004443 count=2; /* size of the area to average - default nearest 4 */
anthonycf4e33d2012-06-08 07:33:23 +00004444 if (interpolate == Average9InterpolatePixel)
4445 {
4446 count=3;
4447 x_offset=(ssize_t) (floor(x+0.5)-1);
4448 y_offset=(ssize_t) (floor(y+0.5)-1);
4449 }
cristyfb122372012-10-17 23:31:21 +00004450 else
4451 if (interpolate == Average16InterpolatePixel)
4452 {
4453 count=4;
4454 x_offset--;
4455 y_offset--;
4456 }
cristy021216a2013-05-20 16:25:51 +00004457 p=GetCacheViewVirtualPixels(image_view,x_offset,y_offset,(size_t) count,
4458 (size_t) count,exception);
cristy884f6002011-07-31 00:51:45 +00004459 if (p == (const Quantum *) NULL)
4460 {
4461 status=MagickFalse;
4462 break;
4463 }
cristy58ee5012013-05-26 23:58:44 +00004464 count*=count; /* Number of pixels to average */
cristy222b19c2011-08-04 01:35:11 +00004465 if ((traits & BlendPixelTrait) == 0)
cristy50e64b82012-06-22 17:46:19 +00004466 for (i=0; i < (ssize_t) count; i++)
cristy884f6002011-07-31 00:51:45 +00004467 {
4468 alpha[i]=1.0;
cristya19f1d72012-08-07 18:24:38 +00004469 pixels[i]=(double) p[i*GetPixelChannels(image)+channel];
cristy884f6002011-07-31 00:51:45 +00004470 }
4471 else
cristy50e64b82012-06-22 17:46:19 +00004472 for (i=0; i < (ssize_t) count; i++)
cristy884f6002011-07-31 00:51:45 +00004473 {
4474 alpha[i]=QuantumScale*GetPixelAlpha(image,p+i*
4475 GetPixelChannels(image));
4476 pixels[i]=alpha[i]*p[i*GetPixelChannels(image)+channel];
4477 }
cristy50e64b82012-06-22 17:46:19 +00004478 for (i=0; i < (ssize_t) count; i++)
cristy884f6002011-07-31 00:51:45 +00004479 {
cristy3e3ec3a2012-11-03 23:11:06 +00004480 gamma=PerceptibleReciprocal(alpha[i])/count;
anthonycf4e33d2012-06-08 07:33:23 +00004481 *pixel+=gamma*pixels[i];
cristy884f6002011-07-31 00:51:45 +00004482 }
4483 break;
4484 }
anthonycf4e33d2012-06-08 07:33:23 +00004485 case BilinearInterpolatePixel:
4486 default:
4487 {
4488 PointInfo
4489 delta,
4490 epsilon;
4491
4492 p=GetCacheViewVirtualPixels(image_view,x_offset,y_offset,2,2,exception);
4493 if (p == (const Quantum *) NULL)
4494 {
4495 status=MagickFalse;
4496 break;
4497 }
4498 if ((traits & BlendPixelTrait) == 0)
4499 for (i=0; i < 4; i++)
4500 {
4501 alpha[i]=1.0;
cristya19f1d72012-08-07 18:24:38 +00004502 pixels[i]=(double) p[i*GetPixelChannels(image)+channel];
anthonycf4e33d2012-06-08 07:33:23 +00004503 }
4504 else
4505 for (i=0; i < 4; i++)
4506 {
4507 alpha[i]=QuantumScale*GetPixelAlpha(image,p+i*
4508 GetPixelChannels(image));
4509 pixels[i]=alpha[i]*p[i*GetPixelChannels(image)+channel];
4510 }
4511 delta.x=x-x_offset;
4512 delta.y=y-y_offset;
4513 epsilon.x=1.0-delta.x;
4514 epsilon.y=1.0-delta.y;
4515 gamma=((epsilon.y*(epsilon.x*alpha[0]+delta.x*alpha[1])+delta.y*
4516 (epsilon.x*alpha[2]+delta.x*alpha[3])));
cristy3e3ec3a2012-11-03 23:11:06 +00004517 gamma=PerceptibleReciprocal(gamma);
anthonycf4e33d2012-06-08 07:33:23 +00004518 *pixel=gamma*(epsilon.y*(epsilon.x*pixels[0]+delta.x*pixels[1])+delta.y*
4519 (epsilon.x*pixels[2]+delta.x*pixels[3]));
4520 break;
4521 }
anthony5f78bca2012-10-05 06:51:00 +00004522 case BlendInterpolatePixel:
4523 {
4524 p=GetCacheViewVirtualPixels(image_view,x_offset,y_offset,2,2,exception);
4525 if (p == (const Quantum *) NULL)
4526 {
4527 status=MagickFalse;
4528 break;
4529 }
4530 if ((traits & BlendPixelTrait) == 0)
4531 for (i=0; i < 4; i++)
4532 {
4533 alpha[i]=1.0;
4534 pixels[i]=(MagickRealType) p[i*GetPixelChannels(image)+channel];
4535 }
4536 else
4537 for (i=0; i < 4; i++)
4538 {
4539 alpha[i]=QuantumScale*GetPixelAlpha(image,p+i*
4540 GetPixelChannels(image));
4541 pixels[i]=alpha[i]*p[i*GetPixelChannels(image)+channel];
4542 }
cristy58ee5012013-05-26 23:58:44 +00004543 gamma=1.0; /* number of pixels blended together (its variable) */
anthony5f78bca2012-10-05 06:51:00 +00004544 for (i=0; i <= 1L; i++) {
cristyfb122372012-10-17 23:31:21 +00004545 if ((y-y_offset) >= 0.75)
4546 {
4547 alpha[i]=alpha[i+2]; /* take right pixels */
4548 pixels[i]=pixels[i+2];
4549 }
4550 else
4551 if ((y-y_offset) > 0.25)
4552 {
4553 gamma=2.0; /* blend both pixels in row */
4554 alpha[i]+=alpha[i+2]; /* add up alpha weights */
4555 pixels[i]+=pixels[i+2];
4556 }
4557 }
4558 if ((x-x_offset) >= 0.75)
4559 {
4560 alpha[0]=alpha[1]; /* take bottom row blend */
4561 pixels[0]=pixels[1];
anthony5f78bca2012-10-05 06:51:00 +00004562 }
cristyfb122372012-10-17 23:31:21 +00004563 else
4564 if ((x-x_offset) > 0.25)
4565 {
4566 gamma*=2.0; /* blend both rows */
4567 alpha[0]+=alpha[1]; /* add up alpha weights */
4568 pixels[0]+=pixels[1];
4569 }
anthony5f78bca2012-10-05 06:51:00 +00004570 if (channel != AlphaPixelChannel)
cristy58ee5012013-05-26 23:58:44 +00004571 gamma=PerceptibleReciprocal(alpha[0]); /* (color) 1/alpha_weights */
anthony5f78bca2012-10-05 06:51:00 +00004572 else
cristy58ee5012013-05-26 23:58:44 +00004573 gamma=PerceptibleReciprocal(gamma); /* (alpha) 1/number_of_pixels */
anthony5f78bca2012-10-05 06:51:00 +00004574 *pixel=gamma*pixels[0];
4575 break;
4576 }
anthonycf4e33d2012-06-08 07:33:23 +00004577 case CatromInterpolatePixel:
cristy884f6002011-07-31 00:51:45 +00004578 {
cristya19f1d72012-08-07 18:24:38 +00004579 double
cristy380a11c2012-06-02 15:15:22 +00004580 cx[4],
nicolas6676f5a2012-06-12 16:01:15 +00004581 cy[4];
cristy884f6002011-07-31 00:51:45 +00004582
cristy884f6002011-07-31 00:51:45 +00004583 p=GetCacheViewVirtualPixels(image_view,x_offset-1,y_offset-1,4,4,
4584 exception);
4585 if (p == (const Quantum *) NULL)
4586 {
4587 status=MagickFalse;
4588 break;
4589 }
cristy222b19c2011-08-04 01:35:11 +00004590 if ((traits & BlendPixelTrait) == 0)
cristy884f6002011-07-31 00:51:45 +00004591 for (i=0; i < 16; i++)
4592 {
4593 alpha[i]=1.0;
cristya19f1d72012-08-07 18:24:38 +00004594 pixels[i]=(double) p[i*GetPixelChannels(image)+channel];
cristy884f6002011-07-31 00:51:45 +00004595 }
4596 else
4597 for (i=0; i < 16; i++)
4598 {
4599 alpha[i]=QuantumScale*GetPixelAlpha(image,p+i*
4600 GetPixelChannels(image));
4601 pixels[i]=alpha[i]*p[i*GetPixelChannels(image)+channel];
4602 }
cristya19f1d72012-08-07 18:24:38 +00004603 CatromWeights((double) (x-x_offset),&cx);
4604 CatromWeights((double) (y-y_offset),&cy);
4605 gamma=(channel == AlphaPixelChannel ? (double) 1.0 :
cristy3e3ec3a2012-11-03 23:11:06 +00004606 PerceptibleReciprocal(cy[0]*(cx[0]*alpha[0]+cx[1]*alpha[1]+cx[2]*
nicolasd32d5e52012-06-12 15:34:10 +00004607 alpha[2]+cx[3]*alpha[3])+cy[1]*(cx[0]*alpha[4]+cx[1]*alpha[5]+cx[2]*
4608 alpha[6]+cx[3]*alpha[7])+cy[2]*(cx[0]*alpha[8]+cx[1]*alpha[9]+cx[2]*
4609 alpha[10]+cx[3]*alpha[11])+cy[3]*(cx[0]*alpha[12]+cx[1]*alpha[13]+
4610 cx[2]*alpha[14]+cx[3]*alpha[15])));
cristy380a11c2012-06-02 15:15:22 +00004611 *pixel=gamma*(cy[0]*(cx[0]*pixels[0]+cx[1]*pixels[1]+cx[2]*pixels[2]+
nicolasd32d5e52012-06-12 15:34:10 +00004612 cx[3]*pixels[3])+cy[1]*(cx[0]*pixels[4]+cx[1]*pixels[5]+cx[2]*
4613 pixels[6]+cx[3]*pixels[7])+cy[2]*(cx[0]*pixels[8]+cx[1]*pixels[9]+
4614 cx[2]*pixels[10]+cx[3]*pixels[11])+cy[3]*(cx[0]*pixels[12]+cx[1]*
4615 pixels[13]+cx[2]*pixels[14]+cx[3]*pixels[15]));
cristy884f6002011-07-31 00:51:45 +00004616 break;
4617 }
cristy884f6002011-07-31 00:51:45 +00004618 case IntegerInterpolatePixel:
4619 {
4620 p=GetCacheViewVirtualPixels(image_view,x_offset,y_offset,1,1,exception);
4621 if (p == (const Quantum *) NULL)
4622 {
4623 status=MagickFalse;
4624 break;
4625 }
cristy0beccfa2011-09-25 20:47:53 +00004626 *pixel=(double) GetPixelChannel(image,channel,p);
cristy884f6002011-07-31 00:51:45 +00004627 break;
4628 }
anthonycf4e33d2012-06-08 07:33:23 +00004629 case NearestInterpolatePixel:
cristy884f6002011-07-31 00:51:45 +00004630 {
anthonycf4e33d2012-06-08 07:33:23 +00004631 x_offset=(ssize_t) floor(x+0.5);
4632 y_offset=(ssize_t) floor(y+0.5);
4633 p=GetCacheViewVirtualPixels(image_view,x_offset,y_offset,1,1,exception);
cristy884f6002011-07-31 00:51:45 +00004634 if (p == (const Quantum *) NULL)
4635 {
4636 status=MagickFalse;
4637 break;
4638 }
cristy0beccfa2011-09-25 20:47:53 +00004639 *pixel=(double) GetPixelChannel(image,channel,p);
cristy884f6002011-07-31 00:51:45 +00004640 break;
4641 }
4642 case MeshInterpolatePixel:
4643 {
4644 PointInfo
4645 delta,
cristy94ea1632011-07-30 20:40:25 +00004646 luminance;
4647
4648 p=GetCacheViewVirtualPixels(image_view,x_offset,y_offset,2,2,exception);
4649 if (p == (const Quantum *) NULL)
4650 {
4651 status=MagickFalse;
4652 break;
4653 }
cristy222b19c2011-08-04 01:35:11 +00004654 if ((traits & BlendPixelTrait) == 0)
cristy94ea1632011-07-30 20:40:25 +00004655 for (i=0; i < 4; i++)
4656 {
4657 alpha[i]=1.0;
cristya19f1d72012-08-07 18:24:38 +00004658 pixels[i]=(double) p[i*GetPixelChannels(image)+channel];
cristy94ea1632011-07-30 20:40:25 +00004659 }
4660 else
4661 for (i=0; i < 4; i++)
4662 {
4663 alpha[i]=QuantumScale*GetPixelAlpha(image,p+i*
4664 GetPixelChannels(image));
4665 pixels[i]=alpha[i]*p[i*GetPixelChannels(image)+channel];
4666 }
cristy884f6002011-07-31 00:51:45 +00004667 delta.x=x-x_offset;
4668 delta.y=y-y_offset;
cristyebfaacf2013-06-24 16:22:40 +00004669 luminance.x=GetPixelLuma(image,p)-(double)
4670 GetPixelLuma(image,p+3*GetPixelChannels(image));
4671 luminance.y=GetPixelLuma(image,p+GetPixelChannels(image))-(double)
4672 GetPixelLuma(image,p+2*GetPixelChannels(image));
cristy94ea1632011-07-30 20:40:25 +00004673 if (fabs(luminance.x) < fabs(luminance.y))
4674 {
4675 /*
4676 Diagonal 0-3 NW-SE.
4677 */
4678 if (delta.x <= delta.y)
4679 {
4680 /*
4681 Bottom-left triangle (pixel: 2, diagonal: 0-3).
4682 */
4683 delta.y=1.0-delta.y;
4684 gamma=MeshInterpolate(&delta,alpha[2],alpha[3],alpha[0]);
cristy3e3ec3a2012-11-03 23:11:06 +00004685 gamma=PerceptibleReciprocal(gamma);
cristy94ea1632011-07-30 20:40:25 +00004686 *pixel=gamma*MeshInterpolate(&delta,pixels[2],pixels[3],
4687 pixels[0]);
4688 }
4689 else
4690 {
4691 /*
4692 Top-right triangle (pixel: 1, diagonal: 0-3).
4693 */
4694 delta.x=1.0-delta.x;
4695 gamma=MeshInterpolate(&delta,alpha[1],alpha[0],alpha[3]);
cristy3e3ec3a2012-11-03 23:11:06 +00004696 gamma=PerceptibleReciprocal(gamma);
cristy94ea1632011-07-30 20:40:25 +00004697 *pixel=gamma*MeshInterpolate(&delta,pixels[1],pixels[0],
4698 pixels[3]);
4699 }
4700 }
4701 else
4702 {
4703 /*
4704 Diagonal 1-2 NE-SW.
4705 */
4706 if (delta.x <= (1.0-delta.y))
4707 {
4708 /*
4709 Top-left triangle (pixel: 0, diagonal: 1-2).
4710 */
4711 gamma=MeshInterpolate(&delta,alpha[0],alpha[1],alpha[2]);
cristy3e3ec3a2012-11-03 23:11:06 +00004712 gamma=PerceptibleReciprocal(gamma);
cristy94ea1632011-07-30 20:40:25 +00004713 *pixel=gamma*MeshInterpolate(&delta,pixels[0],pixels[1],
4714 pixels[2]);
4715 }
4716 else
4717 {
4718 /*
4719 Bottom-right triangle (pixel: 3, diagonal: 1-2).
4720 */
4721 delta.x=1.0-delta.x;
4722 delta.y=1.0-delta.y;
4723 gamma=MeshInterpolate(&delta,alpha[3],alpha[2],alpha[1]);
cristy3e3ec3a2012-11-03 23:11:06 +00004724 gamma=PerceptibleReciprocal(gamma);
cristy94ea1632011-07-30 20:40:25 +00004725 *pixel=gamma*MeshInterpolate(&delta,pixels[3],pixels[2],
4726 pixels[1]);
4727 }
4728 }
cristya085a432011-07-30 01:39:32 +00004729 break;
4730 }
cristy884f6002011-07-31 00:51:45 +00004731 case SplineInterpolatePixel:
4732 {
cristya19f1d72012-08-07 18:24:38 +00004733 double
nicolasd32d5e52012-06-12 15:34:10 +00004734 cx[4],
nicolas6676f5a2012-06-12 16:01:15 +00004735 cy[4];
cristy884f6002011-07-31 00:51:45 +00004736
4737 p=GetCacheViewVirtualPixels(image_view,x_offset-1,y_offset-1,4,4,
4738 exception);
4739 if (p == (const Quantum *) NULL)
4740 {
4741 status=MagickFalse;
4742 break;
4743 }
cristy222b19c2011-08-04 01:35:11 +00004744 if ((traits & BlendPixelTrait) == 0)
cristy884f6002011-07-31 00:51:45 +00004745 for (i=0; i < 16; i++)
4746 {
4747 alpha[i]=1.0;
cristya19f1d72012-08-07 18:24:38 +00004748 pixels[i]=(double) p[i*GetPixelChannels(image)+channel];
cristy884f6002011-07-31 00:51:45 +00004749 }
4750 else
4751 for (i=0; i < 16; i++)
4752 {
4753 alpha[i]=QuantumScale*GetPixelAlpha(image,p+i*
4754 GetPixelChannels(image));
4755 pixels[i]=alpha[i]*p[i*GetPixelChannels(image)+channel];
4756 }
cristya19f1d72012-08-07 18:24:38 +00004757 SplineWeights((double) (x-x_offset),&cx);
4758 SplineWeights((double) (y-y_offset),&cy);
4759 gamma=(channel == AlphaPixelChannel ? (double) 1.0 :
cristy3e3ec3a2012-11-03 23:11:06 +00004760 PerceptibleReciprocal(cy[0]*(cx[0]*alpha[0]+cx[1]*alpha[1]+cx[2]*
nicolasd32d5e52012-06-12 15:34:10 +00004761 alpha[2]+cx[3]*alpha[3])+cy[1]*(cx[0]*alpha[4]+cx[1]*alpha[5]+cx[2]*
4762 alpha[6]+cx[3]*alpha[7])+cy[2]*(cx[0]*alpha[8]+cx[1]*alpha[9]+cx[2]*
4763 alpha[10]+cx[3]*alpha[11])+cy[3]*(cx[0]*alpha[12]+cx[1]*alpha[13]+
4764 cx[2]*alpha[14]+cx[3]*alpha[15])));
4765 *pixel=gamma*(cy[0]*(cx[0]*pixels[0]+cx[1]*pixels[1]+cx[2]*pixels[2]+
4766 cx[3]*pixels[3])+cy[1]*(cx[0]*pixels[4]+cx[1]*pixels[5]+cx[2]*
4767 pixels[6]+cx[3]*pixels[7])+cy[2]*(cx[0]*pixels[8]+cx[1]*pixels[9]+
4768 cx[2]*pixels[10]+cx[3]*pixels[11])+cy[3]*(cx[0]*pixels[12]+cx[1]*
4769 pixels[13]+cx[2]*pixels[14]+cx[3]*pixels[15]));
cristy884f6002011-07-31 00:51:45 +00004770 break;
4771 }
cristya085a432011-07-30 01:39:32 +00004772 }
4773 return(status);
4774}
4775
4776/*
4777%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4778% %
4779% %
4780% %
cristy5c4e2582011-09-11 19:21:03 +00004781% I n t e r p o l a t e P i x e l C h a n n e l s %
4782% %
4783% %
4784% %
4785%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4786%
4787% InterpolatePixelChannels() applies a pixel interpolation method between a
4788% floating point coordinate and the pixels surrounding that coordinate. No
4789% pixel area resampling, or scaling of the result is performed.
4790%
anthonycf4e33d2012-06-08 07:33:23 +00004791% Interpolation is restricted to just the current channel setting of the
4792% destination image into which the color is to be stored
4793%
cristy5c4e2582011-09-11 19:21:03 +00004794% The format of the InterpolatePixelChannels method is:
4795%
4796% MagickBooleanType InterpolatePixelChannels(const Image *source,
4797% const CacheView *source_view,const Image *destination,
4798% const PixelInterpolateMethod method,const double x,const double y,
4799% Quantum *pixel,ExceptionInfo *exception)
4800%
4801% A description of each parameter follows:
4802%
4803% o source: the source.
4804%
4805% o source_view: the source view.
4806%
anthonycf4e33d2012-06-08 07:33:23 +00004807% o destination: the destination image, for the interpolated color
cristy5c4e2582011-09-11 19:21:03 +00004808%
4809% o method: the pixel color interpolation method.
4810%
4811% o x,y: A double representing the current (x,y) position of the pixel.
4812%
4813% o pixel: return the interpolated pixel here.
4814%
4815% o exception: return any errors or warnings in this structure.
4816%
4817*/
4818MagickExport MagickBooleanType InterpolatePixelChannels(const Image *source,
4819 const CacheView *source_view,const Image *destination,
4820 const PixelInterpolateMethod method,const double x,const double y,
4821 Quantum *pixel,ExceptionInfo *exception)
4822{
4823 MagickBooleanType
4824 status;
4825
cristya19f1d72012-08-07 18:24:38 +00004826 double
cristy5c4e2582011-09-11 19:21:03 +00004827 alpha[16],
4828 gamma,
4829 pixels[16];
4830
cristy5c4e2582011-09-11 19:21:03 +00004831 register const Quantum
4832 *p;
4833
cristy50e64b82012-06-22 17:46:19 +00004834 register ssize_t
cristy5c4e2582011-09-11 19:21:03 +00004835 i;
4836
4837 ssize_t
4838 x_offset,
4839 y_offset;
4840
anthonycf4e33d2012-06-08 07:33:23 +00004841 PixelInterpolateMethod
4842 interpolate;
4843
cristy5c4e2582011-09-11 19:21:03 +00004844 assert(source != (Image *) NULL);
4845 assert(source != (Image *) NULL);
4846 assert(source->signature == MagickSignature);
4847 assert(source_view != (CacheView *) NULL);
4848 status=MagickTrue;
4849 x_offset=(ssize_t) floor(x);
4850 y_offset=(ssize_t) floor(y);
anthonycf4e33d2012-06-08 07:33:23 +00004851 interpolate = method;
4852 if ( interpolate == UndefinedInterpolatePixel )
4853 interpolate = source->interpolate;
4854 switch (interpolate)
cristy5c4e2582011-09-11 19:21:03 +00004855 {
cristy58ee5012013-05-26 23:58:44 +00004856 case AverageInterpolatePixel: /* nearest 4 neighbours */
4857 case Average9InterpolatePixel: /* nearest 9 neighbours */
4858 case Average16InterpolatePixel: /* nearest 16 neighbours */
cristy5c4e2582011-09-11 19:21:03 +00004859 {
cristyfb122372012-10-17 23:31:21 +00004860 ssize_t
4861 count;
anthonycf4e33d2012-06-08 07:33:23 +00004862
cristyfb122372012-10-17 23:31:21 +00004863 count=2; /* size of the area to average - default nearest 4 */
anthonycf4e33d2012-06-08 07:33:23 +00004864 if (interpolate == Average9InterpolatePixel)
4865 {
4866 count=3;
4867 x_offset=(ssize_t) (floor(x+0.5)-1);
4868 y_offset=(ssize_t) (floor(y+0.5)-1);
4869 }
cristyfb122372012-10-17 23:31:21 +00004870 else
4871 if (interpolate == Average16InterpolatePixel)
4872 {
4873 count=4;
4874 x_offset--;
4875 y_offset--;
4876 }
cristy1b72b812013-04-19 00:57:44 +00004877 p=GetCacheViewVirtualPixels(source_view,x_offset,y_offset,(size_t) count,
4878 (size_t) count,exception);
cristy5c4e2582011-09-11 19:21:03 +00004879 if (p == (const Quantum *) NULL)
4880 {
4881 status=MagickFalse;
4882 break;
4883 }
cristy58ee5012013-05-26 23:58:44 +00004884 count*=count; /* Number of pixels to average */
cristy50e64b82012-06-22 17:46:19 +00004885 for (i=0; i < (ssize_t) GetPixelChannels(source); i++)
cristy5c4e2582011-09-11 19:21:03 +00004886 {
4887 double
4888 sum;
4889
cristy50e64b82012-06-22 17:46:19 +00004890 register ssize_t
cristy5c4e2582011-09-11 19:21:03 +00004891 j;
4892
cristy5a23c552013-02-13 14:34:28 +00004893 PixelChannel channel=GetPixelChannelChannel(source,i);
4894 PixelTrait traits=GetPixelChannelTraits(source,channel);
4895 PixelTrait destination_traits=GetPixelChannelTraits(destination,
4896 channel);
cristy5c4e2582011-09-11 19:21:03 +00004897 if ((traits == UndefinedPixelTrait) ||
4898 (destination_traits == UndefinedPixelTrait))
4899 continue;
cristy50e64b82012-06-22 17:46:19 +00004900 for (j=0; j < (ssize_t) count; j++)
cristya19f1d72012-08-07 18:24:38 +00004901 pixels[j]=(double) p[j*GetPixelChannels(source)+i];
cristy4a7ae692011-12-14 12:24:11 +00004902 sum=0.0;
cristy5c4e2582011-09-11 19:21:03 +00004903 if ((traits & BlendPixelTrait) == 0)
4904 {
cristy50e64b82012-06-22 17:46:19 +00004905 for (j=0; j < (ssize_t) count; j++)
anthonycf4e33d2012-06-08 07:33:23 +00004906 sum+=pixels[j];
4907 sum/=count;
cristy4a7ae692011-12-14 12:24:11 +00004908 SetPixelChannel(destination,channel,ClampToQuantum(sum),pixel);
cristy5c4e2582011-09-11 19:21:03 +00004909 continue;
4910 }
cristy50e64b82012-06-22 17:46:19 +00004911 for (j=0; j < (ssize_t) count; j++)
cristy5c4e2582011-09-11 19:21:03 +00004912 {
4913 alpha[j]=QuantumScale*GetPixelAlpha(source,p+j*
4914 GetPixelChannels(source));
4915 pixels[j]*=alpha[j];
cristy3e3ec3a2012-11-03 23:11:06 +00004916 gamma=PerceptibleReciprocal(alpha[j]);
anthonycf4e33d2012-06-08 07:33:23 +00004917 sum+=gamma*pixels[j];
cristy5c4e2582011-09-11 19:21:03 +00004918 }
anthonycf4e33d2012-06-08 07:33:23 +00004919 sum/=count;
cristy4a7ae692011-12-14 12:24:11 +00004920 SetPixelChannel(destination,channel,ClampToQuantum(sum),pixel);
cristy5c4e2582011-09-11 19:21:03 +00004921 }
4922 break;
4923 }
anthonycf4e33d2012-06-08 07:33:23 +00004924 case BilinearInterpolatePixel:
4925 default:
4926 {
4927 p=GetCacheViewVirtualPixels(source_view,x_offset,y_offset,2,2,exception);
4928 if (p == (const Quantum *) NULL)
4929 {
4930 status=MagickFalse;
4931 break;
4932 }
cristy50e64b82012-06-22 17:46:19 +00004933 for (i=0; i < (ssize_t) GetPixelChannels(source); i++)
anthonycf4e33d2012-06-08 07:33:23 +00004934 {
4935 PointInfo
4936 delta,
4937 epsilon;
4938
cristy5a23c552013-02-13 14:34:28 +00004939 PixelChannel channel=GetPixelChannelChannel(source,i);
4940 PixelTrait traits=GetPixelChannelTraits(source,channel);
4941 PixelTrait destination_traits=GetPixelChannelTraits(destination,
4942 channel);
anthonycf4e33d2012-06-08 07:33:23 +00004943 if ((traits == UndefinedPixelTrait) ||
4944 (destination_traits == UndefinedPixelTrait))
4945 continue;
4946 delta.x=x-x_offset;
4947 delta.y=y-y_offset;
4948 epsilon.x=1.0-delta.x;
4949 epsilon.y=1.0-delta.y;
cristya19f1d72012-08-07 18:24:38 +00004950 pixels[0]=(double) p[i];
4951 pixels[1]=(double) p[GetPixelChannels(source)+i];
4952 pixels[2]=(double) p[2*GetPixelChannels(source)+i];
4953 pixels[3]=(double) p[3*GetPixelChannels(source)+i];
anthonycf4e33d2012-06-08 07:33:23 +00004954 if ((traits & BlendPixelTrait) == 0)
4955 {
4956 gamma=((epsilon.y*(epsilon.x+delta.x)+delta.y*(epsilon.x+delta.x)));
cristy3e3ec3a2012-11-03 23:11:06 +00004957 gamma=PerceptibleReciprocal(gamma);
anthonycf4e33d2012-06-08 07:33:23 +00004958 SetPixelChannel(destination,channel,ClampToQuantum(gamma*(epsilon.y*
4959 (epsilon.x*pixels[0]+delta.x*pixels[1])+delta.y*(epsilon.x*
4960 pixels[2]+delta.x*pixels[3]))),pixel);
4961 continue;
4962 }
4963 alpha[0]=QuantumScale*GetPixelAlpha(source,p);
4964 alpha[1]=QuantumScale*GetPixelAlpha(source,p+GetPixelChannels(source));
4965 alpha[2]=QuantumScale*GetPixelAlpha(source,p+2*
4966 GetPixelChannels(source));
4967 alpha[3]=QuantumScale*GetPixelAlpha(source,p+3*
4968 GetPixelChannels(source));
4969 pixels[0]*=alpha[0];
4970 pixels[1]*=alpha[1];
4971 pixels[2]*=alpha[2];
4972 pixels[3]*=alpha[3];
4973 gamma=((epsilon.y*(epsilon.x*alpha[0]+delta.x*alpha[1])+delta.y*
4974 (epsilon.x*alpha[2]+delta.x*alpha[3])));
cristy3e3ec3a2012-11-03 23:11:06 +00004975 gamma=PerceptibleReciprocal(gamma);
anthonycf4e33d2012-06-08 07:33:23 +00004976 SetPixelChannel(destination,channel,ClampToQuantum(gamma*(epsilon.y*
4977 (epsilon.x*pixels[0]+delta.x*pixels[1])+delta.y*(epsilon.x*pixels[2]+
4978 delta.x*pixels[3]))),pixel);
4979 }
4980 break;
4981 }
anthony5f78bca2012-10-05 06:51:00 +00004982 case BlendInterpolatePixel:
4983 {
4984 p=GetCacheViewVirtualPixels(source_view,x_offset,y_offset,2,2,exception);
4985 if (p == (const Quantum *) NULL)
4986 {
4987 status=MagickFalse;
4988 break;
4989 }
4990 for (i=0; i < (ssize_t) GetPixelChannels(source); i++)
4991 {
4992 register ssize_t
4993 j;
4994
cristy5a23c552013-02-13 14:34:28 +00004995 PixelChannel channel=GetPixelChannelChannel(source,i);
4996 PixelTrait traits=GetPixelChannelTraits(source,channel);
4997 PixelTrait destination_traits=GetPixelChannelTraits(destination,
4998 channel);
anthony5f78bca2012-10-05 06:51:00 +00004999 if ((traits == UndefinedPixelTrait) ||
5000 (destination_traits == UndefinedPixelTrait))
5001 continue;
5002 if ((traits & BlendPixelTrait) == 0)
5003 for (j=0; j < 4; j++)
5004 {
5005 alpha[j]=1.0;
5006 pixels[j]=(MagickRealType) p[j*GetPixelChannels(source)+channel];
5007 }
5008 else
5009 for (j=0; j < 4; j++)
5010 {
5011 alpha[j]=QuantumScale*GetPixelAlpha(source,p+j*
5012 GetPixelChannels(source));
5013 pixels[j]=alpha[j]*p[j*GetPixelChannels(source)+channel];
5014 }
cristyfb122372012-10-17 23:31:21 +00005015 gamma=1.0; /* number of pixels blended together (its variable) */
5016 for (j=0; j <= 1L; j++)
5017 {
5018 if ((y-y_offset) >= 0.75)
5019 {
5020 alpha[j]=alpha[j+2]; /* take right pixels */
5021 pixels[j]=pixels[j+2];
5022 }
5023 else
5024 if ((y-y_offset) > 0.25)
5025 {
cristy58ee5012013-05-26 23:58:44 +00005026 gamma=2.0; /* blend both pixels in row */
cristyfb122372012-10-17 23:31:21 +00005027 alpha[j]+=alpha[j+2]; /* add up alpha weights */
5028 pixels[j]+=pixels[j+2];
5029 }
5030 }
5031 if ((x-x_offset) >= 0.75)
5032 {
5033 alpha[0]=alpha[1]; /* take bottom row blend */
5034 pixels[0]=pixels[1];
anthony5f78bca2012-10-05 06:51:00 +00005035 }
cristyfb122372012-10-17 23:31:21 +00005036 else
5037 if ((x-x_offset) > 0.25)
5038 {
5039 gamma*=2.0; /* blend both rows */
5040 alpha[0]+=alpha[1]; /* add up alpha weights */
5041 pixels[0]+=pixels[1];
5042 }
anthony5f78bca2012-10-05 06:51:00 +00005043 if ((traits & BlendPixelTrait) == 0)
cristy58ee5012013-05-26 23:58:44 +00005044 gamma=PerceptibleReciprocal(alpha[0]); /* (color) 1/alpha_weights */
anthony5f78bca2012-10-05 06:51:00 +00005045 else
cristy58ee5012013-05-26 23:58:44 +00005046 gamma=PerceptibleReciprocal(gamma); /* (alpha) 1/number_of_pixels */
anthony5f78bca2012-10-05 06:51:00 +00005047 SetPixelChannel(destination,channel,ClampToQuantum(gamma*pixels[0]),
cristyfb122372012-10-17 23:31:21 +00005048 pixel);
anthony5f78bca2012-10-05 06:51:00 +00005049 }
5050 break;
5051 }
anthonycf4e33d2012-06-08 07:33:23 +00005052 case CatromInterpolatePixel:
cristy5c4e2582011-09-11 19:21:03 +00005053 {
cristya19f1d72012-08-07 18:24:38 +00005054 double
cristy380a11c2012-06-02 15:15:22 +00005055 cx[4],
5056 cy[4];
cristy5c4e2582011-09-11 19:21:03 +00005057
cristy5c4e2582011-09-11 19:21:03 +00005058 p=GetCacheViewVirtualPixels(source_view,x_offset-1,y_offset-1,4,4,
5059 exception);
5060 if (p == (const Quantum *) NULL)
5061 {
5062 status=MagickFalse;
5063 break;
5064 }
cristy50e64b82012-06-22 17:46:19 +00005065 for (i=0; i < (ssize_t) GetPixelChannels(source); i++)
cristy5c4e2582011-09-11 19:21:03 +00005066 {
5067 register ssize_t
5068 j;
5069
cristy5a23c552013-02-13 14:34:28 +00005070 PixelChannel channel=GetPixelChannelChannel(source,i);
5071 PixelTrait traits=GetPixelChannelTraits(source,channel);
5072 PixelTrait destination_traits=GetPixelChannelTraits(destination,
5073 channel);
cristy5c4e2582011-09-11 19:21:03 +00005074 if ((traits == UndefinedPixelTrait) ||
5075 (destination_traits == UndefinedPixelTrait))
5076 continue;
5077 if ((traits & BlendPixelTrait) == 0)
5078 for (j=0; j < 16; j++)
5079 {
5080 alpha[j]=1.0;
cristya19f1d72012-08-07 18:24:38 +00005081 pixels[j]=(double) p[j*GetPixelChannels(source)+i];
cristy5c4e2582011-09-11 19:21:03 +00005082 }
5083 else
5084 for (j=0; j < 16; j++)
5085 {
5086 alpha[j]=QuantumScale*GetPixelAlpha(source,p+j*
5087 GetPixelChannels(source));
5088 pixels[j]=alpha[j]*p[j*GetPixelChannels(source)+i];
5089 }
cristya19f1d72012-08-07 18:24:38 +00005090 CatromWeights((double) (x-x_offset),&cx);
5091 CatromWeights((double) (y-y_offset),&cy);
5092 gamma=((traits & BlendPixelTrait) ? (double) (1.0) :
cristy3e3ec3a2012-11-03 23:11:06 +00005093 PerceptibleReciprocal(cy[0]*(cx[0]*alpha[0]+cx[1]*alpha[1]+cx[2]*
nicolasd32d5e52012-06-12 15:34:10 +00005094 alpha[2]+cx[3]*alpha[3])+cy[1]*(cx[0]*alpha[4]+cx[1]*alpha[5]+cx[2]*
5095 alpha[6]+cx[3]*alpha[7])+cy[2]*(cx[0]*alpha[8]+cx[1]*alpha[9]+cx[2]*
5096 alpha[10]+cx[3]*alpha[11])+cy[3]*(cx[0]*alpha[12]+cx[1]*alpha[13]+
5097 cx[2]*alpha[14]+cx[3]*alpha[15])));
cristy380a11c2012-06-02 15:15:22 +00005098 SetPixelChannel(destination,channel,ClampToQuantum(gamma*(cy[0]*(cx[0]*
5099 pixels[0]+cx[1]*pixels[1]+cx[2]*pixels[2]+cx[3]*pixels[3])+cy[1]*
5100 (cx[0]*pixels[4]+cx[1]*pixels[5]+cx[2]*pixels[6]+cx[3]*pixels[7])+
5101 cy[2]*(cx[0]*pixels[8]+cx[1]*pixels[9]+cx[2]*pixels[10]+cx[3]*
nicolasd32d5e52012-06-12 15:34:10 +00005102 pixels[11])+cy[3]*(cx[0]*pixels[12]+cx[1]*pixels[13]+cx[2]*
5103 pixels[14]+cx[3]*pixels[15]))),pixel);
cristy5c4e2582011-09-11 19:21:03 +00005104 }
5105 break;
5106 }
cristy5c4e2582011-09-11 19:21:03 +00005107 case IntegerInterpolatePixel:
5108 {
5109 p=GetCacheViewVirtualPixels(source_view,x_offset,y_offset,1,1,exception);
5110 if (p == (const Quantum *) NULL)
5111 {
5112 status=MagickFalse;
5113 break;
5114 }
cristy50e64b82012-06-22 17:46:19 +00005115 for (i=0; i < (ssize_t) GetPixelChannels(source); i++)
cristy5c4e2582011-09-11 19:21:03 +00005116 {
cristy5a23c552013-02-13 14:34:28 +00005117 PixelChannel channel=GetPixelChannelChannel(source,i);
5118 PixelTrait traits=GetPixelChannelTraits(source,channel);
5119 PixelTrait destination_traits=GetPixelChannelTraits(destination,
5120 channel);
cristy5c4e2582011-09-11 19:21:03 +00005121 if ((traits == UndefinedPixelTrait) ||
5122 (destination_traits == UndefinedPixelTrait))
5123 continue;
cristy4a7ae692011-12-14 12:24:11 +00005124 SetPixelChannel(destination,channel,p[i],pixel);
cristy5c4e2582011-09-11 19:21:03 +00005125 }
5126 break;
5127 }
anthonycf4e33d2012-06-08 07:33:23 +00005128 case NearestInterpolatePixel:
cristy5c4e2582011-09-11 19:21:03 +00005129 {
anthonycf4e33d2012-06-08 07:33:23 +00005130 x_offset=(ssize_t) floor(x+0.5);
5131 y_offset=(ssize_t) floor(y+0.5);
5132 p=GetCacheViewVirtualPixels(source_view,x_offset,y_offset,1,1,exception);
cristy5c4e2582011-09-11 19:21:03 +00005133 if (p == (const Quantum *) NULL)
5134 {
5135 status=MagickFalse;
5136 break;
5137 }
cristy50e64b82012-06-22 17:46:19 +00005138 for (i=0; i < (ssize_t) GetPixelChannels(source); i++)
cristy5c4e2582011-09-11 19:21:03 +00005139 {
cristy5a23c552013-02-13 14:34:28 +00005140 PixelChannel channel=GetPixelChannelChannel(source,i);
5141 PixelTrait traits=GetPixelChannelTraits(source,channel);
5142 PixelTrait destination_traits=GetPixelChannelTraits(destination,
5143 channel);
cristy5c4e2582011-09-11 19:21:03 +00005144 if ((traits == UndefinedPixelTrait) ||
5145 (destination_traits == UndefinedPixelTrait))
5146 continue;
cristy4a7ae692011-12-14 12:24:11 +00005147 SetPixelChannel(destination,channel,p[i],pixel);
cristy5c4e2582011-09-11 19:21:03 +00005148 }
5149 break;
5150 }
5151 case MeshInterpolatePixel:
5152 {
5153 p=GetCacheViewVirtualPixels(source_view,x_offset,y_offset,2,2,exception);
5154 if (p == (const Quantum *) NULL)
5155 {
5156 status=MagickFalse;
5157 break;
5158 }
cristy50e64b82012-06-22 17:46:19 +00005159 for (i=0; i < (ssize_t) GetPixelChannels(source); i++)
cristy5c4e2582011-09-11 19:21:03 +00005160 {
5161 PointInfo
5162 delta,
5163 luminance;
5164
cristy5a23c552013-02-13 14:34:28 +00005165 PixelChannel channel=GetPixelChannelChannel(source,i);
5166 PixelTrait traits=GetPixelChannelTraits(source,channel);
5167 PixelTrait destination_traits=GetPixelChannelTraits(destination,
5168 channel);
cristy5c4e2582011-09-11 19:21:03 +00005169 if ((traits == UndefinedPixelTrait) ||
5170 (destination_traits == UndefinedPixelTrait))
5171 continue;
cristya19f1d72012-08-07 18:24:38 +00005172 pixels[0]=(double) p[i];
5173 pixels[1]=(double) p[GetPixelChannels(source)+i];
5174 pixels[2]=(double) p[2*GetPixelChannels(source)+i];
5175 pixels[3]=(double) p[3*GetPixelChannels(source)+i];
cristy1861c902011-12-14 02:30:00 +00005176 if ((traits & BlendPixelTrait) == 0)
5177 {
5178 alpha[0]=1.0;
5179 alpha[1]=1.0;
5180 alpha[2]=1.0;
5181 alpha[3]=1.0;
5182 }
5183 else
5184 {
5185 alpha[0]=QuantumScale*GetPixelAlpha(source,p);
5186 alpha[1]=QuantumScale*GetPixelAlpha(source,p+
5187 GetPixelChannels(source));
5188 alpha[2]=QuantumScale*GetPixelAlpha(source,p+2*
5189 GetPixelChannels(source));
5190 alpha[3]=QuantumScale*GetPixelAlpha(source,p+3*
5191 GetPixelChannels(source));
5192 }
5193 delta.x=x-x_offset;
5194 delta.y=y-y_offset;
cristyebfaacf2013-06-24 16:22:40 +00005195 luminance.x=fabs((double) (GetPixelLuma(source,p)-
5196 GetPixelLuma(source,p+3*GetPixelChannels(source))));
5197 luminance.y=fabs((double) (GetPixelLuma(source,p+
5198 GetPixelChannels(source))-GetPixelLuma(source,p+2*
cristyfb122372012-10-17 23:31:21 +00005199 GetPixelChannels(source))));
anthonycf4e33d2012-06-08 07:33:23 +00005200 if (luminance.x < luminance.y)
cristy1861c902011-12-14 02:30:00 +00005201 {
5202 /*
5203 Diagonal 0-3 NW-SE.
5204 */
5205 if (delta.x <= delta.y)
5206 {
5207 /*
5208 Bottom-left triangle (pixel: 2, diagonal: 0-3).
5209 */
5210 delta.y=1.0-delta.y;
5211 gamma=MeshInterpolate(&delta,alpha[2],alpha[3],alpha[0]);
cristy3e3ec3a2012-11-03 23:11:06 +00005212 gamma=PerceptibleReciprocal(gamma);
cristy4a7ae692011-12-14 12:24:11 +00005213 SetPixelChannel(destination,channel,ClampToQuantum(gamma*
5214 MeshInterpolate(&delta,pixels[2],pixels[3],pixels[0])),pixel);
cristy1861c902011-12-14 02:30:00 +00005215 }
5216 else
5217 {
5218 /*
5219 Top-right triangle (pixel: 1, diagonal: 0-3).
5220 */
5221 delta.x=1.0-delta.x;
5222 gamma=MeshInterpolate(&delta,alpha[1],alpha[0],alpha[3]);
cristy3e3ec3a2012-11-03 23:11:06 +00005223 gamma=PerceptibleReciprocal(gamma);
cristy4a7ae692011-12-14 12:24:11 +00005224 SetPixelChannel(destination,channel,ClampToQuantum(gamma*
5225 MeshInterpolate(&delta,pixels[1],pixels[0],pixels[3])),pixel);
cristy1861c902011-12-14 02:30:00 +00005226 }
5227 }
5228 else
5229 {
5230 /*
5231 Diagonal 1-2 NE-SW.
5232 */
5233 if (delta.x <= (1.0-delta.y))
5234 {
5235 /*
5236 Top-left triangle (pixel: 0, diagonal: 1-2).
5237 */
5238 gamma=MeshInterpolate(&delta,alpha[0],alpha[1],alpha[2]);
cristy3e3ec3a2012-11-03 23:11:06 +00005239 gamma=PerceptibleReciprocal(gamma);
cristy4a7ae692011-12-14 12:24:11 +00005240 SetPixelChannel(destination,channel,ClampToQuantum(gamma*
5241 MeshInterpolate(&delta,pixels[0],pixels[1],pixels[2])),pixel);
cristy1861c902011-12-14 02:30:00 +00005242 }
5243 else
5244 {
5245 /*
5246 Bottom-right triangle (pixel: 3, diagonal: 1-2).
5247 */
5248 delta.x=1.0-delta.x;
5249 delta.y=1.0-delta.y;
5250 gamma=MeshInterpolate(&delta,alpha[3],alpha[2],alpha[1]);
cristy3e3ec3a2012-11-03 23:11:06 +00005251 gamma=PerceptibleReciprocal(gamma);
cristy4a7ae692011-12-14 12:24:11 +00005252 SetPixelChannel(destination,channel,ClampToQuantum(gamma*
5253 MeshInterpolate(&delta,pixels[3],pixels[2],pixels[1])),pixel);
cristy1861c902011-12-14 02:30:00 +00005254 }
5255 }
cristy5c4e2582011-09-11 19:21:03 +00005256 }
5257 break;
5258 }
5259 case SplineInterpolatePixel:
5260 {
cristya19f1d72012-08-07 18:24:38 +00005261 double
nicolasd32d5e52012-06-12 15:34:10 +00005262 cx[4],
5263 cy[4];
5264
cristy5c4e2582011-09-11 19:21:03 +00005265 p=GetCacheViewVirtualPixels(source_view,x_offset-1,y_offset-1,4,4,
5266 exception);
5267 if (p == (const Quantum *) NULL)
5268 {
5269 status=MagickFalse;
5270 break;
5271 }
cristy50e64b82012-06-22 17:46:19 +00005272 for (i=0; i < (ssize_t) GetPixelChannels(source); i++)
cristy5c4e2582011-09-11 19:21:03 +00005273 {
cristy5c4e2582011-09-11 19:21:03 +00005274 register ssize_t
5275 j;
5276
cristy5a23c552013-02-13 14:34:28 +00005277 PixelChannel channel=GetPixelChannelChannel(source,i);
5278 PixelTrait traits=GetPixelChannelTraits(source,channel);
5279 PixelTrait destination_traits=GetPixelChannelTraits(destination,
5280 channel);
cristy5c4e2582011-09-11 19:21:03 +00005281 if ((traits == UndefinedPixelTrait) ||
5282 (destination_traits == UndefinedPixelTrait))
5283 continue;
5284 if ((traits & BlendPixelTrait) == 0)
5285 for (j=0; j < 16; j++)
5286 {
5287 alpha[j]=1.0;
cristya19f1d72012-08-07 18:24:38 +00005288 pixels[j]=(double) p[j*GetPixelChannels(source)+i];
cristy5c4e2582011-09-11 19:21:03 +00005289 }
5290 else
5291 for (j=0; j < 16; j++)
5292 {
5293 alpha[j]=QuantumScale*GetPixelAlpha(source,p+j*
5294 GetPixelChannels(source));
5295 pixels[j]=alpha[j]*p[j*GetPixelChannels(source)+i];
5296 }
cristya19f1d72012-08-07 18:24:38 +00005297 SplineWeights((double) (x-x_offset),&cx);
5298 SplineWeights((double) (y-y_offset),&cy);
5299 gamma=((traits & BlendPixelTrait) ? (double) (1.0) :
cristy3e3ec3a2012-11-03 23:11:06 +00005300 PerceptibleReciprocal(cy[0]*(cx[0]*alpha[0]+cx[1]*alpha[1]+cx[2]*
nicolasd32d5e52012-06-12 15:34:10 +00005301 alpha[2]+cx[3]*alpha[3])+cy[1]*(cx[0]*alpha[4]+cx[1]*alpha[5]+cx[2]*
5302 alpha[6]+cx[3]*alpha[7])+cy[2]*(cx[0]*alpha[8]+cx[1]*alpha[9]+cx[2]*
5303 alpha[10]+cx[3]*alpha[11])+cy[3]*(cx[0]*alpha[12]+cx[1]*alpha[13]+
5304 cx[2]*alpha[14]+cx[3]*alpha[15])));
5305 SetPixelChannel(destination,channel,ClampToQuantum(gamma*(cy[0]*(cx[0]*
5306 pixels[0]+cx[1]*pixels[1]+cx[2]*pixels[2]+cx[3]*pixels[3])+cy[1]*
5307 (cx[0]*pixels[4]+cx[1]*pixels[5]+cx[2]*pixels[6]+cx[3]*pixels[7])+
5308 cy[2]*(cx[0]*pixels[8]+cx[1]*pixels[9]+cx[2]*pixels[10]+cx[3]*
5309 pixels[11])+cy[3]*(cx[0]*pixels[12]+cx[1]*pixels[13]+cx[2]*
5310 pixels[14]+cx[3]*pixels[15]))),pixel);
cristy5c4e2582011-09-11 19:21:03 +00005311 }
5312 break;
5313 }
5314 }
5315 return(status);
5316}
5317
5318/*
5319%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5320% %
5321% %
5322% %
cristy9075cdb2011-07-30 01:06:23 +00005323% 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 +00005324% %
5325% %
5326% %
5327%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5328%
cristy884f6002011-07-31 00:51:45 +00005329% InterpolatePixelInfo() applies a pixel interpolation method between a
5330% floating point coordinate and the pixels surrounding that coordinate. No
5331% pixel area resampling, or scaling of the result is performed.
cristy4c08aed2011-07-01 19:47:50 +00005332%
anthonycf4e33d2012-06-08 07:33:23 +00005333% Interpolation is restricted to just RGBKA channels.
5334%
cristy4c08aed2011-07-01 19:47:50 +00005335% The format of the InterpolatePixelInfo method is:
5336%
5337% MagickBooleanType InterpolatePixelInfo(const Image *image,
cristy5c4e2582011-09-11 19:21:03 +00005338% const CacheView *image_view,const PixelInterpolateMethod method,
cristy4c08aed2011-07-01 19:47:50 +00005339% const double x,const double y,PixelInfo *pixel,
5340% ExceptionInfo *exception)
5341%
5342% A description of each parameter follows:
5343%
5344% o image: the image.
5345%
5346% o image_view: the image view.
5347%
5348% o method: the pixel color interpolation method.
5349%
5350% o x,y: A double representing the current (x,y) position of the pixel.
5351%
5352% o pixel: return the interpolated pixel here.
5353%
5354% o exception: return any errors or warnings in this structure.
5355%
5356*/
5357
5358static inline void AlphaBlendPixelInfo(const Image *image,
cristya19f1d72012-08-07 18:24:38 +00005359 const Quantum *pixel,PixelInfo *pixel_info,double *alpha)
cristy4c08aed2011-07-01 19:47:50 +00005360{
cristy8a46d822012-08-28 23:32:39 +00005361 if (image->alpha_trait != BlendPixelTrait)
cristy4c08aed2011-07-01 19:47:50 +00005362 {
5363 *alpha=1.0;
cristya19f1d72012-08-07 18:24:38 +00005364 pixel_info->red=(double) GetPixelRed(image,pixel);
5365 pixel_info->green=(double) GetPixelGreen(image,pixel);
5366 pixel_info->blue=(double) GetPixelBlue(image,pixel);
cristy4c08aed2011-07-01 19:47:50 +00005367 pixel_info->black=0.0;
5368 if (image->colorspace == CMYKColorspace)
cristya19f1d72012-08-07 18:24:38 +00005369 pixel_info->black=(double) GetPixelBlack(image,pixel);
5370 pixel_info->alpha=(double) GetPixelAlpha(image,pixel);
cristy4c08aed2011-07-01 19:47:50 +00005371 return;
5372 }
5373 *alpha=QuantumScale*GetPixelAlpha(image,pixel);
5374 pixel_info->red=(*alpha*GetPixelRed(image,pixel));
5375 pixel_info->green=(*alpha*GetPixelGreen(image,pixel));
5376 pixel_info->blue=(*alpha*GetPixelBlue(image,pixel));
5377 pixel_info->black=0.0;
5378 if (image->colorspace == CMYKColorspace)
5379 pixel_info->black=(*alpha*GetPixelBlack(image,pixel));
cristya19f1d72012-08-07 18:24:38 +00005380 pixel_info->alpha=(double) GetPixelAlpha(image,pixel);
cristy4c08aed2011-07-01 19:47:50 +00005381}
5382
cristy4c08aed2011-07-01 19:47:50 +00005383MagickExport MagickBooleanType InterpolatePixelInfo(const Image *image,
cristy5c4e2582011-09-11 19:21:03 +00005384 const CacheView *image_view,const PixelInterpolateMethod method,
cristy4c08aed2011-07-01 19:47:50 +00005385 const double x,const double y,PixelInfo *pixel,ExceptionInfo *exception)
5386{
5387 MagickBooleanType
5388 status;
5389
cristya19f1d72012-08-07 18:24:38 +00005390 double
cristy4c08aed2011-07-01 19:47:50 +00005391 alpha[16],
5392 gamma;
5393
cristy865d58d2011-07-09 00:44:52 +00005394 PixelInfo
5395 pixels[16];
5396
cristy4c08aed2011-07-01 19:47:50 +00005397 register const Quantum
5398 *p;
5399
cristy50e64b82012-06-22 17:46:19 +00005400 register ssize_t
cristy4c08aed2011-07-01 19:47:50 +00005401 i;
5402
5403 ssize_t
5404 x_offset,
5405 y_offset;
5406
anthonycf4e33d2012-06-08 07:33:23 +00005407 PixelInterpolateMethod
5408 interpolate;
5409
cristy4c08aed2011-07-01 19:47:50 +00005410 assert(image != (Image *) NULL);
5411 assert(image->signature == MagickSignature);
5412 assert(image_view != (CacheView *) NULL);
5413 status=MagickTrue;
5414 x_offset=(ssize_t) floor(x);
5415 y_offset=(ssize_t) floor(y);
anthonycf4e33d2012-06-08 07:33:23 +00005416 interpolate = method;
5417 if ( interpolate == UndefinedInterpolatePixel )
5418 interpolate = image->interpolate;
5419 switch (interpolate)
cristy4c08aed2011-07-01 19:47:50 +00005420 {
cristy58ee5012013-05-26 23:58:44 +00005421 case AverageInterpolatePixel: /* nearest 4 neighbours */
5422 case Average9InterpolatePixel: /* nearest 9 neighbours */
5423 case Average16InterpolatePixel: /* nearest 16 neighbours */
cristy4c08aed2011-07-01 19:47:50 +00005424 {
cristyfb122372012-10-17 23:31:21 +00005425 ssize_t
5426 count;
anthonycf4e33d2012-06-08 07:33:23 +00005427
cristyfb122372012-10-17 23:31:21 +00005428 count=2; /* size of the area to average - default nearest 4 */
anthonycf4e33d2012-06-08 07:33:23 +00005429 if (interpolate == Average9InterpolatePixel)
5430 {
5431 count=3;
5432 x_offset=(ssize_t) (floor(x+0.5)-1);
5433 y_offset=(ssize_t) (floor(y+0.5)-1);
5434 }
5435 else if (interpolate == Average16InterpolatePixel)
5436 {
5437 count=4;
5438 x_offset--;
5439 y_offset--;
5440 }
cristy021216a2013-05-20 16:25:51 +00005441 p=GetCacheViewVirtualPixels(image_view,x_offset,y_offset,(size_t) count,
5442 (size_t) count,exception);
cristy4c08aed2011-07-01 19:47:50 +00005443 if (p == (const Quantum *) NULL)
5444 {
5445 status=MagickFalse;
5446 break;
5447 }
cristy4c08aed2011-07-01 19:47:50 +00005448 pixel->red=0.0;
5449 pixel->green=0.0;
5450 pixel->blue=0.0;
cristy4c08aed2011-07-01 19:47:50 +00005451 pixel->black=0.0;
cristy865d58d2011-07-09 00:44:52 +00005452 pixel->alpha=0.0;
cristy58ee5012013-05-26 23:58:44 +00005453 count*=count; /* number of pixels - square of size */
cristy50e64b82012-06-22 17:46:19 +00005454 for (i=0; i < (ssize_t) count; i++)
cristy4c08aed2011-07-01 19:47:50 +00005455 {
anthonycf4e33d2012-06-08 07:33:23 +00005456 AlphaBlendPixelInfo(image,p,pixels,alpha);
cristy3e3ec3a2012-11-03 23:11:06 +00005457 gamma=PerceptibleReciprocal(alpha[0]);
cristyfb122372012-10-17 23:31:21 +00005458 pixel->red+=gamma*pixels[0].red;
5459 pixel->green+=gamma*pixels[0].green;
5460 pixel->blue+=gamma*pixels[0].blue;
5461 pixel->black+=gamma*pixels[0].black;
5462 pixel->alpha+=pixels[0].alpha;
anthonycf4e33d2012-06-08 07:33:23 +00005463 p += GetPixelChannels(image);
cristy4c08aed2011-07-01 19:47:50 +00005464 }
anthonycf4e33d2012-06-08 07:33:23 +00005465 gamma=1.0/count; /* average weighting of each pixel in area */
cristyfb122372012-10-17 23:31:21 +00005466 pixel->red*=gamma;
5467 pixel->green*=gamma;
5468 pixel->blue*=gamma;
5469 pixel->black*=gamma;
5470 pixel->alpha*=gamma;
cristy4c08aed2011-07-01 19:47:50 +00005471 break;
5472 }
anthonycf4e33d2012-06-08 07:33:23 +00005473 case BackgroundInterpolatePixel:
5474 {
cristyfb122372012-10-17 23:31:21 +00005475 *pixel=image->background_color; /* Copy PixelInfo Structure */
anthonycf4e33d2012-06-08 07:33:23 +00005476 break;
5477 }
5478 case BilinearInterpolatePixel:
5479 default:
5480 {
5481 PointInfo
5482 delta,
5483 epsilon;
5484
5485 p=GetCacheViewVirtualPixels(image_view,x_offset,y_offset,2,2,exception);
5486 if (p == (const Quantum *) NULL)
5487 {
5488 status=MagickFalse;
5489 break;
5490 }
5491 for (i=0; i < 4L; i++)
5492 AlphaBlendPixelInfo(image,p+i*GetPixelChannels(image),pixels+i,alpha+i);
5493 delta.x=x-x_offset;
5494 delta.y=y-y_offset;
5495 epsilon.x=1.0-delta.x;
5496 epsilon.y=1.0-delta.y;
5497 gamma=((epsilon.y*(epsilon.x*alpha[0]+delta.x*alpha[1])+delta.y*
5498 (epsilon.x*alpha[2]+delta.x*alpha[3])));
cristy3e3ec3a2012-11-03 23:11:06 +00005499 gamma=PerceptibleReciprocal(gamma);
anthonycf4e33d2012-06-08 07:33:23 +00005500 pixel->red=gamma*(epsilon.y*(epsilon.x*pixels[0].red+delta.x*
5501 pixels[1].red)+delta.y*(epsilon.x*pixels[2].red+delta.x*pixels[3].red));
5502 pixel->green=gamma*(epsilon.y*(epsilon.x*pixels[0].green+delta.x*
5503 pixels[1].green)+delta.y*(epsilon.x*pixels[2].green+delta.x*
5504 pixels[3].green));
5505 pixel->blue=gamma*(epsilon.y*(epsilon.x*pixels[0].blue+delta.x*
5506 pixels[1].blue)+delta.y*(epsilon.x*pixels[2].blue+delta.x*
5507 pixels[3].blue));
5508 if (image->colorspace == CMYKColorspace)
5509 pixel->black=gamma*(epsilon.y*(epsilon.x*pixels[0].black+delta.x*
5510 pixels[1].black)+delta.y*(epsilon.x*pixels[2].black+delta.x*
5511 pixels[3].black));
5512 gamma=((epsilon.y*(epsilon.x+delta.x)+delta.y*(epsilon.x+delta.x)));
cristy3e3ec3a2012-11-03 23:11:06 +00005513 gamma=PerceptibleReciprocal(gamma);
anthonycf4e33d2012-06-08 07:33:23 +00005514 pixel->alpha=(epsilon.y*(epsilon.x*pixels[0].alpha+delta.x*
5515 pixels[1].alpha)+delta.y*(epsilon.x*pixels[2].alpha+delta.x*
5516 pixels[3].alpha));
5517 break;
5518 }
5519 case BlendInterpolatePixel:
5520 {
5521 p=GetCacheViewVirtualPixels(image_view,x_offset,y_offset,2,2,exception);
5522 if (p == (const Quantum *) NULL)
5523 {
5524 status=MagickFalse;
5525 break;
5526 }
5527 for (i=0; i < 4L; i++)
5528 AlphaBlendPixelInfo(image,p+i*GetPixelChannels(image),pixels+i,alpha+i);
cristyfb122372012-10-17 23:31:21 +00005529 gamma=1.0; /* number of pixels blended together (its variable) */
5530 for (i=0; i <= 1L; i++)
5531 {
5532 if ((y-y_offset) >= 0.75)
5533 {
5534 alpha[i]=alpha[i+2]; /* take right pixels */
5535 pixels[i]=pixels[i+2];
5536 }
5537 else
5538 if ((y-y_offset) > 0.25)
5539 {
5540 gamma=2.0; /* blend both pixels in row */
5541 alpha[i]+=alpha[i+2]; /* add up alpha weights */
5542 pixels[i].red+=pixels[i+2].red;
5543 pixels[i].green+=pixels[i+2].green;
5544 pixels[i].blue+=pixels[i+2].blue;
5545 pixels[i].black+=pixels[i+2].black;
5546 pixels[i].alpha+=pixels[i+2].alpha;
5547 }
5548 }
5549 if ((x-x_offset) >= 0.75)
5550 {
5551 alpha[0]=alpha[1];
5552 pixels[0]=pixels[1];
anthonycf4e33d2012-06-08 07:33:23 +00005553 }
cristyfb122372012-10-17 23:31:21 +00005554 else
5555 if ((x-x_offset) > 0.25)
5556 {
5557 gamma*=2.0; /* blend both rows */
cristy58ee5012013-05-26 23:58:44 +00005558 alpha[0]+= alpha[1]; /* add up alpha weights */
cristyfb122372012-10-17 23:31:21 +00005559 pixels[0].red+=pixels[1].red;
5560 pixels[0].green+=pixels[1].green;
5561 pixels[0].blue+=pixels[1].blue;
5562 pixels[0].black+=pixels[1].black;
5563 pixels[0].alpha+=pixels[1].alpha;
5564 }
5565 gamma=1.0/gamma;
cristy3e3ec3a2012-11-03 23:11:06 +00005566 alpha[0]=PerceptibleReciprocal(alpha[0]);
cristyfb122372012-10-17 23:31:21 +00005567 pixel->red=alpha[0]*pixels[0].red;
5568 pixel->green=alpha[0]*pixels[0].green; /* divide by sum of alpha */
5569 pixel->blue=alpha[0]*pixels[0].blue;
5570 pixel->black=alpha[0]*pixels[0].black;
5571 pixel->alpha=gamma*pixels[0].alpha; /* divide by number of pixels */
anthonycf4e33d2012-06-08 07:33:23 +00005572 break;
5573 }
5574 case CatromInterpolatePixel:
cristy4c08aed2011-07-01 19:47:50 +00005575 {
cristya19f1d72012-08-07 18:24:38 +00005576 double
cristy380a11c2012-06-02 15:15:22 +00005577 cx[4],
5578 cy[4];
cristy4c08aed2011-07-01 19:47:50 +00005579
cristy4c08aed2011-07-01 19:47:50 +00005580 p=GetCacheViewVirtualPixels(image_view,x_offset-1,y_offset-1,4,4,
5581 exception);
5582 if (p == (const Quantum *) NULL)
5583 {
5584 status=MagickFalse;
5585 break;
5586 }
anthonycf4e33d2012-06-08 07:33:23 +00005587 for (i=0; i < 16L; i++)
5588 AlphaBlendPixelInfo(image,p+i*GetPixelChannels(image),pixels+i,alpha+i);
cristya19f1d72012-08-07 18:24:38 +00005589 CatromWeights((double) (x-x_offset),&cx);
5590 CatromWeights((double) (y-y_offset),&cy);
cristyfb122372012-10-17 23:31:21 +00005591 pixel->red=(cy[0]*(cx[0]*pixels[0].red+cx[1]*pixels[1].red+cx[2]*
5592 pixels[2].red+cx[3]*pixels[3].red)+cy[1]*(cx[0]*pixels[4].red+cx[1]*
5593 pixels[5].red+cx[2]*pixels[6].red+cx[3]*pixels[7].red)+cy[2]*(cx[0]*
5594 pixels[8].red+cx[1]*pixels[9].red+cx[2]*pixels[10].red+cx[3]*
5595 pixels[11].red)+cy[3]*(cx[0]*pixels[12].red+cx[1]*pixels[13].red+cx[2]*
5596 pixels[14].red+cx[3]*pixels[15].red));
5597 pixel->green=(cy[0]*(cx[0]*pixels[0].green+cx[1]*pixels[1].green+cx[2]*
5598 pixels[2].green+cx[3]*pixels[3].green)+cy[1]*(cx[0]*pixels[4].green+
5599 cx[1]*pixels[5].green+cx[2]*pixels[6].green+cx[3]*pixels[7].green)+
5600 cy[2]*(cx[0]*pixels[8].green+cx[1]*pixels[9].green+cx[2]*
5601 pixels[10].green+cx[3]*pixels[11].green)+cy[3]*(cx[0]*
5602 pixels[12].green+cx[1]*pixels[13].green+cx[2]*pixels[14].green+cx[3]*
5603 pixels[15].green));
5604 pixel->blue=(cy[0]*(cx[0]*pixels[0].blue+cx[1]*pixels[1].blue+cx[2]*
5605 pixels[2].blue+cx[3]*pixels[3].blue)+cy[1]*(cx[0]*pixels[4].blue+cx[1]*
5606 pixels[5].blue+cx[2]*pixels[6].blue+cx[3]*pixels[7].blue)+cy[2]*(cx[0]*
5607 pixels[8].blue+cx[1]*pixels[9].blue+cx[2]*pixels[10].blue+cx[3]*
5608 pixels[11].blue)+cy[3]*(cx[0]*pixels[12].blue+cx[1]*pixels[13].blue+
5609 cx[2]*pixels[14].blue+cx[3]*pixels[15].blue));
cristy380a11c2012-06-02 15:15:22 +00005610 if (image->colorspace == CMYKColorspace)
cristyfb122372012-10-17 23:31:21 +00005611 pixel->black=(cy[0]*(cx[0]*pixels[0].black+cx[1]*pixels[1].black+cx[2]*
5612 pixels[2].black+cx[3]*pixels[3].black)+cy[1]*(cx[0]*pixels[4].black+
5613 cx[1]*pixels[5].black+cx[2]*pixels[6].black+cx[3]*pixels[7].black)+
5614 cy[2]*(cx[0]*pixels[8].black+cx[1]*pixels[9].black+cx[2]*
5615 pixels[10].black+cx[3]*pixels[11].black)+cy[3]*(cx[0]*
5616 pixels[12].black+cx[1]*pixels[13].black+cx[2]*pixels[14].black+cx[3]*
5617 pixels[15].black));
5618 pixel->alpha=(cy[0]*(cx[0]*pixels[0].alpha+cx[1]*pixels[1].alpha+cx[2]*
5619 pixels[2].alpha+cx[3]*pixels[3].alpha)+cy[1]*(cx[0]*pixels[4].alpha+
5620 cx[1]*pixels[5].alpha+cx[2]*pixels[6].alpha+cx[3]*pixels[7].alpha)+
5621 cy[2]*(cx[0]*pixels[8].alpha+cx[1]*pixels[9].alpha+cx[2]*
5622 pixels[10].alpha+cx[3]*pixels[11].alpha)+cy[3]*(cx[0]*pixels[12].alpha+
5623 cx[1]*pixels[13].alpha+cx[2]*pixels[14].alpha+cx[3]*pixels[15].alpha));
cristy4c08aed2011-07-01 19:47:50 +00005624 break;
5625 }
cristy4c08aed2011-07-01 19:47:50 +00005626 case IntegerInterpolatePixel:
5627 {
5628 p=GetCacheViewVirtualPixels(image_view,x_offset,y_offset,1,1,exception);
5629 if (p == (const Quantum *) NULL)
5630 {
5631 status=MagickFalse;
5632 break;
5633 }
cristy803640d2011-11-17 02:11:32 +00005634 GetPixelInfoPixel(image,p,pixel);
cristy4c08aed2011-07-01 19:47:50 +00005635 break;
5636 }
5637 case MeshInterpolatePixel:
5638 {
5639 PointInfo
5640 delta,
5641 luminance;
5642
cristy94ea1632011-07-30 20:40:25 +00005643 p=GetCacheViewVirtualPixels(image_view,x_offset,y_offset,2,2,exception);
cristy4c08aed2011-07-01 19:47:50 +00005644 if (p == (const Quantum *) NULL)
5645 {
5646 status=MagickFalse;
5647 break;
5648 }
cristy94ea1632011-07-30 20:40:25 +00005649 delta.x=x-x_offset;
5650 delta.y=y-y_offset;
cristyebfaacf2013-06-24 16:22:40 +00005651 luminance.x=GetPixelLuma(image,p)-(double)
5652 GetPixelLuma(image,p+3*GetPixelChannels(image));
5653 luminance.y=GetPixelLuma(image,p+GetPixelChannels(image))-(double)
5654 GetPixelLuma(image,p+2*GetPixelChannels(image));
cristy5ce8df82011-07-07 14:52:23 +00005655 AlphaBlendPixelInfo(image,p,pixels+0,alpha+0);
cristy28474bf2011-09-11 23:32:52 +00005656 AlphaBlendPixelInfo(image,p+GetPixelChannels(image),pixels+1,alpha+1);
cristyed231572011-07-14 02:18:59 +00005657 AlphaBlendPixelInfo(image,p+2*GetPixelChannels(image),pixels+2,alpha+2);
5658 AlphaBlendPixelInfo(image,p+3*GetPixelChannels(image),pixels+3,alpha+3);
cristy4c08aed2011-07-01 19:47:50 +00005659 if (fabs(luminance.x) < fabs(luminance.y))
5660 {
5661 /*
5662 Diagonal 0-3 NW-SE.
5663 */
5664 if (delta.x <= delta.y)
5665 {
5666 /*
cristy94ea1632011-07-30 20:40:25 +00005667 Bottom-left triangle (pixel: 2, diagonal: 0-3).
cristy4c08aed2011-07-01 19:47:50 +00005668 */
5669 delta.y=1.0-delta.y;
5670 gamma=MeshInterpolate(&delta,alpha[2],alpha[3],alpha[0]);
cristy3e3ec3a2012-11-03 23:11:06 +00005671 gamma=PerceptibleReciprocal(gamma);
cristy4c08aed2011-07-01 19:47:50 +00005672 pixel->red=gamma*MeshInterpolate(&delta,pixels[2].red,
5673 pixels[3].red,pixels[0].red);
5674 pixel->green=gamma*MeshInterpolate(&delta,pixels[2].green,
5675 pixels[3].green,pixels[0].green);
5676 pixel->blue=gamma*MeshInterpolate(&delta,pixels[2].blue,
5677 pixels[3].blue,pixels[0].blue);
cristy4c08aed2011-07-01 19:47:50 +00005678 if (image->colorspace == CMYKColorspace)
5679 pixel->black=gamma*MeshInterpolate(&delta,pixels[2].black,
5680 pixels[3].black,pixels[0].black);
cristy94ea1632011-07-30 20:40:25 +00005681 gamma=MeshInterpolate(&delta,1.0,1.0,1.0);
cristy865d58d2011-07-09 00:44:52 +00005682 pixel->alpha=gamma*MeshInterpolate(&delta,pixels[2].alpha,
5683 pixels[3].alpha,pixels[0].alpha);
cristy4c08aed2011-07-01 19:47:50 +00005684 }
5685 else
5686 {
5687 /*
cristy94ea1632011-07-30 20:40:25 +00005688 Top-right triangle (pixel:1 , diagonal: 0-3).
cristy4c08aed2011-07-01 19:47:50 +00005689 */
5690 delta.x=1.0-delta.x;
5691 gamma=MeshInterpolate(&delta,alpha[1],alpha[0],alpha[3]);
cristy3e3ec3a2012-11-03 23:11:06 +00005692 gamma=PerceptibleReciprocal(gamma);
cristy4c08aed2011-07-01 19:47:50 +00005693 pixel->red=gamma*MeshInterpolate(&delta,pixels[1].red,
5694 pixels[0].red,pixels[3].red);
5695 pixel->green=gamma*MeshInterpolate(&delta,pixels[1].green,
5696 pixels[0].green,pixels[3].green);
5697 pixel->blue=gamma*MeshInterpolate(&delta,pixels[1].blue,
5698 pixels[0].blue,pixels[3].blue);
cristy4c08aed2011-07-01 19:47:50 +00005699 if (image->colorspace == CMYKColorspace)
5700 pixel->black=gamma*MeshInterpolate(&delta,pixels[1].black,
5701 pixels[0].black,pixels[3].black);
cristy94ea1632011-07-30 20:40:25 +00005702 gamma=MeshInterpolate(&delta,1.0,1.0,1.0);
cristy865d58d2011-07-09 00:44:52 +00005703 pixel->alpha=gamma*MeshInterpolate(&delta,pixels[1].alpha,
5704 pixels[0].alpha,pixels[3].alpha);
cristy4c08aed2011-07-01 19:47:50 +00005705 }
5706 }
5707 else
5708 {
5709 /*
5710 Diagonal 1-2 NE-SW.
5711 */
5712 if (delta.x <= (1.0-delta.y))
5713 {
5714 /*
cristy94ea1632011-07-30 20:40:25 +00005715 Top-left triangle (pixel: 0, diagonal: 1-2).
cristy4c08aed2011-07-01 19:47:50 +00005716 */
5717 gamma=MeshInterpolate(&delta,alpha[0],alpha[1],alpha[2]);
cristy3e3ec3a2012-11-03 23:11:06 +00005718 gamma=PerceptibleReciprocal(gamma);
cristy4c08aed2011-07-01 19:47:50 +00005719 pixel->red=gamma*MeshInterpolate(&delta,pixels[0].red,
5720 pixels[1].red,pixels[2].red);
5721 pixel->green=gamma*MeshInterpolate(&delta,pixels[0].green,
5722 pixels[1].green,pixels[2].green);
5723 pixel->blue=gamma*MeshInterpolate(&delta,pixels[0].blue,
5724 pixels[1].blue,pixels[2].blue);
cristy4c08aed2011-07-01 19:47:50 +00005725 if (image->colorspace == CMYKColorspace)
5726 pixel->black=gamma*MeshInterpolate(&delta,pixels[0].black,
5727 pixels[1].black,pixels[2].black);
cristy94ea1632011-07-30 20:40:25 +00005728 gamma=MeshInterpolate(&delta,1.0,1.0,1.0);
cristy865d58d2011-07-09 00:44:52 +00005729 pixel->alpha=gamma*MeshInterpolate(&delta,pixels[0].alpha,
5730 pixels[1].alpha,pixels[2].alpha);
cristy4c08aed2011-07-01 19:47:50 +00005731 }
5732 else
5733 {
5734 /*
5735 Bottom-right triangle (pixel: 3, diagonal: 1-2).
5736 */
5737 delta.x=1.0-delta.x;
5738 delta.y=1.0-delta.y;
5739 gamma=MeshInterpolate(&delta,alpha[3],alpha[2],alpha[1]);
cristy3e3ec3a2012-11-03 23:11:06 +00005740 gamma=PerceptibleReciprocal(gamma);
cristy4c08aed2011-07-01 19:47:50 +00005741 pixel->red=gamma*MeshInterpolate(&delta,pixels[3].red,
5742 pixels[2].red,pixels[1].red);
5743 pixel->green=gamma*MeshInterpolate(&delta,pixels[3].green,
5744 pixels[2].green,pixels[1].green);
5745 pixel->blue=gamma*MeshInterpolate(&delta,pixels[3].blue,
5746 pixels[2].blue,pixels[1].blue);
cristy4c08aed2011-07-01 19:47:50 +00005747 if (image->colorspace == CMYKColorspace)
5748 pixel->black=gamma*MeshInterpolate(&delta,pixels[3].black,
5749 pixels[2].black,pixels[1].black);
cristy94ea1632011-07-30 20:40:25 +00005750 gamma=MeshInterpolate(&delta,1.0,1.0,1.0);
cristy865d58d2011-07-09 00:44:52 +00005751 pixel->alpha=gamma*MeshInterpolate(&delta,pixels[3].alpha,
5752 pixels[2].alpha,pixels[1].alpha);
cristy4c08aed2011-07-01 19:47:50 +00005753 }
5754 }
5755 break;
5756 }
anthonycf4e33d2012-06-08 07:33:23 +00005757 case NearestInterpolatePixel:
cristy4c08aed2011-07-01 19:47:50 +00005758 {
anthonycf4e33d2012-06-08 07:33:23 +00005759 x_offset=(ssize_t) floor(x+0.5);
5760 y_offset=(ssize_t) floor(y+0.5);
5761 p=GetCacheViewVirtualPixels(image_view,x_offset,y_offset,1,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00005762 if (p == (const Quantum *) NULL)
5763 {
5764 status=MagickFalse;
5765 break;
5766 }
cristy803640d2011-11-17 02:11:32 +00005767 GetPixelInfoPixel(image,p,pixel);
cristy4c08aed2011-07-01 19:47:50 +00005768 break;
5769 }
5770 case SplineInterpolatePixel:
5771 {
cristya19f1d72012-08-07 18:24:38 +00005772 double
nicolasd32d5e52012-06-12 15:34:10 +00005773 cx[4],
5774 cy[4];
cristy4c08aed2011-07-01 19:47:50 +00005775
5776 p=GetCacheViewVirtualPixels(image_view,x_offset-1,y_offset-1,4,4,
5777 exception);
5778 if (p == (const Quantum *) NULL)
5779 {
5780 status=MagickFalse;
5781 break;
5782 }
anthonycf4e33d2012-06-08 07:33:23 +00005783 for (i=0; i < 16L; i++)
5784 AlphaBlendPixelInfo(image,p+i*GetPixelChannels(image),pixels+i,alpha+i);
cristya19f1d72012-08-07 18:24:38 +00005785 SplineWeights((double) (x-x_offset),&cx);
5786 SplineWeights((double) (y-y_offset),&cy);
cristyfb122372012-10-17 23:31:21 +00005787 pixel->red=(cy[0]*(cx[0]*pixels[0].red+cx[1]*pixels[1].red+cx[2]*
5788 pixels[2].red+cx[3]*pixels[3].red)+cy[1]*(cx[0]*pixels[4].red+cx[1]*
5789 pixels[5].red+cx[2]*pixels[6].red+cx[3]*pixels[7].red)+cy[2]*(cx[0]*
5790 pixels[8].red+cx[1]*pixels[9].red+cx[2]*pixels[10].red+cx[3]*
5791 pixels[11].red)+cy[3]*(cx[0]*pixels[12].red+cx[1]*pixels[13].red+cx[2]*
5792 pixels[14].red+cx[3]*pixels[15].red));
5793 pixel->green=(cy[0]*(cx[0]*pixels[0].green+cx[1]*pixels[1].green+cx[2]*
5794 pixels[2].green+cx[3]*pixels[3].green)+cy[1]*(cx[0]*pixels[4].green+
5795 cx[1]*pixels[5].green+cx[2]*pixels[6].green+cx[3]*pixels[7].green)+
5796 cy[2]*(cx[0]*pixels[8].green+cx[1]*pixels[9].green+cx[2]*
5797 pixels[10].green+cx[3]*pixels[11].green)+cy[3]*(cx[0]*pixels[12].green+
5798 cx[1]*pixels[13].green+cx[2]*pixels[14].green+cx[3]*pixels[15].green));
5799 pixel->blue=(cy[0]*(cx[0]*pixels[0].blue+cx[1]*pixels[1].blue+cx[2]*
5800 pixels[2].blue+cx[3]*pixels[3].blue)+cy[1]*(cx[0]*pixels[4].blue+cx[1]*
5801 pixels[5].blue+cx[2]*pixels[6].blue+cx[3]*pixels[7].blue)+cy[2]*(cx[0]*
5802 pixels[8].blue+cx[1]*pixels[9].blue+cx[2]*pixels[10].blue+cx[3]*
5803 pixels[11].blue)+cy[3]*(cx[0]*pixels[12].blue+cx[1]*pixels[13].blue+
5804 cx[2]*pixels[14].blue+cx[3]*pixels[15].blue));
nicolasd32d5e52012-06-12 15:34:10 +00005805 if (image->colorspace == CMYKColorspace)
cristyfb122372012-10-17 23:31:21 +00005806 pixel->black=(cy[0]*(cx[0]*pixels[0].black+cx[1]*pixels[1].black+cx[2]*
5807 pixels[2].black+cx[3]*pixels[3].black)+cy[1]*(cx[0]*pixels[4].black+
5808 cx[1]*pixels[5].black+cx[2]*pixels[6].black+cx[3]*pixels[7].black)+
5809 cy[2]*(cx[0]*pixels[8].black+cx[1]*pixels[9].black+cx[2]*
5810 pixels[10].black+cx[3]*pixels[11].black)+cy[3]*(cx[0]*
5811 pixels[12].black+cx[1]*pixels[13].black+cx[2]*pixels[14].black+cx[3]*
5812 pixels[15].black));
5813 pixel->alpha=(cy[0]*(cx[0]*pixels[0].alpha+cx[1]*pixels[1].alpha+cx[2]*
5814 pixels[2].alpha+cx[3]*pixels[3].alpha)+cy[1]*(cx[0]*pixels[4].alpha+
5815 cx[1]*pixels[5].alpha+cx[2]*pixels[6].alpha+cx[3]*pixels[7].alpha)+
5816 cy[2]*(cx[0]*pixels[8].alpha+cx[1]*pixels[9].alpha+cx[2]*
5817 pixels[10].alpha+cx[3]*pixels[11].alpha)+cy[3]*(cx[0]*pixels[12].alpha+
5818 cx[1]*pixels[13].alpha+cx[2]*pixels[14].alpha+cx[3]*pixels[15].alpha));
cristy4c08aed2011-07-01 19:47:50 +00005819 break;
5820 }
5821 }
5822 return(status);
5823}
5824
5825/*
5826%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5827% %
5828% %
5829% %
5830+ I s F u z z y E q u i v a l e n c e P i x e l %
5831% %
5832% %
5833% %
5834%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5835%
5836% IsFuzzyEquivalencePixel() returns MagickTrue if the distance between two
5837% pixels is less than the specified distance in a linear three (or four)u
5838% dimensional color space.
5839%
5840% The format of the IsFuzzyEquivalencePixel method is:
5841%
cristye4a40472011-12-22 02:56:19 +00005842% void IsFuzzyEquivalencePixel(const Image *source,const Quantum *p,
5843% const Image *destination,const Quantum *q)
cristy4c08aed2011-07-01 19:47:50 +00005844%
5845% A description of each parameter follows:
5846%
cristye4a40472011-12-22 02:56:19 +00005847% o source: the source image.
cristy4c08aed2011-07-01 19:47:50 +00005848%
5849% o p: Pixel p.
5850%
cristye4a40472011-12-22 02:56:19 +00005851% o destination: the destination image.
5852%
cristy4c08aed2011-07-01 19:47:50 +00005853% o q: Pixel q.
5854%
5855*/
cristye4a40472011-12-22 02:56:19 +00005856MagickExport MagickBooleanType IsFuzzyEquivalencePixel(const Image *source,
5857 const Quantum *p,const Image *destination,const Quantum *q)
cristy4c08aed2011-07-01 19:47:50 +00005858{
cristya19f1d72012-08-07 18:24:38 +00005859 double
cristy4c08aed2011-07-01 19:47:50 +00005860 fuzz,
5861 pixel;
5862
cristya19f1d72012-08-07 18:24:38 +00005863 register double
cristy4c08aed2011-07-01 19:47:50 +00005864 distance,
5865 scale;
5866
cristy3522bf42013-08-04 14:53:18 +00005867 fuzz=(double) MagickMax(source->fuzz,(MagickRealType) MagickSQ1_2)*MagickMax(
5868 destination->fuzz,(MagickRealType) MagickSQ1_2);
cristy4c08aed2011-07-01 19:47:50 +00005869 scale=1.0;
5870 distance=0.0;
cristy8a46d822012-08-28 23:32:39 +00005871 if (source->alpha_trait == BlendPixelTrait)
cristy4c08aed2011-07-01 19:47:50 +00005872 {
5873 /*
5874 Transparencies are involved - set alpha distance
5875 */
cristy70e9f682013-03-12 22:31:22 +00005876 pixel=GetPixelAlpha(source,p)-(double) GetPixelAlpha(destination,q);
cristy4c08aed2011-07-01 19:47:50 +00005877 distance=pixel*pixel;
5878 if (distance > fuzz)
5879 return(MagickFalse);
5880 /*
5881 Generate a alpha scaling factor to generate a 4D cone on colorspace
5882 Note that if one color is transparent, distance has no color component.
5883 */
cristye4a40472011-12-22 02:56:19 +00005884 scale=QuantumScale*GetPixelAlpha(source,p);
5885 scale*=QuantumScale*GetPixelAlpha(destination,q);
cristy4c08aed2011-07-01 19:47:50 +00005886 if (scale <= MagickEpsilon)
5887 return(MagickTrue);
5888 }
5889 /*
5890 RGB or CMY color cube
5891 */
5892 distance*=3.0; /* rescale appropriately */
5893 fuzz*=3.0;
cristya19f1d72012-08-07 18:24:38 +00005894 pixel=GetPixelRed(source,p)-(double) GetPixelRed(destination,q);
cristye4a40472011-12-22 02:56:19 +00005895 if ((source->colorspace == HSLColorspace) ||
5896 (source->colorspace == HSBColorspace) ||
5897 (source->colorspace == HWBColorspace))
cristy4c08aed2011-07-01 19:47:50 +00005898 {
5899 /*
5900 Compute an arc distance for hue. It should be a vector angle of
5901 'S'/'W' length with 'L'/'B' forming appropriate cones.
5902 */
5903 if (fabs((double) pixel) > (QuantumRange/2))
5904 pixel-=QuantumRange;
5905 pixel*=2;
5906 }
5907 distance+=scale*pixel*pixel;
5908 if (distance > fuzz)
5909 return(MagickFalse);
cristya19f1d72012-08-07 18:24:38 +00005910 pixel=GetPixelGreen(source,p)-(double) GetPixelGreen(destination,q);
cristy4c08aed2011-07-01 19:47:50 +00005911 distance+=scale*pixel*pixel;
5912 if (distance > fuzz)
5913 return(MagickFalse);
cristya19f1d72012-08-07 18:24:38 +00005914 pixel=GetPixelBlue(source,p)-(double) GetPixelBlue(destination,q);
cristy4c08aed2011-07-01 19:47:50 +00005915 distance+=scale*pixel*pixel;
5916 if (distance > fuzz)
5917 return(MagickFalse);
5918 return(MagickTrue);
5919}
5920
5921/*
5922%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5923% %
5924% %
5925% %
5926+ 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 %
5927% %
5928% %
5929% %
5930%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5931%
5932% IsFuzzyEquivalencePixelInfo() returns true if the distance between two
5933% colors is less than the specified distance in a linear three (or four)
5934% dimensional color space.
5935%
cristy5f95f4f2011-10-23 01:01:01 +00005936% This implements the equivalent of:
5937% fuzz < sqrt(color_distance^2 * u.a*v.a + alpha_distance^2)
cristy4c08aed2011-07-01 19:47:50 +00005938%
5939% Which produces a multi-dimensional cone for that colorspace along the
5940% transparency vector.
5941%
cristy5f95f4f2011-10-23 01:01:01 +00005942% For example for an RGB:
cristy4c08aed2011-07-01 19:47:50 +00005943% color_distance^2 = ( (u.r-v.r)^2 + (u.g-v.g)^2 + (u.b-v.b)^2 ) / 3
5944%
5945% See http://www.imagemagick.org/Usage/bugs/fuzz_distance/
5946%
5947% Hue colorspace distances need more work. Hue is not a distance, it is an
5948% angle!
5949%
5950% A check that q is in the same color space as p should be made and the
5951% appropriate mapping made. -- Anthony Thyssen 8 December 2010
5952%
5953% The format of the IsFuzzyEquivalencePixelInfo method is:
5954%
5955% MagickBooleanType IsFuzzyEquivalencePixelInfo(const PixelInfo *p,
5956% const PixelInfo *q)
5957%
5958% A description of each parameter follows:
5959%
5960% o p: Pixel p.
5961%
5962% o q: Pixel q.
5963%
5964*/
5965MagickExport MagickBooleanType IsFuzzyEquivalencePixelInfo(const PixelInfo *p,
5966 const PixelInfo *q)
5967{
cristya19f1d72012-08-07 18:24:38 +00005968 double
cristy4c08aed2011-07-01 19:47:50 +00005969 fuzz,
5970 pixel;
5971
cristya19f1d72012-08-07 18:24:38 +00005972 register double
cristy4c08aed2011-07-01 19:47:50 +00005973 scale,
5974 distance;
5975
5976 if ((p->fuzz == 0.0) && (q->fuzz == 0.0))
5977 return(IsPixelInfoEquivalent(p,q));
5978 if (p->fuzz == 0.0)
cristy3522bf42013-08-04 14:53:18 +00005979 fuzz=MagickMax(q->fuzz,(MagickRealType) MagickSQ1_2)*
5980 MagickMax(q->fuzz,(MagickRealType) MagickSQ1_2);
cristy4c08aed2011-07-01 19:47:50 +00005981 else if (q->fuzz == 0.0)
cristy3522bf42013-08-04 14:53:18 +00005982 fuzz=MagickMax(p->fuzz,(MagickRealType) MagickSQ1_2)*
5983 MagickMax(p->fuzz,(MagickRealType) MagickSQ1_2);
cristy4c08aed2011-07-01 19:47:50 +00005984 else
cristy3522bf42013-08-04 14:53:18 +00005985 fuzz=MagickMax(p->fuzz,(MagickRealType) MagickSQ1_2)*
5986 MagickMax(q->fuzz,(MagickRealType) MagickSQ1_2);
cristy4c08aed2011-07-01 19:47:50 +00005987 scale=1.0;
5988 distance=0.0;
cristy24dc9722013-05-20 16:02:22 +00005989 if ((p->alpha_trait == BlendPixelTrait) ||
5990 (q->alpha_trait == BlendPixelTrait))
cristy4c08aed2011-07-01 19:47:50 +00005991 {
5992 /*
5993 Transparencies are involved - set alpha distance.
5994 */
cristy8a46d822012-08-28 23:32:39 +00005995 pixel=(p->alpha_trait == BlendPixelTrait ? p->alpha : OpaqueAlpha)-
5996 (q->alpha_trait == BlendPixelTrait ? q->alpha : OpaqueAlpha);
cristy4c08aed2011-07-01 19:47:50 +00005997 distance=pixel*pixel;
5998 if (distance > fuzz)
5999 return(MagickFalse);
6000 /*
6001 Generate a alpha scaling factor to generate a 4D cone on colorspace.
cristy5f95f4f2011-10-23 01:01:01 +00006002 If one color is transparent, distance has no color component.
cristy4c08aed2011-07-01 19:47:50 +00006003 */
cristy8a46d822012-08-28 23:32:39 +00006004 if (p->alpha_trait == BlendPixelTrait)
cristy4c08aed2011-07-01 19:47:50 +00006005 scale=(QuantumScale*p->alpha);
cristy8a46d822012-08-28 23:32:39 +00006006 if (q->alpha_trait == BlendPixelTrait)
cristy4c08aed2011-07-01 19:47:50 +00006007 scale*=(QuantumScale*q->alpha);
6008 if (scale <= MagickEpsilon )
6009 return(MagickTrue);
6010 }
6011 /*
6012 CMYK create a CMY cube with a multi-dimensional cone toward black.
6013 */
6014 if (p->colorspace == CMYKColorspace)
6015 {
6016 pixel=p->black-q->black;
6017 distance+=pixel*pixel*scale;
6018 if (distance > fuzz)
6019 return(MagickFalse);
cristya19f1d72012-08-07 18:24:38 +00006020 scale*=(double) (QuantumScale*(QuantumRange-p->black));
6021 scale*=(double) (QuantumScale*(QuantumRange-q->black));
cristy4c08aed2011-07-01 19:47:50 +00006022 }
6023 /*
6024 RGB or CMY color cube.
6025 */
6026 distance*=3.0; /* rescale appropriately */
6027 fuzz*=3.0;
6028 pixel=p->red-q->red;
6029 if ((p->colorspace == HSLColorspace) || (p->colorspace == HSBColorspace) ||
6030 (p->colorspace == HWBColorspace))
6031 {
cristy5f95f4f2011-10-23 01:01:01 +00006032 /*
cristy58ee5012013-05-26 23:58:44 +00006033 This calculates a arc distance for hue-- it should be a vector
6034 angle of 'S'/'W' length with 'L'/'B' forming appropriate cones.
6035 In other words this is a hack - Anthony.
cristy4c08aed2011-07-01 19:47:50 +00006036 */
6037 if (fabs((double) pixel) > (QuantumRange/2))
6038 pixel-=QuantumRange;
6039 pixel*=2;
6040 }
6041 distance+=pixel*pixel*scale;
6042 if (distance > fuzz)
6043 return(MagickFalse);
6044 pixel=p->green-q->green;
6045 distance+=pixel*pixel*scale;
6046 if (distance > fuzz)
6047 return(MagickFalse);
6048 pixel=p->blue-q->blue;
6049 distance+=pixel*pixel*scale;
6050 if (distance > fuzz)
6051 return(MagickFalse);
6052 return(MagickTrue);
6053}
6054
6055/*
6056%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6057% %
6058% %
6059% %
cristy7ae16542013-05-15 22:41:24 +00006060% 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 +00006061% %
6062% %
6063% %
6064%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6065%
cristy7ae16542013-05-15 22:41:24 +00006066% SetPixelChannelMask() sets the pixel channel map from the specified channel
6067% mask.
cristy2b9582a2011-07-04 17:38:56 +00006068%
cristycf1296e2012-08-26 23:40:49 +00006069% The format of the SetPixelChannelMask method is:
cristy2b9582a2011-07-04 17:38:56 +00006070%
cristycf1296e2012-08-26 23:40:49 +00006071% void SetPixelChannelMask(Image *image,const ChannelType channel_mask)
cristy2b9582a2011-07-04 17:38:56 +00006072%
6073% A description of each parameter follows:
6074%
6075% o image: the image.
6076%
cristydfdb19e2012-03-21 22:22:24 +00006077% o channel_mask: the channel mask.
cristy2b9582a2011-07-04 17:38:56 +00006078%
6079*/
cristycf1296e2012-08-26 23:40:49 +00006080MagickExport void SetPixelChannelMask(Image *image,
cristy07a67852011-08-26 13:25:03 +00006081 const ChannelType channel_mask)
cristy2b9582a2011-07-04 17:38:56 +00006082{
cristy6a917d62011-08-24 17:31:30 +00006083#define GetChannelBit(mask,bit) (((size_t) (mask) >> (size_t) (bit)) & 0x01)
cristydafd2872011-07-24 22:06:13 +00006084
cristy2b9582a2011-07-04 17:38:56 +00006085 register ssize_t
6086 i;
6087
cristy177e41c2012-04-15 15:08:25 +00006088 if (image->debug != MagickFalse)
6089 (void) LogMagickEvent(PixelEvent,GetMagickModule(),"%s[%08x]", \
6090 image->filename,channel_mask); \
cristy3c309812011-11-08 02:40:43 +00006091 image->channel_mask=channel_mask;
cristydafd2872011-07-24 22:06:13 +00006092 for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
cristye2a912b2011-12-05 20:02:07 +00006093 {
cristy5a23c552013-02-13 14:34:28 +00006094 PixelChannel channel=GetPixelChannelChannel(image,i);
cristy297e3a42012-08-26 21:27:29 +00006095 SetPixelChannelTraits(image,channel,
cristye2a912b2011-12-05 20:02:07 +00006096 GetChannelBit(channel_mask,channel) == 0 ? CopyPixelTrait :
cristy8a46d822012-08-28 23:32:39 +00006097 image->alpha_trait != BlendPixelTrait || (channel == AlphaPixelChannel) ?
6098 UpdatePixelTrait : (PixelTrait) (UpdatePixelTrait | image->alpha_trait));
cristye2a912b2011-12-05 20:02:07 +00006099 }
cristy1685e722011-09-06 00:04:19 +00006100 if (image->storage_class == PseudoClass)
cristy297e3a42012-08-26 21:27:29 +00006101 SetPixelChannelTraits(image,IndexPixelChannel,CopyPixelTrait);
cristy883fde12013-04-08 00:50:13 +00006102 if (image->read_mask != MagickFalse)
6103 SetPixelChannelTraits(image,ReadMaskPixelChannel,CopyPixelTrait);
6104 if (image->write_mask != MagickFalse)
6105 SetPixelChannelTraits(image,WriteMaskPixelChannel,CopyPixelTrait);
cristy6dcb9b82011-10-23 23:21:25 +00006106 if (image->debug != MagickFalse)
6107 LogPixelChannels(image);
cristy2b9582a2011-07-04 17:38:56 +00006108}
6109
6110/*
6111%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6112% %
6113% %
6114% %
cristy322d07d2012-03-18 21:17:23 +00006115% S e t P i x e l M e t a C h a n n e l s %
6116% %
6117% %
6118% %
6119%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6120%
6121% SetPixelMetaChannels() sets the image meta channels.
6122%
6123% The format of the SetPixelMetaChannels method is:
6124%
6125% MagickBooleanType SetPixelMetaChannels(Image *image,
6126% const size_t number_meta_channels,ExceptionInfo *exception)
6127%
6128% A description of each parameter follows:
6129%
6130% o image: the image.
6131%
6132% o number_meta_channels: the number of meta channels.
6133%
6134% o exception: return any errors or warnings in this structure.
6135%
6136*/
6137MagickExport MagickBooleanType SetPixelMetaChannels(Image *image,
6138 const size_t number_meta_channels,ExceptionInfo *exception)
6139{
6140 image->number_meta_channels=number_meta_channels;
6141 return(SyncImagePixelCache(image,exception));
6142}