blob: f4ada0eaf05ae9a20c82b6bfeedd49a52b9023f6 [file] [log] [blame]
cristy4c08aed2011-07-01 19:47:50 +00001/*
2%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3% %
4% %
5% %
6% PPPP IIIII X X EEEEE L %
7% P P I X X E L %
8% PPPP I X EEE L %
9% P I X X E L %
10% P IIIII X X EEEEE LLLLL %
11% %
12% MagickCore Methods to Import/Export Pixels %
13% %
14% Software Design %
15% John Cristy %
16% October 1998 %
17% %
18% %
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;
2115 if (image == (const Image *) NULL)
2116 return;
2117 pixel->storage_class=image->storage_class;
2118 pixel->colorspace=image->colorspace;
cristy8a46d822012-08-28 23:32:39 +00002119 pixel->alpha_trait=image->alpha_trait;
cristy4c08aed2011-07-01 19:47:50 +00002120 pixel->depth=image->depth;
2121 pixel->fuzz=image->fuzz;
2122}
2123
2124/*
2125%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2126% %
2127% %
2128% %
cristy9731df72013-03-12 16:31:13 +00002129% G e t P i x e l I n t e n s i t y %
2130% %
2131% %
2132% %
2133%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2134%
cristy0c5c8892013-03-12 16:33:48 +00002135% GetPixelIntensity() returns a single sample intensity value from the red,
cristy70e9f682013-03-12 22:31:22 +00002136% green, and blue components of a pixel based on the selected method:
2137%
cristy2cf5d372013-03-13 12:03:11 +00002138% Rec601Luma 0.298839R' + 0.586811G' + 0.114350B'
2139% Rec601Luminance 0.298839R + 0.586811G + 0.114350B
cristy1352acf2013-06-10 17:16:17 +00002140% Rec709Luma 0.212656R' + 0.715158G' + 0.072186B'
2141% Rec709Luminance 0.212656R + 0.715158G + 0.072186B
cristy09bb0432013-06-01 13:39:18 +00002142% Brightness max(R', G', B')
2143% Lightness (min(R', G', B') + max(R', G', B')) / 2.0
2144%
2145% MS (R^2 + G^2 + B^2) / 3.0
2146% RMS sqrt((R^2 + G^2 + B^2) / 3.0
2147% Average (R + G + B') / 3.0
cristy9731df72013-03-12 16:31:13 +00002148%
2149% The format of the GetPixelIntensity method is:
2150%
cristy2cf5d372013-03-13 12:03:11 +00002151% MagickRealType GetPixelIntensity(const Image *image,
2152% const Quantum *pixel)
cristy9731df72013-03-12 16:31:13 +00002153%
2154% A description of each parameter follows:
2155%
2156% o image: the image.
2157%
2158% o pixel: Specifies a pointer to a Quantum structure.
2159%
2160*/
cristy70e9f682013-03-12 22:31:22 +00002161
2162static inline MagickRealType MagickMax(const MagickRealType x,
2163 const MagickRealType y)
2164{
2165 if (x > y)
2166 return(x);
2167 return(y);
2168}
2169
2170static inline MagickRealType MagickMin(const MagickRealType x,
2171 const MagickRealType y)
2172{
2173 if (x < y)
2174 return(x);
2175 return(y);
2176}
2177
cristy9731df72013-03-12 16:31:13 +00002178MagickExport MagickRealType GetPixelIntensity(const Image *restrict image,
2179 const Quantum *restrict pixel)
2180{
2181 MagickRealType
2182 blue,
2183 green,
cristy70e9f682013-03-12 22:31:22 +00002184 red,
2185 intensity;
cristy9731df72013-03-12 16:31:13 +00002186
2187 if (image->colorspace == GRAYColorspace)
cristy592d6bb2013-04-07 15:20:37 +00002188 return((MagickRealType) GetPixelGray(image,pixel));
2189 red=(MagickRealType) GetPixelRed(image,pixel);
2190 green=(MagickRealType) GetPixelGreen(image,pixel);
2191 blue=(MagickRealType) GetPixelBlue(image,pixel);
cristy70e9f682013-03-12 22:31:22 +00002192 switch (image->intensity)
2193 {
cristybf02d732013-03-13 16:28:58 +00002194 case AveragePixelIntensityMethod:
2195 {
2196 intensity=(red+green+blue)/3.0;
2197 break;
2198 }
2199 case BrightnessPixelIntensityMethod:
2200 {
2201 intensity=MagickMax(MagickMax(red,green),blue);
2202 break;
2203 }
2204 case LightnessPixelIntensityMethod:
2205 {
cristy09bb0432013-06-01 13:39:18 +00002206 intensity=(MagickMin(MagickMin(red,green),blue)+
cristyce326722013-06-01 13:40:28 +00002207 MagickMax(MagickMax(red,green),blue))/2.0;
cristybf02d732013-03-13 16:28:58 +00002208 break;
2209 }
cristy462c1ca2013-04-15 10:29:18 +00002210 case MSPixelIntensityMethod:
2211 {
2212 intensity=(MagickRealType) (((double) red*red+green*green+blue*blue)/
2213 (3.0*QuantumRange));
2214 break;
2215 }
cristy70e9f682013-03-12 22:31:22 +00002216 case Rec601LumaPixelIntensityMethod:
cristy70e9f682013-03-12 22:31:22 +00002217 {
cristy09bb0432013-06-01 13:39:18 +00002218 if (image->colorspace == RGBColorspace)
2219 {
2220 red=EncodePixelGamma(red);
2221 green=EncodePixelGamma(green);
2222 blue=EncodePixelGamma(blue);
2223 }
cristy9e2436a2013-05-02 20:35:59 +00002224 intensity=0.298839*red+0.586811*green+0.114350*blue;
cristy2cf5d372013-03-13 12:03:11 +00002225 break;
2226 }
2227 case Rec601LuminancePixelIntensityMethod:
2228 {
cristy70e9f682013-03-12 22:31:22 +00002229 if (image->colorspace == sRGBColorspace)
2230 {
2231 red=DecodePixelGamma(red);
2232 green=DecodePixelGamma(green);
2233 blue=DecodePixelGamma(blue);
2234 }
cristy9e2436a2013-05-02 20:35:59 +00002235 intensity=0.298839*red+0.586811*green+0.114350*blue;
cristy70e9f682013-03-12 22:31:22 +00002236 break;
2237 }
2238 case Rec709LumaPixelIntensityMethod:
cristyc94210c2013-05-06 14:09:53 +00002239 default:
cristy70e9f682013-03-12 22:31:22 +00002240 {
cristy09bb0432013-06-01 13:39:18 +00002241 if (image->colorspace == RGBColorspace)
2242 {
2243 red=EncodePixelGamma(red);
2244 green=EncodePixelGamma(green);
2245 blue=EncodePixelGamma(blue);
2246 }
cristy1352acf2013-06-10 17:16:17 +00002247 intensity=0.212656*red+0.715158*green+0.072186*blue;
cristy2cf5d372013-03-13 12:03:11 +00002248 break;
2249 }
2250 case Rec709LuminancePixelIntensityMethod:
2251 {
cristy70e9f682013-03-12 22:31:22 +00002252 if (image->colorspace == sRGBColorspace)
2253 {
2254 red=DecodePixelGamma(red);
2255 green=DecodePixelGamma(green);
2256 blue=DecodePixelGamma(blue);
2257 }
cristy1352acf2013-06-10 17:16:17 +00002258 intensity=0.212656*red+0.715158*green+0.072186*blue;
cristy70e9f682013-03-12 22:31:22 +00002259 break;
2260 }
cristy70e9f682013-03-12 22:31:22 +00002261 case RMSPixelIntensityMethod:
2262 {
cristy462c1ca2013-04-15 10:29:18 +00002263 intensity=(MagickRealType) (sqrt((double) red*red+green*green+blue*blue)/
2264 sqrt(3.0));
cristy70e9f682013-03-12 22:31:22 +00002265 break;
2266 }
cristy70e9f682013-03-12 22:31:22 +00002267 }
2268 return(intensity);
cristy9731df72013-03-12 16:31:13 +00002269}
cristy9731df72013-03-12 16:31:13 +00002270
2271/*
2272%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2273% %
2274% %
2275% %
cristy4c08aed2011-07-01 19:47:50 +00002276% I m p o r t I m a g e P i x e l s %
2277% %
2278% %
2279% %
2280%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2281%
2282% ImportImagePixels() accepts pixel data and stores in the image at the
2283% location you specify. The method returns MagickTrue on success otherwise
2284% MagickFalse if an error is encountered. The pixel data can be either char,
cristyb5a45a32012-01-10 13:31:13 +00002285% Quantum, short int, unsigned int, unsigned long long, float, or double in
2286% the order specified by map.
cristy4c08aed2011-07-01 19:47:50 +00002287%
2288% Suppose your want to upload the first scanline of a 640x480 image from
2289% character data in red-green-blue order:
2290%
2291% ImportImagePixels(image,0,0,640,1,"RGB",CharPixel,pixels);
2292%
2293% The format of the ImportImagePixels method is:
2294%
cristycafe0412012-01-10 13:29:58 +00002295% MagickBooleanType ImportImagePixels(Image *image,const ssize_t x,
2296% const ssize_t y,const size_t width,const size_t height,
2297% const char *map,const StorageType type,const void *pixels,
2298% ExceptionInfo *exception)
cristy4c08aed2011-07-01 19:47:50 +00002299%
2300% A description of each parameter follows:
2301%
2302% o image: the image.
2303%
cristycafe0412012-01-10 13:29:58 +00002304% o x,y,width,height: These values define the perimeter
cristy4c08aed2011-07-01 19:47:50 +00002305% of a region of pixels you want to define.
2306%
2307% o map: This string reflects the expected ordering of the pixel array.
2308% It can be any combination or order of R = red, G = green, B = blue,
2309% A = alpha (0 is transparent), O = opacity (0 is opaque), C = cyan,
2310% Y = yellow, M = magenta, K = black, I = intensity (for grayscale),
2311% P = pad.
2312%
2313% o type: Define the data type of the pixels. Float and double types are
2314% normalized to [0..1] otherwise [0..QuantumRange]. Choose from these
cristy6c9e1682012-01-07 21:37:44 +00002315% types: CharPixel (char *), DoublePixel (double *), FloatPixel (float *),
cristyff6834e2012-01-10 03:00:25 +00002316% LongPixel (unsigned int *), LongLongPixel (unsigned long long *),
cristy6c9e1682012-01-07 21:37:44 +00002317% QuantumPixel (Quantum *), or ShortPixel (unsigned short *).
cristy4c08aed2011-07-01 19:47:50 +00002318%
2319% o pixels: This array of values contain the pixel components as defined by
2320% map and type. You must preallocate this array where the expected
2321% length varies depending on the values of width, height, map, and type.
2322%
cristy018f07f2011-09-04 21:15:19 +00002323% o exception: return any errors or warnings in this structure.
2324%
cristy4c08aed2011-07-01 19:47:50 +00002325*/
cristye5370942012-01-06 03:49:31 +00002326
cristycafe0412012-01-10 13:29:58 +00002327static void ImportCharPixel(Image *image,const RectangleInfo *roi,
cristy46f4be22012-01-07 00:26:39 +00002328 const char *restrict map,const QuantumType *quantum_map,const void *pixels,
2329 ExceptionInfo *exception)
cristye5370942012-01-06 03:49:31 +00002330{
2331 register const unsigned char
2332 *restrict p;
2333
2334 register Quantum
cristy3fe11452012-01-09 01:27:42 +00002335 *restrict q;
cristye5370942012-01-06 03:49:31 +00002336
2337 register ssize_t
2338 x;
2339
cristy14d71292012-05-20 16:48:13 +00002340 size_t
2341 length;
2342
cristye5370942012-01-06 03:49:31 +00002343 ssize_t
2344 y;
2345
2346 p=(const unsigned char *) pixels;
2347 if (LocaleCompare(map,"BGR") == 0)
2348 {
cristycafe0412012-01-10 13:29:58 +00002349 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00002350 {
cristycafe0412012-01-10 13:29:58 +00002351 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00002352 if (q == (Quantum *) NULL)
2353 break;
cristycafe0412012-01-10 13:29:58 +00002354 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00002355 {
2356 SetPixelBlue(image,ScaleCharToQuantum(*p++),q);
2357 SetPixelGreen(image,ScaleCharToQuantum(*p++),q);
2358 SetPixelRed(image,ScaleCharToQuantum(*p++),q);
2359 q+=GetPixelChannels(image);
2360 }
2361 if (SyncAuthenticPixels(image,exception) == MagickFalse)
2362 break;
2363 }
2364 return;
2365 }
2366 if (LocaleCompare(map,"BGRA") == 0)
2367 {
cristycafe0412012-01-10 13:29:58 +00002368 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00002369 {
cristycafe0412012-01-10 13:29:58 +00002370 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00002371 if (q == (Quantum *) NULL)
2372 break;
cristycafe0412012-01-10 13:29:58 +00002373 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00002374 {
2375 SetPixelBlue(image,ScaleCharToQuantum(*p++),q);
2376 SetPixelGreen(image,ScaleCharToQuantum(*p++),q);
2377 SetPixelRed(image,ScaleCharToQuantum(*p++),q);
2378 SetPixelAlpha(image,ScaleCharToQuantum(*p++),q);
2379 q+=GetPixelChannels(image);
2380 }
2381 if (SyncAuthenticPixels(image,exception) == MagickFalse)
2382 break;
2383 }
2384 return;
2385 }
2386 if (LocaleCompare(map,"BGRO") == 0)
2387 {
cristycafe0412012-01-10 13:29:58 +00002388 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00002389 {
cristycafe0412012-01-10 13:29:58 +00002390 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00002391 if (q == (Quantum *) NULL)
2392 break;
cristycafe0412012-01-10 13:29:58 +00002393 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00002394 {
2395 SetPixelBlue(image,ScaleCharToQuantum(*p++),q);
2396 SetPixelGreen(image,ScaleCharToQuantum(*p++),q);
2397 SetPixelRed(image,ScaleCharToQuantum(*p++),q);
2398 SetPixelAlpha(image,ScaleCharToQuantum(*p++),q);
2399 q+=GetPixelChannels(image);
2400 }
2401 if (SyncAuthenticPixels(image,exception) == MagickFalse)
2402 break;
2403 }
2404 return;
2405 }
2406 if (LocaleCompare(map,"BGRP") == 0)
2407 {
cristycafe0412012-01-10 13:29:58 +00002408 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00002409 {
cristycafe0412012-01-10 13:29:58 +00002410 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00002411 if (q == (Quantum *) NULL)
2412 break;
cristycafe0412012-01-10 13:29:58 +00002413 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00002414 {
2415 SetPixelBlue(image,ScaleCharToQuantum(*p++),q);
2416 SetPixelGreen(image,ScaleCharToQuantum(*p++),q);
2417 SetPixelRed(image,ScaleCharToQuantum(*p++),q);
2418 p++;
2419 q+=GetPixelChannels(image);
2420 }
2421 if (SyncAuthenticPixels(image,exception) == MagickFalse)
2422 break;
2423 }
2424 return;
2425 }
2426 if (LocaleCompare(map,"I") == 0)
2427 {
cristycafe0412012-01-10 13:29:58 +00002428 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00002429 {
cristycafe0412012-01-10 13:29:58 +00002430 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00002431 if (q == (Quantum *) NULL)
2432 break;
cristycafe0412012-01-10 13:29:58 +00002433 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00002434 {
2435 SetPixelGray(image,ScaleCharToQuantum(*p++),q);
2436 q+=GetPixelChannels(image);
2437 }
2438 if (SyncAuthenticPixels(image,exception) == MagickFalse)
2439 break;
2440 }
2441 return;
2442 }
2443 if (LocaleCompare(map,"RGB") == 0)
2444 {
cristycafe0412012-01-10 13:29:58 +00002445 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00002446 {
cristycafe0412012-01-10 13:29:58 +00002447 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00002448 if (q == (Quantum *) NULL)
2449 break;
cristycafe0412012-01-10 13:29:58 +00002450 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00002451 {
2452 SetPixelRed(image,ScaleCharToQuantum(*p++),q);
2453 SetPixelGreen(image,ScaleCharToQuantum(*p++),q);
2454 SetPixelBlue(image,ScaleCharToQuantum(*p++),q);
2455 q+=GetPixelChannels(image);
2456 }
2457 if (SyncAuthenticPixels(image,exception) == MagickFalse)
2458 break;
2459 }
2460 return;
2461 }
2462 if (LocaleCompare(map,"RGBA") == 0)
2463 {
cristycafe0412012-01-10 13:29:58 +00002464 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00002465 {
cristycafe0412012-01-10 13:29:58 +00002466 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00002467 if (q == (Quantum *) NULL)
2468 break;
cristycafe0412012-01-10 13:29:58 +00002469 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00002470 {
2471 SetPixelRed(image,ScaleCharToQuantum(*p++),q);
2472 SetPixelGreen(image,ScaleCharToQuantum(*p++),q);
2473 SetPixelBlue(image,ScaleCharToQuantum(*p++),q);
2474 SetPixelAlpha(image,ScaleCharToQuantum(*p++),q);
2475 q+=GetPixelChannels(image);
2476 }
2477 if (SyncAuthenticPixels(image,exception) == MagickFalse)
2478 break;
2479 }
2480 return;
2481 }
2482 if (LocaleCompare(map,"RGBO") == 0)
2483 {
cristycafe0412012-01-10 13:29:58 +00002484 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00002485 {
cristycafe0412012-01-10 13:29:58 +00002486 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00002487 if (q == (Quantum *) NULL)
2488 break;
cristycafe0412012-01-10 13:29:58 +00002489 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00002490 {
2491 SetPixelRed(image,ScaleCharToQuantum(*p++),q);
2492 SetPixelGreen(image,ScaleCharToQuantum(*p++),q);
2493 SetPixelBlue(image,ScaleCharToQuantum(*p++),q);
2494 SetPixelAlpha(image,ScaleCharToQuantum(*p++),q);
2495 q+=GetPixelChannels(image);
2496 }
2497 if (SyncAuthenticPixels(image,exception) == MagickFalse)
2498 break;
2499 }
2500 return;
2501 }
2502 if (LocaleCompare(map,"RGBP") == 0)
2503 {
cristycafe0412012-01-10 13:29:58 +00002504 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00002505 {
cristycafe0412012-01-10 13:29:58 +00002506 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00002507 if (q == (Quantum *) NULL)
2508 break;
cristycafe0412012-01-10 13:29:58 +00002509 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00002510 {
2511 SetPixelRed(image,ScaleCharToQuantum(*p++),q);
2512 SetPixelGreen(image,ScaleCharToQuantum(*p++),q);
2513 SetPixelBlue(image,ScaleCharToQuantum(*p++),q);
2514 p++;
2515 q+=GetPixelChannels(image);
2516 }
2517 if (SyncAuthenticPixels(image,exception) == MagickFalse)
2518 break;
2519 }
2520 return;
2521 }
cristy14d71292012-05-20 16:48:13 +00002522 length=strlen(map);
cristycafe0412012-01-10 13:29:58 +00002523 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00002524 {
cristycafe0412012-01-10 13:29:58 +00002525 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00002526 if (q == (Quantum *) NULL)
2527 break;
cristycafe0412012-01-10 13:29:58 +00002528 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00002529 {
2530 register ssize_t
2531 i;
2532
cristy14d71292012-05-20 16:48:13 +00002533 for (i=0; i < (ssize_t) length; i++)
cristye5370942012-01-06 03:49:31 +00002534 {
2535 switch (quantum_map[i])
2536 {
2537 case RedQuantum:
2538 case CyanQuantum:
2539 {
2540 SetPixelRed(image,ScaleCharToQuantum(*p),q);
2541 break;
2542 }
2543 case GreenQuantum:
2544 case MagentaQuantum:
2545 {
2546 SetPixelGreen(image,ScaleCharToQuantum(*p),q);
2547 break;
2548 }
2549 case BlueQuantum:
2550 case YellowQuantum:
2551 {
2552 SetPixelBlue(image,ScaleCharToQuantum(*p),q);
2553 break;
2554 }
2555 case AlphaQuantum:
2556 {
2557 SetPixelAlpha(image,ScaleCharToQuantum(*p),q);
2558 break;
2559 }
2560 case OpacityQuantum:
2561 {
2562 SetPixelAlpha(image,ScaleCharToQuantum(*p),q);
2563 break;
2564 }
2565 case BlackQuantum:
2566 {
2567 SetPixelBlack(image,ScaleCharToQuantum(*p),q);
2568 break;
2569 }
2570 case IndexQuantum:
2571 {
2572 SetPixelGray(image,ScaleCharToQuantum(*p),q);
2573 break;
2574 }
2575 default:
2576 break;
2577 }
2578 p++;
2579 }
2580 q+=GetPixelChannels(image);
2581 }
2582 if (SyncAuthenticPixels(image,exception) == MagickFalse)
2583 break;
2584 }
2585}
2586
cristycafe0412012-01-10 13:29:58 +00002587static void ImportDoublePixel(Image *image,const RectangleInfo *roi,
cristy46f4be22012-01-07 00:26:39 +00002588 const char *restrict map,const QuantumType *quantum_map,const void *pixels,
2589 ExceptionInfo *exception)
cristye5370942012-01-06 03:49:31 +00002590{
2591 register const double
2592 *restrict p;
2593
2594 register Quantum
cristy3fe11452012-01-09 01:27:42 +00002595 *restrict q;
cristye5370942012-01-06 03:49:31 +00002596
2597 register ssize_t
2598 x;
2599
cristy14d71292012-05-20 16:48:13 +00002600 size_t
2601 length;
2602
cristye5370942012-01-06 03:49:31 +00002603 ssize_t
2604 y;
2605
2606 p=(const double *) pixels;
2607 if (LocaleCompare(map,"BGR") == 0)
2608 {
cristycafe0412012-01-10 13:29:58 +00002609 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00002610 {
cristycafe0412012-01-10 13:29:58 +00002611 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00002612 if (q == (Quantum *) NULL)
2613 break;
cristycafe0412012-01-10 13:29:58 +00002614 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00002615 {
cristy8cd03c32012-07-07 18:57:59 +00002616 SetPixelBlue(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002617 p++;
cristy8cd03c32012-07-07 18:57:59 +00002618 SetPixelGreen(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002619 p++;
cristy8cd03c32012-07-07 18:57:59 +00002620 SetPixelRed(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002621 p++;
2622 q+=GetPixelChannels(image);
2623 }
2624 if (SyncAuthenticPixels(image,exception) == MagickFalse)
2625 break;
2626 }
2627 return;
2628 }
2629 if (LocaleCompare(map,"BGRA") == 0)
2630 {
cristycafe0412012-01-10 13:29:58 +00002631 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00002632 {
cristycafe0412012-01-10 13:29:58 +00002633 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00002634 if (q == (Quantum *) NULL)
2635 break;
cristycafe0412012-01-10 13:29:58 +00002636 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00002637 {
cristy8cd03c32012-07-07 18:57:59 +00002638 SetPixelBlue(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002639 p++;
cristy8cd03c32012-07-07 18:57:59 +00002640 SetPixelGreen(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002641 p++;
cristy8cd03c32012-07-07 18:57:59 +00002642 SetPixelRed(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002643 p++;
cristy8cd03c32012-07-07 18:57:59 +00002644 SetPixelAlpha(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002645 p++;
2646 q+=GetPixelChannels(image);
2647 }
2648 if (SyncAuthenticPixels(image,exception) == MagickFalse)
2649 break;
2650 }
2651 return;
2652 }
2653 if (LocaleCompare(map,"BGRP") == 0)
2654 {
cristycafe0412012-01-10 13:29:58 +00002655 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00002656 {
cristycafe0412012-01-10 13:29:58 +00002657 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00002658 if (q == (Quantum *) NULL)
2659 break;
cristycafe0412012-01-10 13:29:58 +00002660 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00002661 {
cristy8cd03c32012-07-07 18:57:59 +00002662 SetPixelBlue(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002663 p++;
cristy8cd03c32012-07-07 18:57:59 +00002664 SetPixelGreen(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002665 p++;
cristy8cd03c32012-07-07 18:57:59 +00002666 SetPixelRed(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002667 p++;
2668 p++;
2669 q+=GetPixelChannels(image);
2670 }
2671 if (SyncAuthenticPixels(image,exception) == MagickFalse)
2672 break;
2673 }
2674 return;
2675 }
2676 if (LocaleCompare(map,"I") == 0)
2677 {
cristycafe0412012-01-10 13:29:58 +00002678 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00002679 {
cristycafe0412012-01-10 13:29:58 +00002680 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00002681 if (q == (Quantum *) NULL)
2682 break;
cristycafe0412012-01-10 13:29:58 +00002683 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00002684 {
cristy8cd03c32012-07-07 18:57:59 +00002685 SetPixelGray(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002686 p++;
2687 q+=GetPixelChannels(image);
2688 }
2689 if (SyncAuthenticPixels(image,exception) == MagickFalse)
2690 break;
2691 }
2692 return;
2693 }
2694 if (LocaleCompare(map,"RGB") == 0)
2695 {
cristycafe0412012-01-10 13:29:58 +00002696 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00002697 {
cristycafe0412012-01-10 13:29:58 +00002698 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00002699 if (q == (Quantum *) NULL)
2700 break;
cristycafe0412012-01-10 13:29:58 +00002701 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00002702 {
cristy8cd03c32012-07-07 18:57:59 +00002703 SetPixelRed(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002704 p++;
cristy8cd03c32012-07-07 18:57:59 +00002705 SetPixelGreen(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002706 p++;
cristy8cd03c32012-07-07 18:57:59 +00002707 SetPixelBlue(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002708 p++;
2709 q+=GetPixelChannels(image);
2710 }
2711 if (SyncAuthenticPixels(image,exception) == MagickFalse)
2712 break;
2713 }
2714 return;
2715 }
2716 if (LocaleCompare(map,"RGBA") == 0)
2717 {
cristycafe0412012-01-10 13:29:58 +00002718 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00002719 {
cristycafe0412012-01-10 13:29:58 +00002720 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00002721 if (q == (Quantum *) NULL)
2722 break;
cristycafe0412012-01-10 13:29:58 +00002723 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00002724 {
cristy8cd03c32012-07-07 18:57:59 +00002725 SetPixelRed(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002726 p++;
cristy8cd03c32012-07-07 18:57:59 +00002727 SetPixelGreen(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002728 p++;
cristy8cd03c32012-07-07 18:57:59 +00002729 SetPixelBlue(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002730 p++;
cristy8cd03c32012-07-07 18:57:59 +00002731 SetPixelAlpha(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002732 p++;
2733 q+=GetPixelChannels(image);
2734 }
2735 if (SyncAuthenticPixels(image,exception) == MagickFalse)
2736 break;
2737 }
2738 return;
2739 }
2740 if (LocaleCompare(map,"RGBP") == 0)
2741 {
cristycafe0412012-01-10 13:29:58 +00002742 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00002743 {
cristycafe0412012-01-10 13:29:58 +00002744 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00002745 if (q == (Quantum *) NULL)
2746 break;
cristycafe0412012-01-10 13:29:58 +00002747 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00002748 {
cristy8cd03c32012-07-07 18:57:59 +00002749 SetPixelRed(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002750 p++;
cristy8cd03c32012-07-07 18:57:59 +00002751 SetPixelGreen(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002752 p++;
cristy8cd03c32012-07-07 18:57:59 +00002753 SetPixelBlue(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002754 p++;
2755 q+=GetPixelChannels(image);
2756 }
2757 if (SyncAuthenticPixels(image,exception) == MagickFalse)
2758 break;
2759 }
2760 return;
2761 }
cristy14d71292012-05-20 16:48:13 +00002762 length=strlen(map);
cristycafe0412012-01-10 13:29:58 +00002763 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00002764 {
cristycafe0412012-01-10 13:29:58 +00002765 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00002766 if (q == (Quantum *) NULL)
2767 break;
cristycafe0412012-01-10 13:29:58 +00002768 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00002769 {
2770 register ssize_t
2771 i;
2772
cristy14d71292012-05-20 16:48:13 +00002773 for (i=0; i < (ssize_t) length; i++)
cristye5370942012-01-06 03:49:31 +00002774 {
2775 switch (quantum_map[i])
2776 {
2777 case RedQuantum:
2778 case CyanQuantum:
2779 {
cristy8cd03c32012-07-07 18:57:59 +00002780 SetPixelRed(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002781 break;
2782 }
2783 case GreenQuantum:
2784 case MagentaQuantum:
2785 {
cristy8cd03c32012-07-07 18:57:59 +00002786 SetPixelGreen(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002787 break;
2788 }
2789 case BlueQuantum:
2790 case YellowQuantum:
2791 {
cristy8cd03c32012-07-07 18:57:59 +00002792 SetPixelBlue(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002793 break;
2794 }
2795 case AlphaQuantum:
2796 {
cristy8cd03c32012-07-07 18:57:59 +00002797 SetPixelAlpha(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002798 break;
2799 }
2800 case OpacityQuantum:
2801 {
cristy8cd03c32012-07-07 18:57:59 +00002802 SetPixelAlpha(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002803 break;
2804 }
2805 case BlackQuantum:
2806 {
cristy8cd03c32012-07-07 18:57:59 +00002807 SetPixelBlack(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002808 break;
2809 }
2810 case IndexQuantum:
2811 {
cristy8cd03c32012-07-07 18:57:59 +00002812 SetPixelGray(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002813 break;
2814 }
2815 default:
2816 break;
2817 }
2818 p++;
2819 }
2820 q+=GetPixelChannels(image);
2821 }
2822 if (SyncAuthenticPixels(image,exception) == MagickFalse)
2823 break;
2824 }
2825}
2826
cristycafe0412012-01-10 13:29:58 +00002827static void ImportFloatPixel(Image *image,const RectangleInfo *roi,
cristy46f4be22012-01-07 00:26:39 +00002828 const char *restrict map,const QuantumType *quantum_map,const void *pixels,
2829 ExceptionInfo *exception)
cristye5370942012-01-06 03:49:31 +00002830{
2831 register const float
2832 *restrict p;
2833
2834 register Quantum
cristy3fe11452012-01-09 01:27:42 +00002835 *restrict q;
cristye5370942012-01-06 03:49:31 +00002836
2837 register ssize_t
2838 x;
2839
cristy14d71292012-05-20 16:48:13 +00002840 size_t
2841 length;
2842
cristye5370942012-01-06 03:49:31 +00002843 ssize_t
2844 y;
2845
2846 p=(const float *) pixels;
2847 if (LocaleCompare(map,"BGR") == 0)
2848 {
cristycafe0412012-01-10 13:29:58 +00002849 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00002850 {
cristycafe0412012-01-10 13:29:58 +00002851 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00002852 if (q == (Quantum *) NULL)
2853 break;
cristycafe0412012-01-10 13:29:58 +00002854 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00002855 {
cristy8cd03c32012-07-07 18:57:59 +00002856 SetPixelBlue(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002857 p++;
cristy8cd03c32012-07-07 18:57:59 +00002858 SetPixelGreen(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002859 p++;
cristy8cd03c32012-07-07 18:57:59 +00002860 SetPixelRed(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002861 p++;
2862 q+=GetPixelChannels(image);
2863 }
2864 if (SyncAuthenticPixels(image,exception) == MagickFalse)
2865 break;
2866 }
2867 return;
2868 }
2869 if (LocaleCompare(map,"BGRA") == 0)
2870 {
cristycafe0412012-01-10 13:29:58 +00002871 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00002872 {
cristycafe0412012-01-10 13:29:58 +00002873 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00002874 if (q == (Quantum *) NULL)
2875 break;
cristycafe0412012-01-10 13:29:58 +00002876 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00002877 {
cristy8cd03c32012-07-07 18:57:59 +00002878 SetPixelBlue(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002879 p++;
cristy8cd03c32012-07-07 18:57:59 +00002880 SetPixelGreen(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002881 p++;
cristy8cd03c32012-07-07 18:57:59 +00002882 SetPixelRed(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002883 p++;
cristy8cd03c32012-07-07 18:57:59 +00002884 SetPixelAlpha(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002885 p++;
2886 q+=GetPixelChannels(image);
2887 }
2888 if (SyncAuthenticPixels(image,exception) == MagickFalse)
2889 break;
2890 }
2891 return;
2892 }
2893 if (LocaleCompare(map,"BGRP") == 0)
2894 {
cristycafe0412012-01-10 13:29:58 +00002895 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00002896 {
cristycafe0412012-01-10 13:29:58 +00002897 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00002898 if (q == (Quantum *) NULL)
2899 break;
cristycafe0412012-01-10 13:29:58 +00002900 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00002901 {
cristy8cd03c32012-07-07 18:57:59 +00002902 SetPixelBlue(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002903 p++;
cristy8cd03c32012-07-07 18:57:59 +00002904 SetPixelGreen(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002905 p++;
cristy8cd03c32012-07-07 18:57:59 +00002906 SetPixelRed(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002907 p++;
2908 p++;
2909 q+=GetPixelChannels(image);
2910 }
2911 if (SyncAuthenticPixels(image,exception) == MagickFalse)
2912 break;
2913 }
2914 return;
2915 }
2916 if (LocaleCompare(map,"I") == 0)
2917 {
cristycafe0412012-01-10 13:29:58 +00002918 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00002919 {
cristycafe0412012-01-10 13:29:58 +00002920 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00002921 if (q == (Quantum *) NULL)
2922 break;
cristycafe0412012-01-10 13:29:58 +00002923 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00002924 {
cristy8cd03c32012-07-07 18:57:59 +00002925 SetPixelGray(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002926 p++;
2927 q+=GetPixelChannels(image);
2928 }
2929 if (SyncAuthenticPixels(image,exception) == MagickFalse)
2930 break;
2931 }
2932 return;
2933 }
2934 if (LocaleCompare(map,"RGB") == 0)
2935 {
cristycafe0412012-01-10 13:29:58 +00002936 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00002937 {
cristycafe0412012-01-10 13:29:58 +00002938 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00002939 if (q == (Quantum *) NULL)
2940 break;
cristycafe0412012-01-10 13:29:58 +00002941 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00002942 {
cristy8cd03c32012-07-07 18:57:59 +00002943 SetPixelRed(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002944 p++;
cristy8cd03c32012-07-07 18:57:59 +00002945 SetPixelGreen(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002946 p++;
cristy8cd03c32012-07-07 18:57:59 +00002947 SetPixelBlue(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002948 p++;
2949 q+=GetPixelChannels(image);
2950 }
2951 if (SyncAuthenticPixels(image,exception) == MagickFalse)
2952 break;
2953 }
2954 return;
2955 }
2956 if (LocaleCompare(map,"RGBA") == 0)
2957 {
cristycafe0412012-01-10 13:29:58 +00002958 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00002959 {
cristycafe0412012-01-10 13:29:58 +00002960 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00002961 if (q == (Quantum *) NULL)
2962 break;
cristycafe0412012-01-10 13:29:58 +00002963 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00002964 {
cristy8cd03c32012-07-07 18:57:59 +00002965 SetPixelRed(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002966 p++;
cristy8cd03c32012-07-07 18:57:59 +00002967 SetPixelGreen(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002968 p++;
cristy8cd03c32012-07-07 18:57:59 +00002969 SetPixelBlue(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002970 p++;
cristy8cd03c32012-07-07 18:57:59 +00002971 SetPixelAlpha(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002972 p++;
2973 q+=GetPixelChannels(image);
2974 }
2975 if (SyncAuthenticPixels(image,exception) == MagickFalse)
2976 break;
2977 }
2978 return;
2979 }
2980 if (LocaleCompare(map,"RGBP") == 0)
2981 {
cristycafe0412012-01-10 13:29:58 +00002982 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00002983 {
cristycafe0412012-01-10 13:29:58 +00002984 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00002985 if (q == (Quantum *) NULL)
2986 break;
cristycafe0412012-01-10 13:29:58 +00002987 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00002988 {
cristy8cd03c32012-07-07 18:57:59 +00002989 SetPixelRed(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002990 p++;
cristy8cd03c32012-07-07 18:57:59 +00002991 SetPixelGreen(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002992 p++;
cristy8cd03c32012-07-07 18:57:59 +00002993 SetPixelBlue(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002994 p++;
2995 q+=GetPixelChannels(image);
2996 }
2997 if (SyncAuthenticPixels(image,exception) == MagickFalse)
2998 break;
2999 }
3000 return;
3001 }
cristy14d71292012-05-20 16:48:13 +00003002 length=strlen(map);
cristycafe0412012-01-10 13:29:58 +00003003 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00003004 {
cristycafe0412012-01-10 13:29:58 +00003005 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00003006 if (q == (Quantum *) NULL)
3007 break;
cristycafe0412012-01-10 13:29:58 +00003008 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00003009 {
3010 register ssize_t
3011 i;
3012
cristy14d71292012-05-20 16:48:13 +00003013 for (i=0; i < (ssize_t) length; i++)
cristye5370942012-01-06 03:49:31 +00003014 {
3015 switch (quantum_map[i])
3016 {
3017 case RedQuantum:
3018 case CyanQuantum:
3019 {
cristy8cd03c32012-07-07 18:57:59 +00003020 SetPixelRed(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00003021 break;
3022 }
3023 case GreenQuantum:
3024 case MagentaQuantum:
3025 {
cristy8cd03c32012-07-07 18:57:59 +00003026 SetPixelGreen(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00003027 break;
3028 }
3029 case BlueQuantum:
3030 case YellowQuantum:
3031 {
cristy8cd03c32012-07-07 18:57:59 +00003032 SetPixelBlue(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00003033 break;
3034 }
3035 case AlphaQuantum:
3036 {
cristy8cd03c32012-07-07 18:57:59 +00003037 SetPixelAlpha(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00003038 break;
3039 }
3040 case OpacityQuantum:
3041 {
cristy8cd03c32012-07-07 18:57:59 +00003042 SetPixelAlpha(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00003043 break;
3044 }
3045 case BlackQuantum:
3046 {
cristy8cd03c32012-07-07 18:57:59 +00003047 SetPixelBlack(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00003048 break;
3049 }
3050 case IndexQuantum:
3051 {
cristy8cd03c32012-07-07 18:57:59 +00003052 SetPixelGray(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00003053 break;
3054 }
3055 default:
3056 break;
3057 }
3058 p++;
3059 }
3060 q+=GetPixelChannels(image);
3061 }
3062 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3063 break;
3064 }
3065}
3066
cristycafe0412012-01-10 13:29:58 +00003067static void ImportLongPixel(Image *image,const RectangleInfo *roi,
cristy46f4be22012-01-07 00:26:39 +00003068 const char *restrict map,const QuantumType *quantum_map,const void *pixels,
3069 ExceptionInfo *exception)
cristye5370942012-01-06 03:49:31 +00003070{
3071 register const unsigned int
3072 *restrict p;
3073
3074 register Quantum
cristy3fe11452012-01-09 01:27:42 +00003075 *restrict q;
cristye5370942012-01-06 03:49:31 +00003076
3077 register ssize_t
3078 x;
3079
cristy14d71292012-05-20 16:48:13 +00003080 size_t
3081 length;
3082
cristye5370942012-01-06 03:49:31 +00003083 ssize_t
3084 y;
3085
3086 p=(const unsigned int *) pixels;
3087 if (LocaleCompare(map,"BGR") == 0)
3088 {
cristycafe0412012-01-10 13:29:58 +00003089 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00003090 {
cristycafe0412012-01-10 13:29:58 +00003091 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00003092 if (q == (Quantum *) NULL)
3093 break;
cristycafe0412012-01-10 13:29:58 +00003094 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00003095 {
3096 SetPixelBlue(image,ScaleLongToQuantum(*p++),q);
3097 SetPixelGreen(image,ScaleLongToQuantum(*p++),q);
3098 SetPixelRed(image,ScaleLongToQuantum(*p++),q);
3099 q+=GetPixelChannels(image);
3100 }
3101 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3102 break;
3103 }
3104 return;
3105 }
3106 if (LocaleCompare(map,"BGRA") == 0)
3107 {
cristycafe0412012-01-10 13:29:58 +00003108 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00003109 {
cristycafe0412012-01-10 13:29:58 +00003110 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00003111 if (q == (Quantum *) NULL)
3112 break;
cristycafe0412012-01-10 13:29:58 +00003113 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00003114 {
3115 SetPixelBlue(image,ScaleLongToQuantum(*p++),q);
3116 SetPixelGreen(image,ScaleLongToQuantum(*p++),q);
3117 SetPixelRed(image,ScaleLongToQuantum(*p++),q);
3118 SetPixelAlpha(image,ScaleLongToQuantum(*p++),q);
3119 q+=GetPixelChannels(image);
3120 }
3121 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3122 break;
3123 }
3124 return;
3125 }
3126 if (LocaleCompare(map,"BGRP") == 0)
3127 {
cristycafe0412012-01-10 13:29:58 +00003128 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00003129 {
cristycafe0412012-01-10 13:29:58 +00003130 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00003131 if (q == (Quantum *) NULL)
3132 break;
cristycafe0412012-01-10 13:29:58 +00003133 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00003134 {
3135 SetPixelBlue(image,ScaleLongToQuantum(*p++),q);
3136 SetPixelGreen(image,ScaleLongToQuantum(*p++),q);
3137 SetPixelRed(image,ScaleLongToQuantum(*p++),q);
3138 p++;
3139 q+=GetPixelChannels(image);
3140 }
3141 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3142 break;
3143 }
3144 return;
3145 }
3146 if (LocaleCompare(map,"I") == 0)
3147 {
cristycafe0412012-01-10 13:29:58 +00003148 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00003149 {
cristycafe0412012-01-10 13:29:58 +00003150 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00003151 if (q == (Quantum *) NULL)
3152 break;
cristycafe0412012-01-10 13:29:58 +00003153 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00003154 {
3155 SetPixelGray(image,ScaleLongToQuantum(*p++),q);
3156 q+=GetPixelChannels(image);
3157 }
3158 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3159 break;
3160 }
3161 return;
3162 }
3163 if (LocaleCompare(map,"RGB") == 0)
3164 {
cristycafe0412012-01-10 13:29:58 +00003165 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00003166 {
cristycafe0412012-01-10 13:29:58 +00003167 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00003168 if (q == (Quantum *) NULL)
3169 break;
cristycafe0412012-01-10 13:29:58 +00003170 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00003171 {
3172 SetPixelRed(image,ScaleLongToQuantum(*p++),q);
3173 SetPixelGreen(image,ScaleLongToQuantum(*p++),q);
3174 SetPixelBlue(image,ScaleLongToQuantum(*p++),q);
3175 q+=GetPixelChannels(image);
3176 }
3177 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3178 break;
3179 }
3180 return;
3181 }
3182 if (LocaleCompare(map,"RGBA") == 0)
3183 {
cristycafe0412012-01-10 13:29:58 +00003184 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00003185 {
cristycafe0412012-01-10 13:29:58 +00003186 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00003187 if (q == (Quantum *) NULL)
3188 break;
cristycafe0412012-01-10 13:29:58 +00003189 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00003190 {
3191 SetPixelRed(image,ScaleLongToQuantum(*p++),q);
3192 SetPixelGreen(image,ScaleLongToQuantum(*p++),q);
3193 SetPixelBlue(image,ScaleLongToQuantum(*p++),q);
3194 SetPixelAlpha(image,ScaleLongToQuantum(*p++),q);
3195 q+=GetPixelChannels(image);
3196 }
3197 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3198 break;
3199 }
3200 return;
3201 }
3202 if (LocaleCompare(map,"RGBP") == 0)
3203 {
cristycafe0412012-01-10 13:29:58 +00003204 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00003205 {
cristycafe0412012-01-10 13:29:58 +00003206 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00003207 if (q == (Quantum *) NULL)
3208 break;
cristycafe0412012-01-10 13:29:58 +00003209 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00003210 {
3211 SetPixelRed(image,ScaleLongToQuantum(*p++),q);
3212 SetPixelGreen(image,ScaleLongToQuantum(*p++),q);
3213 SetPixelBlue(image,ScaleLongToQuantum(*p++),q);
3214 p++;
3215 q+=GetPixelChannels(image);
3216 }
3217 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3218 break;
3219 }
3220 return;
3221 }
cristy14d71292012-05-20 16:48:13 +00003222 length=strlen(map);
cristycafe0412012-01-10 13:29:58 +00003223 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00003224 {
cristycafe0412012-01-10 13:29:58 +00003225 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00003226 if (q == (Quantum *) NULL)
3227 break;
cristycafe0412012-01-10 13:29:58 +00003228 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00003229 {
3230 register ssize_t
3231 i;
3232
cristy14d71292012-05-20 16:48:13 +00003233 for (i=0; i < (ssize_t) length; i++)
cristye5370942012-01-06 03:49:31 +00003234 {
3235 switch (quantum_map[i])
3236 {
3237 case RedQuantum:
3238 case CyanQuantum:
3239 {
3240 SetPixelRed(image,ScaleLongToQuantum(*p),q);
3241 break;
3242 }
3243 case GreenQuantum:
3244 case MagentaQuantum:
3245 {
3246 SetPixelGreen(image,ScaleLongToQuantum(*p),q);
3247 break;
3248 }
3249 case BlueQuantum:
3250 case YellowQuantum:
3251 {
3252 SetPixelBlue(image,ScaleLongToQuantum(*p),q);
3253 break;
3254 }
3255 case AlphaQuantum:
3256 {
3257 SetPixelAlpha(image,ScaleLongToQuantum(*p),q);
3258 break;
3259 }
3260 case OpacityQuantum:
3261 {
3262 SetPixelAlpha(image,ScaleLongToQuantum(*p),q);
3263 break;
3264 }
3265 case BlackQuantum:
3266 {
3267 SetPixelBlack(image,ScaleLongToQuantum(*p),q);
3268 break;
3269 }
3270 case IndexQuantum:
3271 {
3272 SetPixelGray(image,ScaleLongToQuantum(*p),q);
3273 break;
3274 }
3275 default:
3276 break;
3277 }
3278 p++;
3279 }
3280 q+=GetPixelChannels(image);
3281 }
3282 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3283 break;
3284 }
3285}
3286
cristycafe0412012-01-10 13:29:58 +00003287static void ImportLongLongPixel(Image *image,const RectangleInfo *roi,
cristy46f4be22012-01-07 00:26:39 +00003288 const char *restrict map,const QuantumType *quantum_map,const void *pixels,
3289 ExceptionInfo *exception)
cristye5370942012-01-06 03:49:31 +00003290{
cristyb13e12a2012-01-06 21:48:27 +00003291 register const MagickSizeType
cristye5370942012-01-06 03:49:31 +00003292 *restrict p;
3293
3294 register Quantum
cristy3fe11452012-01-09 01:27:42 +00003295 *restrict q;
cristye5370942012-01-06 03:49:31 +00003296
3297 register ssize_t
3298 x;
3299
cristy14d71292012-05-20 16:48:13 +00003300 size_t
3301 length;
3302
cristye5370942012-01-06 03:49:31 +00003303 ssize_t
3304 y;
3305
cristyb13e12a2012-01-06 21:48:27 +00003306 p=(const MagickSizeType *) pixels;
cristye5370942012-01-06 03:49:31 +00003307 if (LocaleCompare(map,"BGR") == 0)
3308 {
cristycafe0412012-01-10 13:29:58 +00003309 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00003310 {
cristycafe0412012-01-10 13:29:58 +00003311 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00003312 if (q == (Quantum *) NULL)
3313 break;
cristycafe0412012-01-10 13:29:58 +00003314 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00003315 {
cristyb13e12a2012-01-06 21:48:27 +00003316 SetPixelBlue(image,ScaleLongLongToQuantum(*p++),q);
3317 SetPixelGreen(image,ScaleLongLongToQuantum(*p++),q);
3318 SetPixelRed(image,ScaleLongLongToQuantum(*p++),q);
cristye5370942012-01-06 03:49:31 +00003319 q+=GetPixelChannels(image);
3320 }
3321 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3322 break;
3323 }
3324 return;
3325 }
3326 if (LocaleCompare(map,"BGRA") == 0)
3327 {
cristycafe0412012-01-10 13:29:58 +00003328 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00003329 {
cristycafe0412012-01-10 13:29:58 +00003330 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00003331 if (q == (Quantum *) NULL)
3332 break;
cristycafe0412012-01-10 13:29:58 +00003333 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00003334 {
cristyb13e12a2012-01-06 21:48:27 +00003335 SetPixelBlue(image,ScaleLongLongToQuantum(*p++),q);
3336 SetPixelGreen(image,ScaleLongLongToQuantum(*p++),q);
3337 SetPixelRed(image,ScaleLongLongToQuantum(*p++),q);
3338 SetPixelAlpha(image,ScaleLongLongToQuantum(*p++),q);
cristye5370942012-01-06 03:49:31 +00003339 q+=GetPixelChannels(image);
3340 }
3341 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3342 break;
3343 }
3344 return;
3345 }
3346 if (LocaleCompare(map,"BGRP") == 0)
3347 {
cristycafe0412012-01-10 13:29:58 +00003348 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00003349 {
cristycafe0412012-01-10 13:29:58 +00003350 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00003351 if (q == (Quantum *) NULL)
3352 break;
cristycafe0412012-01-10 13:29:58 +00003353 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00003354 {
cristyb13e12a2012-01-06 21:48:27 +00003355 SetPixelBlue(image,ScaleLongLongToQuantum(*p++),q);
3356 SetPixelGreen(image,ScaleLongLongToQuantum(*p++),q);
3357 SetPixelRed(image,ScaleLongLongToQuantum(*p++),q);
cristye5370942012-01-06 03:49:31 +00003358 p++;
3359 q+=GetPixelChannels(image);
3360 }
3361 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3362 break;
3363 }
3364 return;
3365 }
3366 if (LocaleCompare(map,"I") == 0)
3367 {
cristycafe0412012-01-10 13:29:58 +00003368 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00003369 {
cristycafe0412012-01-10 13:29:58 +00003370 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00003371 if (q == (Quantum *) NULL)
3372 break;
cristycafe0412012-01-10 13:29:58 +00003373 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00003374 {
cristyb13e12a2012-01-06 21:48:27 +00003375 SetPixelGray(image,ScaleLongLongToQuantum(*p++),q);
cristye5370942012-01-06 03:49:31 +00003376 q+=GetPixelChannels(image);
3377 }
3378 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3379 break;
3380 }
3381 return;
3382 }
3383 if (LocaleCompare(map,"RGB") == 0)
3384 {
cristycafe0412012-01-10 13:29:58 +00003385 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00003386 {
cristycafe0412012-01-10 13:29:58 +00003387 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00003388 if (q == (Quantum *) NULL)
3389 break;
cristycafe0412012-01-10 13:29:58 +00003390 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00003391 {
cristyb13e12a2012-01-06 21:48:27 +00003392 SetPixelRed(image,ScaleLongLongToQuantum(*p++),q);
3393 SetPixelGreen(image,ScaleLongLongToQuantum(*p++),q);
3394 SetPixelBlue(image,ScaleLongLongToQuantum(*p++),q);
cristye5370942012-01-06 03:49:31 +00003395 q+=GetPixelChannels(image);
3396 }
3397 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3398 break;
3399 }
3400 return;
3401 }
3402 if (LocaleCompare(map,"RGBA") == 0)
3403 {
cristycafe0412012-01-10 13:29:58 +00003404 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00003405 {
cristycafe0412012-01-10 13:29:58 +00003406 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00003407 if (q == (Quantum *) NULL)
3408 break;
cristycafe0412012-01-10 13:29:58 +00003409 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00003410 {
cristyb13e12a2012-01-06 21:48:27 +00003411 SetPixelRed(image,ScaleLongLongToQuantum(*p++),q);
3412 SetPixelGreen(image,ScaleLongLongToQuantum(*p++),q);
3413 SetPixelBlue(image,ScaleLongLongToQuantum(*p++),q);
3414 SetPixelAlpha(image,ScaleLongLongToQuantum(*p++),q);
cristye5370942012-01-06 03:49:31 +00003415 q+=GetPixelChannels(image);
3416 }
3417 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3418 break;
3419 }
3420 return;
3421 }
3422 if (LocaleCompare(map,"RGBP") == 0)
3423 {
cristycafe0412012-01-10 13:29:58 +00003424 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00003425 {
cristycafe0412012-01-10 13:29:58 +00003426 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00003427 if (q == (Quantum *) NULL)
3428 break;
cristycafe0412012-01-10 13:29:58 +00003429 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00003430 {
cristyb13e12a2012-01-06 21:48:27 +00003431 SetPixelRed(image,ScaleLongLongToQuantum(*p++),q);
3432 SetPixelGreen(image,ScaleLongLongToQuantum(*p++),q);
3433 SetPixelBlue(image,ScaleLongLongToQuantum(*p++),q);
cristye5370942012-01-06 03:49:31 +00003434 p++;
3435 q+=GetPixelChannels(image);
3436 }
3437 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3438 break;
3439 }
3440 return;
3441 }
cristy14d71292012-05-20 16:48:13 +00003442 length=strlen(map);
cristycafe0412012-01-10 13:29:58 +00003443 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00003444 {
cristycafe0412012-01-10 13:29:58 +00003445 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00003446 if (q == (Quantum *) NULL)
3447 break;
cristycafe0412012-01-10 13:29:58 +00003448 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00003449 {
3450 register ssize_t
3451 i;
3452
cristy14d71292012-05-20 16:48:13 +00003453 for (i=0; i < (ssize_t) length; i++)
cristye5370942012-01-06 03:49:31 +00003454 {
3455 switch (quantum_map[i])
3456 {
3457 case RedQuantum:
3458 case CyanQuantum:
3459 {
cristyb13e12a2012-01-06 21:48:27 +00003460 SetPixelRed(image,ScaleLongLongToQuantum(*p),q);
cristye5370942012-01-06 03:49:31 +00003461 break;
3462 }
3463 case GreenQuantum:
3464 case MagentaQuantum:
3465 {
cristyb13e12a2012-01-06 21:48:27 +00003466 SetPixelGreen(image,ScaleLongLongToQuantum(*p),q);
cristye5370942012-01-06 03:49:31 +00003467 break;
3468 }
3469 case BlueQuantum:
3470 case YellowQuantum:
3471 {
cristyb13e12a2012-01-06 21:48:27 +00003472 SetPixelBlue(image,ScaleLongLongToQuantum(*p),q);
cristye5370942012-01-06 03:49:31 +00003473 break;
3474 }
3475 case AlphaQuantum:
3476 {
cristyb13e12a2012-01-06 21:48:27 +00003477 SetPixelAlpha(image,ScaleLongLongToQuantum(*p),q);
cristye5370942012-01-06 03:49:31 +00003478 break;
3479 }
3480 case OpacityQuantum:
3481 {
cristyb13e12a2012-01-06 21:48:27 +00003482 SetPixelAlpha(image,ScaleLongLongToQuantum(*p),q);
cristye5370942012-01-06 03:49:31 +00003483 break;
3484 }
3485 case BlackQuantum:
3486 {
cristyb13e12a2012-01-06 21:48:27 +00003487 SetPixelBlack(image,ScaleLongLongToQuantum(*p),q);
cristye5370942012-01-06 03:49:31 +00003488 break;
3489 }
3490 case IndexQuantum:
3491 {
cristyb13e12a2012-01-06 21:48:27 +00003492 SetPixelGray(image,ScaleLongLongToQuantum(*p),q);
cristye5370942012-01-06 03:49:31 +00003493 break;
3494 }
3495 default:
3496 break;
3497 }
3498 p++;
3499 }
3500 q+=GetPixelChannels(image);
3501 }
3502 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3503 break;
3504 }
3505}
3506
cristycafe0412012-01-10 13:29:58 +00003507static void ImportQuantumPixel(Image *image,const RectangleInfo *roi,
cristy46f4be22012-01-07 00:26:39 +00003508 const char *restrict map,const QuantumType *quantum_map,const void *pixels,
3509 ExceptionInfo *exception)
cristye5370942012-01-06 03:49:31 +00003510{
3511 register const Quantum
3512 *restrict p;
3513
3514 register Quantum
cristy3fe11452012-01-09 01:27:42 +00003515 *restrict q;
cristye5370942012-01-06 03:49:31 +00003516
3517 register ssize_t
3518 x;
3519
cristy14d71292012-05-20 16:48:13 +00003520 size_t
3521 length;
3522
cristye5370942012-01-06 03:49:31 +00003523 ssize_t
3524 y;
3525
3526 p=(const Quantum *) pixels;
3527 if (LocaleCompare(map,"BGR") == 0)
3528 {
cristycafe0412012-01-10 13:29:58 +00003529 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00003530 {
cristycafe0412012-01-10 13:29:58 +00003531 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00003532 if (q == (Quantum *) NULL)
3533 break;
cristycafe0412012-01-10 13:29:58 +00003534 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00003535 {
3536 SetPixelBlue(image,*p++,q);
3537 SetPixelGreen(image,*p++,q);
3538 SetPixelRed(image,*p++,q);
3539 q+=GetPixelChannels(image);
3540 }
3541 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3542 break;
3543 }
3544 return;
3545 }
3546 if (LocaleCompare(map,"BGRA") == 0)
3547 {
cristycafe0412012-01-10 13:29:58 +00003548 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00003549 {
cristycafe0412012-01-10 13:29:58 +00003550 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00003551 if (q == (Quantum *) NULL)
3552 break;
cristycafe0412012-01-10 13:29:58 +00003553 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00003554 {
3555 SetPixelBlue(image,*p++,q);
3556 SetPixelGreen(image,*p++,q);
3557 SetPixelRed(image,*p++,q);
3558 SetPixelAlpha(image,*p++,q);
3559 q+=GetPixelChannels(image);
3560 }
3561 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3562 break;
3563 }
3564 return;
3565 }
3566 if (LocaleCompare(map,"BGRP") == 0)
3567 {
cristycafe0412012-01-10 13:29:58 +00003568 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00003569 {
cristycafe0412012-01-10 13:29:58 +00003570 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00003571 if (q == (Quantum *) NULL)
3572 break;
cristycafe0412012-01-10 13:29:58 +00003573 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00003574 {
3575 SetPixelBlue(image,*p++,q);
3576 SetPixelGreen(image,*p++,q);
3577 SetPixelRed(image,*p++,q);
3578 p++;
3579 q+=GetPixelChannels(image);
3580 }
3581 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3582 break;
3583 }
3584 return;
3585 }
3586 if (LocaleCompare(map,"I") == 0)
3587 {
cristycafe0412012-01-10 13:29:58 +00003588 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00003589 {
cristycafe0412012-01-10 13:29:58 +00003590 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00003591 if (q == (Quantum *) NULL)
3592 break;
cristycafe0412012-01-10 13:29:58 +00003593 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00003594 {
3595 SetPixelGray(image,*p++,q);
3596 q+=GetPixelChannels(image);
3597 }
3598 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3599 break;
3600 }
3601 return;
3602 }
3603 if (LocaleCompare(map,"RGB") == 0)
3604 {
cristycafe0412012-01-10 13:29:58 +00003605 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00003606 {
cristycafe0412012-01-10 13:29:58 +00003607 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00003608 if (q == (Quantum *) NULL)
3609 break;
cristycafe0412012-01-10 13:29:58 +00003610 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00003611 {
3612 SetPixelRed(image,*p++,q);
3613 SetPixelGreen(image,*p++,q);
3614 SetPixelBlue(image,*p++,q);
3615 q+=GetPixelChannels(image);
3616 }
3617 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3618 break;
3619 }
3620 return;
3621 }
3622 if (LocaleCompare(map,"RGBA") == 0)
3623 {
cristycafe0412012-01-10 13:29:58 +00003624 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00003625 {
cristycafe0412012-01-10 13:29:58 +00003626 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00003627 if (q == (Quantum *) NULL)
3628 break;
cristycafe0412012-01-10 13:29:58 +00003629 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00003630 {
3631 SetPixelRed(image,*p++,q);
3632 SetPixelGreen(image,*p++,q);
3633 SetPixelBlue(image,*p++,q);
3634 SetPixelAlpha(image,*p++,q);
3635 q+=GetPixelChannels(image);
3636 }
3637 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3638 break;
3639 }
3640 return;
3641 }
3642 if (LocaleCompare(map,"RGBP") == 0)
3643 {
cristycafe0412012-01-10 13:29:58 +00003644 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00003645 {
cristycafe0412012-01-10 13:29:58 +00003646 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00003647 if (q == (Quantum *) NULL)
3648 break;
cristycafe0412012-01-10 13:29:58 +00003649 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00003650 {
3651 SetPixelRed(image,*p++,q);
3652 SetPixelGreen(image,*p++,q);
3653 SetPixelBlue(image,*p++,q);
3654 p++;
3655 q+=GetPixelChannels(image);
3656 }
3657 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3658 break;
3659 }
3660 return;
3661 }
cristy14d71292012-05-20 16:48:13 +00003662 length=strlen(map);
cristycafe0412012-01-10 13:29:58 +00003663 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00003664 {
cristycafe0412012-01-10 13:29:58 +00003665 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00003666 if (q == (Quantum *) NULL)
3667 break;
cristycafe0412012-01-10 13:29:58 +00003668 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00003669 {
3670 register ssize_t
3671 i;
3672
cristy14d71292012-05-20 16:48:13 +00003673 for (i=0; i < (ssize_t) length; i++)
cristye5370942012-01-06 03:49:31 +00003674 {
3675 switch (quantum_map[i])
3676 {
3677 case RedQuantum:
3678 case CyanQuantum:
3679 {
3680 SetPixelRed(image,*p,q);
3681 break;
3682 }
3683 case GreenQuantum:
3684 case MagentaQuantum:
3685 {
3686 SetPixelGreen(image,*p,q);
3687 break;
3688 }
3689 case BlueQuantum:
3690 case YellowQuantum:
3691 {
3692 SetPixelBlue(image,*p,q);
3693 break;
3694 }
3695 case AlphaQuantum:
3696 {
3697 SetPixelAlpha(image,*p,q);
3698 break;
3699 }
3700 case OpacityQuantum:
3701 {
3702 SetPixelAlpha(image,*p,q);
3703 break;
3704 }
3705 case BlackQuantum:
3706 {
3707 SetPixelBlack(image,*p,q);
3708 break;
3709 }
3710 case IndexQuantum:
3711 {
3712 SetPixelGray(image,*p,q);
3713 break;
3714 }
3715 default:
3716 break;
3717 }
3718 p++;
3719 }
3720 q+=GetPixelChannels(image);
3721 }
3722 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3723 break;
3724 }
3725}
3726
cristycafe0412012-01-10 13:29:58 +00003727static void ImportShortPixel(Image *image,const RectangleInfo *roi,
cristy46f4be22012-01-07 00:26:39 +00003728 const char *restrict map,const QuantumType *quantum_map,const void *pixels,
3729 ExceptionInfo *exception)
cristye5370942012-01-06 03:49:31 +00003730{
3731 register const unsigned short
3732 *restrict p;
3733
3734 register Quantum
cristy3fe11452012-01-09 01:27:42 +00003735 *restrict q;
cristye5370942012-01-06 03:49:31 +00003736
3737 register ssize_t
3738 x;
3739
cristy14d71292012-05-20 16:48:13 +00003740 size_t
3741 length;
3742
cristye5370942012-01-06 03:49:31 +00003743 ssize_t
3744 y;
3745
3746 p=(const unsigned short *) pixels;
3747 if (LocaleCompare(map,"BGR") == 0)
3748 {
cristycafe0412012-01-10 13:29:58 +00003749 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00003750 {
cristycafe0412012-01-10 13:29:58 +00003751 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00003752 if (q == (Quantum *) NULL)
3753 break;
cristycafe0412012-01-10 13:29:58 +00003754 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00003755 {
3756 SetPixelBlue(image,ScaleShortToQuantum(*p++),q);
3757 SetPixelGreen(image,ScaleShortToQuantum(*p++),q);
3758 SetPixelRed(image,ScaleShortToQuantum(*p++),q);
3759 q+=GetPixelChannels(image);
3760 }
3761 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3762 break;
3763 }
3764 return;
3765 }
3766 if (LocaleCompare(map,"BGRA") == 0)
3767 {
cristycafe0412012-01-10 13:29:58 +00003768 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00003769 {
cristycafe0412012-01-10 13:29:58 +00003770 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00003771 if (q == (Quantum *) NULL)
3772 break;
cristycafe0412012-01-10 13:29:58 +00003773 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00003774 {
3775 SetPixelBlue(image,ScaleShortToQuantum(*p++),q);
3776 SetPixelGreen(image,ScaleShortToQuantum(*p++),q);
3777 SetPixelRed(image,ScaleShortToQuantum(*p++),q);
3778 SetPixelAlpha(image,ScaleShortToQuantum(*p++),q);
3779 q+=GetPixelChannels(image);
3780 }
3781 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3782 break;
3783 }
3784 return;
3785 }
3786 if (LocaleCompare(map,"BGRP") == 0)
3787 {
cristycafe0412012-01-10 13:29:58 +00003788 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00003789 {
cristycafe0412012-01-10 13:29:58 +00003790 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00003791 if (q == (Quantum *) NULL)
3792 break;
cristycafe0412012-01-10 13:29:58 +00003793 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00003794 {
3795 SetPixelBlue(image,ScaleShortToQuantum(*p++),q);
3796 SetPixelGreen(image,ScaleShortToQuantum(*p++),q);
3797 SetPixelRed(image,ScaleShortToQuantum(*p++),q);
3798 p++;
3799 q+=GetPixelChannels(image);
3800 }
3801 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3802 break;
3803 }
3804 return;
3805 }
3806 if (LocaleCompare(map,"I") == 0)
3807 {
cristycafe0412012-01-10 13:29:58 +00003808 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00003809 {
cristycafe0412012-01-10 13:29:58 +00003810 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00003811 if (q == (Quantum *) NULL)
3812 break;
cristycafe0412012-01-10 13:29:58 +00003813 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00003814 {
3815 SetPixelGray(image,ScaleShortToQuantum(*p++),q);
3816 q+=GetPixelChannels(image);
3817 }
3818 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3819 break;
3820 }
3821 return;
3822 }
3823 if (LocaleCompare(map,"RGB") == 0)
3824 {
cristycafe0412012-01-10 13:29:58 +00003825 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00003826 {
cristycafe0412012-01-10 13:29:58 +00003827 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00003828 if (q == (Quantum *) NULL)
3829 break;
cristycafe0412012-01-10 13:29:58 +00003830 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00003831 {
3832 SetPixelRed(image,ScaleShortToQuantum(*p++),q);
3833 SetPixelGreen(image,ScaleShortToQuantum(*p++),q);
3834 SetPixelBlue(image,ScaleShortToQuantum(*p++),q);
3835 q+=GetPixelChannels(image);
3836 }
3837 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3838 break;
3839 }
3840 return;
3841 }
3842 if (LocaleCompare(map,"RGBA") == 0)
3843 {
cristycafe0412012-01-10 13:29:58 +00003844 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00003845 {
cristycafe0412012-01-10 13:29:58 +00003846 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00003847 if (q == (Quantum *) NULL)
3848 break;
cristycafe0412012-01-10 13:29:58 +00003849 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00003850 {
3851 SetPixelRed(image,ScaleShortToQuantum(*p++),q);
3852 SetPixelGreen(image,ScaleShortToQuantum(*p++),q);
3853 SetPixelBlue(image,ScaleShortToQuantum(*p++),q);
3854 SetPixelAlpha(image,ScaleShortToQuantum(*p++),q);
3855 q+=GetPixelChannels(image);
3856 }
3857 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3858 break;
3859 }
3860 return;
3861 }
3862 if (LocaleCompare(map,"RGBP") == 0)
3863 {
cristycafe0412012-01-10 13:29:58 +00003864 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00003865 {
cristycafe0412012-01-10 13:29:58 +00003866 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00003867 if (q == (Quantum *) NULL)
3868 break;
cristycafe0412012-01-10 13:29:58 +00003869 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00003870 {
3871 SetPixelRed(image,ScaleShortToQuantum(*p++),q);
3872 SetPixelGreen(image,ScaleShortToQuantum(*p++),q);
3873 SetPixelBlue(image,ScaleShortToQuantum(*p++),q);
3874 p++;
3875 q+=GetPixelChannels(image);
3876 }
3877 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3878 break;
3879 }
3880 return;
3881 }
cristy14d71292012-05-20 16:48:13 +00003882 length=strlen(map);
cristycafe0412012-01-10 13:29:58 +00003883 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00003884 {
cristycafe0412012-01-10 13:29:58 +00003885 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00003886 if (q == (Quantum *) NULL)
3887 break;
cristycafe0412012-01-10 13:29:58 +00003888 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00003889 {
3890 register ssize_t
3891 i;
3892
cristy14d71292012-05-20 16:48:13 +00003893 for (i=0; i < (ssize_t) length; i++)
cristye5370942012-01-06 03:49:31 +00003894 {
3895 switch (quantum_map[i])
3896 {
3897 case RedQuantum:
3898 case CyanQuantum:
3899 {
3900 SetPixelRed(image,ScaleShortToQuantum(*p),q);
3901 break;
3902 }
3903 case GreenQuantum:
3904 case MagentaQuantum:
3905 {
3906 SetPixelGreen(image,ScaleShortToQuantum(*p),q);
3907 break;
3908 }
3909 case BlueQuantum:
3910 case YellowQuantum:
3911 {
3912 SetPixelBlue(image,ScaleShortToQuantum(*p),q);
3913 break;
3914 }
3915 case AlphaQuantum:
3916 {
3917 SetPixelAlpha(image,ScaleShortToQuantum(*p),q);
3918 break;
3919 }
3920 case OpacityQuantum:
3921 {
3922 SetPixelAlpha(image,ScaleShortToQuantum(*p),q);
3923 break;
3924 }
3925 case BlackQuantum:
3926 {
3927 SetPixelBlack(image,ScaleShortToQuantum(*p),q);
3928 break;
3929 }
3930 case IndexQuantum:
3931 {
3932 SetPixelGray(image,ScaleShortToQuantum(*p),q);
3933 break;
3934 }
3935 default:
3936 break;
3937 }
3938 p++;
3939 }
3940 q+=GetPixelChannels(image);
3941 }
3942 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3943 break;
3944 }
3945}
3946
cristycafe0412012-01-10 13:29:58 +00003947MagickExport MagickBooleanType ImportImagePixels(Image *image,const ssize_t x,
3948 const ssize_t y,const size_t width,const size_t height,const char *map,
3949 const StorageType type,const void *pixels,ExceptionInfo *exception)
cristy4c08aed2011-07-01 19:47:50 +00003950{
cristy4c08aed2011-07-01 19:47:50 +00003951 QuantumType
3952 *quantum_map;
3953
cristycafe0412012-01-10 13:29:58 +00003954 RectangleInfo
3955 roi;
3956
cristy4c08aed2011-07-01 19:47:50 +00003957 register ssize_t
cristye5370942012-01-06 03:49:31 +00003958 i;
cristy4c08aed2011-07-01 19:47:50 +00003959
cristy14d71292012-05-20 16:48:13 +00003960 size_t
3961 length;
3962
cristy4c08aed2011-07-01 19:47:50 +00003963 /*
3964 Allocate image structure.
3965 */
3966 assert(image != (Image *) NULL);
3967 assert(image->signature == MagickSignature);
3968 if (image->debug != MagickFalse)
3969 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
cristy14d71292012-05-20 16:48:13 +00003970 length=strlen(map);
3971 quantum_map=(QuantumType *) AcquireQuantumMemory(length,sizeof(*quantum_map));
cristy4c08aed2011-07-01 19:47:50 +00003972 if (quantum_map == (QuantumType *) NULL)
3973 ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
3974 image->filename);
cristy14d71292012-05-20 16:48:13 +00003975 for (i=0; i < (ssize_t) length; i++)
cristy4c08aed2011-07-01 19:47:50 +00003976 {
3977 switch (map[i])
3978 {
3979 case 'a':
3980 case 'A':
3981 {
3982 quantum_map[i]=AlphaQuantum;
cristy8a46d822012-08-28 23:32:39 +00003983 image->alpha_trait=BlendPixelTrait;
cristy4c08aed2011-07-01 19:47:50 +00003984 break;
3985 }
3986 case 'B':
3987 case 'b':
3988 {
3989 quantum_map[i]=BlueQuantum;
3990 break;
3991 }
3992 case 'C':
3993 case 'c':
3994 {
3995 quantum_map[i]=CyanQuantum;
cristy63240882011-08-05 19:05:27 +00003996 (void) SetImageColorspace(image,CMYKColorspace,exception);
cristy4c08aed2011-07-01 19:47:50 +00003997 break;
3998 }
3999 case 'g':
4000 case 'G':
4001 {
4002 quantum_map[i]=GreenQuantum;
4003 break;
4004 }
4005 case 'K':
4006 case 'k':
4007 {
4008 quantum_map[i]=BlackQuantum;
cristy63240882011-08-05 19:05:27 +00004009 (void) SetImageColorspace(image,CMYKColorspace,exception);
cristy4c08aed2011-07-01 19:47:50 +00004010 break;
4011 }
4012 case 'I':
4013 case 'i':
4014 {
4015 quantum_map[i]=IndexQuantum;
cristyb7b3da62012-07-05 15:43:37 +00004016 (void) SetImageColorspace(image,GRAYColorspace,exception);
cristy4c08aed2011-07-01 19:47:50 +00004017 break;
4018 }
4019 case 'm':
4020 case 'M':
4021 {
4022 quantum_map[i]=MagentaQuantum;
cristy63240882011-08-05 19:05:27 +00004023 (void) SetImageColorspace(image,CMYKColorspace,exception);
cristy4c08aed2011-07-01 19:47:50 +00004024 break;
4025 }
4026 case 'O':
4027 case 'o':
4028 {
4029 quantum_map[i]=OpacityQuantum;
cristy8a46d822012-08-28 23:32:39 +00004030 image->alpha_trait=BlendPixelTrait;
cristy4c08aed2011-07-01 19:47:50 +00004031 break;
4032 }
4033 case 'P':
4034 case 'p':
4035 {
4036 quantum_map[i]=UndefinedQuantum;
4037 break;
4038 }
4039 case 'R':
4040 case 'r':
4041 {
4042 quantum_map[i]=RedQuantum;
4043 break;
4044 }
4045 case 'Y':
4046 case 'y':
4047 {
4048 quantum_map[i]=YellowQuantum;
cristy63240882011-08-05 19:05:27 +00004049 (void) SetImageColorspace(image,CMYKColorspace,exception);
cristy4c08aed2011-07-01 19:47:50 +00004050 break;
4051 }
4052 default:
4053 {
4054 quantum_map=(QuantumType *) RelinquishMagickMemory(quantum_map);
cristy63240882011-08-05 19:05:27 +00004055 (void) ThrowMagickException(exception,GetMagickModule(),OptionError,
cristyefe601c2013-01-05 17:51:12 +00004056 "UnrecognizedPixelMap","`%s'",map);
cristy4c08aed2011-07-01 19:47:50 +00004057 return(MagickFalse);
4058 }
4059 }
4060 }
cristy63240882011-08-05 19:05:27 +00004061 if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
cristy4c08aed2011-07-01 19:47:50 +00004062 return(MagickFalse);
4063 /*
cristye5370942012-01-06 03:49:31 +00004064 Transfer the pixels from the pixel data to the image.
cristy4c08aed2011-07-01 19:47:50 +00004065 */
cristycafe0412012-01-10 13:29:58 +00004066 roi.width=width;
4067 roi.height=height;
4068 roi.x=x;
4069 roi.y=y;
cristy4c08aed2011-07-01 19:47:50 +00004070 switch (type)
4071 {
4072 case CharPixel:
4073 {
cristycafe0412012-01-10 13:29:58 +00004074 ImportCharPixel(image,&roi,map,quantum_map,pixels,exception);
cristy4c08aed2011-07-01 19:47:50 +00004075 break;
4076 }
4077 case DoublePixel:
4078 {
cristycafe0412012-01-10 13:29:58 +00004079 ImportDoublePixel(image,&roi,map,quantum_map,pixels,exception);
cristy4c08aed2011-07-01 19:47:50 +00004080 break;
4081 }
4082 case FloatPixel:
4083 {
cristycafe0412012-01-10 13:29:58 +00004084 ImportFloatPixel(image,&roi,map,quantum_map,pixels,exception);
cristy4c08aed2011-07-01 19:47:50 +00004085 break;
4086 }
cristy4c08aed2011-07-01 19:47:50 +00004087 case LongPixel:
4088 {
cristycafe0412012-01-10 13:29:58 +00004089 ImportLongPixel(image,&roi,map,quantum_map,pixels,exception);
cristy4c08aed2011-07-01 19:47:50 +00004090 break;
4091 }
cristy6c9e1682012-01-07 21:37:44 +00004092 case LongLongPixel:
4093 {
cristycafe0412012-01-10 13:29:58 +00004094 ImportLongLongPixel(image,&roi,map,quantum_map,pixels,exception);
cristy6c9e1682012-01-07 21:37:44 +00004095 break;
4096 }
cristy4c08aed2011-07-01 19:47:50 +00004097 case QuantumPixel:
4098 {
cristycafe0412012-01-10 13:29:58 +00004099 ImportQuantumPixel(image,&roi,map,quantum_map,pixels,exception);
cristy4c08aed2011-07-01 19:47:50 +00004100 break;
4101 }
4102 case ShortPixel:
4103 {
cristycafe0412012-01-10 13:29:58 +00004104 ImportShortPixel(image,&roi,map,quantum_map,pixels,exception);
cristy4c08aed2011-07-01 19:47:50 +00004105 break;
4106 }
4107 default:
4108 {
4109 quantum_map=(QuantumType *) RelinquishMagickMemory(quantum_map);
cristyc82a27b2011-10-21 01:07:16 +00004110 (void) ThrowMagickException(exception,GetMagickModule(),OptionError,
dirk94db6c12013-08-18 21:00:02 +00004111 "UnrecognizedStorageType","`%d'",type);
cristy4c08aed2011-07-01 19:47:50 +00004112 break;
4113 }
4114 }
4115 quantum_map=(QuantumType *) RelinquishMagickMemory(quantum_map);
4116 return(MagickTrue);
4117}
4118
4119/*
4120%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4121% %
4122% %
4123% %
cristybd5a96c2011-08-21 00:04:26 +00004124+ 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 %
4125% %
4126% %
4127% %
4128%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4129%
4130% InitializePixelChannelMap() defines the standard pixel component map.
4131%
4132% The format of the InitializePixelChannelMap() method is:
4133%
4134% void InitializePixelChannelMap(Image *image)
4135%
4136% A description of each parameter follows:
4137%
4138% o image: the image.
4139%
4140*/
cristy021216a2013-05-20 16:25:51 +00004141
4142static void LogPixelChannels(const Image *image)
4143{
4144 register ssize_t
4145 i;
4146
4147 (void) LogMagickEvent(PixelEvent,GetMagickModule(),"%s[%.20g]",
4148 image->filename,(double) image->number_channels);
4149 for (i=0; i < (ssize_t) image->number_channels; i++)
4150 {
4151 char
4152 traits[MaxTextExtent];
4153
4154 const char
4155 *name;
4156
4157 PixelChannel
4158 channel;
4159
4160 switch (GetPixelChannelChannel(image,i))
4161 {
4162 case RedPixelChannel:
4163 {
4164 name="red";
4165 if (image->colorspace == CMYKColorspace)
4166 name="cyan";
4167 if (image->colorspace == GRAYColorspace)
4168 name="gray";
4169 break;
4170 }
4171 case GreenPixelChannel:
4172 {
4173 name="green";
4174 if (image->colorspace == CMYKColorspace)
4175 name="magenta";
4176 break;
4177 }
4178 case BluePixelChannel:
4179 {
4180 name="blue";
4181 if (image->colorspace == CMYKColorspace)
4182 name="yellow";
4183 break;
4184 }
4185 case BlackPixelChannel:
4186 {
4187 name="black";
4188 if (image->storage_class == PseudoClass)
4189 name="index";
4190 break;
4191 }
4192 case IndexPixelChannel:
4193 {
4194 name="index";
4195 break;
4196 }
4197 case AlphaPixelChannel:
4198 {
4199 name="alpha";
4200 break;
4201 }
4202 case ReadMaskPixelChannel:
4203 {
cristy04817142013-05-20 17:14:03 +00004204 name="read-mask";
cristy021216a2013-05-20 16:25:51 +00004205 break;
4206 }
4207 case WriteMaskPixelChannel:
4208 {
cristy04817142013-05-20 17:14:03 +00004209 name="write-mask";
cristy021216a2013-05-20 16:25:51 +00004210 break;
4211 }
4212 case MetaPixelChannel:
4213 {
4214 name="meta";
4215 break;
4216 }
4217 default:
4218 name="undefined";
4219 }
4220 channel=GetPixelChannelChannel(image,i);
4221 *traits='\0';
4222 if ((GetPixelChannelTraits(image,channel) & UpdatePixelTrait) != 0)
4223 (void) ConcatenateMagickString(traits,"update,",MaxTextExtent);
4224 if ((GetPixelChannelTraits(image,channel) & BlendPixelTrait) != 0)
4225 (void) ConcatenateMagickString(traits,"blend,",MaxTextExtent);
4226 if ((GetPixelChannelTraits(image,channel) & CopyPixelTrait) != 0)
4227 (void) ConcatenateMagickString(traits,"copy,",MaxTextExtent);
4228 if (*traits == '\0')
4229 (void) ConcatenateMagickString(traits,"undefined,",MaxTextExtent);
4230 traits[strlen(traits)-1]='\0';
4231 (void) LogMagickEvent(PixelEvent,GetMagickModule()," %.20g: %s (%s)",
4232 (double) i,name,traits);
4233 }
4234}
4235
cristye2a912b2011-12-05 20:02:07 +00004236MagickExport void InitializePixelChannelMap(Image *image)
cristy77c30f52011-10-24 18:56:57 +00004237{
cristye2a912b2011-12-05 20:02:07 +00004238 PixelTrait
4239 trait;
4240
cristy77c30f52011-10-24 18:56:57 +00004241 register ssize_t
4242 i;
4243
cristyd26338f2011-12-14 02:39:30 +00004244 ssize_t
cristy77c30f52011-10-24 18:56:57 +00004245 n;
4246
4247 assert(image != (Image *) NULL);
4248 assert(image->signature == MagickSignature);
cristye2a912b2011-12-05 20:02:07 +00004249 (void) ResetMagickMemory(image->channel_map,0,MaxPixelChannels*
4250 sizeof(*image->channel_map));
4251 trait=UpdatePixelTrait;
cristy8a46d822012-08-28 23:32:39 +00004252 if (image->alpha_trait == BlendPixelTrait)
cristy61f18ad2011-12-08 21:12:37 +00004253 trait=(PixelTrait) (trait | BlendPixelTrait);
cristy77c30f52011-10-24 18:56:57 +00004254 n=0;
cristyc06c5802011-12-31 23:36:16 +00004255 if (image->colorspace == GRAYColorspace)
cristy77c30f52011-10-24 18:56:57 +00004256 {
cristycf1296e2012-08-26 23:40:49 +00004257 SetPixelChannelAttributes(image,BluePixelChannel,trait,n);
4258 SetPixelChannelAttributes(image,GreenPixelChannel,trait,n);
4259 SetPixelChannelAttributes(image,RedPixelChannel,trait,n++);
cristy3c316282011-12-15 15:43:24 +00004260 }
4261 else
4262 {
cristycf1296e2012-08-26 23:40:49 +00004263 SetPixelChannelAttributes(image,RedPixelChannel,trait,n++);
4264 SetPixelChannelAttributes(image,GreenPixelChannel,trait,n++);
4265 SetPixelChannelAttributes(image,BluePixelChannel,trait,n++);
cristy77c30f52011-10-24 18:56:57 +00004266 }
4267 if (image->colorspace == CMYKColorspace)
cristycf1296e2012-08-26 23:40:49 +00004268 SetPixelChannelAttributes(image,BlackPixelChannel,trait,n++);
cristy8a46d822012-08-28 23:32:39 +00004269 if (image->alpha_trait != UndefinedPixelTrait)
cristycf1296e2012-08-26 23:40:49 +00004270 SetPixelChannelAttributes(image,AlphaPixelChannel,CopyPixelTrait,n++);
cristye2a912b2011-12-05 20:02:07 +00004271 if (image->storage_class == PseudoClass)
cristycf1296e2012-08-26 23:40:49 +00004272 SetPixelChannelAttributes(image,IndexPixelChannel,CopyPixelTrait,n++);
cristy883fde12013-04-08 00:50:13 +00004273 if (image->read_mask != MagickFalse)
4274 SetPixelChannelAttributes(image,ReadMaskPixelChannel,CopyPixelTrait,n++);
4275 if (image->write_mask != MagickFalse)
4276 SetPixelChannelAttributes(image,WriteMaskPixelChannel,CopyPixelTrait,n++);
cristye2a912b2011-12-05 20:02:07 +00004277 assert((n+image->number_meta_channels) < MaxPixelChannels);
4278 for (i=0; i < (ssize_t) image->number_meta_channels; i++)
cristycf1296e2012-08-26 23:40:49 +00004279 SetPixelChannelAttributes(image,(PixelChannel) (MetaPixelChannel+i),
4280 CopyPixelTrait,n++);
cristyd26338f2011-12-14 02:39:30 +00004281 image->number_channels=(size_t) n;
cristy77c30f52011-10-24 18:56:57 +00004282 if (image->debug != MagickFalse)
4283 LogPixelChannels(image);
cristycf1296e2012-08-26 23:40:49 +00004284 (void) SetImageChannelMask(image,image->channel_mask);
cristy77c30f52011-10-24 18:56:57 +00004285}
cristybd5a96c2011-08-21 00:04:26 +00004286
4287/*
4288%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4289% %
4290% %
4291% %
cristya085a432011-07-30 01:39:32 +00004292% I n t e r p o l a t e P i x e l C h a n n e l %
4293% %
4294% %
4295% %
4296%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4297%
cristy884f6002011-07-31 00:51:45 +00004298% InterpolatePixelChannel() applies a pixel interpolation method between a
4299% floating point coordinate and the pixels surrounding that coordinate. No
4300% pixel area resampling, or scaling of the result is performed.
cristya085a432011-07-30 01:39:32 +00004301%
anthonycf4e33d2012-06-08 07:33:23 +00004302% Interpolation is restricted to just the specified channel.
4303%
cristya085a432011-07-30 01:39:32 +00004304% The format of the InterpolatePixelChannel method is:
4305%
4306% MagickBooleanType InterpolatePixelChannel(const Image *image,
cristy444eda62011-08-10 02:07:46 +00004307% const CacheView *image_view,const PixelChannel channel,
cristy5c4e2582011-09-11 19:21:03 +00004308% const PixelInterpolateMethod method,const double x,const double y,
cristya085a432011-07-30 01:39:32 +00004309% double *pixel,ExceptionInfo *exception)
4310%
4311% A description of each parameter follows:
4312%
4313% o image: the image.
4314%
4315% o image_view: the image view.
4316%
4317% o channel: the pixel channel to interpolate.
4318%
4319% o method: the pixel color interpolation method.
4320%
4321% o x,y: A double representing the current (x,y) position of the pixel.
4322%
4323% o pixel: return the interpolated pixel here.
4324%
4325% o exception: return any errors or warnings in this structure.
4326%
4327*/
cristy94ea1632011-07-30 20:40:25 +00004328
cristyb0a657e2012-08-29 00:45:37 +00004329static inline void CatromWeights(const double x,double (*weights)[4])
cristy884f6002011-07-31 00:51:45 +00004330{
cristya19f1d72012-08-07 18:24:38 +00004331 double
cristy884f6002011-07-31 00:51:45 +00004332 alpha,
nicolasd32d5e52012-06-12 15:34:10 +00004333 beta,
cristy884f6002011-07-31 00:51:45 +00004334 gamma;
4335
cristy5a5e4d92012-08-29 00:06:25 +00004336 /*
4337 Nicolas Robidoux' 10 flops (4* + 5- + 1+) refactoring of the computation
4338 of the standard four 1D Catmull-Rom weights. The sampling location is
4339 assumed between the second and third input pixel locations, and x is the
4340 position relative to the second input pixel location. Formulas originally
4341 derived for the VIPS (Virtual Image Processing System) library.
4342 */
cristya19f1d72012-08-07 18:24:38 +00004343 alpha=(double) 1.0-x;
4344 beta=(double) (-0.5)*x*alpha;
nicolasd32d5e52012-06-12 15:34:10 +00004345 (*weights)[0]=alpha*beta;
4346 (*weights)[3]=x*beta;
4347 /*
cristy5a5e4d92012-08-29 00:06:25 +00004348 The following computation of the inner weights from the outer ones work
4349 for all Keys cubics.
nicolasd32d5e52012-06-12 15:34:10 +00004350 */
4351 gamma=(*weights)[3]-(*weights)[0];
4352 (*weights)[1]=alpha-(*weights)[0]+gamma;
4353 (*weights)[2]=x-(*weights)[3]-gamma;
4354}
4355
cristyb0a657e2012-08-29 00:45:37 +00004356static inline void SplineWeights(const double x,double (*weights)[4])
nicolasd32d5e52012-06-12 15:34:10 +00004357{
cristy5a5e4d92012-08-29 00:06:25 +00004358 double
4359 alpha,
4360 beta;
4361
nicolasd32d5e52012-06-12 15:34:10 +00004362 /*
cristy58ee5012013-05-26 23:58:44 +00004363 Nicolas Robidoux' 12 flops (6* + 5- + 1+) refactoring of the computation
4364 of the standard four 1D cubic B-spline smoothing weights. The sampling
4365 location is assumed between the second and third input pixel locations,
4366 and x is the position relative to the second input pixel location.
nicolasd32d5e52012-06-12 15:34:10 +00004367 */
cristya19f1d72012-08-07 18:24:38 +00004368 alpha=(double) 1.0-x;
4369 (*weights)[3]=(double) (1.0/6.0)*x*x*x;
4370 (*weights)[0]=(double) (1.0/6.0)*alpha*alpha*alpha;
nicolasd32d5e52012-06-12 15:34:10 +00004371 beta=(*weights)[3]-(*weights)[0];
4372 (*weights)[1]=alpha-(*weights)[0]+beta;
4373 (*weights)[2]=x-(*weights)[3]-beta;
cristy884f6002011-07-31 00:51:45 +00004374}
4375
cristy94ea1632011-07-30 20:40:25 +00004376static inline double MeshInterpolate(const PointInfo *delta,const double p,
4377 const double x,const double y)
4378{
4379 return(delta->x*x+delta->y*y+(1.0-delta->x-delta->y)*p);
4380}
4381
anthonycf4e33d2012-06-08 07:33:23 +00004382/*
cristya19f1d72012-08-07 18:24:38 +00004383static inline ssize_t NearestNeighbor(const double x)
cristy884f6002011-07-31 00:51:45 +00004384{
4385 if (x >= 0.0)
4386 return((ssize_t) (x+0.5));
4387 return((ssize_t) (x-0.5));
4388}
anthonycf4e33d2012-06-08 07:33:23 +00004389*/
cristy884f6002011-07-31 00:51:45 +00004390
cristya085a432011-07-30 01:39:32 +00004391MagickExport MagickBooleanType InterpolatePixelChannel(const Image *image,
4392 const CacheView *image_view,const PixelChannel channel,
cristy5c4e2582011-09-11 19:21:03 +00004393 const PixelInterpolateMethod method,const double x,const double y,
cristya085a432011-07-30 01:39:32 +00004394 double *pixel,ExceptionInfo *exception)
4395{
cristya19f1d72012-08-07 18:24:38 +00004396 double
cristy94ea1632011-07-30 20:40:25 +00004397 alpha[16],
cristy884f6002011-07-31 00:51:45 +00004398 gamma,
4399 pixels[16];
cristy94ea1632011-07-30 20:40:25 +00004400
cristy58ee5012013-05-26 23:58:44 +00004401 MagickBooleanType
4402 status;
4403
4404 PixelInterpolateMethod
4405 interpolate;
4406
cristy94ea1632011-07-30 20:40:25 +00004407 PixelTrait
4408 traits;
4409
cristy94ea1632011-07-30 20:40:25 +00004410 register const Quantum
4411 *p;
4412
cristy50e64b82012-06-22 17:46:19 +00004413 register ssize_t
cristy94ea1632011-07-30 20:40:25 +00004414 i;
4415
cristya085a432011-07-30 01:39:32 +00004416 ssize_t
4417 x_offset,
4418 y_offset;
4419
4420 assert(image != (Image *) NULL);
4421 assert(image != (Image *) NULL);
4422 assert(image->signature == MagickSignature);
4423 assert(image_view != (CacheView *) NULL);
4424 status=MagickTrue;
cristy884f6002011-07-31 00:51:45 +00004425 *pixel=0.0;
cristycf1296e2012-08-26 23:40:49 +00004426 traits=GetPixelChannelTraits(image,channel);
cristya085a432011-07-30 01:39:32 +00004427 x_offset=(ssize_t) floor(x);
4428 y_offset=(ssize_t) floor(y);
anthonycf4e33d2012-06-08 07:33:23 +00004429 interpolate = method;
4430 if ( interpolate == UndefinedInterpolatePixel )
4431 interpolate = image->interpolate;
4432 switch (interpolate)
cristya085a432011-07-30 01:39:32 +00004433 {
cristy58ee5012013-05-26 23:58:44 +00004434 case AverageInterpolatePixel: /* nearest 4 neighbours */
4435 case Average9InterpolatePixel: /* nearest 9 neighbours */
4436 case Average16InterpolatePixel: /* nearest 16 neighbours */
cristy884f6002011-07-31 00:51:45 +00004437 {
cristyfb122372012-10-17 23:31:21 +00004438 ssize_t
4439 count;
anthonycf4e33d2012-06-08 07:33:23 +00004440
cristyfb122372012-10-17 23:31:21 +00004441 count=2; /* size of the area to average - default nearest 4 */
anthonycf4e33d2012-06-08 07:33:23 +00004442 if (interpolate == Average9InterpolatePixel)
4443 {
4444 count=3;
4445 x_offset=(ssize_t) (floor(x+0.5)-1);
4446 y_offset=(ssize_t) (floor(y+0.5)-1);
4447 }
cristyfb122372012-10-17 23:31:21 +00004448 else
4449 if (interpolate == Average16InterpolatePixel)
4450 {
4451 count=4;
4452 x_offset--;
4453 y_offset--;
4454 }
cristy021216a2013-05-20 16:25:51 +00004455 p=GetCacheViewVirtualPixels(image_view,x_offset,y_offset,(size_t) count,
4456 (size_t) count,exception);
cristy884f6002011-07-31 00:51:45 +00004457 if (p == (const Quantum *) NULL)
4458 {
4459 status=MagickFalse;
4460 break;
4461 }
cristy58ee5012013-05-26 23:58:44 +00004462 count*=count; /* Number of pixels to average */
cristy222b19c2011-08-04 01:35:11 +00004463 if ((traits & BlendPixelTrait) == 0)
cristy50e64b82012-06-22 17:46:19 +00004464 for (i=0; i < (ssize_t) count; i++)
cristy884f6002011-07-31 00:51:45 +00004465 {
4466 alpha[i]=1.0;
cristya19f1d72012-08-07 18:24:38 +00004467 pixels[i]=(double) p[i*GetPixelChannels(image)+channel];
cristy884f6002011-07-31 00:51:45 +00004468 }
4469 else
cristy50e64b82012-06-22 17:46:19 +00004470 for (i=0; i < (ssize_t) count; i++)
cristy884f6002011-07-31 00:51:45 +00004471 {
4472 alpha[i]=QuantumScale*GetPixelAlpha(image,p+i*
4473 GetPixelChannels(image));
4474 pixels[i]=alpha[i]*p[i*GetPixelChannels(image)+channel];
4475 }
cristy50e64b82012-06-22 17:46:19 +00004476 for (i=0; i < (ssize_t) count; i++)
cristy884f6002011-07-31 00:51:45 +00004477 {
cristy3e3ec3a2012-11-03 23:11:06 +00004478 gamma=PerceptibleReciprocal(alpha[i])/count;
anthonycf4e33d2012-06-08 07:33:23 +00004479 *pixel+=gamma*pixels[i];
cristy884f6002011-07-31 00:51:45 +00004480 }
4481 break;
4482 }
anthonycf4e33d2012-06-08 07:33:23 +00004483 case BilinearInterpolatePixel:
4484 default:
4485 {
4486 PointInfo
4487 delta,
4488 epsilon;
4489
4490 p=GetCacheViewVirtualPixels(image_view,x_offset,y_offset,2,2,exception);
4491 if (p == (const Quantum *) NULL)
4492 {
4493 status=MagickFalse;
4494 break;
4495 }
4496 if ((traits & BlendPixelTrait) == 0)
4497 for (i=0; i < 4; i++)
4498 {
4499 alpha[i]=1.0;
cristya19f1d72012-08-07 18:24:38 +00004500 pixels[i]=(double) p[i*GetPixelChannels(image)+channel];
anthonycf4e33d2012-06-08 07:33:23 +00004501 }
4502 else
4503 for (i=0; i < 4; i++)
4504 {
4505 alpha[i]=QuantumScale*GetPixelAlpha(image,p+i*
4506 GetPixelChannels(image));
4507 pixels[i]=alpha[i]*p[i*GetPixelChannels(image)+channel];
4508 }
4509 delta.x=x-x_offset;
4510 delta.y=y-y_offset;
4511 epsilon.x=1.0-delta.x;
4512 epsilon.y=1.0-delta.y;
4513 gamma=((epsilon.y*(epsilon.x*alpha[0]+delta.x*alpha[1])+delta.y*
4514 (epsilon.x*alpha[2]+delta.x*alpha[3])));
cristy3e3ec3a2012-11-03 23:11:06 +00004515 gamma=PerceptibleReciprocal(gamma);
anthonycf4e33d2012-06-08 07:33:23 +00004516 *pixel=gamma*(epsilon.y*(epsilon.x*pixels[0]+delta.x*pixels[1])+delta.y*
4517 (epsilon.x*pixels[2]+delta.x*pixels[3]));
4518 break;
4519 }
anthony5f78bca2012-10-05 06:51:00 +00004520 case BlendInterpolatePixel:
4521 {
4522 p=GetCacheViewVirtualPixels(image_view,x_offset,y_offset,2,2,exception);
4523 if (p == (const Quantum *) NULL)
4524 {
4525 status=MagickFalse;
4526 break;
4527 }
4528 if ((traits & BlendPixelTrait) == 0)
4529 for (i=0; i < 4; i++)
4530 {
4531 alpha[i]=1.0;
4532 pixels[i]=(MagickRealType) p[i*GetPixelChannels(image)+channel];
4533 }
4534 else
4535 for (i=0; i < 4; i++)
4536 {
4537 alpha[i]=QuantumScale*GetPixelAlpha(image,p+i*
4538 GetPixelChannels(image));
4539 pixels[i]=alpha[i]*p[i*GetPixelChannels(image)+channel];
4540 }
cristy58ee5012013-05-26 23:58:44 +00004541 gamma=1.0; /* number of pixels blended together (its variable) */
anthony5f78bca2012-10-05 06:51:00 +00004542 for (i=0; i <= 1L; i++) {
cristyfb122372012-10-17 23:31:21 +00004543 if ((y-y_offset) >= 0.75)
4544 {
4545 alpha[i]=alpha[i+2]; /* take right pixels */
4546 pixels[i]=pixels[i+2];
4547 }
4548 else
4549 if ((y-y_offset) > 0.25)
4550 {
4551 gamma=2.0; /* blend both pixels in row */
4552 alpha[i]+=alpha[i+2]; /* add up alpha weights */
4553 pixels[i]+=pixels[i+2];
4554 }
4555 }
4556 if ((x-x_offset) >= 0.75)
4557 {
4558 alpha[0]=alpha[1]; /* take bottom row blend */
4559 pixels[0]=pixels[1];
anthony5f78bca2012-10-05 06:51:00 +00004560 }
cristyfb122372012-10-17 23:31:21 +00004561 else
4562 if ((x-x_offset) > 0.25)
4563 {
4564 gamma*=2.0; /* blend both rows */
4565 alpha[0]+=alpha[1]; /* add up alpha weights */
4566 pixels[0]+=pixels[1];
4567 }
anthony5f78bca2012-10-05 06:51:00 +00004568 if (channel != AlphaPixelChannel)
cristy58ee5012013-05-26 23:58:44 +00004569 gamma=PerceptibleReciprocal(alpha[0]); /* (color) 1/alpha_weights */
anthony5f78bca2012-10-05 06:51:00 +00004570 else
cristy58ee5012013-05-26 23:58:44 +00004571 gamma=PerceptibleReciprocal(gamma); /* (alpha) 1/number_of_pixels */
anthony5f78bca2012-10-05 06:51:00 +00004572 *pixel=gamma*pixels[0];
4573 break;
4574 }
anthonycf4e33d2012-06-08 07:33:23 +00004575 case CatromInterpolatePixel:
cristy884f6002011-07-31 00:51:45 +00004576 {
cristya19f1d72012-08-07 18:24:38 +00004577 double
cristy380a11c2012-06-02 15:15:22 +00004578 cx[4],
nicolas6676f5a2012-06-12 16:01:15 +00004579 cy[4];
cristy884f6002011-07-31 00:51:45 +00004580
cristy884f6002011-07-31 00:51:45 +00004581 p=GetCacheViewVirtualPixels(image_view,x_offset-1,y_offset-1,4,4,
4582 exception);
4583 if (p == (const Quantum *) NULL)
4584 {
4585 status=MagickFalse;
4586 break;
4587 }
cristy222b19c2011-08-04 01:35:11 +00004588 if ((traits & BlendPixelTrait) == 0)
cristy884f6002011-07-31 00:51:45 +00004589 for (i=0; i < 16; i++)
4590 {
4591 alpha[i]=1.0;
cristya19f1d72012-08-07 18:24:38 +00004592 pixels[i]=(double) p[i*GetPixelChannels(image)+channel];
cristy884f6002011-07-31 00:51:45 +00004593 }
4594 else
4595 for (i=0; i < 16; i++)
4596 {
4597 alpha[i]=QuantumScale*GetPixelAlpha(image,p+i*
4598 GetPixelChannels(image));
4599 pixels[i]=alpha[i]*p[i*GetPixelChannels(image)+channel];
4600 }
cristya19f1d72012-08-07 18:24:38 +00004601 CatromWeights((double) (x-x_offset),&cx);
4602 CatromWeights((double) (y-y_offset),&cy);
4603 gamma=(channel == AlphaPixelChannel ? (double) 1.0 :
cristy3e3ec3a2012-11-03 23:11:06 +00004604 PerceptibleReciprocal(cy[0]*(cx[0]*alpha[0]+cx[1]*alpha[1]+cx[2]*
nicolasd32d5e52012-06-12 15:34:10 +00004605 alpha[2]+cx[3]*alpha[3])+cy[1]*(cx[0]*alpha[4]+cx[1]*alpha[5]+cx[2]*
4606 alpha[6]+cx[3]*alpha[7])+cy[2]*(cx[0]*alpha[8]+cx[1]*alpha[9]+cx[2]*
4607 alpha[10]+cx[3]*alpha[11])+cy[3]*(cx[0]*alpha[12]+cx[1]*alpha[13]+
4608 cx[2]*alpha[14]+cx[3]*alpha[15])));
cristy380a11c2012-06-02 15:15:22 +00004609 *pixel=gamma*(cy[0]*(cx[0]*pixels[0]+cx[1]*pixels[1]+cx[2]*pixels[2]+
nicolasd32d5e52012-06-12 15:34:10 +00004610 cx[3]*pixels[3])+cy[1]*(cx[0]*pixels[4]+cx[1]*pixels[5]+cx[2]*
4611 pixels[6]+cx[3]*pixels[7])+cy[2]*(cx[0]*pixels[8]+cx[1]*pixels[9]+
4612 cx[2]*pixels[10]+cx[3]*pixels[11])+cy[3]*(cx[0]*pixels[12]+cx[1]*
4613 pixels[13]+cx[2]*pixels[14]+cx[3]*pixels[15]));
cristy884f6002011-07-31 00:51:45 +00004614 break;
4615 }
cristy884f6002011-07-31 00:51:45 +00004616 case IntegerInterpolatePixel:
4617 {
4618 p=GetCacheViewVirtualPixels(image_view,x_offset,y_offset,1,1,exception);
4619 if (p == (const Quantum *) NULL)
4620 {
4621 status=MagickFalse;
4622 break;
4623 }
cristy0beccfa2011-09-25 20:47:53 +00004624 *pixel=(double) GetPixelChannel(image,channel,p);
cristy884f6002011-07-31 00:51:45 +00004625 break;
4626 }
anthonycf4e33d2012-06-08 07:33:23 +00004627 case NearestInterpolatePixel:
cristy884f6002011-07-31 00:51:45 +00004628 {
anthonycf4e33d2012-06-08 07:33:23 +00004629 x_offset=(ssize_t) floor(x+0.5);
4630 y_offset=(ssize_t) floor(y+0.5);
4631 p=GetCacheViewVirtualPixels(image_view,x_offset,y_offset,1,1,exception);
cristy884f6002011-07-31 00:51:45 +00004632 if (p == (const Quantum *) NULL)
4633 {
4634 status=MagickFalse;
4635 break;
4636 }
cristy0beccfa2011-09-25 20:47:53 +00004637 *pixel=(double) GetPixelChannel(image,channel,p);
cristy884f6002011-07-31 00:51:45 +00004638 break;
4639 }
4640 case MeshInterpolatePixel:
4641 {
4642 PointInfo
4643 delta,
cristy94ea1632011-07-30 20:40:25 +00004644 luminance;
4645
4646 p=GetCacheViewVirtualPixels(image_view,x_offset,y_offset,2,2,exception);
4647 if (p == (const Quantum *) NULL)
4648 {
4649 status=MagickFalse;
4650 break;
4651 }
cristy222b19c2011-08-04 01:35:11 +00004652 if ((traits & BlendPixelTrait) == 0)
cristy94ea1632011-07-30 20:40:25 +00004653 for (i=0; i < 4; i++)
4654 {
4655 alpha[i]=1.0;
cristya19f1d72012-08-07 18:24:38 +00004656 pixels[i]=(double) p[i*GetPixelChannels(image)+channel];
cristy94ea1632011-07-30 20:40:25 +00004657 }
4658 else
4659 for (i=0; i < 4; i++)
4660 {
4661 alpha[i]=QuantumScale*GetPixelAlpha(image,p+i*
4662 GetPixelChannels(image));
4663 pixels[i]=alpha[i]*p[i*GetPixelChannels(image)+channel];
4664 }
cristy884f6002011-07-31 00:51:45 +00004665 delta.x=x-x_offset;
4666 delta.y=y-y_offset;
cristyebfaacf2013-06-24 16:22:40 +00004667 luminance.x=GetPixelLuma(image,p)-(double)
4668 GetPixelLuma(image,p+3*GetPixelChannels(image));
4669 luminance.y=GetPixelLuma(image,p+GetPixelChannels(image))-(double)
4670 GetPixelLuma(image,p+2*GetPixelChannels(image));
cristy94ea1632011-07-30 20:40:25 +00004671 if (fabs(luminance.x) < fabs(luminance.y))
4672 {
4673 /*
4674 Diagonal 0-3 NW-SE.
4675 */
4676 if (delta.x <= delta.y)
4677 {
4678 /*
4679 Bottom-left triangle (pixel: 2, diagonal: 0-3).
4680 */
4681 delta.y=1.0-delta.y;
4682 gamma=MeshInterpolate(&delta,alpha[2],alpha[3],alpha[0]);
cristy3e3ec3a2012-11-03 23:11:06 +00004683 gamma=PerceptibleReciprocal(gamma);
cristy94ea1632011-07-30 20:40:25 +00004684 *pixel=gamma*MeshInterpolate(&delta,pixels[2],pixels[3],
4685 pixels[0]);
4686 }
4687 else
4688 {
4689 /*
4690 Top-right triangle (pixel: 1, diagonal: 0-3).
4691 */
4692 delta.x=1.0-delta.x;
4693 gamma=MeshInterpolate(&delta,alpha[1],alpha[0],alpha[3]);
cristy3e3ec3a2012-11-03 23:11:06 +00004694 gamma=PerceptibleReciprocal(gamma);
cristy94ea1632011-07-30 20:40:25 +00004695 *pixel=gamma*MeshInterpolate(&delta,pixels[1],pixels[0],
4696 pixels[3]);
4697 }
4698 }
4699 else
4700 {
4701 /*
4702 Diagonal 1-2 NE-SW.
4703 */
4704 if (delta.x <= (1.0-delta.y))
4705 {
4706 /*
4707 Top-left triangle (pixel: 0, diagonal: 1-2).
4708 */
4709 gamma=MeshInterpolate(&delta,alpha[0],alpha[1],alpha[2]);
cristy3e3ec3a2012-11-03 23:11:06 +00004710 gamma=PerceptibleReciprocal(gamma);
cristy94ea1632011-07-30 20:40:25 +00004711 *pixel=gamma*MeshInterpolate(&delta,pixels[0],pixels[1],
4712 pixels[2]);
4713 }
4714 else
4715 {
4716 /*
4717 Bottom-right triangle (pixel: 3, diagonal: 1-2).
4718 */
4719 delta.x=1.0-delta.x;
4720 delta.y=1.0-delta.y;
4721 gamma=MeshInterpolate(&delta,alpha[3],alpha[2],alpha[1]);
cristy3e3ec3a2012-11-03 23:11:06 +00004722 gamma=PerceptibleReciprocal(gamma);
cristy94ea1632011-07-30 20:40:25 +00004723 *pixel=gamma*MeshInterpolate(&delta,pixels[3],pixels[2],
4724 pixels[1]);
4725 }
4726 }
cristya085a432011-07-30 01:39:32 +00004727 break;
4728 }
cristy884f6002011-07-31 00:51:45 +00004729 case SplineInterpolatePixel:
4730 {
cristya19f1d72012-08-07 18:24:38 +00004731 double
nicolasd32d5e52012-06-12 15:34:10 +00004732 cx[4],
nicolas6676f5a2012-06-12 16:01:15 +00004733 cy[4];
cristy884f6002011-07-31 00:51:45 +00004734
4735 p=GetCacheViewVirtualPixels(image_view,x_offset-1,y_offset-1,4,4,
4736 exception);
4737 if (p == (const Quantum *) NULL)
4738 {
4739 status=MagickFalse;
4740 break;
4741 }
cristy222b19c2011-08-04 01:35:11 +00004742 if ((traits & BlendPixelTrait) == 0)
cristy884f6002011-07-31 00:51:45 +00004743 for (i=0; i < 16; i++)
4744 {
4745 alpha[i]=1.0;
cristya19f1d72012-08-07 18:24:38 +00004746 pixels[i]=(double) p[i*GetPixelChannels(image)+channel];
cristy884f6002011-07-31 00:51:45 +00004747 }
4748 else
4749 for (i=0; i < 16; i++)
4750 {
4751 alpha[i]=QuantumScale*GetPixelAlpha(image,p+i*
4752 GetPixelChannels(image));
4753 pixels[i]=alpha[i]*p[i*GetPixelChannels(image)+channel];
4754 }
cristya19f1d72012-08-07 18:24:38 +00004755 SplineWeights((double) (x-x_offset),&cx);
4756 SplineWeights((double) (y-y_offset),&cy);
4757 gamma=(channel == AlphaPixelChannel ? (double) 1.0 :
cristy3e3ec3a2012-11-03 23:11:06 +00004758 PerceptibleReciprocal(cy[0]*(cx[0]*alpha[0]+cx[1]*alpha[1]+cx[2]*
nicolasd32d5e52012-06-12 15:34:10 +00004759 alpha[2]+cx[3]*alpha[3])+cy[1]*(cx[0]*alpha[4]+cx[1]*alpha[5]+cx[2]*
4760 alpha[6]+cx[3]*alpha[7])+cy[2]*(cx[0]*alpha[8]+cx[1]*alpha[9]+cx[2]*
4761 alpha[10]+cx[3]*alpha[11])+cy[3]*(cx[0]*alpha[12]+cx[1]*alpha[13]+
4762 cx[2]*alpha[14]+cx[3]*alpha[15])));
4763 *pixel=gamma*(cy[0]*(cx[0]*pixels[0]+cx[1]*pixels[1]+cx[2]*pixels[2]+
4764 cx[3]*pixels[3])+cy[1]*(cx[0]*pixels[4]+cx[1]*pixels[5]+cx[2]*
4765 pixels[6]+cx[3]*pixels[7])+cy[2]*(cx[0]*pixels[8]+cx[1]*pixels[9]+
4766 cx[2]*pixels[10]+cx[3]*pixels[11])+cy[3]*(cx[0]*pixels[12]+cx[1]*
4767 pixels[13]+cx[2]*pixels[14]+cx[3]*pixels[15]));
cristy884f6002011-07-31 00:51:45 +00004768 break;
4769 }
cristya085a432011-07-30 01:39:32 +00004770 }
4771 return(status);
4772}
4773
4774/*
4775%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4776% %
4777% %
4778% %
cristy5c4e2582011-09-11 19:21:03 +00004779% I n t e r p o l a t e P i x e l C h a n n e l s %
4780% %
4781% %
4782% %
4783%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4784%
4785% InterpolatePixelChannels() applies a pixel interpolation method between a
4786% floating point coordinate and the pixels surrounding that coordinate. No
4787% pixel area resampling, or scaling of the result is performed.
4788%
anthonycf4e33d2012-06-08 07:33:23 +00004789% Interpolation is restricted to just the current channel setting of the
4790% destination image into which the color is to be stored
4791%
cristy5c4e2582011-09-11 19:21:03 +00004792% The format of the InterpolatePixelChannels method is:
4793%
4794% MagickBooleanType InterpolatePixelChannels(const Image *source,
4795% const CacheView *source_view,const Image *destination,
4796% const PixelInterpolateMethod method,const double x,const double y,
4797% Quantum *pixel,ExceptionInfo *exception)
4798%
4799% A description of each parameter follows:
4800%
4801% o source: the source.
4802%
4803% o source_view: the source view.
4804%
anthonycf4e33d2012-06-08 07:33:23 +00004805% o destination: the destination image, for the interpolated color
cristy5c4e2582011-09-11 19:21:03 +00004806%
4807% o method: the pixel color interpolation method.
4808%
4809% o x,y: A double representing the current (x,y) position of the pixel.
4810%
4811% o pixel: return the interpolated pixel here.
4812%
4813% o exception: return any errors or warnings in this structure.
4814%
4815*/
4816MagickExport MagickBooleanType InterpolatePixelChannels(const Image *source,
4817 const CacheView *source_view,const Image *destination,
4818 const PixelInterpolateMethod method,const double x,const double y,
4819 Quantum *pixel,ExceptionInfo *exception)
4820{
4821 MagickBooleanType
4822 status;
4823
cristya19f1d72012-08-07 18:24:38 +00004824 double
cristy5c4e2582011-09-11 19:21:03 +00004825 alpha[16],
4826 gamma,
4827 pixels[16];
4828
cristy5c4e2582011-09-11 19:21:03 +00004829 register const Quantum
4830 *p;
4831
cristy50e64b82012-06-22 17:46:19 +00004832 register ssize_t
cristy5c4e2582011-09-11 19:21:03 +00004833 i;
4834
4835 ssize_t
4836 x_offset,
4837 y_offset;
4838
anthonycf4e33d2012-06-08 07:33:23 +00004839 PixelInterpolateMethod
4840 interpolate;
4841
cristy5c4e2582011-09-11 19:21:03 +00004842 assert(source != (Image *) NULL);
4843 assert(source != (Image *) NULL);
4844 assert(source->signature == MagickSignature);
4845 assert(source_view != (CacheView *) NULL);
4846 status=MagickTrue;
4847 x_offset=(ssize_t) floor(x);
4848 y_offset=(ssize_t) floor(y);
anthonycf4e33d2012-06-08 07:33:23 +00004849 interpolate = method;
4850 if ( interpolate == UndefinedInterpolatePixel )
4851 interpolate = source->interpolate;
4852 switch (interpolate)
cristy5c4e2582011-09-11 19:21:03 +00004853 {
cristy58ee5012013-05-26 23:58:44 +00004854 case AverageInterpolatePixel: /* nearest 4 neighbours */
4855 case Average9InterpolatePixel: /* nearest 9 neighbours */
4856 case Average16InterpolatePixel: /* nearest 16 neighbours */
cristy5c4e2582011-09-11 19:21:03 +00004857 {
cristyfb122372012-10-17 23:31:21 +00004858 ssize_t
4859 count;
anthonycf4e33d2012-06-08 07:33:23 +00004860
cristyfb122372012-10-17 23:31:21 +00004861 count=2; /* size of the area to average - default nearest 4 */
anthonycf4e33d2012-06-08 07:33:23 +00004862 if (interpolate == Average9InterpolatePixel)
4863 {
4864 count=3;
4865 x_offset=(ssize_t) (floor(x+0.5)-1);
4866 y_offset=(ssize_t) (floor(y+0.5)-1);
4867 }
cristyfb122372012-10-17 23:31:21 +00004868 else
4869 if (interpolate == Average16InterpolatePixel)
4870 {
4871 count=4;
4872 x_offset--;
4873 y_offset--;
4874 }
cristy1b72b812013-04-19 00:57:44 +00004875 p=GetCacheViewVirtualPixels(source_view,x_offset,y_offset,(size_t) count,
4876 (size_t) count,exception);
cristy5c4e2582011-09-11 19:21:03 +00004877 if (p == (const Quantum *) NULL)
4878 {
4879 status=MagickFalse;
4880 break;
4881 }
cristy58ee5012013-05-26 23:58:44 +00004882 count*=count; /* Number of pixels to average */
cristy50e64b82012-06-22 17:46:19 +00004883 for (i=0; i < (ssize_t) GetPixelChannels(source); i++)
cristy5c4e2582011-09-11 19:21:03 +00004884 {
4885 double
4886 sum;
4887
cristy50e64b82012-06-22 17:46:19 +00004888 register ssize_t
cristy5c4e2582011-09-11 19:21:03 +00004889 j;
4890
cristy5a23c552013-02-13 14:34:28 +00004891 PixelChannel channel=GetPixelChannelChannel(source,i);
4892 PixelTrait traits=GetPixelChannelTraits(source,channel);
4893 PixelTrait destination_traits=GetPixelChannelTraits(destination,
4894 channel);
cristy5c4e2582011-09-11 19:21:03 +00004895 if ((traits == UndefinedPixelTrait) ||
4896 (destination_traits == UndefinedPixelTrait))
4897 continue;
cristy50e64b82012-06-22 17:46:19 +00004898 for (j=0; j < (ssize_t) count; j++)
cristya19f1d72012-08-07 18:24:38 +00004899 pixels[j]=(double) p[j*GetPixelChannels(source)+i];
cristy4a7ae692011-12-14 12:24:11 +00004900 sum=0.0;
cristy5c4e2582011-09-11 19:21:03 +00004901 if ((traits & BlendPixelTrait) == 0)
4902 {
cristy50e64b82012-06-22 17:46:19 +00004903 for (j=0; j < (ssize_t) count; j++)
anthonycf4e33d2012-06-08 07:33:23 +00004904 sum+=pixels[j];
4905 sum/=count;
cristy4a7ae692011-12-14 12:24:11 +00004906 SetPixelChannel(destination,channel,ClampToQuantum(sum),pixel);
cristy5c4e2582011-09-11 19:21:03 +00004907 continue;
4908 }
cristy50e64b82012-06-22 17:46:19 +00004909 for (j=0; j < (ssize_t) count; j++)
cristy5c4e2582011-09-11 19:21:03 +00004910 {
4911 alpha[j]=QuantumScale*GetPixelAlpha(source,p+j*
4912 GetPixelChannels(source));
4913 pixels[j]*=alpha[j];
cristy3e3ec3a2012-11-03 23:11:06 +00004914 gamma=PerceptibleReciprocal(alpha[j]);
anthonycf4e33d2012-06-08 07:33:23 +00004915 sum+=gamma*pixels[j];
cristy5c4e2582011-09-11 19:21:03 +00004916 }
anthonycf4e33d2012-06-08 07:33:23 +00004917 sum/=count;
cristy4a7ae692011-12-14 12:24:11 +00004918 SetPixelChannel(destination,channel,ClampToQuantum(sum),pixel);
cristy5c4e2582011-09-11 19:21:03 +00004919 }
4920 break;
4921 }
anthonycf4e33d2012-06-08 07:33:23 +00004922 case BilinearInterpolatePixel:
4923 default:
4924 {
4925 p=GetCacheViewVirtualPixels(source_view,x_offset,y_offset,2,2,exception);
4926 if (p == (const Quantum *) NULL)
4927 {
4928 status=MagickFalse;
4929 break;
4930 }
cristy50e64b82012-06-22 17:46:19 +00004931 for (i=0; i < (ssize_t) GetPixelChannels(source); i++)
anthonycf4e33d2012-06-08 07:33:23 +00004932 {
4933 PointInfo
4934 delta,
4935 epsilon;
4936
cristy5a23c552013-02-13 14:34:28 +00004937 PixelChannel channel=GetPixelChannelChannel(source,i);
4938 PixelTrait traits=GetPixelChannelTraits(source,channel);
4939 PixelTrait destination_traits=GetPixelChannelTraits(destination,
4940 channel);
anthonycf4e33d2012-06-08 07:33:23 +00004941 if ((traits == UndefinedPixelTrait) ||
4942 (destination_traits == UndefinedPixelTrait))
4943 continue;
4944 delta.x=x-x_offset;
4945 delta.y=y-y_offset;
4946 epsilon.x=1.0-delta.x;
4947 epsilon.y=1.0-delta.y;
cristya19f1d72012-08-07 18:24:38 +00004948 pixels[0]=(double) p[i];
4949 pixels[1]=(double) p[GetPixelChannels(source)+i];
4950 pixels[2]=(double) p[2*GetPixelChannels(source)+i];
4951 pixels[3]=(double) p[3*GetPixelChannels(source)+i];
anthonycf4e33d2012-06-08 07:33:23 +00004952 if ((traits & BlendPixelTrait) == 0)
4953 {
4954 gamma=((epsilon.y*(epsilon.x+delta.x)+delta.y*(epsilon.x+delta.x)));
cristy3e3ec3a2012-11-03 23:11:06 +00004955 gamma=PerceptibleReciprocal(gamma);
anthonycf4e33d2012-06-08 07:33:23 +00004956 SetPixelChannel(destination,channel,ClampToQuantum(gamma*(epsilon.y*
4957 (epsilon.x*pixels[0]+delta.x*pixels[1])+delta.y*(epsilon.x*
4958 pixels[2]+delta.x*pixels[3]))),pixel);
4959 continue;
4960 }
4961 alpha[0]=QuantumScale*GetPixelAlpha(source,p);
4962 alpha[1]=QuantumScale*GetPixelAlpha(source,p+GetPixelChannels(source));
4963 alpha[2]=QuantumScale*GetPixelAlpha(source,p+2*
4964 GetPixelChannels(source));
4965 alpha[3]=QuantumScale*GetPixelAlpha(source,p+3*
4966 GetPixelChannels(source));
4967 pixels[0]*=alpha[0];
4968 pixels[1]*=alpha[1];
4969 pixels[2]*=alpha[2];
4970 pixels[3]*=alpha[3];
4971 gamma=((epsilon.y*(epsilon.x*alpha[0]+delta.x*alpha[1])+delta.y*
4972 (epsilon.x*alpha[2]+delta.x*alpha[3])));
cristy3e3ec3a2012-11-03 23:11:06 +00004973 gamma=PerceptibleReciprocal(gamma);
anthonycf4e33d2012-06-08 07:33:23 +00004974 SetPixelChannel(destination,channel,ClampToQuantum(gamma*(epsilon.y*
4975 (epsilon.x*pixels[0]+delta.x*pixels[1])+delta.y*(epsilon.x*pixels[2]+
4976 delta.x*pixels[3]))),pixel);
4977 }
4978 break;
4979 }
anthony5f78bca2012-10-05 06:51:00 +00004980 case BlendInterpolatePixel:
4981 {
4982 p=GetCacheViewVirtualPixels(source_view,x_offset,y_offset,2,2,exception);
4983 if (p == (const Quantum *) NULL)
4984 {
4985 status=MagickFalse;
4986 break;
4987 }
4988 for (i=0; i < (ssize_t) GetPixelChannels(source); i++)
4989 {
4990 register ssize_t
4991 j;
4992
cristy5a23c552013-02-13 14:34:28 +00004993 PixelChannel channel=GetPixelChannelChannel(source,i);
4994 PixelTrait traits=GetPixelChannelTraits(source,channel);
4995 PixelTrait destination_traits=GetPixelChannelTraits(destination,
4996 channel);
anthony5f78bca2012-10-05 06:51:00 +00004997 if ((traits == UndefinedPixelTrait) ||
4998 (destination_traits == UndefinedPixelTrait))
4999 continue;
5000 if ((traits & BlendPixelTrait) == 0)
5001 for (j=0; j < 4; j++)
5002 {
5003 alpha[j]=1.0;
5004 pixels[j]=(MagickRealType) p[j*GetPixelChannels(source)+channel];
5005 }
5006 else
5007 for (j=0; j < 4; j++)
5008 {
5009 alpha[j]=QuantumScale*GetPixelAlpha(source,p+j*
5010 GetPixelChannels(source));
5011 pixels[j]=alpha[j]*p[j*GetPixelChannels(source)+channel];
5012 }
cristyfb122372012-10-17 23:31:21 +00005013 gamma=1.0; /* number of pixels blended together (its variable) */
5014 for (j=0; j <= 1L; j++)
5015 {
5016 if ((y-y_offset) >= 0.75)
5017 {
5018 alpha[j]=alpha[j+2]; /* take right pixels */
5019 pixels[j]=pixels[j+2];
5020 }
5021 else
5022 if ((y-y_offset) > 0.25)
5023 {
cristy58ee5012013-05-26 23:58:44 +00005024 gamma=2.0; /* blend both pixels in row */
cristyfb122372012-10-17 23:31:21 +00005025 alpha[j]+=alpha[j+2]; /* add up alpha weights */
5026 pixels[j]+=pixels[j+2];
5027 }
5028 }
5029 if ((x-x_offset) >= 0.75)
5030 {
5031 alpha[0]=alpha[1]; /* take bottom row blend */
5032 pixels[0]=pixels[1];
anthony5f78bca2012-10-05 06:51:00 +00005033 }
cristyfb122372012-10-17 23:31:21 +00005034 else
5035 if ((x-x_offset) > 0.25)
5036 {
5037 gamma*=2.0; /* blend both rows */
5038 alpha[0]+=alpha[1]; /* add up alpha weights */
5039 pixels[0]+=pixels[1];
5040 }
anthony5f78bca2012-10-05 06:51:00 +00005041 if ((traits & BlendPixelTrait) == 0)
cristy58ee5012013-05-26 23:58:44 +00005042 gamma=PerceptibleReciprocal(alpha[0]); /* (color) 1/alpha_weights */
anthony5f78bca2012-10-05 06:51:00 +00005043 else
cristy58ee5012013-05-26 23:58:44 +00005044 gamma=PerceptibleReciprocal(gamma); /* (alpha) 1/number_of_pixels */
anthony5f78bca2012-10-05 06:51:00 +00005045 SetPixelChannel(destination,channel,ClampToQuantum(gamma*pixels[0]),
cristyfb122372012-10-17 23:31:21 +00005046 pixel);
anthony5f78bca2012-10-05 06:51:00 +00005047 }
5048 break;
5049 }
anthonycf4e33d2012-06-08 07:33:23 +00005050 case CatromInterpolatePixel:
cristy5c4e2582011-09-11 19:21:03 +00005051 {
cristya19f1d72012-08-07 18:24:38 +00005052 double
cristy380a11c2012-06-02 15:15:22 +00005053 cx[4],
5054 cy[4];
cristy5c4e2582011-09-11 19:21:03 +00005055
cristy5c4e2582011-09-11 19:21:03 +00005056 p=GetCacheViewVirtualPixels(source_view,x_offset-1,y_offset-1,4,4,
5057 exception);
5058 if (p == (const Quantum *) NULL)
5059 {
5060 status=MagickFalse;
5061 break;
5062 }
cristy50e64b82012-06-22 17:46:19 +00005063 for (i=0; i < (ssize_t) GetPixelChannels(source); i++)
cristy5c4e2582011-09-11 19:21:03 +00005064 {
5065 register ssize_t
5066 j;
5067
cristy5a23c552013-02-13 14:34:28 +00005068 PixelChannel channel=GetPixelChannelChannel(source,i);
5069 PixelTrait traits=GetPixelChannelTraits(source,channel);
5070 PixelTrait destination_traits=GetPixelChannelTraits(destination,
5071 channel);
cristy5c4e2582011-09-11 19:21:03 +00005072 if ((traits == UndefinedPixelTrait) ||
5073 (destination_traits == UndefinedPixelTrait))
5074 continue;
5075 if ((traits & BlendPixelTrait) == 0)
5076 for (j=0; j < 16; j++)
5077 {
5078 alpha[j]=1.0;
cristya19f1d72012-08-07 18:24:38 +00005079 pixels[j]=(double) p[j*GetPixelChannels(source)+i];
cristy5c4e2582011-09-11 19:21:03 +00005080 }
5081 else
5082 for (j=0; j < 16; j++)
5083 {
5084 alpha[j]=QuantumScale*GetPixelAlpha(source,p+j*
5085 GetPixelChannels(source));
5086 pixels[j]=alpha[j]*p[j*GetPixelChannels(source)+i];
5087 }
cristya19f1d72012-08-07 18:24:38 +00005088 CatromWeights((double) (x-x_offset),&cx);
5089 CatromWeights((double) (y-y_offset),&cy);
5090 gamma=((traits & BlendPixelTrait) ? (double) (1.0) :
cristy3e3ec3a2012-11-03 23:11:06 +00005091 PerceptibleReciprocal(cy[0]*(cx[0]*alpha[0]+cx[1]*alpha[1]+cx[2]*
nicolasd32d5e52012-06-12 15:34:10 +00005092 alpha[2]+cx[3]*alpha[3])+cy[1]*(cx[0]*alpha[4]+cx[1]*alpha[5]+cx[2]*
5093 alpha[6]+cx[3]*alpha[7])+cy[2]*(cx[0]*alpha[8]+cx[1]*alpha[9]+cx[2]*
5094 alpha[10]+cx[3]*alpha[11])+cy[3]*(cx[0]*alpha[12]+cx[1]*alpha[13]+
5095 cx[2]*alpha[14]+cx[3]*alpha[15])));
cristy380a11c2012-06-02 15:15:22 +00005096 SetPixelChannel(destination,channel,ClampToQuantum(gamma*(cy[0]*(cx[0]*
5097 pixels[0]+cx[1]*pixels[1]+cx[2]*pixels[2]+cx[3]*pixels[3])+cy[1]*
5098 (cx[0]*pixels[4]+cx[1]*pixels[5]+cx[2]*pixels[6]+cx[3]*pixels[7])+
5099 cy[2]*(cx[0]*pixels[8]+cx[1]*pixels[9]+cx[2]*pixels[10]+cx[3]*
nicolasd32d5e52012-06-12 15:34:10 +00005100 pixels[11])+cy[3]*(cx[0]*pixels[12]+cx[1]*pixels[13]+cx[2]*
5101 pixels[14]+cx[3]*pixels[15]))),pixel);
cristy5c4e2582011-09-11 19:21:03 +00005102 }
5103 break;
5104 }
cristy5c4e2582011-09-11 19:21:03 +00005105 case IntegerInterpolatePixel:
5106 {
5107 p=GetCacheViewVirtualPixels(source_view,x_offset,y_offset,1,1,exception);
5108 if (p == (const Quantum *) NULL)
5109 {
5110 status=MagickFalse;
5111 break;
5112 }
cristy50e64b82012-06-22 17:46:19 +00005113 for (i=0; i < (ssize_t) GetPixelChannels(source); i++)
cristy5c4e2582011-09-11 19:21:03 +00005114 {
cristy5a23c552013-02-13 14:34:28 +00005115 PixelChannel channel=GetPixelChannelChannel(source,i);
5116 PixelTrait traits=GetPixelChannelTraits(source,channel);
5117 PixelTrait destination_traits=GetPixelChannelTraits(destination,
5118 channel);
cristy5c4e2582011-09-11 19:21:03 +00005119 if ((traits == UndefinedPixelTrait) ||
5120 (destination_traits == UndefinedPixelTrait))
5121 continue;
cristy4a7ae692011-12-14 12:24:11 +00005122 SetPixelChannel(destination,channel,p[i],pixel);
cristy5c4e2582011-09-11 19:21:03 +00005123 }
5124 break;
5125 }
anthonycf4e33d2012-06-08 07:33:23 +00005126 case NearestInterpolatePixel:
cristy5c4e2582011-09-11 19:21:03 +00005127 {
anthonycf4e33d2012-06-08 07:33:23 +00005128 x_offset=(ssize_t) floor(x+0.5);
5129 y_offset=(ssize_t) floor(y+0.5);
5130 p=GetCacheViewVirtualPixels(source_view,x_offset,y_offset,1,1,exception);
cristy5c4e2582011-09-11 19:21:03 +00005131 if (p == (const Quantum *) NULL)
5132 {
5133 status=MagickFalse;
5134 break;
5135 }
cristy50e64b82012-06-22 17:46:19 +00005136 for (i=0; i < (ssize_t) GetPixelChannels(source); i++)
cristy5c4e2582011-09-11 19:21:03 +00005137 {
cristy5a23c552013-02-13 14:34:28 +00005138 PixelChannel channel=GetPixelChannelChannel(source,i);
5139 PixelTrait traits=GetPixelChannelTraits(source,channel);
5140 PixelTrait destination_traits=GetPixelChannelTraits(destination,
5141 channel);
cristy5c4e2582011-09-11 19:21:03 +00005142 if ((traits == UndefinedPixelTrait) ||
5143 (destination_traits == UndefinedPixelTrait))
5144 continue;
cristy4a7ae692011-12-14 12:24:11 +00005145 SetPixelChannel(destination,channel,p[i],pixel);
cristy5c4e2582011-09-11 19:21:03 +00005146 }
5147 break;
5148 }
5149 case MeshInterpolatePixel:
5150 {
5151 p=GetCacheViewVirtualPixels(source_view,x_offset,y_offset,2,2,exception);
5152 if (p == (const Quantum *) NULL)
5153 {
5154 status=MagickFalse;
5155 break;
5156 }
cristy50e64b82012-06-22 17:46:19 +00005157 for (i=0; i < (ssize_t) GetPixelChannels(source); i++)
cristy5c4e2582011-09-11 19:21:03 +00005158 {
5159 PointInfo
5160 delta,
5161 luminance;
5162
cristy5a23c552013-02-13 14:34:28 +00005163 PixelChannel channel=GetPixelChannelChannel(source,i);
5164 PixelTrait traits=GetPixelChannelTraits(source,channel);
5165 PixelTrait destination_traits=GetPixelChannelTraits(destination,
5166 channel);
cristy5c4e2582011-09-11 19:21:03 +00005167 if ((traits == UndefinedPixelTrait) ||
5168 (destination_traits == UndefinedPixelTrait))
5169 continue;
cristya19f1d72012-08-07 18:24:38 +00005170 pixels[0]=(double) p[i];
5171 pixels[1]=(double) p[GetPixelChannels(source)+i];
5172 pixels[2]=(double) p[2*GetPixelChannels(source)+i];
5173 pixels[3]=(double) p[3*GetPixelChannels(source)+i];
cristy1861c902011-12-14 02:30:00 +00005174 if ((traits & BlendPixelTrait) == 0)
5175 {
5176 alpha[0]=1.0;
5177 alpha[1]=1.0;
5178 alpha[2]=1.0;
5179 alpha[3]=1.0;
5180 }
5181 else
5182 {
5183 alpha[0]=QuantumScale*GetPixelAlpha(source,p);
5184 alpha[1]=QuantumScale*GetPixelAlpha(source,p+
5185 GetPixelChannels(source));
5186 alpha[2]=QuantumScale*GetPixelAlpha(source,p+2*
5187 GetPixelChannels(source));
5188 alpha[3]=QuantumScale*GetPixelAlpha(source,p+3*
5189 GetPixelChannels(source));
5190 }
5191 delta.x=x-x_offset;
5192 delta.y=y-y_offset;
cristyebfaacf2013-06-24 16:22:40 +00005193 luminance.x=fabs((double) (GetPixelLuma(source,p)-
5194 GetPixelLuma(source,p+3*GetPixelChannels(source))));
5195 luminance.y=fabs((double) (GetPixelLuma(source,p+
5196 GetPixelChannels(source))-GetPixelLuma(source,p+2*
cristyfb122372012-10-17 23:31:21 +00005197 GetPixelChannels(source))));
anthonycf4e33d2012-06-08 07:33:23 +00005198 if (luminance.x < luminance.y)
cristy1861c902011-12-14 02:30:00 +00005199 {
5200 /*
5201 Diagonal 0-3 NW-SE.
5202 */
5203 if (delta.x <= delta.y)
5204 {
5205 /*
5206 Bottom-left triangle (pixel: 2, diagonal: 0-3).
5207 */
5208 delta.y=1.0-delta.y;
5209 gamma=MeshInterpolate(&delta,alpha[2],alpha[3],alpha[0]);
cristy3e3ec3a2012-11-03 23:11:06 +00005210 gamma=PerceptibleReciprocal(gamma);
cristy4a7ae692011-12-14 12:24:11 +00005211 SetPixelChannel(destination,channel,ClampToQuantum(gamma*
5212 MeshInterpolate(&delta,pixels[2],pixels[3],pixels[0])),pixel);
cristy1861c902011-12-14 02:30:00 +00005213 }
5214 else
5215 {
5216 /*
5217 Top-right triangle (pixel: 1, diagonal: 0-3).
5218 */
5219 delta.x=1.0-delta.x;
5220 gamma=MeshInterpolate(&delta,alpha[1],alpha[0],alpha[3]);
cristy3e3ec3a2012-11-03 23:11:06 +00005221 gamma=PerceptibleReciprocal(gamma);
cristy4a7ae692011-12-14 12:24:11 +00005222 SetPixelChannel(destination,channel,ClampToQuantum(gamma*
5223 MeshInterpolate(&delta,pixels[1],pixels[0],pixels[3])),pixel);
cristy1861c902011-12-14 02:30:00 +00005224 }
5225 }
5226 else
5227 {
5228 /*
5229 Diagonal 1-2 NE-SW.
5230 */
5231 if (delta.x <= (1.0-delta.y))
5232 {
5233 /*
5234 Top-left triangle (pixel: 0, diagonal: 1-2).
5235 */
5236 gamma=MeshInterpolate(&delta,alpha[0],alpha[1],alpha[2]);
cristy3e3ec3a2012-11-03 23:11:06 +00005237 gamma=PerceptibleReciprocal(gamma);
cristy4a7ae692011-12-14 12:24:11 +00005238 SetPixelChannel(destination,channel,ClampToQuantum(gamma*
5239 MeshInterpolate(&delta,pixels[0],pixels[1],pixels[2])),pixel);
cristy1861c902011-12-14 02:30:00 +00005240 }
5241 else
5242 {
5243 /*
5244 Bottom-right triangle (pixel: 3, diagonal: 1-2).
5245 */
5246 delta.x=1.0-delta.x;
5247 delta.y=1.0-delta.y;
5248 gamma=MeshInterpolate(&delta,alpha[3],alpha[2],alpha[1]);
cristy3e3ec3a2012-11-03 23:11:06 +00005249 gamma=PerceptibleReciprocal(gamma);
cristy4a7ae692011-12-14 12:24:11 +00005250 SetPixelChannel(destination,channel,ClampToQuantum(gamma*
5251 MeshInterpolate(&delta,pixels[3],pixels[2],pixels[1])),pixel);
cristy1861c902011-12-14 02:30:00 +00005252 }
5253 }
cristy5c4e2582011-09-11 19:21:03 +00005254 }
5255 break;
5256 }
5257 case SplineInterpolatePixel:
5258 {
cristya19f1d72012-08-07 18:24:38 +00005259 double
nicolasd32d5e52012-06-12 15:34:10 +00005260 cx[4],
5261 cy[4];
5262
cristy5c4e2582011-09-11 19:21:03 +00005263 p=GetCacheViewVirtualPixels(source_view,x_offset-1,y_offset-1,4,4,
5264 exception);
5265 if (p == (const Quantum *) NULL)
5266 {
5267 status=MagickFalse;
5268 break;
5269 }
cristy50e64b82012-06-22 17:46:19 +00005270 for (i=0; i < (ssize_t) GetPixelChannels(source); i++)
cristy5c4e2582011-09-11 19:21:03 +00005271 {
cristy5c4e2582011-09-11 19:21:03 +00005272 register ssize_t
5273 j;
5274
cristy5a23c552013-02-13 14:34:28 +00005275 PixelChannel channel=GetPixelChannelChannel(source,i);
5276 PixelTrait traits=GetPixelChannelTraits(source,channel);
5277 PixelTrait destination_traits=GetPixelChannelTraits(destination,
5278 channel);
cristy5c4e2582011-09-11 19:21:03 +00005279 if ((traits == UndefinedPixelTrait) ||
5280 (destination_traits == UndefinedPixelTrait))
5281 continue;
5282 if ((traits & BlendPixelTrait) == 0)
5283 for (j=0; j < 16; j++)
5284 {
5285 alpha[j]=1.0;
cristya19f1d72012-08-07 18:24:38 +00005286 pixels[j]=(double) p[j*GetPixelChannels(source)+i];
cristy5c4e2582011-09-11 19:21:03 +00005287 }
5288 else
5289 for (j=0; j < 16; j++)
5290 {
5291 alpha[j]=QuantumScale*GetPixelAlpha(source,p+j*
5292 GetPixelChannels(source));
5293 pixels[j]=alpha[j]*p[j*GetPixelChannels(source)+i];
5294 }
cristya19f1d72012-08-07 18:24:38 +00005295 SplineWeights((double) (x-x_offset),&cx);
5296 SplineWeights((double) (y-y_offset),&cy);
5297 gamma=((traits & BlendPixelTrait) ? (double) (1.0) :
cristy3e3ec3a2012-11-03 23:11:06 +00005298 PerceptibleReciprocal(cy[0]*(cx[0]*alpha[0]+cx[1]*alpha[1]+cx[2]*
nicolasd32d5e52012-06-12 15:34:10 +00005299 alpha[2]+cx[3]*alpha[3])+cy[1]*(cx[0]*alpha[4]+cx[1]*alpha[5]+cx[2]*
5300 alpha[6]+cx[3]*alpha[7])+cy[2]*(cx[0]*alpha[8]+cx[1]*alpha[9]+cx[2]*
5301 alpha[10]+cx[3]*alpha[11])+cy[3]*(cx[0]*alpha[12]+cx[1]*alpha[13]+
5302 cx[2]*alpha[14]+cx[3]*alpha[15])));
5303 SetPixelChannel(destination,channel,ClampToQuantum(gamma*(cy[0]*(cx[0]*
5304 pixels[0]+cx[1]*pixels[1]+cx[2]*pixels[2]+cx[3]*pixels[3])+cy[1]*
5305 (cx[0]*pixels[4]+cx[1]*pixels[5]+cx[2]*pixels[6]+cx[3]*pixels[7])+
5306 cy[2]*(cx[0]*pixels[8]+cx[1]*pixels[9]+cx[2]*pixels[10]+cx[3]*
5307 pixels[11])+cy[3]*(cx[0]*pixels[12]+cx[1]*pixels[13]+cx[2]*
5308 pixels[14]+cx[3]*pixels[15]))),pixel);
cristy5c4e2582011-09-11 19:21:03 +00005309 }
5310 break;
5311 }
5312 }
5313 return(status);
5314}
5315
5316/*
5317%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5318% %
5319% %
5320% %
cristy9075cdb2011-07-30 01:06:23 +00005321% 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 +00005322% %
5323% %
5324% %
5325%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5326%
cristy884f6002011-07-31 00:51:45 +00005327% InterpolatePixelInfo() applies a pixel interpolation method between a
5328% floating point coordinate and the pixels surrounding that coordinate. No
5329% pixel area resampling, or scaling of the result is performed.
cristy4c08aed2011-07-01 19:47:50 +00005330%
anthonycf4e33d2012-06-08 07:33:23 +00005331% Interpolation is restricted to just RGBKA channels.
5332%
cristy4c08aed2011-07-01 19:47:50 +00005333% The format of the InterpolatePixelInfo method is:
5334%
5335% MagickBooleanType InterpolatePixelInfo(const Image *image,
cristy5c4e2582011-09-11 19:21:03 +00005336% const CacheView *image_view,const PixelInterpolateMethod method,
cristy4c08aed2011-07-01 19:47:50 +00005337% const double x,const double y,PixelInfo *pixel,
5338% ExceptionInfo *exception)
5339%
5340% A description of each parameter follows:
5341%
5342% o image: the image.
5343%
5344% o image_view: the image view.
5345%
5346% o method: the pixel color interpolation method.
5347%
5348% o x,y: A double representing the current (x,y) position of the pixel.
5349%
5350% o pixel: return the interpolated pixel here.
5351%
5352% o exception: return any errors or warnings in this structure.
5353%
5354*/
5355
5356static inline void AlphaBlendPixelInfo(const Image *image,
cristya19f1d72012-08-07 18:24:38 +00005357 const Quantum *pixel,PixelInfo *pixel_info,double *alpha)
cristy4c08aed2011-07-01 19:47:50 +00005358{
cristy8a46d822012-08-28 23:32:39 +00005359 if (image->alpha_trait != BlendPixelTrait)
cristy4c08aed2011-07-01 19:47:50 +00005360 {
5361 *alpha=1.0;
cristya19f1d72012-08-07 18:24:38 +00005362 pixel_info->red=(double) GetPixelRed(image,pixel);
5363 pixel_info->green=(double) GetPixelGreen(image,pixel);
5364 pixel_info->blue=(double) GetPixelBlue(image,pixel);
cristy4c08aed2011-07-01 19:47:50 +00005365 pixel_info->black=0.0;
5366 if (image->colorspace == CMYKColorspace)
cristya19f1d72012-08-07 18:24:38 +00005367 pixel_info->black=(double) GetPixelBlack(image,pixel);
5368 pixel_info->alpha=(double) GetPixelAlpha(image,pixel);
cristy4c08aed2011-07-01 19:47:50 +00005369 return;
5370 }
5371 *alpha=QuantumScale*GetPixelAlpha(image,pixel);
5372 pixel_info->red=(*alpha*GetPixelRed(image,pixel));
5373 pixel_info->green=(*alpha*GetPixelGreen(image,pixel));
5374 pixel_info->blue=(*alpha*GetPixelBlue(image,pixel));
5375 pixel_info->black=0.0;
5376 if (image->colorspace == CMYKColorspace)
5377 pixel_info->black=(*alpha*GetPixelBlack(image,pixel));
cristya19f1d72012-08-07 18:24:38 +00005378 pixel_info->alpha=(double) GetPixelAlpha(image,pixel);
cristy4c08aed2011-07-01 19:47:50 +00005379}
5380
cristy4c08aed2011-07-01 19:47:50 +00005381MagickExport MagickBooleanType InterpolatePixelInfo(const Image *image,
cristy5c4e2582011-09-11 19:21:03 +00005382 const CacheView *image_view,const PixelInterpolateMethod method,
cristy4c08aed2011-07-01 19:47:50 +00005383 const double x,const double y,PixelInfo *pixel,ExceptionInfo *exception)
5384{
5385 MagickBooleanType
5386 status;
5387
cristya19f1d72012-08-07 18:24:38 +00005388 double
cristy4c08aed2011-07-01 19:47:50 +00005389 alpha[16],
5390 gamma;
5391
cristy865d58d2011-07-09 00:44:52 +00005392 PixelInfo
5393 pixels[16];
5394
cristy4c08aed2011-07-01 19:47:50 +00005395 register const Quantum
5396 *p;
5397
cristy50e64b82012-06-22 17:46:19 +00005398 register ssize_t
cristy4c08aed2011-07-01 19:47:50 +00005399 i;
5400
5401 ssize_t
5402 x_offset,
5403 y_offset;
5404
anthonycf4e33d2012-06-08 07:33:23 +00005405 PixelInterpolateMethod
5406 interpolate;
5407
cristy4c08aed2011-07-01 19:47:50 +00005408 assert(image != (Image *) NULL);
5409 assert(image->signature == MagickSignature);
5410 assert(image_view != (CacheView *) NULL);
5411 status=MagickTrue;
5412 x_offset=(ssize_t) floor(x);
5413 y_offset=(ssize_t) floor(y);
anthonycf4e33d2012-06-08 07:33:23 +00005414 interpolate = method;
5415 if ( interpolate == UndefinedInterpolatePixel )
5416 interpolate = image->interpolate;
5417 switch (interpolate)
cristy4c08aed2011-07-01 19:47:50 +00005418 {
cristy58ee5012013-05-26 23:58:44 +00005419 case AverageInterpolatePixel: /* nearest 4 neighbours */
5420 case Average9InterpolatePixel: /* nearest 9 neighbours */
5421 case Average16InterpolatePixel: /* nearest 16 neighbours */
cristy4c08aed2011-07-01 19:47:50 +00005422 {
cristyfb122372012-10-17 23:31:21 +00005423 ssize_t
5424 count;
anthonycf4e33d2012-06-08 07:33:23 +00005425
cristyfb122372012-10-17 23:31:21 +00005426 count=2; /* size of the area to average - default nearest 4 */
anthonycf4e33d2012-06-08 07:33:23 +00005427 if (interpolate == Average9InterpolatePixel)
5428 {
5429 count=3;
5430 x_offset=(ssize_t) (floor(x+0.5)-1);
5431 y_offset=(ssize_t) (floor(y+0.5)-1);
5432 }
5433 else if (interpolate == Average16InterpolatePixel)
5434 {
5435 count=4;
5436 x_offset--;
5437 y_offset--;
5438 }
cristy021216a2013-05-20 16:25:51 +00005439 p=GetCacheViewVirtualPixels(image_view,x_offset,y_offset,(size_t) count,
5440 (size_t) count,exception);
cristy4c08aed2011-07-01 19:47:50 +00005441 if (p == (const Quantum *) NULL)
5442 {
5443 status=MagickFalse;
5444 break;
5445 }
cristy4c08aed2011-07-01 19:47:50 +00005446 pixel->red=0.0;
5447 pixel->green=0.0;
5448 pixel->blue=0.0;
cristy4c08aed2011-07-01 19:47:50 +00005449 pixel->black=0.0;
cristy865d58d2011-07-09 00:44:52 +00005450 pixel->alpha=0.0;
cristy58ee5012013-05-26 23:58:44 +00005451 count*=count; /* number of pixels - square of size */
cristy50e64b82012-06-22 17:46:19 +00005452 for (i=0; i < (ssize_t) count; i++)
cristy4c08aed2011-07-01 19:47:50 +00005453 {
anthonycf4e33d2012-06-08 07:33:23 +00005454 AlphaBlendPixelInfo(image,p,pixels,alpha);
cristy3e3ec3a2012-11-03 23:11:06 +00005455 gamma=PerceptibleReciprocal(alpha[0]);
cristyfb122372012-10-17 23:31:21 +00005456 pixel->red+=gamma*pixels[0].red;
5457 pixel->green+=gamma*pixels[0].green;
5458 pixel->blue+=gamma*pixels[0].blue;
5459 pixel->black+=gamma*pixels[0].black;
5460 pixel->alpha+=pixels[0].alpha;
anthonycf4e33d2012-06-08 07:33:23 +00005461 p += GetPixelChannels(image);
cristy4c08aed2011-07-01 19:47:50 +00005462 }
anthonycf4e33d2012-06-08 07:33:23 +00005463 gamma=1.0/count; /* average weighting of each pixel in area */
cristyfb122372012-10-17 23:31:21 +00005464 pixel->red*=gamma;
5465 pixel->green*=gamma;
5466 pixel->blue*=gamma;
5467 pixel->black*=gamma;
5468 pixel->alpha*=gamma;
cristy4c08aed2011-07-01 19:47:50 +00005469 break;
5470 }
anthonycf4e33d2012-06-08 07:33:23 +00005471 case BackgroundInterpolatePixel:
5472 {
cristyfb122372012-10-17 23:31:21 +00005473 *pixel=image->background_color; /* Copy PixelInfo Structure */
anthonycf4e33d2012-06-08 07:33:23 +00005474 break;
5475 }
5476 case BilinearInterpolatePixel:
5477 default:
5478 {
5479 PointInfo
5480 delta,
5481 epsilon;
5482
5483 p=GetCacheViewVirtualPixels(image_view,x_offset,y_offset,2,2,exception);
5484 if (p == (const Quantum *) NULL)
5485 {
5486 status=MagickFalse;
5487 break;
5488 }
5489 for (i=0; i < 4L; i++)
5490 AlphaBlendPixelInfo(image,p+i*GetPixelChannels(image),pixels+i,alpha+i);
5491 delta.x=x-x_offset;
5492 delta.y=y-y_offset;
5493 epsilon.x=1.0-delta.x;
5494 epsilon.y=1.0-delta.y;
5495 gamma=((epsilon.y*(epsilon.x*alpha[0]+delta.x*alpha[1])+delta.y*
5496 (epsilon.x*alpha[2]+delta.x*alpha[3])));
cristy3e3ec3a2012-11-03 23:11:06 +00005497 gamma=PerceptibleReciprocal(gamma);
anthonycf4e33d2012-06-08 07:33:23 +00005498 pixel->red=gamma*(epsilon.y*(epsilon.x*pixels[0].red+delta.x*
5499 pixels[1].red)+delta.y*(epsilon.x*pixels[2].red+delta.x*pixels[3].red));
5500 pixel->green=gamma*(epsilon.y*(epsilon.x*pixels[0].green+delta.x*
5501 pixels[1].green)+delta.y*(epsilon.x*pixels[2].green+delta.x*
5502 pixels[3].green));
5503 pixel->blue=gamma*(epsilon.y*(epsilon.x*pixels[0].blue+delta.x*
5504 pixels[1].blue)+delta.y*(epsilon.x*pixels[2].blue+delta.x*
5505 pixels[3].blue));
5506 if (image->colorspace == CMYKColorspace)
5507 pixel->black=gamma*(epsilon.y*(epsilon.x*pixels[0].black+delta.x*
5508 pixels[1].black)+delta.y*(epsilon.x*pixels[2].black+delta.x*
5509 pixels[3].black));
5510 gamma=((epsilon.y*(epsilon.x+delta.x)+delta.y*(epsilon.x+delta.x)));
cristy3e3ec3a2012-11-03 23:11:06 +00005511 gamma=PerceptibleReciprocal(gamma);
anthonycf4e33d2012-06-08 07:33:23 +00005512 pixel->alpha=(epsilon.y*(epsilon.x*pixels[0].alpha+delta.x*
5513 pixels[1].alpha)+delta.y*(epsilon.x*pixels[2].alpha+delta.x*
5514 pixels[3].alpha));
5515 break;
5516 }
5517 case BlendInterpolatePixel:
5518 {
5519 p=GetCacheViewVirtualPixels(image_view,x_offset,y_offset,2,2,exception);
5520 if (p == (const Quantum *) NULL)
5521 {
5522 status=MagickFalse;
5523 break;
5524 }
5525 for (i=0; i < 4L; i++)
5526 AlphaBlendPixelInfo(image,p+i*GetPixelChannels(image),pixels+i,alpha+i);
cristyfb122372012-10-17 23:31:21 +00005527 gamma=1.0; /* number of pixels blended together (its variable) */
5528 for (i=0; i <= 1L; i++)
5529 {
5530 if ((y-y_offset) >= 0.75)
5531 {
5532 alpha[i]=alpha[i+2]; /* take right pixels */
5533 pixels[i]=pixels[i+2];
5534 }
5535 else
5536 if ((y-y_offset) > 0.25)
5537 {
5538 gamma=2.0; /* blend both pixels in row */
5539 alpha[i]+=alpha[i+2]; /* add up alpha weights */
5540 pixels[i].red+=pixels[i+2].red;
5541 pixels[i].green+=pixels[i+2].green;
5542 pixels[i].blue+=pixels[i+2].blue;
5543 pixels[i].black+=pixels[i+2].black;
5544 pixels[i].alpha+=pixels[i+2].alpha;
5545 }
5546 }
5547 if ((x-x_offset) >= 0.75)
5548 {
5549 alpha[0]=alpha[1];
5550 pixels[0]=pixels[1];
anthonycf4e33d2012-06-08 07:33:23 +00005551 }
cristyfb122372012-10-17 23:31:21 +00005552 else
5553 if ((x-x_offset) > 0.25)
5554 {
5555 gamma*=2.0; /* blend both rows */
cristy58ee5012013-05-26 23:58:44 +00005556 alpha[0]+= alpha[1]; /* add up alpha weights */
cristyfb122372012-10-17 23:31:21 +00005557 pixels[0].red+=pixels[1].red;
5558 pixels[0].green+=pixels[1].green;
5559 pixels[0].blue+=pixels[1].blue;
5560 pixels[0].black+=pixels[1].black;
5561 pixels[0].alpha+=pixels[1].alpha;
5562 }
5563 gamma=1.0/gamma;
cristy3e3ec3a2012-11-03 23:11:06 +00005564 alpha[0]=PerceptibleReciprocal(alpha[0]);
cristyfb122372012-10-17 23:31:21 +00005565 pixel->red=alpha[0]*pixels[0].red;
5566 pixel->green=alpha[0]*pixels[0].green; /* divide by sum of alpha */
5567 pixel->blue=alpha[0]*pixels[0].blue;
5568 pixel->black=alpha[0]*pixels[0].black;
5569 pixel->alpha=gamma*pixels[0].alpha; /* divide by number of pixels */
anthonycf4e33d2012-06-08 07:33:23 +00005570 break;
5571 }
5572 case CatromInterpolatePixel:
cristy4c08aed2011-07-01 19:47:50 +00005573 {
cristya19f1d72012-08-07 18:24:38 +00005574 double
cristy380a11c2012-06-02 15:15:22 +00005575 cx[4],
5576 cy[4];
cristy4c08aed2011-07-01 19:47:50 +00005577
cristy4c08aed2011-07-01 19:47:50 +00005578 p=GetCacheViewVirtualPixels(image_view,x_offset-1,y_offset-1,4,4,
5579 exception);
5580 if (p == (const Quantum *) NULL)
5581 {
5582 status=MagickFalse;
5583 break;
5584 }
anthonycf4e33d2012-06-08 07:33:23 +00005585 for (i=0; i < 16L; i++)
5586 AlphaBlendPixelInfo(image,p+i*GetPixelChannels(image),pixels+i,alpha+i);
cristya19f1d72012-08-07 18:24:38 +00005587 CatromWeights((double) (x-x_offset),&cx);
5588 CatromWeights((double) (y-y_offset),&cy);
cristyfb122372012-10-17 23:31:21 +00005589 pixel->red=(cy[0]*(cx[0]*pixels[0].red+cx[1]*pixels[1].red+cx[2]*
5590 pixels[2].red+cx[3]*pixels[3].red)+cy[1]*(cx[0]*pixels[4].red+cx[1]*
5591 pixels[5].red+cx[2]*pixels[6].red+cx[3]*pixels[7].red)+cy[2]*(cx[0]*
5592 pixels[8].red+cx[1]*pixels[9].red+cx[2]*pixels[10].red+cx[3]*
5593 pixels[11].red)+cy[3]*(cx[0]*pixels[12].red+cx[1]*pixels[13].red+cx[2]*
5594 pixels[14].red+cx[3]*pixels[15].red));
5595 pixel->green=(cy[0]*(cx[0]*pixels[0].green+cx[1]*pixels[1].green+cx[2]*
5596 pixels[2].green+cx[3]*pixels[3].green)+cy[1]*(cx[0]*pixels[4].green+
5597 cx[1]*pixels[5].green+cx[2]*pixels[6].green+cx[3]*pixels[7].green)+
5598 cy[2]*(cx[0]*pixels[8].green+cx[1]*pixels[9].green+cx[2]*
5599 pixels[10].green+cx[3]*pixels[11].green)+cy[3]*(cx[0]*
5600 pixels[12].green+cx[1]*pixels[13].green+cx[2]*pixels[14].green+cx[3]*
5601 pixels[15].green));
5602 pixel->blue=(cy[0]*(cx[0]*pixels[0].blue+cx[1]*pixels[1].blue+cx[2]*
5603 pixels[2].blue+cx[3]*pixels[3].blue)+cy[1]*(cx[0]*pixels[4].blue+cx[1]*
5604 pixels[5].blue+cx[2]*pixels[6].blue+cx[3]*pixels[7].blue)+cy[2]*(cx[0]*
5605 pixels[8].blue+cx[1]*pixels[9].blue+cx[2]*pixels[10].blue+cx[3]*
5606 pixels[11].blue)+cy[3]*(cx[0]*pixels[12].blue+cx[1]*pixels[13].blue+
5607 cx[2]*pixels[14].blue+cx[3]*pixels[15].blue));
cristy380a11c2012-06-02 15:15:22 +00005608 if (image->colorspace == CMYKColorspace)
cristyfb122372012-10-17 23:31:21 +00005609 pixel->black=(cy[0]*(cx[0]*pixels[0].black+cx[1]*pixels[1].black+cx[2]*
5610 pixels[2].black+cx[3]*pixels[3].black)+cy[1]*(cx[0]*pixels[4].black+
5611 cx[1]*pixels[5].black+cx[2]*pixels[6].black+cx[3]*pixels[7].black)+
5612 cy[2]*(cx[0]*pixels[8].black+cx[1]*pixels[9].black+cx[2]*
5613 pixels[10].black+cx[3]*pixels[11].black)+cy[3]*(cx[0]*
5614 pixels[12].black+cx[1]*pixels[13].black+cx[2]*pixels[14].black+cx[3]*
5615 pixels[15].black));
5616 pixel->alpha=(cy[0]*(cx[0]*pixels[0].alpha+cx[1]*pixels[1].alpha+cx[2]*
5617 pixels[2].alpha+cx[3]*pixels[3].alpha)+cy[1]*(cx[0]*pixels[4].alpha+
5618 cx[1]*pixels[5].alpha+cx[2]*pixels[6].alpha+cx[3]*pixels[7].alpha)+
5619 cy[2]*(cx[0]*pixels[8].alpha+cx[1]*pixels[9].alpha+cx[2]*
5620 pixels[10].alpha+cx[3]*pixels[11].alpha)+cy[3]*(cx[0]*pixels[12].alpha+
5621 cx[1]*pixels[13].alpha+cx[2]*pixels[14].alpha+cx[3]*pixels[15].alpha));
cristy4c08aed2011-07-01 19:47:50 +00005622 break;
5623 }
cristy4c08aed2011-07-01 19:47:50 +00005624 case IntegerInterpolatePixel:
5625 {
5626 p=GetCacheViewVirtualPixels(image_view,x_offset,y_offset,1,1,exception);
5627 if (p == (const Quantum *) NULL)
5628 {
5629 status=MagickFalse;
5630 break;
5631 }
cristy803640d2011-11-17 02:11:32 +00005632 GetPixelInfoPixel(image,p,pixel);
cristy4c08aed2011-07-01 19:47:50 +00005633 break;
5634 }
5635 case MeshInterpolatePixel:
5636 {
5637 PointInfo
5638 delta,
5639 luminance;
5640
cristy94ea1632011-07-30 20:40:25 +00005641 p=GetCacheViewVirtualPixels(image_view,x_offset,y_offset,2,2,exception);
cristy4c08aed2011-07-01 19:47:50 +00005642 if (p == (const Quantum *) NULL)
5643 {
5644 status=MagickFalse;
5645 break;
5646 }
cristy94ea1632011-07-30 20:40:25 +00005647 delta.x=x-x_offset;
5648 delta.y=y-y_offset;
cristyebfaacf2013-06-24 16:22:40 +00005649 luminance.x=GetPixelLuma(image,p)-(double)
5650 GetPixelLuma(image,p+3*GetPixelChannels(image));
5651 luminance.y=GetPixelLuma(image,p+GetPixelChannels(image))-(double)
5652 GetPixelLuma(image,p+2*GetPixelChannels(image));
cristy5ce8df82011-07-07 14:52:23 +00005653 AlphaBlendPixelInfo(image,p,pixels+0,alpha+0);
cristy28474bf2011-09-11 23:32:52 +00005654 AlphaBlendPixelInfo(image,p+GetPixelChannels(image),pixels+1,alpha+1);
cristyed231572011-07-14 02:18:59 +00005655 AlphaBlendPixelInfo(image,p+2*GetPixelChannels(image),pixels+2,alpha+2);
5656 AlphaBlendPixelInfo(image,p+3*GetPixelChannels(image),pixels+3,alpha+3);
cristy4c08aed2011-07-01 19:47:50 +00005657 if (fabs(luminance.x) < fabs(luminance.y))
5658 {
5659 /*
5660 Diagonal 0-3 NW-SE.
5661 */
5662 if (delta.x <= delta.y)
5663 {
5664 /*
cristy94ea1632011-07-30 20:40:25 +00005665 Bottom-left triangle (pixel: 2, diagonal: 0-3).
cristy4c08aed2011-07-01 19:47:50 +00005666 */
5667 delta.y=1.0-delta.y;
5668 gamma=MeshInterpolate(&delta,alpha[2],alpha[3],alpha[0]);
cristy3e3ec3a2012-11-03 23:11:06 +00005669 gamma=PerceptibleReciprocal(gamma);
cristy4c08aed2011-07-01 19:47:50 +00005670 pixel->red=gamma*MeshInterpolate(&delta,pixels[2].red,
5671 pixels[3].red,pixels[0].red);
5672 pixel->green=gamma*MeshInterpolate(&delta,pixels[2].green,
5673 pixels[3].green,pixels[0].green);
5674 pixel->blue=gamma*MeshInterpolate(&delta,pixels[2].blue,
5675 pixels[3].blue,pixels[0].blue);
cristy4c08aed2011-07-01 19:47:50 +00005676 if (image->colorspace == CMYKColorspace)
5677 pixel->black=gamma*MeshInterpolate(&delta,pixels[2].black,
5678 pixels[3].black,pixels[0].black);
cristy94ea1632011-07-30 20:40:25 +00005679 gamma=MeshInterpolate(&delta,1.0,1.0,1.0);
cristy865d58d2011-07-09 00:44:52 +00005680 pixel->alpha=gamma*MeshInterpolate(&delta,pixels[2].alpha,
5681 pixels[3].alpha,pixels[0].alpha);
cristy4c08aed2011-07-01 19:47:50 +00005682 }
5683 else
5684 {
5685 /*
cristy94ea1632011-07-30 20:40:25 +00005686 Top-right triangle (pixel:1 , diagonal: 0-3).
cristy4c08aed2011-07-01 19:47:50 +00005687 */
5688 delta.x=1.0-delta.x;
5689 gamma=MeshInterpolate(&delta,alpha[1],alpha[0],alpha[3]);
cristy3e3ec3a2012-11-03 23:11:06 +00005690 gamma=PerceptibleReciprocal(gamma);
cristy4c08aed2011-07-01 19:47:50 +00005691 pixel->red=gamma*MeshInterpolate(&delta,pixels[1].red,
5692 pixels[0].red,pixels[3].red);
5693 pixel->green=gamma*MeshInterpolate(&delta,pixels[1].green,
5694 pixels[0].green,pixels[3].green);
5695 pixel->blue=gamma*MeshInterpolate(&delta,pixels[1].blue,
5696 pixels[0].blue,pixels[3].blue);
cristy4c08aed2011-07-01 19:47:50 +00005697 if (image->colorspace == CMYKColorspace)
5698 pixel->black=gamma*MeshInterpolate(&delta,pixels[1].black,
5699 pixels[0].black,pixels[3].black);
cristy94ea1632011-07-30 20:40:25 +00005700 gamma=MeshInterpolate(&delta,1.0,1.0,1.0);
cristy865d58d2011-07-09 00:44:52 +00005701 pixel->alpha=gamma*MeshInterpolate(&delta,pixels[1].alpha,
5702 pixels[0].alpha,pixels[3].alpha);
cristy4c08aed2011-07-01 19:47:50 +00005703 }
5704 }
5705 else
5706 {
5707 /*
5708 Diagonal 1-2 NE-SW.
5709 */
5710 if (delta.x <= (1.0-delta.y))
5711 {
5712 /*
cristy94ea1632011-07-30 20:40:25 +00005713 Top-left triangle (pixel: 0, diagonal: 1-2).
cristy4c08aed2011-07-01 19:47:50 +00005714 */
5715 gamma=MeshInterpolate(&delta,alpha[0],alpha[1],alpha[2]);
cristy3e3ec3a2012-11-03 23:11:06 +00005716 gamma=PerceptibleReciprocal(gamma);
cristy4c08aed2011-07-01 19:47:50 +00005717 pixel->red=gamma*MeshInterpolate(&delta,pixels[0].red,
5718 pixels[1].red,pixels[2].red);
5719 pixel->green=gamma*MeshInterpolate(&delta,pixels[0].green,
5720 pixels[1].green,pixels[2].green);
5721 pixel->blue=gamma*MeshInterpolate(&delta,pixels[0].blue,
5722 pixels[1].blue,pixels[2].blue);
cristy4c08aed2011-07-01 19:47:50 +00005723 if (image->colorspace == CMYKColorspace)
5724 pixel->black=gamma*MeshInterpolate(&delta,pixels[0].black,
5725 pixels[1].black,pixels[2].black);
cristy94ea1632011-07-30 20:40:25 +00005726 gamma=MeshInterpolate(&delta,1.0,1.0,1.0);
cristy865d58d2011-07-09 00:44:52 +00005727 pixel->alpha=gamma*MeshInterpolate(&delta,pixels[0].alpha,
5728 pixels[1].alpha,pixels[2].alpha);
cristy4c08aed2011-07-01 19:47:50 +00005729 }
5730 else
5731 {
5732 /*
5733 Bottom-right triangle (pixel: 3, diagonal: 1-2).
5734 */
5735 delta.x=1.0-delta.x;
5736 delta.y=1.0-delta.y;
5737 gamma=MeshInterpolate(&delta,alpha[3],alpha[2],alpha[1]);
cristy3e3ec3a2012-11-03 23:11:06 +00005738 gamma=PerceptibleReciprocal(gamma);
cristy4c08aed2011-07-01 19:47:50 +00005739 pixel->red=gamma*MeshInterpolate(&delta,pixels[3].red,
5740 pixels[2].red,pixels[1].red);
5741 pixel->green=gamma*MeshInterpolate(&delta,pixels[3].green,
5742 pixels[2].green,pixels[1].green);
5743 pixel->blue=gamma*MeshInterpolate(&delta,pixels[3].blue,
5744 pixels[2].blue,pixels[1].blue);
cristy4c08aed2011-07-01 19:47:50 +00005745 if (image->colorspace == CMYKColorspace)
5746 pixel->black=gamma*MeshInterpolate(&delta,pixels[3].black,
5747 pixels[2].black,pixels[1].black);
cristy94ea1632011-07-30 20:40:25 +00005748 gamma=MeshInterpolate(&delta,1.0,1.0,1.0);
cristy865d58d2011-07-09 00:44:52 +00005749 pixel->alpha=gamma*MeshInterpolate(&delta,pixels[3].alpha,
5750 pixels[2].alpha,pixels[1].alpha);
cristy4c08aed2011-07-01 19:47:50 +00005751 }
5752 }
5753 break;
5754 }
anthonycf4e33d2012-06-08 07:33:23 +00005755 case NearestInterpolatePixel:
cristy4c08aed2011-07-01 19:47:50 +00005756 {
anthonycf4e33d2012-06-08 07:33:23 +00005757 x_offset=(ssize_t) floor(x+0.5);
5758 y_offset=(ssize_t) floor(y+0.5);
5759 p=GetCacheViewVirtualPixels(image_view,x_offset,y_offset,1,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00005760 if (p == (const Quantum *) NULL)
5761 {
5762 status=MagickFalse;
5763 break;
5764 }
cristy803640d2011-11-17 02:11:32 +00005765 GetPixelInfoPixel(image,p,pixel);
cristy4c08aed2011-07-01 19:47:50 +00005766 break;
5767 }
5768 case SplineInterpolatePixel:
5769 {
cristya19f1d72012-08-07 18:24:38 +00005770 double
nicolasd32d5e52012-06-12 15:34:10 +00005771 cx[4],
5772 cy[4];
cristy4c08aed2011-07-01 19:47:50 +00005773
5774 p=GetCacheViewVirtualPixels(image_view,x_offset-1,y_offset-1,4,4,
5775 exception);
5776 if (p == (const Quantum *) NULL)
5777 {
5778 status=MagickFalse;
5779 break;
5780 }
anthonycf4e33d2012-06-08 07:33:23 +00005781 for (i=0; i < 16L; i++)
5782 AlphaBlendPixelInfo(image,p+i*GetPixelChannels(image),pixels+i,alpha+i);
cristya19f1d72012-08-07 18:24:38 +00005783 SplineWeights((double) (x-x_offset),&cx);
5784 SplineWeights((double) (y-y_offset),&cy);
cristyfb122372012-10-17 23:31:21 +00005785 pixel->red=(cy[0]*(cx[0]*pixels[0].red+cx[1]*pixels[1].red+cx[2]*
5786 pixels[2].red+cx[3]*pixels[3].red)+cy[1]*(cx[0]*pixels[4].red+cx[1]*
5787 pixels[5].red+cx[2]*pixels[6].red+cx[3]*pixels[7].red)+cy[2]*(cx[0]*
5788 pixels[8].red+cx[1]*pixels[9].red+cx[2]*pixels[10].red+cx[3]*
5789 pixels[11].red)+cy[3]*(cx[0]*pixels[12].red+cx[1]*pixels[13].red+cx[2]*
5790 pixels[14].red+cx[3]*pixels[15].red));
5791 pixel->green=(cy[0]*(cx[0]*pixels[0].green+cx[1]*pixels[1].green+cx[2]*
5792 pixels[2].green+cx[3]*pixels[3].green)+cy[1]*(cx[0]*pixels[4].green+
5793 cx[1]*pixels[5].green+cx[2]*pixels[6].green+cx[3]*pixels[7].green)+
5794 cy[2]*(cx[0]*pixels[8].green+cx[1]*pixels[9].green+cx[2]*
5795 pixels[10].green+cx[3]*pixels[11].green)+cy[3]*(cx[0]*pixels[12].green+
5796 cx[1]*pixels[13].green+cx[2]*pixels[14].green+cx[3]*pixels[15].green));
5797 pixel->blue=(cy[0]*(cx[0]*pixels[0].blue+cx[1]*pixels[1].blue+cx[2]*
5798 pixels[2].blue+cx[3]*pixels[3].blue)+cy[1]*(cx[0]*pixels[4].blue+cx[1]*
5799 pixels[5].blue+cx[2]*pixels[6].blue+cx[3]*pixels[7].blue)+cy[2]*(cx[0]*
5800 pixels[8].blue+cx[1]*pixels[9].blue+cx[2]*pixels[10].blue+cx[3]*
5801 pixels[11].blue)+cy[3]*(cx[0]*pixels[12].blue+cx[1]*pixels[13].blue+
5802 cx[2]*pixels[14].blue+cx[3]*pixels[15].blue));
nicolasd32d5e52012-06-12 15:34:10 +00005803 if (image->colorspace == CMYKColorspace)
cristyfb122372012-10-17 23:31:21 +00005804 pixel->black=(cy[0]*(cx[0]*pixels[0].black+cx[1]*pixels[1].black+cx[2]*
5805 pixels[2].black+cx[3]*pixels[3].black)+cy[1]*(cx[0]*pixels[4].black+
5806 cx[1]*pixels[5].black+cx[2]*pixels[6].black+cx[3]*pixels[7].black)+
5807 cy[2]*(cx[0]*pixels[8].black+cx[1]*pixels[9].black+cx[2]*
5808 pixels[10].black+cx[3]*pixels[11].black)+cy[3]*(cx[0]*
5809 pixels[12].black+cx[1]*pixels[13].black+cx[2]*pixels[14].black+cx[3]*
5810 pixels[15].black));
5811 pixel->alpha=(cy[0]*(cx[0]*pixels[0].alpha+cx[1]*pixels[1].alpha+cx[2]*
5812 pixels[2].alpha+cx[3]*pixels[3].alpha)+cy[1]*(cx[0]*pixels[4].alpha+
5813 cx[1]*pixels[5].alpha+cx[2]*pixels[6].alpha+cx[3]*pixels[7].alpha)+
5814 cy[2]*(cx[0]*pixels[8].alpha+cx[1]*pixels[9].alpha+cx[2]*
5815 pixels[10].alpha+cx[3]*pixels[11].alpha)+cy[3]*(cx[0]*pixels[12].alpha+
5816 cx[1]*pixels[13].alpha+cx[2]*pixels[14].alpha+cx[3]*pixels[15].alpha));
cristy4c08aed2011-07-01 19:47:50 +00005817 break;
5818 }
5819 }
5820 return(status);
5821}
5822
5823/*
5824%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5825% %
5826% %
5827% %
5828+ I s F u z z y E q u i v a l e n c e P i x e l %
5829% %
5830% %
5831% %
5832%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5833%
5834% IsFuzzyEquivalencePixel() returns MagickTrue if the distance between two
5835% pixels is less than the specified distance in a linear three (or four)u
5836% dimensional color space.
5837%
5838% The format of the IsFuzzyEquivalencePixel method is:
5839%
cristye4a40472011-12-22 02:56:19 +00005840% void IsFuzzyEquivalencePixel(const Image *source,const Quantum *p,
5841% const Image *destination,const Quantum *q)
cristy4c08aed2011-07-01 19:47:50 +00005842%
5843% A description of each parameter follows:
5844%
cristye4a40472011-12-22 02:56:19 +00005845% o source: the source image.
cristy4c08aed2011-07-01 19:47:50 +00005846%
5847% o p: Pixel p.
5848%
cristye4a40472011-12-22 02:56:19 +00005849% o destination: the destination image.
5850%
cristy4c08aed2011-07-01 19:47:50 +00005851% o q: Pixel q.
5852%
5853*/
cristye4a40472011-12-22 02:56:19 +00005854MagickExport MagickBooleanType IsFuzzyEquivalencePixel(const Image *source,
5855 const Quantum *p,const Image *destination,const Quantum *q)
cristy4c08aed2011-07-01 19:47:50 +00005856{
cristya19f1d72012-08-07 18:24:38 +00005857 double
cristy4c08aed2011-07-01 19:47:50 +00005858 fuzz,
5859 pixel;
5860
cristya19f1d72012-08-07 18:24:38 +00005861 register double
cristy4c08aed2011-07-01 19:47:50 +00005862 distance,
5863 scale;
5864
cristy3522bf42013-08-04 14:53:18 +00005865 fuzz=(double) MagickMax(source->fuzz,(MagickRealType) MagickSQ1_2)*MagickMax(
5866 destination->fuzz,(MagickRealType) MagickSQ1_2);
cristy4c08aed2011-07-01 19:47:50 +00005867 scale=1.0;
5868 distance=0.0;
cristy8a46d822012-08-28 23:32:39 +00005869 if (source->alpha_trait == BlendPixelTrait)
cristy4c08aed2011-07-01 19:47:50 +00005870 {
5871 /*
5872 Transparencies are involved - set alpha distance
5873 */
cristy70e9f682013-03-12 22:31:22 +00005874 pixel=GetPixelAlpha(source,p)-(double) GetPixelAlpha(destination,q);
cristy4c08aed2011-07-01 19:47:50 +00005875 distance=pixel*pixel;
5876 if (distance > fuzz)
5877 return(MagickFalse);
5878 /*
5879 Generate a alpha scaling factor to generate a 4D cone on colorspace
5880 Note that if one color is transparent, distance has no color component.
5881 */
cristye4a40472011-12-22 02:56:19 +00005882 scale=QuantumScale*GetPixelAlpha(source,p);
5883 scale*=QuantumScale*GetPixelAlpha(destination,q);
cristy4c08aed2011-07-01 19:47:50 +00005884 if (scale <= MagickEpsilon)
5885 return(MagickTrue);
5886 }
5887 /*
5888 RGB or CMY color cube
5889 */
5890 distance*=3.0; /* rescale appropriately */
5891 fuzz*=3.0;
cristya19f1d72012-08-07 18:24:38 +00005892 pixel=GetPixelRed(source,p)-(double) GetPixelRed(destination,q);
cristye4a40472011-12-22 02:56:19 +00005893 if ((source->colorspace == HSLColorspace) ||
5894 (source->colorspace == HSBColorspace) ||
5895 (source->colorspace == HWBColorspace))
cristy4c08aed2011-07-01 19:47:50 +00005896 {
5897 /*
5898 Compute an arc distance for hue. It should be a vector angle of
5899 'S'/'W' length with 'L'/'B' forming appropriate cones.
5900 */
5901 if (fabs((double) pixel) > (QuantumRange/2))
5902 pixel-=QuantumRange;
5903 pixel*=2;
5904 }
5905 distance+=scale*pixel*pixel;
5906 if (distance > fuzz)
5907 return(MagickFalse);
cristya19f1d72012-08-07 18:24:38 +00005908 pixel=GetPixelGreen(source,p)-(double) GetPixelGreen(destination,q);
cristy4c08aed2011-07-01 19:47:50 +00005909 distance+=scale*pixel*pixel;
5910 if (distance > fuzz)
5911 return(MagickFalse);
cristya19f1d72012-08-07 18:24:38 +00005912 pixel=GetPixelBlue(source,p)-(double) GetPixelBlue(destination,q);
cristy4c08aed2011-07-01 19:47:50 +00005913 distance+=scale*pixel*pixel;
5914 if (distance > fuzz)
5915 return(MagickFalse);
5916 return(MagickTrue);
5917}
5918
5919/*
5920%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5921% %
5922% %
5923% %
5924+ 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 %
5925% %
5926% %
5927% %
5928%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5929%
5930% IsFuzzyEquivalencePixelInfo() returns true if the distance between two
5931% colors is less than the specified distance in a linear three (or four)
5932% dimensional color space.
5933%
cristy5f95f4f2011-10-23 01:01:01 +00005934% This implements the equivalent of:
5935% fuzz < sqrt(color_distance^2 * u.a*v.a + alpha_distance^2)
cristy4c08aed2011-07-01 19:47:50 +00005936%
5937% Which produces a multi-dimensional cone for that colorspace along the
5938% transparency vector.
5939%
cristy5f95f4f2011-10-23 01:01:01 +00005940% For example for an RGB:
cristy4c08aed2011-07-01 19:47:50 +00005941% color_distance^2 = ( (u.r-v.r)^2 + (u.g-v.g)^2 + (u.b-v.b)^2 ) / 3
5942%
5943% See http://www.imagemagick.org/Usage/bugs/fuzz_distance/
5944%
5945% Hue colorspace distances need more work. Hue is not a distance, it is an
5946% angle!
5947%
5948% A check that q is in the same color space as p should be made and the
5949% appropriate mapping made. -- Anthony Thyssen 8 December 2010
5950%
5951% The format of the IsFuzzyEquivalencePixelInfo method is:
5952%
5953% MagickBooleanType IsFuzzyEquivalencePixelInfo(const PixelInfo *p,
5954% const PixelInfo *q)
5955%
5956% A description of each parameter follows:
5957%
5958% o p: Pixel p.
5959%
5960% o q: Pixel q.
5961%
5962*/
5963MagickExport MagickBooleanType IsFuzzyEquivalencePixelInfo(const PixelInfo *p,
5964 const PixelInfo *q)
5965{
cristya19f1d72012-08-07 18:24:38 +00005966 double
cristy4c08aed2011-07-01 19:47:50 +00005967 fuzz,
5968 pixel;
5969
cristya19f1d72012-08-07 18:24:38 +00005970 register double
cristy4c08aed2011-07-01 19:47:50 +00005971 scale,
5972 distance;
5973
5974 if ((p->fuzz == 0.0) && (q->fuzz == 0.0))
5975 return(IsPixelInfoEquivalent(p,q));
5976 if (p->fuzz == 0.0)
cristy3522bf42013-08-04 14:53:18 +00005977 fuzz=MagickMax(q->fuzz,(MagickRealType) MagickSQ1_2)*
5978 MagickMax(q->fuzz,(MagickRealType) MagickSQ1_2);
cristy4c08aed2011-07-01 19:47:50 +00005979 else if (q->fuzz == 0.0)
cristy3522bf42013-08-04 14:53:18 +00005980 fuzz=MagickMax(p->fuzz,(MagickRealType) MagickSQ1_2)*
5981 MagickMax(p->fuzz,(MagickRealType) MagickSQ1_2);
cristy4c08aed2011-07-01 19:47:50 +00005982 else
cristy3522bf42013-08-04 14:53:18 +00005983 fuzz=MagickMax(p->fuzz,(MagickRealType) MagickSQ1_2)*
5984 MagickMax(q->fuzz,(MagickRealType) MagickSQ1_2);
cristy4c08aed2011-07-01 19:47:50 +00005985 scale=1.0;
5986 distance=0.0;
cristy24dc9722013-05-20 16:02:22 +00005987 if ((p->alpha_trait == BlendPixelTrait) ||
5988 (q->alpha_trait == BlendPixelTrait))
cristy4c08aed2011-07-01 19:47:50 +00005989 {
5990 /*
5991 Transparencies are involved - set alpha distance.
5992 */
cristy8a46d822012-08-28 23:32:39 +00005993 pixel=(p->alpha_trait == BlendPixelTrait ? p->alpha : OpaqueAlpha)-
5994 (q->alpha_trait == BlendPixelTrait ? q->alpha : OpaqueAlpha);
cristy4c08aed2011-07-01 19:47:50 +00005995 distance=pixel*pixel;
5996 if (distance > fuzz)
5997 return(MagickFalse);
5998 /*
5999 Generate a alpha scaling factor to generate a 4D cone on colorspace.
cristy5f95f4f2011-10-23 01:01:01 +00006000 If one color is transparent, distance has no color component.
cristy4c08aed2011-07-01 19:47:50 +00006001 */
cristy8a46d822012-08-28 23:32:39 +00006002 if (p->alpha_trait == BlendPixelTrait)
cristy4c08aed2011-07-01 19:47:50 +00006003 scale=(QuantumScale*p->alpha);
cristy8a46d822012-08-28 23:32:39 +00006004 if (q->alpha_trait == BlendPixelTrait)
cristy4c08aed2011-07-01 19:47:50 +00006005 scale*=(QuantumScale*q->alpha);
6006 if (scale <= MagickEpsilon )
6007 return(MagickTrue);
6008 }
6009 /*
6010 CMYK create a CMY cube with a multi-dimensional cone toward black.
6011 */
6012 if (p->colorspace == CMYKColorspace)
6013 {
6014 pixel=p->black-q->black;
6015 distance+=pixel*pixel*scale;
6016 if (distance > fuzz)
6017 return(MagickFalse);
cristya19f1d72012-08-07 18:24:38 +00006018 scale*=(double) (QuantumScale*(QuantumRange-p->black));
6019 scale*=(double) (QuantumScale*(QuantumRange-q->black));
cristy4c08aed2011-07-01 19:47:50 +00006020 }
6021 /*
6022 RGB or CMY color cube.
6023 */
6024 distance*=3.0; /* rescale appropriately */
6025 fuzz*=3.0;
6026 pixel=p->red-q->red;
6027 if ((p->colorspace == HSLColorspace) || (p->colorspace == HSBColorspace) ||
6028 (p->colorspace == HWBColorspace))
6029 {
cristy5f95f4f2011-10-23 01:01:01 +00006030 /*
cristy58ee5012013-05-26 23:58:44 +00006031 This calculates a arc distance for hue-- it should be a vector
6032 angle of 'S'/'W' length with 'L'/'B' forming appropriate cones.
6033 In other words this is a hack - Anthony.
cristy4c08aed2011-07-01 19:47:50 +00006034 */
6035 if (fabs((double) pixel) > (QuantumRange/2))
6036 pixel-=QuantumRange;
6037 pixel*=2;
6038 }
6039 distance+=pixel*pixel*scale;
6040 if (distance > fuzz)
6041 return(MagickFalse);
6042 pixel=p->green-q->green;
6043 distance+=pixel*pixel*scale;
6044 if (distance > fuzz)
6045 return(MagickFalse);
6046 pixel=p->blue-q->blue;
6047 distance+=pixel*pixel*scale;
6048 if (distance > fuzz)
6049 return(MagickFalse);
6050 return(MagickTrue);
6051}
6052
6053/*
6054%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6055% %
6056% %
6057% %
cristy7ae16542013-05-15 22:41:24 +00006058% 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 +00006059% %
6060% %
6061% %
6062%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6063%
cristy7ae16542013-05-15 22:41:24 +00006064% SetPixelChannelMask() sets the pixel channel map from the specified channel
6065% mask.
cristy2b9582a2011-07-04 17:38:56 +00006066%
cristycf1296e2012-08-26 23:40:49 +00006067% The format of the SetPixelChannelMask method is:
cristy2b9582a2011-07-04 17:38:56 +00006068%
cristycf1296e2012-08-26 23:40:49 +00006069% void SetPixelChannelMask(Image *image,const ChannelType channel_mask)
cristy2b9582a2011-07-04 17:38:56 +00006070%
6071% A description of each parameter follows:
6072%
6073% o image: the image.
6074%
cristydfdb19e2012-03-21 22:22:24 +00006075% o channel_mask: the channel mask.
cristy2b9582a2011-07-04 17:38:56 +00006076%
6077*/
cristycf1296e2012-08-26 23:40:49 +00006078MagickExport void SetPixelChannelMask(Image *image,
cristy07a67852011-08-26 13:25:03 +00006079 const ChannelType channel_mask)
cristy2b9582a2011-07-04 17:38:56 +00006080{
cristy6a917d62011-08-24 17:31:30 +00006081#define GetChannelBit(mask,bit) (((size_t) (mask) >> (size_t) (bit)) & 0x01)
cristydafd2872011-07-24 22:06:13 +00006082
cristy2b9582a2011-07-04 17:38:56 +00006083 register ssize_t
6084 i;
6085
cristy177e41c2012-04-15 15:08:25 +00006086 if (image->debug != MagickFalse)
6087 (void) LogMagickEvent(PixelEvent,GetMagickModule(),"%s[%08x]", \
6088 image->filename,channel_mask); \
cristy3c309812011-11-08 02:40:43 +00006089 image->channel_mask=channel_mask;
cristydafd2872011-07-24 22:06:13 +00006090 for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
cristye2a912b2011-12-05 20:02:07 +00006091 {
cristy5a23c552013-02-13 14:34:28 +00006092 PixelChannel channel=GetPixelChannelChannel(image,i);
cristy297e3a42012-08-26 21:27:29 +00006093 SetPixelChannelTraits(image,channel,
cristye2a912b2011-12-05 20:02:07 +00006094 GetChannelBit(channel_mask,channel) == 0 ? CopyPixelTrait :
cristy8a46d822012-08-28 23:32:39 +00006095 image->alpha_trait != BlendPixelTrait || (channel == AlphaPixelChannel) ?
6096 UpdatePixelTrait : (PixelTrait) (UpdatePixelTrait | image->alpha_trait));
cristye2a912b2011-12-05 20:02:07 +00006097 }
cristy1685e722011-09-06 00:04:19 +00006098 if (image->storage_class == PseudoClass)
cristy297e3a42012-08-26 21:27:29 +00006099 SetPixelChannelTraits(image,IndexPixelChannel,CopyPixelTrait);
cristy883fde12013-04-08 00:50:13 +00006100 if (image->read_mask != MagickFalse)
6101 SetPixelChannelTraits(image,ReadMaskPixelChannel,CopyPixelTrait);
6102 if (image->write_mask != MagickFalse)
6103 SetPixelChannelTraits(image,WriteMaskPixelChannel,CopyPixelTrait);
cristy6dcb9b82011-10-23 23:21:25 +00006104 if (image->debug != MagickFalse)
6105 LogPixelChannels(image);
cristy2b9582a2011-07-04 17:38:56 +00006106}
6107
6108/*
6109%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6110% %
6111% %
6112% %
cristy322d07d2012-03-18 21:17:23 +00006113% S e t P i x e l M e t a C h a n n e l s %
6114% %
6115% %
6116% %
6117%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6118%
6119% SetPixelMetaChannels() sets the image meta channels.
6120%
6121% The format of the SetPixelMetaChannels method is:
6122%
6123% MagickBooleanType SetPixelMetaChannels(Image *image,
6124% const size_t number_meta_channels,ExceptionInfo *exception)
6125%
6126% A description of each parameter follows:
6127%
6128% o image: the image.
6129%
6130% o number_meta_channels: the number of meta channels.
6131%
6132% o exception: return any errors or warnings in this structure.
6133%
6134*/
6135MagickExport MagickBooleanType SetPixelMetaChannels(Image *image,
6136 const size_t number_meta_channels,ExceptionInfo *exception)
6137{
6138 image->number_meta_channels=number_meta_channels;
6139 return(SyncImagePixelCache(image,exception));
6140}