blob: fb6c87acaf36848e2ff94443f7cdb4874133a8c5 [file] [log] [blame]
cristy4c08aed2011-07-01 19:47:50 +00001/*
2%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3% %
4% %
5% %
6% PPPP IIIII X X EEEEE L %
7% P P I X X E L %
8% PPPP I X EEE L %
9% P I X X E L %
10% P IIIII X X EEEEE LLLLL %
11% %
12% MagickCore Methods to Import/Export Pixels %
13% %
14% Software Design %
15% John Cristy %
16% October 1998 %
17% %
18% %
cristy45ef08f2012-12-07 13:13:34 +000019% Copyright 1999-2013 ImageMagick Studio LLC, a non-profit organization %
cristy4c08aed2011-07-01 19:47:50 +000020% dedicated to making software imaging solutions freely available. %
21% %
22% You may not use this file except in compliance with the License. You may %
23% obtain a copy of the License at %
24% %
25% http://www.imagemagick.org/script/license.php %
26% %
27% Unless required by applicable law or agreed to in writing, software %
28% distributed under the License is distributed on an "AS IS" BASIS, %
29% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %
30% See the License for the specific language governing permissions and %
31% limitations under the License. %
32% %
33%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
34%
35%
36*/
37
38/*
39 Include declarations.
40*/
41#include "MagickCore/studio.h"
42#include "MagickCore/property.h"
43#include "MagickCore/blob.h"
44#include "MagickCore/blob-private.h"
cristy322d07d2012-03-18 21:17:23 +000045#include "MagickCore/cache-private.h"
cristy4c08aed2011-07-01 19:47:50 +000046#include "MagickCore/color-private.h"
47#include "MagickCore/draw.h"
48#include "MagickCore/exception.h"
49#include "MagickCore/exception-private.h"
50#include "MagickCore/cache.h"
51#include "MagickCore/constitute.h"
52#include "MagickCore/delegate.h"
53#include "MagickCore/geometry.h"
54#include "MagickCore/image-private.h"
55#include "MagickCore/list.h"
56#include "MagickCore/magick.h"
57#include "MagickCore/memory_.h"
58#include "MagickCore/monitor.h"
59#include "MagickCore/option.h"
60#include "MagickCore/pixel.h"
61#include "MagickCore/pixel-accessor.h"
cristy380a11c2012-06-02 15:15:22 +000062#include "MagickCore/pixel-private.h"
cristy4c08aed2011-07-01 19:47:50 +000063#include "MagickCore/quantum.h"
64#include "MagickCore/quantum-private.h"
65#include "MagickCore/resource_.h"
66#include "MagickCore/semaphore.h"
67#include "MagickCore/statistic.h"
68#include "MagickCore/stream.h"
69#include "MagickCore/string_.h"
70#include "MagickCore/transform.h"
71#include "MagickCore/utility.h"
72
cristy146a62b2011-10-23 23:40:46 +000073#define LogPixelChannels(image) \
74{ \
75 register ssize_t \
76 i; \
77 \
78 (void) LogMagickEvent(PixelEvent,GetMagickModule(),"%s[%.20g]", \
79 image->filename,(double) image->number_channels); \
80 for (i=0; i < (ssize_t) image->number_channels; i++) \
81 { \
82 char \
83 traits[MaxTextExtent]; \
84 \
85 const char \
cristy46795722011-12-10 23:56:57 +000086 *name; \
87 \
88 PixelChannel \
89 channel; \
cristy146a62b2011-10-23 23:40:46 +000090 \
cristycf1296e2012-08-26 23:40:49 +000091 switch (GetPixelChannelChannel(image,i)) \
cristy146a62b2011-10-23 23:40:46 +000092 { \
93 case RedPixelChannel: \
94 { \
cristy46795722011-12-10 23:56:57 +000095 name="red"; \
cristy146a62b2011-10-23 23:40:46 +000096 if (image->colorspace == CMYKColorspace) \
cristy46795722011-12-10 23:56:57 +000097 name="cyan"; \
cristy146a62b2011-10-23 23:40:46 +000098 if (image->colorspace == GRAYColorspace) \
cristy46795722011-12-10 23:56:57 +000099 name="gray"; \
cristy146a62b2011-10-23 23:40:46 +0000100 break; \
101 } \
102 case GreenPixelChannel: \
103 { \
cristy46795722011-12-10 23:56:57 +0000104 name="green"; \
cristy146a62b2011-10-23 23:40:46 +0000105 if (image->colorspace == CMYKColorspace) \
cristy46795722011-12-10 23:56:57 +0000106 name="magenta"; \
cristy146a62b2011-10-23 23:40:46 +0000107 break; \
108 } \
109 case BluePixelChannel: \
110 { \
cristy46795722011-12-10 23:56:57 +0000111 name="blue"; \
cristy146a62b2011-10-23 23:40:46 +0000112 if (image->colorspace == CMYKColorspace) \
cristy46795722011-12-10 23:56:57 +0000113 name="yellow"; \
cristy146a62b2011-10-23 23:40:46 +0000114 break; \
115 } \
116 case BlackPixelChannel: \
117 { \
cristy46795722011-12-10 23:56:57 +0000118 name="black"; \
cristy146a62b2011-10-23 23:40:46 +0000119 if (image->storage_class == PseudoClass) \
cristy46795722011-12-10 23:56:57 +0000120 name="index"; \
cristy146a62b2011-10-23 23:40:46 +0000121 break; \
122 } \
cristye2a912b2011-12-05 20:02:07 +0000123 case IndexPixelChannel: \
124 { \
cristy46795722011-12-10 23:56:57 +0000125 name="index"; \
cristye2a912b2011-12-05 20:02:07 +0000126 break; \
127 } \
cristy146a62b2011-10-23 23:40:46 +0000128 case AlphaPixelChannel: \
129 { \
cristy46795722011-12-10 23:56:57 +0000130 name="alpha"; \
cristy146a62b2011-10-23 23:40:46 +0000131 break; \
132 } \
cristy883fde12013-04-08 00:50:13 +0000133 case ReadMaskPixelChannel: \
cristy146a62b2011-10-23 23:40:46 +0000134 { \
cristy46795722011-12-10 23:56:57 +0000135 name="mask"; \
cristy146a62b2011-10-23 23:40:46 +0000136 break; \
137 } \
cristye2a912b2011-12-05 20:02:07 +0000138 case MetaPixelChannel: \
cristy146a62b2011-10-23 23:40:46 +0000139 { \
cristy46795722011-12-10 23:56:57 +0000140 name="meta"; \
cristye2a912b2011-12-05 20:02:07 +0000141 break; \
cristy146a62b2011-10-23 23:40:46 +0000142 } \
cristye2a912b2011-12-05 20:02:07 +0000143 default: \
cristy46795722011-12-10 23:56:57 +0000144 name="undefined"; \
cristy146a62b2011-10-23 23:40:46 +0000145 } \
cristycf1296e2012-08-26 23:40:49 +0000146 channel=GetPixelChannelChannel(image,i); \
cristy146a62b2011-10-23 23:40:46 +0000147 *traits='\0'; \
cristycf1296e2012-08-26 23:40:49 +0000148 if ((GetPixelChannelTraits(image,channel) & UpdatePixelTrait) != 0) \
cristy146a62b2011-10-23 23:40:46 +0000149 (void) ConcatenateMagickString(traits,"update,",MaxTextExtent); \
cristycf1296e2012-08-26 23:40:49 +0000150 if ((GetPixelChannelTraits(image,channel) & BlendPixelTrait) != 0) \
cristy146a62b2011-10-23 23:40:46 +0000151 (void) ConcatenateMagickString(traits,"blend,",MaxTextExtent); \
cristycf1296e2012-08-26 23:40:49 +0000152 if ((GetPixelChannelTraits(image,channel) & CopyPixelTrait) != 0) \
cristy146a62b2011-10-23 23:40:46 +0000153 (void) ConcatenateMagickString(traits,"copy,",MaxTextExtent); \
154 if (*traits == '\0') \
155 (void) ConcatenateMagickString(traits,"undefined,",MaxTextExtent); \
156 traits[strlen(traits)-1]='\0'; \
157 (void) LogMagickEvent(PixelEvent,GetMagickModule()," %.20g: %s (%s)", \
cristy46795722011-12-10 23:56:57 +0000158 (double) i,name,traits); \
cristy146a62b2011-10-23 23:40:46 +0000159 } \
160}
161
162/*
cristy4c08aed2011-07-01 19:47:50 +0000163%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
164% %
165% %
166% %
cristyed231572011-07-14 02:18:59 +0000167+ A c q u i r e P i x e l C h a n n e l M a p %
cristy4c08aed2011-07-01 19:47:50 +0000168% %
169% %
170% %
171%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
172%
cristyed231572011-07-14 02:18:59 +0000173% AcquirePixelChannelMap() acquires a pixel component map.
cristy4c08aed2011-07-01 19:47:50 +0000174%
cristyed231572011-07-14 02:18:59 +0000175% The format of the AcquirePixelChannelMap() method is:
cristy4c08aed2011-07-01 19:47:50 +0000176%
cristybd5a96c2011-08-21 00:04:26 +0000177% PixelChannelMap *AcquirePixelChannelMap(void)
cristy4c08aed2011-07-01 19:47:50 +0000178%
179*/
cristybd5a96c2011-08-21 00:04:26 +0000180MagickExport PixelChannelMap *AcquirePixelChannelMap(void)
cristy4c08aed2011-07-01 19:47:50 +0000181{
cristyed231572011-07-14 02:18:59 +0000182 PixelChannelMap
cristybd5a96c2011-08-21 00:04:26 +0000183 *channel_map;
cristy4c08aed2011-07-01 19:47:50 +0000184
185 register ssize_t
186 i;
187
cristybd5a96c2011-08-21 00:04:26 +0000188 channel_map=(PixelChannelMap *) AcquireQuantumMemory(MaxPixelChannels,
189 sizeof(*channel_map));
190 if (channel_map == (PixelChannelMap *) NULL)
cristy4c08aed2011-07-01 19:47:50 +0000191 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
cristybd5a96c2011-08-21 00:04:26 +0000192 (void) ResetMagickMemory(channel_map,0,MaxPixelChannels*sizeof(*channel_map));
193 for (i=0; i < MaxPixelChannels; i++)
194 channel_map[i].channel=(PixelChannel) i;
cristyed231572011-07-14 02:18:59 +0000195 return(channel_map);
cristy4c08aed2011-07-01 19:47:50 +0000196}
197
198/*
199%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
200% %
201% %
202% %
cristyed231572011-07-14 02:18:59 +0000203+ C l o n e P i x e l C h a n n e l M a p %
cristy4c08aed2011-07-01 19:47:50 +0000204% %
205% %
206% %
207%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
208%
cristyed231572011-07-14 02:18:59 +0000209% ClonePixelChannelMap() clones a pixel component map.
cristy4c08aed2011-07-01 19:47:50 +0000210%
cristyed231572011-07-14 02:18:59 +0000211% The format of the ClonePixelChannelMap() method is:
cristy4c08aed2011-07-01 19:47:50 +0000212%
cristybd5a96c2011-08-21 00:04:26 +0000213% PixelChannelMap *ClonePixelChannelMap(PixelChannelMap *channel_map)
cristy4c08aed2011-07-01 19:47:50 +0000214%
215% A description of each parameter follows:
216%
cristyed231572011-07-14 02:18:59 +0000217% o channel_map: the pixel component map.
cristy4c08aed2011-07-01 19:47:50 +0000218%
219*/
cristybd5a96c2011-08-21 00:04:26 +0000220MagickExport PixelChannelMap *ClonePixelChannelMap(PixelChannelMap *channel_map)
cristy4c08aed2011-07-01 19:47:50 +0000221{
cristyed231572011-07-14 02:18:59 +0000222 PixelChannelMap
cristybd5a96c2011-08-21 00:04:26 +0000223 *clone_map;
cristy4c08aed2011-07-01 19:47:50 +0000224
cristybd5a96c2011-08-21 00:04:26 +0000225 assert(channel_map != (PixelChannelMap *) NULL);
cristyed231572011-07-14 02:18:59 +0000226 clone_map=AcquirePixelChannelMap();
cristybd5a96c2011-08-21 00:04:26 +0000227 if (clone_map == (PixelChannelMap *) NULL)
228 return((PixelChannelMap *) NULL);
229 (void) CopyMagickMemory(clone_map,channel_map,MaxPixelChannels*
230 sizeof(*channel_map));
cristy4c08aed2011-07-01 19:47:50 +0000231 return(clone_map);
232}
233
234/*
235%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
236% %
237% %
238% %
239+ C l o n e P i x e l I n f o %
240% %
241% %
242% %
243%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
244%
245% ClonePixelInfo() makes a duplicate of the given pixel info structure, or if
246% pixel info is NULL, a new one.
247%
248% The format of the ClonePixelInfo method is:
249%
250% PixelInfo *ClonePixelInfo(const PixelInfo *pixel_info)
251%
252% A description of each parameter follows:
253%
254% o pixel_info: the pixel info.
255%
256*/
257MagickExport PixelInfo *ClonePixelInfo(const PixelInfo *pixel)
258{
259 PixelInfo
260 *pixel_info;
261
cristya64b85d2011-09-14 01:02:31 +0000262 pixel_info=(PixelInfo *) AcquireQuantumMemory(1,sizeof(*pixel_info));
cristy4c08aed2011-07-01 19:47:50 +0000263 if (pixel_info == (PixelInfo *) NULL)
264 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
265 *pixel_info=(*pixel);
266 return(pixel_info);
267}
268
269/*
270%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
271% %
272% %
273% %
cristyc8aff842012-12-24 16:59:46 +0000274% D e c o d e P i x e l G a m m a %
275% %
276% %
277% %
278%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
279%
280% DecodePixelGamma() applies the expansive power-law nonlinearity to the pixel.
281%
cristy35060592013-04-17 14:10:20 +0000282% The format of the DecodePixelGamma method is:
cristyc8aff842012-12-24 16:59:46 +0000283%
284% double DecodePixelGamma(const MagickRealType pixel)
285%
286% A description of each parameter follows:
287%
288% o pixel: the pixel.
289%
290*/
cristyc29824a2013-04-17 21:52:56 +0000291
292static inline double DecodeGamma(const double x)
293{
294 div_t
295 quotient;
296
297 double
298 p,
299 term[9];
300
301 int
302 exponent;
303
304 static const double coefficient[] = /* terms for x^(7/5), x=1.5 */
305 {
306 1.7917488588043277509,
307 0.82045614371976854984,
308 0.027694100686325412819,
309 -0.00094244335181762134018,
310 0.000064355540911469709545,
311 -5.7224404636060757485e-06,
312 5.8767669437311184313e-07,
313 -6.6139920053589721168e-08,
314 7.9323242696227458163e-09
315 };
316
317 static const double powers_of_two[] = /* (2^x)^(7/5) */
318 {
319 1.0,
320 2.6390158215457883983,
321 6.9644045063689921093,
322 1.8379173679952558018e+01,
323 4.8502930128332728543e+01
324 };
325
326 /*
327 Compute x^2.4 == x*x^(7/5) == pow(x,2.4).
328 */
329 term[0]=1.0;
330 term[1]=4.0*frexp(x,&exponent)-3.0;
331 term[2]=2.0*term[1]*term[1]-term[0];
332 term[3]=2.0*term[1]*term[2]-term[1];
333 term[4]=2.0*term[1]*term[3]-term[2];
334 term[5]=2.0*term[1]*term[4]-term[3];
335 term[6]=2.0*term[1]*term[5]-term[4];
336 term[7]=2.0*term[1]*term[6]-term[5];
337 term[8]=2.0*term[1]*term[7]-term[6];
338 p=coefficient[0]*term[0]+coefficient[1]*term[1]+coefficient[2]*term[2]+
339 coefficient[3]*term[3]+coefficient[4]*term[4]+coefficient[5]*term[5]+
340 coefficient[6]*term[6]+coefficient[7]*term[7]+coefficient[8]*term[8];
341 quotient=div(exponent-1,5);
342 if (quotient.rem < 0)
343 {
344 quotient.quot-=1;
345 quotient.rem+=5;
346 }
347 return(x*ldexp(powers_of_two[quotient.rem]*p,7*quotient.quot));
348}
349
cristyc8aff842012-12-24 16:59:46 +0000350MagickExport MagickRealType DecodePixelGamma(const MagickRealType pixel)
351{
352 if (pixel <= (0.0404482362771076*QuantumRange))
353 return(pixel/12.92f);
cristyc29824a2013-04-17 21:52:56 +0000354 return((MagickRealType) (QuantumRange*DecodeGamma((double) (QuantumScale*
355 pixel+0.055)/1.055)));
cristyc8aff842012-12-24 16:59:46 +0000356}
357
358/*
359%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
360% %
361% %
362% %
cristyed231572011-07-14 02:18:59 +0000363+ 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 +0000364% %
365% %
366% %
367%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
368%
cristyed231572011-07-14 02:18:59 +0000369% DestroyPixelChannelMap() deallocates memory associated with the pixel
370% channel map.
cristy4c08aed2011-07-01 19:47:50 +0000371%
cristyed231572011-07-14 02:18:59 +0000372% The format of the DestroyPixelChannelMap() method is:
cristy4c08aed2011-07-01 19:47:50 +0000373%
cristybd5a96c2011-08-21 00:04:26 +0000374% PixelChannelMap *DestroyPixelChannelMap(PixelChannelMap *channel_map)
cristy4c08aed2011-07-01 19:47:50 +0000375%
376% A description of each parameter follows:
377%
cristyed231572011-07-14 02:18:59 +0000378% o channel_map: the pixel component map.
cristy4c08aed2011-07-01 19:47:50 +0000379%
380*/
cristybd5a96c2011-08-21 00:04:26 +0000381MagickExport PixelChannelMap *DestroyPixelChannelMap(
382 PixelChannelMap *channel_map)
cristy4c08aed2011-07-01 19:47:50 +0000383{
cristybd5a96c2011-08-21 00:04:26 +0000384 assert(channel_map != (PixelChannelMap *) NULL);
385 channel_map=(PixelChannelMap *) RelinquishMagickMemory(channel_map);
386 return((PixelChannelMap *) RelinquishMagickMemory(channel_map));
cristy4c08aed2011-07-01 19:47:50 +0000387}
388
389/*
390%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
391% %
392% %
393% %
cristyc8aff842012-12-24 16:59:46 +0000394+ E n c o d e P i x e l G a m m a %
395% %
396% %
397% %
398%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
399%
400% EncodePixelGamma() cancels any nonlinearity in the pixel.
401%
cristy35060592013-04-17 14:10:20 +0000402% The format of the EncodePixelGamma method is:
cristyc8aff842012-12-24 16:59:46 +0000403%
404% MagickRealType EncodePixelGamma(const double MagickRealType)
405%
406% A description of each parameter follows:
407%
408% o pixel: the pixel.
409%
410*/
cristyc29824a2013-04-17 21:52:56 +0000411
412static inline double EncodeGamma(const double x)
413{
414 div_t
415 quotient;
416
417 double
418 p,
419 term[9];
420
421 int
422 exponent;
423
424 static const double coefficient[] = /* Chebychevi poly: x^(5/12), x=1.5 */
425 {
426 1.1758200232996901923,
427 0.16665763094889061230,
428 -0.0083154894939042125035,
429 0.00075187976780420279038,
430 -0.000083240178519391795367,
431 0.000010229209410070008679,
432 -1.3400466409860246e-06,
433 1.8333422241635376682e-07,
434 -2.5878596761348859722e-08
435 };
436
437 static const double powers_of_two[] = /* (2^N)^(5/12) */
438 {
439 1.0,
440 1.3348398541700343678,
441 1.7817974362806785482,
442 2.3784142300054420538,
443 3.1748021039363991669,
444 4.2378523774371812394,
445 5.6568542494923805819,
446 7.5509945014535482244,
447 1.0079368399158985525e1,
448 1.3454342644059433809e1,
449 1.7959392772949968275e1,
450 2.3972913230026907883e1
451 };
452
453 /*
454 Compute x^(1/2.4) == x^(5/12) == pow(x,1.0/2.4).
455 */
456 term[0]=1.0;
457 term[1]=4.0*frexp(x,&exponent)-3.0;
458 term[2]=2.0*term[1]*term[1]-term[0];
459 term[3]=2.0*term[1]*term[2]-term[1];
460 term[4]=2.0*term[1]*term[3]-term[2];
461 term[5]=2.0*term[1]*term[4]-term[3];
462 term[6]=2.0*term[1]*term[5]-term[4];
463 term[7]=2.0*term[1]*term[6]-term[5];
464 term[8]=2.0*term[1]*term[7]-term[6];
465 p=coefficient[0]*term[0]+coefficient[1]*term[1]+coefficient[2]*term[2]+
466 coefficient[3]*term[3]+coefficient[4]*term[4]+coefficient[5]*term[5]+
467 coefficient[6]*term[6]+coefficient[7]*term[7]+coefficient[8]*term[8];
468 quotient=div(exponent-1,12);
469 if (quotient.rem < 0)
470 {
471 quotient.quot-=1;
472 quotient.rem+=12;
473 }
474 return(ldexp(powers_of_two[quotient.rem]*p,5*quotient.quot));
475}
476
cristyc8aff842012-12-24 16:59:46 +0000477MagickExport MagickRealType EncodePixelGamma(const MagickRealType pixel)
478{
479 if (pixel <= (0.0031306684425005883*QuantumRange))
480 return(12.92f*pixel);
cristyc29824a2013-04-17 21:52:56 +0000481 return((MagickRealType) QuantumRange*(1.055*EncodeGamma((double) QuantumScale*
cristy2a13aa62013-04-18 19:15:28 +0000482 pixel)-0.055));
cristyc8aff842012-12-24 16:59:46 +0000483}
484
485/*
486%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
487% %
488% %
489% %
cristy4c08aed2011-07-01 19:47:50 +0000490% E x p o r t I m a g e P i x e l s %
491% %
492% %
493% %
494%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
495%
496% ExportImagePixels() extracts pixel data from an image and returns it to you.
497% The method returns MagickTrue on success otherwise MagickFalse if an error is
cristyb5a45a32012-01-10 13:31:13 +0000498% encountered. The data is returned as char, short int, Quantum, unsigned int,
cristycafe0412012-01-10 13:29:58 +0000499% unsigned long long, float, or double in the order specified by map.
cristy4c08aed2011-07-01 19:47:50 +0000500%
501% Suppose you want to extract the first scanline of a 640x480 image as
502% character data in red-green-blue order:
503%
504% ExportImagePixels(image,0,0,640,1,"RGB",CharPixel,pixels,exception);
505%
506% The format of the ExportImagePixels method is:
507%
cristycafe0412012-01-10 13:29:58 +0000508% MagickBooleanType ExportImagePixels(const Image *image,const ssize_t x,
509% const ssize_t y,const size_t width,const size_t height,
510% const char *map,const StorageType type,void *pixels,
cristy46f4be22012-01-07 00:26:39 +0000511% ExceptionInfo *exception)
cristy4c08aed2011-07-01 19:47:50 +0000512%
513% A description of each parameter follows:
514%
515% o image: the image.
516%
cristycafe0412012-01-10 13:29:58 +0000517% o x,y,width,height: These values define the perimeter
cristy4c08aed2011-07-01 19:47:50 +0000518% of a region of pixels you want to extract.
519%
520% o map: This string reflects the expected ordering of the pixel array.
521% It can be any combination or order of R = red, G = green, B = blue,
522% A = alpha (0 is transparent), O = opacity (0 is opaque), C = cyan,
523% Y = yellow, M = magenta, K = black, I = intensity (for grayscale),
524% P = pad.
525%
526% o type: Define the data type of the pixels. Float and double types are
527% normalized to [0..1] otherwise [0..QuantumRange]. Choose from these
cristy6c9e1682012-01-07 21:37:44 +0000528% types: CharPixel (char *), DoublePixel (double *), FloatPixel (float *),
cristyff6834e2012-01-10 03:00:25 +0000529% LongPixel (unsigned int *), LongLongPixel (unsigned long long *),
cristy6c9e1682012-01-07 21:37:44 +0000530% QuantumPixel (Quantum *), or ShortPixel (unsigned short *).
cristy4c08aed2011-07-01 19:47:50 +0000531%
532% o pixels: This array of values contain the pixel components as defined by
533% map and type. You must preallocate this array where the expected
534% length varies depending on the values of width, height, map, and type.
535%
536% o exception: return any errors or warnings in this structure.
537%
538*/
cristye5370942012-01-06 03:49:31 +0000539
cristy2dc655d2012-07-05 13:16:28 +0000540static void ExportCharPixel(Image *image,const RectangleInfo *roi,
cristy46f4be22012-01-07 00:26:39 +0000541 const char *restrict map,const QuantumType *quantum_map,void *pixels,
542 ExceptionInfo *exception)
cristye5370942012-01-06 03:49:31 +0000543{
544 register const Quantum
545 *restrict p;
546
547 register ssize_t
548 x;
549
550 register unsigned char
cristy3fe11452012-01-09 01:27:42 +0000551 *restrict q;
cristye5370942012-01-06 03:49:31 +0000552
cristy14d71292012-05-20 16:48:13 +0000553 size_t
554 length;
555
cristye5370942012-01-06 03:49:31 +0000556 ssize_t
557 y;
558
cristy46f4be22012-01-07 00:26:39 +0000559 q=(unsigned char *) pixels;
cristye5370942012-01-06 03:49:31 +0000560 if (LocaleCompare(map,"BGR") == 0)
561 {
cristycafe0412012-01-10 13:29:58 +0000562 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +0000563 {
cristycafe0412012-01-10 13:29:58 +0000564 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +0000565 if (p == (const Quantum *) NULL)
566 break;
cristycafe0412012-01-10 13:29:58 +0000567 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +0000568 {
569 *q++=ScaleQuantumToChar(GetPixelBlue(image,p));
570 *q++=ScaleQuantumToChar(GetPixelGreen(image,p));
571 *q++=ScaleQuantumToChar(GetPixelRed(image,p));
572 p+=GetPixelChannels(image);
573 }
574 }
575 return;
576 }
577 if (LocaleCompare(map,"BGRA") == 0)
578 {
cristycafe0412012-01-10 13:29:58 +0000579 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +0000580 {
cristycafe0412012-01-10 13:29:58 +0000581 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +0000582 if (p == (const Quantum *) NULL)
583 break;
cristycafe0412012-01-10 13:29:58 +0000584 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +0000585 {
586 *q++=ScaleQuantumToChar(GetPixelBlue(image,p));
587 *q++=ScaleQuantumToChar(GetPixelGreen(image,p));
588 *q++=ScaleQuantumToChar(GetPixelRed(image,p));
589 *q++=ScaleQuantumToChar(GetPixelAlpha(image,p));
590 p+=GetPixelChannels(image);
591 }
592 }
593 return;
594 }
595 if (LocaleCompare(map,"BGRP") == 0)
596 {
cristycafe0412012-01-10 13:29:58 +0000597 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +0000598 {
cristycafe0412012-01-10 13:29:58 +0000599 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +0000600 if (p == (const Quantum *) NULL)
601 break;
cristycafe0412012-01-10 13:29:58 +0000602 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +0000603 {
604 *q++=ScaleQuantumToChar(GetPixelBlue(image,p));
605 *q++=ScaleQuantumToChar(GetPixelGreen(image,p));
606 *q++=ScaleQuantumToChar(GetPixelRed(image,p));
607 *q++=ScaleQuantumToChar((Quantum) 0);
608 p+=GetPixelChannels(image);
609 }
610 }
611 return;
612 }
613 if (LocaleCompare(map,"I") == 0)
614 {
cristycafe0412012-01-10 13:29:58 +0000615 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +0000616 {
cristycafe0412012-01-10 13:29:58 +0000617 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +0000618 if (p == (const Quantum *) NULL)
619 break;
cristycafe0412012-01-10 13:29:58 +0000620 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +0000621 {
cristy70e9f682013-03-12 22:31:22 +0000622 *q++=ScaleQuantumToChar(ClampToQuantum(GetPixelIntensity(image,p)));
cristye5370942012-01-06 03:49:31 +0000623 p+=GetPixelChannels(image);
624 }
625 }
626 return;
627 }
628 if (LocaleCompare(map,"RGB") == 0)
629 {
cristycafe0412012-01-10 13:29:58 +0000630 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +0000631 {
cristycafe0412012-01-10 13:29:58 +0000632 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +0000633 if (p == (const Quantum *) NULL)
634 break;
cristycafe0412012-01-10 13:29:58 +0000635 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +0000636 {
637 *q++=ScaleQuantumToChar(GetPixelRed(image,p));
638 *q++=ScaleQuantumToChar(GetPixelGreen(image,p));
639 *q++=ScaleQuantumToChar(GetPixelBlue(image,p));
640 p+=GetPixelChannels(image);
641 }
642 }
643 return;
644 }
645 if (LocaleCompare(map,"RGBA") == 0)
646 {
cristycafe0412012-01-10 13:29:58 +0000647 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +0000648 {
cristycafe0412012-01-10 13:29:58 +0000649 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +0000650 if (p == (const Quantum *) NULL)
651 break;
cristycafe0412012-01-10 13:29:58 +0000652 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +0000653 {
654 *q++=ScaleQuantumToChar(GetPixelRed(image,p));
655 *q++=ScaleQuantumToChar(GetPixelGreen(image,p));
656 *q++=ScaleQuantumToChar(GetPixelBlue(image,p));
657 *q++=ScaleQuantumToChar(GetPixelAlpha(image,p));
658 p+=GetPixelChannels(image);
659 }
660 }
661 return;
662 }
663 if (LocaleCompare(map,"RGBP") == 0)
664 {
cristycafe0412012-01-10 13:29:58 +0000665 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +0000666 {
cristycafe0412012-01-10 13:29:58 +0000667 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +0000668 if (p == (const Quantum *) NULL)
669 break;
cristycafe0412012-01-10 13:29:58 +0000670 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +0000671 {
672 *q++=ScaleQuantumToChar(GetPixelRed(image,p));
673 *q++=ScaleQuantumToChar(GetPixelGreen(image,p));
674 *q++=ScaleQuantumToChar(GetPixelBlue(image,p));
675 *q++=ScaleQuantumToChar((Quantum) 0);
676 p+=GetPixelChannels(image);
677 }
678 }
679 return;
680 }
cristy14d71292012-05-20 16:48:13 +0000681 length=strlen(map);
cristycafe0412012-01-10 13:29:58 +0000682 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +0000683 {
cristycafe0412012-01-10 13:29:58 +0000684 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +0000685 if (p == (const Quantum *) NULL)
686 break;
cristycafe0412012-01-10 13:29:58 +0000687 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +0000688 {
689 register ssize_t
690 i;
691
cristy14d71292012-05-20 16:48:13 +0000692 for (i=0; i < (ssize_t) length; i++)
cristye5370942012-01-06 03:49:31 +0000693 {
694 *q=0;
695 switch (quantum_map[i])
696 {
697 case RedQuantum:
698 case CyanQuantum:
699 {
700 *q=ScaleQuantumToChar(GetPixelRed(image,p));
701 break;
702 }
703 case GreenQuantum:
704 case MagentaQuantum:
705 {
706 *q=ScaleQuantumToChar(GetPixelGreen(image,p));
707 break;
708 }
709 case BlueQuantum:
710 case YellowQuantum:
711 {
712 *q=ScaleQuantumToChar(GetPixelBlue(image,p));
713 break;
714 }
715 case AlphaQuantum:
716 {
717 *q=ScaleQuantumToChar(GetPixelAlpha(image,p));
718 break;
719 }
720 case OpacityQuantum:
721 {
722 *q=ScaleQuantumToChar(GetPixelAlpha(image,p));
723 break;
724 }
725 case BlackQuantum:
726 {
727 if (image->colorspace == CMYKColorspace)
728 *q=ScaleQuantumToChar(GetPixelBlack(image,p));
729 break;
730 }
731 case IndexQuantum:
732 {
cristy70e9f682013-03-12 22:31:22 +0000733 *q=ScaleQuantumToChar(ClampToQuantum(GetPixelIntensity(image,p)));
cristye5370942012-01-06 03:49:31 +0000734 break;
735 }
736 default:
737 break;
738 }
739 q++;
740 }
741 p+=GetPixelChannels(image);
742 }
743 }
744}
745
cristy2dc655d2012-07-05 13:16:28 +0000746static void ExportDoublePixel(Image *image,const RectangleInfo *roi,
cristy46f4be22012-01-07 00:26:39 +0000747 const char *restrict map,const QuantumType *quantum_map,void *pixels,
748 ExceptionInfo *exception)
cristye5370942012-01-06 03:49:31 +0000749{
750 register const Quantum
751 *restrict p;
752
753 register double
cristy3fe11452012-01-09 01:27:42 +0000754 *restrict q;
cristye5370942012-01-06 03:49:31 +0000755
756 register ssize_t
757 x;
758
cristy14d71292012-05-20 16:48:13 +0000759 size_t
760 length;
761
cristye5370942012-01-06 03:49:31 +0000762 ssize_t
763 y;
764
765 q=(double *) pixels;
766 if (LocaleCompare(map,"BGR") == 0)
767 {
cristycafe0412012-01-10 13:29:58 +0000768 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +0000769 {
cristycafe0412012-01-10 13:29:58 +0000770 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +0000771 if (p == (const Quantum *) NULL)
772 break;
cristycafe0412012-01-10 13:29:58 +0000773 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +0000774 {
775 *q++=(double) (QuantumScale*GetPixelBlue(image,p));
776 *q++=(double) (QuantumScale*GetPixelGreen(image,p));
777 *q++=(double) (QuantumScale*GetPixelRed(image,p));
778 p+=GetPixelChannels(image);
779 }
780 }
781 return;
782 }
783 if (LocaleCompare(map,"BGRA") == 0)
784 {
cristycafe0412012-01-10 13:29:58 +0000785 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +0000786 {
cristycafe0412012-01-10 13:29:58 +0000787 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +0000788 if (p == (const Quantum *) NULL)
789 break;
cristycafe0412012-01-10 13:29:58 +0000790 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +0000791 {
792 *q++=(double) (QuantumScale*GetPixelBlue(image,p));
793 *q++=(double) (QuantumScale*GetPixelGreen(image,p));
794 *q++=(double) (QuantumScale*GetPixelRed(image,p));
795 *q++=(double) (QuantumScale*GetPixelAlpha(image,p));
796 p+=GetPixelChannels(image);
797 }
798 }
799 return;
800 }
801 if (LocaleCompare(map,"BGRP") == 0)
802 {
cristycafe0412012-01-10 13:29:58 +0000803 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +0000804 {
cristycafe0412012-01-10 13:29:58 +0000805 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +0000806 if (p == (const Quantum *) NULL)
807 break;
cristycafe0412012-01-10 13:29:58 +0000808 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +0000809 {
810 *q++=(double) (QuantumScale*GetPixelBlue(image,p));
811 *q++=(double) (QuantumScale*GetPixelGreen(image,p));
812 *q++=(double) (QuantumScale*GetPixelRed(image,p));
813 *q++=0.0;
814 p+=GetPixelChannels(image);
815 }
816 }
817 return;
818 }
819 if (LocaleCompare(map,"I") == 0)
820 {
cristycafe0412012-01-10 13:29:58 +0000821 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +0000822 {
cristycafe0412012-01-10 13:29:58 +0000823 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +0000824 if (p == (const Quantum *) NULL)
825 break;
cristycafe0412012-01-10 13:29:58 +0000826 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +0000827 {
828 *q++=(double) (QuantumScale*GetPixelIntensity(image,p));
829 p+=GetPixelChannels(image);
830 }
831 }
832 return;
833 }
834 if (LocaleCompare(map,"RGB") == 0)
835 {
cristycafe0412012-01-10 13:29:58 +0000836 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +0000837 {
cristycafe0412012-01-10 13:29:58 +0000838 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +0000839 if (p == (const Quantum *) NULL)
840 break;
cristycafe0412012-01-10 13:29:58 +0000841 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +0000842 {
843 *q++=(double) (QuantumScale*GetPixelRed(image,p));
844 *q++=(double) (QuantumScale*GetPixelGreen(image,p));
845 *q++=(double) (QuantumScale*GetPixelBlue(image,p));
846 p+=GetPixelChannels(image);
847 }
848 }
849 return;
850 }
851 if (LocaleCompare(map,"RGBA") == 0)
852 {
cristycafe0412012-01-10 13:29:58 +0000853 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +0000854 {
cristycafe0412012-01-10 13:29:58 +0000855 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +0000856 if (p == (const Quantum *) NULL)
857 break;
cristycafe0412012-01-10 13:29:58 +0000858 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +0000859 {
860 *q++=(double) (QuantumScale*GetPixelRed(image,p));
861 *q++=(double) (QuantumScale*GetPixelGreen(image,p));
862 *q++=(double) (QuantumScale*GetPixelBlue(image,p));
863 *q++=(double) (QuantumScale*GetPixelAlpha(image,p));
864 p+=GetPixelChannels(image);
865 }
866 }
867 return;
868 }
869 if (LocaleCompare(map,"RGBP") == 0)
870 {
cristycafe0412012-01-10 13:29:58 +0000871 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +0000872 {
cristycafe0412012-01-10 13:29:58 +0000873 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +0000874 if (p == (const Quantum *) NULL)
875 break;
cristycafe0412012-01-10 13:29:58 +0000876 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +0000877 {
878 *q++=(double) (QuantumScale*GetPixelRed(image,p));
879 *q++=(double) (QuantumScale*GetPixelGreen(image,p));
880 *q++=(double) (QuantumScale*GetPixelBlue(image,p));
881 *q++=0.0;
882 p+=GetPixelChannels(image);
883 }
884 }
885 return;
886 }
cristy14d71292012-05-20 16:48:13 +0000887 length=strlen(map);
cristycafe0412012-01-10 13:29:58 +0000888 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +0000889 {
cristycafe0412012-01-10 13:29:58 +0000890 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +0000891 if (p == (const Quantum *) NULL)
892 break;
cristycafe0412012-01-10 13:29:58 +0000893 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +0000894 {
895 register ssize_t
896 i;
897
cristy14d71292012-05-20 16:48:13 +0000898 for (i=0; i < (ssize_t) length; i++)
cristye5370942012-01-06 03:49:31 +0000899 {
900 *q=0;
901 switch (quantum_map[i])
902 {
903 case RedQuantum:
904 case CyanQuantum:
905 {
906 *q=(double) (QuantumScale*GetPixelRed(image,p));
907 break;
908 }
909 case GreenQuantum:
910 case MagentaQuantum:
911 {
912 *q=(double) (QuantumScale*GetPixelGreen(image,p));
913 break;
914 }
915 case BlueQuantum:
916 case YellowQuantum:
917 {
918 *q=(double) (QuantumScale*GetPixelBlue(image,p));
919 break;
920 }
921 case AlphaQuantum:
922 {
923 *q=(double) (QuantumScale*GetPixelAlpha(image,p));
924 break;
925 }
926 case OpacityQuantum:
927 {
928 *q=(double) (QuantumScale*GetPixelAlpha(image,p));
929 break;
930 }
931 case BlackQuantum:
932 {
933 if (image->colorspace == CMYKColorspace)
934 *q=(double) (QuantumScale*
935 GetPixelBlack(image,p));
936 break;
937 }
938 case IndexQuantum:
939 {
940 *q=(double) (QuantumScale*GetPixelIntensity(image,p));
941 break;
942 }
943 default:
944 *q=0;
945 }
946 q++;
947 }
948 p+=GetPixelChannels(image);
949 }
950 }
951}
952
cristy2dc655d2012-07-05 13:16:28 +0000953static void ExportFloatPixel(Image *image,const RectangleInfo *roi,
cristy46f4be22012-01-07 00:26:39 +0000954 const char *restrict map,const QuantumType *quantum_map,void *pixels,
955 ExceptionInfo *exception)
cristye5370942012-01-06 03:49:31 +0000956{
957 register const Quantum
958 *restrict p;
959
960 register float
cristy3fe11452012-01-09 01:27:42 +0000961 *restrict q;
cristye5370942012-01-06 03:49:31 +0000962
963 register ssize_t
964 x;
965
cristy14d71292012-05-20 16:48:13 +0000966 size_t
967 length;
968
cristye5370942012-01-06 03:49:31 +0000969 ssize_t
970 y;
971
972 q=(float *) pixels;
973 if (LocaleCompare(map,"BGR") == 0)
974 {
cristycafe0412012-01-10 13:29:58 +0000975 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +0000976 {
cristycafe0412012-01-10 13:29:58 +0000977 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +0000978 if (p == (const Quantum *) NULL)
979 break;
cristycafe0412012-01-10 13:29:58 +0000980 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +0000981 {
982 *q++=(float) (QuantumScale*GetPixelBlue(image,p));
983 *q++=(float) (QuantumScale*GetPixelGreen(image,p));
984 *q++=(float) (QuantumScale*GetPixelRed(image,p));
985 p+=GetPixelChannels(image);
986 }
987 }
988 return;
989 }
990 if (LocaleCompare(map,"BGRA") == 0)
991 {
cristycafe0412012-01-10 13:29:58 +0000992 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +0000993 {
cristycafe0412012-01-10 13:29:58 +0000994 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +0000995 if (p == (const Quantum *) NULL)
996 break;
cristycafe0412012-01-10 13:29:58 +0000997 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +0000998 {
999 *q++=(float) (QuantumScale*GetPixelBlue(image,p));
1000 *q++=(float) (QuantumScale*GetPixelGreen(image,p));
1001 *q++=(float) (QuantumScale*GetPixelRed(image,p));
1002 *q++=(float) (QuantumScale*GetPixelAlpha(image,p));
1003 p+=GetPixelChannels(image);
1004 }
1005 }
1006 return;
1007 }
1008 if (LocaleCompare(map,"BGRP") == 0)
1009 {
cristycafe0412012-01-10 13:29:58 +00001010 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00001011 {
cristycafe0412012-01-10 13:29:58 +00001012 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00001013 if (p == (const Quantum *) NULL)
1014 break;
cristycafe0412012-01-10 13:29:58 +00001015 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00001016 {
1017 *q++=(float) (QuantumScale*GetPixelBlue(image,p));
1018 *q++=(float) (QuantumScale*GetPixelGreen(image,p));
1019 *q++=(float) (QuantumScale*GetPixelRed(image,p));
1020 *q++=0.0;
1021 p+=GetPixelChannels(image);
1022 }
1023 }
1024 return;
1025 }
1026 if (LocaleCompare(map,"I") == 0)
1027 {
cristycafe0412012-01-10 13:29:58 +00001028 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00001029 {
cristycafe0412012-01-10 13:29:58 +00001030 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00001031 if (p == (const Quantum *) NULL)
1032 break;
cristycafe0412012-01-10 13:29:58 +00001033 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00001034 {
1035 *q++=(float) (QuantumScale*GetPixelIntensity(image,p));
1036 p+=GetPixelChannels(image);
1037 }
1038 }
1039 return;
1040 }
1041 if (LocaleCompare(map,"RGB") == 0)
1042 {
cristycafe0412012-01-10 13:29:58 +00001043 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00001044 {
cristycafe0412012-01-10 13:29:58 +00001045 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00001046 if (p == (const Quantum *) NULL)
1047 break;
cristycafe0412012-01-10 13:29:58 +00001048 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00001049 {
1050 *q++=(float) (QuantumScale*GetPixelRed(image,p));
1051 *q++=(float) (QuantumScale*GetPixelGreen(image,p));
1052 *q++=(float) (QuantumScale*GetPixelBlue(image,p));
1053 p+=GetPixelChannels(image);
1054 }
1055 }
1056 return;
1057 }
1058 if (LocaleCompare(map,"RGBA") == 0)
1059 {
cristycafe0412012-01-10 13:29:58 +00001060 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00001061 {
cristycafe0412012-01-10 13:29:58 +00001062 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00001063 if (p == (const Quantum *) NULL)
1064 break;
cristycafe0412012-01-10 13:29:58 +00001065 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00001066 {
1067 *q++=(float) (QuantumScale*GetPixelRed(image,p));
1068 *q++=(float) (QuantumScale*GetPixelGreen(image,p));
1069 *q++=(float) (QuantumScale*GetPixelBlue(image,p));
1070 *q++=(float) (QuantumScale*GetPixelAlpha(image,p));
1071 p+=GetPixelChannels(image);
1072 }
1073 }
1074 return;
1075 }
1076 if (LocaleCompare(map,"RGBP") == 0)
1077 {
cristycafe0412012-01-10 13:29:58 +00001078 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00001079 {
cristycafe0412012-01-10 13:29:58 +00001080 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00001081 if (p == (const Quantum *) NULL)
1082 break;
cristycafe0412012-01-10 13:29:58 +00001083 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00001084 {
1085 *q++=(float) (QuantumScale*GetPixelRed(image,p));
1086 *q++=(float) (QuantumScale*GetPixelGreen(image,p));
1087 *q++=(float) (QuantumScale*GetPixelBlue(image,p));
1088 *q++=0.0;
1089 p+=GetPixelChannels(image);
1090 }
1091 }
1092 return;
1093 }
cristy14d71292012-05-20 16:48:13 +00001094 length=strlen(map);
cristycafe0412012-01-10 13:29:58 +00001095 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00001096 {
cristycafe0412012-01-10 13:29:58 +00001097 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00001098 if (p == (const Quantum *) NULL)
1099 break;
cristycafe0412012-01-10 13:29:58 +00001100 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00001101 {
1102 register ssize_t
1103 i;
1104
cristy14d71292012-05-20 16:48:13 +00001105 for (i=0; i < (ssize_t) length; i++)
cristye5370942012-01-06 03:49:31 +00001106 {
1107 *q=0;
1108 switch (quantum_map[i])
1109 {
1110 case RedQuantum:
1111 case CyanQuantum:
1112 {
1113 *q=(float) (QuantumScale*GetPixelRed(image,p));
1114 break;
1115 }
1116 case GreenQuantum:
1117 case MagentaQuantum:
1118 {
1119 *q=(float) (QuantumScale*GetPixelGreen(image,p));
1120 break;
1121 }
1122 case BlueQuantum:
1123 case YellowQuantum:
1124 {
1125 *q=(float) (QuantumScale*GetPixelBlue(image,p));
1126 break;
1127 }
1128 case AlphaQuantum:
1129 {
1130 *q=(float) (QuantumScale*((Quantum) (GetPixelAlpha(image,p))));
1131 break;
1132 }
1133 case OpacityQuantum:
1134 {
1135 *q=(float) (QuantumScale*GetPixelAlpha(image,p));
1136 break;
1137 }
1138 case BlackQuantum:
1139 {
1140 if (image->colorspace == CMYKColorspace)
1141 *q=(float) (QuantumScale* GetPixelBlack(image,p));
1142 break;
1143 }
1144 case IndexQuantum:
1145 {
1146 *q=(float) (QuantumScale*GetPixelIntensity(image,p));
1147 break;
1148 }
1149 default:
1150 *q=0;
1151 }
1152 q++;
1153 }
1154 p+=GetPixelChannels(image);
1155 }
1156 }
1157}
1158
cristy2dc655d2012-07-05 13:16:28 +00001159static void ExportLongPixel(Image *image,const RectangleInfo *roi,
cristy46f4be22012-01-07 00:26:39 +00001160 const char *restrict map,const QuantumType *quantum_map,void *pixels,
1161 ExceptionInfo *exception)
cristye5370942012-01-06 03:49:31 +00001162{
1163 register const Quantum
1164 *restrict p;
1165
1166 register ssize_t
1167 x;
1168
1169 register unsigned int
cristy3fe11452012-01-09 01:27:42 +00001170 *restrict q;
cristye5370942012-01-06 03:49:31 +00001171
cristy14d71292012-05-20 16:48:13 +00001172 size_t
1173 length;
1174
cristye5370942012-01-06 03:49:31 +00001175 ssize_t
1176 y;
1177
1178 q=(unsigned int *) pixels;
1179 if (LocaleCompare(map,"BGR") == 0)
1180 {
cristycafe0412012-01-10 13:29:58 +00001181 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00001182 {
cristycafe0412012-01-10 13:29:58 +00001183 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00001184 if (p == (const Quantum *) NULL)
1185 break;
cristycafe0412012-01-10 13:29:58 +00001186 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00001187 {
cristy6c9e1682012-01-07 21:37:44 +00001188 *q++=ScaleQuantumToLong(GetPixelBlue(image,p));
1189 *q++=ScaleQuantumToLong(GetPixelGreen(image,p));
1190 *q++=ScaleQuantumToLong(GetPixelRed(image,p));
cristye5370942012-01-06 03:49:31 +00001191 p+=GetPixelChannels(image);
1192 }
1193 }
1194 return;
1195 }
1196 if (LocaleCompare(map,"BGRA") == 0)
1197 {
cristycafe0412012-01-10 13:29:58 +00001198 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00001199 {
cristycafe0412012-01-10 13:29:58 +00001200 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00001201 if (p == (const Quantum *) NULL)
1202 break;
cristycafe0412012-01-10 13:29:58 +00001203 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00001204 {
cristy6c9e1682012-01-07 21:37:44 +00001205 *q++=ScaleQuantumToLong(GetPixelBlue(image,p));
1206 *q++=ScaleQuantumToLong(GetPixelGreen(image,p));
1207 *q++=ScaleQuantumToLong(GetPixelRed(image,p));
1208 *q++=ScaleQuantumToLong(GetPixelAlpha(image,p));
cristye5370942012-01-06 03:49:31 +00001209 p+=GetPixelChannels(image);
1210 }
1211 }
1212 return;
1213 }
1214 if (LocaleCompare(map,"BGRP") == 0)
1215 {
cristycafe0412012-01-10 13:29:58 +00001216 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00001217 {
cristycafe0412012-01-10 13:29:58 +00001218 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00001219 if (p == (const Quantum *) NULL)
1220 break;
cristycafe0412012-01-10 13:29:58 +00001221 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00001222 {
cristy6c9e1682012-01-07 21:37:44 +00001223 *q++=ScaleQuantumToLong(GetPixelBlue(image,p));
1224 *q++=ScaleQuantumToLong(GetPixelGreen(image,p));
1225 *q++=ScaleQuantumToLong(GetPixelRed(image,p));
1226 *q++=0;
cristye5370942012-01-06 03:49:31 +00001227 p+=GetPixelChannels(image);
1228 }
1229 }
1230 return;
1231 }
1232 if (LocaleCompare(map,"I") == 0)
1233 {
cristycafe0412012-01-10 13:29:58 +00001234 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00001235 {
cristycafe0412012-01-10 13:29:58 +00001236 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00001237 if (p == (const Quantum *) NULL)
1238 break;
cristycafe0412012-01-10 13:29:58 +00001239 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00001240 {
cristy70e9f682013-03-12 22:31:22 +00001241 *q++=ScaleQuantumToLong(ClampToQuantum(GetPixelIntensity(image,p)));
cristye5370942012-01-06 03:49:31 +00001242 p+=GetPixelChannels(image);
1243 }
1244 }
1245 return;
1246 }
1247 if (LocaleCompare(map,"RGB") == 0)
1248 {
cristycafe0412012-01-10 13:29:58 +00001249 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00001250 {
cristycafe0412012-01-10 13:29:58 +00001251 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00001252 if (p == (const Quantum *) NULL)
1253 break;
cristycafe0412012-01-10 13:29:58 +00001254 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00001255 {
cristy6c9e1682012-01-07 21:37:44 +00001256 *q++=ScaleQuantumToLong(GetPixelRed(image,p));
1257 *q++=ScaleQuantumToLong(GetPixelGreen(image,p));
1258 *q++=ScaleQuantumToLong(GetPixelBlue(image,p));
cristye5370942012-01-06 03:49:31 +00001259 p+=GetPixelChannels(image);
1260 }
1261 }
1262 return;
1263 }
1264 if (LocaleCompare(map,"RGBA") == 0)
1265 {
cristycafe0412012-01-10 13:29:58 +00001266 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00001267 {
cristycafe0412012-01-10 13:29:58 +00001268 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00001269 if (p == (const Quantum *) NULL)
1270 break;
cristycafe0412012-01-10 13:29:58 +00001271 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00001272 {
cristy6c9e1682012-01-07 21:37:44 +00001273 *q++=ScaleQuantumToLong(GetPixelRed(image,p));
1274 *q++=ScaleQuantumToLong(GetPixelGreen(image,p));
1275 *q++=ScaleQuantumToLong(GetPixelBlue(image,p));
1276 *q++=ScaleQuantumToLong(GetPixelAlpha(image,p));
cristye5370942012-01-06 03:49:31 +00001277 p+=GetPixelChannels(image);
1278 }
1279 }
1280 return;
1281 }
1282 if (LocaleCompare(map,"RGBP") == 0)
1283 {
cristycafe0412012-01-10 13:29:58 +00001284 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00001285 {
cristycafe0412012-01-10 13:29:58 +00001286 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00001287 if (p == (const Quantum *) NULL)
1288 break;
cristycafe0412012-01-10 13:29:58 +00001289 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00001290 {
cristy6c9e1682012-01-07 21:37:44 +00001291 *q++=ScaleQuantumToLong(GetPixelRed(image,p));
1292 *q++=ScaleQuantumToLong(GetPixelGreen(image,p));
1293 *q++=ScaleQuantumToLong(GetPixelBlue(image,p));
1294 *q++=0;
cristye5370942012-01-06 03:49:31 +00001295 p+=GetPixelChannels(image);
1296 }
1297 }
1298 return;
1299 }
cristy14d71292012-05-20 16:48:13 +00001300 length=strlen(map);
cristycafe0412012-01-10 13:29:58 +00001301 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00001302 {
cristycafe0412012-01-10 13:29:58 +00001303 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00001304 if (p == (const Quantum *) NULL)
1305 break;
cristycafe0412012-01-10 13:29:58 +00001306 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00001307 {
1308 register ssize_t
1309 i;
1310
cristy14d71292012-05-20 16:48:13 +00001311 for (i=0; i < (ssize_t) length; i++)
cristye5370942012-01-06 03:49:31 +00001312 {
1313 *q=0;
1314 switch (quantum_map[i])
1315 {
1316 case RedQuantum:
1317 case CyanQuantum:
1318 {
cristy6c9e1682012-01-07 21:37:44 +00001319 *q=ScaleQuantumToLong(GetPixelRed(image,p));
cristye5370942012-01-06 03:49:31 +00001320 break;
1321 }
1322 case GreenQuantum:
1323 case MagentaQuantum:
1324 {
cristy6c9e1682012-01-07 21:37:44 +00001325 *q=ScaleQuantumToLong(GetPixelGreen(image,p));
cristye5370942012-01-06 03:49:31 +00001326 break;
1327 }
1328 case BlueQuantum:
1329 case YellowQuantum:
1330 {
cristy6c9e1682012-01-07 21:37:44 +00001331 *q=ScaleQuantumToLong(GetPixelBlue(image,p));
cristye5370942012-01-06 03:49:31 +00001332 break;
1333 }
1334 case AlphaQuantum:
1335 {
cristy6c9e1682012-01-07 21:37:44 +00001336 *q=ScaleQuantumToLong(GetPixelAlpha(image,p));
cristye5370942012-01-06 03:49:31 +00001337 break;
1338 }
1339 case OpacityQuantum:
1340 {
cristy6c9e1682012-01-07 21:37:44 +00001341 *q=ScaleQuantumToLong(GetPixelAlpha(image,p));
cristye5370942012-01-06 03:49:31 +00001342 break;
1343 }
1344 case BlackQuantum:
1345 {
1346 if (image->colorspace == CMYKColorspace)
cristy6c9e1682012-01-07 21:37:44 +00001347 *q=ScaleQuantumToLong(GetPixelBlack(image,p));
cristye5370942012-01-06 03:49:31 +00001348 break;
1349 }
1350 case IndexQuantum:
1351 {
cristy70e9f682013-03-12 22:31:22 +00001352 *q=ScaleQuantumToLong(ClampToQuantum(GetPixelIntensity(image,p)));
cristye5370942012-01-06 03:49:31 +00001353 break;
1354 }
1355 default:
cristy6c9e1682012-01-07 21:37:44 +00001356 break;
cristye5370942012-01-06 03:49:31 +00001357 }
1358 q++;
1359 }
1360 p+=GetPixelChannels(image);
1361 }
1362 }
1363}
1364
cristy2dc655d2012-07-05 13:16:28 +00001365static void ExportLongLongPixel(Image *image,const RectangleInfo *roi,
cristy46f4be22012-01-07 00:26:39 +00001366 const char *restrict map,const QuantumType *quantum_map,void *pixels,
1367 ExceptionInfo *exception)
cristye5370942012-01-06 03:49:31 +00001368{
1369 register const Quantum
1370 *restrict p;
1371
1372 register ssize_t
1373 x;
1374
cristyb13e12a2012-01-06 21:48:27 +00001375 register MagickSizeType
cristy3fe11452012-01-09 01:27:42 +00001376 *restrict q;
cristye5370942012-01-06 03:49:31 +00001377
cristy14d71292012-05-20 16:48:13 +00001378 size_t
1379 length;
1380
cristye5370942012-01-06 03:49:31 +00001381 ssize_t
1382 y;
1383
cristyb13e12a2012-01-06 21:48:27 +00001384 q=(MagickSizeType *) pixels;
cristye5370942012-01-06 03:49:31 +00001385 if (LocaleCompare(map,"BGR") == 0)
1386 {
cristycafe0412012-01-10 13:29:58 +00001387 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00001388 {
cristycafe0412012-01-10 13:29:58 +00001389 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00001390 if (p == (const Quantum *) NULL)
1391 break;
cristycafe0412012-01-10 13:29:58 +00001392 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00001393 {
cristyb13e12a2012-01-06 21:48:27 +00001394 *q++=ScaleQuantumToLongLong(GetPixelBlue(image,p));
1395 *q++=ScaleQuantumToLongLong(GetPixelGreen(image,p));
1396 *q++=ScaleQuantumToLongLong(GetPixelRed(image,p));
cristye5370942012-01-06 03:49:31 +00001397 p+=GetPixelChannels(image);
1398 }
1399 }
1400 return;
1401 }
1402 if (LocaleCompare(map,"BGRA") == 0)
1403 {
cristycafe0412012-01-10 13:29:58 +00001404 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00001405 {
cristycafe0412012-01-10 13:29:58 +00001406 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00001407 if (p == (const Quantum *) NULL)
1408 break;
cristycafe0412012-01-10 13:29:58 +00001409 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00001410 {
cristyb13e12a2012-01-06 21:48:27 +00001411 *q++=ScaleQuantumToLongLong(GetPixelBlue(image,p));
1412 *q++=ScaleQuantumToLongLong(GetPixelGreen(image,p));
1413 *q++=ScaleQuantumToLongLong(GetPixelRed(image,p));
1414 *q++=ScaleQuantumToLongLong(GetPixelAlpha(image,p));
cristye5370942012-01-06 03:49:31 +00001415 p+=GetPixelChannels(image);
1416 }
1417 }
1418 return;
1419 }
1420 if (LocaleCompare(map,"BGRP") == 0)
1421 {
cristycafe0412012-01-10 13:29:58 +00001422 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00001423 {
cristycafe0412012-01-10 13:29:58 +00001424 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00001425 if (p == (const Quantum *) NULL)
1426 break;
cristycafe0412012-01-10 13:29:58 +00001427 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00001428 {
cristyb13e12a2012-01-06 21:48:27 +00001429 *q++=ScaleQuantumToLongLong(GetPixelBlue(image,p));
1430 *q++=ScaleQuantumToLongLong(GetPixelGreen(image,p));
1431 *q++=ScaleQuantumToLongLong(GetPixelRed(image,p));
cristye5370942012-01-06 03:49:31 +00001432 *q++=0;
1433 p+=GetPixelChannels(image);
1434 }
1435 }
1436 return;
1437 }
1438 if (LocaleCompare(map,"I") == 0)
1439 {
cristycafe0412012-01-10 13:29:58 +00001440 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00001441 {
cristycafe0412012-01-10 13:29:58 +00001442 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00001443 if (p == (const Quantum *) NULL)
1444 break;
cristycafe0412012-01-10 13:29:58 +00001445 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00001446 {
cristy70e9f682013-03-12 22:31:22 +00001447 *q++=ScaleQuantumToLongLong(ClampToQuantum(GetPixelIntensity(image,p)));
cristye5370942012-01-06 03:49:31 +00001448 p+=GetPixelChannels(image);
1449 }
1450 }
1451 return;
1452 }
1453 if (LocaleCompare(map,"RGB") == 0)
1454 {
cristycafe0412012-01-10 13:29:58 +00001455 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00001456 {
cristycafe0412012-01-10 13:29:58 +00001457 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00001458 if (p == (const Quantum *) NULL)
1459 break;
cristycafe0412012-01-10 13:29:58 +00001460 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00001461 {
cristyb13e12a2012-01-06 21:48:27 +00001462 *q++=ScaleQuantumToLongLong(GetPixelRed(image,p));
1463 *q++=ScaleQuantumToLongLong(GetPixelGreen(image,p));
1464 *q++=ScaleQuantumToLongLong(GetPixelBlue(image,p));
cristye5370942012-01-06 03:49:31 +00001465 p+=GetPixelChannels(image);
1466 }
1467 }
1468 return;
1469 }
1470 if (LocaleCompare(map,"RGBA") == 0)
1471 {
cristycafe0412012-01-10 13:29:58 +00001472 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00001473 {
cristycafe0412012-01-10 13:29:58 +00001474 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00001475 if (p == (const Quantum *) NULL)
1476 break;
cristycafe0412012-01-10 13:29:58 +00001477 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00001478 {
cristyb13e12a2012-01-06 21:48:27 +00001479 *q++=ScaleQuantumToLongLong(GetPixelRed(image,p));
1480 *q++=ScaleQuantumToLongLong(GetPixelGreen(image,p));
1481 *q++=ScaleQuantumToLongLong(GetPixelBlue(image,p));
1482 *q++=ScaleQuantumToLongLong(GetPixelAlpha(image,p));
cristye5370942012-01-06 03:49:31 +00001483 p+=GetPixelChannels(image);
1484 }
1485 }
1486 return;
1487 }
1488 if (LocaleCompare(map,"RGBP") == 0)
1489 {
cristycafe0412012-01-10 13:29:58 +00001490 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00001491 {
cristycafe0412012-01-10 13:29:58 +00001492 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00001493 if (p == (const Quantum *) NULL)
1494 break;
cristycafe0412012-01-10 13:29:58 +00001495 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00001496 {
cristyb13e12a2012-01-06 21:48:27 +00001497 *q++=ScaleQuantumToLongLong(GetPixelRed(image,p));
1498 *q++=ScaleQuantumToLongLong(GetPixelGreen(image,p));
1499 *q++=ScaleQuantumToLongLong(GetPixelBlue(image,p));
cristye5370942012-01-06 03:49:31 +00001500 *q++=0;
1501 p+=GetPixelChannels(image);
1502 }
1503 }
1504 return;
1505 }
cristy14d71292012-05-20 16:48:13 +00001506 length=strlen(map);
cristycafe0412012-01-10 13:29:58 +00001507 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00001508 {
cristycafe0412012-01-10 13:29:58 +00001509 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00001510 if (p == (const Quantum *) NULL)
1511 break;
cristycafe0412012-01-10 13:29:58 +00001512 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00001513 {
1514 register ssize_t
1515 i;
1516
cristy14d71292012-05-20 16:48:13 +00001517 for (i=0; i < (ssize_t) length; i++)
cristye5370942012-01-06 03:49:31 +00001518 {
1519 *q=0;
1520 switch (quantum_map[i])
1521 {
1522 case RedQuantum:
1523 case CyanQuantum:
1524 {
cristyb13e12a2012-01-06 21:48:27 +00001525 *q=ScaleQuantumToLongLong(GetPixelRed(image,p));
cristye5370942012-01-06 03:49:31 +00001526 break;
1527 }
1528 case GreenQuantum:
1529 case MagentaQuantum:
1530 {
cristyb13e12a2012-01-06 21:48:27 +00001531 *q=ScaleQuantumToLongLong(GetPixelGreen(image,p));
cristye5370942012-01-06 03:49:31 +00001532 break;
1533 }
1534 case BlueQuantum:
1535 case YellowQuantum:
1536 {
cristyb13e12a2012-01-06 21:48:27 +00001537 *q=ScaleQuantumToLongLong(GetPixelBlue(image,p));
cristye5370942012-01-06 03:49:31 +00001538 break;
1539 }
1540 case AlphaQuantum:
1541 {
cristyb13e12a2012-01-06 21:48:27 +00001542 *q=ScaleQuantumToLongLong(GetPixelAlpha(image,p));
cristye5370942012-01-06 03:49:31 +00001543 break;
1544 }
1545 case OpacityQuantum:
1546 {
cristyb13e12a2012-01-06 21:48:27 +00001547 *q=ScaleQuantumToLongLong(GetPixelAlpha(image,p));
cristye5370942012-01-06 03:49:31 +00001548 break;
1549 }
1550 case BlackQuantum:
1551 {
1552 if (image->colorspace == CMYKColorspace)
cristyb13e12a2012-01-06 21:48:27 +00001553 *q=ScaleQuantumToLongLong(GetPixelBlack(image,p));
cristye5370942012-01-06 03:49:31 +00001554 break;
1555 }
1556 case IndexQuantum:
1557 {
cristy70e9f682013-03-12 22:31:22 +00001558 *q=ScaleQuantumToLongLong(ClampToQuantum(GetPixelIntensity(image,p)));
cristye5370942012-01-06 03:49:31 +00001559 break;
1560 }
1561 default:
1562 break;
1563 }
1564 q++;
1565 }
1566 p+=GetPixelChannels(image);
1567 }
1568 }
1569}
1570
cristy2dc655d2012-07-05 13:16:28 +00001571static void ExportQuantumPixel(Image *image,const RectangleInfo *roi,
cristy46f4be22012-01-07 00:26:39 +00001572 const char *restrict map,const QuantumType *quantum_map,void *pixels,
1573 ExceptionInfo *exception)
cristye5370942012-01-06 03:49:31 +00001574{
1575 register const Quantum
1576 *restrict p;
1577
1578 register Quantum
cristy3fe11452012-01-09 01:27:42 +00001579 *restrict q;
cristye5370942012-01-06 03:49:31 +00001580
1581 register ssize_t
1582 x;
1583
cristy14d71292012-05-20 16:48:13 +00001584 size_t
1585 length;
1586
cristye5370942012-01-06 03:49:31 +00001587 ssize_t
1588 y;
1589
1590 q=(Quantum *) pixels;
1591 if (LocaleCompare(map,"BGR") == 0)
1592 {
cristycafe0412012-01-10 13:29:58 +00001593 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00001594 {
cristycafe0412012-01-10 13:29:58 +00001595 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00001596 if (p == (const Quantum *) NULL)
1597 break;
cristycafe0412012-01-10 13:29:58 +00001598 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00001599 {
1600 *q++=GetPixelBlue(image,p);
1601 *q++=GetPixelGreen(image,p);
1602 *q++=GetPixelRed(image,p);
1603 p+=GetPixelChannels(image);
1604 }
1605 }
1606 return;
1607 }
1608 if (LocaleCompare(map,"BGRA") == 0)
1609 {
cristycafe0412012-01-10 13:29:58 +00001610 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00001611 {
cristycafe0412012-01-10 13:29:58 +00001612 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00001613 if (p == (const Quantum *) NULL)
1614 break;
cristycafe0412012-01-10 13:29:58 +00001615 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00001616 {
1617 *q++=GetPixelBlue(image,p);
1618 *q++=GetPixelGreen(image,p);
1619 *q++=GetPixelRed(image,p);
1620 *q++=(Quantum) (GetPixelAlpha(image,p));
1621 p+=GetPixelChannels(image);
1622 }
1623 }
1624 return;
1625 }
1626 if (LocaleCompare(map,"BGRP") == 0)
1627 {
cristycafe0412012-01-10 13:29:58 +00001628 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00001629 {
cristycafe0412012-01-10 13:29:58 +00001630 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00001631 if (p == (const Quantum *) NULL)
1632 break;
cristycafe0412012-01-10 13:29:58 +00001633 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00001634 {
1635 *q++=GetPixelBlue(image,p);
1636 *q++=GetPixelGreen(image,p);
1637 *q++=GetPixelRed(image,p);
1638 *q++=(Quantum) 0;
1639 p+=GetPixelChannels(image);
1640 }
1641 }
1642 return;
1643 }
1644 if (LocaleCompare(map,"I") == 0)
1645 {
cristycafe0412012-01-10 13:29:58 +00001646 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00001647 {
cristycafe0412012-01-10 13:29:58 +00001648 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00001649 if (p == (const Quantum *) NULL)
1650 break;
cristycafe0412012-01-10 13:29:58 +00001651 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00001652 {
cristy70e9f682013-03-12 22:31:22 +00001653 *q++=ClampToQuantum(GetPixelIntensity(image,p));
cristye5370942012-01-06 03:49:31 +00001654 p+=GetPixelChannels(image);
1655 }
1656 }
1657 return;
1658 }
1659 if (LocaleCompare(map,"RGB") == 0)
1660 {
cristycafe0412012-01-10 13:29:58 +00001661 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00001662 {
cristycafe0412012-01-10 13:29:58 +00001663 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00001664 if (p == (const Quantum *) NULL)
1665 break;
cristycafe0412012-01-10 13:29:58 +00001666 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00001667 {
1668 *q++=GetPixelRed(image,p);
1669 *q++=GetPixelGreen(image,p);
1670 *q++=GetPixelBlue(image,p);
1671 p+=GetPixelChannels(image);
1672 }
1673 }
1674 return;
1675 }
1676 if (LocaleCompare(map,"RGBA") == 0)
1677 {
cristycafe0412012-01-10 13:29:58 +00001678 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00001679 {
cristycafe0412012-01-10 13:29:58 +00001680 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00001681 if (p == (const Quantum *) NULL)
1682 break;
cristycafe0412012-01-10 13:29:58 +00001683 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00001684 {
1685 *q++=GetPixelRed(image,p);
1686 *q++=GetPixelGreen(image,p);
1687 *q++=GetPixelBlue(image,p);
1688 *q++=(Quantum) (GetPixelAlpha(image,p));
1689 p+=GetPixelChannels(image);
1690 }
1691 }
1692 return;
1693 }
1694 if (LocaleCompare(map,"RGBP") == 0)
1695 {
cristycafe0412012-01-10 13:29:58 +00001696 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00001697 {
cristycafe0412012-01-10 13:29:58 +00001698 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00001699 if (p == (const Quantum *) NULL)
1700 break;
cristycafe0412012-01-10 13:29:58 +00001701 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00001702 {
1703 *q++=GetPixelRed(image,p);
1704 *q++=GetPixelGreen(image,p);
1705 *q++=GetPixelBlue(image,p);
1706 *q++=(Quantum) 0;
1707 p+=GetPixelChannels(image);
1708 }
1709 }
1710 return;
1711 }
cristy14d71292012-05-20 16:48:13 +00001712 length=strlen(map);
cristycafe0412012-01-10 13:29:58 +00001713 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00001714 {
cristycafe0412012-01-10 13:29:58 +00001715 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00001716 if (p == (const Quantum *) NULL)
1717 break;
cristycafe0412012-01-10 13:29:58 +00001718 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00001719 {
1720 register ssize_t
1721 i;
1722
cristy14d71292012-05-20 16:48:13 +00001723 for (i=0; i < (ssize_t) length; i++)
cristye5370942012-01-06 03:49:31 +00001724 {
1725 *q=(Quantum) 0;
1726 switch (quantum_map[i])
1727 {
1728 case RedQuantum:
1729 case CyanQuantum:
1730 {
1731 *q=GetPixelRed(image,p);
1732 break;
1733 }
1734 case GreenQuantum:
1735 case MagentaQuantum:
1736 {
1737 *q=GetPixelGreen(image,p);
1738 break;
1739 }
1740 case BlueQuantum:
1741 case YellowQuantum:
1742 {
1743 *q=GetPixelBlue(image,p);
1744 break;
1745 }
1746 case AlphaQuantum:
1747 {
1748 *q=GetPixelAlpha(image,p);
1749 break;
1750 }
1751 case OpacityQuantum:
1752 {
1753 *q=GetPixelAlpha(image,p);
1754 break;
1755 }
1756 case BlackQuantum:
1757 {
1758 if (image->colorspace == CMYKColorspace)
1759 *q=GetPixelBlack(image,p);
1760 break;
1761 }
1762 case IndexQuantum:
1763 {
cristy70e9f682013-03-12 22:31:22 +00001764 *q=ClampToQuantum(GetPixelIntensity(image,p));
cristye5370942012-01-06 03:49:31 +00001765 break;
1766 }
1767 default:
1768 {
1769 *q=(Quantum) 0;
1770 break;
1771 }
1772 }
1773 q++;
1774 }
1775 p+=GetPixelChannels(image);
1776 }
1777 }
1778}
1779
cristy2dc655d2012-07-05 13:16:28 +00001780static void ExportShortPixel(Image *image,const RectangleInfo *roi,
cristy46f4be22012-01-07 00:26:39 +00001781 const char *restrict map,const QuantumType *quantum_map,void *pixels,
1782 ExceptionInfo *exception)
cristye5370942012-01-06 03:49:31 +00001783{
1784 register const Quantum
1785 *restrict p;
1786
1787 register ssize_t
1788 x;
1789
cristye5370942012-01-06 03:49:31 +00001790 register unsigned short
cristy3fe11452012-01-09 01:27:42 +00001791 *restrict q;
cristye5370942012-01-06 03:49:31 +00001792
cristy14d71292012-05-20 16:48:13 +00001793 size_t
1794 length;
1795
1796 ssize_t
1797 y;
1798
cristye5370942012-01-06 03:49:31 +00001799 q=(unsigned short *) pixels;
1800 if (LocaleCompare(map,"BGR") == 0)
1801 {
cristycafe0412012-01-10 13:29:58 +00001802 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00001803 {
cristycafe0412012-01-10 13:29:58 +00001804 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00001805 if (p == (const Quantum *) NULL)
1806 break;
cristycafe0412012-01-10 13:29:58 +00001807 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00001808 {
1809 *q++=ScaleQuantumToShort(GetPixelBlue(image,p));
1810 *q++=ScaleQuantumToShort(GetPixelGreen(image,p));
1811 *q++=ScaleQuantumToShort(GetPixelRed(image,p));
1812 p+=GetPixelChannels(image);
1813 }
1814 }
1815 return;
1816 }
1817 if (LocaleCompare(map,"BGRA") == 0)
1818 {
cristycafe0412012-01-10 13:29:58 +00001819 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00001820 {
cristycafe0412012-01-10 13:29:58 +00001821 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00001822 if (p == (const Quantum *) NULL)
1823 break;
cristycafe0412012-01-10 13:29:58 +00001824 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00001825 {
1826 *q++=ScaleQuantumToShort(GetPixelBlue(image,p));
1827 *q++=ScaleQuantumToShort(GetPixelGreen(image,p));
1828 *q++=ScaleQuantumToShort(GetPixelRed(image,p));
1829 *q++=ScaleQuantumToShort(GetPixelAlpha(image,p));
1830 p+=GetPixelChannels(image);
1831 }
1832 }
1833 return;
1834 }
1835 if (LocaleCompare(map,"BGRP") == 0)
1836 {
cristycafe0412012-01-10 13:29:58 +00001837 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00001838 {
cristycafe0412012-01-10 13:29:58 +00001839 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00001840 if (p == (const Quantum *) NULL)
1841 break;
cristycafe0412012-01-10 13:29:58 +00001842 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00001843 {
1844 *q++=ScaleQuantumToShort(GetPixelBlue(image,p));
1845 *q++=ScaleQuantumToShort(GetPixelGreen(image,p));
1846 *q++=ScaleQuantumToShort(GetPixelRed(image,p));
1847 *q++=0;
1848 p+=GetPixelChannels(image);
1849 }
1850 }
1851 return;
1852 }
1853 if (LocaleCompare(map,"I") == 0)
1854 {
cristycafe0412012-01-10 13:29:58 +00001855 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00001856 {
cristycafe0412012-01-10 13:29:58 +00001857 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00001858 if (p == (const Quantum *) NULL)
1859 break;
cristycafe0412012-01-10 13:29:58 +00001860 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00001861 {
cristy70e9f682013-03-12 22:31:22 +00001862 *q++=ScaleQuantumToShort(ClampToQuantum(GetPixelIntensity(image,p)));
cristye5370942012-01-06 03:49:31 +00001863 p+=GetPixelChannels(image);
1864 }
1865 }
1866 return;
1867 }
1868 if (LocaleCompare(map,"RGB") == 0)
1869 {
cristycafe0412012-01-10 13:29:58 +00001870 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00001871 {
cristycafe0412012-01-10 13:29:58 +00001872 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00001873 if (p == (const Quantum *) NULL)
1874 break;
cristycafe0412012-01-10 13:29:58 +00001875 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00001876 {
1877 *q++=ScaleQuantumToShort(GetPixelRed(image,p));
1878 *q++=ScaleQuantumToShort(GetPixelGreen(image,p));
1879 *q++=ScaleQuantumToShort(GetPixelBlue(image,p));
1880 p+=GetPixelChannels(image);
1881 }
1882 }
1883 return;
1884 }
1885 if (LocaleCompare(map,"RGBA") == 0)
1886 {
cristycafe0412012-01-10 13:29:58 +00001887 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00001888 {
cristycafe0412012-01-10 13:29:58 +00001889 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00001890 if (p == (const Quantum *) NULL)
1891 break;
cristycafe0412012-01-10 13:29:58 +00001892 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00001893 {
1894 *q++=ScaleQuantumToShort(GetPixelRed(image,p));
1895 *q++=ScaleQuantumToShort(GetPixelGreen(image,p));
1896 *q++=ScaleQuantumToShort(GetPixelBlue(image,p));
1897 *q++=ScaleQuantumToShort(GetPixelAlpha(image,p));
1898 p+=GetPixelChannels(image);
1899 }
1900 }
1901 return;
1902 }
1903 if (LocaleCompare(map,"RGBP") == 0)
1904 {
cristycafe0412012-01-10 13:29:58 +00001905 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00001906 {
cristycafe0412012-01-10 13:29:58 +00001907 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00001908 if (p == (const Quantum *) NULL)
1909 break;
cristycafe0412012-01-10 13:29:58 +00001910 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00001911 {
1912 *q++=ScaleQuantumToShort(GetPixelRed(image,p));
1913 *q++=ScaleQuantumToShort(GetPixelGreen(image,p));
1914 *q++=ScaleQuantumToShort(GetPixelBlue(image,p));
1915 *q++=0;
1916 p+=GetPixelChannels(image);
1917 }
1918 }
1919 return;
1920 }
cristy14d71292012-05-20 16:48:13 +00001921 length=strlen(map);
cristycafe0412012-01-10 13:29:58 +00001922 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00001923 {
cristycafe0412012-01-10 13:29:58 +00001924 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00001925 if (p == (const Quantum *) NULL)
1926 break;
cristycafe0412012-01-10 13:29:58 +00001927 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00001928 {
1929 register ssize_t
1930 i;
1931
cristy14d71292012-05-20 16:48:13 +00001932 for (i=0; i < (ssize_t) length; i++)
cristye5370942012-01-06 03:49:31 +00001933 {
1934 *q=0;
1935 switch (quantum_map[i])
1936 {
1937 case RedQuantum:
1938 case CyanQuantum:
1939 {
1940 *q=ScaleQuantumToShort(GetPixelRed(image,p));
1941 break;
1942 }
1943 case GreenQuantum:
1944 case MagentaQuantum:
1945 {
1946 *q=ScaleQuantumToShort(GetPixelGreen(image,p));
1947 break;
1948 }
1949 case BlueQuantum:
1950 case YellowQuantum:
1951 {
1952 *q=ScaleQuantumToShort(GetPixelBlue(image,p));
1953 break;
1954 }
1955 case AlphaQuantum:
1956 {
1957 *q=ScaleQuantumToShort(GetPixelAlpha(image,p));
1958 break;
1959 }
1960 case OpacityQuantum:
1961 {
1962 *q=ScaleQuantumToShort(GetPixelAlpha(image,p));
1963 break;
1964 }
1965 case BlackQuantum:
1966 {
1967 if (image->colorspace == CMYKColorspace)
1968 *q=ScaleQuantumToShort(GetPixelBlack(image,p));
1969 break;
1970 }
1971 case IndexQuantum:
1972 {
cristy70e9f682013-03-12 22:31:22 +00001973 *q=ScaleQuantumToShort(ClampToQuantum(GetPixelIntensity(image,p)));
cristye5370942012-01-06 03:49:31 +00001974 break;
1975 }
1976 default:
1977 break;
1978 }
1979 q++;
1980 }
1981 p+=GetPixelChannels(image);
1982 }
1983 }
1984}
1985
cristy2dc655d2012-07-05 13:16:28 +00001986MagickExport MagickBooleanType ExportImagePixels(Image *image,
cristycafe0412012-01-10 13:29:58 +00001987 const ssize_t x,const ssize_t y,const size_t width,const size_t height,
1988 const char *map,const StorageType type,void *pixels,ExceptionInfo *exception)
cristy4c08aed2011-07-01 19:47:50 +00001989{
1990 QuantumType
1991 *quantum_map;
1992
cristycafe0412012-01-10 13:29:58 +00001993 RectangleInfo
1994 roi;
1995
cristy4c08aed2011-07-01 19:47:50 +00001996 register ssize_t
cristye5370942012-01-06 03:49:31 +00001997 i;
cristy4c08aed2011-07-01 19:47:50 +00001998
cristy14d71292012-05-20 16:48:13 +00001999 size_t
2000 length;
2001
cristy4c08aed2011-07-01 19:47:50 +00002002 assert(image != (Image *) NULL);
2003 assert(image->signature == MagickSignature);
2004 if (image->debug != MagickFalse)
2005 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
cristy14d71292012-05-20 16:48:13 +00002006 length=strlen(map);
2007 quantum_map=(QuantumType *) AcquireQuantumMemory(length,sizeof(*quantum_map));
cristy4c08aed2011-07-01 19:47:50 +00002008 if (quantum_map == (QuantumType *) NULL)
2009 {
2010 (void) ThrowMagickException(exception,GetMagickModule(),
cristyefe601c2013-01-05 17:51:12 +00002011 ResourceLimitError,"MemoryAllocationFailed","`%s'",image->filename);
cristy4c08aed2011-07-01 19:47:50 +00002012 return(MagickFalse);
2013 }
cristy14d71292012-05-20 16:48:13 +00002014 for (i=0; i < (ssize_t) length; i++)
cristy4c08aed2011-07-01 19:47:50 +00002015 {
2016 switch (map[i])
2017 {
2018 case 'A':
2019 case 'a':
2020 {
2021 quantum_map[i]=AlphaQuantum;
2022 break;
2023 }
2024 case 'B':
2025 case 'b':
2026 {
2027 quantum_map[i]=BlueQuantum;
2028 break;
2029 }
2030 case 'C':
2031 case 'c':
2032 {
2033 quantum_map[i]=CyanQuantum;
2034 if (image->colorspace == CMYKColorspace)
2035 break;
2036 quantum_map=(QuantumType *) RelinquishMagickMemory(quantum_map);
2037 (void) ThrowMagickException(exception,GetMagickModule(),ImageError,
cristyefe601c2013-01-05 17:51:12 +00002038 "ColorSeparatedImageRequired","`%s'",map);
cristy4c08aed2011-07-01 19:47:50 +00002039 return(MagickFalse);
2040 }
2041 case 'g':
2042 case 'G':
2043 {
2044 quantum_map[i]=GreenQuantum;
2045 break;
2046 }
2047 case 'I':
2048 case 'i':
2049 {
2050 quantum_map[i]=IndexQuantum;
2051 break;
2052 }
2053 case 'K':
2054 case 'k':
2055 {
2056 quantum_map[i]=BlackQuantum;
2057 if (image->colorspace == CMYKColorspace)
2058 break;
2059 quantum_map=(QuantumType *) RelinquishMagickMemory(quantum_map);
2060 (void) ThrowMagickException(exception,GetMagickModule(),ImageError,
cristyefe601c2013-01-05 17:51:12 +00002061 "ColorSeparatedImageRequired","`%s'",map);
cristy4c08aed2011-07-01 19:47:50 +00002062 return(MagickFalse);
2063 }
2064 case 'M':
2065 case 'm':
2066 {
2067 quantum_map[i]=MagentaQuantum;
2068 if (image->colorspace == CMYKColorspace)
2069 break;
2070 quantum_map=(QuantumType *) RelinquishMagickMemory(quantum_map);
2071 (void) ThrowMagickException(exception,GetMagickModule(),ImageError,
cristyefe601c2013-01-05 17:51:12 +00002072 "ColorSeparatedImageRequired","`%s'",map);
cristy4c08aed2011-07-01 19:47:50 +00002073 return(MagickFalse);
2074 }
2075 case 'o':
2076 case 'O':
2077 {
2078 quantum_map[i]=OpacityQuantum;
2079 break;
2080 }
2081 case 'P':
2082 case 'p':
2083 {
2084 quantum_map[i]=UndefinedQuantum;
2085 break;
2086 }
2087 case 'R':
2088 case 'r':
2089 {
2090 quantum_map[i]=RedQuantum;
2091 break;
2092 }
2093 case 'Y':
2094 case 'y':
2095 {
2096 quantum_map[i]=YellowQuantum;
2097 if (image->colorspace == CMYKColorspace)
2098 break;
2099 quantum_map=(QuantumType *) RelinquishMagickMemory(quantum_map);
2100 (void) ThrowMagickException(exception,GetMagickModule(),ImageError,
cristyefe601c2013-01-05 17:51:12 +00002101 "ColorSeparatedImageRequired","`%s'",map);
cristy4c08aed2011-07-01 19:47:50 +00002102 return(MagickFalse);
2103 }
2104 default:
2105 {
2106 quantum_map=(QuantumType *) RelinquishMagickMemory(quantum_map);
2107 (void) ThrowMagickException(exception,GetMagickModule(),OptionError,
cristyefe601c2013-01-05 17:51:12 +00002108 "UnrecognizedPixelMap","`%s'",map);
cristy4c08aed2011-07-01 19:47:50 +00002109 return(MagickFalse);
2110 }
2111 }
2112 }
cristycafe0412012-01-10 13:29:58 +00002113 roi.width=width;
2114 roi.height=height;
2115 roi.x=x;
2116 roi.y=y;
cristy4c08aed2011-07-01 19:47:50 +00002117 switch (type)
2118 {
2119 case CharPixel:
2120 {
cristycafe0412012-01-10 13:29:58 +00002121 ExportCharPixel(image,&roi,map,quantum_map,pixels,exception);
cristy4c08aed2011-07-01 19:47:50 +00002122 break;
2123 }
2124 case DoublePixel:
2125 {
cristycafe0412012-01-10 13:29:58 +00002126 ExportDoublePixel(image,&roi,map,quantum_map,pixels,exception);
cristy4c08aed2011-07-01 19:47:50 +00002127 break;
2128 }
2129 case FloatPixel:
2130 {
cristycafe0412012-01-10 13:29:58 +00002131 ExportFloatPixel(image,&roi,map,quantum_map,pixels,exception);
cristy4c08aed2011-07-01 19:47:50 +00002132 break;
2133 }
cristy4c08aed2011-07-01 19:47:50 +00002134 case LongPixel:
2135 {
cristycafe0412012-01-10 13:29:58 +00002136 ExportLongPixel(image,&roi,map,quantum_map,pixels,exception);
cristy4c08aed2011-07-01 19:47:50 +00002137 break;
2138 }
cristy6c9e1682012-01-07 21:37:44 +00002139 case LongLongPixel:
2140 {
cristycafe0412012-01-10 13:29:58 +00002141 ExportLongLongPixel(image,&roi,map,quantum_map,pixels,exception);
cristy6c9e1682012-01-07 21:37:44 +00002142 break;
2143 }
cristy4c08aed2011-07-01 19:47:50 +00002144 case QuantumPixel:
2145 {
cristycafe0412012-01-10 13:29:58 +00002146 ExportQuantumPixel(image,&roi,map,quantum_map,pixels,exception);
cristy4c08aed2011-07-01 19:47:50 +00002147 break;
2148 }
2149 case ShortPixel:
2150 {
cristycafe0412012-01-10 13:29:58 +00002151 ExportShortPixel(image,&roi,map,quantum_map,pixels,exception);
cristy4c08aed2011-07-01 19:47:50 +00002152 break;
2153 }
2154 default:
2155 {
2156 quantum_map=(QuantumType *) RelinquishMagickMemory(quantum_map);
2157 (void) ThrowMagickException(exception,GetMagickModule(),OptionError,
cristyefe601c2013-01-05 17:51:12 +00002158 "UnrecognizedPixelMap","`%s'",map);
cristy4c08aed2011-07-01 19:47:50 +00002159 break;
2160 }
2161 }
2162 quantum_map=(QuantumType *) RelinquishMagickMemory(quantum_map);
2163 return(MagickTrue);
2164}
2165
2166/*
2167%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2168% %
2169% %
2170% %
cristyaa8634f2011-10-01 13:25:12 +00002171% G e t P i x e l I n f o %
cristy4c08aed2011-07-01 19:47:50 +00002172% %
2173% %
2174% %
2175%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2176%
2177% GetPixelInfo() initializes the PixelInfo structure.
2178%
2179% The format of the GetPixelInfo method is:
2180%
2181% GetPixelInfo(const Image *image,PixelInfo *pixel)
2182%
2183% A description of each parameter follows:
2184%
anthonya322a832013-04-27 06:28:03 +00002185% o image: the image. (optional - may be NULL)
cristy4c08aed2011-07-01 19:47:50 +00002186%
cristy101ab702011-10-13 13:06:32 +00002187% o pixel: Specifies a pointer to a PixelInfo structure.
cristy4c08aed2011-07-01 19:47:50 +00002188%
2189*/
cristyaa8634f2011-10-01 13:25:12 +00002190MagickExport void GetPixelInfo(const Image *image,PixelInfo *pixel)
cristy4c08aed2011-07-01 19:47:50 +00002191{
2192 pixel->storage_class=DirectClass;
cristy7020ae62012-04-18 12:58:34 +00002193 pixel->colorspace=sRGBColorspace;
cristy8a46d822012-08-28 23:32:39 +00002194 pixel->alpha_trait=UndefinedPixelTrait;
cristy4c08aed2011-07-01 19:47:50 +00002195 pixel->fuzz=0.0;
2196 pixel->depth=MAGICKCORE_QUANTUM_DEPTH;
2197 pixel->red=0.0;
2198 pixel->green=0.0;
2199 pixel->blue=0.0;
2200 pixel->black=0.0;
cristya19f1d72012-08-07 18:24:38 +00002201 pixel->alpha=(double) OpaqueAlpha;
cristy4c08aed2011-07-01 19:47:50 +00002202 pixel->index=0.0;
2203 if (image == (const Image *) NULL)
2204 return;
2205 pixel->storage_class=image->storage_class;
2206 pixel->colorspace=image->colorspace;
cristy8a46d822012-08-28 23:32:39 +00002207 pixel->alpha_trait=image->alpha_trait;
cristy4c08aed2011-07-01 19:47:50 +00002208 pixel->depth=image->depth;
2209 pixel->fuzz=image->fuzz;
2210}
2211
2212/*
2213%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2214% %
2215% %
2216% %
cristy9731df72013-03-12 16:31:13 +00002217% G e t P i x e l I n t e n s i t y %
2218% %
2219% %
2220% %
2221%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2222%
cristy0c5c8892013-03-12 16:33:48 +00002223% GetPixelIntensity() returns a single sample intensity value from the red,
cristy70e9f682013-03-12 22:31:22 +00002224% green, and blue components of a pixel based on the selected method:
2225%
cristy2cf5d372013-03-13 12:03:11 +00002226% Rec601Luma 0.298839R' + 0.586811G' + 0.114350B'
2227% Rec601Luminance 0.298839R + 0.586811G + 0.114350B
2228% Rec709Luma 0.21260R' + 0.71520G' + 0.07220B'
2229% Rec709Luminance 0.21260R + 0.71520G + 0.07220B
2230% Brightness max(R, G, B)
2231% Lightness (min(R, G, B) + max(R, G, B)) / 2.0
2232% RMS (R'^2 + G'^2 + B'^2) / 3.0
2233% Average (R' + G' + B') / 3.0
cristy9731df72013-03-12 16:31:13 +00002234%
2235% The format of the GetPixelIntensity method is:
2236%
cristy2cf5d372013-03-13 12:03:11 +00002237% MagickRealType GetPixelIntensity(const Image *image,
2238% const Quantum *pixel)
cristy9731df72013-03-12 16:31:13 +00002239%
2240% A description of each parameter follows:
2241%
2242% o image: the image.
2243%
2244% o pixel: Specifies a pointer to a Quantum structure.
2245%
2246*/
cristy70e9f682013-03-12 22:31:22 +00002247
2248static inline MagickRealType MagickMax(const MagickRealType x,
2249 const MagickRealType y)
2250{
2251 if (x > y)
2252 return(x);
2253 return(y);
2254}
2255
2256static inline MagickRealType MagickMin(const MagickRealType x,
2257 const MagickRealType y)
2258{
2259 if (x < y)
2260 return(x);
2261 return(y);
2262}
2263
cristy9731df72013-03-12 16:31:13 +00002264MagickExport MagickRealType GetPixelIntensity(const Image *restrict image,
2265 const Quantum *restrict pixel)
2266{
2267 MagickRealType
2268 blue,
2269 green,
cristy70e9f682013-03-12 22:31:22 +00002270 red,
2271 intensity;
cristy9731df72013-03-12 16:31:13 +00002272
2273 if (image->colorspace == GRAYColorspace)
cristy592d6bb2013-04-07 15:20:37 +00002274 return((MagickRealType) GetPixelGray(image,pixel));
2275 red=(MagickRealType) GetPixelRed(image,pixel);
2276 green=(MagickRealType) GetPixelGreen(image,pixel);
2277 blue=(MagickRealType) GetPixelBlue(image,pixel);
cristy70e9f682013-03-12 22:31:22 +00002278 switch (image->intensity)
2279 {
cristybf02d732013-03-13 16:28:58 +00002280 case AveragePixelIntensityMethod:
2281 {
2282 intensity=(red+green+blue)/3.0;
2283 break;
2284 }
2285 case BrightnessPixelIntensityMethod:
2286 {
2287 intensity=MagickMax(MagickMax(red,green),blue);
2288 break;
2289 }
2290 case LightnessPixelIntensityMethod:
2291 {
2292 intensity=MagickMin(MagickMin(red,green),blue);
2293 break;
2294 }
cristy462c1ca2013-04-15 10:29:18 +00002295 case MSPixelIntensityMethod:
2296 {
2297 intensity=(MagickRealType) (((double) red*red+green*green+blue*blue)/
2298 (3.0*QuantumRange));
2299 break;
2300 }
cristy70e9f682013-03-12 22:31:22 +00002301 case Rec601LumaPixelIntensityMethod:
cristy70e9f682013-03-12 22:31:22 +00002302 {
cristy9e2436a2013-05-02 20:35:59 +00002303 intensity=0.298839*red+0.586811*green+0.114350*blue;
cristy2cf5d372013-03-13 12:03:11 +00002304 break;
2305 }
2306 case Rec601LuminancePixelIntensityMethod:
2307 {
cristy70e9f682013-03-12 22:31:22 +00002308 if (image->colorspace == sRGBColorspace)
2309 {
2310 red=DecodePixelGamma(red);
2311 green=DecodePixelGamma(green);
2312 blue=DecodePixelGamma(blue);
2313 }
cristy9e2436a2013-05-02 20:35:59 +00002314 intensity=0.298839*red+0.586811*green+0.114350*blue;
cristy70e9f682013-03-12 22:31:22 +00002315 break;
2316 }
2317 case Rec709LumaPixelIntensityMethod:
cristyc94210c2013-05-06 14:09:53 +00002318 default:
cristy70e9f682013-03-12 22:31:22 +00002319 {
cristy2cf5d372013-03-13 12:03:11 +00002320 intensity=0.21260f*red+0.71520f*green+0.07220f*blue;
2321 break;
2322 }
2323 case Rec709LuminancePixelIntensityMethod:
2324 {
cristy70e9f682013-03-12 22:31:22 +00002325 if (image->colorspace == sRGBColorspace)
2326 {
2327 red=DecodePixelGamma(red);
2328 green=DecodePixelGamma(green);
2329 blue=DecodePixelGamma(blue);
2330 }
2331 intensity=0.21260f*red+0.71520f*green+0.07220f*blue;
2332 break;
2333 }
cristy70e9f682013-03-12 22:31:22 +00002334 case RMSPixelIntensityMethod:
2335 {
cristy462c1ca2013-04-15 10:29:18 +00002336 intensity=(MagickRealType) (sqrt((double) red*red+green*green+blue*blue)/
2337 sqrt(3.0));
cristy70e9f682013-03-12 22:31:22 +00002338 break;
2339 }
cristy70e9f682013-03-12 22:31:22 +00002340 }
2341 return(intensity);
cristy9731df72013-03-12 16:31:13 +00002342}
cristy9731df72013-03-12 16:31:13 +00002343
2344/*
2345%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2346% %
2347% %
2348% %
cristy4c08aed2011-07-01 19:47:50 +00002349% I m p o r t I m a g e P i x e l s %
2350% %
2351% %
2352% %
2353%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2354%
2355% ImportImagePixels() accepts pixel data and stores in the image at the
2356% location you specify. The method returns MagickTrue on success otherwise
2357% MagickFalse if an error is encountered. The pixel data can be either char,
cristyb5a45a32012-01-10 13:31:13 +00002358% Quantum, short int, unsigned int, unsigned long long, float, or double in
2359% the order specified by map.
cristy4c08aed2011-07-01 19:47:50 +00002360%
2361% Suppose your want to upload the first scanline of a 640x480 image from
2362% character data in red-green-blue order:
2363%
2364% ImportImagePixels(image,0,0,640,1,"RGB",CharPixel,pixels);
2365%
2366% The format of the ImportImagePixels method is:
2367%
cristycafe0412012-01-10 13:29:58 +00002368% MagickBooleanType ImportImagePixels(Image *image,const ssize_t x,
2369% const ssize_t y,const size_t width,const size_t height,
2370% const char *map,const StorageType type,const void *pixels,
2371% ExceptionInfo *exception)
cristy4c08aed2011-07-01 19:47:50 +00002372%
2373% A description of each parameter follows:
2374%
2375% o image: the image.
2376%
cristycafe0412012-01-10 13:29:58 +00002377% o x,y,width,height: These values define the perimeter
cristy4c08aed2011-07-01 19:47:50 +00002378% of a region of pixels you want to define.
2379%
2380% o map: This string reflects the expected ordering of the pixel array.
2381% It can be any combination or order of R = red, G = green, B = blue,
2382% A = alpha (0 is transparent), O = opacity (0 is opaque), C = cyan,
2383% Y = yellow, M = magenta, K = black, I = intensity (for grayscale),
2384% P = pad.
2385%
2386% o type: Define the data type of the pixels. Float and double types are
2387% normalized to [0..1] otherwise [0..QuantumRange]. Choose from these
cristy6c9e1682012-01-07 21:37:44 +00002388% types: CharPixel (char *), DoublePixel (double *), FloatPixel (float *),
cristyff6834e2012-01-10 03:00:25 +00002389% LongPixel (unsigned int *), LongLongPixel (unsigned long long *),
cristy6c9e1682012-01-07 21:37:44 +00002390% QuantumPixel (Quantum *), or ShortPixel (unsigned short *).
cristy4c08aed2011-07-01 19:47:50 +00002391%
2392% o pixels: This array of values contain the pixel components as defined by
2393% map and type. You must preallocate this array where the expected
2394% length varies depending on the values of width, height, map, and type.
2395%
cristy018f07f2011-09-04 21:15:19 +00002396% o exception: return any errors or warnings in this structure.
2397%
cristy4c08aed2011-07-01 19:47:50 +00002398*/
cristye5370942012-01-06 03:49:31 +00002399
cristycafe0412012-01-10 13:29:58 +00002400static void ImportCharPixel(Image *image,const RectangleInfo *roi,
cristy46f4be22012-01-07 00:26:39 +00002401 const char *restrict map,const QuantumType *quantum_map,const void *pixels,
2402 ExceptionInfo *exception)
cristye5370942012-01-06 03:49:31 +00002403{
2404 register const unsigned char
2405 *restrict p;
2406
2407 register Quantum
cristy3fe11452012-01-09 01:27:42 +00002408 *restrict q;
cristye5370942012-01-06 03:49:31 +00002409
2410 register ssize_t
2411 x;
2412
cristy14d71292012-05-20 16:48:13 +00002413 size_t
2414 length;
2415
cristye5370942012-01-06 03:49:31 +00002416 ssize_t
2417 y;
2418
2419 p=(const unsigned char *) pixels;
2420 if (LocaleCompare(map,"BGR") == 0)
2421 {
cristycafe0412012-01-10 13:29:58 +00002422 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00002423 {
cristycafe0412012-01-10 13:29:58 +00002424 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00002425 if (q == (Quantum *) NULL)
2426 break;
cristycafe0412012-01-10 13:29:58 +00002427 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00002428 {
2429 SetPixelBlue(image,ScaleCharToQuantum(*p++),q);
2430 SetPixelGreen(image,ScaleCharToQuantum(*p++),q);
2431 SetPixelRed(image,ScaleCharToQuantum(*p++),q);
2432 q+=GetPixelChannels(image);
2433 }
2434 if (SyncAuthenticPixels(image,exception) == MagickFalse)
2435 break;
2436 }
2437 return;
2438 }
2439 if (LocaleCompare(map,"BGRA") == 0)
2440 {
cristycafe0412012-01-10 13:29:58 +00002441 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00002442 {
cristycafe0412012-01-10 13:29:58 +00002443 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00002444 if (q == (Quantum *) NULL)
2445 break;
cristycafe0412012-01-10 13:29:58 +00002446 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00002447 {
2448 SetPixelBlue(image,ScaleCharToQuantum(*p++),q);
2449 SetPixelGreen(image,ScaleCharToQuantum(*p++),q);
2450 SetPixelRed(image,ScaleCharToQuantum(*p++),q);
2451 SetPixelAlpha(image,ScaleCharToQuantum(*p++),q);
2452 q+=GetPixelChannels(image);
2453 }
2454 if (SyncAuthenticPixels(image,exception) == MagickFalse)
2455 break;
2456 }
2457 return;
2458 }
2459 if (LocaleCompare(map,"BGRO") == 0)
2460 {
cristycafe0412012-01-10 13:29:58 +00002461 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00002462 {
cristycafe0412012-01-10 13:29:58 +00002463 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00002464 if (q == (Quantum *) NULL)
2465 break;
cristycafe0412012-01-10 13:29:58 +00002466 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00002467 {
2468 SetPixelBlue(image,ScaleCharToQuantum(*p++),q);
2469 SetPixelGreen(image,ScaleCharToQuantum(*p++),q);
2470 SetPixelRed(image,ScaleCharToQuantum(*p++),q);
2471 SetPixelAlpha(image,ScaleCharToQuantum(*p++),q);
2472 q+=GetPixelChannels(image);
2473 }
2474 if (SyncAuthenticPixels(image,exception) == MagickFalse)
2475 break;
2476 }
2477 return;
2478 }
2479 if (LocaleCompare(map,"BGRP") == 0)
2480 {
cristycafe0412012-01-10 13:29:58 +00002481 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00002482 {
cristycafe0412012-01-10 13:29:58 +00002483 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00002484 if (q == (Quantum *) NULL)
2485 break;
cristycafe0412012-01-10 13:29:58 +00002486 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00002487 {
2488 SetPixelBlue(image,ScaleCharToQuantum(*p++),q);
2489 SetPixelGreen(image,ScaleCharToQuantum(*p++),q);
2490 SetPixelRed(image,ScaleCharToQuantum(*p++),q);
2491 p++;
2492 q+=GetPixelChannels(image);
2493 }
2494 if (SyncAuthenticPixels(image,exception) == MagickFalse)
2495 break;
2496 }
2497 return;
2498 }
2499 if (LocaleCompare(map,"I") == 0)
2500 {
cristycafe0412012-01-10 13:29:58 +00002501 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00002502 {
cristycafe0412012-01-10 13:29:58 +00002503 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00002504 if (q == (Quantum *) NULL)
2505 break;
cristycafe0412012-01-10 13:29:58 +00002506 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00002507 {
2508 SetPixelGray(image,ScaleCharToQuantum(*p++),q);
2509 q+=GetPixelChannels(image);
2510 }
2511 if (SyncAuthenticPixels(image,exception) == MagickFalse)
2512 break;
2513 }
2514 return;
2515 }
2516 if (LocaleCompare(map,"RGB") == 0)
2517 {
cristycafe0412012-01-10 13:29:58 +00002518 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00002519 {
cristycafe0412012-01-10 13:29:58 +00002520 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00002521 if (q == (Quantum *) NULL)
2522 break;
cristycafe0412012-01-10 13:29:58 +00002523 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00002524 {
2525 SetPixelRed(image,ScaleCharToQuantum(*p++),q);
2526 SetPixelGreen(image,ScaleCharToQuantum(*p++),q);
2527 SetPixelBlue(image,ScaleCharToQuantum(*p++),q);
2528 q+=GetPixelChannels(image);
2529 }
2530 if (SyncAuthenticPixels(image,exception) == MagickFalse)
2531 break;
2532 }
2533 return;
2534 }
2535 if (LocaleCompare(map,"RGBA") == 0)
2536 {
cristycafe0412012-01-10 13:29:58 +00002537 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00002538 {
cristycafe0412012-01-10 13:29:58 +00002539 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00002540 if (q == (Quantum *) NULL)
2541 break;
cristycafe0412012-01-10 13:29:58 +00002542 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00002543 {
2544 SetPixelRed(image,ScaleCharToQuantum(*p++),q);
2545 SetPixelGreen(image,ScaleCharToQuantum(*p++),q);
2546 SetPixelBlue(image,ScaleCharToQuantum(*p++),q);
2547 SetPixelAlpha(image,ScaleCharToQuantum(*p++),q);
2548 q+=GetPixelChannels(image);
2549 }
2550 if (SyncAuthenticPixels(image,exception) == MagickFalse)
2551 break;
2552 }
2553 return;
2554 }
2555 if (LocaleCompare(map,"RGBO") == 0)
2556 {
cristycafe0412012-01-10 13:29:58 +00002557 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00002558 {
cristycafe0412012-01-10 13:29:58 +00002559 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00002560 if (q == (Quantum *) NULL)
2561 break;
cristycafe0412012-01-10 13:29:58 +00002562 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00002563 {
2564 SetPixelRed(image,ScaleCharToQuantum(*p++),q);
2565 SetPixelGreen(image,ScaleCharToQuantum(*p++),q);
2566 SetPixelBlue(image,ScaleCharToQuantum(*p++),q);
2567 SetPixelAlpha(image,ScaleCharToQuantum(*p++),q);
2568 q+=GetPixelChannels(image);
2569 }
2570 if (SyncAuthenticPixels(image,exception) == MagickFalse)
2571 break;
2572 }
2573 return;
2574 }
2575 if (LocaleCompare(map,"RGBP") == 0)
2576 {
cristycafe0412012-01-10 13:29:58 +00002577 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00002578 {
cristycafe0412012-01-10 13:29:58 +00002579 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00002580 if (q == (Quantum *) NULL)
2581 break;
cristycafe0412012-01-10 13:29:58 +00002582 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00002583 {
2584 SetPixelRed(image,ScaleCharToQuantum(*p++),q);
2585 SetPixelGreen(image,ScaleCharToQuantum(*p++),q);
2586 SetPixelBlue(image,ScaleCharToQuantum(*p++),q);
2587 p++;
2588 q+=GetPixelChannels(image);
2589 }
2590 if (SyncAuthenticPixels(image,exception) == MagickFalse)
2591 break;
2592 }
2593 return;
2594 }
cristy14d71292012-05-20 16:48:13 +00002595 length=strlen(map);
cristycafe0412012-01-10 13:29:58 +00002596 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00002597 {
cristycafe0412012-01-10 13:29:58 +00002598 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00002599 if (q == (Quantum *) NULL)
2600 break;
cristycafe0412012-01-10 13:29:58 +00002601 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00002602 {
2603 register ssize_t
2604 i;
2605
cristy14d71292012-05-20 16:48:13 +00002606 for (i=0; i < (ssize_t) length; i++)
cristye5370942012-01-06 03:49:31 +00002607 {
2608 switch (quantum_map[i])
2609 {
2610 case RedQuantum:
2611 case CyanQuantum:
2612 {
2613 SetPixelRed(image,ScaleCharToQuantum(*p),q);
2614 break;
2615 }
2616 case GreenQuantum:
2617 case MagentaQuantum:
2618 {
2619 SetPixelGreen(image,ScaleCharToQuantum(*p),q);
2620 break;
2621 }
2622 case BlueQuantum:
2623 case YellowQuantum:
2624 {
2625 SetPixelBlue(image,ScaleCharToQuantum(*p),q);
2626 break;
2627 }
2628 case AlphaQuantum:
2629 {
2630 SetPixelAlpha(image,ScaleCharToQuantum(*p),q);
2631 break;
2632 }
2633 case OpacityQuantum:
2634 {
2635 SetPixelAlpha(image,ScaleCharToQuantum(*p),q);
2636 break;
2637 }
2638 case BlackQuantum:
2639 {
2640 SetPixelBlack(image,ScaleCharToQuantum(*p),q);
2641 break;
2642 }
2643 case IndexQuantum:
2644 {
2645 SetPixelGray(image,ScaleCharToQuantum(*p),q);
2646 break;
2647 }
2648 default:
2649 break;
2650 }
2651 p++;
2652 }
2653 q+=GetPixelChannels(image);
2654 }
2655 if (SyncAuthenticPixels(image,exception) == MagickFalse)
2656 break;
2657 }
2658}
2659
cristycafe0412012-01-10 13:29:58 +00002660static void ImportDoublePixel(Image *image,const RectangleInfo *roi,
cristy46f4be22012-01-07 00:26:39 +00002661 const char *restrict map,const QuantumType *quantum_map,const void *pixels,
2662 ExceptionInfo *exception)
cristye5370942012-01-06 03:49:31 +00002663{
2664 register const double
2665 *restrict p;
2666
2667 register Quantum
cristy3fe11452012-01-09 01:27:42 +00002668 *restrict q;
cristye5370942012-01-06 03:49:31 +00002669
2670 register ssize_t
2671 x;
2672
cristy14d71292012-05-20 16:48:13 +00002673 size_t
2674 length;
2675
cristye5370942012-01-06 03:49:31 +00002676 ssize_t
2677 y;
2678
2679 p=(const double *) pixels;
2680 if (LocaleCompare(map,"BGR") == 0)
2681 {
cristycafe0412012-01-10 13:29:58 +00002682 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00002683 {
cristycafe0412012-01-10 13:29:58 +00002684 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00002685 if (q == (Quantum *) NULL)
2686 break;
cristycafe0412012-01-10 13:29:58 +00002687 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00002688 {
cristy8cd03c32012-07-07 18:57:59 +00002689 SetPixelBlue(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002690 p++;
cristy8cd03c32012-07-07 18:57:59 +00002691 SetPixelGreen(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002692 p++;
cristy8cd03c32012-07-07 18:57:59 +00002693 SetPixelRed(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002694 p++;
2695 q+=GetPixelChannels(image);
2696 }
2697 if (SyncAuthenticPixels(image,exception) == MagickFalse)
2698 break;
2699 }
2700 return;
2701 }
2702 if (LocaleCompare(map,"BGRA") == 0)
2703 {
cristycafe0412012-01-10 13:29:58 +00002704 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00002705 {
cristycafe0412012-01-10 13:29:58 +00002706 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00002707 if (q == (Quantum *) NULL)
2708 break;
cristycafe0412012-01-10 13:29:58 +00002709 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00002710 {
cristy8cd03c32012-07-07 18:57:59 +00002711 SetPixelBlue(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002712 p++;
cristy8cd03c32012-07-07 18:57:59 +00002713 SetPixelGreen(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002714 p++;
cristy8cd03c32012-07-07 18:57:59 +00002715 SetPixelRed(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002716 p++;
cristy8cd03c32012-07-07 18:57:59 +00002717 SetPixelAlpha(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002718 p++;
2719 q+=GetPixelChannels(image);
2720 }
2721 if (SyncAuthenticPixels(image,exception) == MagickFalse)
2722 break;
2723 }
2724 return;
2725 }
2726 if (LocaleCompare(map,"BGRP") == 0)
2727 {
cristycafe0412012-01-10 13:29:58 +00002728 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00002729 {
cristycafe0412012-01-10 13:29:58 +00002730 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00002731 if (q == (Quantum *) NULL)
2732 break;
cristycafe0412012-01-10 13:29:58 +00002733 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00002734 {
cristy8cd03c32012-07-07 18:57:59 +00002735 SetPixelBlue(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002736 p++;
cristy8cd03c32012-07-07 18:57:59 +00002737 SetPixelGreen(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002738 p++;
cristy8cd03c32012-07-07 18:57:59 +00002739 SetPixelRed(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002740 p++;
2741 p++;
2742 q+=GetPixelChannels(image);
2743 }
2744 if (SyncAuthenticPixels(image,exception) == MagickFalse)
2745 break;
2746 }
2747 return;
2748 }
2749 if (LocaleCompare(map,"I") == 0)
2750 {
cristycafe0412012-01-10 13:29:58 +00002751 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00002752 {
cristycafe0412012-01-10 13:29:58 +00002753 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00002754 if (q == (Quantum *) NULL)
2755 break;
cristycafe0412012-01-10 13:29:58 +00002756 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00002757 {
cristy8cd03c32012-07-07 18:57:59 +00002758 SetPixelGray(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002759 p++;
2760 q+=GetPixelChannels(image);
2761 }
2762 if (SyncAuthenticPixels(image,exception) == MagickFalse)
2763 break;
2764 }
2765 return;
2766 }
2767 if (LocaleCompare(map,"RGB") == 0)
2768 {
cristycafe0412012-01-10 13:29:58 +00002769 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00002770 {
cristycafe0412012-01-10 13:29:58 +00002771 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00002772 if (q == (Quantum *) NULL)
2773 break;
cristycafe0412012-01-10 13:29:58 +00002774 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00002775 {
cristy8cd03c32012-07-07 18:57:59 +00002776 SetPixelRed(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002777 p++;
cristy8cd03c32012-07-07 18:57:59 +00002778 SetPixelGreen(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002779 p++;
cristy8cd03c32012-07-07 18:57:59 +00002780 SetPixelBlue(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002781 p++;
2782 q+=GetPixelChannels(image);
2783 }
2784 if (SyncAuthenticPixels(image,exception) == MagickFalse)
2785 break;
2786 }
2787 return;
2788 }
2789 if (LocaleCompare(map,"RGBA") == 0)
2790 {
cristycafe0412012-01-10 13:29:58 +00002791 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00002792 {
cristycafe0412012-01-10 13:29:58 +00002793 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00002794 if (q == (Quantum *) NULL)
2795 break;
cristycafe0412012-01-10 13:29:58 +00002796 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00002797 {
cristy8cd03c32012-07-07 18:57:59 +00002798 SetPixelRed(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002799 p++;
cristy8cd03c32012-07-07 18:57:59 +00002800 SetPixelGreen(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002801 p++;
cristy8cd03c32012-07-07 18:57:59 +00002802 SetPixelBlue(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002803 p++;
cristy8cd03c32012-07-07 18:57:59 +00002804 SetPixelAlpha(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002805 p++;
2806 q+=GetPixelChannels(image);
2807 }
2808 if (SyncAuthenticPixels(image,exception) == MagickFalse)
2809 break;
2810 }
2811 return;
2812 }
2813 if (LocaleCompare(map,"RGBP") == 0)
2814 {
cristycafe0412012-01-10 13:29:58 +00002815 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00002816 {
cristycafe0412012-01-10 13:29:58 +00002817 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00002818 if (q == (Quantum *) NULL)
2819 break;
cristycafe0412012-01-10 13:29:58 +00002820 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00002821 {
cristy8cd03c32012-07-07 18:57:59 +00002822 SetPixelRed(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002823 p++;
cristy8cd03c32012-07-07 18:57:59 +00002824 SetPixelGreen(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002825 p++;
cristy8cd03c32012-07-07 18:57:59 +00002826 SetPixelBlue(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002827 p++;
2828 q+=GetPixelChannels(image);
2829 }
2830 if (SyncAuthenticPixels(image,exception) == MagickFalse)
2831 break;
2832 }
2833 return;
2834 }
cristy14d71292012-05-20 16:48:13 +00002835 length=strlen(map);
cristycafe0412012-01-10 13:29:58 +00002836 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00002837 {
cristycafe0412012-01-10 13:29:58 +00002838 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00002839 if (q == (Quantum *) NULL)
2840 break;
cristycafe0412012-01-10 13:29:58 +00002841 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00002842 {
2843 register ssize_t
2844 i;
2845
cristy14d71292012-05-20 16:48:13 +00002846 for (i=0; i < (ssize_t) length; i++)
cristye5370942012-01-06 03:49:31 +00002847 {
2848 switch (quantum_map[i])
2849 {
2850 case RedQuantum:
2851 case CyanQuantum:
2852 {
cristy8cd03c32012-07-07 18:57:59 +00002853 SetPixelRed(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002854 break;
2855 }
2856 case GreenQuantum:
2857 case MagentaQuantum:
2858 {
cristy8cd03c32012-07-07 18:57:59 +00002859 SetPixelGreen(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002860 break;
2861 }
2862 case BlueQuantum:
2863 case YellowQuantum:
2864 {
cristy8cd03c32012-07-07 18:57:59 +00002865 SetPixelBlue(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002866 break;
2867 }
2868 case AlphaQuantum:
2869 {
cristy8cd03c32012-07-07 18:57:59 +00002870 SetPixelAlpha(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002871 break;
2872 }
2873 case OpacityQuantum:
2874 {
cristy8cd03c32012-07-07 18:57:59 +00002875 SetPixelAlpha(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002876 break;
2877 }
2878 case BlackQuantum:
2879 {
cristy8cd03c32012-07-07 18:57:59 +00002880 SetPixelBlack(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002881 break;
2882 }
2883 case IndexQuantum:
2884 {
cristy8cd03c32012-07-07 18:57:59 +00002885 SetPixelGray(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002886 break;
2887 }
2888 default:
2889 break;
2890 }
2891 p++;
2892 }
2893 q+=GetPixelChannels(image);
2894 }
2895 if (SyncAuthenticPixels(image,exception) == MagickFalse)
2896 break;
2897 }
2898}
2899
cristycafe0412012-01-10 13:29:58 +00002900static void ImportFloatPixel(Image *image,const RectangleInfo *roi,
cristy46f4be22012-01-07 00:26:39 +00002901 const char *restrict map,const QuantumType *quantum_map,const void *pixels,
2902 ExceptionInfo *exception)
cristye5370942012-01-06 03:49:31 +00002903{
2904 register const float
2905 *restrict p;
2906
2907 register Quantum
cristy3fe11452012-01-09 01:27:42 +00002908 *restrict q;
cristye5370942012-01-06 03:49:31 +00002909
2910 register ssize_t
2911 x;
2912
cristy14d71292012-05-20 16:48:13 +00002913 size_t
2914 length;
2915
cristye5370942012-01-06 03:49:31 +00002916 ssize_t
2917 y;
2918
2919 p=(const float *) pixels;
2920 if (LocaleCompare(map,"BGR") == 0)
2921 {
cristycafe0412012-01-10 13:29:58 +00002922 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00002923 {
cristycafe0412012-01-10 13:29:58 +00002924 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00002925 if (q == (Quantum *) NULL)
2926 break;
cristycafe0412012-01-10 13:29:58 +00002927 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00002928 {
cristy8cd03c32012-07-07 18:57:59 +00002929 SetPixelBlue(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002930 p++;
cristy8cd03c32012-07-07 18:57:59 +00002931 SetPixelGreen(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002932 p++;
cristy8cd03c32012-07-07 18:57:59 +00002933 SetPixelRed(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002934 p++;
2935 q+=GetPixelChannels(image);
2936 }
2937 if (SyncAuthenticPixels(image,exception) == MagickFalse)
2938 break;
2939 }
2940 return;
2941 }
2942 if (LocaleCompare(map,"BGRA") == 0)
2943 {
cristycafe0412012-01-10 13:29:58 +00002944 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00002945 {
cristycafe0412012-01-10 13:29:58 +00002946 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00002947 if (q == (Quantum *) NULL)
2948 break;
cristycafe0412012-01-10 13:29:58 +00002949 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00002950 {
cristy8cd03c32012-07-07 18:57:59 +00002951 SetPixelBlue(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002952 p++;
cristy8cd03c32012-07-07 18:57:59 +00002953 SetPixelGreen(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002954 p++;
cristy8cd03c32012-07-07 18:57:59 +00002955 SetPixelRed(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002956 p++;
cristy8cd03c32012-07-07 18:57:59 +00002957 SetPixelAlpha(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002958 p++;
2959 q+=GetPixelChannels(image);
2960 }
2961 if (SyncAuthenticPixels(image,exception) == MagickFalse)
2962 break;
2963 }
2964 return;
2965 }
2966 if (LocaleCompare(map,"BGRP") == 0)
2967 {
cristycafe0412012-01-10 13:29:58 +00002968 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00002969 {
cristycafe0412012-01-10 13:29:58 +00002970 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00002971 if (q == (Quantum *) NULL)
2972 break;
cristycafe0412012-01-10 13:29:58 +00002973 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00002974 {
cristy8cd03c32012-07-07 18:57:59 +00002975 SetPixelBlue(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002976 p++;
cristy8cd03c32012-07-07 18:57:59 +00002977 SetPixelGreen(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002978 p++;
cristy8cd03c32012-07-07 18:57:59 +00002979 SetPixelRed(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002980 p++;
2981 p++;
2982 q+=GetPixelChannels(image);
2983 }
2984 if (SyncAuthenticPixels(image,exception) == MagickFalse)
2985 break;
2986 }
2987 return;
2988 }
2989 if (LocaleCompare(map,"I") == 0)
2990 {
cristycafe0412012-01-10 13:29:58 +00002991 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00002992 {
cristycafe0412012-01-10 13:29:58 +00002993 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00002994 if (q == (Quantum *) NULL)
2995 break;
cristycafe0412012-01-10 13:29:58 +00002996 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00002997 {
cristy8cd03c32012-07-07 18:57:59 +00002998 SetPixelGray(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00002999 p++;
3000 q+=GetPixelChannels(image);
3001 }
3002 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3003 break;
3004 }
3005 return;
3006 }
3007 if (LocaleCompare(map,"RGB") == 0)
3008 {
cristycafe0412012-01-10 13:29:58 +00003009 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00003010 {
cristycafe0412012-01-10 13:29:58 +00003011 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00003012 if (q == (Quantum *) NULL)
3013 break;
cristycafe0412012-01-10 13:29:58 +00003014 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00003015 {
cristy8cd03c32012-07-07 18:57:59 +00003016 SetPixelRed(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00003017 p++;
cristy8cd03c32012-07-07 18:57:59 +00003018 SetPixelGreen(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00003019 p++;
cristy8cd03c32012-07-07 18:57:59 +00003020 SetPixelBlue(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00003021 p++;
3022 q+=GetPixelChannels(image);
3023 }
3024 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3025 break;
3026 }
3027 return;
3028 }
3029 if (LocaleCompare(map,"RGBA") == 0)
3030 {
cristycafe0412012-01-10 13:29:58 +00003031 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00003032 {
cristycafe0412012-01-10 13:29:58 +00003033 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00003034 if (q == (Quantum *) NULL)
3035 break;
cristycafe0412012-01-10 13:29:58 +00003036 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00003037 {
cristy8cd03c32012-07-07 18:57:59 +00003038 SetPixelRed(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00003039 p++;
cristy8cd03c32012-07-07 18:57:59 +00003040 SetPixelGreen(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00003041 p++;
cristy8cd03c32012-07-07 18:57:59 +00003042 SetPixelBlue(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00003043 p++;
cristy8cd03c32012-07-07 18:57:59 +00003044 SetPixelAlpha(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00003045 p++;
3046 q+=GetPixelChannels(image);
3047 }
3048 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3049 break;
3050 }
3051 return;
3052 }
3053 if (LocaleCompare(map,"RGBP") == 0)
3054 {
cristycafe0412012-01-10 13:29:58 +00003055 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00003056 {
cristycafe0412012-01-10 13:29:58 +00003057 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00003058 if (q == (Quantum *) NULL)
3059 break;
cristycafe0412012-01-10 13:29:58 +00003060 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00003061 {
cristy8cd03c32012-07-07 18:57:59 +00003062 SetPixelRed(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00003063 p++;
cristy8cd03c32012-07-07 18:57:59 +00003064 SetPixelGreen(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00003065 p++;
cristy8cd03c32012-07-07 18:57:59 +00003066 SetPixelBlue(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00003067 p++;
3068 q+=GetPixelChannels(image);
3069 }
3070 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3071 break;
3072 }
3073 return;
3074 }
cristy14d71292012-05-20 16:48:13 +00003075 length=strlen(map);
cristycafe0412012-01-10 13:29:58 +00003076 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00003077 {
cristycafe0412012-01-10 13:29:58 +00003078 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00003079 if (q == (Quantum *) NULL)
3080 break;
cristycafe0412012-01-10 13:29:58 +00003081 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00003082 {
3083 register ssize_t
3084 i;
3085
cristy14d71292012-05-20 16:48:13 +00003086 for (i=0; i < (ssize_t) length; i++)
cristye5370942012-01-06 03:49:31 +00003087 {
3088 switch (quantum_map[i])
3089 {
3090 case RedQuantum:
3091 case CyanQuantum:
3092 {
cristy8cd03c32012-07-07 18:57:59 +00003093 SetPixelRed(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00003094 break;
3095 }
3096 case GreenQuantum:
3097 case MagentaQuantum:
3098 {
cristy8cd03c32012-07-07 18:57:59 +00003099 SetPixelGreen(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00003100 break;
3101 }
3102 case BlueQuantum:
3103 case YellowQuantum:
3104 {
cristy8cd03c32012-07-07 18:57:59 +00003105 SetPixelBlue(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00003106 break;
3107 }
3108 case AlphaQuantum:
3109 {
cristy8cd03c32012-07-07 18:57:59 +00003110 SetPixelAlpha(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00003111 break;
3112 }
3113 case OpacityQuantum:
3114 {
cristy8cd03c32012-07-07 18:57:59 +00003115 SetPixelAlpha(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00003116 break;
3117 }
3118 case BlackQuantum:
3119 {
cristy8cd03c32012-07-07 18:57:59 +00003120 SetPixelBlack(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00003121 break;
3122 }
3123 case IndexQuantum:
3124 {
cristy8cd03c32012-07-07 18:57:59 +00003125 SetPixelGray(image,ClampToQuantum(QuantumRange*(*p)),q);
cristye5370942012-01-06 03:49:31 +00003126 break;
3127 }
3128 default:
3129 break;
3130 }
3131 p++;
3132 }
3133 q+=GetPixelChannels(image);
3134 }
3135 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3136 break;
3137 }
3138}
3139
cristycafe0412012-01-10 13:29:58 +00003140static void ImportLongPixel(Image *image,const RectangleInfo *roi,
cristy46f4be22012-01-07 00:26:39 +00003141 const char *restrict map,const QuantumType *quantum_map,const void *pixels,
3142 ExceptionInfo *exception)
cristye5370942012-01-06 03:49:31 +00003143{
3144 register const unsigned int
3145 *restrict p;
3146
3147 register Quantum
cristy3fe11452012-01-09 01:27:42 +00003148 *restrict q;
cristye5370942012-01-06 03:49:31 +00003149
3150 register ssize_t
3151 x;
3152
cristy14d71292012-05-20 16:48:13 +00003153 size_t
3154 length;
3155
cristye5370942012-01-06 03:49:31 +00003156 ssize_t
3157 y;
3158
3159 p=(const unsigned int *) pixels;
3160 if (LocaleCompare(map,"BGR") == 0)
3161 {
cristycafe0412012-01-10 13:29:58 +00003162 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00003163 {
cristycafe0412012-01-10 13:29:58 +00003164 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00003165 if (q == (Quantum *) NULL)
3166 break;
cristycafe0412012-01-10 13:29:58 +00003167 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00003168 {
3169 SetPixelBlue(image,ScaleLongToQuantum(*p++),q);
3170 SetPixelGreen(image,ScaleLongToQuantum(*p++),q);
3171 SetPixelRed(image,ScaleLongToQuantum(*p++),q);
3172 q+=GetPixelChannels(image);
3173 }
3174 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3175 break;
3176 }
3177 return;
3178 }
3179 if (LocaleCompare(map,"BGRA") == 0)
3180 {
cristycafe0412012-01-10 13:29:58 +00003181 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00003182 {
cristycafe0412012-01-10 13:29:58 +00003183 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00003184 if (q == (Quantum *) NULL)
3185 break;
cristycafe0412012-01-10 13:29:58 +00003186 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00003187 {
3188 SetPixelBlue(image,ScaleLongToQuantum(*p++),q);
3189 SetPixelGreen(image,ScaleLongToQuantum(*p++),q);
3190 SetPixelRed(image,ScaleLongToQuantum(*p++),q);
3191 SetPixelAlpha(image,ScaleLongToQuantum(*p++),q);
3192 q+=GetPixelChannels(image);
3193 }
3194 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3195 break;
3196 }
3197 return;
3198 }
3199 if (LocaleCompare(map,"BGRP") == 0)
3200 {
cristycafe0412012-01-10 13:29:58 +00003201 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00003202 {
cristycafe0412012-01-10 13:29:58 +00003203 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00003204 if (q == (Quantum *) NULL)
3205 break;
cristycafe0412012-01-10 13:29:58 +00003206 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00003207 {
3208 SetPixelBlue(image,ScaleLongToQuantum(*p++),q);
3209 SetPixelGreen(image,ScaleLongToQuantum(*p++),q);
3210 SetPixelRed(image,ScaleLongToQuantum(*p++),q);
3211 p++;
3212 q+=GetPixelChannels(image);
3213 }
3214 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3215 break;
3216 }
3217 return;
3218 }
3219 if (LocaleCompare(map,"I") == 0)
3220 {
cristycafe0412012-01-10 13:29:58 +00003221 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00003222 {
cristycafe0412012-01-10 13:29:58 +00003223 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00003224 if (q == (Quantum *) NULL)
3225 break;
cristycafe0412012-01-10 13:29:58 +00003226 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00003227 {
3228 SetPixelGray(image,ScaleLongToQuantum(*p++),q);
3229 q+=GetPixelChannels(image);
3230 }
3231 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3232 break;
3233 }
3234 return;
3235 }
3236 if (LocaleCompare(map,"RGB") == 0)
3237 {
cristycafe0412012-01-10 13:29:58 +00003238 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00003239 {
cristycafe0412012-01-10 13:29:58 +00003240 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00003241 if (q == (Quantum *) NULL)
3242 break;
cristycafe0412012-01-10 13:29:58 +00003243 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00003244 {
3245 SetPixelRed(image,ScaleLongToQuantum(*p++),q);
3246 SetPixelGreen(image,ScaleLongToQuantum(*p++),q);
3247 SetPixelBlue(image,ScaleLongToQuantum(*p++),q);
3248 q+=GetPixelChannels(image);
3249 }
3250 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3251 break;
3252 }
3253 return;
3254 }
3255 if (LocaleCompare(map,"RGBA") == 0)
3256 {
cristycafe0412012-01-10 13:29:58 +00003257 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00003258 {
cristycafe0412012-01-10 13:29:58 +00003259 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00003260 if (q == (Quantum *) NULL)
3261 break;
cristycafe0412012-01-10 13:29:58 +00003262 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00003263 {
3264 SetPixelRed(image,ScaleLongToQuantum(*p++),q);
3265 SetPixelGreen(image,ScaleLongToQuantum(*p++),q);
3266 SetPixelBlue(image,ScaleLongToQuantum(*p++),q);
3267 SetPixelAlpha(image,ScaleLongToQuantum(*p++),q);
3268 q+=GetPixelChannels(image);
3269 }
3270 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3271 break;
3272 }
3273 return;
3274 }
3275 if (LocaleCompare(map,"RGBP") == 0)
3276 {
cristycafe0412012-01-10 13:29:58 +00003277 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00003278 {
cristycafe0412012-01-10 13:29:58 +00003279 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00003280 if (q == (Quantum *) NULL)
3281 break;
cristycafe0412012-01-10 13:29:58 +00003282 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00003283 {
3284 SetPixelRed(image,ScaleLongToQuantum(*p++),q);
3285 SetPixelGreen(image,ScaleLongToQuantum(*p++),q);
3286 SetPixelBlue(image,ScaleLongToQuantum(*p++),q);
3287 p++;
3288 q+=GetPixelChannels(image);
3289 }
3290 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3291 break;
3292 }
3293 return;
3294 }
cristy14d71292012-05-20 16:48:13 +00003295 length=strlen(map);
cristycafe0412012-01-10 13:29:58 +00003296 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00003297 {
cristycafe0412012-01-10 13:29:58 +00003298 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00003299 if (q == (Quantum *) NULL)
3300 break;
cristycafe0412012-01-10 13:29:58 +00003301 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00003302 {
3303 register ssize_t
3304 i;
3305
cristy14d71292012-05-20 16:48:13 +00003306 for (i=0; i < (ssize_t) length; i++)
cristye5370942012-01-06 03:49:31 +00003307 {
3308 switch (quantum_map[i])
3309 {
3310 case RedQuantum:
3311 case CyanQuantum:
3312 {
3313 SetPixelRed(image,ScaleLongToQuantum(*p),q);
3314 break;
3315 }
3316 case GreenQuantum:
3317 case MagentaQuantum:
3318 {
3319 SetPixelGreen(image,ScaleLongToQuantum(*p),q);
3320 break;
3321 }
3322 case BlueQuantum:
3323 case YellowQuantum:
3324 {
3325 SetPixelBlue(image,ScaleLongToQuantum(*p),q);
3326 break;
3327 }
3328 case AlphaQuantum:
3329 {
3330 SetPixelAlpha(image,ScaleLongToQuantum(*p),q);
3331 break;
3332 }
3333 case OpacityQuantum:
3334 {
3335 SetPixelAlpha(image,ScaleLongToQuantum(*p),q);
3336 break;
3337 }
3338 case BlackQuantum:
3339 {
3340 SetPixelBlack(image,ScaleLongToQuantum(*p),q);
3341 break;
3342 }
3343 case IndexQuantum:
3344 {
3345 SetPixelGray(image,ScaleLongToQuantum(*p),q);
3346 break;
3347 }
3348 default:
3349 break;
3350 }
3351 p++;
3352 }
3353 q+=GetPixelChannels(image);
3354 }
3355 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3356 break;
3357 }
3358}
3359
cristycafe0412012-01-10 13:29:58 +00003360static void ImportLongLongPixel(Image *image,const RectangleInfo *roi,
cristy46f4be22012-01-07 00:26:39 +00003361 const char *restrict map,const QuantumType *quantum_map,const void *pixels,
3362 ExceptionInfo *exception)
cristye5370942012-01-06 03:49:31 +00003363{
cristyb13e12a2012-01-06 21:48:27 +00003364 register const MagickSizeType
cristye5370942012-01-06 03:49:31 +00003365 *restrict p;
3366
3367 register Quantum
cristy3fe11452012-01-09 01:27:42 +00003368 *restrict q;
cristye5370942012-01-06 03:49:31 +00003369
3370 register ssize_t
3371 x;
3372
cristy14d71292012-05-20 16:48:13 +00003373 size_t
3374 length;
3375
cristye5370942012-01-06 03:49:31 +00003376 ssize_t
3377 y;
3378
cristyb13e12a2012-01-06 21:48:27 +00003379 p=(const MagickSizeType *) pixels;
cristye5370942012-01-06 03:49:31 +00003380 if (LocaleCompare(map,"BGR") == 0)
3381 {
cristycafe0412012-01-10 13:29:58 +00003382 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00003383 {
cristycafe0412012-01-10 13:29:58 +00003384 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00003385 if (q == (Quantum *) NULL)
3386 break;
cristycafe0412012-01-10 13:29:58 +00003387 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00003388 {
cristyb13e12a2012-01-06 21:48:27 +00003389 SetPixelBlue(image,ScaleLongLongToQuantum(*p++),q);
3390 SetPixelGreen(image,ScaleLongLongToQuantum(*p++),q);
3391 SetPixelRed(image,ScaleLongLongToQuantum(*p++),q);
cristye5370942012-01-06 03:49:31 +00003392 q+=GetPixelChannels(image);
3393 }
3394 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3395 break;
3396 }
3397 return;
3398 }
3399 if (LocaleCompare(map,"BGRA") == 0)
3400 {
cristycafe0412012-01-10 13:29:58 +00003401 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00003402 {
cristycafe0412012-01-10 13:29:58 +00003403 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00003404 if (q == (Quantum *) NULL)
3405 break;
cristycafe0412012-01-10 13:29:58 +00003406 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00003407 {
cristyb13e12a2012-01-06 21:48:27 +00003408 SetPixelBlue(image,ScaleLongLongToQuantum(*p++),q);
3409 SetPixelGreen(image,ScaleLongLongToQuantum(*p++),q);
3410 SetPixelRed(image,ScaleLongLongToQuantum(*p++),q);
3411 SetPixelAlpha(image,ScaleLongLongToQuantum(*p++),q);
cristye5370942012-01-06 03:49:31 +00003412 q+=GetPixelChannels(image);
3413 }
3414 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3415 break;
3416 }
3417 return;
3418 }
3419 if (LocaleCompare(map,"BGRP") == 0)
3420 {
cristycafe0412012-01-10 13:29:58 +00003421 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00003422 {
cristycafe0412012-01-10 13:29:58 +00003423 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00003424 if (q == (Quantum *) NULL)
3425 break;
cristycafe0412012-01-10 13:29:58 +00003426 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00003427 {
cristyb13e12a2012-01-06 21:48:27 +00003428 SetPixelBlue(image,ScaleLongLongToQuantum(*p++),q);
3429 SetPixelGreen(image,ScaleLongLongToQuantum(*p++),q);
3430 SetPixelRed(image,ScaleLongLongToQuantum(*p++),q);
cristye5370942012-01-06 03:49:31 +00003431 p++;
3432 q+=GetPixelChannels(image);
3433 }
3434 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3435 break;
3436 }
3437 return;
3438 }
3439 if (LocaleCompare(map,"I") == 0)
3440 {
cristycafe0412012-01-10 13:29:58 +00003441 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00003442 {
cristycafe0412012-01-10 13:29:58 +00003443 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00003444 if (q == (Quantum *) NULL)
3445 break;
cristycafe0412012-01-10 13:29:58 +00003446 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00003447 {
cristyb13e12a2012-01-06 21:48:27 +00003448 SetPixelGray(image,ScaleLongLongToQuantum(*p++),q);
cristye5370942012-01-06 03:49:31 +00003449 q+=GetPixelChannels(image);
3450 }
3451 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3452 break;
3453 }
3454 return;
3455 }
3456 if (LocaleCompare(map,"RGB") == 0)
3457 {
cristycafe0412012-01-10 13:29:58 +00003458 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00003459 {
cristycafe0412012-01-10 13:29:58 +00003460 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00003461 if (q == (Quantum *) NULL)
3462 break;
cristycafe0412012-01-10 13:29:58 +00003463 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00003464 {
cristyb13e12a2012-01-06 21:48:27 +00003465 SetPixelRed(image,ScaleLongLongToQuantum(*p++),q);
3466 SetPixelGreen(image,ScaleLongLongToQuantum(*p++),q);
3467 SetPixelBlue(image,ScaleLongLongToQuantum(*p++),q);
cristye5370942012-01-06 03:49:31 +00003468 q+=GetPixelChannels(image);
3469 }
3470 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3471 break;
3472 }
3473 return;
3474 }
3475 if (LocaleCompare(map,"RGBA") == 0)
3476 {
cristycafe0412012-01-10 13:29:58 +00003477 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00003478 {
cristycafe0412012-01-10 13:29:58 +00003479 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00003480 if (q == (Quantum *) NULL)
3481 break;
cristycafe0412012-01-10 13:29:58 +00003482 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00003483 {
cristyb13e12a2012-01-06 21:48:27 +00003484 SetPixelRed(image,ScaleLongLongToQuantum(*p++),q);
3485 SetPixelGreen(image,ScaleLongLongToQuantum(*p++),q);
3486 SetPixelBlue(image,ScaleLongLongToQuantum(*p++),q);
3487 SetPixelAlpha(image,ScaleLongLongToQuantum(*p++),q);
cristye5370942012-01-06 03:49:31 +00003488 q+=GetPixelChannels(image);
3489 }
3490 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3491 break;
3492 }
3493 return;
3494 }
3495 if (LocaleCompare(map,"RGBP") == 0)
3496 {
cristycafe0412012-01-10 13:29:58 +00003497 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00003498 {
cristycafe0412012-01-10 13:29:58 +00003499 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00003500 if (q == (Quantum *) NULL)
3501 break;
cristycafe0412012-01-10 13:29:58 +00003502 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00003503 {
cristyb13e12a2012-01-06 21:48:27 +00003504 SetPixelRed(image,ScaleLongLongToQuantum(*p++),q);
3505 SetPixelGreen(image,ScaleLongLongToQuantum(*p++),q);
3506 SetPixelBlue(image,ScaleLongLongToQuantum(*p++),q);
cristye5370942012-01-06 03:49:31 +00003507 p++;
3508 q+=GetPixelChannels(image);
3509 }
3510 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3511 break;
3512 }
3513 return;
3514 }
cristy14d71292012-05-20 16:48:13 +00003515 length=strlen(map);
cristycafe0412012-01-10 13:29:58 +00003516 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00003517 {
cristycafe0412012-01-10 13:29:58 +00003518 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00003519 if (q == (Quantum *) NULL)
3520 break;
cristycafe0412012-01-10 13:29:58 +00003521 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00003522 {
3523 register ssize_t
3524 i;
3525
cristy14d71292012-05-20 16:48:13 +00003526 for (i=0; i < (ssize_t) length; i++)
cristye5370942012-01-06 03:49:31 +00003527 {
3528 switch (quantum_map[i])
3529 {
3530 case RedQuantum:
3531 case CyanQuantum:
3532 {
cristyb13e12a2012-01-06 21:48:27 +00003533 SetPixelRed(image,ScaleLongLongToQuantum(*p),q);
cristye5370942012-01-06 03:49:31 +00003534 break;
3535 }
3536 case GreenQuantum:
3537 case MagentaQuantum:
3538 {
cristyb13e12a2012-01-06 21:48:27 +00003539 SetPixelGreen(image,ScaleLongLongToQuantum(*p),q);
cristye5370942012-01-06 03:49:31 +00003540 break;
3541 }
3542 case BlueQuantum:
3543 case YellowQuantum:
3544 {
cristyb13e12a2012-01-06 21:48:27 +00003545 SetPixelBlue(image,ScaleLongLongToQuantum(*p),q);
cristye5370942012-01-06 03:49:31 +00003546 break;
3547 }
3548 case AlphaQuantum:
3549 {
cristyb13e12a2012-01-06 21:48:27 +00003550 SetPixelAlpha(image,ScaleLongLongToQuantum(*p),q);
cristye5370942012-01-06 03:49:31 +00003551 break;
3552 }
3553 case OpacityQuantum:
3554 {
cristyb13e12a2012-01-06 21:48:27 +00003555 SetPixelAlpha(image,ScaleLongLongToQuantum(*p),q);
cristye5370942012-01-06 03:49:31 +00003556 break;
3557 }
3558 case BlackQuantum:
3559 {
cristyb13e12a2012-01-06 21:48:27 +00003560 SetPixelBlack(image,ScaleLongLongToQuantum(*p),q);
cristye5370942012-01-06 03:49:31 +00003561 break;
3562 }
3563 case IndexQuantum:
3564 {
cristyb13e12a2012-01-06 21:48:27 +00003565 SetPixelGray(image,ScaleLongLongToQuantum(*p),q);
cristye5370942012-01-06 03:49:31 +00003566 break;
3567 }
3568 default:
3569 break;
3570 }
3571 p++;
3572 }
3573 q+=GetPixelChannels(image);
3574 }
3575 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3576 break;
3577 }
3578}
3579
cristycafe0412012-01-10 13:29:58 +00003580static void ImportQuantumPixel(Image *image,const RectangleInfo *roi,
cristy46f4be22012-01-07 00:26:39 +00003581 const char *restrict map,const QuantumType *quantum_map,const void *pixels,
3582 ExceptionInfo *exception)
cristye5370942012-01-06 03:49:31 +00003583{
3584 register const Quantum
3585 *restrict p;
3586
3587 register Quantum
cristy3fe11452012-01-09 01:27:42 +00003588 *restrict q;
cristye5370942012-01-06 03:49:31 +00003589
3590 register ssize_t
3591 x;
3592
cristy14d71292012-05-20 16:48:13 +00003593 size_t
3594 length;
3595
cristye5370942012-01-06 03:49:31 +00003596 ssize_t
3597 y;
3598
3599 p=(const Quantum *) pixels;
3600 if (LocaleCompare(map,"BGR") == 0)
3601 {
cristycafe0412012-01-10 13:29:58 +00003602 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00003603 {
cristycafe0412012-01-10 13:29:58 +00003604 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00003605 if (q == (Quantum *) NULL)
3606 break;
cristycafe0412012-01-10 13:29:58 +00003607 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00003608 {
3609 SetPixelBlue(image,*p++,q);
3610 SetPixelGreen(image,*p++,q);
3611 SetPixelRed(image,*p++,q);
3612 q+=GetPixelChannels(image);
3613 }
3614 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3615 break;
3616 }
3617 return;
3618 }
3619 if (LocaleCompare(map,"BGRA") == 0)
3620 {
cristycafe0412012-01-10 13:29:58 +00003621 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00003622 {
cristycafe0412012-01-10 13:29:58 +00003623 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00003624 if (q == (Quantum *) NULL)
3625 break;
cristycafe0412012-01-10 13:29:58 +00003626 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00003627 {
3628 SetPixelBlue(image,*p++,q);
3629 SetPixelGreen(image,*p++,q);
3630 SetPixelRed(image,*p++,q);
3631 SetPixelAlpha(image,*p++,q);
3632 q+=GetPixelChannels(image);
3633 }
3634 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3635 break;
3636 }
3637 return;
3638 }
3639 if (LocaleCompare(map,"BGRP") == 0)
3640 {
cristycafe0412012-01-10 13:29:58 +00003641 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00003642 {
cristycafe0412012-01-10 13:29:58 +00003643 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00003644 if (q == (Quantum *) NULL)
3645 break;
cristycafe0412012-01-10 13:29:58 +00003646 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00003647 {
3648 SetPixelBlue(image,*p++,q);
3649 SetPixelGreen(image,*p++,q);
3650 SetPixelRed(image,*p++,q);
3651 p++;
3652 q+=GetPixelChannels(image);
3653 }
3654 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3655 break;
3656 }
3657 return;
3658 }
3659 if (LocaleCompare(map,"I") == 0)
3660 {
cristycafe0412012-01-10 13:29:58 +00003661 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00003662 {
cristycafe0412012-01-10 13:29:58 +00003663 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00003664 if (q == (Quantum *) NULL)
3665 break;
cristycafe0412012-01-10 13:29:58 +00003666 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00003667 {
3668 SetPixelGray(image,*p++,q);
3669 q+=GetPixelChannels(image);
3670 }
3671 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3672 break;
3673 }
3674 return;
3675 }
3676 if (LocaleCompare(map,"RGB") == 0)
3677 {
cristycafe0412012-01-10 13:29:58 +00003678 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00003679 {
cristycafe0412012-01-10 13:29:58 +00003680 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00003681 if (q == (Quantum *) NULL)
3682 break;
cristycafe0412012-01-10 13:29:58 +00003683 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00003684 {
3685 SetPixelRed(image,*p++,q);
3686 SetPixelGreen(image,*p++,q);
3687 SetPixelBlue(image,*p++,q);
3688 q+=GetPixelChannels(image);
3689 }
3690 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3691 break;
3692 }
3693 return;
3694 }
3695 if (LocaleCompare(map,"RGBA") == 0)
3696 {
cristycafe0412012-01-10 13:29:58 +00003697 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00003698 {
cristycafe0412012-01-10 13:29:58 +00003699 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00003700 if (q == (Quantum *) NULL)
3701 break;
cristycafe0412012-01-10 13:29:58 +00003702 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00003703 {
3704 SetPixelRed(image,*p++,q);
3705 SetPixelGreen(image,*p++,q);
3706 SetPixelBlue(image,*p++,q);
3707 SetPixelAlpha(image,*p++,q);
3708 q+=GetPixelChannels(image);
3709 }
3710 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3711 break;
3712 }
3713 return;
3714 }
3715 if (LocaleCompare(map,"RGBP") == 0)
3716 {
cristycafe0412012-01-10 13:29:58 +00003717 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00003718 {
cristycafe0412012-01-10 13:29:58 +00003719 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00003720 if (q == (Quantum *) NULL)
3721 break;
cristycafe0412012-01-10 13:29:58 +00003722 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00003723 {
3724 SetPixelRed(image,*p++,q);
3725 SetPixelGreen(image,*p++,q);
3726 SetPixelBlue(image,*p++,q);
3727 p++;
3728 q+=GetPixelChannels(image);
3729 }
3730 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3731 break;
3732 }
3733 return;
3734 }
cristy14d71292012-05-20 16:48:13 +00003735 length=strlen(map);
cristycafe0412012-01-10 13:29:58 +00003736 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00003737 {
cristycafe0412012-01-10 13:29:58 +00003738 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00003739 if (q == (Quantum *) NULL)
3740 break;
cristycafe0412012-01-10 13:29:58 +00003741 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00003742 {
3743 register ssize_t
3744 i;
3745
cristy14d71292012-05-20 16:48:13 +00003746 for (i=0; i < (ssize_t) length; i++)
cristye5370942012-01-06 03:49:31 +00003747 {
3748 switch (quantum_map[i])
3749 {
3750 case RedQuantum:
3751 case CyanQuantum:
3752 {
3753 SetPixelRed(image,*p,q);
3754 break;
3755 }
3756 case GreenQuantum:
3757 case MagentaQuantum:
3758 {
3759 SetPixelGreen(image,*p,q);
3760 break;
3761 }
3762 case BlueQuantum:
3763 case YellowQuantum:
3764 {
3765 SetPixelBlue(image,*p,q);
3766 break;
3767 }
3768 case AlphaQuantum:
3769 {
3770 SetPixelAlpha(image,*p,q);
3771 break;
3772 }
3773 case OpacityQuantum:
3774 {
3775 SetPixelAlpha(image,*p,q);
3776 break;
3777 }
3778 case BlackQuantum:
3779 {
3780 SetPixelBlack(image,*p,q);
3781 break;
3782 }
3783 case IndexQuantum:
3784 {
3785 SetPixelGray(image,*p,q);
3786 break;
3787 }
3788 default:
3789 break;
3790 }
3791 p++;
3792 }
3793 q+=GetPixelChannels(image);
3794 }
3795 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3796 break;
3797 }
3798}
3799
cristycafe0412012-01-10 13:29:58 +00003800static void ImportShortPixel(Image *image,const RectangleInfo *roi,
cristy46f4be22012-01-07 00:26:39 +00003801 const char *restrict map,const QuantumType *quantum_map,const void *pixels,
3802 ExceptionInfo *exception)
cristye5370942012-01-06 03:49:31 +00003803{
3804 register const unsigned short
3805 *restrict p;
3806
3807 register Quantum
cristy3fe11452012-01-09 01:27:42 +00003808 *restrict q;
cristye5370942012-01-06 03:49:31 +00003809
3810 register ssize_t
3811 x;
3812
cristy14d71292012-05-20 16:48:13 +00003813 size_t
3814 length;
3815
cristye5370942012-01-06 03:49:31 +00003816 ssize_t
3817 y;
3818
3819 p=(const unsigned short *) pixels;
3820 if (LocaleCompare(map,"BGR") == 0)
3821 {
cristycafe0412012-01-10 13:29:58 +00003822 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00003823 {
cristycafe0412012-01-10 13:29:58 +00003824 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00003825 if (q == (Quantum *) NULL)
3826 break;
cristycafe0412012-01-10 13:29:58 +00003827 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00003828 {
3829 SetPixelBlue(image,ScaleShortToQuantum(*p++),q);
3830 SetPixelGreen(image,ScaleShortToQuantum(*p++),q);
3831 SetPixelRed(image,ScaleShortToQuantum(*p++),q);
3832 q+=GetPixelChannels(image);
3833 }
3834 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3835 break;
3836 }
3837 return;
3838 }
3839 if (LocaleCompare(map,"BGRA") == 0)
3840 {
cristycafe0412012-01-10 13:29:58 +00003841 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00003842 {
cristycafe0412012-01-10 13:29:58 +00003843 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00003844 if (q == (Quantum *) NULL)
3845 break;
cristycafe0412012-01-10 13:29:58 +00003846 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00003847 {
3848 SetPixelBlue(image,ScaleShortToQuantum(*p++),q);
3849 SetPixelGreen(image,ScaleShortToQuantum(*p++),q);
3850 SetPixelRed(image,ScaleShortToQuantum(*p++),q);
3851 SetPixelAlpha(image,ScaleShortToQuantum(*p++),q);
3852 q+=GetPixelChannels(image);
3853 }
3854 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3855 break;
3856 }
3857 return;
3858 }
3859 if (LocaleCompare(map,"BGRP") == 0)
3860 {
cristycafe0412012-01-10 13:29:58 +00003861 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00003862 {
cristycafe0412012-01-10 13:29:58 +00003863 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00003864 if (q == (Quantum *) NULL)
3865 break;
cristycafe0412012-01-10 13:29:58 +00003866 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00003867 {
3868 SetPixelBlue(image,ScaleShortToQuantum(*p++),q);
3869 SetPixelGreen(image,ScaleShortToQuantum(*p++),q);
3870 SetPixelRed(image,ScaleShortToQuantum(*p++),q);
3871 p++;
3872 q+=GetPixelChannels(image);
3873 }
3874 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3875 break;
3876 }
3877 return;
3878 }
3879 if (LocaleCompare(map,"I") == 0)
3880 {
cristycafe0412012-01-10 13:29:58 +00003881 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00003882 {
cristycafe0412012-01-10 13:29:58 +00003883 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00003884 if (q == (Quantum *) NULL)
3885 break;
cristycafe0412012-01-10 13:29:58 +00003886 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00003887 {
3888 SetPixelGray(image,ScaleShortToQuantum(*p++),q);
3889 q+=GetPixelChannels(image);
3890 }
3891 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3892 break;
3893 }
3894 return;
3895 }
3896 if (LocaleCompare(map,"RGB") == 0)
3897 {
cristycafe0412012-01-10 13:29:58 +00003898 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00003899 {
cristycafe0412012-01-10 13:29:58 +00003900 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00003901 if (q == (Quantum *) NULL)
3902 break;
cristycafe0412012-01-10 13:29:58 +00003903 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00003904 {
3905 SetPixelRed(image,ScaleShortToQuantum(*p++),q);
3906 SetPixelGreen(image,ScaleShortToQuantum(*p++),q);
3907 SetPixelBlue(image,ScaleShortToQuantum(*p++),q);
3908 q+=GetPixelChannels(image);
3909 }
3910 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3911 break;
3912 }
3913 return;
3914 }
3915 if (LocaleCompare(map,"RGBA") == 0)
3916 {
cristycafe0412012-01-10 13:29:58 +00003917 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00003918 {
cristycafe0412012-01-10 13:29:58 +00003919 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00003920 if (q == (Quantum *) NULL)
3921 break;
cristycafe0412012-01-10 13:29:58 +00003922 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00003923 {
3924 SetPixelRed(image,ScaleShortToQuantum(*p++),q);
3925 SetPixelGreen(image,ScaleShortToQuantum(*p++),q);
3926 SetPixelBlue(image,ScaleShortToQuantum(*p++),q);
3927 SetPixelAlpha(image,ScaleShortToQuantum(*p++),q);
3928 q+=GetPixelChannels(image);
3929 }
3930 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3931 break;
3932 }
3933 return;
3934 }
3935 if (LocaleCompare(map,"RGBP") == 0)
3936 {
cristycafe0412012-01-10 13:29:58 +00003937 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00003938 {
cristycafe0412012-01-10 13:29:58 +00003939 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00003940 if (q == (Quantum *) NULL)
3941 break;
cristycafe0412012-01-10 13:29:58 +00003942 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00003943 {
3944 SetPixelRed(image,ScaleShortToQuantum(*p++),q);
3945 SetPixelGreen(image,ScaleShortToQuantum(*p++),q);
3946 SetPixelBlue(image,ScaleShortToQuantum(*p++),q);
3947 p++;
3948 q+=GetPixelChannels(image);
3949 }
3950 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3951 break;
3952 }
3953 return;
3954 }
cristy14d71292012-05-20 16:48:13 +00003955 length=strlen(map);
cristycafe0412012-01-10 13:29:58 +00003956 for (y=0; y < (ssize_t) roi->height; y++)
cristye5370942012-01-06 03:49:31 +00003957 {
cristycafe0412012-01-10 13:29:58 +00003958 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
cristye5370942012-01-06 03:49:31 +00003959 if (q == (Quantum *) NULL)
3960 break;
cristycafe0412012-01-10 13:29:58 +00003961 for (x=0; x < (ssize_t) roi->width; x++)
cristye5370942012-01-06 03:49:31 +00003962 {
3963 register ssize_t
3964 i;
3965
cristy14d71292012-05-20 16:48:13 +00003966 for (i=0; i < (ssize_t) length; i++)
cristye5370942012-01-06 03:49:31 +00003967 {
3968 switch (quantum_map[i])
3969 {
3970 case RedQuantum:
3971 case CyanQuantum:
3972 {
3973 SetPixelRed(image,ScaleShortToQuantum(*p),q);
3974 break;
3975 }
3976 case GreenQuantum:
3977 case MagentaQuantum:
3978 {
3979 SetPixelGreen(image,ScaleShortToQuantum(*p),q);
3980 break;
3981 }
3982 case BlueQuantum:
3983 case YellowQuantum:
3984 {
3985 SetPixelBlue(image,ScaleShortToQuantum(*p),q);
3986 break;
3987 }
3988 case AlphaQuantum:
3989 {
3990 SetPixelAlpha(image,ScaleShortToQuantum(*p),q);
3991 break;
3992 }
3993 case OpacityQuantum:
3994 {
3995 SetPixelAlpha(image,ScaleShortToQuantum(*p),q);
3996 break;
3997 }
3998 case BlackQuantum:
3999 {
4000 SetPixelBlack(image,ScaleShortToQuantum(*p),q);
4001 break;
4002 }
4003 case IndexQuantum:
4004 {
4005 SetPixelGray(image,ScaleShortToQuantum(*p),q);
4006 break;
4007 }
4008 default:
4009 break;
4010 }
4011 p++;
4012 }
4013 q+=GetPixelChannels(image);
4014 }
4015 if (SyncAuthenticPixels(image,exception) == MagickFalse)
4016 break;
4017 }
4018}
4019
cristycafe0412012-01-10 13:29:58 +00004020MagickExport MagickBooleanType ImportImagePixels(Image *image,const ssize_t x,
4021 const ssize_t y,const size_t width,const size_t height,const char *map,
4022 const StorageType type,const void *pixels,ExceptionInfo *exception)
cristy4c08aed2011-07-01 19:47:50 +00004023{
cristy4c08aed2011-07-01 19:47:50 +00004024 QuantumType
4025 *quantum_map;
4026
cristycafe0412012-01-10 13:29:58 +00004027 RectangleInfo
4028 roi;
4029
cristy4c08aed2011-07-01 19:47:50 +00004030 register ssize_t
cristye5370942012-01-06 03:49:31 +00004031 i;
cristy4c08aed2011-07-01 19:47:50 +00004032
cristy14d71292012-05-20 16:48:13 +00004033 size_t
4034 length;
4035
cristy4c08aed2011-07-01 19:47:50 +00004036 /*
4037 Allocate image structure.
4038 */
4039 assert(image != (Image *) NULL);
4040 assert(image->signature == MagickSignature);
4041 if (image->debug != MagickFalse)
4042 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
cristy14d71292012-05-20 16:48:13 +00004043 length=strlen(map);
4044 quantum_map=(QuantumType *) AcquireQuantumMemory(length,sizeof(*quantum_map));
cristy4c08aed2011-07-01 19:47:50 +00004045 if (quantum_map == (QuantumType *) NULL)
4046 ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
4047 image->filename);
cristy14d71292012-05-20 16:48:13 +00004048 for (i=0; i < (ssize_t) length; i++)
cristy4c08aed2011-07-01 19:47:50 +00004049 {
4050 switch (map[i])
4051 {
4052 case 'a':
4053 case 'A':
4054 {
4055 quantum_map[i]=AlphaQuantum;
cristy8a46d822012-08-28 23:32:39 +00004056 image->alpha_trait=BlendPixelTrait;
cristy4c08aed2011-07-01 19:47:50 +00004057 break;
4058 }
4059 case 'B':
4060 case 'b':
4061 {
4062 quantum_map[i]=BlueQuantum;
4063 break;
4064 }
4065 case 'C':
4066 case 'c':
4067 {
4068 quantum_map[i]=CyanQuantum;
cristy63240882011-08-05 19:05:27 +00004069 (void) SetImageColorspace(image,CMYKColorspace,exception);
cristy4c08aed2011-07-01 19:47:50 +00004070 break;
4071 }
4072 case 'g':
4073 case 'G':
4074 {
4075 quantum_map[i]=GreenQuantum;
4076 break;
4077 }
4078 case 'K':
4079 case 'k':
4080 {
4081 quantum_map[i]=BlackQuantum;
cristy63240882011-08-05 19:05:27 +00004082 (void) SetImageColorspace(image,CMYKColorspace,exception);
cristy4c08aed2011-07-01 19:47:50 +00004083 break;
4084 }
4085 case 'I':
4086 case 'i':
4087 {
4088 quantum_map[i]=IndexQuantum;
cristyb7b3da62012-07-05 15:43:37 +00004089 (void) SetImageColorspace(image,GRAYColorspace,exception);
cristy4c08aed2011-07-01 19:47:50 +00004090 break;
4091 }
4092 case 'm':
4093 case 'M':
4094 {
4095 quantum_map[i]=MagentaQuantum;
cristy63240882011-08-05 19:05:27 +00004096 (void) SetImageColorspace(image,CMYKColorspace,exception);
cristy4c08aed2011-07-01 19:47:50 +00004097 break;
4098 }
4099 case 'O':
4100 case 'o':
4101 {
4102 quantum_map[i]=OpacityQuantum;
cristy8a46d822012-08-28 23:32:39 +00004103 image->alpha_trait=BlendPixelTrait;
cristy4c08aed2011-07-01 19:47:50 +00004104 break;
4105 }
4106 case 'P':
4107 case 'p':
4108 {
4109 quantum_map[i]=UndefinedQuantum;
4110 break;
4111 }
4112 case 'R':
4113 case 'r':
4114 {
4115 quantum_map[i]=RedQuantum;
4116 break;
4117 }
4118 case 'Y':
4119 case 'y':
4120 {
4121 quantum_map[i]=YellowQuantum;
cristy63240882011-08-05 19:05:27 +00004122 (void) SetImageColorspace(image,CMYKColorspace,exception);
cristy4c08aed2011-07-01 19:47:50 +00004123 break;
4124 }
4125 default:
4126 {
4127 quantum_map=(QuantumType *) RelinquishMagickMemory(quantum_map);
cristy63240882011-08-05 19:05:27 +00004128 (void) ThrowMagickException(exception,GetMagickModule(),OptionError,
cristyefe601c2013-01-05 17:51:12 +00004129 "UnrecognizedPixelMap","`%s'",map);
cristy4c08aed2011-07-01 19:47:50 +00004130 return(MagickFalse);
4131 }
4132 }
4133 }
cristy63240882011-08-05 19:05:27 +00004134 if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
cristy4c08aed2011-07-01 19:47:50 +00004135 return(MagickFalse);
4136 /*
cristye5370942012-01-06 03:49:31 +00004137 Transfer the pixels from the pixel data to the image.
cristy4c08aed2011-07-01 19:47:50 +00004138 */
cristycafe0412012-01-10 13:29:58 +00004139 roi.width=width;
4140 roi.height=height;
4141 roi.x=x;
4142 roi.y=y;
cristy4c08aed2011-07-01 19:47:50 +00004143 switch (type)
4144 {
4145 case CharPixel:
4146 {
cristycafe0412012-01-10 13:29:58 +00004147 ImportCharPixel(image,&roi,map,quantum_map,pixels,exception);
cristy4c08aed2011-07-01 19:47:50 +00004148 break;
4149 }
4150 case DoublePixel:
4151 {
cristycafe0412012-01-10 13:29:58 +00004152 ImportDoublePixel(image,&roi,map,quantum_map,pixels,exception);
cristy4c08aed2011-07-01 19:47:50 +00004153 break;
4154 }
4155 case FloatPixel:
4156 {
cristycafe0412012-01-10 13:29:58 +00004157 ImportFloatPixel(image,&roi,map,quantum_map,pixels,exception);
cristy4c08aed2011-07-01 19:47:50 +00004158 break;
4159 }
cristy4c08aed2011-07-01 19:47:50 +00004160 case LongPixel:
4161 {
cristycafe0412012-01-10 13:29:58 +00004162 ImportLongPixel(image,&roi,map,quantum_map,pixels,exception);
cristy4c08aed2011-07-01 19:47:50 +00004163 break;
4164 }
cristy6c9e1682012-01-07 21:37:44 +00004165 case LongLongPixel:
4166 {
cristycafe0412012-01-10 13:29:58 +00004167 ImportLongLongPixel(image,&roi,map,quantum_map,pixels,exception);
cristy6c9e1682012-01-07 21:37:44 +00004168 break;
4169 }
cristy4c08aed2011-07-01 19:47:50 +00004170 case QuantumPixel:
4171 {
cristycafe0412012-01-10 13:29:58 +00004172 ImportQuantumPixel(image,&roi,map,quantum_map,pixels,exception);
cristy4c08aed2011-07-01 19:47:50 +00004173 break;
4174 }
4175 case ShortPixel:
4176 {
cristycafe0412012-01-10 13:29:58 +00004177 ImportShortPixel(image,&roi,map,quantum_map,pixels,exception);
cristy4c08aed2011-07-01 19:47:50 +00004178 break;
4179 }
4180 default:
4181 {
4182 quantum_map=(QuantumType *) RelinquishMagickMemory(quantum_map);
cristyc82a27b2011-10-21 01:07:16 +00004183 (void) ThrowMagickException(exception,GetMagickModule(),OptionError,
cristyefe601c2013-01-05 17:51:12 +00004184 "UnrecognizedPixelMap","`%s'",map);
cristy4c08aed2011-07-01 19:47:50 +00004185 break;
4186 }
4187 }
4188 quantum_map=(QuantumType *) RelinquishMagickMemory(quantum_map);
4189 return(MagickTrue);
4190}
4191
4192/*
4193%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4194% %
4195% %
4196% %
cristybd5a96c2011-08-21 00:04:26 +00004197+ 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 %
4198% %
4199% %
4200% %
4201%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4202%
4203% InitializePixelChannelMap() defines the standard pixel component map.
4204%
4205% The format of the InitializePixelChannelMap() method is:
4206%
4207% void InitializePixelChannelMap(Image *image)
4208%
4209% A description of each parameter follows:
4210%
4211% o image: the image.
4212%
4213*/
cristye2a912b2011-12-05 20:02:07 +00004214MagickExport void InitializePixelChannelMap(Image *image)
cristy77c30f52011-10-24 18:56:57 +00004215{
cristye2a912b2011-12-05 20:02:07 +00004216 PixelTrait
4217 trait;
4218
cristy77c30f52011-10-24 18:56:57 +00004219 register ssize_t
4220 i;
4221
cristyd26338f2011-12-14 02:39:30 +00004222 ssize_t
cristy77c30f52011-10-24 18:56:57 +00004223 n;
4224
4225 assert(image != (Image *) NULL);
4226 assert(image->signature == MagickSignature);
cristye2a912b2011-12-05 20:02:07 +00004227 (void) ResetMagickMemory(image->channel_map,0,MaxPixelChannels*
4228 sizeof(*image->channel_map));
4229 trait=UpdatePixelTrait;
cristy8a46d822012-08-28 23:32:39 +00004230 if (image->alpha_trait == BlendPixelTrait)
cristy61f18ad2011-12-08 21:12:37 +00004231 trait=(PixelTrait) (trait | BlendPixelTrait);
cristy77c30f52011-10-24 18:56:57 +00004232 n=0;
cristyc06c5802011-12-31 23:36:16 +00004233 if (image->colorspace == GRAYColorspace)
cristy77c30f52011-10-24 18:56:57 +00004234 {
cristycf1296e2012-08-26 23:40:49 +00004235 SetPixelChannelAttributes(image,BluePixelChannel,trait,n);
4236 SetPixelChannelAttributes(image,GreenPixelChannel,trait,n);
4237 SetPixelChannelAttributes(image,RedPixelChannel,trait,n++);
cristy3c316282011-12-15 15:43:24 +00004238 }
4239 else
4240 {
cristycf1296e2012-08-26 23:40:49 +00004241 SetPixelChannelAttributes(image,RedPixelChannel,trait,n++);
4242 SetPixelChannelAttributes(image,GreenPixelChannel,trait,n++);
4243 SetPixelChannelAttributes(image,BluePixelChannel,trait,n++);
cristy77c30f52011-10-24 18:56:57 +00004244 }
4245 if (image->colorspace == CMYKColorspace)
cristycf1296e2012-08-26 23:40:49 +00004246 SetPixelChannelAttributes(image,BlackPixelChannel,trait,n++);
cristy8a46d822012-08-28 23:32:39 +00004247 if (image->alpha_trait != UndefinedPixelTrait)
cristycf1296e2012-08-26 23:40:49 +00004248 SetPixelChannelAttributes(image,AlphaPixelChannel,CopyPixelTrait,n++);
cristye2a912b2011-12-05 20:02:07 +00004249 if (image->storage_class == PseudoClass)
cristycf1296e2012-08-26 23:40:49 +00004250 SetPixelChannelAttributes(image,IndexPixelChannel,CopyPixelTrait,n++);
cristy883fde12013-04-08 00:50:13 +00004251 if (image->read_mask != MagickFalse)
4252 SetPixelChannelAttributes(image,ReadMaskPixelChannel,CopyPixelTrait,n++);
4253 if (image->write_mask != MagickFalse)
4254 SetPixelChannelAttributes(image,WriteMaskPixelChannel,CopyPixelTrait,n++);
cristye2a912b2011-12-05 20:02:07 +00004255 assert((n+image->number_meta_channels) < MaxPixelChannels);
4256 for (i=0; i < (ssize_t) image->number_meta_channels; i++)
cristycf1296e2012-08-26 23:40:49 +00004257 SetPixelChannelAttributes(image,(PixelChannel) (MetaPixelChannel+i),
4258 CopyPixelTrait,n++);
cristyd26338f2011-12-14 02:39:30 +00004259 image->number_channels=(size_t) n;
cristy77c30f52011-10-24 18:56:57 +00004260 if (image->debug != MagickFalse)
4261 LogPixelChannels(image);
cristycf1296e2012-08-26 23:40:49 +00004262 (void) SetImageChannelMask(image,image->channel_mask);
cristy77c30f52011-10-24 18:56:57 +00004263}
cristybd5a96c2011-08-21 00:04:26 +00004264
4265/*
4266%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4267% %
4268% %
4269% %
cristya085a432011-07-30 01:39:32 +00004270% I n t e r p o l a t e P i x e l C h a n n e l %
4271% %
4272% %
4273% %
4274%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4275%
cristy884f6002011-07-31 00:51:45 +00004276% InterpolatePixelChannel() applies a pixel interpolation method between a
4277% floating point coordinate and the pixels surrounding that coordinate. No
4278% pixel area resampling, or scaling of the result is performed.
cristya085a432011-07-30 01:39:32 +00004279%
anthonycf4e33d2012-06-08 07:33:23 +00004280% Interpolation is restricted to just the specified channel.
4281%
cristya085a432011-07-30 01:39:32 +00004282% The format of the InterpolatePixelChannel method is:
4283%
4284% MagickBooleanType InterpolatePixelChannel(const Image *image,
cristy444eda62011-08-10 02:07:46 +00004285% const CacheView *image_view,const PixelChannel channel,
cristy5c4e2582011-09-11 19:21:03 +00004286% const PixelInterpolateMethod method,const double x,const double y,
cristya085a432011-07-30 01:39:32 +00004287% double *pixel,ExceptionInfo *exception)
4288%
4289% A description of each parameter follows:
4290%
4291% o image: the image.
4292%
4293% o image_view: the image view.
4294%
4295% o channel: the pixel channel to interpolate.
4296%
4297% o method: the pixel color interpolation method.
4298%
4299% o x,y: A double representing the current (x,y) position of the pixel.
4300%
4301% o pixel: return the interpolated pixel here.
4302%
4303% o exception: return any errors or warnings in this structure.
4304%
4305*/
cristy94ea1632011-07-30 20:40:25 +00004306
cristyb0a657e2012-08-29 00:45:37 +00004307static inline void CatromWeights(const double x,double (*weights)[4])
cristy884f6002011-07-31 00:51:45 +00004308{
cristya19f1d72012-08-07 18:24:38 +00004309 double
cristy884f6002011-07-31 00:51:45 +00004310 alpha,
nicolasd32d5e52012-06-12 15:34:10 +00004311 beta,
cristy884f6002011-07-31 00:51:45 +00004312 gamma;
4313
cristy5a5e4d92012-08-29 00:06:25 +00004314 /*
4315 Nicolas Robidoux' 10 flops (4* + 5- + 1+) refactoring of the computation
4316 of the standard four 1D Catmull-Rom weights. The sampling location is
4317 assumed between the second and third input pixel locations, and x is the
4318 position relative to the second input pixel location. Formulas originally
4319 derived for the VIPS (Virtual Image Processing System) library.
4320 */
cristya19f1d72012-08-07 18:24:38 +00004321 alpha=(double) 1.0-x;
4322 beta=(double) (-0.5)*x*alpha;
nicolasd32d5e52012-06-12 15:34:10 +00004323 (*weights)[0]=alpha*beta;
4324 (*weights)[3]=x*beta;
4325 /*
cristy5a5e4d92012-08-29 00:06:25 +00004326 The following computation of the inner weights from the outer ones work
4327 for all Keys cubics.
nicolasd32d5e52012-06-12 15:34:10 +00004328 */
4329 gamma=(*weights)[3]-(*weights)[0];
4330 (*weights)[1]=alpha-(*weights)[0]+gamma;
4331 (*weights)[2]=x-(*weights)[3]-gamma;
4332}
4333
cristyb0a657e2012-08-29 00:45:37 +00004334static inline void SplineWeights(const double x,double (*weights)[4])
nicolasd32d5e52012-06-12 15:34:10 +00004335{
cristy5a5e4d92012-08-29 00:06:25 +00004336 double
4337 alpha,
4338 beta;
4339
nicolasd32d5e52012-06-12 15:34:10 +00004340 /*
4341 Nicolas Robidoux' 12 flops (6* + 5- + 1+) refactoring of the
4342 computation of the standard four 1D cubic B-spline smoothing
4343 weights. The sampling location is assumed between the second and
4344 third input pixel locations, and x is the position relative to the
4345 second input pixel location.
4346 */
cristya19f1d72012-08-07 18:24:38 +00004347 alpha=(double) 1.0-x;
4348 (*weights)[3]=(double) (1.0/6.0)*x*x*x;
4349 (*weights)[0]=(double) (1.0/6.0)*alpha*alpha*alpha;
nicolasd32d5e52012-06-12 15:34:10 +00004350 beta=(*weights)[3]-(*weights)[0];
4351 (*weights)[1]=alpha-(*weights)[0]+beta;
4352 (*weights)[2]=x-(*weights)[3]-beta;
cristy884f6002011-07-31 00:51:45 +00004353}
4354
cristy94ea1632011-07-30 20:40:25 +00004355static inline double MeshInterpolate(const PointInfo *delta,const double p,
4356 const double x,const double y)
4357{
4358 return(delta->x*x+delta->y*y+(1.0-delta->x-delta->y)*p);
4359}
4360
anthonycf4e33d2012-06-08 07:33:23 +00004361/*
cristya19f1d72012-08-07 18:24:38 +00004362static inline ssize_t NearestNeighbor(const double x)
cristy884f6002011-07-31 00:51:45 +00004363{
4364 if (x >= 0.0)
4365 return((ssize_t) (x+0.5));
4366 return((ssize_t) (x-0.5));
4367}
anthonycf4e33d2012-06-08 07:33:23 +00004368*/
cristy884f6002011-07-31 00:51:45 +00004369
cristya085a432011-07-30 01:39:32 +00004370MagickExport MagickBooleanType InterpolatePixelChannel(const Image *image,
4371 const CacheView *image_view,const PixelChannel channel,
cristy5c4e2582011-09-11 19:21:03 +00004372 const PixelInterpolateMethod method,const double x,const double y,
cristya085a432011-07-30 01:39:32 +00004373 double *pixel,ExceptionInfo *exception)
4374{
4375 MagickBooleanType
4376 status;
4377
cristya19f1d72012-08-07 18:24:38 +00004378 double
cristy94ea1632011-07-30 20:40:25 +00004379 alpha[16],
cristy884f6002011-07-31 00:51:45 +00004380 gamma,
4381 pixels[16];
cristy94ea1632011-07-30 20:40:25 +00004382
4383 PixelTrait
4384 traits;
4385
cristy94ea1632011-07-30 20:40:25 +00004386 register const Quantum
4387 *p;
4388
cristy50e64b82012-06-22 17:46:19 +00004389 register ssize_t
cristy94ea1632011-07-30 20:40:25 +00004390 i;
4391
cristya085a432011-07-30 01:39:32 +00004392 ssize_t
4393 x_offset,
4394 y_offset;
4395
anthonycf4e33d2012-06-08 07:33:23 +00004396 PixelInterpolateMethod
4397 interpolate;
4398
cristya085a432011-07-30 01:39:32 +00004399 assert(image != (Image *) NULL);
4400 assert(image != (Image *) NULL);
4401 assert(image->signature == MagickSignature);
4402 assert(image_view != (CacheView *) NULL);
4403 status=MagickTrue;
cristy884f6002011-07-31 00:51:45 +00004404 *pixel=0.0;
cristycf1296e2012-08-26 23:40:49 +00004405 traits=GetPixelChannelTraits(image,channel);
cristya085a432011-07-30 01:39:32 +00004406 x_offset=(ssize_t) floor(x);
4407 y_offset=(ssize_t) floor(y);
anthonycf4e33d2012-06-08 07:33:23 +00004408 interpolate = method;
4409 if ( interpolate == UndefinedInterpolatePixel )
4410 interpolate = image->interpolate;
4411 switch (interpolate)
cristya085a432011-07-30 01:39:32 +00004412 {
anthonycf4e33d2012-06-08 07:33:23 +00004413 case AverageInterpolatePixel: /* nearest 4 neighbours */
4414 case Average9InterpolatePixel: /* nearest 9 neighbours */
4415 case Average16InterpolatePixel: /* nearest 16 neighbours */
cristy884f6002011-07-31 00:51:45 +00004416 {
cristyfb122372012-10-17 23:31:21 +00004417 ssize_t
4418 count;
anthonycf4e33d2012-06-08 07:33:23 +00004419
cristyfb122372012-10-17 23:31:21 +00004420 count=2; /* size of the area to average - default nearest 4 */
anthonycf4e33d2012-06-08 07:33:23 +00004421 if (interpolate == Average9InterpolatePixel)
4422 {
4423 count=3;
4424 x_offset=(ssize_t) (floor(x+0.5)-1);
4425 y_offset=(ssize_t) (floor(y+0.5)-1);
4426 }
cristyfb122372012-10-17 23:31:21 +00004427 else
4428 if (interpolate == Average16InterpolatePixel)
4429 {
4430 count=4;
4431 x_offset--;
4432 y_offset--;
4433 }
cristy70e9f682013-03-12 22:31:22 +00004434 p=GetCacheViewVirtualPixels(image_view,x_offset,y_offset,(size_t) count,(size_t)
4435 count,exception);
cristy884f6002011-07-31 00:51:45 +00004436 if (p == (const Quantum *) NULL)
4437 {
4438 status=MagickFalse;
4439 break;
4440 }
anthonycf4e33d2012-06-08 07:33:23 +00004441 count*=count; /* Number of pixels to Average */
cristy222b19c2011-08-04 01:35:11 +00004442 if ((traits & BlendPixelTrait) == 0)
cristy50e64b82012-06-22 17:46:19 +00004443 for (i=0; i < (ssize_t) count; i++)
cristy884f6002011-07-31 00:51:45 +00004444 {
4445 alpha[i]=1.0;
cristya19f1d72012-08-07 18:24:38 +00004446 pixels[i]=(double) p[i*GetPixelChannels(image)+channel];
cristy884f6002011-07-31 00:51:45 +00004447 }
4448 else
cristy50e64b82012-06-22 17:46:19 +00004449 for (i=0; i < (ssize_t) count; i++)
cristy884f6002011-07-31 00:51:45 +00004450 {
4451 alpha[i]=QuantumScale*GetPixelAlpha(image,p+i*
4452 GetPixelChannels(image));
4453 pixels[i]=alpha[i]*p[i*GetPixelChannels(image)+channel];
4454 }
cristy50e64b82012-06-22 17:46:19 +00004455 for (i=0; i < (ssize_t) count; i++)
cristy884f6002011-07-31 00:51:45 +00004456 {
cristy3e3ec3a2012-11-03 23:11:06 +00004457 gamma=PerceptibleReciprocal(alpha[i])/count;
anthonycf4e33d2012-06-08 07:33:23 +00004458 *pixel+=gamma*pixels[i];
cristy884f6002011-07-31 00:51:45 +00004459 }
4460 break;
4461 }
anthonycf4e33d2012-06-08 07:33:23 +00004462 case BilinearInterpolatePixel:
4463 default:
4464 {
4465 PointInfo
4466 delta,
4467 epsilon;
4468
4469 p=GetCacheViewVirtualPixels(image_view,x_offset,y_offset,2,2,exception);
4470 if (p == (const Quantum *) NULL)
4471 {
4472 status=MagickFalse;
4473 break;
4474 }
4475 if ((traits & BlendPixelTrait) == 0)
4476 for (i=0; i < 4; i++)
4477 {
4478 alpha[i]=1.0;
cristya19f1d72012-08-07 18:24:38 +00004479 pixels[i]=(double) p[i*GetPixelChannels(image)+channel];
anthonycf4e33d2012-06-08 07:33:23 +00004480 }
4481 else
4482 for (i=0; i < 4; i++)
4483 {
4484 alpha[i]=QuantumScale*GetPixelAlpha(image,p+i*
4485 GetPixelChannels(image));
4486 pixels[i]=alpha[i]*p[i*GetPixelChannels(image)+channel];
4487 }
4488 delta.x=x-x_offset;
4489 delta.y=y-y_offset;
4490 epsilon.x=1.0-delta.x;
4491 epsilon.y=1.0-delta.y;
4492 gamma=((epsilon.y*(epsilon.x*alpha[0]+delta.x*alpha[1])+delta.y*
4493 (epsilon.x*alpha[2]+delta.x*alpha[3])));
cristy3e3ec3a2012-11-03 23:11:06 +00004494 gamma=PerceptibleReciprocal(gamma);
anthonycf4e33d2012-06-08 07:33:23 +00004495 *pixel=gamma*(epsilon.y*(epsilon.x*pixels[0]+delta.x*pixels[1])+delta.y*
4496 (epsilon.x*pixels[2]+delta.x*pixels[3]));
4497 break;
4498 }
anthony5f78bca2012-10-05 06:51:00 +00004499 case BlendInterpolatePixel:
4500 {
4501 p=GetCacheViewVirtualPixels(image_view,x_offset,y_offset,2,2,exception);
4502 if (p == (const Quantum *) NULL)
4503 {
4504 status=MagickFalse;
4505 break;
4506 }
4507 if ((traits & BlendPixelTrait) == 0)
4508 for (i=0; i < 4; i++)
4509 {
4510 alpha[i]=1.0;
4511 pixels[i]=(MagickRealType) p[i*GetPixelChannels(image)+channel];
4512 }
4513 else
4514 for (i=0; i < 4; i++)
4515 {
4516 alpha[i]=QuantumScale*GetPixelAlpha(image,p+i*
4517 GetPixelChannels(image));
4518 pixels[i]=alpha[i]*p[i*GetPixelChannels(image)+channel];
4519 }
4520 gamma=1.0; /* number of pixels blended together (its variable) */
4521 for (i=0; i <= 1L; i++) {
cristyfb122372012-10-17 23:31:21 +00004522 if ((y-y_offset) >= 0.75)
4523 {
4524 alpha[i]=alpha[i+2]; /* take right pixels */
4525 pixels[i]=pixels[i+2];
4526 }
4527 else
4528 if ((y-y_offset) > 0.25)
4529 {
4530 gamma=2.0; /* blend both pixels in row */
4531 alpha[i]+=alpha[i+2]; /* add up alpha weights */
4532 pixels[i]+=pixels[i+2];
4533 }
4534 }
4535 if ((x-x_offset) >= 0.75)
4536 {
4537 alpha[0]=alpha[1]; /* take bottom row blend */
4538 pixels[0]=pixels[1];
anthony5f78bca2012-10-05 06:51:00 +00004539 }
cristyfb122372012-10-17 23:31:21 +00004540 else
4541 if ((x-x_offset) > 0.25)
4542 {
4543 gamma*=2.0; /* blend both rows */
4544 alpha[0]+=alpha[1]; /* add up alpha weights */
4545 pixels[0]+=pixels[1];
4546 }
anthony5f78bca2012-10-05 06:51:00 +00004547 if (channel != AlphaPixelChannel)
cristy3e3ec3a2012-11-03 23:11:06 +00004548 gamma=PerceptibleReciprocal(alpha[0]); /* (color) 1/alpha_weights */
anthony5f78bca2012-10-05 06:51:00 +00004549 else
cristy3e3ec3a2012-11-03 23:11:06 +00004550 gamma=PerceptibleReciprocal(gamma); /* (alpha) 1/number_of_pixels */
anthony5f78bca2012-10-05 06:51:00 +00004551 *pixel=gamma*pixels[0];
4552 break;
4553 }
anthonycf4e33d2012-06-08 07:33:23 +00004554 case CatromInterpolatePixel:
cristy884f6002011-07-31 00:51:45 +00004555 {
cristya19f1d72012-08-07 18:24:38 +00004556 double
cristy380a11c2012-06-02 15:15:22 +00004557 cx[4],
nicolas6676f5a2012-06-12 16:01:15 +00004558 cy[4];
cristy884f6002011-07-31 00:51:45 +00004559
cristy884f6002011-07-31 00:51:45 +00004560 p=GetCacheViewVirtualPixels(image_view,x_offset-1,y_offset-1,4,4,
4561 exception);
4562 if (p == (const Quantum *) NULL)
4563 {
4564 status=MagickFalse;
4565 break;
4566 }
cristy222b19c2011-08-04 01:35:11 +00004567 if ((traits & BlendPixelTrait) == 0)
cristy884f6002011-07-31 00:51:45 +00004568 for (i=0; i < 16; i++)
4569 {
4570 alpha[i]=1.0;
cristya19f1d72012-08-07 18:24:38 +00004571 pixels[i]=(double) p[i*GetPixelChannels(image)+channel];
cristy884f6002011-07-31 00:51:45 +00004572 }
4573 else
4574 for (i=0; i < 16; i++)
4575 {
4576 alpha[i]=QuantumScale*GetPixelAlpha(image,p+i*
4577 GetPixelChannels(image));
4578 pixels[i]=alpha[i]*p[i*GetPixelChannels(image)+channel];
4579 }
cristya19f1d72012-08-07 18:24:38 +00004580 CatromWeights((double) (x-x_offset),&cx);
4581 CatromWeights((double) (y-y_offset),&cy);
4582 gamma=(channel == AlphaPixelChannel ? (double) 1.0 :
cristy3e3ec3a2012-11-03 23:11:06 +00004583 PerceptibleReciprocal(cy[0]*(cx[0]*alpha[0]+cx[1]*alpha[1]+cx[2]*
nicolasd32d5e52012-06-12 15:34:10 +00004584 alpha[2]+cx[3]*alpha[3])+cy[1]*(cx[0]*alpha[4]+cx[1]*alpha[5]+cx[2]*
4585 alpha[6]+cx[3]*alpha[7])+cy[2]*(cx[0]*alpha[8]+cx[1]*alpha[9]+cx[2]*
4586 alpha[10]+cx[3]*alpha[11])+cy[3]*(cx[0]*alpha[12]+cx[1]*alpha[13]+
4587 cx[2]*alpha[14]+cx[3]*alpha[15])));
cristy380a11c2012-06-02 15:15:22 +00004588 *pixel=gamma*(cy[0]*(cx[0]*pixels[0]+cx[1]*pixels[1]+cx[2]*pixels[2]+
nicolasd32d5e52012-06-12 15:34:10 +00004589 cx[3]*pixels[3])+cy[1]*(cx[0]*pixels[4]+cx[1]*pixels[5]+cx[2]*
4590 pixels[6]+cx[3]*pixels[7])+cy[2]*(cx[0]*pixels[8]+cx[1]*pixels[9]+
4591 cx[2]*pixels[10]+cx[3]*pixels[11])+cy[3]*(cx[0]*pixels[12]+cx[1]*
4592 pixels[13]+cx[2]*pixels[14]+cx[3]*pixels[15]));
cristy884f6002011-07-31 00:51:45 +00004593 break;
4594 }
anthonycf4e33d2012-06-08 07:33:23 +00004595#if 0
nicolas20075dc2012-06-12 20:47:38 +00004596 /* deprecated useless and very slow interpolator */
cristy884f6002011-07-31 00:51:45 +00004597 case FilterInterpolatePixel:
4598 {
4599 CacheView
4600 *filter_view;
4601
4602 Image
4603 *excerpt_image,
4604 *filter_image;
4605
4606 RectangleInfo
4607 geometry;
4608
4609 geometry.width=4L;
4610 geometry.height=4L;
4611 geometry.x=x_offset-1;
4612 geometry.y=y_offset-1;
4613 excerpt_image=ExcerptImage(image,&geometry,exception);
4614 if (excerpt_image == (Image *) NULL)
4615 {
4616 status=MagickFalse;
4617 break;
4618 }
cristyaa2c16c2012-03-25 22:21:35 +00004619 filter_image=ResizeImage(excerpt_image,1,1,image->filter,exception);
cristy884f6002011-07-31 00:51:45 +00004620 excerpt_image=DestroyImage(excerpt_image);
4621 if (filter_image == (Image *) NULL)
4622 break;
cristy46ff2672012-12-14 15:32:26 +00004623 filter_view=AcquireVirtualCacheView(filter_image,exception);
cristy884f6002011-07-31 00:51:45 +00004624 p=GetCacheViewVirtualPixels(filter_view,0,0,1,1,exception);
4625 if (p == (const Quantum *) NULL)
4626 status=MagickFalse;
4627 else
cristy0beccfa2011-09-25 20:47:53 +00004628 *pixel=(double) GetPixelChannel(image,channel,p);
cristy884f6002011-07-31 00:51:45 +00004629 filter_view=DestroyCacheView(filter_view);
4630 filter_image=DestroyImage(filter_image);
4631 break;
4632 }
anthonycf4e33d2012-06-08 07:33:23 +00004633#endif
cristy884f6002011-07-31 00:51:45 +00004634 case IntegerInterpolatePixel:
4635 {
4636 p=GetCacheViewVirtualPixels(image_view,x_offset,y_offset,1,1,exception);
4637 if (p == (const Quantum *) NULL)
4638 {
4639 status=MagickFalse;
4640 break;
4641 }
cristy0beccfa2011-09-25 20:47:53 +00004642 *pixel=(double) GetPixelChannel(image,channel,p);
cristy884f6002011-07-31 00:51:45 +00004643 break;
4644 }
anthonycf4e33d2012-06-08 07:33:23 +00004645 case NearestInterpolatePixel:
cristy884f6002011-07-31 00:51:45 +00004646 {
anthonycf4e33d2012-06-08 07:33:23 +00004647 x_offset=(ssize_t) floor(x+0.5);
4648 y_offset=(ssize_t) floor(y+0.5);
4649 p=GetCacheViewVirtualPixels(image_view,x_offset,y_offset,1,1,exception);
cristy884f6002011-07-31 00:51:45 +00004650 if (p == (const Quantum *) NULL)
4651 {
4652 status=MagickFalse;
4653 break;
4654 }
cristy0beccfa2011-09-25 20:47:53 +00004655 *pixel=(double) GetPixelChannel(image,channel,p);
cristy884f6002011-07-31 00:51:45 +00004656 break;
4657 }
4658 case MeshInterpolatePixel:
4659 {
4660 PointInfo
4661 delta,
cristy94ea1632011-07-30 20:40:25 +00004662 luminance;
4663
4664 p=GetCacheViewVirtualPixels(image_view,x_offset,y_offset,2,2,exception);
4665 if (p == (const Quantum *) NULL)
4666 {
4667 status=MagickFalse;
4668 break;
4669 }
cristy222b19c2011-08-04 01:35:11 +00004670 if ((traits & BlendPixelTrait) == 0)
cristy94ea1632011-07-30 20:40:25 +00004671 for (i=0; i < 4; i++)
4672 {
4673 alpha[i]=1.0;
cristya19f1d72012-08-07 18:24:38 +00004674 pixels[i]=(double) p[i*GetPixelChannels(image)+channel];
cristy94ea1632011-07-30 20:40:25 +00004675 }
4676 else
4677 for (i=0; i < 4; i++)
4678 {
4679 alpha[i]=QuantumScale*GetPixelAlpha(image,p+i*
4680 GetPixelChannels(image));
4681 pixels[i]=alpha[i]*p[i*GetPixelChannels(image)+channel];
4682 }
cristy884f6002011-07-31 00:51:45 +00004683 delta.x=x-x_offset;
4684 delta.y=y-y_offset;
4685 luminance.x=GetPixelLuminance(image,p)-(double)
4686 GetPixelLuminance(image,p+3*GetPixelChannels(image));
cristy28474bf2011-09-11 23:32:52 +00004687 luminance.y=GetPixelLuminance(image,p+GetPixelChannels(image))-(double)
cristy884f6002011-07-31 00:51:45 +00004688 GetPixelLuminance(image,p+2*GetPixelChannels(image));
cristy94ea1632011-07-30 20:40:25 +00004689 if (fabs(luminance.x) < fabs(luminance.y))
4690 {
4691 /*
4692 Diagonal 0-3 NW-SE.
4693 */
4694 if (delta.x <= delta.y)
4695 {
4696 /*
4697 Bottom-left triangle (pixel: 2, diagonal: 0-3).
4698 */
4699 delta.y=1.0-delta.y;
4700 gamma=MeshInterpolate(&delta,alpha[2],alpha[3],alpha[0]);
cristy3e3ec3a2012-11-03 23:11:06 +00004701 gamma=PerceptibleReciprocal(gamma);
cristy94ea1632011-07-30 20:40:25 +00004702 *pixel=gamma*MeshInterpolate(&delta,pixels[2],pixels[3],
4703 pixels[0]);
4704 }
4705 else
4706 {
4707 /*
4708 Top-right triangle (pixel: 1, diagonal: 0-3).
4709 */
4710 delta.x=1.0-delta.x;
4711 gamma=MeshInterpolate(&delta,alpha[1],alpha[0],alpha[3]);
cristy3e3ec3a2012-11-03 23:11:06 +00004712 gamma=PerceptibleReciprocal(gamma);
cristy94ea1632011-07-30 20:40:25 +00004713 *pixel=gamma*MeshInterpolate(&delta,pixels[1],pixels[0],
4714 pixels[3]);
4715 }
4716 }
4717 else
4718 {
4719 /*
4720 Diagonal 1-2 NE-SW.
4721 */
4722 if (delta.x <= (1.0-delta.y))
4723 {
4724 /*
4725 Top-left triangle (pixel: 0, diagonal: 1-2).
4726 */
4727 gamma=MeshInterpolate(&delta,alpha[0],alpha[1],alpha[2]);
cristy3e3ec3a2012-11-03 23:11:06 +00004728 gamma=PerceptibleReciprocal(gamma);
cristy94ea1632011-07-30 20:40:25 +00004729 *pixel=gamma*MeshInterpolate(&delta,pixels[0],pixels[1],
4730 pixels[2]);
4731 }
4732 else
4733 {
4734 /*
4735 Bottom-right triangle (pixel: 3, diagonal: 1-2).
4736 */
4737 delta.x=1.0-delta.x;
4738 delta.y=1.0-delta.y;
4739 gamma=MeshInterpolate(&delta,alpha[3],alpha[2],alpha[1]);
cristy3e3ec3a2012-11-03 23:11:06 +00004740 gamma=PerceptibleReciprocal(gamma);
cristy94ea1632011-07-30 20:40:25 +00004741 *pixel=gamma*MeshInterpolate(&delta,pixels[3],pixels[2],
4742 pixels[1]);
4743 }
4744 }
cristya085a432011-07-30 01:39:32 +00004745 break;
4746 }
cristy884f6002011-07-31 00:51:45 +00004747 case SplineInterpolatePixel:
4748 {
cristya19f1d72012-08-07 18:24:38 +00004749 double
nicolasd32d5e52012-06-12 15:34:10 +00004750 cx[4],
nicolas6676f5a2012-06-12 16:01:15 +00004751 cy[4];
cristy884f6002011-07-31 00:51:45 +00004752
4753 p=GetCacheViewVirtualPixels(image_view,x_offset-1,y_offset-1,4,4,
4754 exception);
4755 if (p == (const Quantum *) NULL)
4756 {
4757 status=MagickFalse;
4758 break;
4759 }
cristy222b19c2011-08-04 01:35:11 +00004760 if ((traits & BlendPixelTrait) == 0)
cristy884f6002011-07-31 00:51:45 +00004761 for (i=0; i < 16; i++)
4762 {
4763 alpha[i]=1.0;
cristya19f1d72012-08-07 18:24:38 +00004764 pixels[i]=(double) p[i*GetPixelChannels(image)+channel];
cristy884f6002011-07-31 00:51:45 +00004765 }
4766 else
4767 for (i=0; i < 16; i++)
4768 {
4769 alpha[i]=QuantumScale*GetPixelAlpha(image,p+i*
4770 GetPixelChannels(image));
4771 pixels[i]=alpha[i]*p[i*GetPixelChannels(image)+channel];
4772 }
cristya19f1d72012-08-07 18:24:38 +00004773 SplineWeights((double) (x-x_offset),&cx);
4774 SplineWeights((double) (y-y_offset),&cy);
4775 gamma=(channel == AlphaPixelChannel ? (double) 1.0 :
cristy3e3ec3a2012-11-03 23:11:06 +00004776 PerceptibleReciprocal(cy[0]*(cx[0]*alpha[0]+cx[1]*alpha[1]+cx[2]*
nicolasd32d5e52012-06-12 15:34:10 +00004777 alpha[2]+cx[3]*alpha[3])+cy[1]*(cx[0]*alpha[4]+cx[1]*alpha[5]+cx[2]*
4778 alpha[6]+cx[3]*alpha[7])+cy[2]*(cx[0]*alpha[8]+cx[1]*alpha[9]+cx[2]*
4779 alpha[10]+cx[3]*alpha[11])+cy[3]*(cx[0]*alpha[12]+cx[1]*alpha[13]+
4780 cx[2]*alpha[14]+cx[3]*alpha[15])));
4781 *pixel=gamma*(cy[0]*(cx[0]*pixels[0]+cx[1]*pixels[1]+cx[2]*pixels[2]+
4782 cx[3]*pixels[3])+cy[1]*(cx[0]*pixels[4]+cx[1]*pixels[5]+cx[2]*
4783 pixels[6]+cx[3]*pixels[7])+cy[2]*(cx[0]*pixels[8]+cx[1]*pixels[9]+
4784 cx[2]*pixels[10]+cx[3]*pixels[11])+cy[3]*(cx[0]*pixels[12]+cx[1]*
4785 pixels[13]+cx[2]*pixels[14]+cx[3]*pixels[15]));
cristy884f6002011-07-31 00:51:45 +00004786 break;
4787 }
cristya085a432011-07-30 01:39:32 +00004788 }
4789 return(status);
4790}
4791
4792/*
4793%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4794% %
4795% %
4796% %
cristy5c4e2582011-09-11 19:21:03 +00004797% I n t e r p o l a t e P i x e l C h a n n e l s %
4798% %
4799% %
4800% %
4801%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4802%
4803% InterpolatePixelChannels() applies a pixel interpolation method between a
4804% floating point coordinate and the pixels surrounding that coordinate. No
4805% pixel area resampling, or scaling of the result is performed.
4806%
anthonycf4e33d2012-06-08 07:33:23 +00004807% Interpolation is restricted to just the current channel setting of the
4808% destination image into which the color is to be stored
4809%
cristy5c4e2582011-09-11 19:21:03 +00004810% The format of the InterpolatePixelChannels method is:
4811%
4812% MagickBooleanType InterpolatePixelChannels(const Image *source,
4813% const CacheView *source_view,const Image *destination,
4814% const PixelInterpolateMethod method,const double x,const double y,
4815% Quantum *pixel,ExceptionInfo *exception)
4816%
4817% A description of each parameter follows:
4818%
4819% o source: the source.
4820%
4821% o source_view: the source view.
4822%
anthonycf4e33d2012-06-08 07:33:23 +00004823% o destination: the destination image, for the interpolated color
cristy5c4e2582011-09-11 19:21:03 +00004824%
4825% o method: the pixel color interpolation method.
4826%
4827% o x,y: A double representing the current (x,y) position of the pixel.
4828%
4829% o pixel: return the interpolated pixel here.
4830%
4831% o exception: return any errors or warnings in this structure.
4832%
4833*/
4834MagickExport MagickBooleanType InterpolatePixelChannels(const Image *source,
4835 const CacheView *source_view,const Image *destination,
4836 const PixelInterpolateMethod method,const double x,const double y,
4837 Quantum *pixel,ExceptionInfo *exception)
4838{
4839 MagickBooleanType
4840 status;
4841
cristya19f1d72012-08-07 18:24:38 +00004842 double
cristy5c4e2582011-09-11 19:21:03 +00004843 alpha[16],
4844 gamma,
4845 pixels[16];
4846
cristy5c4e2582011-09-11 19:21:03 +00004847 register const Quantum
4848 *p;
4849
cristy50e64b82012-06-22 17:46:19 +00004850 register ssize_t
cristy5c4e2582011-09-11 19:21:03 +00004851 i;
4852
4853 ssize_t
4854 x_offset,
4855 y_offset;
4856
anthonycf4e33d2012-06-08 07:33:23 +00004857 PixelInterpolateMethod
4858 interpolate;
4859
cristy5c4e2582011-09-11 19:21:03 +00004860 assert(source != (Image *) NULL);
4861 assert(source != (Image *) NULL);
4862 assert(source->signature == MagickSignature);
4863 assert(source_view != (CacheView *) NULL);
4864 status=MagickTrue;
4865 x_offset=(ssize_t) floor(x);
4866 y_offset=(ssize_t) floor(y);
anthonycf4e33d2012-06-08 07:33:23 +00004867 interpolate = method;
4868 if ( interpolate == UndefinedInterpolatePixel )
4869 interpolate = source->interpolate;
4870 switch (interpolate)
cristy5c4e2582011-09-11 19:21:03 +00004871 {
anthonycf4e33d2012-06-08 07:33:23 +00004872 case AverageInterpolatePixel: /* nearest 4 neighbours */
4873 case Average9InterpolatePixel: /* nearest 9 neighbours */
4874 case Average16InterpolatePixel: /* nearest 16 neighbours */
cristy5c4e2582011-09-11 19:21:03 +00004875 {
cristyfb122372012-10-17 23:31:21 +00004876 ssize_t
4877 count;
anthonycf4e33d2012-06-08 07:33:23 +00004878
cristyfb122372012-10-17 23:31:21 +00004879 count=2; /* size of the area to average - default nearest 4 */
anthonycf4e33d2012-06-08 07:33:23 +00004880 if (interpolate == Average9InterpolatePixel)
4881 {
4882 count=3;
4883 x_offset=(ssize_t) (floor(x+0.5)-1);
4884 y_offset=(ssize_t) (floor(y+0.5)-1);
4885 }
cristyfb122372012-10-17 23:31:21 +00004886 else
4887 if (interpolate == Average16InterpolatePixel)
4888 {
4889 count=4;
4890 x_offset--;
4891 y_offset--;
4892 }
cristy1b72b812013-04-19 00:57:44 +00004893 p=GetCacheViewVirtualPixels(source_view,x_offset,y_offset,(size_t) count,
4894 (size_t) count,exception);
cristy5c4e2582011-09-11 19:21:03 +00004895 if (p == (const Quantum *) NULL)
4896 {
4897 status=MagickFalse;
4898 break;
4899 }
cristyfb122372012-10-17 23:31:21 +00004900 count*=count; /* Number of pixels to Average */
cristy50e64b82012-06-22 17:46:19 +00004901 for (i=0; i < (ssize_t) GetPixelChannels(source); i++)
cristy5c4e2582011-09-11 19:21:03 +00004902 {
4903 double
4904 sum;
4905
cristy50e64b82012-06-22 17:46:19 +00004906 register ssize_t
cristy5c4e2582011-09-11 19:21:03 +00004907 j;
4908
cristy5a23c552013-02-13 14:34:28 +00004909 PixelChannel channel=GetPixelChannelChannel(source,i);
4910 PixelTrait traits=GetPixelChannelTraits(source,channel);
4911 PixelTrait destination_traits=GetPixelChannelTraits(destination,
4912 channel);
cristy5c4e2582011-09-11 19:21:03 +00004913 if ((traits == UndefinedPixelTrait) ||
4914 (destination_traits == UndefinedPixelTrait))
4915 continue;
cristy50e64b82012-06-22 17:46:19 +00004916 for (j=0; j < (ssize_t) count; j++)
cristya19f1d72012-08-07 18:24:38 +00004917 pixels[j]=(double) p[j*GetPixelChannels(source)+i];
cristy4a7ae692011-12-14 12:24:11 +00004918 sum=0.0;
cristy5c4e2582011-09-11 19:21:03 +00004919 if ((traits & BlendPixelTrait) == 0)
4920 {
cristy50e64b82012-06-22 17:46:19 +00004921 for (j=0; j < (ssize_t) count; j++)
anthonycf4e33d2012-06-08 07:33:23 +00004922 sum+=pixels[j];
4923 sum/=count;
cristy4a7ae692011-12-14 12:24:11 +00004924 SetPixelChannel(destination,channel,ClampToQuantum(sum),pixel);
cristy5c4e2582011-09-11 19:21:03 +00004925 continue;
4926 }
cristy50e64b82012-06-22 17:46:19 +00004927 for (j=0; j < (ssize_t) count; j++)
cristy5c4e2582011-09-11 19:21:03 +00004928 {
4929 alpha[j]=QuantumScale*GetPixelAlpha(source,p+j*
4930 GetPixelChannels(source));
4931 pixels[j]*=alpha[j];
cristy3e3ec3a2012-11-03 23:11:06 +00004932 gamma=PerceptibleReciprocal(alpha[j]);
anthonycf4e33d2012-06-08 07:33:23 +00004933 sum+=gamma*pixels[j];
cristy5c4e2582011-09-11 19:21:03 +00004934 }
anthonycf4e33d2012-06-08 07:33:23 +00004935 sum/=count;
cristy4a7ae692011-12-14 12:24:11 +00004936 SetPixelChannel(destination,channel,ClampToQuantum(sum),pixel);
cristy5c4e2582011-09-11 19:21:03 +00004937 }
4938 break;
4939 }
anthonycf4e33d2012-06-08 07:33:23 +00004940 case BilinearInterpolatePixel:
4941 default:
4942 {
4943 p=GetCacheViewVirtualPixels(source_view,x_offset,y_offset,2,2,exception);
4944 if (p == (const Quantum *) NULL)
4945 {
4946 status=MagickFalse;
4947 break;
4948 }
cristy50e64b82012-06-22 17:46:19 +00004949 for (i=0; i < (ssize_t) GetPixelChannels(source); i++)
anthonycf4e33d2012-06-08 07:33:23 +00004950 {
4951 PointInfo
4952 delta,
4953 epsilon;
4954
cristy5a23c552013-02-13 14:34:28 +00004955 PixelChannel channel=GetPixelChannelChannel(source,i);
4956 PixelTrait traits=GetPixelChannelTraits(source,channel);
4957 PixelTrait destination_traits=GetPixelChannelTraits(destination,
4958 channel);
anthonycf4e33d2012-06-08 07:33:23 +00004959 if ((traits == UndefinedPixelTrait) ||
4960 (destination_traits == UndefinedPixelTrait))
4961 continue;
4962 delta.x=x-x_offset;
4963 delta.y=y-y_offset;
4964 epsilon.x=1.0-delta.x;
4965 epsilon.y=1.0-delta.y;
cristya19f1d72012-08-07 18:24:38 +00004966 pixels[0]=(double) p[i];
4967 pixels[1]=(double) p[GetPixelChannels(source)+i];
4968 pixels[2]=(double) p[2*GetPixelChannels(source)+i];
4969 pixels[3]=(double) p[3*GetPixelChannels(source)+i];
anthonycf4e33d2012-06-08 07:33:23 +00004970 if ((traits & BlendPixelTrait) == 0)
4971 {
4972 gamma=((epsilon.y*(epsilon.x+delta.x)+delta.y*(epsilon.x+delta.x)));
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*
4976 pixels[2]+delta.x*pixels[3]))),pixel);
4977 continue;
4978 }
4979 alpha[0]=QuantumScale*GetPixelAlpha(source,p);
4980 alpha[1]=QuantumScale*GetPixelAlpha(source,p+GetPixelChannels(source));
4981 alpha[2]=QuantumScale*GetPixelAlpha(source,p+2*
4982 GetPixelChannels(source));
4983 alpha[3]=QuantumScale*GetPixelAlpha(source,p+3*
4984 GetPixelChannels(source));
4985 pixels[0]*=alpha[0];
4986 pixels[1]*=alpha[1];
4987 pixels[2]*=alpha[2];
4988 pixels[3]*=alpha[3];
4989 gamma=((epsilon.y*(epsilon.x*alpha[0]+delta.x*alpha[1])+delta.y*
4990 (epsilon.x*alpha[2]+delta.x*alpha[3])));
cristy3e3ec3a2012-11-03 23:11:06 +00004991 gamma=PerceptibleReciprocal(gamma);
anthonycf4e33d2012-06-08 07:33:23 +00004992 SetPixelChannel(destination,channel,ClampToQuantum(gamma*(epsilon.y*
4993 (epsilon.x*pixels[0]+delta.x*pixels[1])+delta.y*(epsilon.x*pixels[2]+
4994 delta.x*pixels[3]))),pixel);
4995 }
4996 break;
4997 }
anthony5f78bca2012-10-05 06:51:00 +00004998 case BlendInterpolatePixel:
4999 {
5000 p=GetCacheViewVirtualPixels(source_view,x_offset,y_offset,2,2,exception);
5001 if (p == (const Quantum *) NULL)
5002 {
5003 status=MagickFalse;
5004 break;
5005 }
5006 for (i=0; i < (ssize_t) GetPixelChannels(source); i++)
5007 {
5008 register ssize_t
5009 j;
5010
cristy5a23c552013-02-13 14:34:28 +00005011 PixelChannel channel=GetPixelChannelChannel(source,i);
5012 PixelTrait traits=GetPixelChannelTraits(source,channel);
5013 PixelTrait destination_traits=GetPixelChannelTraits(destination,
5014 channel);
anthony5f78bca2012-10-05 06:51:00 +00005015 if ((traits == UndefinedPixelTrait) ||
5016 (destination_traits == UndefinedPixelTrait))
5017 continue;
5018 if ((traits & BlendPixelTrait) == 0)
5019 for (j=0; j < 4; j++)
5020 {
5021 alpha[j]=1.0;
5022 pixels[j]=(MagickRealType) p[j*GetPixelChannels(source)+channel];
5023 }
5024 else
5025 for (j=0; j < 4; j++)
5026 {
5027 alpha[j]=QuantumScale*GetPixelAlpha(source,p+j*
5028 GetPixelChannels(source));
5029 pixels[j]=alpha[j]*p[j*GetPixelChannels(source)+channel];
5030 }
cristyfb122372012-10-17 23:31:21 +00005031 gamma=1.0; /* number of pixels blended together (its variable) */
5032 for (j=0; j <= 1L; j++)
5033 {
5034 if ((y-y_offset) >= 0.75)
5035 {
5036 alpha[j]=alpha[j+2]; /* take right pixels */
5037 pixels[j]=pixels[j+2];
5038 }
5039 else
5040 if ((y-y_offset) > 0.25)
5041 {
5042 gamma=2.0; /* blend both pixels in row */
5043 alpha[j]+=alpha[j+2]; /* add up alpha weights */
5044 pixels[j]+=pixels[j+2];
5045 }
5046 }
5047 if ((x-x_offset) >= 0.75)
5048 {
5049 alpha[0]=alpha[1]; /* take bottom row blend */
5050 pixels[0]=pixels[1];
anthony5f78bca2012-10-05 06:51:00 +00005051 }
cristyfb122372012-10-17 23:31:21 +00005052 else
5053 if ((x-x_offset) > 0.25)
5054 {
5055 gamma*=2.0; /* blend both rows */
5056 alpha[0]+=alpha[1]; /* add up alpha weights */
5057 pixels[0]+=pixels[1];
5058 }
anthony5f78bca2012-10-05 06:51:00 +00005059 if ((traits & BlendPixelTrait) == 0)
cristy3e3ec3a2012-11-03 23:11:06 +00005060 gamma=PerceptibleReciprocal(alpha[0]); /* (color) 1/alpha_weights */
anthony5f78bca2012-10-05 06:51:00 +00005061 else
cristy3e3ec3a2012-11-03 23:11:06 +00005062 gamma=PerceptibleReciprocal(gamma); /* (alpha) 1/number_of_pixels */
anthony5f78bca2012-10-05 06:51:00 +00005063 SetPixelChannel(destination,channel,ClampToQuantum(gamma*pixels[0]),
cristyfb122372012-10-17 23:31:21 +00005064 pixel);
anthony5f78bca2012-10-05 06:51:00 +00005065 }
5066 break;
5067 }
anthonycf4e33d2012-06-08 07:33:23 +00005068 case CatromInterpolatePixel:
cristy5c4e2582011-09-11 19:21:03 +00005069 {
cristya19f1d72012-08-07 18:24:38 +00005070 double
cristy380a11c2012-06-02 15:15:22 +00005071 cx[4],
5072 cy[4];
cristy5c4e2582011-09-11 19:21:03 +00005073
cristy5c4e2582011-09-11 19:21:03 +00005074 p=GetCacheViewVirtualPixels(source_view,x_offset-1,y_offset-1,4,4,
5075 exception);
5076 if (p == (const Quantum *) NULL)
5077 {
5078 status=MagickFalse;
5079 break;
5080 }
cristy50e64b82012-06-22 17:46:19 +00005081 for (i=0; i < (ssize_t) GetPixelChannels(source); i++)
cristy5c4e2582011-09-11 19:21:03 +00005082 {
5083 register ssize_t
5084 j;
5085
cristy5a23c552013-02-13 14:34:28 +00005086 PixelChannel channel=GetPixelChannelChannel(source,i);
5087 PixelTrait traits=GetPixelChannelTraits(source,channel);
5088 PixelTrait destination_traits=GetPixelChannelTraits(destination,
5089 channel);
cristy5c4e2582011-09-11 19:21:03 +00005090 if ((traits == UndefinedPixelTrait) ||
5091 (destination_traits == UndefinedPixelTrait))
5092 continue;
5093 if ((traits & BlendPixelTrait) == 0)
5094 for (j=0; j < 16; j++)
5095 {
5096 alpha[j]=1.0;
cristya19f1d72012-08-07 18:24:38 +00005097 pixels[j]=(double) p[j*GetPixelChannels(source)+i];
cristy5c4e2582011-09-11 19:21:03 +00005098 }
5099 else
5100 for (j=0; j < 16; j++)
5101 {
5102 alpha[j]=QuantumScale*GetPixelAlpha(source,p+j*
5103 GetPixelChannels(source));
5104 pixels[j]=alpha[j]*p[j*GetPixelChannels(source)+i];
5105 }
cristya19f1d72012-08-07 18:24:38 +00005106 CatromWeights((double) (x-x_offset),&cx);
5107 CatromWeights((double) (y-y_offset),&cy);
5108 gamma=((traits & BlendPixelTrait) ? (double) (1.0) :
cristy3e3ec3a2012-11-03 23:11:06 +00005109 PerceptibleReciprocal(cy[0]*(cx[0]*alpha[0]+cx[1]*alpha[1]+cx[2]*
nicolasd32d5e52012-06-12 15:34:10 +00005110 alpha[2]+cx[3]*alpha[3])+cy[1]*(cx[0]*alpha[4]+cx[1]*alpha[5]+cx[2]*
5111 alpha[6]+cx[3]*alpha[7])+cy[2]*(cx[0]*alpha[8]+cx[1]*alpha[9]+cx[2]*
5112 alpha[10]+cx[3]*alpha[11])+cy[3]*(cx[0]*alpha[12]+cx[1]*alpha[13]+
5113 cx[2]*alpha[14]+cx[3]*alpha[15])));
cristy380a11c2012-06-02 15:15:22 +00005114 SetPixelChannel(destination,channel,ClampToQuantum(gamma*(cy[0]*(cx[0]*
5115 pixels[0]+cx[1]*pixels[1]+cx[2]*pixels[2]+cx[3]*pixels[3])+cy[1]*
5116 (cx[0]*pixels[4]+cx[1]*pixels[5]+cx[2]*pixels[6]+cx[3]*pixels[7])+
5117 cy[2]*(cx[0]*pixels[8]+cx[1]*pixels[9]+cx[2]*pixels[10]+cx[3]*
nicolasd32d5e52012-06-12 15:34:10 +00005118 pixels[11])+cy[3]*(cx[0]*pixels[12]+cx[1]*pixels[13]+cx[2]*
5119 pixels[14]+cx[3]*pixels[15]))),pixel);
cristy5c4e2582011-09-11 19:21:03 +00005120 }
5121 break;
5122 }
anthonycf4e33d2012-06-08 07:33:23 +00005123#if 0
nicolas20075dc2012-06-12 20:47:38 +00005124 /* deprecated useless and very slow interpolator */
cristy5c4e2582011-09-11 19:21:03 +00005125 case FilterInterpolatePixel:
5126 {
cristy50e64b82012-06-22 17:46:19 +00005127 for (i=0; i < (ssize_t) GetPixelChannels(source); i++)
cristy5c4e2582011-09-11 19:21:03 +00005128 {
5129 CacheView
5130 *filter_view;
5131
5132 Image
5133 *excerpt_source,
5134 *filter_source;
5135
5136 RectangleInfo
5137 geometry;
5138
cristy5a23c552013-02-13 14:34:28 +00005139 PixelChannel channel=GetPixelChannelChannel(source,i);
5140 PixelTrait traits=GetPixelChannelTraits(source,channel);
5141 PixelTrait destination_traits=GetPixelChannelTraits(destination,
5142 channel);
cristy5c4e2582011-09-11 19:21:03 +00005143 if ((traits == UndefinedPixelTrait) ||
5144 (destination_traits == UndefinedPixelTrait))
5145 continue;
5146 geometry.width=4L;
5147 geometry.height=4L;
5148 geometry.x=x_offset-1;
5149 geometry.y=y_offset-1;
5150 excerpt_source=ExcerptImage(source,&geometry,exception);
5151 if (excerpt_source == (Image *) NULL)
5152 {
5153 status=MagickFalse;
5154 continue;
5155 }
cristyaa2c16c2012-03-25 22:21:35 +00005156 filter_source=ResizeImage(excerpt_source,1,1,source->filter,exception);
cristy5c4e2582011-09-11 19:21:03 +00005157 excerpt_source=DestroyImage(excerpt_source);
5158 if (filter_source == (Image *) NULL)
5159 continue;
cristy46ff2672012-12-14 15:32:26 +00005160 filter_view=AcquireVirtualCacheView(filter_source,exception);
cristy5c4e2582011-09-11 19:21:03 +00005161 p=GetCacheViewVirtualPixels(filter_view,0,0,1,1,exception);
5162 if (p == (const Quantum *) NULL)
5163 status=MagickFalse;
5164 else
cristy1861c902011-12-14 02:30:00 +00005165 {
cristy4a7ae692011-12-14 12:24:11 +00005166 SetPixelChannel(destination,channel,p[i],pixel);
cristy1861c902011-12-14 02:30:00 +00005167 }
cristy5c4e2582011-09-11 19:21:03 +00005168 filter_view=DestroyCacheView(filter_view);
5169 filter_source=DestroyImage(filter_source);
5170 }
5171 break;
5172 }
anthonycf4e33d2012-06-08 07:33:23 +00005173#endif
cristy5c4e2582011-09-11 19:21:03 +00005174 case IntegerInterpolatePixel:
5175 {
5176 p=GetCacheViewVirtualPixels(source_view,x_offset,y_offset,1,1,exception);
5177 if (p == (const Quantum *) NULL)
5178 {
5179 status=MagickFalse;
5180 break;
5181 }
cristy50e64b82012-06-22 17:46:19 +00005182 for (i=0; i < (ssize_t) GetPixelChannels(source); i++)
cristy5c4e2582011-09-11 19:21:03 +00005183 {
cristy5a23c552013-02-13 14:34:28 +00005184 PixelChannel channel=GetPixelChannelChannel(source,i);
5185 PixelTrait traits=GetPixelChannelTraits(source,channel);
5186 PixelTrait destination_traits=GetPixelChannelTraits(destination,
5187 channel);
cristy5c4e2582011-09-11 19:21:03 +00005188 if ((traits == UndefinedPixelTrait) ||
5189 (destination_traits == UndefinedPixelTrait))
5190 continue;
cristy4a7ae692011-12-14 12:24:11 +00005191 SetPixelChannel(destination,channel,p[i],pixel);
cristy5c4e2582011-09-11 19:21:03 +00005192 }
5193 break;
5194 }
anthonycf4e33d2012-06-08 07:33:23 +00005195 case NearestInterpolatePixel:
cristy5c4e2582011-09-11 19:21:03 +00005196 {
anthonycf4e33d2012-06-08 07:33:23 +00005197 x_offset=(ssize_t) floor(x+0.5);
5198 y_offset=(ssize_t) floor(y+0.5);
5199 p=GetCacheViewVirtualPixels(source_view,x_offset,y_offset,1,1,exception);
cristy5c4e2582011-09-11 19:21:03 +00005200 if (p == (const Quantum *) NULL)
5201 {
5202 status=MagickFalse;
5203 break;
5204 }
cristy50e64b82012-06-22 17:46:19 +00005205 for (i=0; i < (ssize_t) GetPixelChannels(source); i++)
cristy5c4e2582011-09-11 19:21:03 +00005206 {
cristy5a23c552013-02-13 14:34:28 +00005207 PixelChannel channel=GetPixelChannelChannel(source,i);
5208 PixelTrait traits=GetPixelChannelTraits(source,channel);
5209 PixelTrait destination_traits=GetPixelChannelTraits(destination,
5210 channel);
cristy5c4e2582011-09-11 19:21:03 +00005211 if ((traits == UndefinedPixelTrait) ||
5212 (destination_traits == UndefinedPixelTrait))
5213 continue;
cristy4a7ae692011-12-14 12:24:11 +00005214 SetPixelChannel(destination,channel,p[i],pixel);
cristy5c4e2582011-09-11 19:21:03 +00005215 }
5216 break;
5217 }
5218 case MeshInterpolatePixel:
5219 {
5220 p=GetCacheViewVirtualPixels(source_view,x_offset,y_offset,2,2,exception);
5221 if (p == (const Quantum *) NULL)
5222 {
5223 status=MagickFalse;
5224 break;
5225 }
cristy50e64b82012-06-22 17:46:19 +00005226 for (i=0; i < (ssize_t) GetPixelChannels(source); i++)
cristy5c4e2582011-09-11 19:21:03 +00005227 {
5228 PointInfo
5229 delta,
5230 luminance;
5231
cristy5a23c552013-02-13 14:34:28 +00005232 PixelChannel channel=GetPixelChannelChannel(source,i);
5233 PixelTrait traits=GetPixelChannelTraits(source,channel);
5234 PixelTrait destination_traits=GetPixelChannelTraits(destination,
5235 channel);
cristy5c4e2582011-09-11 19:21:03 +00005236 if ((traits == UndefinedPixelTrait) ||
5237 (destination_traits == UndefinedPixelTrait))
5238 continue;
cristya19f1d72012-08-07 18:24:38 +00005239 pixels[0]=(double) p[i];
5240 pixels[1]=(double) p[GetPixelChannels(source)+i];
5241 pixels[2]=(double) p[2*GetPixelChannels(source)+i];
5242 pixels[3]=(double) p[3*GetPixelChannels(source)+i];
cristy1861c902011-12-14 02:30:00 +00005243 if ((traits & BlendPixelTrait) == 0)
5244 {
5245 alpha[0]=1.0;
5246 alpha[1]=1.0;
5247 alpha[2]=1.0;
5248 alpha[3]=1.0;
5249 }
5250 else
5251 {
5252 alpha[0]=QuantumScale*GetPixelAlpha(source,p);
5253 alpha[1]=QuantumScale*GetPixelAlpha(source,p+
5254 GetPixelChannels(source));
5255 alpha[2]=QuantumScale*GetPixelAlpha(source,p+2*
5256 GetPixelChannels(source));
5257 alpha[3]=QuantumScale*GetPixelAlpha(source,p+3*
5258 GetPixelChannels(source));
5259 }
5260 delta.x=x-x_offset;
5261 delta.y=y-y_offset;
cristyfb122372012-10-17 23:31:21 +00005262 luminance.x=fabs((double) (GetPixelLuminance(source,p)-
5263 GetPixelLuminance(source,p+3*GetPixelChannels(source))));
5264 luminance.y=fabs((double) (GetPixelLuminance(source,p+
5265 GetPixelChannels(source))-GetPixelLuminance(source,p+2*
5266 GetPixelChannels(source))));
anthonycf4e33d2012-06-08 07:33:23 +00005267 if (luminance.x < luminance.y)
cristy1861c902011-12-14 02:30:00 +00005268 {
5269 /*
5270 Diagonal 0-3 NW-SE.
5271 */
5272 if (delta.x <= delta.y)
5273 {
5274 /*
5275 Bottom-left triangle (pixel: 2, diagonal: 0-3).
5276 */
5277 delta.y=1.0-delta.y;
5278 gamma=MeshInterpolate(&delta,alpha[2],alpha[3],alpha[0]);
cristy3e3ec3a2012-11-03 23:11:06 +00005279 gamma=PerceptibleReciprocal(gamma);
cristy4a7ae692011-12-14 12:24:11 +00005280 SetPixelChannel(destination,channel,ClampToQuantum(gamma*
5281 MeshInterpolate(&delta,pixels[2],pixels[3],pixels[0])),pixel);
cristy1861c902011-12-14 02:30:00 +00005282 }
5283 else
5284 {
5285 /*
5286 Top-right triangle (pixel: 1, diagonal: 0-3).
5287 */
5288 delta.x=1.0-delta.x;
5289 gamma=MeshInterpolate(&delta,alpha[1],alpha[0],alpha[3]);
cristy3e3ec3a2012-11-03 23:11:06 +00005290 gamma=PerceptibleReciprocal(gamma);
cristy4a7ae692011-12-14 12:24:11 +00005291 SetPixelChannel(destination,channel,ClampToQuantum(gamma*
5292 MeshInterpolate(&delta,pixels[1],pixels[0],pixels[3])),pixel);
cristy1861c902011-12-14 02:30:00 +00005293 }
5294 }
5295 else
5296 {
5297 /*
5298 Diagonal 1-2 NE-SW.
5299 */
5300 if (delta.x <= (1.0-delta.y))
5301 {
5302 /*
5303 Top-left triangle (pixel: 0, diagonal: 1-2).
5304 */
5305 gamma=MeshInterpolate(&delta,alpha[0],alpha[1],alpha[2]);
cristy3e3ec3a2012-11-03 23:11:06 +00005306 gamma=PerceptibleReciprocal(gamma);
cristy4a7ae692011-12-14 12:24:11 +00005307 SetPixelChannel(destination,channel,ClampToQuantum(gamma*
5308 MeshInterpolate(&delta,pixels[0],pixels[1],pixels[2])),pixel);
cristy1861c902011-12-14 02:30:00 +00005309 }
5310 else
5311 {
5312 /*
5313 Bottom-right triangle (pixel: 3, diagonal: 1-2).
5314 */
5315 delta.x=1.0-delta.x;
5316 delta.y=1.0-delta.y;
5317 gamma=MeshInterpolate(&delta,alpha[3],alpha[2],alpha[1]);
cristy3e3ec3a2012-11-03 23:11:06 +00005318 gamma=PerceptibleReciprocal(gamma);
cristy4a7ae692011-12-14 12:24:11 +00005319 SetPixelChannel(destination,channel,ClampToQuantum(gamma*
5320 MeshInterpolate(&delta,pixels[3],pixels[2],pixels[1])),pixel);
cristy1861c902011-12-14 02:30:00 +00005321 }
5322 }
cristy5c4e2582011-09-11 19:21:03 +00005323 }
5324 break;
5325 }
5326 case SplineInterpolatePixel:
5327 {
cristya19f1d72012-08-07 18:24:38 +00005328 double
nicolasd32d5e52012-06-12 15:34:10 +00005329 cx[4],
5330 cy[4];
5331
cristy5c4e2582011-09-11 19:21:03 +00005332 p=GetCacheViewVirtualPixels(source_view,x_offset-1,y_offset-1,4,4,
5333 exception);
5334 if (p == (const Quantum *) NULL)
5335 {
5336 status=MagickFalse;
5337 break;
5338 }
cristy50e64b82012-06-22 17:46:19 +00005339 for (i=0; i < (ssize_t) GetPixelChannels(source); i++)
cristy5c4e2582011-09-11 19:21:03 +00005340 {
cristy5c4e2582011-09-11 19:21:03 +00005341 register ssize_t
5342 j;
5343
cristy5a23c552013-02-13 14:34:28 +00005344 PixelChannel channel=GetPixelChannelChannel(source,i);
5345 PixelTrait traits=GetPixelChannelTraits(source,channel);
5346 PixelTrait destination_traits=GetPixelChannelTraits(destination,
5347 channel);
cristy5c4e2582011-09-11 19:21:03 +00005348 if ((traits == UndefinedPixelTrait) ||
5349 (destination_traits == UndefinedPixelTrait))
5350 continue;
5351 if ((traits & BlendPixelTrait) == 0)
5352 for (j=0; j < 16; j++)
5353 {
5354 alpha[j]=1.0;
cristya19f1d72012-08-07 18:24:38 +00005355 pixels[j]=(double) p[j*GetPixelChannels(source)+i];
cristy5c4e2582011-09-11 19:21:03 +00005356 }
5357 else
5358 for (j=0; j < 16; j++)
5359 {
5360 alpha[j]=QuantumScale*GetPixelAlpha(source,p+j*
5361 GetPixelChannels(source));
5362 pixels[j]=alpha[j]*p[j*GetPixelChannels(source)+i];
5363 }
cristya19f1d72012-08-07 18:24:38 +00005364 SplineWeights((double) (x-x_offset),&cx);
5365 SplineWeights((double) (y-y_offset),&cy);
5366 gamma=((traits & BlendPixelTrait) ? (double) (1.0) :
cristy3e3ec3a2012-11-03 23:11:06 +00005367 PerceptibleReciprocal(cy[0]*(cx[0]*alpha[0]+cx[1]*alpha[1]+cx[2]*
nicolasd32d5e52012-06-12 15:34:10 +00005368 alpha[2]+cx[3]*alpha[3])+cy[1]*(cx[0]*alpha[4]+cx[1]*alpha[5]+cx[2]*
5369 alpha[6]+cx[3]*alpha[7])+cy[2]*(cx[0]*alpha[8]+cx[1]*alpha[9]+cx[2]*
5370 alpha[10]+cx[3]*alpha[11])+cy[3]*(cx[0]*alpha[12]+cx[1]*alpha[13]+
5371 cx[2]*alpha[14]+cx[3]*alpha[15])));
5372 SetPixelChannel(destination,channel,ClampToQuantum(gamma*(cy[0]*(cx[0]*
5373 pixels[0]+cx[1]*pixels[1]+cx[2]*pixels[2]+cx[3]*pixels[3])+cy[1]*
5374 (cx[0]*pixels[4]+cx[1]*pixels[5]+cx[2]*pixels[6]+cx[3]*pixels[7])+
5375 cy[2]*(cx[0]*pixels[8]+cx[1]*pixels[9]+cx[2]*pixels[10]+cx[3]*
5376 pixels[11])+cy[3]*(cx[0]*pixels[12]+cx[1]*pixels[13]+cx[2]*
5377 pixels[14]+cx[3]*pixels[15]))),pixel);
cristy5c4e2582011-09-11 19:21:03 +00005378 }
5379 break;
5380 }
5381 }
5382 return(status);
5383}
5384
5385/*
5386%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5387% %
5388% %
5389% %
cristy9075cdb2011-07-30 01:06:23 +00005390% 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 +00005391% %
5392% %
5393% %
5394%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5395%
cristy884f6002011-07-31 00:51:45 +00005396% InterpolatePixelInfo() applies a pixel interpolation method between a
5397% floating point coordinate and the pixels surrounding that coordinate. No
5398% pixel area resampling, or scaling of the result is performed.
cristy4c08aed2011-07-01 19:47:50 +00005399%
anthonycf4e33d2012-06-08 07:33:23 +00005400% Interpolation is restricted to just RGBKA channels.
5401%
cristy4c08aed2011-07-01 19:47:50 +00005402% The format of the InterpolatePixelInfo method is:
5403%
5404% MagickBooleanType InterpolatePixelInfo(const Image *image,
cristy5c4e2582011-09-11 19:21:03 +00005405% const CacheView *image_view,const PixelInterpolateMethod method,
cristy4c08aed2011-07-01 19:47:50 +00005406% const double x,const double y,PixelInfo *pixel,
5407% ExceptionInfo *exception)
5408%
5409% A description of each parameter follows:
5410%
5411% o image: the image.
5412%
5413% o image_view: the image view.
5414%
5415% o method: the pixel color interpolation method.
5416%
5417% o x,y: A double representing the current (x,y) position of the pixel.
5418%
5419% o pixel: return the interpolated pixel here.
5420%
5421% o exception: return any errors or warnings in this structure.
5422%
5423*/
5424
5425static inline void AlphaBlendPixelInfo(const Image *image,
cristya19f1d72012-08-07 18:24:38 +00005426 const Quantum *pixel,PixelInfo *pixel_info,double *alpha)
cristy4c08aed2011-07-01 19:47:50 +00005427{
cristy8a46d822012-08-28 23:32:39 +00005428 if (image->alpha_trait != BlendPixelTrait)
cristy4c08aed2011-07-01 19:47:50 +00005429 {
5430 *alpha=1.0;
cristya19f1d72012-08-07 18:24:38 +00005431 pixel_info->red=(double) GetPixelRed(image,pixel);
5432 pixel_info->green=(double) GetPixelGreen(image,pixel);
5433 pixel_info->blue=(double) GetPixelBlue(image,pixel);
cristy4c08aed2011-07-01 19:47:50 +00005434 pixel_info->black=0.0;
5435 if (image->colorspace == CMYKColorspace)
cristya19f1d72012-08-07 18:24:38 +00005436 pixel_info->black=(double) GetPixelBlack(image,pixel);
5437 pixel_info->alpha=(double) GetPixelAlpha(image,pixel);
cristy4c08aed2011-07-01 19:47:50 +00005438 return;
5439 }
5440 *alpha=QuantumScale*GetPixelAlpha(image,pixel);
5441 pixel_info->red=(*alpha*GetPixelRed(image,pixel));
5442 pixel_info->green=(*alpha*GetPixelGreen(image,pixel));
5443 pixel_info->blue=(*alpha*GetPixelBlue(image,pixel));
5444 pixel_info->black=0.0;
5445 if (image->colorspace == CMYKColorspace)
5446 pixel_info->black=(*alpha*GetPixelBlack(image,pixel));
cristya19f1d72012-08-07 18:24:38 +00005447 pixel_info->alpha=(double) GetPixelAlpha(image,pixel);
cristy4c08aed2011-07-01 19:47:50 +00005448}
5449
cristy4c08aed2011-07-01 19:47:50 +00005450MagickExport MagickBooleanType InterpolatePixelInfo(const Image *image,
cristy5c4e2582011-09-11 19:21:03 +00005451 const CacheView *image_view,const PixelInterpolateMethod method,
cristy4c08aed2011-07-01 19:47:50 +00005452 const double x,const double y,PixelInfo *pixel,ExceptionInfo *exception)
5453{
5454 MagickBooleanType
5455 status;
5456
cristya19f1d72012-08-07 18:24:38 +00005457 double
cristy4c08aed2011-07-01 19:47:50 +00005458 alpha[16],
5459 gamma;
5460
cristy865d58d2011-07-09 00:44:52 +00005461 PixelInfo
5462 pixels[16];
5463
cristy4c08aed2011-07-01 19:47:50 +00005464 register const Quantum
5465 *p;
5466
cristy50e64b82012-06-22 17:46:19 +00005467 register ssize_t
cristy4c08aed2011-07-01 19:47:50 +00005468 i;
5469
5470 ssize_t
5471 x_offset,
5472 y_offset;
5473
anthonycf4e33d2012-06-08 07:33:23 +00005474 PixelInterpolateMethod
5475 interpolate;
5476
cristy4c08aed2011-07-01 19:47:50 +00005477 assert(image != (Image *) NULL);
5478 assert(image->signature == MagickSignature);
5479 assert(image_view != (CacheView *) NULL);
5480 status=MagickTrue;
5481 x_offset=(ssize_t) floor(x);
5482 y_offset=(ssize_t) floor(y);
anthonycf4e33d2012-06-08 07:33:23 +00005483 interpolate = method;
5484 if ( interpolate == UndefinedInterpolatePixel )
5485 interpolate = image->interpolate;
5486 switch (interpolate)
cristy4c08aed2011-07-01 19:47:50 +00005487 {
anthonycf4e33d2012-06-08 07:33:23 +00005488 case AverageInterpolatePixel: /* nearest 4 neighbours */
5489 case Average9InterpolatePixel: /* nearest 9 neighbours */
5490 case Average16InterpolatePixel: /* nearest 16 neighbours */
cristy4c08aed2011-07-01 19:47:50 +00005491 {
cristyfb122372012-10-17 23:31:21 +00005492 ssize_t
5493 count;
anthonycf4e33d2012-06-08 07:33:23 +00005494
cristyfb122372012-10-17 23:31:21 +00005495 count=2; /* size of the area to average - default nearest 4 */
anthonycf4e33d2012-06-08 07:33:23 +00005496 if (interpolate == Average9InterpolatePixel)
5497 {
5498 count=3;
5499 x_offset=(ssize_t) (floor(x+0.5)-1);
5500 y_offset=(ssize_t) (floor(y+0.5)-1);
5501 }
5502 else if (interpolate == Average16InterpolatePixel)
5503 {
5504 count=4;
5505 x_offset--;
5506 y_offset--;
5507 }
cristy70e9f682013-03-12 22:31:22 +00005508 p=GetCacheViewVirtualPixels(image_view,x_offset,y_offset,(size_t) count,(size_t)
5509 count,exception);
cristy4c08aed2011-07-01 19:47:50 +00005510 if (p == (const Quantum *) NULL)
5511 {
5512 status=MagickFalse;
5513 break;
5514 }
cristy4c08aed2011-07-01 19:47:50 +00005515 pixel->red=0.0;
5516 pixel->green=0.0;
5517 pixel->blue=0.0;
cristy4c08aed2011-07-01 19:47:50 +00005518 pixel->black=0.0;
cristy865d58d2011-07-09 00:44:52 +00005519 pixel->alpha=0.0;
anthonycf4e33d2012-06-08 07:33:23 +00005520 count*=count; /* number of pixels - square of size */
cristy50e64b82012-06-22 17:46:19 +00005521 for (i=0; i < (ssize_t) count; i++)
cristy4c08aed2011-07-01 19:47:50 +00005522 {
anthonycf4e33d2012-06-08 07:33:23 +00005523 AlphaBlendPixelInfo(image,p,pixels,alpha);
cristy3e3ec3a2012-11-03 23:11:06 +00005524 gamma=PerceptibleReciprocal(alpha[0]);
cristyfb122372012-10-17 23:31:21 +00005525 pixel->red+=gamma*pixels[0].red;
5526 pixel->green+=gamma*pixels[0].green;
5527 pixel->blue+=gamma*pixels[0].blue;
5528 pixel->black+=gamma*pixels[0].black;
5529 pixel->alpha+=pixels[0].alpha;
anthonycf4e33d2012-06-08 07:33:23 +00005530 p += GetPixelChannels(image);
cristy4c08aed2011-07-01 19:47:50 +00005531 }
anthonycf4e33d2012-06-08 07:33:23 +00005532 gamma=1.0/count; /* average weighting of each pixel in area */
cristyfb122372012-10-17 23:31:21 +00005533 pixel->red*=gamma;
5534 pixel->green*=gamma;
5535 pixel->blue*=gamma;
5536 pixel->black*=gamma;
5537 pixel->alpha*=gamma;
cristy4c08aed2011-07-01 19:47:50 +00005538 break;
5539 }
anthonycf4e33d2012-06-08 07:33:23 +00005540 case BackgroundInterpolatePixel:
5541 {
cristyfb122372012-10-17 23:31:21 +00005542 *pixel=image->background_color; /* Copy PixelInfo Structure */
anthonycf4e33d2012-06-08 07:33:23 +00005543 break;
5544 }
5545 case BilinearInterpolatePixel:
5546 default:
5547 {
5548 PointInfo
5549 delta,
5550 epsilon;
5551
5552 p=GetCacheViewVirtualPixels(image_view,x_offset,y_offset,2,2,exception);
5553 if (p == (const Quantum *) NULL)
5554 {
5555 status=MagickFalse;
5556 break;
5557 }
5558 for (i=0; i < 4L; i++)
5559 AlphaBlendPixelInfo(image,p+i*GetPixelChannels(image),pixels+i,alpha+i);
5560 delta.x=x-x_offset;
5561 delta.y=y-y_offset;
5562 epsilon.x=1.0-delta.x;
5563 epsilon.y=1.0-delta.y;
5564 gamma=((epsilon.y*(epsilon.x*alpha[0]+delta.x*alpha[1])+delta.y*
5565 (epsilon.x*alpha[2]+delta.x*alpha[3])));
cristy3e3ec3a2012-11-03 23:11:06 +00005566 gamma=PerceptibleReciprocal(gamma);
anthonycf4e33d2012-06-08 07:33:23 +00005567 pixel->red=gamma*(epsilon.y*(epsilon.x*pixels[0].red+delta.x*
5568 pixels[1].red)+delta.y*(epsilon.x*pixels[2].red+delta.x*pixels[3].red));
5569 pixel->green=gamma*(epsilon.y*(epsilon.x*pixels[0].green+delta.x*
5570 pixels[1].green)+delta.y*(epsilon.x*pixels[2].green+delta.x*
5571 pixels[3].green));
5572 pixel->blue=gamma*(epsilon.y*(epsilon.x*pixels[0].blue+delta.x*
5573 pixels[1].blue)+delta.y*(epsilon.x*pixels[2].blue+delta.x*
5574 pixels[3].blue));
5575 if (image->colorspace == CMYKColorspace)
5576 pixel->black=gamma*(epsilon.y*(epsilon.x*pixels[0].black+delta.x*
5577 pixels[1].black)+delta.y*(epsilon.x*pixels[2].black+delta.x*
5578 pixels[3].black));
5579 gamma=((epsilon.y*(epsilon.x+delta.x)+delta.y*(epsilon.x+delta.x)));
cristy3e3ec3a2012-11-03 23:11:06 +00005580 gamma=PerceptibleReciprocal(gamma);
anthonycf4e33d2012-06-08 07:33:23 +00005581 pixel->alpha=(epsilon.y*(epsilon.x*pixels[0].alpha+delta.x*
5582 pixels[1].alpha)+delta.y*(epsilon.x*pixels[2].alpha+delta.x*
5583 pixels[3].alpha));
5584 break;
5585 }
5586 case BlendInterpolatePixel:
5587 {
5588 p=GetCacheViewVirtualPixels(image_view,x_offset,y_offset,2,2,exception);
5589 if (p == (const Quantum *) NULL)
5590 {
5591 status=MagickFalse;
5592 break;
5593 }
5594 for (i=0; i < 4L; i++)
5595 AlphaBlendPixelInfo(image,p+i*GetPixelChannels(image),pixels+i,alpha+i);
cristyfb122372012-10-17 23:31:21 +00005596 gamma=1.0; /* number of pixels blended together (its variable) */
5597 for (i=0; i <= 1L; i++)
5598 {
5599 if ((y-y_offset) >= 0.75)
5600 {
5601 alpha[i]=alpha[i+2]; /* take right pixels */
5602 pixels[i]=pixels[i+2];
5603 }
5604 else
5605 if ((y-y_offset) > 0.25)
5606 {
5607 gamma=2.0; /* blend both pixels in row */
5608 alpha[i]+=alpha[i+2]; /* add up alpha weights */
5609 pixels[i].red+=pixels[i+2].red;
5610 pixels[i].green+=pixels[i+2].green;
5611 pixels[i].blue+=pixels[i+2].blue;
5612 pixels[i].black+=pixels[i+2].black;
5613 pixels[i].alpha+=pixels[i+2].alpha;
5614 }
5615 }
5616 if ((x-x_offset) >= 0.75)
5617 {
5618 alpha[0]=alpha[1];
5619 pixels[0]=pixels[1];
anthonycf4e33d2012-06-08 07:33:23 +00005620 }
cristyfb122372012-10-17 23:31:21 +00005621 else
5622 if ((x-x_offset) > 0.25)
5623 {
5624 gamma*=2.0; /* blend both rows */
5625 alpha[0]+= alpha[1]; /* add up alpha weights */
5626 pixels[0].red+=pixels[1].red;
5627 pixels[0].green+=pixels[1].green;
5628 pixels[0].blue+=pixels[1].blue;
5629 pixels[0].black+=pixels[1].black;
5630 pixels[0].alpha+=pixels[1].alpha;
5631 }
5632 gamma=1.0/gamma;
cristy3e3ec3a2012-11-03 23:11:06 +00005633 alpha[0]=PerceptibleReciprocal(alpha[0]);
cristyfb122372012-10-17 23:31:21 +00005634 pixel->red=alpha[0]*pixels[0].red;
5635 pixel->green=alpha[0]*pixels[0].green; /* divide by sum of alpha */
5636 pixel->blue=alpha[0]*pixels[0].blue;
5637 pixel->black=alpha[0]*pixels[0].black;
5638 pixel->alpha=gamma*pixels[0].alpha; /* divide by number of pixels */
anthonycf4e33d2012-06-08 07:33:23 +00005639 break;
5640 }
5641 case CatromInterpolatePixel:
cristy4c08aed2011-07-01 19:47:50 +00005642 {
cristya19f1d72012-08-07 18:24:38 +00005643 double
cristy380a11c2012-06-02 15:15:22 +00005644 cx[4],
5645 cy[4];
cristy4c08aed2011-07-01 19:47:50 +00005646
cristy4c08aed2011-07-01 19:47:50 +00005647 p=GetCacheViewVirtualPixels(image_view,x_offset-1,y_offset-1,4,4,
5648 exception);
5649 if (p == (const Quantum *) NULL)
5650 {
5651 status=MagickFalse;
5652 break;
5653 }
anthonycf4e33d2012-06-08 07:33:23 +00005654 for (i=0; i < 16L; i++)
5655 AlphaBlendPixelInfo(image,p+i*GetPixelChannels(image),pixels+i,alpha+i);
cristya19f1d72012-08-07 18:24:38 +00005656 CatromWeights((double) (x-x_offset),&cx);
5657 CatromWeights((double) (y-y_offset),&cy);
cristyfb122372012-10-17 23:31:21 +00005658 pixel->red=(cy[0]*(cx[0]*pixels[0].red+cx[1]*pixels[1].red+cx[2]*
5659 pixels[2].red+cx[3]*pixels[3].red)+cy[1]*(cx[0]*pixels[4].red+cx[1]*
5660 pixels[5].red+cx[2]*pixels[6].red+cx[3]*pixels[7].red)+cy[2]*(cx[0]*
5661 pixels[8].red+cx[1]*pixels[9].red+cx[2]*pixels[10].red+cx[3]*
5662 pixels[11].red)+cy[3]*(cx[0]*pixels[12].red+cx[1]*pixels[13].red+cx[2]*
5663 pixels[14].red+cx[3]*pixels[15].red));
5664 pixel->green=(cy[0]*(cx[0]*pixels[0].green+cx[1]*pixels[1].green+cx[2]*
5665 pixels[2].green+cx[3]*pixels[3].green)+cy[1]*(cx[0]*pixels[4].green+
5666 cx[1]*pixels[5].green+cx[2]*pixels[6].green+cx[3]*pixels[7].green)+
5667 cy[2]*(cx[0]*pixels[8].green+cx[1]*pixels[9].green+cx[2]*
5668 pixels[10].green+cx[3]*pixels[11].green)+cy[3]*(cx[0]*
5669 pixels[12].green+cx[1]*pixels[13].green+cx[2]*pixels[14].green+cx[3]*
5670 pixels[15].green));
5671 pixel->blue=(cy[0]*(cx[0]*pixels[0].blue+cx[1]*pixels[1].blue+cx[2]*
5672 pixels[2].blue+cx[3]*pixels[3].blue)+cy[1]*(cx[0]*pixels[4].blue+cx[1]*
5673 pixels[5].blue+cx[2]*pixels[6].blue+cx[3]*pixels[7].blue)+cy[2]*(cx[0]*
5674 pixels[8].blue+cx[1]*pixels[9].blue+cx[2]*pixels[10].blue+cx[3]*
5675 pixels[11].blue)+cy[3]*(cx[0]*pixels[12].blue+cx[1]*pixels[13].blue+
5676 cx[2]*pixels[14].blue+cx[3]*pixels[15].blue));
cristy380a11c2012-06-02 15:15:22 +00005677 if (image->colorspace == CMYKColorspace)
cristyfb122372012-10-17 23:31:21 +00005678 pixel->black=(cy[0]*(cx[0]*pixels[0].black+cx[1]*pixels[1].black+cx[2]*
5679 pixels[2].black+cx[3]*pixels[3].black)+cy[1]*(cx[0]*pixels[4].black+
5680 cx[1]*pixels[5].black+cx[2]*pixels[6].black+cx[3]*pixels[7].black)+
5681 cy[2]*(cx[0]*pixels[8].black+cx[1]*pixels[9].black+cx[2]*
5682 pixels[10].black+cx[3]*pixels[11].black)+cy[3]*(cx[0]*
5683 pixels[12].black+cx[1]*pixels[13].black+cx[2]*pixels[14].black+cx[3]*
5684 pixels[15].black));
5685 pixel->alpha=(cy[0]*(cx[0]*pixels[0].alpha+cx[1]*pixels[1].alpha+cx[2]*
5686 pixels[2].alpha+cx[3]*pixels[3].alpha)+cy[1]*(cx[0]*pixels[4].alpha+
5687 cx[1]*pixels[5].alpha+cx[2]*pixels[6].alpha+cx[3]*pixels[7].alpha)+
5688 cy[2]*(cx[0]*pixels[8].alpha+cx[1]*pixels[9].alpha+cx[2]*
5689 pixels[10].alpha+cx[3]*pixels[11].alpha)+cy[3]*(cx[0]*pixels[12].alpha+
5690 cx[1]*pixels[13].alpha+cx[2]*pixels[14].alpha+cx[3]*pixels[15].alpha));
cristy4c08aed2011-07-01 19:47:50 +00005691 break;
5692 }
anthonycf4e33d2012-06-08 07:33:23 +00005693#if 0
nicolas20075dc2012-06-12 20:47:38 +00005694 /* deprecated useless and very slow interpolator */
cristy4c08aed2011-07-01 19:47:50 +00005695 case FilterInterpolatePixel:
5696 {
5697 CacheView
5698 *filter_view;
5699
5700 Image
5701 *excerpt_image,
5702 *filter_image;
5703
5704 RectangleInfo
5705 geometry;
5706
5707 geometry.width=4L;
5708 geometry.height=4L;
5709 geometry.x=x_offset-1;
5710 geometry.y=y_offset-1;
5711 excerpt_image=ExcerptImage(image,&geometry,exception);
5712 if (excerpt_image == (Image *) NULL)
5713 {
5714 status=MagickFalse;
5715 break;
5716 }
cristyaa2c16c2012-03-25 22:21:35 +00005717 filter_image=ResizeImage(excerpt_image,1,1,image->filter,exception);
cristy4c08aed2011-07-01 19:47:50 +00005718 excerpt_image=DestroyImage(excerpt_image);
5719 if (filter_image == (Image *) NULL)
5720 break;
cristy46ff2672012-12-14 15:32:26 +00005721 filter_view=AcquireVirtualCacheView(filter_image,exception);
cristy4c08aed2011-07-01 19:47:50 +00005722 p=GetCacheViewVirtualPixels(filter_view,0,0,1,1,exception);
5723 if (p != (const Quantum *) NULL)
cristy803640d2011-11-17 02:11:32 +00005724 GetPixelInfoPixel(image,p,pixel);
cristy4c08aed2011-07-01 19:47:50 +00005725 filter_view=DestroyCacheView(filter_view);
5726 filter_image=DestroyImage(filter_image);
5727 break;
5728 }
anthonycf4e33d2012-06-08 07:33:23 +00005729#endif
cristy4c08aed2011-07-01 19:47:50 +00005730 case IntegerInterpolatePixel:
5731 {
5732 p=GetCacheViewVirtualPixels(image_view,x_offset,y_offset,1,1,exception);
5733 if (p == (const Quantum *) NULL)
5734 {
5735 status=MagickFalse;
5736 break;
5737 }
cristy803640d2011-11-17 02:11:32 +00005738 GetPixelInfoPixel(image,p,pixel);
cristy4c08aed2011-07-01 19:47:50 +00005739 break;
5740 }
5741 case MeshInterpolatePixel:
5742 {
5743 PointInfo
5744 delta,
5745 luminance;
5746
cristy94ea1632011-07-30 20:40:25 +00005747 p=GetCacheViewVirtualPixels(image_view,x_offset,y_offset,2,2,exception);
cristy4c08aed2011-07-01 19:47:50 +00005748 if (p == (const Quantum *) NULL)
5749 {
5750 status=MagickFalse;
5751 break;
5752 }
cristy94ea1632011-07-30 20:40:25 +00005753 delta.x=x-x_offset;
5754 delta.y=y-y_offset;
cristy884f6002011-07-31 00:51:45 +00005755 luminance.x=GetPixelLuminance(image,p)-(double)
cristy94ea1632011-07-30 20:40:25 +00005756 GetPixelLuminance(image,p+3*GetPixelChannels(image));
cristy28474bf2011-09-11 23:32:52 +00005757 luminance.y=GetPixelLuminance(image,p+GetPixelChannels(image))-(double)
cristy94ea1632011-07-30 20:40:25 +00005758 GetPixelLuminance(image,p+2*GetPixelChannels(image));
cristy5ce8df82011-07-07 14:52:23 +00005759 AlphaBlendPixelInfo(image,p,pixels+0,alpha+0);
cristy28474bf2011-09-11 23:32:52 +00005760 AlphaBlendPixelInfo(image,p+GetPixelChannels(image),pixels+1,alpha+1);
cristyed231572011-07-14 02:18:59 +00005761 AlphaBlendPixelInfo(image,p+2*GetPixelChannels(image),pixels+2,alpha+2);
5762 AlphaBlendPixelInfo(image,p+3*GetPixelChannels(image),pixels+3,alpha+3);
cristy4c08aed2011-07-01 19:47:50 +00005763 if (fabs(luminance.x) < fabs(luminance.y))
5764 {
5765 /*
5766 Diagonal 0-3 NW-SE.
5767 */
5768 if (delta.x <= delta.y)
5769 {
5770 /*
cristy94ea1632011-07-30 20:40:25 +00005771 Bottom-left triangle (pixel: 2, diagonal: 0-3).
cristy4c08aed2011-07-01 19:47:50 +00005772 */
5773 delta.y=1.0-delta.y;
5774 gamma=MeshInterpolate(&delta,alpha[2],alpha[3],alpha[0]);
cristy3e3ec3a2012-11-03 23:11:06 +00005775 gamma=PerceptibleReciprocal(gamma);
cristy4c08aed2011-07-01 19:47:50 +00005776 pixel->red=gamma*MeshInterpolate(&delta,pixels[2].red,
5777 pixels[3].red,pixels[0].red);
5778 pixel->green=gamma*MeshInterpolate(&delta,pixels[2].green,
5779 pixels[3].green,pixels[0].green);
5780 pixel->blue=gamma*MeshInterpolate(&delta,pixels[2].blue,
5781 pixels[3].blue,pixels[0].blue);
cristy4c08aed2011-07-01 19:47:50 +00005782 if (image->colorspace == CMYKColorspace)
5783 pixel->black=gamma*MeshInterpolate(&delta,pixels[2].black,
5784 pixels[3].black,pixels[0].black);
cristy94ea1632011-07-30 20:40:25 +00005785 gamma=MeshInterpolate(&delta,1.0,1.0,1.0);
cristy865d58d2011-07-09 00:44:52 +00005786 pixel->alpha=gamma*MeshInterpolate(&delta,pixels[2].alpha,
5787 pixels[3].alpha,pixels[0].alpha);
cristy4c08aed2011-07-01 19:47:50 +00005788 }
5789 else
5790 {
5791 /*
cristy94ea1632011-07-30 20:40:25 +00005792 Top-right triangle (pixel:1 , diagonal: 0-3).
cristy4c08aed2011-07-01 19:47:50 +00005793 */
5794 delta.x=1.0-delta.x;
5795 gamma=MeshInterpolate(&delta,alpha[1],alpha[0],alpha[3]);
cristy3e3ec3a2012-11-03 23:11:06 +00005796 gamma=PerceptibleReciprocal(gamma);
cristy4c08aed2011-07-01 19:47:50 +00005797 pixel->red=gamma*MeshInterpolate(&delta,pixels[1].red,
5798 pixels[0].red,pixels[3].red);
5799 pixel->green=gamma*MeshInterpolate(&delta,pixels[1].green,
5800 pixels[0].green,pixels[3].green);
5801 pixel->blue=gamma*MeshInterpolate(&delta,pixels[1].blue,
5802 pixels[0].blue,pixels[3].blue);
cristy4c08aed2011-07-01 19:47:50 +00005803 if (image->colorspace == CMYKColorspace)
5804 pixel->black=gamma*MeshInterpolate(&delta,pixels[1].black,
5805 pixels[0].black,pixels[3].black);
cristy94ea1632011-07-30 20:40:25 +00005806 gamma=MeshInterpolate(&delta,1.0,1.0,1.0);
cristy865d58d2011-07-09 00:44:52 +00005807 pixel->alpha=gamma*MeshInterpolate(&delta,pixels[1].alpha,
5808 pixels[0].alpha,pixels[3].alpha);
cristy4c08aed2011-07-01 19:47:50 +00005809 }
5810 }
5811 else
5812 {
5813 /*
5814 Diagonal 1-2 NE-SW.
5815 */
5816 if (delta.x <= (1.0-delta.y))
5817 {
5818 /*
cristy94ea1632011-07-30 20:40:25 +00005819 Top-left triangle (pixel: 0, diagonal: 1-2).
cristy4c08aed2011-07-01 19:47:50 +00005820 */
5821 gamma=MeshInterpolate(&delta,alpha[0],alpha[1],alpha[2]);
cristy3e3ec3a2012-11-03 23:11:06 +00005822 gamma=PerceptibleReciprocal(gamma);
cristy4c08aed2011-07-01 19:47:50 +00005823 pixel->red=gamma*MeshInterpolate(&delta,pixels[0].red,
5824 pixels[1].red,pixels[2].red);
5825 pixel->green=gamma*MeshInterpolate(&delta,pixels[0].green,
5826 pixels[1].green,pixels[2].green);
5827 pixel->blue=gamma*MeshInterpolate(&delta,pixels[0].blue,
5828 pixels[1].blue,pixels[2].blue);
cristy4c08aed2011-07-01 19:47:50 +00005829 if (image->colorspace == CMYKColorspace)
5830 pixel->black=gamma*MeshInterpolate(&delta,pixels[0].black,
5831 pixels[1].black,pixels[2].black);
cristy94ea1632011-07-30 20:40:25 +00005832 gamma=MeshInterpolate(&delta,1.0,1.0,1.0);
cristy865d58d2011-07-09 00:44:52 +00005833 pixel->alpha=gamma*MeshInterpolate(&delta,pixels[0].alpha,
5834 pixels[1].alpha,pixels[2].alpha);
cristy4c08aed2011-07-01 19:47:50 +00005835 }
5836 else
5837 {
5838 /*
5839 Bottom-right triangle (pixel: 3, diagonal: 1-2).
5840 */
5841 delta.x=1.0-delta.x;
5842 delta.y=1.0-delta.y;
5843 gamma=MeshInterpolate(&delta,alpha[3],alpha[2],alpha[1]);
cristy3e3ec3a2012-11-03 23:11:06 +00005844 gamma=PerceptibleReciprocal(gamma);
cristy4c08aed2011-07-01 19:47:50 +00005845 pixel->red=gamma*MeshInterpolate(&delta,pixels[3].red,
5846 pixels[2].red,pixels[1].red);
5847 pixel->green=gamma*MeshInterpolate(&delta,pixels[3].green,
5848 pixels[2].green,pixels[1].green);
5849 pixel->blue=gamma*MeshInterpolate(&delta,pixels[3].blue,
5850 pixels[2].blue,pixels[1].blue);
cristy4c08aed2011-07-01 19:47:50 +00005851 if (image->colorspace == CMYKColorspace)
5852 pixel->black=gamma*MeshInterpolate(&delta,pixels[3].black,
5853 pixels[2].black,pixels[1].black);
cristy94ea1632011-07-30 20:40:25 +00005854 gamma=MeshInterpolate(&delta,1.0,1.0,1.0);
cristy865d58d2011-07-09 00:44:52 +00005855 pixel->alpha=gamma*MeshInterpolate(&delta,pixels[3].alpha,
5856 pixels[2].alpha,pixels[1].alpha);
cristy4c08aed2011-07-01 19:47:50 +00005857 }
5858 }
5859 break;
5860 }
anthonycf4e33d2012-06-08 07:33:23 +00005861 case NearestInterpolatePixel:
cristy4c08aed2011-07-01 19:47:50 +00005862 {
anthonycf4e33d2012-06-08 07:33:23 +00005863 x_offset=(ssize_t) floor(x+0.5);
5864 y_offset=(ssize_t) floor(y+0.5);
5865 p=GetCacheViewVirtualPixels(image_view,x_offset,y_offset,1,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00005866 if (p == (const Quantum *) NULL)
5867 {
5868 status=MagickFalse;
5869 break;
5870 }
cristy803640d2011-11-17 02:11:32 +00005871 GetPixelInfoPixel(image,p,pixel);
cristy4c08aed2011-07-01 19:47:50 +00005872 break;
5873 }
5874 case SplineInterpolatePixel:
5875 {
cristya19f1d72012-08-07 18:24:38 +00005876 double
nicolasd32d5e52012-06-12 15:34:10 +00005877 cx[4],
5878 cy[4];
cristy4c08aed2011-07-01 19:47:50 +00005879
5880 p=GetCacheViewVirtualPixels(image_view,x_offset-1,y_offset-1,4,4,
5881 exception);
5882 if (p == (const Quantum *) NULL)
5883 {
5884 status=MagickFalse;
5885 break;
5886 }
anthonycf4e33d2012-06-08 07:33:23 +00005887 for (i=0; i < 16L; i++)
5888 AlphaBlendPixelInfo(image,p+i*GetPixelChannels(image),pixels+i,alpha+i);
cristya19f1d72012-08-07 18:24:38 +00005889 SplineWeights((double) (x-x_offset),&cx);
5890 SplineWeights((double) (y-y_offset),&cy);
cristyfb122372012-10-17 23:31:21 +00005891 pixel->red=(cy[0]*(cx[0]*pixels[0].red+cx[1]*pixels[1].red+cx[2]*
5892 pixels[2].red+cx[3]*pixels[3].red)+cy[1]*(cx[0]*pixels[4].red+cx[1]*
5893 pixels[5].red+cx[2]*pixels[6].red+cx[3]*pixels[7].red)+cy[2]*(cx[0]*
5894 pixels[8].red+cx[1]*pixels[9].red+cx[2]*pixels[10].red+cx[3]*
5895 pixels[11].red)+cy[3]*(cx[0]*pixels[12].red+cx[1]*pixels[13].red+cx[2]*
5896 pixels[14].red+cx[3]*pixels[15].red));
5897 pixel->green=(cy[0]*(cx[0]*pixels[0].green+cx[1]*pixels[1].green+cx[2]*
5898 pixels[2].green+cx[3]*pixels[3].green)+cy[1]*(cx[0]*pixels[4].green+
5899 cx[1]*pixels[5].green+cx[2]*pixels[6].green+cx[3]*pixels[7].green)+
5900 cy[2]*(cx[0]*pixels[8].green+cx[1]*pixels[9].green+cx[2]*
5901 pixels[10].green+cx[3]*pixels[11].green)+cy[3]*(cx[0]*pixels[12].green+
5902 cx[1]*pixels[13].green+cx[2]*pixels[14].green+cx[3]*pixels[15].green));
5903 pixel->blue=(cy[0]*(cx[0]*pixels[0].blue+cx[1]*pixels[1].blue+cx[2]*
5904 pixels[2].blue+cx[3]*pixels[3].blue)+cy[1]*(cx[0]*pixels[4].blue+cx[1]*
5905 pixels[5].blue+cx[2]*pixels[6].blue+cx[3]*pixels[7].blue)+cy[2]*(cx[0]*
5906 pixels[8].blue+cx[1]*pixels[9].blue+cx[2]*pixels[10].blue+cx[3]*
5907 pixels[11].blue)+cy[3]*(cx[0]*pixels[12].blue+cx[1]*pixels[13].blue+
5908 cx[2]*pixels[14].blue+cx[3]*pixels[15].blue));
nicolasd32d5e52012-06-12 15:34:10 +00005909 if (image->colorspace == CMYKColorspace)
cristyfb122372012-10-17 23:31:21 +00005910 pixel->black=(cy[0]*(cx[0]*pixels[0].black+cx[1]*pixels[1].black+cx[2]*
5911 pixels[2].black+cx[3]*pixels[3].black)+cy[1]*(cx[0]*pixels[4].black+
5912 cx[1]*pixels[5].black+cx[2]*pixels[6].black+cx[3]*pixels[7].black)+
5913 cy[2]*(cx[0]*pixels[8].black+cx[1]*pixels[9].black+cx[2]*
5914 pixels[10].black+cx[3]*pixels[11].black)+cy[3]*(cx[0]*
5915 pixels[12].black+cx[1]*pixels[13].black+cx[2]*pixels[14].black+cx[3]*
5916 pixels[15].black));
5917 pixel->alpha=(cy[0]*(cx[0]*pixels[0].alpha+cx[1]*pixels[1].alpha+cx[2]*
5918 pixels[2].alpha+cx[3]*pixels[3].alpha)+cy[1]*(cx[0]*pixels[4].alpha+
5919 cx[1]*pixels[5].alpha+cx[2]*pixels[6].alpha+cx[3]*pixels[7].alpha)+
5920 cy[2]*(cx[0]*pixels[8].alpha+cx[1]*pixels[9].alpha+cx[2]*
5921 pixels[10].alpha+cx[3]*pixels[11].alpha)+cy[3]*(cx[0]*pixels[12].alpha+
5922 cx[1]*pixels[13].alpha+cx[2]*pixels[14].alpha+cx[3]*pixels[15].alpha));
cristy4c08aed2011-07-01 19:47:50 +00005923 break;
5924 }
5925 }
5926 return(status);
5927}
5928
5929/*
5930%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5931% %
5932% %
5933% %
5934+ I s F u z z y E q u i v a l e n c e P i x e l %
5935% %
5936% %
5937% %
5938%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5939%
5940% IsFuzzyEquivalencePixel() returns MagickTrue if the distance between two
5941% pixels is less than the specified distance in a linear three (or four)u
5942% dimensional color space.
5943%
5944% The format of the IsFuzzyEquivalencePixel method is:
5945%
cristye4a40472011-12-22 02:56:19 +00005946% void IsFuzzyEquivalencePixel(const Image *source,const Quantum *p,
5947% const Image *destination,const Quantum *q)
cristy4c08aed2011-07-01 19:47:50 +00005948%
5949% A description of each parameter follows:
5950%
cristye4a40472011-12-22 02:56:19 +00005951% o source: the source image.
cristy4c08aed2011-07-01 19:47:50 +00005952%
5953% o p: Pixel p.
5954%
cristye4a40472011-12-22 02:56:19 +00005955% o destination: the destination image.
5956%
cristy4c08aed2011-07-01 19:47:50 +00005957% o q: Pixel q.
5958%
5959*/
cristye4a40472011-12-22 02:56:19 +00005960MagickExport MagickBooleanType IsFuzzyEquivalencePixel(const Image *source,
5961 const Quantum *p,const Image *destination,const Quantum *q)
cristy4c08aed2011-07-01 19:47:50 +00005962{
cristya19f1d72012-08-07 18:24:38 +00005963 double
cristy4c08aed2011-07-01 19:47:50 +00005964 fuzz,
5965 pixel;
5966
cristya19f1d72012-08-07 18:24:38 +00005967 register double
cristy4c08aed2011-07-01 19:47:50 +00005968 distance,
5969 scale;
5970
cristya19f1d72012-08-07 18:24:38 +00005971 fuzz=MagickMax(source->fuzz,(double) MagickSQ1_2)*MagickMax(
5972 destination->fuzz,(double) MagickSQ1_2);
cristy4c08aed2011-07-01 19:47:50 +00005973 scale=1.0;
5974 distance=0.0;
cristy8a46d822012-08-28 23:32:39 +00005975 if (source->alpha_trait == BlendPixelTrait)
cristy4c08aed2011-07-01 19:47:50 +00005976 {
5977 /*
5978 Transparencies are involved - set alpha distance
5979 */
cristy70e9f682013-03-12 22:31:22 +00005980 pixel=GetPixelAlpha(source,p)-(double) GetPixelAlpha(destination,q);
cristy4c08aed2011-07-01 19:47:50 +00005981 distance=pixel*pixel;
5982 if (distance > fuzz)
5983 return(MagickFalse);
5984 /*
5985 Generate a alpha scaling factor to generate a 4D cone on colorspace
5986 Note that if one color is transparent, distance has no color component.
5987 */
cristye4a40472011-12-22 02:56:19 +00005988 scale=QuantumScale*GetPixelAlpha(source,p);
5989 scale*=QuantumScale*GetPixelAlpha(destination,q);
cristy4c08aed2011-07-01 19:47:50 +00005990 if (scale <= MagickEpsilon)
5991 return(MagickTrue);
5992 }
5993 /*
5994 RGB or CMY color cube
5995 */
5996 distance*=3.0; /* rescale appropriately */
5997 fuzz*=3.0;
cristya19f1d72012-08-07 18:24:38 +00005998 pixel=GetPixelRed(source,p)-(double) GetPixelRed(destination,q);
cristye4a40472011-12-22 02:56:19 +00005999 if ((source->colorspace == HSLColorspace) ||
6000 (source->colorspace == HSBColorspace) ||
6001 (source->colorspace == HWBColorspace))
cristy4c08aed2011-07-01 19:47:50 +00006002 {
6003 /*
6004 Compute an arc distance for hue. It should be a vector angle of
6005 'S'/'W' length with 'L'/'B' forming appropriate cones.
6006 */
6007 if (fabs((double) pixel) > (QuantumRange/2))
6008 pixel-=QuantumRange;
6009 pixel*=2;
6010 }
6011 distance+=scale*pixel*pixel;
6012 if (distance > fuzz)
6013 return(MagickFalse);
cristya19f1d72012-08-07 18:24:38 +00006014 pixel=GetPixelGreen(source,p)-(double) GetPixelGreen(destination,q);
cristy4c08aed2011-07-01 19:47:50 +00006015 distance+=scale*pixel*pixel;
6016 if (distance > fuzz)
6017 return(MagickFalse);
cristya19f1d72012-08-07 18:24:38 +00006018 pixel=GetPixelBlue(source,p)-(double) GetPixelBlue(destination,q);
cristy4c08aed2011-07-01 19:47:50 +00006019 distance+=scale*pixel*pixel;
6020 if (distance > fuzz)
6021 return(MagickFalse);
6022 return(MagickTrue);
6023}
6024
6025/*
6026%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6027% %
6028% %
6029% %
6030+ 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 %
6031% %
6032% %
6033% %
6034%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6035%
6036% IsFuzzyEquivalencePixelInfo() returns true if the distance between two
6037% colors is less than the specified distance in a linear three (or four)
6038% dimensional color space.
6039%
cristy5f95f4f2011-10-23 01:01:01 +00006040% This implements the equivalent of:
6041% fuzz < sqrt(color_distance^2 * u.a*v.a + alpha_distance^2)
cristy4c08aed2011-07-01 19:47:50 +00006042%
6043% Which produces a multi-dimensional cone for that colorspace along the
6044% transparency vector.
6045%
cristy5f95f4f2011-10-23 01:01:01 +00006046% For example for an RGB:
cristy4c08aed2011-07-01 19:47:50 +00006047% color_distance^2 = ( (u.r-v.r)^2 + (u.g-v.g)^2 + (u.b-v.b)^2 ) / 3
6048%
6049% See http://www.imagemagick.org/Usage/bugs/fuzz_distance/
6050%
6051% Hue colorspace distances need more work. Hue is not a distance, it is an
6052% angle!
6053%
6054% A check that q is in the same color space as p should be made and the
6055% appropriate mapping made. -- Anthony Thyssen 8 December 2010
6056%
6057% The format of the IsFuzzyEquivalencePixelInfo method is:
6058%
6059% MagickBooleanType IsFuzzyEquivalencePixelInfo(const PixelInfo *p,
6060% const PixelInfo *q)
6061%
6062% A description of each parameter follows:
6063%
6064% o p: Pixel p.
6065%
6066% o q: Pixel q.
6067%
6068*/
6069MagickExport MagickBooleanType IsFuzzyEquivalencePixelInfo(const PixelInfo *p,
6070 const PixelInfo *q)
6071{
cristya19f1d72012-08-07 18:24:38 +00006072 double
cristy4c08aed2011-07-01 19:47:50 +00006073 fuzz,
6074 pixel;
6075
cristya19f1d72012-08-07 18:24:38 +00006076 register double
cristy4c08aed2011-07-01 19:47:50 +00006077 scale,
6078 distance;
6079
6080 if ((p->fuzz == 0.0) && (q->fuzz == 0.0))
6081 return(IsPixelInfoEquivalent(p,q));
6082 if (p->fuzz == 0.0)
cristy24dc9722013-05-20 16:02:22 +00006083 fuzz=MagickMax(q->fuzz,(double) MagickSQ1_2)*MagickMax(q->fuzz,MagickSQ1_2);
cristy4c08aed2011-07-01 19:47:50 +00006084 else if (q->fuzz == 0.0)
cristy24dc9722013-05-20 16:02:22 +00006085 fuzz=MagickMax(p->fuzz,(double) MagickSQ1_2)*MagickMax(p->fuzz,MagickSQ1_2);
cristy4c08aed2011-07-01 19:47:50 +00006086 else
cristy24dc9722013-05-20 16:02:22 +00006087 fuzz=MagickMax(p->fuzz,(double) MagickSQ1_2)*MagickMax(q->fuzz,MagickSQ1_2);
cristy4c08aed2011-07-01 19:47:50 +00006088 scale=1.0;
6089 distance=0.0;
cristy24dc9722013-05-20 16:02:22 +00006090 if ((p->alpha_trait == BlendPixelTrait) ||
6091 (q->alpha_trait == BlendPixelTrait))
cristy4c08aed2011-07-01 19:47:50 +00006092 {
6093 /*
6094 Transparencies are involved - set alpha distance.
6095 */
cristy8a46d822012-08-28 23:32:39 +00006096 pixel=(p->alpha_trait == BlendPixelTrait ? p->alpha : OpaqueAlpha)-
6097 (q->alpha_trait == BlendPixelTrait ? q->alpha : OpaqueAlpha);
cristy4c08aed2011-07-01 19:47:50 +00006098 distance=pixel*pixel;
6099 if (distance > fuzz)
6100 return(MagickFalse);
6101 /*
6102 Generate a alpha scaling factor to generate a 4D cone on colorspace.
cristy5f95f4f2011-10-23 01:01:01 +00006103 If one color is transparent, distance has no color component.
cristy4c08aed2011-07-01 19:47:50 +00006104 */
cristy8a46d822012-08-28 23:32:39 +00006105 if (p->alpha_trait == BlendPixelTrait)
cristy4c08aed2011-07-01 19:47:50 +00006106 scale=(QuantumScale*p->alpha);
cristy8a46d822012-08-28 23:32:39 +00006107 if (q->alpha_trait == BlendPixelTrait)
cristy4c08aed2011-07-01 19:47:50 +00006108 scale*=(QuantumScale*q->alpha);
6109 if (scale <= MagickEpsilon )
6110 return(MagickTrue);
6111 }
6112 /*
6113 CMYK create a CMY cube with a multi-dimensional cone toward black.
6114 */
6115 if (p->colorspace == CMYKColorspace)
6116 {
6117 pixel=p->black-q->black;
6118 distance+=pixel*pixel*scale;
6119 if (distance > fuzz)
6120 return(MagickFalse);
cristya19f1d72012-08-07 18:24:38 +00006121 scale*=(double) (QuantumScale*(QuantumRange-p->black));
6122 scale*=(double) (QuantumScale*(QuantumRange-q->black));
cristy4c08aed2011-07-01 19:47:50 +00006123 }
6124 /*
6125 RGB or CMY color cube.
6126 */
6127 distance*=3.0; /* rescale appropriately */
6128 fuzz*=3.0;
6129 pixel=p->red-q->red;
6130 if ((p->colorspace == HSLColorspace) || (p->colorspace == HSBColorspace) ||
6131 (p->colorspace == HWBColorspace))
6132 {
cristy5f95f4f2011-10-23 01:01:01 +00006133 /*
6134 This calculates a arc distance for hue-- it should be a vector angle
6135 of 'S'/'W' length with 'L'/'B' forming appropriate cones. In other
6136 words this is a hack - Anthony.
cristy4c08aed2011-07-01 19:47:50 +00006137 */
6138 if (fabs((double) pixel) > (QuantumRange/2))
6139 pixel-=QuantumRange;
6140 pixel*=2;
6141 }
6142 distance+=pixel*pixel*scale;
6143 if (distance > fuzz)
6144 return(MagickFalse);
6145 pixel=p->green-q->green;
6146 distance+=pixel*pixel*scale;
6147 if (distance > fuzz)
6148 return(MagickFalse);
6149 pixel=p->blue-q->blue;
6150 distance+=pixel*pixel*scale;
6151 if (distance > fuzz)
6152 return(MagickFalse);
6153 return(MagickTrue);
6154}
6155
6156/*
6157%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6158% %
6159% %
6160% %
cristy7ae16542013-05-15 22:41:24 +00006161% 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 +00006162% %
6163% %
6164% %
6165%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6166%
cristy7ae16542013-05-15 22:41:24 +00006167% SetPixelChannelMask() sets the pixel channel map from the specified channel
6168% mask.
cristy2b9582a2011-07-04 17:38:56 +00006169%
cristycf1296e2012-08-26 23:40:49 +00006170% The format of the SetPixelChannelMask method is:
cristy2b9582a2011-07-04 17:38:56 +00006171%
cristycf1296e2012-08-26 23:40:49 +00006172% void SetPixelChannelMask(Image *image,const ChannelType channel_mask)
cristy2b9582a2011-07-04 17:38:56 +00006173%
6174% A description of each parameter follows:
6175%
6176% o image: the image.
6177%
cristydfdb19e2012-03-21 22:22:24 +00006178% o channel_mask: the channel mask.
cristy2b9582a2011-07-04 17:38:56 +00006179%
6180*/
cristycf1296e2012-08-26 23:40:49 +00006181MagickExport void SetPixelChannelMask(Image *image,
cristy07a67852011-08-26 13:25:03 +00006182 const ChannelType channel_mask)
cristy2b9582a2011-07-04 17:38:56 +00006183{
cristy6a917d62011-08-24 17:31:30 +00006184#define GetChannelBit(mask,bit) (((size_t) (mask) >> (size_t) (bit)) & 0x01)
cristydafd2872011-07-24 22:06:13 +00006185
cristy2b9582a2011-07-04 17:38:56 +00006186 register ssize_t
6187 i;
6188
cristy177e41c2012-04-15 15:08:25 +00006189 if (image->debug != MagickFalse)
6190 (void) LogMagickEvent(PixelEvent,GetMagickModule(),"%s[%08x]", \
6191 image->filename,channel_mask); \
cristy3c309812011-11-08 02:40:43 +00006192 image->channel_mask=channel_mask;
cristydafd2872011-07-24 22:06:13 +00006193 for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
cristye2a912b2011-12-05 20:02:07 +00006194 {
cristy5a23c552013-02-13 14:34:28 +00006195 PixelChannel channel=GetPixelChannelChannel(image,i);
cristy297e3a42012-08-26 21:27:29 +00006196 SetPixelChannelTraits(image,channel,
cristye2a912b2011-12-05 20:02:07 +00006197 GetChannelBit(channel_mask,channel) == 0 ? CopyPixelTrait :
cristy8a46d822012-08-28 23:32:39 +00006198 image->alpha_trait != BlendPixelTrait || (channel == AlphaPixelChannel) ?
6199 UpdatePixelTrait : (PixelTrait) (UpdatePixelTrait | image->alpha_trait));
cristye2a912b2011-12-05 20:02:07 +00006200 }
cristy1685e722011-09-06 00:04:19 +00006201 if (image->storage_class == PseudoClass)
cristy297e3a42012-08-26 21:27:29 +00006202 SetPixelChannelTraits(image,IndexPixelChannel,CopyPixelTrait);
cristy883fde12013-04-08 00:50:13 +00006203 if (image->read_mask != MagickFalse)
6204 SetPixelChannelTraits(image,ReadMaskPixelChannel,CopyPixelTrait);
6205 if (image->write_mask != MagickFalse)
6206 SetPixelChannelTraits(image,WriteMaskPixelChannel,CopyPixelTrait);
cristy6dcb9b82011-10-23 23:21:25 +00006207 if (image->debug != MagickFalse)
6208 LogPixelChannels(image);
cristy2b9582a2011-07-04 17:38:56 +00006209}
6210
6211/*
6212%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6213% %
6214% %
6215% %
cristy322d07d2012-03-18 21:17:23 +00006216% S e t P i x e l M e t a C h a n n e l s %
6217% %
6218% %
6219% %
6220%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6221%
6222% SetPixelMetaChannels() sets the image meta channels.
6223%
6224% The format of the SetPixelMetaChannels method is:
6225%
6226% MagickBooleanType SetPixelMetaChannels(Image *image,
6227% const size_t number_meta_channels,ExceptionInfo *exception)
6228%
6229% A description of each parameter follows:
6230%
6231% o image: the image.
6232%
6233% o number_meta_channels: the number of meta channels.
6234%
6235% o exception: return any errors or warnings in this structure.
6236%
6237*/
6238MagickExport MagickBooleanType SetPixelMetaChannels(Image *image,
6239 const size_t number_meta_channels,ExceptionInfo *exception)
6240{
6241 image->number_meta_channels=number_meta_channels;
6242 return(SyncImagePixelCache(image,exception));
6243}