1 /*
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 % Cristy %
16 % October 1998 %
17 % %
18 % %
19 % Copyright 1999-2019 ImageMagick Studio LLC, a non-profit organization %
20 % 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 % https://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"
45 #include "MagickCore/cache-private.h"
46 #include "MagickCore/color-private.h"
47 #include "MagickCore/colorspace-private.h"
48 #include "MagickCore/draw.h"
49 #include "MagickCore/exception.h"
50 #include "MagickCore/exception-private.h"
51 #include "MagickCore/cache.h"
52 #include "MagickCore/constitute.h"
53 #include "MagickCore/delegate.h"
54 #include "MagickCore/geometry.h"
55 #include "MagickCore/image-private.h"
56 #include "MagickCore/list.h"
57 #include "MagickCore/magick.h"
58 #include "MagickCore/memory_.h"
59 #include "MagickCore/memory-private.h"
60 #include "MagickCore/monitor.h"
61 #include "MagickCore/option.h"
62 #include "MagickCore/pixel.h"
63 #include "MagickCore/pixel-accessor.h"
64 #include "MagickCore/pixel-private.h"
65 #include "MagickCore/quantum.h"
66 #include "MagickCore/quantum-private.h"
67 #include "MagickCore/resource_.h"
68 #include "MagickCore/semaphore.h"
69 #include "MagickCore/statistic.h"
70 #include "MagickCore/stream.h"
71 #include "MagickCore/string_.h"
72 #include "MagickCore/transform.h"
73 #include "MagickCore/utility.h"
74
75 /*
76 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
77 % %
78 % %
79 % %
80 + A c q u i r e P i x e l C h a n n e l M a p %
81 % %
82 % %
83 % %
84 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
85 %
86 % AcquirePixelChannelMap() acquires a pixel component map.
87 %
88 % The format of the AcquirePixelChannelMap() method is:
89 %
90 % PixelChannelMap *AcquirePixelChannelMap(void)
91 %
92 */
AcquirePixelChannelMap(void)93 MagickExport PixelChannelMap *AcquirePixelChannelMap(void)
94 {
95 PixelChannelMap
96 *channel_map;
97
98 register ssize_t
99 i;
100
101 channel_map=(PixelChannelMap *) AcquireQuantumMemory(MaxPixelChannels,
102 sizeof(*channel_map));
103 if (channel_map == (PixelChannelMap *) NULL)
104 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
105 (void) memset(channel_map,0,MaxPixelChannels*sizeof(*channel_map));
106 for (i=0; i < MaxPixelChannels; i++)
107 channel_map[i].channel=(PixelChannel) i;
108 return(channel_map);
109 }
110
111 /*
112 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
113 % %
114 % %
115 % %
116 + C l o n e P i x e l C h a n n e l M a p %
117 % %
118 % %
119 % %
120 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
121 %
122 % ClonePixelChannelMap() clones a pixel component map.
123 %
124 % The format of the ClonePixelChannelMap() method is:
125 %
126 % PixelChannelMap *ClonePixelChannelMap(PixelChannelMap *channel_map)
127 %
128 % A description of each parameter follows:
129 %
130 % o channel_map: the pixel component map.
131 %
132 */
ClonePixelChannelMap(PixelChannelMap * channel_map)133 MagickExport PixelChannelMap *ClonePixelChannelMap(PixelChannelMap *channel_map)
134 {
135 PixelChannelMap
136 *clone_map;
137
138 assert(channel_map != (PixelChannelMap *) NULL);
139 clone_map=AcquirePixelChannelMap();
140 if (clone_map == (PixelChannelMap *) NULL)
141 return((PixelChannelMap *) NULL);
142 (void) memcpy(clone_map,channel_map,MaxPixelChannels*
143 sizeof(*channel_map));
144 return(clone_map);
145 }
146
147 /*
148 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
149 % %
150 % %
151 % %
152 + C l o n e P i x e l I n f o %
153 % %
154 % %
155 % %
156 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
157 %
158 % ClonePixelInfo() makes a duplicate of the given pixel info structure, or if
159 % pixel info is NULL, a new one.
160 %
161 % The format of the ClonePixelInfo method is:
162 %
163 % PixelInfo *ClonePixelInfo(const PixelInfo *pixel)
164 %
165 % A description of each parameter follows:
166 %
167 % o pixel: the pixel info.
168 %
169 */
ClonePixelInfo(const PixelInfo * pixel)170 MagickExport PixelInfo *ClonePixelInfo(const PixelInfo *pixel)
171 {
172 PixelInfo
173 *pixel_info;
174
175 pixel_info=(PixelInfo *) AcquireQuantumMemory(1,sizeof(*pixel_info));
176 if (pixel_info == (PixelInfo *) NULL)
177 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
178 *pixel_info=(*pixel);
179 return(pixel_info);
180 }
181
182 /*
183 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
184 % %
185 % %
186 % %
187 + C o n f o r m P i x e l I n f o %
188 % %
189 % %
190 % %
191 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
192 %
193 % ConformPixelInfo() ensures the pixel conforms with the colorspace and alpha
194 % attribute of the image.
195 %
196 % The format of the ConformPixelInfo method is:
197 %
198 % void *ConformPixelInfo((Image *image,const PixelInfo *source,
199 % PixelInfo *destination,ExceptionInfo *exception)
200 %
201 % A description of each parameter follows:
202 %
203 % o image: the image.
204 %
205 % o source: the source pixel info.
206 %
207 % o destination: the destination pixel info.
208 %
209 % o exception: return any errors or warnings in this structure.
210 %
211 */
ConformPixelInfo(Image * image,const PixelInfo * source,PixelInfo * destination,ExceptionInfo * exception)212 MagickExport void ConformPixelInfo(Image *image,const PixelInfo *source,
213 PixelInfo *destination,ExceptionInfo *exception)
214 {
215 assert(image != (Image *) NULL);
216 assert(image->signature == MagickCoreSignature);
217 assert(destination != (const PixelInfo *) NULL);
218 *destination=(*source);
219 if (image->colorspace == CMYKColorspace)
220 {
221 if (IssRGBCompatibleColorspace(destination->colorspace))
222 ConvertRGBToCMYK(destination);
223 }
224 else
225 if (destination->colorspace == CMYKColorspace)
226 {
227 if (IssRGBCompatibleColorspace(image->colorspace))
228 ConvertCMYKToRGB(destination);
229 }
230 if ((IsPixelInfoGray(&image->background_color) == MagickFalse) &&
231 (IsGrayColorspace(image->colorspace) != MagickFalse))
232 (void) TransformImageColorspace(image,sRGBColorspace,exception);
233 if ((destination->alpha_trait != UndefinedPixelTrait) &&
234 (image->alpha_trait == UndefinedPixelTrait))
235 (void) SetImageAlpha(image,OpaqueAlpha,exception);
236 }
237
238 /*
239 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
240 % %
241 % %
242 % %
243 % D e c o d e P i x e l G a m m a %
244 % %
245 % %
246 % %
247 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
248 %
249 % DecodePixelGamma() applies the expansive power-law nonlinearity to the pixel.
250 %
251 % The format of the DecodePixelGamma method is:
252 %
253 % double DecodePixelGamma(const MagickRealType pixel)
254 %
255 % A description of each parameter follows:
256 %
257 % o pixel: the pixel.
258 %
259 */
260
DecodeGamma(const double x)261 static inline double DecodeGamma(const double x)
262 {
263 div_t
264 quotient;
265
266 double
267 p,
268 term[9];
269
270 int
271 exponent;
272
273 static const double coefficient[] = /* terms for x^(7/5), x=1.5 */
274 {
275 1.7917488588043277509,
276 0.82045614371976854984,
277 0.027694100686325412819,
278 -0.00094244335181762134018,
279 0.000064355540911469709545,
280 -5.7224404636060757485e-06,
281 5.8767669437311184313e-07,
282 -6.6139920053589721168e-08,
283 7.9323242696227458163e-09
284 };
285
286 static const double powers_of_two[] = /* (2^x)^(7/5) */
287 {
288 1.0,
289 2.6390158215457883983,
290 6.9644045063689921093,
291 1.8379173679952558018e+01,
292 4.8502930128332728543e+01
293 };
294
295 /*
296 Compute x^2.4 == x*x^(7/5) == pow(x,2.4).
297 */
298 term[0]=1.0;
299 term[1]=4.0*frexp(x,&exponent)-3.0;
300 term[2]=2.0*term[1]*term[1]-term[0];
301 term[3]=2.0*term[1]*term[2]-term[1];
302 term[4]=2.0*term[1]*term[3]-term[2];
303 term[5]=2.0*term[1]*term[4]-term[3];
304 term[6]=2.0*term[1]*term[5]-term[4];
305 term[7]=2.0*term[1]*term[6]-term[5];
306 term[8]=2.0*term[1]*term[7]-term[6];
307 p=coefficient[0]*term[0]+coefficient[1]*term[1]+coefficient[2]*term[2]+
308 coefficient[3]*term[3]+coefficient[4]*term[4]+coefficient[5]*term[5]+
309 coefficient[6]*term[6]+coefficient[7]*term[7]+coefficient[8]*term[8];
310 quotient=div(exponent-1,5);
311 if (quotient.rem < 0)
312 {
313 quotient.quot-=1;
314 quotient.rem+=5;
315 }
316 return(x*ldexp(powers_of_two[quotient.rem]*p,7*quotient.quot));
317 }
318
DecodePixelGamma(const MagickRealType pixel)319 MagickExport MagickRealType DecodePixelGamma(const MagickRealType pixel)
320 {
321 if (pixel <= (0.0404482362771076*QuantumRange))
322 return(pixel/12.92f);
323 return((MagickRealType) (QuantumRange*DecodeGamma((double) (QuantumScale*
324 pixel+0.055)/1.055)));
325 }
326
327 /*
328 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
329 % %
330 % %
331 % %
332 + D e s t r o y P i x e l C h a n n e l M a p %
333 % %
334 % %
335 % %
336 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
337 %
338 % DestroyPixelChannelMap() deallocates memory associated with the pixel
339 % channel map.
340 %
341 % The format of the DestroyPixelChannelMap() method is:
342 %
343 % PixelChannelMap *DestroyPixelChannelMap(PixelChannelMap *channel_map)
344 %
345 % A description of each parameter follows:
346 %
347 % o channel_map: the pixel component map.
348 %
349 */
DestroyPixelChannelMap(PixelChannelMap * channel_map)350 MagickExport PixelChannelMap *DestroyPixelChannelMap(
351 PixelChannelMap *channel_map)
352 {
353 assert(channel_map != (PixelChannelMap *) NULL);
354 channel_map=(PixelChannelMap *) RelinquishMagickMemory(channel_map);
355 return((PixelChannelMap *) RelinquishMagickMemory(channel_map));
356 }
357
358 /*
359 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
360 % %
361 % %
362 % %
363 + E n c o d e P i x e l G a m m a %
364 % %
365 % %
366 % %
367 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
368 %
369 % EncodePixelGamma() cancels any nonlinearity in the pixel.
370 %
371 % The format of the EncodePixelGamma method is:
372 %
373 % MagickRealType EncodePixelGamma(const double MagickRealType)
374 %
375 % A description of each parameter follows:
376 %
377 % o pixel: the pixel.
378 %
379 */
380
EncodeGamma(const double x)381 static inline double EncodeGamma(const double x)
382 {
383 div_t
384 quotient;
385
386 double
387 p,
388 term[9];
389
390 int
391 exponent;
392
393 static const double coefficient[] = /* Chebychevi poly: x^(5/12), x=1.5 */
394 {
395 1.1758200232996901923,
396 0.16665763094889061230,
397 -0.0083154894939042125035,
398 0.00075187976780420279038,
399 -0.000083240178519391795367,
400 0.000010229209410070008679,
401 -1.3400466409860246e-06,
402 1.8333422241635376682e-07,
403 -2.5878596761348859722e-08
404 };
405
406 static const double powers_of_two[] = /* (2^N)^(5/12) */
407 {
408 1.0,
409 1.3348398541700343678,
410 1.7817974362806785482,
411 2.3784142300054420538,
412 3.1748021039363991669,
413 4.2378523774371812394,
414 5.6568542494923805819,
415 7.5509945014535482244,
416 1.0079368399158985525e1,
417 1.3454342644059433809e1,
418 1.7959392772949968275e1,
419 2.3972913230026907883e1
420 };
421
422 /*
423 Compute x^(1/2.4) == x^(5/12) == pow(x,1.0/2.4).
424 */
425 term[0]=1.0;
426 term[1]=4.0*frexp(x,&exponent)-3.0;
427 term[2]=2.0*term[1]*term[1]-term[0];
428 term[3]=2.0*term[1]*term[2]-term[1];
429 term[4]=2.0*term[1]*term[3]-term[2];
430 term[5]=2.0*term[1]*term[4]-term[3];
431 term[6]=2.0*term[1]*term[5]-term[4];
432 term[7]=2.0*term[1]*term[6]-term[5];
433 term[8]=2.0*term[1]*term[7]-term[6];
434 p=coefficient[0]*term[0]+coefficient[1]*term[1]+coefficient[2]*term[2]+
435 coefficient[3]*term[3]+coefficient[4]*term[4]+coefficient[5]*term[5]+
436 coefficient[6]*term[6]+coefficient[7]*term[7]+coefficient[8]*term[8];
437 quotient=div(exponent-1,12);
438 if (quotient.rem < 0)
439 {
440 quotient.quot-=1;
441 quotient.rem+=12;
442 }
443 return(ldexp(powers_of_two[quotient.rem]*p,5*quotient.quot));
444 }
445
EncodePixelGamma(const MagickRealType pixel)446 MagickExport MagickRealType EncodePixelGamma(const MagickRealType pixel)
447 {
448 if (pixel <= (0.0031306684425005883*QuantumRange))
449 return(12.92f*pixel);
450 return((MagickRealType) QuantumRange*(1.055*EncodeGamma((double) QuantumScale*
451 pixel)-0.055));
452 }
453
454 /*
455 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
456 % %
457 % %
458 % %
459 % E x p o r t I m a g e P i x e l s %
460 % %
461 % %
462 % %
463 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
464 %
465 % ExportImagePixels() extracts pixel data from an image and returns it to you.
466 % The method returns MagickTrue on success otherwise MagickFalse if an error is
467 % encountered. The data is returned as char, short int, Quantum, unsigned int,
468 % unsigned long long, float, or double in the order specified by map.
469 %
470 % Suppose you want to extract the first scanline of a 640x480 image as
471 % character data in red-green-blue order:
472 %
473 % ExportImagePixels(image,0,0,640,1,"RGB",CharPixel,pixels,exception);
474 %
475 % The format of the ExportImagePixels method is:
476 %
477 % MagickBooleanType ExportImagePixels(const Image *image,const ssize_t x,
478 % const ssize_t y,const size_t width,const size_t height,
479 % const char *map,const StorageType type,void *pixels,
480 % ExceptionInfo *exception)
481 %
482 % A description of each parameter follows:
483 %
484 % o image: the image.
485 %
486 % o x,y,width,height: These values define the perimeter
487 % of a region of pixels you want to extract.
488 %
489 % o map: This string reflects the expected ordering of the pixel array.
490 % It can be any combination or order of R = red, G = green, B = blue,
491 % A = alpha (0 is transparent), O = opacity (0 is opaque), C = cyan,
492 % Y = yellow, M = magenta, K = black, I = intensity (for grayscale),
493 % P = pad.
494 %
495 % o type: Define the data type of the pixels. Float and double types are
496 % normalized to [0..1] otherwise [0..QuantumRange]. Choose from these
497 % types: CharPixel (char *), DoublePixel (double *), FloatPixel (float *),
498 % LongPixel (unsigned int *), LongLongPixel (unsigned long long *),
499 % QuantumPixel (Quantum *), or ShortPixel (unsigned short *).
500 %
501 % o pixels: This array of values contain the pixel components as defined by
502 % map and type. You must preallocate this array where the expected
503 % length varies depending on the values of width, height, map, and type.
504 %
505 % o exception: return any errors or warnings in this structure.
506 %
507 */
508
ExportCharPixel(const Image * image,const RectangleInfo * roi,const char * magick_restrict map,const QuantumType * quantum_map,void * pixels,ExceptionInfo * exception)509 static MagickBooleanType ExportCharPixel(const Image *image,
510 const RectangleInfo *roi,const char *magick_restrict map,
511 const QuantumType *quantum_map,void *pixels,ExceptionInfo *exception)
512 {
513 register const Quantum
514 *magick_restrict p;
515
516 register ssize_t
517 x;
518
519 register unsigned char
520 *magick_restrict q;
521
522 size_t
523 length;
524
525 ssize_t
526 y;
527
528 q=(unsigned char *) pixels;
529 if (LocaleCompare(map,"BGR") == 0)
530 {
531 for (y=0; y < (ssize_t) roi->height; y++)
532 {
533 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
534 if (p == (const Quantum *) NULL)
535 break;
536 for (x=0; x < (ssize_t) roi->width; x++)
537 {
538 *q++=ScaleQuantumToChar(GetPixelBlue(image,p));
539 *q++=ScaleQuantumToChar(GetPixelGreen(image,p));
540 *q++=ScaleQuantumToChar(GetPixelRed(image,p));
541 p+=GetPixelChannels(image);
542 }
543 }
544 return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
545 }
546 if (LocaleCompare(map,"BGRA") == 0)
547 {
548 for (y=0; y < (ssize_t) roi->height; y++)
549 {
550 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
551 if (p == (const Quantum *) NULL)
552 break;
553 for (x=0; x < (ssize_t) roi->width; x++)
554 {
555 *q++=ScaleQuantumToChar(GetPixelBlue(image,p));
556 *q++=ScaleQuantumToChar(GetPixelGreen(image,p));
557 *q++=ScaleQuantumToChar(GetPixelRed(image,p));
558 *q++=ScaleQuantumToChar(GetPixelAlpha(image,p));
559 p+=GetPixelChannels(image);
560 }
561 }
562 return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
563 }
564 if (LocaleCompare(map,"BGRP") == 0)
565 {
566 for (y=0; y < (ssize_t) roi->height; y++)
567 {
568 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
569 if (p == (const Quantum *) NULL)
570 break;
571 for (x=0; x < (ssize_t) roi->width; x++)
572 {
573 *q++=ScaleQuantumToChar(GetPixelBlue(image,p));
574 *q++=ScaleQuantumToChar(GetPixelGreen(image,p));
575 *q++=ScaleQuantumToChar(GetPixelRed(image,p));
576 *q++=ScaleQuantumToChar((Quantum) 0);
577 p+=GetPixelChannels(image);
578 }
579 }
580 return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
581 }
582 if (LocaleCompare(map,"I") == 0)
583 {
584 for (y=0; y < (ssize_t) roi->height; y++)
585 {
586 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
587 if (p == (const Quantum *) NULL)
588 break;
589 for (x=0; x < (ssize_t) roi->width; x++)
590 {
591 *q++=ScaleQuantumToChar(ClampToQuantum(GetPixelIntensity(image,p)));
592 p+=GetPixelChannels(image);
593 }
594 }
595 return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
596 }
597 if (LocaleCompare(map,"RGB") == 0)
598 {
599 for (y=0; y < (ssize_t) roi->height; y++)
600 {
601 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
602 if (p == (const Quantum *) NULL)
603 break;
604 for (x=0; x < (ssize_t) roi->width; x++)
605 {
606 *q++=ScaleQuantumToChar(GetPixelRed(image,p));
607 *q++=ScaleQuantumToChar(GetPixelGreen(image,p));
608 *q++=ScaleQuantumToChar(GetPixelBlue(image,p));
609 p+=GetPixelChannels(image);
610 }
611 }
612 return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
613 }
614 if (LocaleCompare(map,"RGBA") == 0)
615 {
616 for (y=0; y < (ssize_t) roi->height; y++)
617 {
618 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
619 if (p == (const Quantum *) NULL)
620 break;
621 for (x=0; x < (ssize_t) roi->width; x++)
622 {
623 *q++=ScaleQuantumToChar(GetPixelRed(image,p));
624 *q++=ScaleQuantumToChar(GetPixelGreen(image,p));
625 *q++=ScaleQuantumToChar(GetPixelBlue(image,p));
626 *q++=ScaleQuantumToChar(GetPixelAlpha(image,p));
627 p+=GetPixelChannels(image);
628 }
629 }
630 return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
631 }
632 if (LocaleCompare(map,"RGBP") == 0)
633 {
634 for (y=0; y < (ssize_t) roi->height; y++)
635 {
636 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
637 if (p == (const Quantum *) NULL)
638 break;
639 for (x=0; x < (ssize_t) roi->width; x++)
640 {
641 *q++=ScaleQuantumToChar(GetPixelRed(image,p));
642 *q++=ScaleQuantumToChar(GetPixelGreen(image,p));
643 *q++=ScaleQuantumToChar(GetPixelBlue(image,p));
644 *q++=ScaleQuantumToChar((Quantum) 0);
645 p+=GetPixelChannels(image);
646 }
647 }
648 return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
649 }
650 length=strlen(map);
651 for (y=0; y < (ssize_t) roi->height; y++)
652 {
653 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
654 if (p == (const Quantum *) NULL)
655 break;
656 for (x=0; x < (ssize_t) roi->width; x++)
657 {
658 register ssize_t
659 i;
660
661 for (i=0; i < (ssize_t) length; i++)
662 {
663 *q=0;
664 switch (quantum_map[i])
665 {
666 case RedQuantum:
667 case CyanQuantum:
668 {
669 *q=ScaleQuantumToChar(GetPixelRed(image,p));
670 break;
671 }
672 case GreenQuantum:
673 case MagentaQuantum:
674 {
675 *q=ScaleQuantumToChar(GetPixelGreen(image,p));
676 break;
677 }
678 case BlueQuantum:
679 case YellowQuantum:
680 {
681 *q=ScaleQuantumToChar(GetPixelBlue(image,p));
682 break;
683 }
684 case AlphaQuantum:
685 {
686 *q=ScaleQuantumToChar(GetPixelAlpha(image,p));
687 break;
688 }
689 case OpacityQuantum:
690 {
691 *q=ScaleQuantumToChar(GetPixelAlpha(image,p));
692 break;
693 }
694 case BlackQuantum:
695 {
696 if (image->colorspace == CMYKColorspace)
697 *q=ScaleQuantumToChar(GetPixelBlack(image,p));
698 break;
699 }
700 case IndexQuantum:
701 {
702 *q=ScaleQuantumToChar(ClampToQuantum(GetPixelIntensity(image,p)));
703 break;
704 }
705 default:
706 break;
707 }
708 q++;
709 }
710 p+=GetPixelChannels(image);
711 }
712 }
713 return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
714 }
715
ExportDoublePixel(const Image * image,const RectangleInfo * roi,const char * magick_restrict map,const QuantumType * quantum_map,void * pixels,ExceptionInfo * exception)716 static MagickBooleanType ExportDoublePixel(const Image *image,
717 const RectangleInfo *roi,const char *magick_restrict map,
718 const QuantumType *quantum_map,void *pixels,ExceptionInfo *exception)
719 {
720 register const Quantum
721 *magick_restrict p;
722
723 register double
724 *magick_restrict q;
725
726 register ssize_t
727 x;
728
729 size_t
730 length;
731
732 ssize_t
733 y;
734
735 q=(double *) pixels;
736 if (LocaleCompare(map,"BGR") == 0)
737 {
738 for (y=0; y < (ssize_t) roi->height; y++)
739 {
740 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
741 if (p == (const Quantum *) NULL)
742 break;
743 for (x=0; x < (ssize_t) roi->width; x++)
744 {
745 *q++=(double) (QuantumScale*GetPixelBlue(image,p));
746 *q++=(double) (QuantumScale*GetPixelGreen(image,p));
747 *q++=(double) (QuantumScale*GetPixelRed(image,p));
748 p+=GetPixelChannels(image);
749 }
750 }
751 return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
752 }
753 if (LocaleCompare(map,"BGRA") == 0)
754 {
755 for (y=0; y < (ssize_t) roi->height; y++)
756 {
757 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
758 if (p == (const Quantum *) NULL)
759 break;
760 for (x=0; x < (ssize_t) roi->width; x++)
761 {
762 *q++=(double) (QuantumScale*GetPixelBlue(image,p));
763 *q++=(double) (QuantumScale*GetPixelGreen(image,p));
764 *q++=(double) (QuantumScale*GetPixelRed(image,p));
765 *q++=(double) (QuantumScale*GetPixelAlpha(image,p));
766 p+=GetPixelChannels(image);
767 }
768 }
769 return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
770 }
771 if (LocaleCompare(map,"BGRP") == 0)
772 {
773 for (y=0; y < (ssize_t) roi->height; y++)
774 {
775 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
776 if (p == (const Quantum *) NULL)
777 break;
778 for (x=0; x < (ssize_t) roi->width; x++)
779 {
780 *q++=(double) (QuantumScale*GetPixelBlue(image,p));
781 *q++=(double) (QuantumScale*GetPixelGreen(image,p));
782 *q++=(double) (QuantumScale*GetPixelRed(image,p));
783 *q++=0.0;
784 p+=GetPixelChannels(image);
785 }
786 }
787 return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
788 }
789 if (LocaleCompare(map,"I") == 0)
790 {
791 for (y=0; y < (ssize_t) roi->height; y++)
792 {
793 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
794 if (p == (const Quantum *) NULL)
795 break;
796 for (x=0; x < (ssize_t) roi->width; x++)
797 {
798 *q++=(double) (QuantumScale*GetPixelIntensity(image,p));
799 p+=GetPixelChannels(image);
800 }
801 }
802 return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
803 }
804 if (LocaleCompare(map,"RGB") == 0)
805 {
806 for (y=0; y < (ssize_t) roi->height; y++)
807 {
808 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
809 if (p == (const Quantum *) NULL)
810 break;
811 for (x=0; x < (ssize_t) roi->width; x++)
812 {
813 *q++=(double) (QuantumScale*GetPixelRed(image,p));
814 *q++=(double) (QuantumScale*GetPixelGreen(image,p));
815 *q++=(double) (QuantumScale*GetPixelBlue(image,p));
816 p+=GetPixelChannels(image);
817 }
818 }
819 return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
820 }
821 if (LocaleCompare(map,"RGBA") == 0)
822 {
823 for (y=0; y < (ssize_t) roi->height; y++)
824 {
825 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
826 if (p == (const Quantum *) NULL)
827 break;
828 for (x=0; x < (ssize_t) roi->width; x++)
829 {
830 *q++=(double) (QuantumScale*GetPixelRed(image,p));
831 *q++=(double) (QuantumScale*GetPixelGreen(image,p));
832 *q++=(double) (QuantumScale*GetPixelBlue(image,p));
833 *q++=(double) (QuantumScale*GetPixelAlpha(image,p));
834 p+=GetPixelChannels(image);
835 }
836 }
837 return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
838 }
839 if (LocaleCompare(map,"RGBP") == 0)
840 {
841 for (y=0; y < (ssize_t) roi->height; y++)
842 {
843 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
844 if (p == (const Quantum *) NULL)
845 break;
846 for (x=0; x < (ssize_t) roi->width; x++)
847 {
848 *q++=(double) (QuantumScale*GetPixelRed(image,p));
849 *q++=(double) (QuantumScale*GetPixelGreen(image,p));
850 *q++=(double) (QuantumScale*GetPixelBlue(image,p));
851 *q++=0.0;
852 p+=GetPixelChannels(image);
853 }
854 }
855 return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
856 }
857 length=strlen(map);
858 for (y=0; y < (ssize_t) roi->height; y++)
859 {
860 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
861 if (p == (const Quantum *) NULL)
862 break;
863 for (x=0; x < (ssize_t) roi->width; x++)
864 {
865 register ssize_t
866 i;
867
868 for (i=0; i < (ssize_t) length; i++)
869 {
870 *q=0;
871 switch (quantum_map[i])
872 {
873 case RedQuantum:
874 case CyanQuantum:
875 {
876 *q=(double) (QuantumScale*GetPixelRed(image,p));
877 break;
878 }
879 case GreenQuantum:
880 case MagentaQuantum:
881 {
882 *q=(double) (QuantumScale*GetPixelGreen(image,p));
883 break;
884 }
885 case BlueQuantum:
886 case YellowQuantum:
887 {
888 *q=(double) (QuantumScale*GetPixelBlue(image,p));
889 break;
890 }
891 case AlphaQuantum:
892 {
893 *q=(double) (QuantumScale*GetPixelAlpha(image,p));
894 break;
895 }
896 case OpacityQuantum:
897 {
898 *q=(double) (QuantumScale*GetPixelAlpha(image,p));
899 break;
900 }
901 case BlackQuantum:
902 {
903 if (image->colorspace == CMYKColorspace)
904 *q=(double) (QuantumScale*
905 GetPixelBlack(image,p));
906 break;
907 }
908 case IndexQuantum:
909 {
910 *q=(double) (QuantumScale*GetPixelIntensity(image,p));
911 break;
912 }
913 default:
914 *q=0;
915 }
916 q++;
917 }
918 p+=GetPixelChannels(image);
919 }
920 }
921 return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
922 }
923
ExportFloatPixel(const Image * image,const RectangleInfo * roi,const char * magick_restrict map,const QuantumType * quantum_map,void * pixels,ExceptionInfo * exception)924 static MagickBooleanType ExportFloatPixel(const Image *image,
925 const RectangleInfo *roi,const char *magick_restrict map,
926 const QuantumType *quantum_map,void *pixels,ExceptionInfo *exception)
927 {
928 register const Quantum
929 *magick_restrict p;
930
931 register float
932 *magick_restrict q;
933
934 register ssize_t
935 x;
936
937 size_t
938 length;
939
940 ssize_t
941 y;
942
943 q=(float *) pixels;
944 if (LocaleCompare(map,"BGR") == 0)
945 {
946 for (y=0; y < (ssize_t) roi->height; y++)
947 {
948 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
949 if (p == (const Quantum *) NULL)
950 break;
951 for (x=0; x < (ssize_t) roi->width; x++)
952 {
953 *q++=(float) (QuantumScale*GetPixelBlue(image,p));
954 *q++=(float) (QuantumScale*GetPixelGreen(image,p));
955 *q++=(float) (QuantumScale*GetPixelRed(image,p));
956 p+=GetPixelChannels(image);
957 }
958 }
959 return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
960 }
961 if (LocaleCompare(map,"BGRA") == 0)
962 {
963 for (y=0; y < (ssize_t) roi->height; y++)
964 {
965 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
966 if (p == (const Quantum *) NULL)
967 break;
968 for (x=0; x < (ssize_t) roi->width; x++)
969 {
970 *q++=(float) (QuantumScale*GetPixelBlue(image,p));
971 *q++=(float) (QuantumScale*GetPixelGreen(image,p));
972 *q++=(float) (QuantumScale*GetPixelRed(image,p));
973 *q++=(float) (QuantumScale*GetPixelAlpha(image,p));
974 p+=GetPixelChannels(image);
975 }
976 }
977 return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
978 }
979 if (LocaleCompare(map,"BGRP") == 0)
980 {
981 for (y=0; y < (ssize_t) roi->height; y++)
982 {
983 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
984 if (p == (const Quantum *) NULL)
985 break;
986 for (x=0; x < (ssize_t) roi->width; x++)
987 {
988 *q++=(float) (QuantumScale*GetPixelBlue(image,p));
989 *q++=(float) (QuantumScale*GetPixelGreen(image,p));
990 *q++=(float) (QuantumScale*GetPixelRed(image,p));
991 *q++=0.0;
992 p+=GetPixelChannels(image);
993 }
994 }
995 return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
996 }
997 if (LocaleCompare(map,"I") == 0)
998 {
999 for (y=0; y < (ssize_t) roi->height; y++)
1000 {
1001 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
1002 if (p == (const Quantum *) NULL)
1003 break;
1004 for (x=0; x < (ssize_t) roi->width; x++)
1005 {
1006 *q++=(float) (QuantumScale*GetPixelIntensity(image,p));
1007 p+=GetPixelChannels(image);
1008 }
1009 }
1010 return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
1011 }
1012 if (LocaleCompare(map,"RGB") == 0)
1013 {
1014 for (y=0; y < (ssize_t) roi->height; y++)
1015 {
1016 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
1017 if (p == (const Quantum *) NULL)
1018 break;
1019 for (x=0; x < (ssize_t) roi->width; x++)
1020 {
1021 *q++=(float) (QuantumScale*GetPixelRed(image,p));
1022 *q++=(float) (QuantumScale*GetPixelGreen(image,p));
1023 *q++=(float) (QuantumScale*GetPixelBlue(image,p));
1024 p+=GetPixelChannels(image);
1025 }
1026 }
1027 return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
1028 }
1029 if (LocaleCompare(map,"RGBA") == 0)
1030 {
1031 for (y=0; y < (ssize_t) roi->height; y++)
1032 {
1033 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
1034 if (p == (const Quantum *) NULL)
1035 break;
1036 for (x=0; x < (ssize_t) roi->width; x++)
1037 {
1038 *q++=(float) (QuantumScale*GetPixelRed(image,p));
1039 *q++=(float) (QuantumScale*GetPixelGreen(image,p));
1040 *q++=(float) (QuantumScale*GetPixelBlue(image,p));
1041 *q++=(float) (QuantumScale*GetPixelAlpha(image,p));
1042 p+=GetPixelChannels(image);
1043 }
1044 }
1045 return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
1046 }
1047 if (LocaleCompare(map,"RGBP") == 0)
1048 {
1049 for (y=0; y < (ssize_t) roi->height; y++)
1050 {
1051 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
1052 if (p == (const Quantum *) NULL)
1053 break;
1054 for (x=0; x < (ssize_t) roi->width; x++)
1055 {
1056 *q++=(float) (QuantumScale*GetPixelRed(image,p));
1057 *q++=(float) (QuantumScale*GetPixelGreen(image,p));
1058 *q++=(float) (QuantumScale*GetPixelBlue(image,p));
1059 *q++=0.0;
1060 p+=GetPixelChannels(image);
1061 }
1062 }
1063 return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
1064 }
1065 length=strlen(map);
1066 for (y=0; y < (ssize_t) roi->height; y++)
1067 {
1068 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
1069 if (p == (const Quantum *) NULL)
1070 break;
1071 for (x=0; x < (ssize_t) roi->width; x++)
1072 {
1073 register ssize_t
1074 i;
1075
1076 for (i=0; i < (ssize_t) length; i++)
1077 {
1078 *q=0;
1079 switch (quantum_map[i])
1080 {
1081 case RedQuantum:
1082 case CyanQuantum:
1083 {
1084 *q=(float) (QuantumScale*GetPixelRed(image,p));
1085 break;
1086 }
1087 case GreenQuantum:
1088 case MagentaQuantum:
1089 {
1090 *q=(float) (QuantumScale*GetPixelGreen(image,p));
1091 break;
1092 }
1093 case BlueQuantum:
1094 case YellowQuantum:
1095 {
1096 *q=(float) (QuantumScale*GetPixelBlue(image,p));
1097 break;
1098 }
1099 case AlphaQuantum:
1100 {
1101 *q=(float) (QuantumScale*((Quantum) (GetPixelAlpha(image,p))));
1102 break;
1103 }
1104 case OpacityQuantum:
1105 {
1106 *q=(float) (QuantumScale*GetPixelAlpha(image,p));
1107 break;
1108 }
1109 case BlackQuantum:
1110 {
1111 if (image->colorspace == CMYKColorspace)
1112 *q=(float) (QuantumScale* GetPixelBlack(image,p));
1113 break;
1114 }
1115 case IndexQuantum:
1116 {
1117 *q=(float) (QuantumScale*GetPixelIntensity(image,p));
1118 break;
1119 }
1120 default:
1121 *q=0;
1122 }
1123 q++;
1124 }
1125 p+=GetPixelChannels(image);
1126 }
1127 }
1128 return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
1129 }
1130
ExportLongPixel(const Image * image,const RectangleInfo * roi,const char * magick_restrict map,const QuantumType * quantum_map,void * pixels,ExceptionInfo * exception)1131 static MagickBooleanType ExportLongPixel(const Image *image,
1132 const RectangleInfo *roi,const char *magick_restrict map,
1133 const QuantumType *quantum_map,void *pixels,ExceptionInfo *exception)
1134 {
1135 register const Quantum
1136 *magick_restrict p;
1137
1138 register ssize_t
1139 x;
1140
1141 register unsigned int
1142 *magick_restrict q;
1143
1144 size_t
1145 length;
1146
1147 ssize_t
1148 y;
1149
1150 q=(unsigned int *) pixels;
1151 if (LocaleCompare(map,"BGR") == 0)
1152 {
1153 for (y=0; y < (ssize_t) roi->height; y++)
1154 {
1155 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
1156 if (p == (const Quantum *) NULL)
1157 break;
1158 for (x=0; x < (ssize_t) roi->width; x++)
1159 {
1160 *q++=ScaleQuantumToLong(GetPixelBlue(image,p));
1161 *q++=ScaleQuantumToLong(GetPixelGreen(image,p));
1162 *q++=ScaleQuantumToLong(GetPixelRed(image,p));
1163 p+=GetPixelChannels(image);
1164 }
1165 }
1166 return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
1167 }
1168 if (LocaleCompare(map,"BGRA") == 0)
1169 {
1170 for (y=0; y < (ssize_t) roi->height; y++)
1171 {
1172 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
1173 if (p == (const Quantum *) NULL)
1174 break;
1175 for (x=0; x < (ssize_t) roi->width; x++)
1176 {
1177 *q++=ScaleQuantumToLong(GetPixelBlue(image,p));
1178 *q++=ScaleQuantumToLong(GetPixelGreen(image,p));
1179 *q++=ScaleQuantumToLong(GetPixelRed(image,p));
1180 *q++=ScaleQuantumToLong(GetPixelAlpha(image,p));
1181 p+=GetPixelChannels(image);
1182 }
1183 }
1184 return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
1185 }
1186 if (LocaleCompare(map,"BGRP") == 0)
1187 {
1188 for (y=0; y < (ssize_t) roi->height; y++)
1189 {
1190 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
1191 if (p == (const Quantum *) NULL)
1192 break;
1193 for (x=0; x < (ssize_t) roi->width; x++)
1194 {
1195 *q++=ScaleQuantumToLong(GetPixelBlue(image,p));
1196 *q++=ScaleQuantumToLong(GetPixelGreen(image,p));
1197 *q++=ScaleQuantumToLong(GetPixelRed(image,p));
1198 *q++=0;
1199 p+=GetPixelChannels(image);
1200 }
1201 }
1202 return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
1203 }
1204 if (LocaleCompare(map,"I") == 0)
1205 {
1206 for (y=0; y < (ssize_t) roi->height; y++)
1207 {
1208 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
1209 if (p == (const Quantum *) NULL)
1210 break;
1211 for (x=0; x < (ssize_t) roi->width; x++)
1212 {
1213 *q++=ScaleQuantumToLong(ClampToQuantum(GetPixelIntensity(image,p)));
1214 p+=GetPixelChannels(image);
1215 }
1216 }
1217 return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
1218 }
1219 if (LocaleCompare(map,"RGB") == 0)
1220 {
1221 for (y=0; y < (ssize_t) roi->height; y++)
1222 {
1223 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
1224 if (p == (const Quantum *) NULL)
1225 break;
1226 for (x=0; x < (ssize_t) roi->width; x++)
1227 {
1228 *q++=ScaleQuantumToLong(GetPixelRed(image,p));
1229 *q++=ScaleQuantumToLong(GetPixelGreen(image,p));
1230 *q++=ScaleQuantumToLong(GetPixelBlue(image,p));
1231 p+=GetPixelChannels(image);
1232 }
1233 }
1234 return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
1235 }
1236 if (LocaleCompare(map,"RGBA") == 0)
1237 {
1238 for (y=0; y < (ssize_t) roi->height; y++)
1239 {
1240 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
1241 if (p == (const Quantum *) NULL)
1242 break;
1243 for (x=0; x < (ssize_t) roi->width; x++)
1244 {
1245 *q++=ScaleQuantumToLong(GetPixelRed(image,p));
1246 *q++=ScaleQuantumToLong(GetPixelGreen(image,p));
1247 *q++=ScaleQuantumToLong(GetPixelBlue(image,p));
1248 *q++=ScaleQuantumToLong(GetPixelAlpha(image,p));
1249 p+=GetPixelChannels(image);
1250 }
1251 }
1252 return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
1253 }
1254 if (LocaleCompare(map,"RGBP") == 0)
1255 {
1256 for (y=0; y < (ssize_t) roi->height; y++)
1257 {
1258 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
1259 if (p == (const Quantum *) NULL)
1260 break;
1261 for (x=0; x < (ssize_t) roi->width; x++)
1262 {
1263 *q++=ScaleQuantumToLong(GetPixelRed(image,p));
1264 *q++=ScaleQuantumToLong(GetPixelGreen(image,p));
1265 *q++=ScaleQuantumToLong(GetPixelBlue(image,p));
1266 *q++=0;
1267 p+=GetPixelChannels(image);
1268 }
1269 }
1270 return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
1271 }
1272 length=strlen(map);
1273 for (y=0; y < (ssize_t) roi->height; y++)
1274 {
1275 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
1276 if (p == (const Quantum *) NULL)
1277 break;
1278 for (x=0; x < (ssize_t) roi->width; x++)
1279 {
1280 register ssize_t
1281 i;
1282
1283 for (i=0; i < (ssize_t) length; i++)
1284 {
1285 *q=0;
1286 switch (quantum_map[i])
1287 {
1288 case RedQuantum:
1289 case CyanQuantum:
1290 {
1291 *q=ScaleQuantumToLong(GetPixelRed(image,p));
1292 break;
1293 }
1294 case GreenQuantum:
1295 case MagentaQuantum:
1296 {
1297 *q=ScaleQuantumToLong(GetPixelGreen(image,p));
1298 break;
1299 }
1300 case BlueQuantum:
1301 case YellowQuantum:
1302 {
1303 *q=ScaleQuantumToLong(GetPixelBlue(image,p));
1304 break;
1305 }
1306 case AlphaQuantum:
1307 {
1308 *q=ScaleQuantumToLong(GetPixelAlpha(image,p));
1309 break;
1310 }
1311 case OpacityQuantum:
1312 {
1313 *q=ScaleQuantumToLong(GetPixelAlpha(image,p));
1314 break;
1315 }
1316 case BlackQuantum:
1317 {
1318 if (image->colorspace == CMYKColorspace)
1319 *q=ScaleQuantumToLong(GetPixelBlack(image,p));
1320 break;
1321 }
1322 case IndexQuantum:
1323 {
1324 *q=ScaleQuantumToLong(ClampToQuantum(GetPixelIntensity(image,p)));
1325 break;
1326 }
1327 default:
1328 break;
1329 }
1330 q++;
1331 }
1332 p+=GetPixelChannels(image);
1333 }
1334 }
1335 return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
1336 }
1337
ExportLongLongPixel(const Image * image,const RectangleInfo * roi,const char * magick_restrict map,const QuantumType * quantum_map,void * pixels,ExceptionInfo * exception)1338 static MagickBooleanType ExportLongLongPixel(const Image *image,
1339 const RectangleInfo *roi,const char *magick_restrict map,
1340 const QuantumType *quantum_map,void *pixels,ExceptionInfo *exception)
1341 {
1342 register const Quantum
1343 *magick_restrict p;
1344
1345 register ssize_t
1346 x;
1347
1348 register MagickSizeType
1349 *magick_restrict q;
1350
1351 size_t
1352 length;
1353
1354 ssize_t
1355 y;
1356
1357 q=(MagickSizeType *) pixels;
1358 if (LocaleCompare(map,"BGR") == 0)
1359 {
1360 for (y=0; y < (ssize_t) roi->height; y++)
1361 {
1362 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
1363 if (p == (const Quantum *) NULL)
1364 break;
1365 for (x=0; x < (ssize_t) roi->width; x++)
1366 {
1367 *q++=ScaleQuantumToLongLong(GetPixelBlue(image,p));
1368 *q++=ScaleQuantumToLongLong(GetPixelGreen(image,p));
1369 *q++=ScaleQuantumToLongLong(GetPixelRed(image,p));
1370 p+=GetPixelChannels(image);
1371 }
1372 }
1373 return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
1374 }
1375 if (LocaleCompare(map,"BGRA") == 0)
1376 {
1377 for (y=0; y < (ssize_t) roi->height; y++)
1378 {
1379 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
1380 if (p == (const Quantum *) NULL)
1381 break;
1382 for (x=0; x < (ssize_t) roi->width; x++)
1383 {
1384 *q++=ScaleQuantumToLongLong(GetPixelBlue(image,p));
1385 *q++=ScaleQuantumToLongLong(GetPixelGreen(image,p));
1386 *q++=ScaleQuantumToLongLong(GetPixelRed(image,p));
1387 *q++=ScaleQuantumToLongLong(GetPixelAlpha(image,p));
1388 p+=GetPixelChannels(image);
1389 }
1390 }
1391 return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
1392 }
1393 if (LocaleCompare(map,"BGRP") == 0)
1394 {
1395 for (y=0; y < (ssize_t) roi->height; y++)
1396 {
1397 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
1398 if (p == (const Quantum *) NULL)
1399 break;
1400 for (x=0; x < (ssize_t) roi->width; x++)
1401 {
1402 *q++=ScaleQuantumToLongLong(GetPixelBlue(image,p));
1403 *q++=ScaleQuantumToLongLong(GetPixelGreen(image,p));
1404 *q++=ScaleQuantumToLongLong(GetPixelRed(image,p));
1405 *q++=0;
1406 p+=GetPixelChannels(image);
1407 }
1408 }
1409 return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
1410 }
1411 if (LocaleCompare(map,"I") == 0)
1412 {
1413 for (y=0; y < (ssize_t) roi->height; y++)
1414 {
1415 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
1416 if (p == (const Quantum *) NULL)
1417 break;
1418 for (x=0; x < (ssize_t) roi->width; x++)
1419 {
1420 *q++=ScaleQuantumToLongLong(ClampToQuantum(
1421 GetPixelIntensity(image,p)));
1422 p+=GetPixelChannels(image);
1423 }
1424 }
1425 return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
1426 }
1427 if (LocaleCompare(map,"RGB") == 0)
1428 {
1429 for (y=0; y < (ssize_t) roi->height; y++)
1430 {
1431 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
1432 if (p == (const Quantum *) NULL)
1433 break;
1434 for (x=0; x < (ssize_t) roi->width; x++)
1435 {
1436 *q++=ScaleQuantumToLongLong(GetPixelRed(image,p));
1437 *q++=ScaleQuantumToLongLong(GetPixelGreen(image,p));
1438 *q++=ScaleQuantumToLongLong(GetPixelBlue(image,p));
1439 p+=GetPixelChannels(image);
1440 }
1441 }
1442 return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
1443 }
1444 if (LocaleCompare(map,"RGBA") == 0)
1445 {
1446 for (y=0; y < (ssize_t) roi->height; y++)
1447 {
1448 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
1449 if (p == (const Quantum *) NULL)
1450 break;
1451 for (x=0; x < (ssize_t) roi->width; x++)
1452 {
1453 *q++=ScaleQuantumToLongLong(GetPixelRed(image,p));
1454 *q++=ScaleQuantumToLongLong(GetPixelGreen(image,p));
1455 *q++=ScaleQuantumToLongLong(GetPixelBlue(image,p));
1456 *q++=ScaleQuantumToLongLong(GetPixelAlpha(image,p));
1457 p+=GetPixelChannels(image);
1458 }
1459 }
1460 return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
1461 }
1462 if (LocaleCompare(map,"RGBP") == 0)
1463 {
1464 for (y=0; y < (ssize_t) roi->height; y++)
1465 {
1466 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
1467 if (p == (const Quantum *) NULL)
1468 break;
1469 for (x=0; x < (ssize_t) roi->width; x++)
1470 {
1471 *q++=ScaleQuantumToLongLong(GetPixelRed(image,p));
1472 *q++=ScaleQuantumToLongLong(GetPixelGreen(image,p));
1473 *q++=ScaleQuantumToLongLong(GetPixelBlue(image,p));
1474 *q++=0;
1475 p+=GetPixelChannels(image);
1476 }
1477 }
1478 return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
1479 }
1480 length=strlen(map);
1481 for (y=0; y < (ssize_t) roi->height; y++)
1482 {
1483 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
1484 if (p == (const Quantum *) NULL)
1485 break;
1486 for (x=0; x < (ssize_t) roi->width; x++)
1487 {
1488 register ssize_t
1489 i;
1490
1491 for (i=0; i < (ssize_t) length; i++)
1492 {
1493 *q=0;
1494 switch (quantum_map[i])
1495 {
1496 case RedQuantum:
1497 case CyanQuantum:
1498 {
1499 *q=ScaleQuantumToLongLong(GetPixelRed(image,p));
1500 break;
1501 }
1502 case GreenQuantum:
1503 case MagentaQuantum:
1504 {
1505 *q=ScaleQuantumToLongLong(GetPixelGreen(image,p));
1506 break;
1507 }
1508 case BlueQuantum:
1509 case YellowQuantum:
1510 {
1511 *q=ScaleQuantumToLongLong(GetPixelBlue(image,p));
1512 break;
1513 }
1514 case AlphaQuantum:
1515 {
1516 *q=ScaleQuantumToLongLong(GetPixelAlpha(image,p));
1517 break;
1518 }
1519 case OpacityQuantum:
1520 {
1521 *q=ScaleQuantumToLongLong(GetPixelAlpha(image,p));
1522 break;
1523 }
1524 case BlackQuantum:
1525 {
1526 if (image->colorspace == CMYKColorspace)
1527 *q=ScaleQuantumToLongLong(GetPixelBlack(image,p));
1528 break;
1529 }
1530 case IndexQuantum:
1531 {
1532 *q=ScaleQuantumToLongLong(ClampToQuantum(
1533 GetPixelIntensity(image,p)));
1534 break;
1535 }
1536 default:
1537 break;
1538 }
1539 q++;
1540 }
1541 p+=GetPixelChannels(image);
1542 }
1543 }
1544 return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
1545 }
1546
ExportQuantumPixel(const Image * image,const RectangleInfo * roi,const char * magick_restrict map,const QuantumType * quantum_map,void * pixels,ExceptionInfo * exception)1547 static MagickBooleanType ExportQuantumPixel(const Image *image,
1548 const RectangleInfo *roi,const char *magick_restrict map,
1549 const QuantumType *quantum_map,void *pixels,ExceptionInfo *exception)
1550 {
1551 register const Quantum
1552 *magick_restrict p;
1553
1554 register Quantum
1555 *magick_restrict q;
1556
1557 register ssize_t
1558 x;
1559
1560 size_t
1561 length;
1562
1563 ssize_t
1564 y;
1565
1566 q=(Quantum *) pixels;
1567 if (LocaleCompare(map,"BGR") == 0)
1568 {
1569 for (y=0; y < (ssize_t) roi->height; y++)
1570 {
1571 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
1572 if (p == (const Quantum *) NULL)
1573 break;
1574 for (x=0; x < (ssize_t) roi->width; x++)
1575 {
1576 *q++=GetPixelBlue(image,p);
1577 *q++=GetPixelGreen(image,p);
1578 *q++=GetPixelRed(image,p);
1579 p+=GetPixelChannels(image);
1580 }
1581 }
1582 return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
1583 }
1584 if (LocaleCompare(map,"BGRA") == 0)
1585 {
1586 for (y=0; y < (ssize_t) roi->height; y++)
1587 {
1588 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
1589 if (p == (const Quantum *) NULL)
1590 break;
1591 for (x=0; x < (ssize_t) roi->width; x++)
1592 {
1593 *q++=GetPixelBlue(image,p);
1594 *q++=GetPixelGreen(image,p);
1595 *q++=GetPixelRed(image,p);
1596 *q++=(Quantum) (GetPixelAlpha(image,p));
1597 p+=GetPixelChannels(image);
1598 }
1599 }
1600 return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
1601 }
1602 if (LocaleCompare(map,"BGRP") == 0)
1603 {
1604 for (y=0; y < (ssize_t) roi->height; y++)
1605 {
1606 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
1607 if (p == (const Quantum *) NULL)
1608 break;
1609 for (x=0; x < (ssize_t) roi->width; x++)
1610 {
1611 *q++=GetPixelBlue(image,p);
1612 *q++=GetPixelGreen(image,p);
1613 *q++=GetPixelRed(image,p);
1614 *q++=(Quantum) 0;
1615 p+=GetPixelChannels(image);
1616 }
1617 }
1618 return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
1619 }
1620 if (LocaleCompare(map,"I") == 0)
1621 {
1622 for (y=0; y < (ssize_t) roi->height; y++)
1623 {
1624 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
1625 if (p == (const Quantum *) NULL)
1626 break;
1627 for (x=0; x < (ssize_t) roi->width; x++)
1628 {
1629 *q++=ClampToQuantum(GetPixelIntensity(image,p));
1630 p+=GetPixelChannels(image);
1631 }
1632 }
1633 return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
1634 }
1635 if (LocaleCompare(map,"RGB") == 0)
1636 {
1637 for (y=0; y < (ssize_t) roi->height; y++)
1638 {
1639 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
1640 if (p == (const Quantum *) NULL)
1641 break;
1642 for (x=0; x < (ssize_t) roi->width; x++)
1643 {
1644 *q++=GetPixelRed(image,p);
1645 *q++=GetPixelGreen(image,p);
1646 *q++=GetPixelBlue(image,p);
1647 p+=GetPixelChannels(image);
1648 }
1649 }
1650 return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
1651 }
1652 if (LocaleCompare(map,"RGBA") == 0)
1653 {
1654 for (y=0; y < (ssize_t) roi->height; y++)
1655 {
1656 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
1657 if (p == (const Quantum *) NULL)
1658 break;
1659 for (x=0; x < (ssize_t) roi->width; x++)
1660 {
1661 *q++=GetPixelRed(image,p);
1662 *q++=GetPixelGreen(image,p);
1663 *q++=GetPixelBlue(image,p);
1664 *q++=(Quantum) (GetPixelAlpha(image,p));
1665 p+=GetPixelChannels(image);
1666 }
1667 }
1668 return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
1669 }
1670 if (LocaleCompare(map,"RGBP") == 0)
1671 {
1672 for (y=0; y < (ssize_t) roi->height; y++)
1673 {
1674 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
1675 if (p == (const Quantum *) NULL)
1676 break;
1677 for (x=0; x < (ssize_t) roi->width; x++)
1678 {
1679 *q++=GetPixelRed(image,p);
1680 *q++=GetPixelGreen(image,p);
1681 *q++=GetPixelBlue(image,p);
1682 *q++=(Quantum) 0;
1683 p+=GetPixelChannels(image);
1684 }
1685 }
1686 return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
1687 }
1688 length=strlen(map);
1689 for (y=0; y < (ssize_t) roi->height; y++)
1690 {
1691 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
1692 if (p == (const Quantum *) NULL)
1693 break;
1694 for (x=0; x < (ssize_t) roi->width; x++)
1695 {
1696 register ssize_t
1697 i;
1698
1699 for (i=0; i < (ssize_t) length; i++)
1700 {
1701 *q=(Quantum) 0;
1702 switch (quantum_map[i])
1703 {
1704 case RedQuantum:
1705 case CyanQuantum:
1706 {
1707 *q=GetPixelRed(image,p);
1708 break;
1709 }
1710 case GreenQuantum:
1711 case MagentaQuantum:
1712 {
1713 *q=GetPixelGreen(image,p);
1714 break;
1715 }
1716 case BlueQuantum:
1717 case YellowQuantum:
1718 {
1719 *q=GetPixelBlue(image,p);
1720 break;
1721 }
1722 case AlphaQuantum:
1723 {
1724 *q=GetPixelAlpha(image,p);
1725 break;
1726 }
1727 case OpacityQuantum:
1728 {
1729 *q=GetPixelAlpha(image,p);
1730 break;
1731 }
1732 case BlackQuantum:
1733 {
1734 if (image->colorspace == CMYKColorspace)
1735 *q=GetPixelBlack(image,p);
1736 break;
1737 }
1738 case IndexQuantum:
1739 {
1740 *q=ClampToQuantum(GetPixelIntensity(image,p));
1741 break;
1742 }
1743 default:
1744 {
1745 *q=(Quantum) 0;
1746 break;
1747 }
1748 }
1749 q++;
1750 }
1751 p+=GetPixelChannels(image);
1752 }
1753 }
1754 return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
1755 }
1756
ExportShortPixel(const Image * image,const RectangleInfo * roi,const char * magick_restrict map,const QuantumType * quantum_map,void * pixels,ExceptionInfo * exception)1757 static MagickBooleanType ExportShortPixel(const Image *image,
1758 const RectangleInfo *roi,const char *magick_restrict map,
1759 const QuantumType *quantum_map,void *pixels,ExceptionInfo *exception)
1760 {
1761 register const Quantum
1762 *magick_restrict p;
1763
1764 register ssize_t
1765 x;
1766
1767 register unsigned short
1768 *magick_restrict q;
1769
1770 size_t
1771 length;
1772
1773 ssize_t
1774 y;
1775
1776 q=(unsigned short *) pixels;
1777 if (LocaleCompare(map,"BGR") == 0)
1778 {
1779 for (y=0; y < (ssize_t) roi->height; y++)
1780 {
1781 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
1782 if (p == (const Quantum *) NULL)
1783 break;
1784 for (x=0; x < (ssize_t) roi->width; x++)
1785 {
1786 *q++=ScaleQuantumToShort(GetPixelBlue(image,p));
1787 *q++=ScaleQuantumToShort(GetPixelGreen(image,p));
1788 *q++=ScaleQuantumToShort(GetPixelRed(image,p));
1789 p+=GetPixelChannels(image);
1790 }
1791 }
1792 return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
1793 }
1794 if (LocaleCompare(map,"BGRA") == 0)
1795 {
1796 for (y=0; y < (ssize_t) roi->height; y++)
1797 {
1798 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
1799 if (p == (const Quantum *) NULL)
1800 break;
1801 for (x=0; x < (ssize_t) roi->width; x++)
1802 {
1803 *q++=ScaleQuantumToShort(GetPixelBlue(image,p));
1804 *q++=ScaleQuantumToShort(GetPixelGreen(image,p));
1805 *q++=ScaleQuantumToShort(GetPixelRed(image,p));
1806 *q++=ScaleQuantumToShort(GetPixelAlpha(image,p));
1807 p+=GetPixelChannels(image);
1808 }
1809 }
1810 return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
1811 }
1812 if (LocaleCompare(map,"BGRP") == 0)
1813 {
1814 for (y=0; y < (ssize_t) roi->height; y++)
1815 {
1816 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
1817 if (p == (const Quantum *) NULL)
1818 break;
1819 for (x=0; x < (ssize_t) roi->width; x++)
1820 {
1821 *q++=ScaleQuantumToShort(GetPixelBlue(image,p));
1822 *q++=ScaleQuantumToShort(GetPixelGreen(image,p));
1823 *q++=ScaleQuantumToShort(GetPixelRed(image,p));
1824 *q++=0;
1825 p+=GetPixelChannels(image);
1826 }
1827 }
1828 return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
1829 }
1830 if (LocaleCompare(map,"I") == 0)
1831 {
1832 for (y=0; y < (ssize_t) roi->height; y++)
1833 {
1834 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
1835 if (p == (const Quantum *) NULL)
1836 break;
1837 for (x=0; x < (ssize_t) roi->width; x++)
1838 {
1839 *q++=ScaleQuantumToShort(ClampToQuantum(GetPixelIntensity(image,p)));
1840 p+=GetPixelChannels(image);
1841 }
1842 }
1843 return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
1844 }
1845 if (LocaleCompare(map,"RGB") == 0)
1846 {
1847 for (y=0; y < (ssize_t) roi->height; y++)
1848 {
1849 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
1850 if (p == (const Quantum *) NULL)
1851 break;
1852 for (x=0; x < (ssize_t) roi->width; x++)
1853 {
1854 *q++=ScaleQuantumToShort(GetPixelRed(image,p));
1855 *q++=ScaleQuantumToShort(GetPixelGreen(image,p));
1856 *q++=ScaleQuantumToShort(GetPixelBlue(image,p));
1857 p+=GetPixelChannels(image);
1858 }
1859 }
1860 return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
1861 }
1862 if (LocaleCompare(map,"RGBA") == 0)
1863 {
1864 for (y=0; y < (ssize_t) roi->height; y++)
1865 {
1866 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
1867 if (p == (const Quantum *) NULL)
1868 break;
1869 for (x=0; x < (ssize_t) roi->width; x++)
1870 {
1871 *q++=ScaleQuantumToShort(GetPixelRed(image,p));
1872 *q++=ScaleQuantumToShort(GetPixelGreen(image,p));
1873 *q++=ScaleQuantumToShort(GetPixelBlue(image,p));
1874 *q++=ScaleQuantumToShort(GetPixelAlpha(image,p));
1875 p+=GetPixelChannels(image);
1876 }
1877 }
1878 return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
1879 }
1880 if (LocaleCompare(map,"RGBP") == 0)
1881 {
1882 for (y=0; y < (ssize_t) roi->height; y++)
1883 {
1884 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
1885 if (p == (const Quantum *) NULL)
1886 break;
1887 for (x=0; x < (ssize_t) roi->width; x++)
1888 {
1889 *q++=ScaleQuantumToShort(GetPixelRed(image,p));
1890 *q++=ScaleQuantumToShort(GetPixelGreen(image,p));
1891 *q++=ScaleQuantumToShort(GetPixelBlue(image,p));
1892 *q++=0;
1893 p+=GetPixelChannels(image);
1894 }
1895 }
1896 return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
1897 }
1898 length=strlen(map);
1899 for (y=0; y < (ssize_t) roi->height; y++)
1900 {
1901 p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
1902 if (p == (const Quantum *) NULL)
1903 break;
1904 for (x=0; x < (ssize_t) roi->width; x++)
1905 {
1906 register ssize_t
1907 i;
1908
1909 for (i=0; i < (ssize_t) length; i++)
1910 {
1911 *q=0;
1912 switch (quantum_map[i])
1913 {
1914 case RedQuantum:
1915 case CyanQuantum:
1916 {
1917 *q=ScaleQuantumToShort(GetPixelRed(image,p));
1918 break;
1919 }
1920 case GreenQuantum:
1921 case MagentaQuantum:
1922 {
1923 *q=ScaleQuantumToShort(GetPixelGreen(image,p));
1924 break;
1925 }
1926 case BlueQuantum:
1927 case YellowQuantum:
1928 {
1929 *q=ScaleQuantumToShort(GetPixelBlue(image,p));
1930 break;
1931 }
1932 case AlphaQuantum:
1933 {
1934 *q=ScaleQuantumToShort(GetPixelAlpha(image,p));
1935 break;
1936 }
1937 case OpacityQuantum:
1938 {
1939 *q=ScaleQuantumToShort(GetPixelAlpha(image,p));
1940 break;
1941 }
1942 case BlackQuantum:
1943 {
1944 if (image->colorspace == CMYKColorspace)
1945 *q=ScaleQuantumToShort(GetPixelBlack(image,p));
1946 break;
1947 }
1948 case IndexQuantum:
1949 {
1950 *q=ScaleQuantumToShort(ClampToQuantum(GetPixelIntensity(image,p)));
1951 break;
1952 }
1953 default:
1954 break;
1955 }
1956 q++;
1957 }
1958 p+=GetPixelChannels(image);
1959 }
1960 }
1961 return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
1962 }
1963
ExportImagePixels(const Image * image,const ssize_t x,const ssize_t y,const size_t width,const size_t height,const char * map,const StorageType type,void * pixels,ExceptionInfo * exception)1964 MagickExport MagickBooleanType ExportImagePixels(const Image *image,
1965 const ssize_t x,const ssize_t y,const size_t width,const size_t height,
1966 const char *map,const StorageType type,void *pixels,ExceptionInfo *exception)
1967 {
1968 MagickBooleanType
1969 status;
1970
1971 QuantumType
1972 *quantum_map;
1973
1974 RectangleInfo
1975 roi;
1976
1977 register ssize_t
1978 i;
1979
1980 size_t
1981 length;
1982
1983 assert(image != (Image *) NULL);
1984 assert(image->signature == MagickCoreSignature);
1985 if (image->debug != MagickFalse)
1986 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1987 length=strlen(map);
1988 quantum_map=(QuantumType *) AcquireQuantumMemory(length,sizeof(*quantum_map));
1989 if (quantum_map == (QuantumType *) NULL)
1990 {
1991 (void) ThrowMagickException(exception,GetMagickModule(),
1992 ResourceLimitError,"MemoryAllocationFailed","`%s'",image->filename);
1993 return(MagickFalse);
1994 }
1995 for (i=0; i < (ssize_t) length; i++)
1996 {
1997 switch (map[i])
1998 {
1999 case 'A':
2000 case 'a':
2001 {
2002 quantum_map[i]=AlphaQuantum;
2003 break;
2004 }
2005 case 'B':
2006 case 'b':
2007 {
2008 quantum_map[i]=BlueQuantum;
2009 break;
2010 }
2011 case 'C':
2012 case 'c':
2013 {
2014 quantum_map[i]=CyanQuantum;
2015 if (image->colorspace == CMYKColorspace)
2016 break;
2017 quantum_map=(QuantumType *) RelinquishMagickMemory(quantum_map);
2018 (void) ThrowMagickException(exception,GetMagickModule(),ImageError,
2019 "ColorSeparatedImageRequired","`%s'",map);
2020 return(MagickFalse);
2021 }
2022 case 'g':
2023 case 'G':
2024 {
2025 quantum_map[i]=GreenQuantum;
2026 break;
2027 }
2028 case 'I':
2029 case 'i':
2030 {
2031 quantum_map[i]=IndexQuantum;
2032 break;
2033 }
2034 case 'K':
2035 case 'k':
2036 {
2037 quantum_map[i]=BlackQuantum;
2038 if (image->colorspace == CMYKColorspace)
2039 break;
2040 quantum_map=(QuantumType *) RelinquishMagickMemory(quantum_map);
2041 (void) ThrowMagickException(exception,GetMagickModule(),ImageError,
2042 "ColorSeparatedImageRequired","`%s'",map);
2043 return(MagickFalse);
2044 }
2045 case 'M':
2046 case 'm':
2047 {
2048 quantum_map[i]=MagentaQuantum;
2049 if (image->colorspace == CMYKColorspace)
2050 break;
2051 quantum_map=(QuantumType *) RelinquishMagickMemory(quantum_map);
2052 (void) ThrowMagickException(exception,GetMagickModule(),ImageError,
2053 "ColorSeparatedImageRequired","`%s'",map);
2054 return(MagickFalse);
2055 }
2056 case 'o':
2057 case 'O':
2058 {
2059 quantum_map[i]=OpacityQuantum;
2060 break;
2061 }
2062 case 'P':
2063 case 'p':
2064 {
2065 quantum_map[i]=UndefinedQuantum;
2066 break;
2067 }
2068 case 'R':
2069 case 'r':
2070 {
2071 quantum_map[i]=RedQuantum;
2072 break;
2073 }
2074 case 'Y':
2075 case 'y':
2076 {
2077 quantum_map[i]=YellowQuantum;
2078 if (image->colorspace == CMYKColorspace)
2079 break;
2080 quantum_map=(QuantumType *) RelinquishMagickMemory(quantum_map);
2081 (void) ThrowMagickException(exception,GetMagickModule(),ImageError,
2082 "ColorSeparatedImageRequired","`%s'",map);
2083 return(MagickFalse);
2084 }
2085 default:
2086 {
2087 quantum_map=(QuantumType *) RelinquishMagickMemory(quantum_map);
2088 (void) ThrowMagickException(exception,GetMagickModule(),OptionError,
2089 "UnrecognizedPixelMap","`%s'",map);
2090 return(MagickFalse);
2091 }
2092 }
2093 }
2094 roi.width=width;
2095 roi.height=height;
2096 roi.x=x;
2097 roi.y=y;
2098 switch (type)
2099 {
2100 case CharPixel:
2101 {
2102 status=ExportCharPixel(image,&roi,map,quantum_map,pixels,exception);
2103 break;
2104 }
2105 case DoublePixel:
2106 {
2107 status=ExportDoublePixel(image,&roi,map,quantum_map,pixels,exception);
2108 break;
2109 }
2110 case FloatPixel:
2111 {
2112 status=ExportFloatPixel(image,&roi,map,quantum_map,pixels,exception);
2113 break;
2114 }
2115 case LongPixel:
2116 {
2117 status=ExportLongPixel(image,&roi,map,quantum_map,pixels,exception);
2118 break;
2119 }
2120 case LongLongPixel:
2121 {
2122 status=ExportLongLongPixel(image,&roi,map,quantum_map,pixels,exception);
2123 break;
2124 }
2125 case QuantumPixel:
2126 {
2127 status=ExportQuantumPixel(image,&roi,map,quantum_map,pixels,exception);
2128 break;
2129 }
2130 case ShortPixel:
2131 {
2132 status=ExportShortPixel(image,&roi,map,quantum_map,pixels,exception);
2133 break;
2134 }
2135 default:
2136 {
2137 (void) ThrowMagickException(exception,GetMagickModule(),OptionError,
2138 "UnrecognizedPixelMap","`%s'",map);
2139 status=MagickFalse;
2140 }
2141 }
2142 quantum_map=(QuantumType *) RelinquishMagickMemory(quantum_map);
2143 return(status);
2144 }
2145
2146 /*
2147 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2148 % %
2149 % %
2150 % %
2151 % G e t P i x e l I n f o %
2152 % %
2153 % %
2154 % %
2155 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2156 %
2157 % GetPixelInfo() initializes the PixelInfo structure.
2158 %
2159 % The format of the GetPixelInfo method is:
2160 %
2161 % GetPixelInfo(const Image *image,PixelInfo *pixel)
2162 %
2163 % A description of each parameter follows:
2164 %
2165 % o image: the image. (optional - may be NULL)
2166 %
2167 % o pixel: Specifies a pointer to a PixelInfo structure.
2168 %
2169 */
GetPixelInfo(const Image * image,PixelInfo * pixel)2170 MagickExport void GetPixelInfo(const Image *image,PixelInfo *pixel)
2171 {
2172 (void) memset(pixel,0,sizeof(*pixel));
2173 pixel->storage_class=DirectClass;
2174 pixel->colorspace=sRGBColorspace;
2175 pixel->depth=MAGICKCORE_QUANTUM_DEPTH;
2176 pixel->alpha_trait=UndefinedPixelTrait;
2177 pixel->alpha=(double) OpaqueAlpha;
2178 if (image == (const Image *) NULL)
2179 return;
2180 pixel->storage_class=image->storage_class;
2181 pixel->colorspace=image->colorspace;
2182 pixel->alpha_trait=image->alpha_trait;
2183 pixel->depth=image->depth;
2184 pixel->fuzz=image->fuzz;
2185 }
2186
2187 /*
2188 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2189 % %
2190 % %
2191 % %
2192 % G e t P i x e l I n d o I n t e n s i t y %
2193 % %
2194 % %
2195 % %
2196 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2197 %
2198 % GetPixelInfoIntensity() returns a single sample intensity value from the red,
2199 % green, and blue components of a pixel based on the selected method:
2200 %
2201 % Rec601Luma 0.298839R' + 0.586811G' + 0.114350B'
2202 % Rec601Luminance 0.298839R + 0.586811G + 0.114350B
2203 % Rec709Luma 0.212656R' + 0.715158G' + 0.072186B'
2204 % Rec709Luminance 0.212656R + 0.715158G + 0.072186B
2205 % Brightness max(R', G', B')
2206 % Lightness (min(R', G', B') + max(R', G', B')) / 2.0
2207 %
2208 % MS (R^2 + G^2 + B^2) / 3.0
2209 % RMS sqrt((R^2 + G^2 + B^2) / 3.0
2210 % Average (R + G + B') / 3.0
2211 %
2212 % The format of the GetPixelInfoIntensity method is:
2213 %
2214 % MagickRealType GetPixelInfoIntensity(const Image *image,
2215 % const Quantum *pixel)
2216 %
2217 % A description of each parameter follows:
2218 %
2219 % o image: the image.
2220 %
2221 % o pixel: Specifies a pointer to a Quantum structure.
2222 %
2223 */
GetPixelInfoIntensity(const Image * magick_restrict image,const PixelInfo * magick_restrict pixel)2224 MagickExport MagickRealType GetPixelInfoIntensity(
2225 const Image *magick_restrict image,const PixelInfo *magick_restrict pixel)
2226 {
2227 MagickRealType
2228 blue,
2229 green,
2230 red,
2231 intensity;
2232
2233 PixelIntensityMethod
2234 method;
2235
2236 method=Rec709LumaPixelIntensityMethod;
2237 if (image != (const Image *) NULL)
2238 method=image->intensity;
2239 red=pixel->red;
2240 green=pixel->green;
2241 blue=pixel->blue;
2242 switch (method)
2243 {
2244 case AveragePixelIntensityMethod:
2245 {
2246 intensity=(red+green+blue)/3.0;
2247 break;
2248 }
2249 case BrightnessPixelIntensityMethod:
2250 {
2251 intensity=MagickMax(MagickMax(red,green),blue);
2252 break;
2253 }
2254 case LightnessPixelIntensityMethod:
2255 {
2256 intensity=(MagickMin(MagickMin(red,green),blue)+
2257 MagickMax(MagickMax(red,green),blue))/2.0;
2258 break;
2259 }
2260 case MSPixelIntensityMethod:
2261 {
2262 intensity=(MagickRealType) (((double) red*red+green*green+blue*blue)/
2263 (3.0*QuantumRange));
2264 break;
2265 }
2266 case Rec601LumaPixelIntensityMethod:
2267 {
2268 if (pixel->colorspace == RGBColorspace)
2269 {
2270 red=EncodePixelGamma(red);
2271 green=EncodePixelGamma(green);
2272 blue=EncodePixelGamma(blue);
2273 }
2274 intensity=0.298839*red+0.586811*green+0.114350*blue;
2275 break;
2276 }
2277 case Rec601LuminancePixelIntensityMethod:
2278 {
2279 if (pixel->colorspace == sRGBColorspace)
2280 {
2281 red=DecodePixelGamma(red);
2282 green=DecodePixelGamma(green);
2283 blue=DecodePixelGamma(blue);
2284 }
2285 intensity=0.298839*red+0.586811*green+0.114350*blue;
2286 break;
2287 }
2288 case Rec709LumaPixelIntensityMethod:
2289 default:
2290 {
2291 if (pixel->colorspace == RGBColorspace)
2292 {
2293 red=EncodePixelGamma(red);
2294 green=EncodePixelGamma(green);
2295 blue=EncodePixelGamma(blue);
2296 }
2297 intensity=0.212656*red+0.715158*green+0.072186*blue;
2298 break;
2299 }
2300 case Rec709LuminancePixelIntensityMethod:
2301 {
2302 if (pixel->colorspace == sRGBColorspace)
2303 {
2304 red=DecodePixelGamma(red);
2305 green=DecodePixelGamma(green);
2306 blue=DecodePixelGamma(blue);
2307 }
2308 intensity=0.212656*red+0.715158*green+0.072186*blue;
2309 break;
2310 }
2311 case RMSPixelIntensityMethod:
2312 {
2313 intensity=(MagickRealType) (sqrt((double) red*red+green*green+blue*blue)/
2314 sqrt(3.0));
2315 break;
2316 }
2317 }
2318 return(intensity);
2319 }
2320
2321 /*
2322 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2323 % %
2324 % %
2325 % %
2326 % G e t P i x e l I n t e n s i t y %
2327 % %
2328 % %
2329 % %
2330 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2331 %
2332 % GetPixelIntensity() returns a single sample intensity value from the red,
2333 % green, and blue components of a pixel based on the selected method:
2334 %
2335 % Rec601Luma 0.298839R' + 0.586811G' + 0.114350B'
2336 % Rec601Luminance 0.298839R + 0.586811G + 0.114350B
2337 % Rec709Luma 0.212656R' + 0.715158G' + 0.072186B'
2338 % Rec709Luminance 0.212656R + 0.715158G + 0.072186B
2339 % Brightness max(R', G', B')
2340 % Lightness (min(R', G', B') + max(R', G', B')) / 2.0
2341 %
2342 % MS (R^2 + G^2 + B^2) / 3.0
2343 % RMS sqrt((R^2 + G^2 + B^2) / 3.0
2344 % Average (R + G + B') / 3.0
2345 %
2346 % The format of the GetPixelIntensity method is:
2347 %
2348 % MagickRealType GetPixelIntensity(const Image *image,
2349 % const Quantum *pixel)
2350 %
2351 % A description of each parameter follows:
2352 %
2353 % o image: the image.
2354 %
2355 % o pixel: Specifies a pointer to a Quantum structure.
2356 %
2357 */
GetPixelIntensity(const Image * magick_restrict image,const Quantum * magick_restrict pixel)2358 MagickExport MagickRealType GetPixelIntensity(
2359 const Image *magick_restrict image,const Quantum *magick_restrict pixel)
2360 {
2361 MagickRealType
2362 blue,
2363 green,
2364 red,
2365 intensity;
2366
2367 red=(MagickRealType) GetPixelRed(image,pixel);
2368 green=(MagickRealType) GetPixelGreen(image,pixel);
2369 blue=(MagickRealType) GetPixelBlue(image,pixel);
2370 switch (image->intensity)
2371 {
2372 case AveragePixelIntensityMethod:
2373 {
2374 intensity=(red+green+blue)/3.0;
2375 break;
2376 }
2377 case BrightnessPixelIntensityMethod:
2378 {
2379 intensity=MagickMax(MagickMax(red,green),blue);
2380 break;
2381 }
2382 case LightnessPixelIntensityMethod:
2383 {
2384 intensity=(MagickMin(MagickMin(red,green),blue)+
2385 MagickMax(MagickMax(red,green),blue))/2.0;
2386 break;
2387 }
2388 case MSPixelIntensityMethod:
2389 {
2390 intensity=(MagickRealType) (((double) red*red+green*green+blue*blue)/
2391 (3.0*QuantumRange));
2392 break;
2393 }
2394 case Rec601LumaPixelIntensityMethod:
2395 {
2396 if (image->colorspace == RGBColorspace)
2397 {
2398 red=EncodePixelGamma(red);
2399 green=EncodePixelGamma(green);
2400 blue=EncodePixelGamma(blue);
2401 }
2402 intensity=0.298839*red+0.586811*green+0.114350*blue;
2403 break;
2404 }
2405 case Rec601LuminancePixelIntensityMethod:
2406 {
2407 if (image->colorspace == sRGBColorspace)
2408 {
2409 red=DecodePixelGamma(red);
2410 green=DecodePixelGamma(green);
2411 blue=DecodePixelGamma(blue);
2412 }
2413 intensity=0.298839*red+0.586811*green+0.114350*blue;
2414 break;
2415 }
2416 case Rec709LumaPixelIntensityMethod:
2417 default:
2418 {
2419 if (image->colorspace == RGBColorspace)
2420 {
2421 red=EncodePixelGamma(red);
2422 green=EncodePixelGamma(green);
2423 blue=EncodePixelGamma(blue);
2424 }
2425 intensity=0.212656*red+0.715158*green+0.072186*blue;
2426 break;
2427 }
2428 case Rec709LuminancePixelIntensityMethod:
2429 {
2430 if (image->colorspace == sRGBColorspace)
2431 {
2432 red=DecodePixelGamma(red);
2433 green=DecodePixelGamma(green);
2434 blue=DecodePixelGamma(blue);
2435 }
2436 intensity=0.212656*red+0.715158*green+0.072186*blue;
2437 break;
2438 }
2439 case RMSPixelIntensityMethod:
2440 {
2441 intensity=(MagickRealType) (sqrt((double) red*red+green*green+blue*blue)/
2442 sqrt(3.0));
2443 break;
2444 }
2445 }
2446 return(intensity);
2447 }
2448
2449 /*
2450 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2451 % %
2452 % %
2453 % %
2454 % I m p o r t I m a g e P i x e l s %
2455 % %
2456 % %
2457 % %
2458 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2459 %
2460 % ImportImagePixels() accepts pixel data and stores in the image at the
2461 % location you specify. The method returns MagickTrue on success otherwise
2462 % MagickFalse if an error is encountered. The pixel data can be either char,
2463 % Quantum, short int, unsigned int, unsigned long long, float, or double in
2464 % the order specified by map.
2465 %
2466 % Suppose your want to upload the first scanline of a 640x480 image from
2467 % character data in red-green-blue order:
2468 %
2469 % ImportImagePixels(image,0,0,640,1,"RGB",CharPixel,pixels);
2470 %
2471 % The format of the ImportImagePixels method is:
2472 %
2473 % MagickBooleanType ImportImagePixels(Image *image,const ssize_t x,
2474 % const ssize_t y,const size_t width,const size_t height,
2475 % const char *map,const StorageType type,const void *pixels,
2476 % ExceptionInfo *exception)
2477 %
2478 % A description of each parameter follows:
2479 %
2480 % o image: the image.
2481 %
2482 % o x,y,width,height: These values define the perimeter
2483 % of a region of pixels you want to define.
2484 %
2485 % o map: This string reflects the expected ordering of the pixel array.
2486 % It can be any combination or order of R = red, G = green, B = blue,
2487 % A = alpha (0 is transparent), O = opacity (0 is opaque), C = cyan,
2488 % Y = yellow, M = magenta, K = black, I = intensity (for grayscale),
2489 % P = pad.
2490 %
2491 % o type: Define the data type of the pixels. Float and double types are
2492 % normalized to [0..1] otherwise [0..QuantumRange]. Choose from these
2493 % types: CharPixel (char *), DoublePixel (double *), FloatPixel (float *),
2494 % LongPixel (unsigned int *), LongLongPixel (unsigned long long *),
2495 % QuantumPixel (Quantum *), or ShortPixel (unsigned short *).
2496 %
2497 % o pixels: This array of values contain the pixel components as defined by
2498 % map and type. You must preallocate this array where the expected
2499 % length varies depending on the values of width, height, map, and type.
2500 %
2501 % o exception: return any errors or warnings in this structure.
2502 %
2503 */
2504
ImportCharPixel(Image * image,const RectangleInfo * roi,const char * magick_restrict map,const QuantumType * quantum_map,const void * pixels,ExceptionInfo * exception)2505 static MagickBooleanType ImportCharPixel(Image *image,const RectangleInfo *roi,
2506 const char *magick_restrict map,const QuantumType *quantum_map,
2507 const void *pixels,ExceptionInfo *exception)
2508 {
2509 register const unsigned char
2510 *magick_restrict p;
2511
2512 register Quantum
2513 *magick_restrict q;
2514
2515 register ssize_t
2516 x;
2517
2518 size_t
2519 length;
2520
2521 ssize_t
2522 y;
2523
2524 p=(const unsigned char *) pixels;
2525 if (LocaleCompare(map,"BGR") == 0)
2526 {
2527 for (y=0; y < (ssize_t) roi->height; y++)
2528 {
2529 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
2530 if (q == (Quantum *) NULL)
2531 break;
2532 for (x=0; x < (ssize_t) roi->width; x++)
2533 {
2534 SetPixelBlue(image,ScaleCharToQuantum(*p++),q);
2535 SetPixelGreen(image,ScaleCharToQuantum(*p++),q);
2536 SetPixelRed(image,ScaleCharToQuantum(*p++),q);
2537 q+=GetPixelChannels(image);
2538 }
2539 if (SyncAuthenticPixels(image,exception) == MagickFalse)
2540 break;
2541 }
2542 return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
2543 }
2544 if (LocaleCompare(map,"BGRA") == 0)
2545 {
2546 for (y=0; y < (ssize_t) roi->height; y++)
2547 {
2548 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
2549 if (q == (Quantum *) NULL)
2550 break;
2551 for (x=0; x < (ssize_t) roi->width; x++)
2552 {
2553 SetPixelBlue(image,ScaleCharToQuantum(*p++),q);
2554 SetPixelGreen(image,ScaleCharToQuantum(*p++),q);
2555 SetPixelRed(image,ScaleCharToQuantum(*p++),q);
2556 SetPixelAlpha(image,ScaleCharToQuantum(*p++),q);
2557 q+=GetPixelChannels(image);
2558 }
2559 if (SyncAuthenticPixels(image,exception) == MagickFalse)
2560 break;
2561 }
2562 return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
2563 }
2564 if (LocaleCompare(map,"BGRO") == 0)
2565 {
2566 for (y=0; y < (ssize_t) roi->height; y++)
2567 {
2568 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
2569 if (q == (Quantum *) NULL)
2570 break;
2571 for (x=0; x < (ssize_t) roi->width; x++)
2572 {
2573 SetPixelBlue(image,ScaleCharToQuantum(*p++),q);
2574 SetPixelGreen(image,ScaleCharToQuantum(*p++),q);
2575 SetPixelRed(image,ScaleCharToQuantum(*p++),q);
2576 SetPixelAlpha(image,ScaleCharToQuantum(*p++),q);
2577 q+=GetPixelChannels(image);
2578 }
2579 if (SyncAuthenticPixels(image,exception) == MagickFalse)
2580 break;
2581 }
2582 return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
2583 }
2584 if (LocaleCompare(map,"BGRP") == 0)
2585 {
2586 for (y=0; y < (ssize_t) roi->height; y++)
2587 {
2588 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
2589 if (q == (Quantum *) NULL)
2590 break;
2591 for (x=0; x < (ssize_t) roi->width; x++)
2592 {
2593 SetPixelBlue(image,ScaleCharToQuantum(*p++),q);
2594 SetPixelGreen(image,ScaleCharToQuantum(*p++),q);
2595 SetPixelRed(image,ScaleCharToQuantum(*p++),q);
2596 p++;
2597 q+=GetPixelChannels(image);
2598 }
2599 if (SyncAuthenticPixels(image,exception) == MagickFalse)
2600 break;
2601 }
2602 return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
2603 }
2604 if (LocaleCompare(map,"I") == 0)
2605 {
2606 for (y=0; y < (ssize_t) roi->height; y++)
2607 {
2608 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
2609 if (q == (Quantum *) NULL)
2610 break;
2611 for (x=0; x < (ssize_t) roi->width; x++)
2612 {
2613 SetPixelGray(image,ScaleCharToQuantum(*p++),q);
2614 q+=GetPixelChannels(image);
2615 }
2616 if (SyncAuthenticPixels(image,exception) == MagickFalse)
2617 break;
2618 }
2619 return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
2620 }
2621 if (LocaleCompare(map,"RGB") == 0)
2622 {
2623 for (y=0; y < (ssize_t) roi->height; y++)
2624 {
2625 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
2626 if (q == (Quantum *) NULL)
2627 break;
2628 for (x=0; x < (ssize_t) roi->width; x++)
2629 {
2630 SetPixelRed(image,ScaleCharToQuantum(*p++),q);
2631 SetPixelGreen(image,ScaleCharToQuantum(*p++),q);
2632 SetPixelBlue(image,ScaleCharToQuantum(*p++),q);
2633 q+=GetPixelChannels(image);
2634 }
2635 if (SyncAuthenticPixels(image,exception) == MagickFalse)
2636 break;
2637 }
2638 return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
2639 }
2640 if (LocaleCompare(map,"RGBA") == 0)
2641 {
2642 for (y=0; y < (ssize_t) roi->height; y++)
2643 {
2644 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
2645 if (q == (Quantum *) NULL)
2646 break;
2647 for (x=0; x < (ssize_t) roi->width; x++)
2648 {
2649 SetPixelRed(image,ScaleCharToQuantum(*p++),q);
2650 SetPixelGreen(image,ScaleCharToQuantum(*p++),q);
2651 SetPixelBlue(image,ScaleCharToQuantum(*p++),q);
2652 SetPixelAlpha(image,ScaleCharToQuantum(*p++),q);
2653 q+=GetPixelChannels(image);
2654 }
2655 if (SyncAuthenticPixels(image,exception) == MagickFalse)
2656 break;
2657 }
2658 return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
2659 }
2660 if (LocaleCompare(map,"RGBO") == 0)
2661 {
2662 for (y=0; y < (ssize_t) roi->height; y++)
2663 {
2664 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
2665 if (q == (Quantum *) NULL)
2666 break;
2667 for (x=0; x < (ssize_t) roi->width; x++)
2668 {
2669 SetPixelRed(image,ScaleCharToQuantum(*p++),q);
2670 SetPixelGreen(image,ScaleCharToQuantum(*p++),q);
2671 SetPixelBlue(image,ScaleCharToQuantum(*p++),q);
2672 SetPixelAlpha(image,ScaleCharToQuantum(*p++),q);
2673 q+=GetPixelChannels(image);
2674 }
2675 if (SyncAuthenticPixels(image,exception) == MagickFalse)
2676 break;
2677 }
2678 return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
2679 }
2680 if (LocaleCompare(map,"RGBP") == 0)
2681 {
2682 for (y=0; y < (ssize_t) roi->height; y++)
2683 {
2684 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
2685 if (q == (Quantum *) NULL)
2686 break;
2687 for (x=0; x < (ssize_t) roi->width; x++)
2688 {
2689 SetPixelRed(image,ScaleCharToQuantum(*p++),q);
2690 SetPixelGreen(image,ScaleCharToQuantum(*p++),q);
2691 SetPixelBlue(image,ScaleCharToQuantum(*p++),q);
2692 p++;
2693 q+=GetPixelChannels(image);
2694 }
2695 if (SyncAuthenticPixels(image,exception) == MagickFalse)
2696 break;
2697 }
2698 return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
2699 }
2700 length=strlen(map);
2701 for (y=0; y < (ssize_t) roi->height; y++)
2702 {
2703 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
2704 if (q == (Quantum *) NULL)
2705 break;
2706 for (x=0; x < (ssize_t) roi->width; x++)
2707 {
2708 register ssize_t
2709 i;
2710
2711 for (i=0; i < (ssize_t) length; i++)
2712 {
2713 switch (quantum_map[i])
2714 {
2715 case RedQuantum:
2716 case CyanQuantum:
2717 {
2718 SetPixelRed(image,ScaleCharToQuantum(*p),q);
2719 break;
2720 }
2721 case GreenQuantum:
2722 case MagentaQuantum:
2723 {
2724 SetPixelGreen(image,ScaleCharToQuantum(*p),q);
2725 break;
2726 }
2727 case BlueQuantum:
2728 case YellowQuantum:
2729 {
2730 SetPixelBlue(image,ScaleCharToQuantum(*p),q);
2731 break;
2732 }
2733 case AlphaQuantum:
2734 {
2735 SetPixelAlpha(image,ScaleCharToQuantum(*p),q);
2736 break;
2737 }
2738 case OpacityQuantum:
2739 {
2740 SetPixelAlpha(image,ScaleCharToQuantum(*p),q);
2741 break;
2742 }
2743 case BlackQuantum:
2744 {
2745 SetPixelBlack(image,ScaleCharToQuantum(*p),q);
2746 break;
2747 }
2748 case IndexQuantum:
2749 {
2750 SetPixelGray(image,ScaleCharToQuantum(*p),q);
2751 break;
2752 }
2753 default:
2754 break;
2755 }
2756 p++;
2757 }
2758 q+=GetPixelChannels(image);
2759 }
2760 if (SyncAuthenticPixels(image,exception) == MagickFalse)
2761 break;
2762 }
2763 return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
2764 }
2765
ImportDoublePixel(Image * image,const RectangleInfo * roi,const char * magick_restrict map,const QuantumType * quantum_map,const void * pixels,ExceptionInfo * exception)2766 static MagickBooleanType ImportDoublePixel(Image *image,
2767 const RectangleInfo *roi,const char *magick_restrict map,
2768 const QuantumType *quantum_map,const void *pixels,ExceptionInfo *exception)
2769 {
2770 register const double
2771 *magick_restrict p;
2772
2773 register Quantum
2774 *magick_restrict q;
2775
2776 register ssize_t
2777 x;
2778
2779 size_t
2780 length;
2781
2782 ssize_t
2783 y;
2784
2785 p=(const double *) pixels;
2786 if (LocaleCompare(map,"BGR") == 0)
2787 {
2788 for (y=0; y < (ssize_t) roi->height; y++)
2789 {
2790 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
2791 if (q == (Quantum *) NULL)
2792 break;
2793 for (x=0; x < (ssize_t) roi->width; x++)
2794 {
2795 SetPixelBlue(image,ClampToQuantum(QuantumRange*(*p)),q);
2796 p++;
2797 SetPixelGreen(image,ClampToQuantum(QuantumRange*(*p)),q);
2798 p++;
2799 SetPixelRed(image,ClampToQuantum(QuantumRange*(*p)),q);
2800 p++;
2801 q+=GetPixelChannels(image);
2802 }
2803 if (SyncAuthenticPixels(image,exception) == MagickFalse)
2804 break;
2805 }
2806 return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
2807 }
2808 if (LocaleCompare(map,"BGRA") == 0)
2809 {
2810 for (y=0; y < (ssize_t) roi->height; y++)
2811 {
2812 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
2813 if (q == (Quantum *) NULL)
2814 break;
2815 for (x=0; x < (ssize_t) roi->width; x++)
2816 {
2817 SetPixelBlue(image,ClampToQuantum(QuantumRange*(*p)),q);
2818 p++;
2819 SetPixelGreen(image,ClampToQuantum(QuantumRange*(*p)),q);
2820 p++;
2821 SetPixelRed(image,ClampToQuantum(QuantumRange*(*p)),q);
2822 p++;
2823 SetPixelAlpha(image,ClampToQuantum(QuantumRange*(*p)),q);
2824 p++;
2825 q+=GetPixelChannels(image);
2826 }
2827 if (SyncAuthenticPixels(image,exception) == MagickFalse)
2828 break;
2829 }
2830 return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
2831 }
2832 if (LocaleCompare(map,"BGRP") == 0)
2833 {
2834 for (y=0; y < (ssize_t) roi->height; y++)
2835 {
2836 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
2837 if (q == (Quantum *) NULL)
2838 break;
2839 for (x=0; x < (ssize_t) roi->width; x++)
2840 {
2841 SetPixelBlue(image,ClampToQuantum(QuantumRange*(*p)),q);
2842 p++;
2843 SetPixelGreen(image,ClampToQuantum(QuantumRange*(*p)),q);
2844 p++;
2845 SetPixelRed(image,ClampToQuantum(QuantumRange*(*p)),q);
2846 p++;
2847 p++;
2848 q+=GetPixelChannels(image);
2849 }
2850 if (SyncAuthenticPixels(image,exception) == MagickFalse)
2851 break;
2852 }
2853 return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
2854 }
2855 if (LocaleCompare(map,"I") == 0)
2856 {
2857 for (y=0; y < (ssize_t) roi->height; y++)
2858 {
2859 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
2860 if (q == (Quantum *) NULL)
2861 break;
2862 for (x=0; x < (ssize_t) roi->width; x++)
2863 {
2864 SetPixelGray(image,ClampToQuantum(QuantumRange*(*p)),q);
2865 p++;
2866 q+=GetPixelChannels(image);
2867 }
2868 if (SyncAuthenticPixels(image,exception) == MagickFalse)
2869 break;
2870 }
2871 return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
2872 }
2873 if (LocaleCompare(map,"RGB") == 0)
2874 {
2875 for (y=0; y < (ssize_t) roi->height; y++)
2876 {
2877 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
2878 if (q == (Quantum *) NULL)
2879 break;
2880 for (x=0; x < (ssize_t) roi->width; x++)
2881 {
2882 SetPixelRed(image,ClampToQuantum(QuantumRange*(*p)),q);
2883 p++;
2884 SetPixelGreen(image,ClampToQuantum(QuantumRange*(*p)),q);
2885 p++;
2886 SetPixelBlue(image,ClampToQuantum(QuantumRange*(*p)),q);
2887 p++;
2888 q+=GetPixelChannels(image);
2889 }
2890 if (SyncAuthenticPixels(image,exception) == MagickFalse)
2891 break;
2892 }
2893 return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
2894 }
2895 if (LocaleCompare(map,"RGBA") == 0)
2896 {
2897 for (y=0; y < (ssize_t) roi->height; y++)
2898 {
2899 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
2900 if (q == (Quantum *) NULL)
2901 break;
2902 for (x=0; x < (ssize_t) roi->width; x++)
2903 {
2904 SetPixelRed(image,ClampToQuantum(QuantumRange*(*p)),q);
2905 p++;
2906 SetPixelGreen(image,ClampToQuantum(QuantumRange*(*p)),q);
2907 p++;
2908 SetPixelBlue(image,ClampToQuantum(QuantumRange*(*p)),q);
2909 p++;
2910 SetPixelAlpha(image,ClampToQuantum(QuantumRange*(*p)),q);
2911 p++;
2912 q+=GetPixelChannels(image);
2913 }
2914 if (SyncAuthenticPixels(image,exception) == MagickFalse)
2915 break;
2916 }
2917 return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
2918 }
2919 if (LocaleCompare(map,"RGBP") == 0)
2920 {
2921 for (y=0; y < (ssize_t) roi->height; y++)
2922 {
2923 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
2924 if (q == (Quantum *) NULL)
2925 break;
2926 for (x=0; x < (ssize_t) roi->width; x++)
2927 {
2928 SetPixelRed(image,ClampToQuantum(QuantumRange*(*p)),q);
2929 p++;
2930 SetPixelGreen(image,ClampToQuantum(QuantumRange*(*p)),q);
2931 p++;
2932 SetPixelBlue(image,ClampToQuantum(QuantumRange*(*p)),q);
2933 p++;
2934 q+=GetPixelChannels(image);
2935 }
2936 if (SyncAuthenticPixels(image,exception) == MagickFalse)
2937 break;
2938 }
2939 return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
2940 }
2941 length=strlen(map);
2942 for (y=0; y < (ssize_t) roi->height; y++)
2943 {
2944 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
2945 if (q == (Quantum *) NULL)
2946 break;
2947 for (x=0; x < (ssize_t) roi->width; x++)
2948 {
2949 register ssize_t
2950 i;
2951
2952 for (i=0; i < (ssize_t) length; i++)
2953 {
2954 switch (quantum_map[i])
2955 {
2956 case RedQuantum:
2957 case CyanQuantum:
2958 {
2959 SetPixelRed(image,ClampToQuantum(QuantumRange*(*p)),q);
2960 break;
2961 }
2962 case GreenQuantum:
2963 case MagentaQuantum:
2964 {
2965 SetPixelGreen(image,ClampToQuantum(QuantumRange*(*p)),q);
2966 break;
2967 }
2968 case BlueQuantum:
2969 case YellowQuantum:
2970 {
2971 SetPixelBlue(image,ClampToQuantum(QuantumRange*(*p)),q);
2972 break;
2973 }
2974 case AlphaQuantum:
2975 {
2976 SetPixelAlpha(image,ClampToQuantum(QuantumRange*(*p)),q);
2977 break;
2978 }
2979 case OpacityQuantum:
2980 {
2981 SetPixelAlpha(image,ClampToQuantum(QuantumRange*(*p)),q);
2982 break;
2983 }
2984 case BlackQuantum:
2985 {
2986 SetPixelBlack(image,ClampToQuantum(QuantumRange*(*p)),q);
2987 break;
2988 }
2989 case IndexQuantum:
2990 {
2991 SetPixelGray(image,ClampToQuantum(QuantumRange*(*p)),q);
2992 break;
2993 }
2994 default:
2995 break;
2996 }
2997 p++;
2998 }
2999 q+=GetPixelChannels(image);
3000 }
3001 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3002 break;
3003 }
3004 return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
3005 }
3006
ImportFloatPixel(Image * image,const RectangleInfo * roi,const char * magick_restrict map,const QuantumType * quantum_map,const void * pixels,ExceptionInfo * exception)3007 static MagickBooleanType ImportFloatPixel(Image *image,const RectangleInfo *roi,
3008 const char *magick_restrict map,const QuantumType *quantum_map,
3009 const void *pixels,ExceptionInfo *exception)
3010 {
3011 register const float
3012 *magick_restrict p;
3013
3014 register Quantum
3015 *magick_restrict q;
3016
3017 register ssize_t
3018 x;
3019
3020 size_t
3021 length;
3022
3023 ssize_t
3024 y;
3025
3026 p=(const float *) pixels;
3027 if (LocaleCompare(map,"BGR") == 0)
3028 {
3029 for (y=0; y < (ssize_t) roi->height; y++)
3030 {
3031 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
3032 if (q == (Quantum *) NULL)
3033 break;
3034 for (x=0; x < (ssize_t) roi->width; x++)
3035 {
3036 SetPixelBlue(image,ClampToQuantum(QuantumRange*(*p)),q);
3037 p++;
3038 SetPixelGreen(image,ClampToQuantum(QuantumRange*(*p)),q);
3039 p++;
3040 SetPixelRed(image,ClampToQuantum(QuantumRange*(*p)),q);
3041 p++;
3042 q+=GetPixelChannels(image);
3043 }
3044 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3045 break;
3046 }
3047 return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
3048 }
3049 if (LocaleCompare(map,"BGRA") == 0)
3050 {
3051 for (y=0; y < (ssize_t) roi->height; y++)
3052 {
3053 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
3054 if (q == (Quantum *) NULL)
3055 break;
3056 for (x=0; x < (ssize_t) roi->width; x++)
3057 {
3058 SetPixelBlue(image,ClampToQuantum(QuantumRange*(*p)),q);
3059 p++;
3060 SetPixelGreen(image,ClampToQuantum(QuantumRange*(*p)),q);
3061 p++;
3062 SetPixelRed(image,ClampToQuantum(QuantumRange*(*p)),q);
3063 p++;
3064 SetPixelAlpha(image,ClampToQuantum(QuantumRange*(*p)),q);
3065 p++;
3066 q+=GetPixelChannels(image);
3067 }
3068 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3069 break;
3070 }
3071 return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
3072 }
3073 if (LocaleCompare(map,"BGRP") == 0)
3074 {
3075 for (y=0; y < (ssize_t) roi->height; y++)
3076 {
3077 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
3078 if (q == (Quantum *) NULL)
3079 break;
3080 for (x=0; x < (ssize_t) roi->width; x++)
3081 {
3082 SetPixelBlue(image,ClampToQuantum(QuantumRange*(*p)),q);
3083 p++;
3084 SetPixelGreen(image,ClampToQuantum(QuantumRange*(*p)),q);
3085 p++;
3086 SetPixelRed(image,ClampToQuantum(QuantumRange*(*p)),q);
3087 p++;
3088 p++;
3089 q+=GetPixelChannels(image);
3090 }
3091 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3092 break;
3093 }
3094 return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
3095 }
3096 if (LocaleCompare(map,"I") == 0)
3097 {
3098 for (y=0; y < (ssize_t) roi->height; y++)
3099 {
3100 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
3101 if (q == (Quantum *) NULL)
3102 break;
3103 for (x=0; x < (ssize_t) roi->width; x++)
3104 {
3105 SetPixelGray(image,ClampToQuantum(QuantumRange*(*p)),q);
3106 p++;
3107 q+=GetPixelChannels(image);
3108 }
3109 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3110 break;
3111 }
3112 return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
3113 }
3114 if (LocaleCompare(map,"RGB") == 0)
3115 {
3116 for (y=0; y < (ssize_t) roi->height; y++)
3117 {
3118 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
3119 if (q == (Quantum *) NULL)
3120 break;
3121 for (x=0; x < (ssize_t) roi->width; x++)
3122 {
3123 SetPixelRed(image,ClampToQuantum(QuantumRange*(*p)),q);
3124 p++;
3125 SetPixelGreen(image,ClampToQuantum(QuantumRange*(*p)),q);
3126 p++;
3127 SetPixelBlue(image,ClampToQuantum(QuantumRange*(*p)),q);
3128 p++;
3129 q+=GetPixelChannels(image);
3130 }
3131 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3132 break;
3133 }
3134 return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
3135 }
3136 if (LocaleCompare(map,"RGBA") == 0)
3137 {
3138 for (y=0; y < (ssize_t) roi->height; y++)
3139 {
3140 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
3141 if (q == (Quantum *) NULL)
3142 break;
3143 for (x=0; x < (ssize_t) roi->width; x++)
3144 {
3145 SetPixelRed(image,ClampToQuantum(QuantumRange*(*p)),q);
3146 p++;
3147 SetPixelGreen(image,ClampToQuantum(QuantumRange*(*p)),q);
3148 p++;
3149 SetPixelBlue(image,ClampToQuantum(QuantumRange*(*p)),q);
3150 p++;
3151 SetPixelAlpha(image,ClampToQuantum(QuantumRange*(*p)),q);
3152 p++;
3153 q+=GetPixelChannels(image);
3154 }
3155 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3156 break;
3157 }
3158 return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
3159 }
3160 if (LocaleCompare(map,"RGBP") == 0)
3161 {
3162 for (y=0; y < (ssize_t) roi->height; y++)
3163 {
3164 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
3165 if (q == (Quantum *) NULL)
3166 break;
3167 for (x=0; x < (ssize_t) roi->width; x++)
3168 {
3169 SetPixelRed(image,ClampToQuantum(QuantumRange*(*p)),q);
3170 p++;
3171 SetPixelGreen(image,ClampToQuantum(QuantumRange*(*p)),q);
3172 p++;
3173 SetPixelBlue(image,ClampToQuantum(QuantumRange*(*p)),q);
3174 p++;
3175 q+=GetPixelChannels(image);
3176 }
3177 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3178 break;
3179 }
3180 return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
3181 }
3182 length=strlen(map);
3183 for (y=0; y < (ssize_t) roi->height; y++)
3184 {
3185 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
3186 if (q == (Quantum *) NULL)
3187 break;
3188 for (x=0; x < (ssize_t) roi->width; x++)
3189 {
3190 register ssize_t
3191 i;
3192
3193 for (i=0; i < (ssize_t) length; i++)
3194 {
3195 switch (quantum_map[i])
3196 {
3197 case RedQuantum:
3198 case CyanQuantum:
3199 {
3200 SetPixelRed(image,ClampToQuantum(QuantumRange*(*p)),q);
3201 break;
3202 }
3203 case GreenQuantum:
3204 case MagentaQuantum:
3205 {
3206 SetPixelGreen(image,ClampToQuantum(QuantumRange*(*p)),q);
3207 break;
3208 }
3209 case BlueQuantum:
3210 case YellowQuantum:
3211 {
3212 SetPixelBlue(image,ClampToQuantum(QuantumRange*(*p)),q);
3213 break;
3214 }
3215 case AlphaQuantum:
3216 {
3217 SetPixelAlpha(image,ClampToQuantum(QuantumRange*(*p)),q);
3218 break;
3219 }
3220 case OpacityQuantum:
3221 {
3222 SetPixelAlpha(image,ClampToQuantum(QuantumRange*(*p)),q);
3223 break;
3224 }
3225 case BlackQuantum:
3226 {
3227 SetPixelBlack(image,ClampToQuantum(QuantumRange*(*p)),q);
3228 break;
3229 }
3230 case IndexQuantum:
3231 {
3232 SetPixelGray(image,ClampToQuantum(QuantumRange*(*p)),q);
3233 break;
3234 }
3235 default:
3236 break;
3237 }
3238 p++;
3239 }
3240 q+=GetPixelChannels(image);
3241 }
3242 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3243 break;
3244 }
3245 return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
3246 }
3247
ImportLongPixel(Image * image,const RectangleInfo * roi,const char * magick_restrict map,const QuantumType * quantum_map,const void * pixels,ExceptionInfo * exception)3248 static MagickBooleanType ImportLongPixel(Image *image,const RectangleInfo *roi,
3249 const char *magick_restrict map,const QuantumType *quantum_map,
3250 const void *pixels,ExceptionInfo *exception)
3251 {
3252 register const unsigned int
3253 *magick_restrict p;
3254
3255 register Quantum
3256 *magick_restrict q;
3257
3258 register ssize_t
3259 x;
3260
3261 size_t
3262 length;
3263
3264 ssize_t
3265 y;
3266
3267 p=(const unsigned int *) pixels;
3268 if (LocaleCompare(map,"BGR") == 0)
3269 {
3270 for (y=0; y < (ssize_t) roi->height; y++)
3271 {
3272 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
3273 if (q == (Quantum *) NULL)
3274 break;
3275 for (x=0; x < (ssize_t) roi->width; x++)
3276 {
3277 SetPixelBlue(image,ScaleLongToQuantum(*p++),q);
3278 SetPixelGreen(image,ScaleLongToQuantum(*p++),q);
3279 SetPixelRed(image,ScaleLongToQuantum(*p++),q);
3280 q+=GetPixelChannels(image);
3281 }
3282 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3283 break;
3284 }
3285 return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
3286 }
3287 if (LocaleCompare(map,"BGRA") == 0)
3288 {
3289 for (y=0; y < (ssize_t) roi->height; y++)
3290 {
3291 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
3292 if (q == (Quantum *) NULL)
3293 break;
3294 for (x=0; x < (ssize_t) roi->width; x++)
3295 {
3296 SetPixelBlue(image,ScaleLongToQuantum(*p++),q);
3297 SetPixelGreen(image,ScaleLongToQuantum(*p++),q);
3298 SetPixelRed(image,ScaleLongToQuantum(*p++),q);
3299 SetPixelAlpha(image,ScaleLongToQuantum(*p++),q);
3300 q+=GetPixelChannels(image);
3301 }
3302 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3303 break;
3304 }
3305 return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
3306 }
3307 if (LocaleCompare(map,"BGRP") == 0)
3308 {
3309 for (y=0; y < (ssize_t) roi->height; y++)
3310 {
3311 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
3312 if (q == (Quantum *) NULL)
3313 break;
3314 for (x=0; x < (ssize_t) roi->width; x++)
3315 {
3316 SetPixelBlue(image,ScaleLongToQuantum(*p++),q);
3317 SetPixelGreen(image,ScaleLongToQuantum(*p++),q);
3318 SetPixelRed(image,ScaleLongToQuantum(*p++),q);
3319 p++;
3320 q+=GetPixelChannels(image);
3321 }
3322 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3323 break;
3324 }
3325 return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
3326 }
3327 if (LocaleCompare(map,"I") == 0)
3328 {
3329 for (y=0; y < (ssize_t) roi->height; y++)
3330 {
3331 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
3332 if (q == (Quantum *) NULL)
3333 break;
3334 for (x=0; x < (ssize_t) roi->width; x++)
3335 {
3336 SetPixelGray(image,ScaleLongToQuantum(*p++),q);
3337 q+=GetPixelChannels(image);
3338 }
3339 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3340 break;
3341 }
3342 return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
3343 }
3344 if (LocaleCompare(map,"RGB") == 0)
3345 {
3346 for (y=0; y < (ssize_t) roi->height; y++)
3347 {
3348 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
3349 if (q == (Quantum *) NULL)
3350 break;
3351 for (x=0; x < (ssize_t) roi->width; x++)
3352 {
3353 SetPixelRed(image,ScaleLongToQuantum(*p++),q);
3354 SetPixelGreen(image,ScaleLongToQuantum(*p++),q);
3355 SetPixelBlue(image,ScaleLongToQuantum(*p++),q);
3356 q+=GetPixelChannels(image);
3357 }
3358 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3359 break;
3360 }
3361 return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
3362 }
3363 if (LocaleCompare(map,"RGBA") == 0)
3364 {
3365 for (y=0; y < (ssize_t) roi->height; y++)
3366 {
3367 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
3368 if (q == (Quantum *) NULL)
3369 break;
3370 for (x=0; x < (ssize_t) roi->width; x++)
3371 {
3372 SetPixelRed(image,ScaleLongToQuantum(*p++),q);
3373 SetPixelGreen(image,ScaleLongToQuantum(*p++),q);
3374 SetPixelBlue(image,ScaleLongToQuantum(*p++),q);
3375 SetPixelAlpha(image,ScaleLongToQuantum(*p++),q);
3376 q+=GetPixelChannels(image);
3377 }
3378 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3379 break;
3380 }
3381 return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
3382 }
3383 if (LocaleCompare(map,"RGBP") == 0)
3384 {
3385 for (y=0; y < (ssize_t) roi->height; y++)
3386 {
3387 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
3388 if (q == (Quantum *) NULL)
3389 break;
3390 for (x=0; x < (ssize_t) roi->width; x++)
3391 {
3392 SetPixelRed(image,ScaleLongToQuantum(*p++),q);
3393 SetPixelGreen(image,ScaleLongToQuantum(*p++),q);
3394 SetPixelBlue(image,ScaleLongToQuantum(*p++),q);
3395 p++;
3396 q+=GetPixelChannels(image);
3397 }
3398 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3399 break;
3400 }
3401 return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
3402 }
3403 length=strlen(map);
3404 for (y=0; y < (ssize_t) roi->height; y++)
3405 {
3406 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
3407 if (q == (Quantum *) NULL)
3408 break;
3409 for (x=0; x < (ssize_t) roi->width; x++)
3410 {
3411 register ssize_t
3412 i;
3413
3414 for (i=0; i < (ssize_t) length; i++)
3415 {
3416 switch (quantum_map[i])
3417 {
3418 case RedQuantum:
3419 case CyanQuantum:
3420 {
3421 SetPixelRed(image,ScaleLongToQuantum(*p),q);
3422 break;
3423 }
3424 case GreenQuantum:
3425 case MagentaQuantum:
3426 {
3427 SetPixelGreen(image,ScaleLongToQuantum(*p),q);
3428 break;
3429 }
3430 case BlueQuantum:
3431 case YellowQuantum:
3432 {
3433 SetPixelBlue(image,ScaleLongToQuantum(*p),q);
3434 break;
3435 }
3436 case AlphaQuantum:
3437 {
3438 SetPixelAlpha(image,ScaleLongToQuantum(*p),q);
3439 break;
3440 }
3441 case OpacityQuantum:
3442 {
3443 SetPixelAlpha(image,ScaleLongToQuantum(*p),q);
3444 break;
3445 }
3446 case BlackQuantum:
3447 {
3448 SetPixelBlack(image,ScaleLongToQuantum(*p),q);
3449 break;
3450 }
3451 case IndexQuantum:
3452 {
3453 SetPixelGray(image,ScaleLongToQuantum(*p),q);
3454 break;
3455 }
3456 default:
3457 break;
3458 }
3459 p++;
3460 }
3461 q+=GetPixelChannels(image);
3462 }
3463 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3464 break;
3465 }
3466 return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
3467 }
3468
ImportLongLongPixel(Image * image,const RectangleInfo * roi,const char * magick_restrict map,const QuantumType * quantum_map,const void * pixels,ExceptionInfo * exception)3469 static MagickBooleanType ImportLongLongPixel(Image *image,
3470 const RectangleInfo *roi,const char *magick_restrict map,
3471 const QuantumType *quantum_map,const void *pixels,ExceptionInfo *exception)
3472 {
3473 register const MagickSizeType
3474 *magick_restrict p;
3475
3476 register Quantum
3477 *magick_restrict q;
3478
3479 register ssize_t
3480 x;
3481
3482 size_t
3483 length;
3484
3485 ssize_t
3486 y;
3487
3488 p=(const MagickSizeType *) pixels;
3489 if (LocaleCompare(map,"BGR") == 0)
3490 {
3491 for (y=0; y < (ssize_t) roi->height; y++)
3492 {
3493 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
3494 if (q == (Quantum *) NULL)
3495 break;
3496 for (x=0; x < (ssize_t) roi->width; x++)
3497 {
3498 SetPixelBlue(image,ScaleLongLongToQuantum(*p++),q);
3499 SetPixelGreen(image,ScaleLongLongToQuantum(*p++),q);
3500 SetPixelRed(image,ScaleLongLongToQuantum(*p++),q);
3501 q+=GetPixelChannels(image);
3502 }
3503 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3504 break;
3505 }
3506 return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
3507 }
3508 if (LocaleCompare(map,"BGRA") == 0)
3509 {
3510 for (y=0; y < (ssize_t) roi->height; y++)
3511 {
3512 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
3513 if (q == (Quantum *) NULL)
3514 break;
3515 for (x=0; x < (ssize_t) roi->width; x++)
3516 {
3517 SetPixelBlue(image,ScaleLongLongToQuantum(*p++),q);
3518 SetPixelGreen(image,ScaleLongLongToQuantum(*p++),q);
3519 SetPixelRed(image,ScaleLongLongToQuantum(*p++),q);
3520 SetPixelAlpha(image,ScaleLongLongToQuantum(*p++),q);
3521 q+=GetPixelChannels(image);
3522 }
3523 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3524 break;
3525 }
3526 return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
3527 }
3528 if (LocaleCompare(map,"BGRP") == 0)
3529 {
3530 for (y=0; y < (ssize_t) roi->height; y++)
3531 {
3532 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
3533 if (q == (Quantum *) NULL)
3534 break;
3535 for (x=0; x < (ssize_t) roi->width; x++)
3536 {
3537 SetPixelBlue(image,ScaleLongLongToQuantum(*p++),q);
3538 SetPixelGreen(image,ScaleLongLongToQuantum(*p++),q);
3539 SetPixelRed(image,ScaleLongLongToQuantum(*p++),q);
3540 p++;
3541 q+=GetPixelChannels(image);
3542 }
3543 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3544 break;
3545 }
3546 return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
3547 }
3548 if (LocaleCompare(map,"I") == 0)
3549 {
3550 for (y=0; y < (ssize_t) roi->height; y++)
3551 {
3552 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
3553 if (q == (Quantum *) NULL)
3554 break;
3555 for (x=0; x < (ssize_t) roi->width; x++)
3556 {
3557 SetPixelGray(image,ScaleLongLongToQuantum(*p++),q);
3558 q+=GetPixelChannels(image);
3559 }
3560 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3561 break;
3562 }
3563 return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
3564 }
3565 if (LocaleCompare(map,"RGB") == 0)
3566 {
3567 for (y=0; y < (ssize_t) roi->height; y++)
3568 {
3569 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
3570 if (q == (Quantum *) NULL)
3571 break;
3572 for (x=0; x < (ssize_t) roi->width; x++)
3573 {
3574 SetPixelRed(image,ScaleLongLongToQuantum(*p++),q);
3575 SetPixelGreen(image,ScaleLongLongToQuantum(*p++),q);
3576 SetPixelBlue(image,ScaleLongLongToQuantum(*p++),q);
3577 q+=GetPixelChannels(image);
3578 }
3579 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3580 break;
3581 }
3582 return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
3583 }
3584 if (LocaleCompare(map,"RGBA") == 0)
3585 {
3586 for (y=0; y < (ssize_t) roi->height; y++)
3587 {
3588 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
3589 if (q == (Quantum *) NULL)
3590 break;
3591 for (x=0; x < (ssize_t) roi->width; x++)
3592 {
3593 SetPixelRed(image,ScaleLongLongToQuantum(*p++),q);
3594 SetPixelGreen(image,ScaleLongLongToQuantum(*p++),q);
3595 SetPixelBlue(image,ScaleLongLongToQuantum(*p++),q);
3596 SetPixelAlpha(image,ScaleLongLongToQuantum(*p++),q);
3597 q+=GetPixelChannels(image);
3598 }
3599 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3600 break;
3601 }
3602 return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
3603 }
3604 if (LocaleCompare(map,"RGBP") == 0)
3605 {
3606 for (y=0; y < (ssize_t) roi->height; y++)
3607 {
3608 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
3609 if (q == (Quantum *) NULL)
3610 break;
3611 for (x=0; x < (ssize_t) roi->width; x++)
3612 {
3613 SetPixelRed(image,ScaleLongLongToQuantum(*p++),q);
3614 SetPixelGreen(image,ScaleLongLongToQuantum(*p++),q);
3615 SetPixelBlue(image,ScaleLongLongToQuantum(*p++),q);
3616 p++;
3617 q+=GetPixelChannels(image);
3618 }
3619 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3620 break;
3621 }
3622 return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
3623 }
3624 length=strlen(map);
3625 for (y=0; y < (ssize_t) roi->height; y++)
3626 {
3627 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
3628 if (q == (Quantum *) NULL)
3629 break;
3630 for (x=0; x < (ssize_t) roi->width; x++)
3631 {
3632 register ssize_t
3633 i;
3634
3635 for (i=0; i < (ssize_t) length; i++)
3636 {
3637 switch (quantum_map[i])
3638 {
3639 case RedQuantum:
3640 case CyanQuantum:
3641 {
3642 SetPixelRed(image,ScaleLongLongToQuantum(*p),q);
3643 break;
3644 }
3645 case GreenQuantum:
3646 case MagentaQuantum:
3647 {
3648 SetPixelGreen(image,ScaleLongLongToQuantum(*p),q);
3649 break;
3650 }
3651 case BlueQuantum:
3652 case YellowQuantum:
3653 {
3654 SetPixelBlue(image,ScaleLongLongToQuantum(*p),q);
3655 break;
3656 }
3657 case AlphaQuantum:
3658 {
3659 SetPixelAlpha(image,ScaleLongLongToQuantum(*p),q);
3660 break;
3661 }
3662 case OpacityQuantum:
3663 {
3664 SetPixelAlpha(image,ScaleLongLongToQuantum(*p),q);
3665 break;
3666 }
3667 case BlackQuantum:
3668 {
3669 SetPixelBlack(image,ScaleLongLongToQuantum(*p),q);
3670 break;
3671 }
3672 case IndexQuantum:
3673 {
3674 SetPixelGray(image,ScaleLongLongToQuantum(*p),q);
3675 break;
3676 }
3677 default:
3678 break;
3679 }
3680 p++;
3681 }
3682 q+=GetPixelChannels(image);
3683 }
3684 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3685 break;
3686 }
3687 return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
3688 }
3689
ImportQuantumPixel(Image * image,const RectangleInfo * roi,const char * magick_restrict map,const QuantumType * quantum_map,const void * pixels,ExceptionInfo * exception)3690 static MagickBooleanType ImportQuantumPixel(Image *image,
3691 const RectangleInfo *roi,const char *magick_restrict map,
3692 const QuantumType *quantum_map,const void *pixels,ExceptionInfo *exception)
3693 {
3694 register const Quantum
3695 *magick_restrict p;
3696
3697 register Quantum
3698 *magick_restrict q;
3699
3700 register ssize_t
3701 x;
3702
3703 size_t
3704 length;
3705
3706 ssize_t
3707 y;
3708
3709 p=(const Quantum *) pixels;
3710 if (LocaleCompare(map,"BGR") == 0)
3711 {
3712 for (y=0; y < (ssize_t) roi->height; y++)
3713 {
3714 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
3715 if (q == (Quantum *) NULL)
3716 break;
3717 for (x=0; x < (ssize_t) roi->width; x++)
3718 {
3719 SetPixelBlue(image,*p++,q);
3720 SetPixelGreen(image,*p++,q);
3721 SetPixelRed(image,*p++,q);
3722 q+=GetPixelChannels(image);
3723 }
3724 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3725 break;
3726 }
3727 return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
3728 }
3729 if (LocaleCompare(map,"BGRA") == 0)
3730 {
3731 for (y=0; y < (ssize_t) roi->height; y++)
3732 {
3733 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
3734 if (q == (Quantum *) NULL)
3735 break;
3736 for (x=0; x < (ssize_t) roi->width; x++)
3737 {
3738 SetPixelBlue(image,*p++,q);
3739 SetPixelGreen(image,*p++,q);
3740 SetPixelRed(image,*p++,q);
3741 SetPixelAlpha(image,*p++,q);
3742 q+=GetPixelChannels(image);
3743 }
3744 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3745 break;
3746 }
3747 return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
3748 }
3749 if (LocaleCompare(map,"BGRP") == 0)
3750 {
3751 for (y=0; y < (ssize_t) roi->height; y++)
3752 {
3753 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
3754 if (q == (Quantum *) NULL)
3755 break;
3756 for (x=0; x < (ssize_t) roi->width; x++)
3757 {
3758 SetPixelBlue(image,*p++,q);
3759 SetPixelGreen(image,*p++,q);
3760 SetPixelRed(image,*p++,q);
3761 p++;
3762 q+=GetPixelChannels(image);
3763 }
3764 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3765 break;
3766 }
3767 return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
3768 }
3769 if (LocaleCompare(map,"I") == 0)
3770 {
3771 for (y=0; y < (ssize_t) roi->height; y++)
3772 {
3773 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
3774 if (q == (Quantum *) NULL)
3775 break;
3776 for (x=0; x < (ssize_t) roi->width; x++)
3777 {
3778 SetPixelGray(image,*p++,q);
3779 q+=GetPixelChannels(image);
3780 }
3781 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3782 break;
3783 }
3784 return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
3785 }
3786 if (LocaleCompare(map,"RGB") == 0)
3787 {
3788 for (y=0; y < (ssize_t) roi->height; y++)
3789 {
3790 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
3791 if (q == (Quantum *) NULL)
3792 break;
3793 for (x=0; x < (ssize_t) roi->width; x++)
3794 {
3795 SetPixelRed(image,*p++,q);
3796 SetPixelGreen(image,*p++,q);
3797 SetPixelBlue(image,*p++,q);
3798 q+=GetPixelChannels(image);
3799 }
3800 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3801 break;
3802 }
3803 return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
3804 }
3805 if (LocaleCompare(map,"RGBA") == 0)
3806 {
3807 for (y=0; y < (ssize_t) roi->height; y++)
3808 {
3809 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
3810 if (q == (Quantum *) NULL)
3811 break;
3812 for (x=0; x < (ssize_t) roi->width; x++)
3813 {
3814 SetPixelRed(image,*p++,q);
3815 SetPixelGreen(image,*p++,q);
3816 SetPixelBlue(image,*p++,q);
3817 SetPixelAlpha(image,*p++,q);
3818 q+=GetPixelChannels(image);
3819 }
3820 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3821 break;
3822 }
3823 return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
3824 }
3825 if (LocaleCompare(map,"RGBP") == 0)
3826 {
3827 for (y=0; y < (ssize_t) roi->height; y++)
3828 {
3829 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
3830 if (q == (Quantum *) NULL)
3831 break;
3832 for (x=0; x < (ssize_t) roi->width; x++)
3833 {
3834 SetPixelRed(image,*p++,q);
3835 SetPixelGreen(image,*p++,q);
3836 SetPixelBlue(image,*p++,q);
3837 p++;
3838 q+=GetPixelChannels(image);
3839 }
3840 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3841 break;
3842 }
3843 return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
3844 }
3845 length=strlen(map);
3846 for (y=0; y < (ssize_t) roi->height; y++)
3847 {
3848 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
3849 if (q == (Quantum *) NULL)
3850 break;
3851 for (x=0; x < (ssize_t) roi->width; x++)
3852 {
3853 register ssize_t
3854 i;
3855
3856 for (i=0; i < (ssize_t) length; i++)
3857 {
3858 switch (quantum_map[i])
3859 {
3860 case RedQuantum:
3861 case CyanQuantum:
3862 {
3863 SetPixelRed(image,*p,q);
3864 break;
3865 }
3866 case GreenQuantum:
3867 case MagentaQuantum:
3868 {
3869 SetPixelGreen(image,*p,q);
3870 break;
3871 }
3872 case BlueQuantum:
3873 case YellowQuantum:
3874 {
3875 SetPixelBlue(image,*p,q);
3876 break;
3877 }
3878 case AlphaQuantum:
3879 {
3880 SetPixelAlpha(image,*p,q);
3881 break;
3882 }
3883 case OpacityQuantum:
3884 {
3885 SetPixelAlpha(image,*p,q);
3886 break;
3887 }
3888 case BlackQuantum:
3889 {
3890 SetPixelBlack(image,*p,q);
3891 break;
3892 }
3893 case IndexQuantum:
3894 {
3895 SetPixelGray(image,*p,q);
3896 break;
3897 }
3898 default:
3899 break;
3900 }
3901 p++;
3902 }
3903 q+=GetPixelChannels(image);
3904 }
3905 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3906 break;
3907 }
3908 return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
3909 }
3910
ImportShortPixel(Image * image,const RectangleInfo * roi,const char * magick_restrict map,const QuantumType * quantum_map,const void * pixels,ExceptionInfo * exception)3911 static MagickBooleanType ImportShortPixel(Image *image,const RectangleInfo *roi,
3912 const char *magick_restrict map,const QuantumType *quantum_map,
3913 const void *pixels,ExceptionInfo *exception)
3914 {
3915 register const unsigned short
3916 *magick_restrict p;
3917
3918 register Quantum
3919 *magick_restrict q;
3920
3921 register ssize_t
3922 x;
3923
3924 size_t
3925 length;
3926
3927 ssize_t
3928 y;
3929
3930 p=(const unsigned short *) pixels;
3931 if (LocaleCompare(map,"BGR") == 0)
3932 {
3933 for (y=0; y < (ssize_t) roi->height; y++)
3934 {
3935 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
3936 if (q == (Quantum *) NULL)
3937 break;
3938 for (x=0; x < (ssize_t) roi->width; x++)
3939 {
3940 SetPixelBlue(image,ScaleShortToQuantum(*p++),q);
3941 SetPixelGreen(image,ScaleShortToQuantum(*p++),q);
3942 SetPixelRed(image,ScaleShortToQuantum(*p++),q);
3943 q+=GetPixelChannels(image);
3944 }
3945 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3946 break;
3947 }
3948 return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
3949 }
3950 if (LocaleCompare(map,"BGRA") == 0)
3951 {
3952 for (y=0; y < (ssize_t) roi->height; y++)
3953 {
3954 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
3955 if (q == (Quantum *) NULL)
3956 break;
3957 for (x=0; x < (ssize_t) roi->width; x++)
3958 {
3959 SetPixelBlue(image,ScaleShortToQuantum(*p++),q);
3960 SetPixelGreen(image,ScaleShortToQuantum(*p++),q);
3961 SetPixelRed(image,ScaleShortToQuantum(*p++),q);
3962 SetPixelAlpha(image,ScaleShortToQuantum(*p++),q);
3963 q+=GetPixelChannels(image);
3964 }
3965 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3966 break;
3967 }
3968 return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
3969 }
3970 if (LocaleCompare(map,"BGRP") == 0)
3971 {
3972 for (y=0; y < (ssize_t) roi->height; y++)
3973 {
3974 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
3975 if (q == (Quantum *) NULL)
3976 break;
3977 for (x=0; x < (ssize_t) roi->width; x++)
3978 {
3979 SetPixelBlue(image,ScaleShortToQuantum(*p++),q);
3980 SetPixelGreen(image,ScaleShortToQuantum(*p++),q);
3981 SetPixelRed(image,ScaleShortToQuantum(*p++),q);
3982 p++;
3983 q+=GetPixelChannels(image);
3984 }
3985 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3986 break;
3987 }
3988 return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
3989 }
3990 if (LocaleCompare(map,"I") == 0)
3991 {
3992 for (y=0; y < (ssize_t) roi->height; y++)
3993 {
3994 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
3995 if (q == (Quantum *) NULL)
3996 break;
3997 for (x=0; x < (ssize_t) roi->width; x++)
3998 {
3999 SetPixelGray(image,ScaleShortToQuantum(*p++),q);
4000 q+=GetPixelChannels(image);
4001 }
4002 if (SyncAuthenticPixels(image,exception) == MagickFalse)
4003 break;
4004 }
4005 return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
4006 }
4007 if (LocaleCompare(map,"RGB") == 0)
4008 {
4009 for (y=0; y < (ssize_t) roi->height; y++)
4010 {
4011 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
4012 if (q == (Quantum *) NULL)
4013 break;
4014 for (x=0; x < (ssize_t) roi->width; x++)
4015 {
4016 SetPixelRed(image,ScaleShortToQuantum(*p++),q);
4017 SetPixelGreen(image,ScaleShortToQuantum(*p++),q);
4018 SetPixelBlue(image,ScaleShortToQuantum(*p++),q);
4019 q+=GetPixelChannels(image);
4020 }
4021 if (SyncAuthenticPixels(image,exception) == MagickFalse)
4022 break;
4023 }
4024 return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
4025 }
4026 if (LocaleCompare(map,"RGBA") == 0)
4027 {
4028 for (y=0; y < (ssize_t) roi->height; y++)
4029 {
4030 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
4031 if (q == (Quantum *) NULL)
4032 break;
4033 for (x=0; x < (ssize_t) roi->width; x++)
4034 {
4035 SetPixelRed(image,ScaleShortToQuantum(*p++),q);
4036 SetPixelGreen(image,ScaleShortToQuantum(*p++),q);
4037 SetPixelBlue(image,ScaleShortToQuantum(*p++),q);
4038 SetPixelAlpha(image,ScaleShortToQuantum(*p++),q);
4039 q+=GetPixelChannels(image);
4040 }
4041 if (SyncAuthenticPixels(image,exception) == MagickFalse)
4042 break;
4043 }
4044 return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
4045 }
4046 if (LocaleCompare(map,"RGBP") == 0)
4047 {
4048 for (y=0; y < (ssize_t) roi->height; y++)
4049 {
4050 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
4051 if (q == (Quantum *) NULL)
4052 break;
4053 for (x=0; x < (ssize_t) roi->width; x++)
4054 {
4055 SetPixelRed(image,ScaleShortToQuantum(*p++),q);
4056 SetPixelGreen(image,ScaleShortToQuantum(*p++),q);
4057 SetPixelBlue(image,ScaleShortToQuantum(*p++),q);
4058 p++;
4059 q+=GetPixelChannels(image);
4060 }
4061 if (SyncAuthenticPixels(image,exception) == MagickFalse)
4062 break;
4063 }
4064 return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
4065 }
4066 length=strlen(map);
4067 for (y=0; y < (ssize_t) roi->height; y++)
4068 {
4069 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
4070 if (q == (Quantum *) NULL)
4071 break;
4072 for (x=0; x < (ssize_t) roi->width; x++)
4073 {
4074 register ssize_t
4075 i;
4076
4077 for (i=0; i < (ssize_t) length; i++)
4078 {
4079 switch (quantum_map[i])
4080 {
4081 case RedQuantum:
4082 case CyanQuantum:
4083 {
4084 SetPixelRed(image,ScaleShortToQuantum(*p),q);
4085 break;
4086 }
4087 case GreenQuantum:
4088 case MagentaQuantum:
4089 {
4090 SetPixelGreen(image,ScaleShortToQuantum(*p),q);
4091 break;
4092 }
4093 case BlueQuantum:
4094 case YellowQuantum:
4095 {
4096 SetPixelBlue(image,ScaleShortToQuantum(*p),q);
4097 break;
4098 }
4099 case AlphaQuantum:
4100 {
4101 SetPixelAlpha(image,ScaleShortToQuantum(*p),q);
4102 break;
4103 }
4104 case OpacityQuantum:
4105 {
4106 SetPixelAlpha(image,ScaleShortToQuantum(*p),q);
4107 break;
4108 }
4109 case BlackQuantum:
4110 {
4111 SetPixelBlack(image,ScaleShortToQuantum(*p),q);
4112 break;
4113 }
4114 case IndexQuantum:
4115 {
4116 SetPixelGray(image,ScaleShortToQuantum(*p),q);
4117 break;
4118 }
4119 default:
4120 break;
4121 }
4122 p++;
4123 }
4124 q+=GetPixelChannels(image);
4125 }
4126 if (SyncAuthenticPixels(image,exception) == MagickFalse)
4127 break;
4128 }
4129 return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
4130 }
4131
ImportImagePixels(Image * image,const ssize_t x,const ssize_t y,const size_t width,const size_t height,const char * map,const StorageType type,const void * pixels,ExceptionInfo * exception)4132 MagickExport MagickBooleanType ImportImagePixels(Image *image,const ssize_t x,
4133 const ssize_t y,const size_t width,const size_t height,const char *map,
4134 const StorageType type,const void *pixels,ExceptionInfo *exception)
4135 {
4136 MagickBooleanType
4137 status;
4138
4139 QuantumType
4140 *quantum_map;
4141
4142 RectangleInfo
4143 roi;
4144
4145 register ssize_t
4146 i;
4147
4148 size_t
4149 length;
4150
4151 /*
4152 Allocate image structure.
4153 */
4154 assert(image != (Image *) NULL);
4155 assert(image->signature == MagickCoreSignature);
4156 if (image->debug != MagickFalse)
4157 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
4158 length=strlen(map);
4159 quantum_map=(QuantumType *) AcquireQuantumMemory(length,sizeof(*quantum_map));
4160 if (quantum_map == (QuantumType *) NULL)
4161 ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
4162 image->filename);
4163 for (i=0; i < (ssize_t) length; i++)
4164 {
4165 switch (map[i])
4166 {
4167 case 'a':
4168 case 'A':
4169 {
4170 quantum_map[i]=AlphaQuantum;
4171 image->alpha_trait=BlendPixelTrait;
4172 break;
4173 }
4174 case 'B':
4175 case 'b':
4176 {
4177 quantum_map[i]=BlueQuantum;
4178 break;
4179 }
4180 case 'C':
4181 case 'c':
4182 {
4183 quantum_map[i]=CyanQuantum;
4184 (void) SetImageColorspace(image,CMYKColorspace,exception);
4185 break;
4186 }
4187 case 'g':
4188 case 'G':
4189 {
4190 quantum_map[i]=GreenQuantum;
4191 break;
4192 }
4193 case 'K':
4194 case 'k':
4195 {
4196 quantum_map[i]=BlackQuantum;
4197 (void) SetImageColorspace(image,CMYKColorspace,exception);
4198 break;
4199 }
4200 case 'I':
4201 case 'i':
4202 {
4203 quantum_map[i]=IndexQuantum;
4204 (void) SetImageColorspace(image,GRAYColorspace,exception);
4205 break;
4206 }
4207 case 'm':
4208 case 'M':
4209 {
4210 quantum_map[i]=MagentaQuantum;
4211 (void) SetImageColorspace(image,CMYKColorspace,exception);
4212 break;
4213 }
4214 case 'O':
4215 case 'o':
4216 {
4217 quantum_map[i]=OpacityQuantum;
4218 image->alpha_trait=BlendPixelTrait;
4219 break;
4220 }
4221 case 'P':
4222 case 'p':
4223 {
4224 quantum_map[i]=UndefinedQuantum;
4225 break;
4226 }
4227 case 'R':
4228 case 'r':
4229 {
4230 quantum_map[i]=RedQuantum;
4231 break;
4232 }
4233 case 'Y':
4234 case 'y':
4235 {
4236 quantum_map[i]=YellowQuantum;
4237 (void) SetImageColorspace(image,CMYKColorspace,exception);
4238 break;
4239 }
4240 default:
4241 {
4242 quantum_map=(QuantumType *) RelinquishMagickMemory(quantum_map);
4243 (void) ThrowMagickException(exception,GetMagickModule(),OptionError,
4244 "UnrecognizedPixelMap","`%s'",map);
4245 return(MagickFalse);
4246 }
4247 }
4248 }
4249 if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
4250 return(MagickFalse);
4251 /*
4252 Transfer the pixels from the pixel data to the image.
4253 */
4254 roi.width=width;
4255 roi.height=height;
4256 roi.x=x;
4257 roi.y=y;
4258 switch (type)
4259 {
4260 case CharPixel:
4261 {
4262 status=ImportCharPixel(image,&roi,map,quantum_map,pixels,exception);
4263 break;
4264 }
4265 case DoublePixel:
4266 {
4267 status=ImportDoublePixel(image,&roi,map,quantum_map,pixels,exception);
4268 break;
4269 }
4270 case FloatPixel:
4271 {
4272 status=ImportFloatPixel(image,&roi,map,quantum_map,pixels,exception);
4273 break;
4274 }
4275 case LongPixel:
4276 {
4277 status=ImportLongPixel(image,&roi,map,quantum_map,pixels,exception);
4278 break;
4279 }
4280 case LongLongPixel:
4281 {
4282 status=ImportLongLongPixel(image,&roi,map,quantum_map,pixels,exception);
4283 break;
4284 }
4285 case QuantumPixel:
4286 {
4287 status=ImportQuantumPixel(image,&roi,map,quantum_map,pixels,exception);
4288 break;
4289 }
4290 case ShortPixel:
4291 {
4292 status=ImportShortPixel(image,&roi,map,quantum_map,pixels,exception);
4293 break;
4294 }
4295 default:
4296 {
4297 (void) ThrowMagickException(exception,GetMagickModule(),OptionError,
4298 "UnrecognizedStorageType","`%d'",type);
4299 status=MagickFalse;
4300 }
4301 }
4302 quantum_map=(QuantumType *) RelinquishMagickMemory(quantum_map);
4303 return(status);
4304 }
4305
4306 /*
4307 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4308 % %
4309 % %
4310 % %
4311 + 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 %
4312 % %
4313 % %
4314 % %
4315 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4316 %
4317 % InitializePixelChannelMap() defines the standard pixel component map.
4318 %
4319 % The format of the InitializePixelChannelMap() method is:
4320 %
4321 % void InitializePixelChannelMap(Image *image)
4322 %
4323 % A description of each parameter follows:
4324 %
4325 % o image: the image.
4326 %
4327 */
InitializePixelChannelMap(Image * image)4328 MagickExport void InitializePixelChannelMap(Image *image)
4329 {
4330 PixelTrait
4331 trait;
4332
4333 register ssize_t
4334 i;
4335
4336 ssize_t
4337 n;
4338
4339 assert(image != (Image *) NULL);
4340 assert(image->signature == MagickCoreSignature);
4341 (void) memset(image->channel_map,0,MaxPixelChannels*
4342 sizeof(*image->channel_map));
4343 trait=UpdatePixelTrait;
4344 if (image->alpha_trait != UndefinedPixelTrait)
4345 trait=(PixelTrait) (trait | BlendPixelTrait);
4346 n=0;
4347 if ((image->colorspace == LinearGRAYColorspace) ||
4348 (image->colorspace == GRAYColorspace))
4349 {
4350 SetPixelChannelAttributes(image,BluePixelChannel,trait,n);
4351 SetPixelChannelAttributes(image,GreenPixelChannel,trait,n);
4352 SetPixelChannelAttributes(image,RedPixelChannel,trait,n++);
4353 }
4354 else
4355 {
4356 SetPixelChannelAttributes(image,RedPixelChannel,trait,n++);
4357 SetPixelChannelAttributes(image,GreenPixelChannel,trait,n++);
4358 SetPixelChannelAttributes(image,BluePixelChannel,trait,n++);
4359 }
4360 if (image->colorspace == CMYKColorspace)
4361 SetPixelChannelAttributes(image,BlackPixelChannel,trait,n++);
4362 for (i=0; i < (ssize_t) image->number_meta_channels; i++)
4363 {
4364 SetPixelChannelAttributes(image,(PixelChannel) n,UpdatePixelTrait,n);
4365 n++;
4366 }
4367 if (image->alpha_trait != UndefinedPixelTrait)
4368 SetPixelChannelAttributes(image,AlphaPixelChannel,CopyPixelTrait,n++);
4369 if (image->storage_class == PseudoClass)
4370 SetPixelChannelAttributes(image,IndexPixelChannel,CopyPixelTrait,n++);
4371 if ((image->channels & ReadMaskChannel) != 0)
4372 SetPixelChannelAttributes(image,ReadMaskPixelChannel,CopyPixelTrait,n++);
4373 if ((image->channels & WriteMaskChannel) != 0)
4374 SetPixelChannelAttributes(image,WriteMaskPixelChannel,CopyPixelTrait,n++);
4375 if ((image->channels & CompositeMaskChannel) != 0)
4376 SetPixelChannelAttributes(image,CompositeMaskPixelChannel,CopyPixelTrait,
4377 n++);
4378 image->number_channels=(size_t) n;
4379 (void) SetPixelChannelMask(image,image->channel_mask);
4380 }
4381
4382 /*
4383 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4384 % %
4385 % %
4386 % %
4387 % I n t e r p o l a t e P i x e l C h a n n e l %
4388 % %
4389 % %
4390 % %
4391 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4392 %
4393 % InterpolatePixelChannel() applies a pixel interpolation method between a
4394 % floating point coordinate and the pixels surrounding that coordinate. No
4395 % pixel area resampling, or scaling of the result is performed.
4396 %
4397 % Interpolation is restricted to just the specified channel.
4398 %
4399 % The format of the InterpolatePixelChannel method is:
4400 %
4401 % MagickBooleanType InterpolatePixelChannel(const Image *image,
4402 % const CacheView *image_view,const PixelChannel channel,
4403 % const PixelInterpolateMethod method,const double x,const double y,
4404 % double *pixel,ExceptionInfo *exception)
4405 %
4406 % A description of each parameter follows:
4407 %
4408 % o image: the image.
4409 %
4410 % o image_view: the image view.
4411 %
4412 % o channel: the pixel channel to interpolate.
4413 %
4414 % o method: the pixel color interpolation method.
4415 %
4416 % o x,y: A double representing the current (x,y) position of the pixel.
4417 %
4418 % o pixel: return the interpolated pixel here.
4419 %
4420 % o exception: return any errors or warnings in this structure.
4421 %
4422 */
4423
CatromWeights(const double x,double (* weights)[4])4424 static inline void CatromWeights(const double x,double (*weights)[4])
4425 {
4426 double
4427 alpha,
4428 beta,
4429 gamma;
4430
4431 /*
4432 Nicolas Robidoux' 10 flops (4* + 5- + 1+) refactoring of the computation
4433 of the standard four 1D Catmull-Rom weights. The sampling location is
4434 assumed between the second and third input pixel locations, and x is the
4435 position relative to the second input pixel location. Formulas originally
4436 derived for the VIPS (Virtual Image Processing System) library.
4437 */
4438 alpha=(double) 1.0-x;
4439 beta=(double) (-0.5)*x*alpha;
4440 (*weights)[0]=alpha*beta;
4441 (*weights)[3]=x*beta;
4442 /*
4443 The following computation of the inner weights from the outer ones work
4444 for all Keys cubics.
4445 */
4446 gamma=(*weights)[3]-(*weights)[0];
4447 (*weights)[1]=alpha-(*weights)[0]+gamma;
4448 (*weights)[2]=x-(*weights)[3]-gamma;
4449 }
4450
SplineWeights(const double x,double (* weights)[4])4451 static inline void SplineWeights(const double x,double (*weights)[4])
4452 {
4453 double
4454 alpha,
4455 beta;
4456
4457 /*
4458 Nicolas Robidoux' 12 flops (6* + 5- + 1+) refactoring of the computation
4459 of the standard four 1D cubic B-spline smoothing weights. The sampling
4460 location is assumed between the second and third input pixel locations,
4461 and x is the position relative to the second input pixel location.
4462 */
4463 alpha=(double) 1.0-x;
4464 (*weights)[3]=(double) (1.0/6.0)*x*x*x;
4465 (*weights)[0]=(double) (1.0/6.0)*alpha*alpha*alpha;
4466 beta=(*weights)[3]-(*weights)[0];
4467 (*weights)[1]=alpha-(*weights)[0]+beta;
4468 (*weights)[2]=x-(*weights)[3]-beta;
4469 }
4470
MeshInterpolate(const PointInfo * delta,const double p,const double x,const double y)4471 static inline double MeshInterpolate(const PointInfo *delta,const double p,
4472 const double x,const double y)
4473 {
4474 return(delta->x*x+delta->y*y+(1.0-delta->x-delta->y)*p);
4475 }
4476
4477 /*
4478 static inline ssize_t NearestNeighbor(const double x)
4479 {
4480 if (x >= 0.0)
4481 return((ssize_t) (x+0.5));
4482 return((ssize_t) (x-0.5));
4483 }
4484 */
4485
InterpolatePixelChannel(const Image * image,const CacheView_ * image_view,const PixelChannel channel,const PixelInterpolateMethod method,const double x,const double y,double * pixel,ExceptionInfo * exception)4486 MagickExport MagickBooleanType InterpolatePixelChannel(const Image *image,
4487 const CacheView_ *image_view,const PixelChannel channel,
4488 const PixelInterpolateMethod method,const double x,const double y,
4489 double *pixel,ExceptionInfo *exception)
4490 {
4491 double
4492 alpha[16],
4493 gamma,
4494 pixels[16];
4495
4496 MagickBooleanType
4497 status;
4498
4499 PixelInterpolateMethod
4500 interpolate;
4501
4502 PixelTrait
4503 traits;
4504
4505 register const Quantum
4506 *p;
4507
4508 register ssize_t
4509 i;
4510
4511 ssize_t
4512 x_offset,
4513 y_offset;
4514
4515 assert(image != (Image *) NULL);
4516 assert(image->signature == MagickCoreSignature);
4517 assert(image_view != (CacheView *) NULL);
4518 status=MagickTrue;
4519 *pixel=0.0;
4520 traits=GetPixelChannelTraits(image,channel);
4521 x_offset=(ssize_t) floor(x);
4522 y_offset=(ssize_t) floor(y);
4523 interpolate=method;
4524 if (interpolate == UndefinedInterpolatePixel)
4525 interpolate=image->interpolate;
4526 switch (interpolate)
4527 {
4528 case AverageInterpolatePixel: /* nearest 4 neighbours */
4529 case Average9InterpolatePixel: /* nearest 9 neighbours */
4530 case Average16InterpolatePixel: /* nearest 16 neighbours */
4531 {
4532 ssize_t
4533 count;
4534
4535 count=2; /* size of the area to average - default nearest 4 */
4536 if (interpolate == Average9InterpolatePixel)
4537 {
4538 count=3;
4539 x_offset=(ssize_t) (floor(x+0.5)-1);
4540 y_offset=(ssize_t) (floor(y+0.5)-1);
4541 }
4542 else
4543 if (interpolate == Average16InterpolatePixel)
4544 {
4545 count=4;
4546 x_offset--;
4547 y_offset--;
4548 }
4549 p=GetCacheViewVirtualPixels(image_view,x_offset,y_offset,(size_t) count,
4550 (size_t) count,exception);
4551 if (p == (const Quantum *) NULL)
4552 {
4553 status=MagickFalse;
4554 break;
4555 }
4556 count*=count; /* Number of pixels to average */
4557 if ((traits & BlendPixelTrait) == 0)
4558 for (i=0; i < (ssize_t) count; i++)
4559 {
4560 alpha[i]=1.0;
4561 pixels[i]=(double) p[i*GetPixelChannels(image)+channel];
4562 }
4563 else
4564 for (i=0; i < (ssize_t) count; i++)
4565 {
4566 alpha[i]=QuantumScale*GetPixelAlpha(image,p+i*
4567 GetPixelChannels(image));
4568 pixels[i]=alpha[i]*p[i*GetPixelChannels(image)+channel];
4569 }
4570 for (i=0; i < (ssize_t) count; i++)
4571 {
4572 gamma=PerceptibleReciprocal(alpha[i])/count;
4573 *pixel+=gamma*pixels[i];
4574 }
4575 break;
4576 }
4577 case BilinearInterpolatePixel:
4578 default:
4579 {
4580 PointInfo
4581 delta,
4582 epsilon;
4583
4584 p=GetCacheViewVirtualPixels(image_view,x_offset,y_offset,2,2,exception);
4585 if (p == (const Quantum *) NULL)
4586 {
4587 status=MagickFalse;
4588 break;
4589 }
4590 if ((traits & BlendPixelTrait) == 0)
4591 for (i=0; i < 4; i++)
4592 {
4593 alpha[i]=1.0;
4594 pixels[i]=(double) p[i*GetPixelChannels(image)+channel];
4595 }
4596 else
4597 for (i=0; i < 4; i++)
4598 {
4599 alpha[i]=QuantumScale*GetPixelAlpha(image,p+i*
4600 GetPixelChannels(image));
4601 pixels[i]=alpha[i]*p[i*GetPixelChannels(image)+channel];
4602 }
4603 delta.x=x-x_offset;
4604 delta.y=y-y_offset;
4605 epsilon.x=1.0-delta.x;
4606 epsilon.y=1.0-delta.y;
4607 gamma=((epsilon.y*(epsilon.x*alpha[0]+delta.x*alpha[1])+delta.y*
4608 (epsilon.x*alpha[2]+delta.x*alpha[3])));
4609 gamma=PerceptibleReciprocal(gamma);
4610 *pixel=gamma*(epsilon.y*(epsilon.x*pixels[0]+delta.x*pixels[1])+delta.y*
4611 (epsilon.x*pixels[2]+delta.x*pixels[3]));
4612 break;
4613 }
4614 case BlendInterpolatePixel:
4615 {
4616 p=GetCacheViewVirtualPixels(image_view,x_offset,y_offset,2,2,exception);
4617 if (p == (const Quantum *) NULL)
4618 {
4619 status=MagickFalse;
4620 break;
4621 }
4622 if ((traits & BlendPixelTrait) == 0)
4623 for (i=0; i < 4; i++)
4624 {
4625 alpha[i]=1.0;
4626 pixels[i]=(MagickRealType) p[i*GetPixelChannels(image)+channel];
4627 }
4628 else
4629 for (i=0; i < 4; i++)
4630 {
4631 alpha[i]=QuantumScale*GetPixelAlpha(image,p+i*
4632 GetPixelChannels(image));
4633 pixels[i]=alpha[i]*p[i*GetPixelChannels(image)+channel];
4634 }
4635 gamma=1.0; /* number of pixels blended together (its variable) */
4636 for (i=0; i <= 1L; i++) {
4637 if ((y-y_offset) >= 0.75)
4638 {
4639 alpha[i]=alpha[i+2]; /* take right pixels */
4640 pixels[i]=pixels[i+2];
4641 }
4642 else
4643 if ((y-y_offset) > 0.25)
4644 {
4645 gamma=2.0; /* blend both pixels in row */
4646 alpha[i]+=alpha[i+2]; /* add up alpha weights */
4647 pixels[i]+=pixels[i+2];
4648 }
4649 }
4650 if ((x-x_offset) >= 0.75)
4651 {
4652 alpha[0]=alpha[1]; /* take bottom row blend */
4653 pixels[0]=pixels[1];
4654 }
4655 else
4656 if ((x-x_offset) > 0.25)
4657 {
4658 gamma*=2.0; /* blend both rows */
4659 alpha[0]+=alpha[1]; /* add up alpha weights */
4660 pixels[0]+=pixels[1];
4661 }
4662 if (channel != AlphaPixelChannel)
4663 gamma=PerceptibleReciprocal(alpha[0]); /* (color) 1/alpha_weights */
4664 else
4665 gamma=PerceptibleReciprocal(gamma); /* (alpha) 1/number_of_pixels */
4666 *pixel=gamma*pixels[0];
4667 break;
4668 }
4669 case CatromInterpolatePixel:
4670 {
4671 double
4672 cx[4],
4673 cy[4];
4674
4675 p=GetCacheViewVirtualPixels(image_view,x_offset-1,y_offset-1,4,4,
4676 exception);
4677 if (p == (const Quantum *) NULL)
4678 {
4679 status=MagickFalse;
4680 break;
4681 }
4682 if ((traits & BlendPixelTrait) == 0)
4683 for (i=0; i < 16; i++)
4684 {
4685 alpha[i]=1.0;
4686 pixels[i]=(double) p[i*GetPixelChannels(image)+channel];
4687 }
4688 else
4689 for (i=0; i < 16; i++)
4690 {
4691 alpha[i]=QuantumScale*GetPixelAlpha(image,p+i*
4692 GetPixelChannels(image));
4693 pixels[i]=alpha[i]*p[i*GetPixelChannels(image)+channel];
4694 }
4695 CatromWeights((double) (x-x_offset),&cx);
4696 CatromWeights((double) (y-y_offset),&cy);
4697 gamma=(channel == AlphaPixelChannel ? (double) 1.0 :
4698 PerceptibleReciprocal(cy[0]*(cx[0]*alpha[0]+cx[1]*alpha[1]+cx[2]*
4699 alpha[2]+cx[3]*alpha[3])+cy[1]*(cx[0]*alpha[4]+cx[1]*alpha[5]+cx[2]*
4700 alpha[6]+cx[3]*alpha[7])+cy[2]*(cx[0]*alpha[8]+cx[1]*alpha[9]+cx[2]*
4701 alpha[10]+cx[3]*alpha[11])+cy[3]*(cx[0]*alpha[12]+cx[1]*alpha[13]+
4702 cx[2]*alpha[14]+cx[3]*alpha[15])));
4703 *pixel=gamma*(cy[0]*(cx[0]*pixels[0]+cx[1]*pixels[1]+cx[2]*pixels[2]+
4704 cx[3]*pixels[3])+cy[1]*(cx[0]*pixels[4]+cx[1]*pixels[5]+cx[2]*
4705 pixels[6]+cx[3]*pixels[7])+cy[2]*(cx[0]*pixels[8]+cx[1]*pixels[9]+
4706 cx[2]*pixels[10]+cx[3]*pixels[11])+cy[3]*(cx[0]*pixels[12]+cx[1]*
4707 pixels[13]+cx[2]*pixels[14]+cx[3]*pixels[15]));
4708 break;
4709 }
4710 case IntegerInterpolatePixel:
4711 {
4712 p=GetCacheViewVirtualPixels(image_view,x_offset,y_offset,1,1,exception);
4713 if (p == (const Quantum *) NULL)
4714 {
4715 status=MagickFalse;
4716 break;
4717 }
4718 *pixel=(double) GetPixelChannel(image,channel,p);
4719 break;
4720 }
4721 case NearestInterpolatePixel:
4722 {
4723 x_offset=(ssize_t) floor(x+0.5);
4724 y_offset=(ssize_t) floor(y+0.5);
4725 p=GetCacheViewVirtualPixels(image_view,x_offset,y_offset,1,1,exception);
4726 if (p == (const Quantum *) NULL)
4727 {
4728 status=MagickFalse;
4729 break;
4730 }
4731 *pixel=(double) GetPixelChannel(image,channel,p);
4732 break;
4733 }
4734 case MeshInterpolatePixel:
4735 {
4736 PointInfo
4737 delta,
4738 luminance;
4739
4740 p=GetCacheViewVirtualPixels(image_view,x_offset,y_offset,2,2,exception);
4741 if (p == (const Quantum *) NULL)
4742 {
4743 status=MagickFalse;
4744 break;
4745 }
4746 if ((traits & BlendPixelTrait) == 0)
4747 for (i=0; i < 4; i++)
4748 {
4749 alpha[i]=1.0;
4750 pixels[i]=(double) p[i*GetPixelChannels(image)+channel];
4751 }
4752 else
4753 for (i=0; i < 4; i++)
4754 {
4755 alpha[i]=QuantumScale*GetPixelAlpha(image,p+i*
4756 GetPixelChannels(image));
4757 pixels[i]=alpha[i]*p[i*GetPixelChannels(image)+channel];
4758 }
4759 delta.x=x-x_offset;
4760 delta.y=y-y_offset;
4761 luminance.x=GetPixelLuma(image,p)-(double)
4762 GetPixelLuma(image,p+3*GetPixelChannels(image));
4763 luminance.y=GetPixelLuma(image,p+GetPixelChannels(image))-(double)
4764 GetPixelLuma(image,p+2*GetPixelChannels(image));
4765 if (fabs(luminance.x) < fabs(luminance.y))
4766 {
4767 /*
4768 Diagonal 0-3 NW-SE.
4769 */
4770 if (delta.x <= delta.y)
4771 {
4772 /*
4773 Bottom-left triangle (pixel: 2, diagonal: 0-3).
4774 */
4775 delta.y=1.0-delta.y;
4776 gamma=MeshInterpolate(&delta,alpha[2],alpha[3],alpha[0]);
4777 gamma=PerceptibleReciprocal(gamma);
4778 *pixel=gamma*MeshInterpolate(&delta,pixels[2],pixels[3],
4779 pixels[0]);
4780 }
4781 else
4782 {
4783 /*
4784 Top-right triangle (pixel: 1, diagonal: 0-3).
4785 */
4786 delta.x=1.0-delta.x;
4787 gamma=MeshInterpolate(&delta,alpha[1],alpha[0],alpha[3]);
4788 gamma=PerceptibleReciprocal(gamma);
4789 *pixel=gamma*MeshInterpolate(&delta,pixels[1],pixels[0],
4790 pixels[3]);
4791 }
4792 }
4793 else
4794 {
4795 /*
4796 Diagonal 1-2 NE-SW.
4797 */
4798 if (delta.x <= (1.0-delta.y))
4799 {
4800 /*
4801 Top-left triangle (pixel: 0, diagonal: 1-2).
4802 */
4803 gamma=MeshInterpolate(&delta,alpha[0],alpha[1],alpha[2]);
4804 gamma=PerceptibleReciprocal(gamma);
4805 *pixel=gamma*MeshInterpolate(&delta,pixels[0],pixels[1],
4806 pixels[2]);
4807 }
4808 else
4809 {
4810 /*
4811 Bottom-right triangle (pixel: 3, diagonal: 1-2).
4812 */
4813 delta.x=1.0-delta.x;
4814 delta.y=1.0-delta.y;
4815 gamma=MeshInterpolate(&delta,alpha[3],alpha[2],alpha[1]);
4816 gamma=PerceptibleReciprocal(gamma);
4817 *pixel=gamma*MeshInterpolate(&delta,pixels[3],pixels[2],
4818 pixels[1]);
4819 }
4820 }
4821 break;
4822 }
4823 case SplineInterpolatePixel:
4824 {
4825 double
4826 cx[4],
4827 cy[4];
4828
4829 p=GetCacheViewVirtualPixels(image_view,x_offset-1,y_offset-1,4,4,
4830 exception);
4831 if (p == (const Quantum *) NULL)
4832 {
4833 status=MagickFalse;
4834 break;
4835 }
4836 if ((traits & BlendPixelTrait) == 0)
4837 for (i=0; i < 16; i++)
4838 {
4839 alpha[i]=1.0;
4840 pixels[i]=(double) p[i*GetPixelChannels(image)+channel];
4841 }
4842 else
4843 for (i=0; i < 16; i++)
4844 {
4845 alpha[i]=QuantumScale*GetPixelAlpha(image,p+i*
4846 GetPixelChannels(image));
4847 pixels[i]=alpha[i]*p[i*GetPixelChannels(image)+channel];
4848 }
4849 SplineWeights((double) (x-x_offset),&cx);
4850 SplineWeights((double) (y-y_offset),&cy);
4851 gamma=(channel == AlphaPixelChannel ? (double) 1.0 :
4852 PerceptibleReciprocal(cy[0]*(cx[0]*alpha[0]+cx[1]*alpha[1]+cx[2]*
4853 alpha[2]+cx[3]*alpha[3])+cy[1]*(cx[0]*alpha[4]+cx[1]*alpha[5]+cx[2]*
4854 alpha[6]+cx[3]*alpha[7])+cy[2]*(cx[0]*alpha[8]+cx[1]*alpha[9]+cx[2]*
4855 alpha[10]+cx[3]*alpha[11])+cy[3]*(cx[0]*alpha[12]+cx[1]*alpha[13]+
4856 cx[2]*alpha[14]+cx[3]*alpha[15])));
4857 *pixel=gamma*(cy[0]*(cx[0]*pixels[0]+cx[1]*pixels[1]+cx[2]*pixels[2]+
4858 cx[3]*pixels[3])+cy[1]*(cx[0]*pixels[4]+cx[1]*pixels[5]+cx[2]*
4859 pixels[6]+cx[3]*pixels[7])+cy[2]*(cx[0]*pixels[8]+cx[1]*pixels[9]+
4860 cx[2]*pixels[10]+cx[3]*pixels[11])+cy[3]*(cx[0]*pixels[12]+cx[1]*
4861 pixels[13]+cx[2]*pixels[14]+cx[3]*pixels[15]));
4862 break;
4863 }
4864 }
4865 return(status);
4866 }
4867
4868 /*
4869 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4870 % %
4871 % %
4872 % %
4873 % I n t e r p o l a t e P i x e l C h a n n e l s %
4874 % %
4875 % %
4876 % %
4877 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4878 %
4879 % InterpolatePixelChannels() applies a pixel interpolation method between a
4880 % floating point coordinate and the pixels surrounding that coordinate. No
4881 % pixel area resampling, or scaling of the result is performed.
4882 %
4883 % Interpolation is restricted to just the current channel setting of the
4884 % destination image into which the color is to be stored
4885 %
4886 % The format of the InterpolatePixelChannels method is:
4887 %
4888 % MagickBooleanType InterpolatePixelChannels(const Image *source,
4889 % const CacheView *source_view,const Image *destination,
4890 % const PixelInterpolateMethod method,const double x,const double y,
4891 % Quantum *pixel,ExceptionInfo *exception)
4892 %
4893 % A description of each parameter follows:
4894 %
4895 % o source: the source.
4896 %
4897 % o source_view: the source view.
4898 %
4899 % o destination: the destination image, for the interpolated color
4900 %
4901 % o method: the pixel color interpolation method.
4902 %
4903 % o x,y: A double representing the current (x,y) position of the pixel.
4904 %
4905 % o pixel: return the interpolated pixel here.
4906 %
4907 % o exception: return any errors or warnings in this structure.
4908 %
4909 */
InterpolatePixelChannels(const Image * source,const CacheView_ * source_view,const Image * destination,const PixelInterpolateMethod method,const double x,const double y,Quantum * pixel,ExceptionInfo * exception)4910 MagickExport MagickBooleanType InterpolatePixelChannels(const Image *source,
4911 const CacheView_ *source_view,const Image *destination,
4912 const PixelInterpolateMethod method,const double x,const double y,
4913 Quantum *pixel,ExceptionInfo *exception)
4914 {
4915 MagickBooleanType
4916 status;
4917
4918 double
4919 alpha[16],
4920 gamma,
4921 pixels[16];
4922
4923 register const Quantum
4924 *p;
4925
4926 register ssize_t
4927 i;
4928
4929 ssize_t
4930 x_offset,
4931 y_offset;
4932
4933 PixelInterpolateMethod
4934 interpolate;
4935
4936 assert(source != (Image *) NULL);
4937 assert(source->signature == MagickCoreSignature);
4938 assert(source_view != (CacheView *) NULL);
4939 status=MagickTrue;
4940 x_offset=(ssize_t) floor(x);
4941 y_offset=(ssize_t) floor(y);
4942 interpolate=method;
4943 if (interpolate == UndefinedInterpolatePixel)
4944 interpolate=source->interpolate;
4945 switch (interpolate)
4946 {
4947 case AverageInterpolatePixel: /* nearest 4 neighbours */
4948 case Average9InterpolatePixel: /* nearest 9 neighbours */
4949 case Average16InterpolatePixel: /* nearest 16 neighbours */
4950 {
4951 ssize_t
4952 count;
4953
4954 count=2; /* size of the area to average - default nearest 4 */
4955 if (interpolate == Average9InterpolatePixel)
4956 {
4957 count=3;
4958 x_offset=(ssize_t) (floor(x+0.5)-1);
4959 y_offset=(ssize_t) (floor(y+0.5)-1);
4960 }
4961 else
4962 if (interpolate == Average16InterpolatePixel)
4963 {
4964 count=4;
4965 x_offset--;
4966 y_offset--;
4967 }
4968 p=GetCacheViewVirtualPixels(source_view,x_offset,y_offset,(size_t) count,
4969 (size_t) count,exception);
4970 if (p == (const Quantum *) NULL)
4971 {
4972 status=MagickFalse;
4973 break;
4974 }
4975 count*=count; /* Number of pixels to average */
4976 for (i=0; i < (ssize_t) GetPixelChannels(source); i++)
4977 {
4978 double
4979 sum;
4980
4981 register ssize_t
4982 j;
4983
4984 PixelChannel channel = GetPixelChannelChannel(source,i);
4985 PixelTrait traits = GetPixelChannelTraits(source,channel);
4986 PixelTrait destination_traits=GetPixelChannelTraits(destination,
4987 channel);
4988 if ((traits == UndefinedPixelTrait) ||
4989 (destination_traits == UndefinedPixelTrait))
4990 continue;
4991 for (j=0; j < (ssize_t) count; j++)
4992 pixels[j]=(double) p[j*GetPixelChannels(source)+i];
4993 sum=0.0;
4994 if ((traits & BlendPixelTrait) == 0)
4995 {
4996 for (j=0; j < (ssize_t) count; j++)
4997 sum+=pixels[j];
4998 sum/=count;
4999 SetPixelChannel(destination,channel,ClampToQuantum(sum),pixel);
5000 continue;
5001 }
5002 for (j=0; j < (ssize_t) count; j++)
5003 {
5004 alpha[j]=QuantumScale*GetPixelAlpha(source,p+j*
5005 GetPixelChannels(source));
5006 pixels[j]*=alpha[j];
5007 gamma=PerceptibleReciprocal(alpha[j]);
5008 sum+=gamma*pixels[j];
5009 }
5010 sum/=count;
5011 SetPixelChannel(destination,channel,ClampToQuantum(sum),pixel);
5012 }
5013 break;
5014 }
5015 case BilinearInterpolatePixel:
5016 default:
5017 {
5018 p=GetCacheViewVirtualPixels(source_view,x_offset,y_offset,2,2,exception);
5019 if (p == (const Quantum *) NULL)
5020 {
5021 status=MagickFalse;
5022 break;
5023 }
5024 for (i=0; i < (ssize_t) GetPixelChannels(source); i++)
5025 {
5026 PointInfo
5027 delta,
5028 epsilon;
5029
5030 PixelChannel channel = GetPixelChannelChannel(source,i);
5031 PixelTrait traits = GetPixelChannelTraits(source,channel);
5032 PixelTrait destination_traits=GetPixelChannelTraits(destination,
5033 channel);
5034 if ((traits == UndefinedPixelTrait) ||
5035 (destination_traits == UndefinedPixelTrait))
5036 continue;
5037 delta.x=x-x_offset;
5038 delta.y=y-y_offset;
5039 epsilon.x=1.0-delta.x;
5040 epsilon.y=1.0-delta.y;
5041 pixels[0]=(double) p[i];
5042 pixels[1]=(double) p[GetPixelChannels(source)+i];
5043 pixels[2]=(double) p[2*GetPixelChannels(source)+i];
5044 pixels[3]=(double) p[3*GetPixelChannels(source)+i];
5045 if ((traits & BlendPixelTrait) == 0)
5046 {
5047 gamma=((epsilon.y*(epsilon.x+delta.x)+delta.y*(epsilon.x+delta.x)));
5048 gamma=PerceptibleReciprocal(gamma);
5049 SetPixelChannel(destination,channel,ClampToQuantum(gamma*(epsilon.y*
5050 (epsilon.x*pixels[0]+delta.x*pixels[1])+delta.y*(epsilon.x*
5051 pixels[2]+delta.x*pixels[3]))),pixel);
5052 continue;
5053 }
5054 alpha[0]=QuantumScale*GetPixelAlpha(source,p);
5055 alpha[1]=QuantumScale*GetPixelAlpha(source,p+GetPixelChannels(source));
5056 alpha[2]=QuantumScale*GetPixelAlpha(source,p+2*
5057 GetPixelChannels(source));
5058 alpha[3]=QuantumScale*GetPixelAlpha(source,p+3*
5059 GetPixelChannels(source));
5060 pixels[0]*=alpha[0];
5061 pixels[1]*=alpha[1];
5062 pixels[2]*=alpha[2];
5063 pixels[3]*=alpha[3];
5064 gamma=((epsilon.y*(epsilon.x*alpha[0]+delta.x*alpha[1])+delta.y*
5065 (epsilon.x*alpha[2]+delta.x*alpha[3])));
5066 gamma=PerceptibleReciprocal(gamma);
5067 SetPixelChannel(destination,channel,ClampToQuantum(gamma*(epsilon.y*
5068 (epsilon.x*pixels[0]+delta.x*pixels[1])+delta.y*(epsilon.x*pixels[2]+
5069 delta.x*pixels[3]))),pixel);
5070 }
5071 break;
5072 }
5073 case BlendInterpolatePixel:
5074 {
5075 p=GetCacheViewVirtualPixels(source_view,x_offset,y_offset,2,2,exception);
5076 if (p == (const Quantum *) NULL)
5077 {
5078 status=MagickFalse;
5079 break;
5080 }
5081 for (i=0; i < (ssize_t) GetPixelChannels(source); i++)
5082 {
5083 register ssize_t
5084 j;
5085
5086 PixelChannel channel = GetPixelChannelChannel(source,i);
5087 PixelTrait traits = GetPixelChannelTraits(source,channel);
5088 PixelTrait destination_traits=GetPixelChannelTraits(destination,
5089 channel);
5090 if ((traits == UndefinedPixelTrait) ||
5091 (destination_traits == UndefinedPixelTrait))
5092 continue;
5093 if (source->alpha_trait != BlendPixelTrait)
5094 for (j=0; j < 4; j++)
5095 {
5096 alpha[j]=1.0;
5097 pixels[j]=(double) p[j*GetPixelChannels(source)+i];
5098 }
5099 else
5100 for (j=0; j < 4; j++)
5101 {
5102 alpha[j]=QuantumScale*GetPixelAlpha(source,p+j*
5103 GetPixelChannels(source));
5104 pixels[j]=(double) p[j*GetPixelChannels(source)+i];
5105 if (channel != AlphaPixelChannel)
5106 pixels[j]*=alpha[j];
5107 }
5108 gamma=1.0; /* number of pixels blended together (its variable) */
5109 for (j=0; j <= 1L; j++)
5110 {
5111 if ((y-y_offset) >= 0.75)
5112 {
5113 alpha[j]=alpha[j+2]; /* take right pixels */
5114 pixels[j]=pixels[j+2];
5115 }
5116 else
5117 if ((y-y_offset) > 0.25)
5118 {
5119 gamma=2.0; /* blend both pixels in row */
5120 alpha[j]+=alpha[j+2]; /* add up alpha weights */
5121 pixels[j]+=pixels[j+2];
5122 }
5123 }
5124 if ((x-x_offset) >= 0.75)
5125 {
5126 alpha[0]=alpha[1]; /* take bottom row blend */
5127 pixels[0]=pixels[1];
5128 }
5129 else
5130 if ((x-x_offset) > 0.25)
5131 {
5132 gamma*=2.0; /* blend both rows */
5133 alpha[0]+=alpha[1]; /* add up alpha weights */
5134 pixels[0]+=pixels[1];
5135 }
5136 if (channel != AlphaPixelChannel)
5137 gamma=PerceptibleReciprocal(alpha[0]); /* (color) 1/alpha_weights */
5138 else
5139 gamma=PerceptibleReciprocal(gamma); /* (alpha) 1/number_of_pixels */
5140 SetPixelChannel(destination,channel,ClampToQuantum(gamma*pixels[0]),
5141 pixel);
5142 }
5143 break;
5144 }
5145 case CatromInterpolatePixel:
5146 {
5147 double
5148 cx[4],
5149 cy[4];
5150
5151 p=GetCacheViewVirtualPixels(source_view,x_offset-1,y_offset-1,4,4,
5152 exception);
5153 if (p == (const Quantum *) NULL)
5154 {
5155 status=MagickFalse;
5156 break;
5157 }
5158 for (i=0; i < (ssize_t) GetPixelChannels(source); i++)
5159 {
5160 register ssize_t
5161 j;
5162
5163 PixelChannel channel = GetPixelChannelChannel(source,i);
5164 PixelTrait traits = GetPixelChannelTraits(source,channel);
5165 PixelTrait destination_traits=GetPixelChannelTraits(destination,
5166 channel);
5167 if ((traits == UndefinedPixelTrait) ||
5168 (destination_traits == UndefinedPixelTrait))
5169 continue;
5170 if ((traits & BlendPixelTrait) == 0)
5171 for (j=0; j < 16; j++)
5172 {
5173 alpha[j]=1.0;
5174 pixels[j]=(double) p[j*GetPixelChannels(source)+i];
5175 }
5176 else
5177 for (j=0; j < 16; j++)
5178 {
5179 alpha[j]=QuantumScale*GetPixelAlpha(source,p+j*
5180 GetPixelChannels(source));
5181 pixels[j]=alpha[j]*p[j*GetPixelChannels(source)+i];
5182 }
5183 CatromWeights((double) (x-x_offset),&cx);
5184 CatromWeights((double) (y-y_offset),&cy);
5185 gamma=((traits & BlendPixelTrait) ? (double) (1.0) :
5186 PerceptibleReciprocal(cy[0]*(cx[0]*alpha[0]+cx[1]*alpha[1]+cx[2]*
5187 alpha[2]+cx[3]*alpha[3])+cy[1]*(cx[0]*alpha[4]+cx[1]*alpha[5]+cx[2]*
5188 alpha[6]+cx[3]*alpha[7])+cy[2]*(cx[0]*alpha[8]+cx[1]*alpha[9]+cx[2]*
5189 alpha[10]+cx[3]*alpha[11])+cy[3]*(cx[0]*alpha[12]+cx[1]*alpha[13]+
5190 cx[2]*alpha[14]+cx[3]*alpha[15])));
5191 SetPixelChannel(destination,channel,ClampToQuantum(gamma*(cy[0]*(cx[0]*
5192 pixels[0]+cx[1]*pixels[1]+cx[2]*pixels[2]+cx[3]*pixels[3])+cy[1]*
5193 (cx[0]*pixels[4]+cx[1]*pixels[5]+cx[2]*pixels[6]+cx[3]*pixels[7])+
5194 cy[2]*(cx[0]*pixels[8]+cx[1]*pixels[9]+cx[2]*pixels[10]+cx[3]*
5195 pixels[11])+cy[3]*(cx[0]*pixels[12]+cx[1]*pixels[13]+cx[2]*
5196 pixels[14]+cx[3]*pixels[15]))),pixel);
5197 }
5198 break;
5199 }
5200 case IntegerInterpolatePixel:
5201 {
5202 p=GetCacheViewVirtualPixels(source_view,x_offset,y_offset,1,1,exception);
5203 if (p == (const Quantum *) NULL)
5204 {
5205 status=MagickFalse;
5206 break;
5207 }
5208 for (i=0; i < (ssize_t) GetPixelChannels(source); i++)
5209 {
5210 PixelChannel channel = GetPixelChannelChannel(source,i);
5211 PixelTrait traits = GetPixelChannelTraits(source,channel);
5212 PixelTrait destination_traits=GetPixelChannelTraits(destination,
5213 channel);
5214 if ((traits == UndefinedPixelTrait) ||
5215 (destination_traits == UndefinedPixelTrait))
5216 continue;
5217 SetPixelChannel(destination,channel,p[i],pixel);
5218 }
5219 break;
5220 }
5221 case NearestInterpolatePixel:
5222 {
5223 x_offset=(ssize_t) floor(x+0.5);
5224 y_offset=(ssize_t) floor(y+0.5);
5225 p=GetCacheViewVirtualPixels(source_view,x_offset,y_offset,1,1,exception);
5226 if (p == (const Quantum *) NULL)
5227 {
5228 status=MagickFalse;
5229 break;
5230 }
5231 for (i=0; i < (ssize_t) GetPixelChannels(source); i++)
5232 {
5233 PixelChannel channel = GetPixelChannelChannel(source,i);
5234 PixelTrait traits = GetPixelChannelTraits(source,channel);
5235 PixelTrait destination_traits=GetPixelChannelTraits(destination,
5236 channel);
5237 if ((traits == UndefinedPixelTrait) ||
5238 (destination_traits == UndefinedPixelTrait))
5239 continue;
5240 SetPixelChannel(destination,channel,p[i],pixel);
5241 }
5242 break;
5243 }
5244 case MeshInterpolatePixel:
5245 {
5246 p=GetCacheViewVirtualPixels(source_view,x_offset,y_offset,2,2,exception);
5247 if (p == (const Quantum *) NULL)
5248 {
5249 status=MagickFalse;
5250 break;
5251 }
5252 for (i=0; i < (ssize_t) GetPixelChannels(source); i++)
5253 {
5254 PointInfo
5255 delta,
5256 luminance;
5257
5258 PixelChannel channel = GetPixelChannelChannel(source,i);
5259 PixelTrait traits = GetPixelChannelTraits(source,channel);
5260 PixelTrait destination_traits=GetPixelChannelTraits(destination,
5261 channel);
5262 if ((traits == UndefinedPixelTrait) ||
5263 (destination_traits == UndefinedPixelTrait))
5264 continue;
5265 pixels[0]=(double) p[i];
5266 pixels[1]=(double) p[GetPixelChannels(source)+i];
5267 pixels[2]=(double) p[2*GetPixelChannels(source)+i];
5268 pixels[3]=(double) p[3*GetPixelChannels(source)+i];
5269 if ((traits & BlendPixelTrait) == 0)
5270 {
5271 alpha[0]=1.0;
5272 alpha[1]=1.0;
5273 alpha[2]=1.0;
5274 alpha[3]=1.0;
5275 }
5276 else
5277 {
5278 alpha[0]=QuantumScale*GetPixelAlpha(source,p);
5279 alpha[1]=QuantumScale*GetPixelAlpha(source,p+
5280 GetPixelChannels(source));
5281 alpha[2]=QuantumScale*GetPixelAlpha(source,p+2*
5282 GetPixelChannels(source));
5283 alpha[3]=QuantumScale*GetPixelAlpha(source,p+3*
5284 GetPixelChannels(source));
5285 }
5286 delta.x=x-x_offset;
5287 delta.y=y-y_offset;
5288 luminance.x=fabs((double) (GetPixelLuma(source,p)-
5289 GetPixelLuma(source,p+3*GetPixelChannels(source))));
5290 luminance.y=fabs((double) (GetPixelLuma(source,p+
5291 GetPixelChannels(source))-GetPixelLuma(source,p+2*
5292 GetPixelChannels(source))));
5293 if (luminance.x < luminance.y)
5294 {
5295 /*
5296 Diagonal 0-3 NW-SE.
5297 */
5298 if (delta.x <= delta.y)
5299 {
5300 /*
5301 Bottom-left triangle (pixel: 2, diagonal: 0-3).
5302 */
5303 delta.y=1.0-delta.y;
5304 gamma=MeshInterpolate(&delta,alpha[2],alpha[3],alpha[0]);
5305 gamma=PerceptibleReciprocal(gamma);
5306 SetPixelChannel(destination,channel,ClampToQuantum(gamma*
5307 MeshInterpolate(&delta,pixels[2],pixels[3],pixels[0])),pixel);
5308 }
5309 else
5310 {
5311 /*
5312 Top-right triangle (pixel: 1, diagonal: 0-3).
5313 */
5314 delta.x=1.0-delta.x;
5315 gamma=MeshInterpolate(&delta,alpha[1],alpha[0],alpha[3]);
5316 gamma=PerceptibleReciprocal(gamma);
5317 SetPixelChannel(destination,channel,ClampToQuantum(gamma*
5318 MeshInterpolate(&delta,pixels[1],pixels[0],pixels[3])),pixel);
5319 }
5320 }
5321 else
5322 {
5323 /*
5324 Diagonal 1-2 NE-SW.
5325 */
5326 if (delta.x <= (1.0-delta.y))
5327 {
5328 /*
5329 Top-left triangle (pixel: 0, diagonal: 1-2).
5330 */
5331 gamma=MeshInterpolate(&delta,alpha[0],alpha[1],alpha[2]);
5332 gamma=PerceptibleReciprocal(gamma);
5333 SetPixelChannel(destination,channel,ClampToQuantum(gamma*
5334 MeshInterpolate(&delta,pixels[0],pixels[1],pixels[2])),pixel);
5335 }
5336 else
5337 {
5338 /*
5339 Bottom-right triangle (pixel: 3, diagonal: 1-2).
5340 */
5341 delta.x=1.0-delta.x;
5342 delta.y=1.0-delta.y;
5343 gamma=MeshInterpolate(&delta,alpha[3],alpha[2],alpha[1]);
5344 gamma=PerceptibleReciprocal(gamma);
5345 SetPixelChannel(destination,channel,ClampToQuantum(gamma*
5346 MeshInterpolate(&delta,pixels[3],pixels[2],pixels[1])),pixel);
5347 }
5348 }
5349 }
5350 break;
5351 }
5352 case SplineInterpolatePixel:
5353 {
5354 double
5355 cx[4],
5356 cy[4];
5357
5358 p=GetCacheViewVirtualPixels(source_view,x_offset-1,y_offset-1,4,4,
5359 exception);
5360 if (p == (const Quantum *) NULL)
5361 {
5362 status=MagickFalse;
5363 break;
5364 }
5365 for (i=0; i < (ssize_t) GetPixelChannels(source); i++)
5366 {
5367 register ssize_t
5368 j;
5369
5370 PixelChannel channel = GetPixelChannelChannel(source,i);
5371 PixelTrait traits = GetPixelChannelTraits(source,channel);
5372 PixelTrait destination_traits=GetPixelChannelTraits(destination,
5373 channel);
5374 if ((traits == UndefinedPixelTrait) ||
5375 (destination_traits == UndefinedPixelTrait))
5376 continue;
5377 if ((traits & BlendPixelTrait) == 0)
5378 for (j=0; j < 16; j++)
5379 {
5380 alpha[j]=1.0;
5381 pixels[j]=(double) p[j*GetPixelChannels(source)+i];
5382 }
5383 else
5384 for (j=0; j < 16; j++)
5385 {
5386 alpha[j]=QuantumScale*GetPixelAlpha(source,p+j*
5387 GetPixelChannels(source));
5388 pixels[j]=alpha[j]*p[j*GetPixelChannels(source)+i];
5389 }
5390 SplineWeights((double) (x-x_offset),&cx);
5391 SplineWeights((double) (y-y_offset),&cy);
5392 gamma=((traits & BlendPixelTrait) ? (double) (1.0) :
5393 PerceptibleReciprocal(cy[0]*(cx[0]*alpha[0]+cx[1]*alpha[1]+cx[2]*
5394 alpha[2]+cx[3]*alpha[3])+cy[1]*(cx[0]*alpha[4]+cx[1]*alpha[5]+cx[2]*
5395 alpha[6]+cx[3]*alpha[7])+cy[2]*(cx[0]*alpha[8]+cx[1]*alpha[9]+cx[2]*
5396 alpha[10]+cx[3]*alpha[11])+cy[3]*(cx[0]*alpha[12]+cx[1]*alpha[13]+
5397 cx[2]*alpha[14]+cx[3]*alpha[15])));
5398 SetPixelChannel(destination,channel,ClampToQuantum(gamma*(cy[0]*(cx[0]*
5399 pixels[0]+cx[1]*pixels[1]+cx[2]*pixels[2]+cx[3]*pixels[3])+cy[1]*
5400 (cx[0]*pixels[4]+cx[1]*pixels[5]+cx[2]*pixels[6]+cx[3]*pixels[7])+
5401 cy[2]*(cx[0]*pixels[8]+cx[1]*pixels[9]+cx[2]*pixels[10]+cx[3]*
5402 pixels[11])+cy[3]*(cx[0]*pixels[12]+cx[1]*pixels[13]+cx[2]*
5403 pixels[14]+cx[3]*pixels[15]))),pixel);
5404 }
5405 break;
5406 }
5407 }
5408 return(status);
5409 }
5410
5411 /*
5412 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5413 % %
5414 % %
5415 % %
5416 % I n t e r p o l a t e P i x e l I n f o %
5417 % %
5418 % %
5419 % %
5420 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5421 %
5422 % InterpolatePixelInfo() applies a pixel interpolation method between a
5423 % floating point coordinate and the pixels surrounding that coordinate. No
5424 % pixel area resampling, or scaling of the result is performed.
5425 %
5426 % Interpolation is restricted to just RGBKA channels.
5427 %
5428 % The format of the InterpolatePixelInfo method is:
5429 %
5430 % MagickBooleanType InterpolatePixelInfo(const Image *image,
5431 % const CacheView *image_view,const PixelInterpolateMethod method,
5432 % const double x,const double y,PixelInfo *pixel,
5433 % ExceptionInfo *exception)
5434 %
5435 % A description of each parameter follows:
5436 %
5437 % o image: the image.
5438 %
5439 % o image_view: the image view.
5440 %
5441 % o method: the pixel color interpolation method.
5442 %
5443 % o x,y: A double representing the current (x,y) position of the pixel.
5444 %
5445 % o pixel: return the interpolated pixel here.
5446 %
5447 % o exception: return any errors or warnings in this structure.
5448 %
5449 */
5450
AlphaBlendPixelInfo(const Image * image,const Quantum * pixel,PixelInfo * pixel_info,double * alpha)5451 static inline void AlphaBlendPixelInfo(const Image *image,
5452 const Quantum *pixel,PixelInfo *pixel_info,double *alpha)
5453 {
5454 if (image->alpha_trait == UndefinedPixelTrait)
5455 {
5456 *alpha=1.0;
5457 pixel_info->red=(double) GetPixelRed(image,pixel);
5458 pixel_info->green=(double) GetPixelGreen(image,pixel);
5459 pixel_info->blue=(double) GetPixelBlue(image,pixel);
5460 pixel_info->black=0.0;
5461 if (image->colorspace == CMYKColorspace)
5462 pixel_info->black=(double) GetPixelBlack(image,pixel);
5463 pixel_info->alpha=(double) GetPixelAlpha(image,pixel);
5464 return;
5465 }
5466 *alpha=QuantumScale*GetPixelAlpha(image,pixel);
5467 pixel_info->red=(*alpha*GetPixelRed(image,pixel));
5468 pixel_info->green=(*alpha*GetPixelGreen(image,pixel));
5469 pixel_info->blue=(*alpha*GetPixelBlue(image,pixel));
5470 pixel_info->black=0.0;
5471 if (image->colorspace == CMYKColorspace)
5472 pixel_info->black=(*alpha*GetPixelBlack(image,pixel));
5473 pixel_info->alpha=(double) GetPixelAlpha(image,pixel);
5474 }
5475
InterpolatePixelInfo(const Image * image,const CacheView_ * image_view,const PixelInterpolateMethod method,const double x,const double y,PixelInfo * pixel,ExceptionInfo * exception)5476 MagickExport MagickBooleanType InterpolatePixelInfo(const Image *image,
5477 const CacheView_ *image_view,const PixelInterpolateMethod method,
5478 const double x,const double y,PixelInfo *pixel,ExceptionInfo *exception)
5479 {
5480 MagickBooleanType
5481 status;
5482
5483 double
5484 alpha[16],
5485 gamma;
5486
5487 PixelInfo
5488 pixels[16];
5489
5490 register const Quantum
5491 *p;
5492
5493 register ssize_t
5494 i;
5495
5496 ssize_t
5497 x_offset,
5498 y_offset;
5499
5500 PixelInterpolateMethod
5501 interpolate;
5502
5503 assert(image != (Image *) NULL);
5504 assert(image->signature == MagickCoreSignature);
5505 assert(image_view != (CacheView *) NULL);
5506 status=MagickTrue;
5507 x_offset=(ssize_t) floor(x);
5508 y_offset=(ssize_t) floor(y);
5509 interpolate=method;
5510 if (interpolate == UndefinedInterpolatePixel)
5511 interpolate=image->interpolate;
5512 GetPixelInfoPixel(image,(const Quantum *) NULL,pixel);
5513 (void) memset(&pixels,0,sizeof(pixels));
5514 switch (interpolate)
5515 {
5516 case AverageInterpolatePixel: /* nearest 4 neighbours */
5517 case Average9InterpolatePixel: /* nearest 9 neighbours */
5518 case Average16InterpolatePixel: /* nearest 16 neighbours */
5519 {
5520 ssize_t
5521 count;
5522
5523 count=2; /* size of the area to average - default nearest 4 */
5524 if (interpolate == Average9InterpolatePixel)
5525 {
5526 count=3;
5527 x_offset=(ssize_t) (floor(x+0.5)-1);
5528 y_offset=(ssize_t) (floor(y+0.5)-1);
5529 }
5530 else if (interpolate == Average16InterpolatePixel)
5531 {
5532 count=4;
5533 x_offset--;
5534 y_offset--;
5535 }
5536 p=GetCacheViewVirtualPixels(image_view,x_offset,y_offset,(size_t) count,
5537 (size_t) count,exception);
5538 if (p == (const Quantum *) NULL)
5539 {
5540 status=MagickFalse;
5541 break;
5542 }
5543 count*=count; /* number of pixels - square of size */
5544 for (i=0; i < (ssize_t) count; i++)
5545 {
5546 AlphaBlendPixelInfo(image,p,pixels,alpha);
5547 gamma=PerceptibleReciprocal(alpha[0]);
5548 pixel->red+=gamma*pixels[0].red;
5549 pixel->green+=gamma*pixels[0].green;
5550 pixel->blue+=gamma*pixels[0].blue;
5551 pixel->black+=gamma*pixels[0].black;
5552 pixel->alpha+=pixels[0].alpha;
5553 p += GetPixelChannels(image);
5554 }
5555 gamma=1.0/count; /* average weighting of each pixel in area */
5556 pixel->red*=gamma;
5557 pixel->green*=gamma;
5558 pixel->blue*=gamma;
5559 pixel->black*=gamma;
5560 pixel->alpha*=gamma;
5561 break;
5562 }
5563 case BackgroundInterpolatePixel:
5564 {
5565 *pixel=image->background_color; /* Copy PixelInfo Structure */
5566 break;
5567 }
5568 case BilinearInterpolatePixel:
5569 default:
5570 {
5571 PointInfo
5572 delta,
5573 epsilon;
5574
5575 p=GetCacheViewVirtualPixels(image_view,x_offset,y_offset,2,2,exception);
5576 if (p == (const Quantum *) NULL)
5577 {
5578 status=MagickFalse;
5579 break;
5580 }
5581 for (i=0; i < 4L; i++)
5582 AlphaBlendPixelInfo(image,p+i*GetPixelChannels(image),pixels+i,alpha+i);
5583 delta.x=x-x_offset;
5584 delta.y=y-y_offset;
5585 epsilon.x=1.0-delta.x;
5586 epsilon.y=1.0-delta.y;
5587 gamma=((epsilon.y*(epsilon.x*alpha[0]+delta.x*alpha[1])+delta.y*
5588 (epsilon.x*alpha[2]+delta.x*alpha[3])));
5589 gamma=PerceptibleReciprocal(gamma);
5590 pixel->red=gamma*(epsilon.y*(epsilon.x*pixels[0].red+delta.x*
5591 pixels[1].red)+delta.y*(epsilon.x*pixels[2].red+delta.x*pixels[3].red));
5592 pixel->green=gamma*(epsilon.y*(epsilon.x*pixels[0].green+delta.x*
5593 pixels[1].green)+delta.y*(epsilon.x*pixels[2].green+delta.x*
5594 pixels[3].green));
5595 pixel->blue=gamma*(epsilon.y*(epsilon.x*pixels[0].blue+delta.x*
5596 pixels[1].blue)+delta.y*(epsilon.x*pixels[2].blue+delta.x*
5597 pixels[3].blue));
5598 if (image->colorspace == CMYKColorspace)
5599 pixel->black=gamma*(epsilon.y*(epsilon.x*pixels[0].black+delta.x*
5600 pixels[1].black)+delta.y*(epsilon.x*pixels[2].black+delta.x*
5601 pixels[3].black));
5602 gamma=((epsilon.y*(epsilon.x+delta.x)+delta.y*(epsilon.x+delta.x)));
5603 gamma=PerceptibleReciprocal(gamma);
5604 pixel->alpha=gamma*(epsilon.y*(epsilon.x*pixels[0].alpha+delta.x*
5605 pixels[1].alpha)+delta.y*(epsilon.x*pixels[2].alpha+delta.x*
5606 pixels[3].alpha));
5607 break;
5608 }
5609 case BlendInterpolatePixel:
5610 {
5611 p=GetCacheViewVirtualPixels(image_view,x_offset,y_offset,2,2,exception);
5612 if (p == (const Quantum *) NULL)
5613 {
5614 status=MagickFalse;
5615 break;
5616 }
5617 for (i=0; i < 4L; i++)
5618 {
5619 GetPixelInfoPixel(image,p+i*GetPixelChannels(image),pixels+i);
5620 AlphaBlendPixelInfo(image,p+i*GetPixelChannels(image),pixels+i,alpha+i);
5621 }
5622 gamma=1.0; /* number of pixels blended together (its variable) */
5623 for (i=0; i <= 1L; i++)
5624 {
5625 if ((y-y_offset) >= 0.75)
5626 {
5627 alpha[i]=alpha[i+2]; /* take right pixels */
5628 pixels[i]=pixels[i+2];
5629 }
5630 else
5631 if ((y-y_offset) > 0.25)
5632 {
5633 gamma=2.0; /* blend both pixels in row */
5634 alpha[i]+=alpha[i+2]; /* add up alpha weights */
5635 pixels[i].red+=pixels[i+2].red;
5636 pixels[i].green+=pixels[i+2].green;
5637 pixels[i].blue+=pixels[i+2].blue;
5638 pixels[i].black+=pixels[i+2].black;
5639 pixels[i].alpha+=pixels[i+2].alpha;
5640 }
5641 }
5642 if ((x-x_offset) >= 0.75)
5643 {
5644 alpha[0]=alpha[1];
5645 pixels[0]=pixels[1];
5646 }
5647 else
5648 if ((x-x_offset) > 0.25)
5649 {
5650 gamma*=2.0; /* blend both rows */
5651 alpha[0]+= alpha[1]; /* add up alpha weights */
5652 pixels[0].red+=pixels[1].red;
5653 pixels[0].green+=pixels[1].green;
5654 pixels[0].blue+=pixels[1].blue;
5655 pixels[0].black+=pixels[1].black;
5656 pixels[0].alpha+=pixels[1].alpha;
5657 }
5658 gamma=1.0/gamma;
5659 alpha[0]=PerceptibleReciprocal(alpha[0]);
5660 pixel->red=alpha[0]*pixels[0].red;
5661 pixel->green=alpha[0]*pixels[0].green; /* divide by sum of alpha */
5662 pixel->blue=alpha[0]*pixels[0].blue;
5663 pixel->black=alpha[0]*pixels[0].black;
5664 pixel->alpha=gamma*pixels[0].alpha; /* divide by number of pixels */
5665 break;
5666 }
5667 case CatromInterpolatePixel:
5668 {
5669 double
5670 cx[4],
5671 cy[4];
5672
5673 p=GetCacheViewVirtualPixels(image_view,x_offset-1,y_offset-1,4,4,
5674 exception);
5675 if (p == (const Quantum *) NULL)
5676 {
5677 status=MagickFalse;
5678 break;
5679 }
5680 for (i=0; i < 16L; i++)
5681 AlphaBlendPixelInfo(image,p+i*GetPixelChannels(image),pixels+i,alpha+i);
5682 CatromWeights((double) (x-x_offset),&cx);
5683 CatromWeights((double) (y-y_offset),&cy);
5684 pixel->red=(cy[0]*(cx[0]*pixels[0].red+cx[1]*pixels[1].red+cx[2]*
5685 pixels[2].red+cx[3]*pixels[3].red)+cy[1]*(cx[0]*pixels[4].red+cx[1]*
5686 pixels[5].red+cx[2]*pixels[6].red+cx[3]*pixels[7].red)+cy[2]*(cx[0]*
5687 pixels[8].red+cx[1]*pixels[9].red+cx[2]*pixels[10].red+cx[3]*
5688 pixels[11].red)+cy[3]*(cx[0]*pixels[12].red+cx[1]*pixels[13].red+cx[2]*
5689 pixels[14].red+cx[3]*pixels[15].red));
5690 pixel->green=(cy[0]*(cx[0]*pixels[0].green+cx[1]*pixels[1].green+cx[2]*
5691 pixels[2].green+cx[3]*pixels[3].green)+cy[1]*(cx[0]*pixels[4].green+
5692 cx[1]*pixels[5].green+cx[2]*pixels[6].green+cx[3]*pixels[7].green)+
5693 cy[2]*(cx[0]*pixels[8].green+cx[1]*pixels[9].green+cx[2]*
5694 pixels[10].green+cx[3]*pixels[11].green)+cy[3]*(cx[0]*
5695 pixels[12].green+cx[1]*pixels[13].green+cx[2]*pixels[14].green+cx[3]*
5696 pixels[15].green));
5697 pixel->blue=(cy[0]*(cx[0]*pixels[0].blue+cx[1]*pixels[1].blue+cx[2]*
5698 pixels[2].blue+cx[3]*pixels[3].blue)+cy[1]*(cx[0]*pixels[4].blue+cx[1]*
5699 pixels[5].blue+cx[2]*pixels[6].blue+cx[3]*pixels[7].blue)+cy[2]*(cx[0]*
5700 pixels[8].blue+cx[1]*pixels[9].blue+cx[2]*pixels[10].blue+cx[3]*
5701 pixels[11].blue)+cy[3]*(cx[0]*pixels[12].blue+cx[1]*pixels[13].blue+
5702 cx[2]*pixels[14].blue+cx[3]*pixels[15].blue));
5703 if (image->colorspace == CMYKColorspace)
5704 pixel->black=(cy[0]*(cx[0]*pixels[0].black+cx[1]*pixels[1].black+cx[2]*
5705 pixels[2].black+cx[3]*pixels[3].black)+cy[1]*(cx[0]*pixels[4].black+
5706 cx[1]*pixels[5].black+cx[2]*pixels[6].black+cx[3]*pixels[7].black)+
5707 cy[2]*(cx[0]*pixels[8].black+cx[1]*pixels[9].black+cx[2]*
5708 pixels[10].black+cx[3]*pixels[11].black)+cy[3]*(cx[0]*
5709 pixels[12].black+cx[1]*pixels[13].black+cx[2]*pixels[14].black+cx[3]*
5710 pixels[15].black));
5711 pixel->alpha=(cy[0]*(cx[0]*pixels[0].alpha+cx[1]*pixels[1].alpha+cx[2]*
5712 pixels[2].alpha+cx[3]*pixels[3].alpha)+cy[1]*(cx[0]*pixels[4].alpha+
5713 cx[1]*pixels[5].alpha+cx[2]*pixels[6].alpha+cx[3]*pixels[7].alpha)+
5714 cy[2]*(cx[0]*pixels[8].alpha+cx[1]*pixels[9].alpha+cx[2]*
5715 pixels[10].alpha+cx[3]*pixels[11].alpha)+cy[3]*(cx[0]*pixels[12].alpha+
5716 cx[1]*pixels[13].alpha+cx[2]*pixels[14].alpha+cx[3]*pixels[15].alpha));
5717 break;
5718 }
5719 case IntegerInterpolatePixel:
5720 {
5721 p=GetCacheViewVirtualPixels(image_view,x_offset,y_offset,1,1,exception);
5722 if (p == (const Quantum *) NULL)
5723 {
5724 status=MagickFalse;
5725 break;
5726 }
5727 GetPixelInfoPixel(image,p,pixel);
5728 break;
5729 }
5730 case MeshInterpolatePixel:
5731 {
5732 PointInfo
5733 delta,
5734 luminance;
5735
5736 p=GetCacheViewVirtualPixels(image_view,x_offset,y_offset,2,2,exception);
5737 if (p == (const Quantum *) NULL)
5738 {
5739 status=MagickFalse;
5740 break;
5741 }
5742 delta.x=x-x_offset;
5743 delta.y=y-y_offset;
5744 luminance.x=GetPixelLuma(image,p)-(double)
5745 GetPixelLuma(image,p+3*GetPixelChannels(image));
5746 luminance.y=GetPixelLuma(image,p+GetPixelChannels(image))-(double)
5747 GetPixelLuma(image,p+2*GetPixelChannels(image));
5748 AlphaBlendPixelInfo(image,p,pixels+0,alpha+0);
5749 AlphaBlendPixelInfo(image,p+GetPixelChannels(image),pixels+1,alpha+1);
5750 AlphaBlendPixelInfo(image,p+2*GetPixelChannels(image),pixels+2,alpha+2);
5751 AlphaBlendPixelInfo(image,p+3*GetPixelChannels(image),pixels+3,alpha+3);
5752 if (fabs(luminance.x) < fabs(luminance.y))
5753 {
5754 /*
5755 Diagonal 0-3 NW-SE.
5756 */
5757 if (delta.x <= delta.y)
5758 {
5759 /*
5760 Bottom-left triangle (pixel: 2, diagonal: 0-3).
5761 */
5762 delta.y=1.0-delta.y;
5763 gamma=MeshInterpolate(&delta,alpha[2],alpha[3],alpha[0]);
5764 gamma=PerceptibleReciprocal(gamma);
5765 pixel->red=gamma*MeshInterpolate(&delta,pixels[2].red,
5766 pixels[3].red,pixels[0].red);
5767 pixel->green=gamma*MeshInterpolate(&delta,pixels[2].green,
5768 pixels[3].green,pixels[0].green);
5769 pixel->blue=gamma*MeshInterpolate(&delta,pixels[2].blue,
5770 pixels[3].blue,pixels[0].blue);
5771 if (image->colorspace == CMYKColorspace)
5772 pixel->black=gamma*MeshInterpolate(&delta,pixels[2].black,
5773 pixels[3].black,pixels[0].black);
5774 gamma=MeshInterpolate(&delta,1.0,1.0,1.0);
5775 pixel->alpha=gamma*MeshInterpolate(&delta,pixels[2].alpha,
5776 pixels[3].alpha,pixels[0].alpha);
5777 }
5778 else
5779 {
5780 /*
5781 Top-right triangle (pixel:1 , diagonal: 0-3).
5782 */
5783 delta.x=1.0-delta.x;
5784 gamma=MeshInterpolate(&delta,alpha[1],alpha[0],alpha[3]);
5785 gamma=PerceptibleReciprocal(gamma);
5786 pixel->red=gamma*MeshInterpolate(&delta,pixels[1].red,
5787 pixels[0].red,pixels[3].red);
5788 pixel->green=gamma*MeshInterpolate(&delta,pixels[1].green,
5789 pixels[0].green,pixels[3].green);
5790 pixel->blue=gamma*MeshInterpolate(&delta,pixels[1].blue,
5791 pixels[0].blue,pixels[3].blue);
5792 if (image->colorspace == CMYKColorspace)
5793 pixel->black=gamma*MeshInterpolate(&delta,pixels[1].black,
5794 pixels[0].black,pixels[3].black);
5795 gamma=MeshInterpolate(&delta,1.0,1.0,1.0);
5796 pixel->alpha=gamma*MeshInterpolate(&delta,pixels[1].alpha,
5797 pixels[0].alpha,pixels[3].alpha);
5798 }
5799 }
5800 else
5801 {
5802 /*
5803 Diagonal 1-2 NE-SW.
5804 */
5805 if (delta.x <= (1.0-delta.y))
5806 {
5807 /*
5808 Top-left triangle (pixel: 0, diagonal: 1-2).
5809 */
5810 gamma=MeshInterpolate(&delta,alpha[0],alpha[1],alpha[2]);
5811 gamma=PerceptibleReciprocal(gamma);
5812 pixel->red=gamma*MeshInterpolate(&delta,pixels[0].red,
5813 pixels[1].red,pixels[2].red);
5814 pixel->green=gamma*MeshInterpolate(&delta,pixels[0].green,
5815 pixels[1].green,pixels[2].green);
5816 pixel->blue=gamma*MeshInterpolate(&delta,pixels[0].blue,
5817 pixels[1].blue,pixels[2].blue);
5818 if (image->colorspace == CMYKColorspace)
5819 pixel->black=gamma*MeshInterpolate(&delta,pixels[0].black,
5820 pixels[1].black,pixels[2].black);
5821 gamma=MeshInterpolate(&delta,1.0,1.0,1.0);
5822 pixel->alpha=gamma*MeshInterpolate(&delta,pixels[0].alpha,
5823 pixels[1].alpha,pixels[2].alpha);
5824 }
5825 else
5826 {
5827 /*
5828 Bottom-right triangle (pixel: 3, diagonal: 1-2).
5829 */
5830 delta.x=1.0-delta.x;
5831 delta.y=1.0-delta.y;
5832 gamma=MeshInterpolate(&delta,alpha[3],alpha[2],alpha[1]);
5833 gamma=PerceptibleReciprocal(gamma);
5834 pixel->red=gamma*MeshInterpolate(&delta,pixels[3].red,
5835 pixels[2].red,pixels[1].red);
5836 pixel->green=gamma*MeshInterpolate(&delta,pixels[3].green,
5837 pixels[2].green,pixels[1].green);
5838 pixel->blue=gamma*MeshInterpolate(&delta,pixels[3].blue,
5839 pixels[2].blue,pixels[1].blue);
5840 if (image->colorspace == CMYKColorspace)
5841 pixel->black=gamma*MeshInterpolate(&delta,pixels[3].black,
5842 pixels[2].black,pixels[1].black);
5843 gamma=MeshInterpolate(&delta,1.0,1.0,1.0);
5844 pixel->alpha=gamma*MeshInterpolate(&delta,pixels[3].alpha,
5845 pixels[2].alpha,pixels[1].alpha);
5846 }
5847 }
5848 break;
5849 }
5850 case NearestInterpolatePixel:
5851 {
5852 x_offset=(ssize_t) floor(x+0.5);
5853 y_offset=(ssize_t) floor(y+0.5);
5854 p=GetCacheViewVirtualPixels(image_view,x_offset,y_offset,1,1,exception);
5855 if (p == (const Quantum *) NULL)
5856 {
5857 status=MagickFalse;
5858 break;
5859 }
5860 GetPixelInfoPixel(image,p,pixel);
5861 break;
5862 }
5863 case SplineInterpolatePixel:
5864 {
5865 double
5866 cx[4],
5867 cy[4];
5868
5869 p=GetCacheViewVirtualPixels(image_view,x_offset-1,y_offset-1,4,4,
5870 exception);
5871 if (p == (const Quantum *) NULL)
5872 {
5873 status=MagickFalse;
5874 break;
5875 }
5876 for (i=0; i < 16L; i++)
5877 AlphaBlendPixelInfo(image,p+i*GetPixelChannels(image),pixels+i,alpha+i);
5878 SplineWeights((double) (x-x_offset),&cx);
5879 SplineWeights((double) (y-y_offset),&cy);
5880 pixel->red=(cy[0]*(cx[0]*pixels[0].red+cx[1]*pixels[1].red+cx[2]*
5881 pixels[2].red+cx[3]*pixels[3].red)+cy[1]*(cx[0]*pixels[4].red+cx[1]*
5882 pixels[5].red+cx[2]*pixels[6].red+cx[3]*pixels[7].red)+cy[2]*(cx[0]*
5883 pixels[8].red+cx[1]*pixels[9].red+cx[2]*pixels[10].red+cx[3]*
5884 pixels[11].red)+cy[3]*(cx[0]*pixels[12].red+cx[1]*pixels[13].red+cx[2]*
5885 pixels[14].red+cx[3]*pixels[15].red));
5886 pixel->green=(cy[0]*(cx[0]*pixels[0].green+cx[1]*pixels[1].green+cx[2]*
5887 pixels[2].green+cx[3]*pixels[3].green)+cy[1]*(cx[0]*pixels[4].green+
5888 cx[1]*pixels[5].green+cx[2]*pixels[6].green+cx[3]*pixels[7].green)+
5889 cy[2]*(cx[0]*pixels[8].green+cx[1]*pixels[9].green+cx[2]*
5890 pixels[10].green+cx[3]*pixels[11].green)+cy[3]*(cx[0]*pixels[12].green+
5891 cx[1]*pixels[13].green+cx[2]*pixels[14].green+cx[3]*pixels[15].green));
5892 pixel->blue=(cy[0]*(cx[0]*pixels[0].blue+cx[1]*pixels[1].blue+cx[2]*
5893 pixels[2].blue+cx[3]*pixels[3].blue)+cy[1]*(cx[0]*pixels[4].blue+cx[1]*
5894 pixels[5].blue+cx[2]*pixels[6].blue+cx[3]*pixels[7].blue)+cy[2]*(cx[0]*
5895 pixels[8].blue+cx[1]*pixels[9].blue+cx[2]*pixels[10].blue+cx[3]*
5896 pixels[11].blue)+cy[3]*(cx[0]*pixels[12].blue+cx[1]*pixels[13].blue+
5897 cx[2]*pixels[14].blue+cx[3]*pixels[15].blue));
5898 if (image->colorspace == CMYKColorspace)
5899 pixel->black=(cy[0]*(cx[0]*pixels[0].black+cx[1]*pixels[1].black+cx[2]*
5900 pixels[2].black+cx[3]*pixels[3].black)+cy[1]*(cx[0]*pixels[4].black+
5901 cx[1]*pixels[5].black+cx[2]*pixels[6].black+cx[3]*pixels[7].black)+
5902 cy[2]*(cx[0]*pixels[8].black+cx[1]*pixels[9].black+cx[2]*
5903 pixels[10].black+cx[3]*pixels[11].black)+cy[3]*(cx[0]*
5904 pixels[12].black+cx[1]*pixels[13].black+cx[2]*pixels[14].black+cx[3]*
5905 pixels[15].black));
5906 pixel->alpha=(cy[0]*(cx[0]*pixels[0].alpha+cx[1]*pixels[1].alpha+cx[2]*
5907 pixels[2].alpha+cx[3]*pixels[3].alpha)+cy[1]*(cx[0]*pixels[4].alpha+
5908 cx[1]*pixels[5].alpha+cx[2]*pixels[6].alpha+cx[3]*pixels[7].alpha)+
5909 cy[2]*(cx[0]*pixels[8].alpha+cx[1]*pixels[9].alpha+cx[2]*
5910 pixels[10].alpha+cx[3]*pixels[11].alpha)+cy[3]*(cx[0]*pixels[12].alpha+
5911 cx[1]*pixels[13].alpha+cx[2]*pixels[14].alpha+cx[3]*pixels[15].alpha));
5912 break;
5913 }
5914 }
5915 return(status);
5916 }
5917
5918 /*
5919 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5920 % %
5921 % %
5922 % %
5923 + I s F u z z y E q u i v a l e n c e P i x e l %
5924 % %
5925 % %
5926 % %
5927 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5928 %
5929 % IsFuzzyEquivalencePixel() returns MagickTrue if the distance between two
5930 % pixels is less than the specified distance in a linear three (or four)
5931 % dimensional color space.
5932 %
5933 % The format of the IsFuzzyEquivalencePixel method is:
5934 %
5935 % void IsFuzzyEquivalencePixel(const Image *source,const Quantum *p,
5936 % const Image *destination,const Quantum *q)
5937 %
5938 % A description of each parameter follows:
5939 %
5940 % o source: the source image.
5941 %
5942 % o p: Pixel p.
5943 %
5944 % o destination: the destination image.
5945 %
5946 % o q: Pixel q.
5947 %
5948 */
IsFuzzyEquivalencePixel(const Image * source,const Quantum * p,const Image * destination,const Quantum * q)5949 MagickExport MagickBooleanType IsFuzzyEquivalencePixel(const Image *source,
5950 const Quantum *p,const Image *destination,const Quantum *q)
5951 {
5952 double
5953 fuzz,
5954 pixel;
5955
5956 register double
5957 distance,
5958 scale;
5959
5960 fuzz=GetFuzzyColorDistance(source,destination);
5961 scale=1.0;
5962 distance=0.0;
5963 if (source->alpha_trait != UndefinedPixelTrait ||
5964 destination->alpha_trait != UndefinedPixelTrait)
5965 {
5966 /*
5967 Transparencies are involved - set alpha distance
5968 */
5969 pixel=GetPixelAlpha(source,p)-(double) GetPixelAlpha(destination,q);
5970 distance=pixel*pixel;
5971 if (distance > fuzz)
5972 return(MagickFalse);
5973 /*
5974 Generate a alpha scaling factor to generate a 4D cone on colorspace
5975 Note that if one color is transparent, distance has no color component.
5976 */
5977 if (source->alpha_trait != UndefinedPixelTrait)
5978 scale=QuantumScale*GetPixelAlpha(source,p);
5979 if (destination->alpha_trait != UndefinedPixelTrait)
5980 scale*=QuantumScale*GetPixelAlpha(destination,q);
5981 if (scale <= MagickEpsilon)
5982 return(MagickTrue);
5983 }
5984 /*
5985 RGB or CMY color cube
5986 */
5987 distance*=3.0; /* rescale appropriately */
5988 fuzz*=3.0;
5989 pixel=GetPixelRed(source,p)-(double) GetPixelRed(destination,q);
5990 if ((source->colorspace == HSLColorspace) ||
5991 (source->colorspace == HSBColorspace) ||
5992 (source->colorspace == HWBColorspace))
5993 {
5994 /*
5995 Compute an arc distance for hue. It should be a vector angle of
5996 'S'/'W' length with 'L'/'B' forming appropriate cones.
5997 */
5998 if (fabs((double) pixel) > (QuantumRange/2))
5999 pixel-=QuantumRange;
6000 pixel*=2;
6001 }
6002 distance+=scale*pixel*pixel;
6003 if (distance > fuzz)
6004 return(MagickFalse);
6005 pixel=GetPixelGreen(source,p)-(double) GetPixelGreen(destination,q);
6006 distance+=scale*pixel*pixel;
6007 if (distance > fuzz)
6008 return(MagickFalse);
6009 pixel=GetPixelBlue(source,p)-(double) GetPixelBlue(destination,q);
6010 distance+=scale*pixel*pixel;
6011 if (distance > fuzz)
6012 return(MagickFalse);
6013 return(MagickTrue);
6014 }
6015
6016 /*
6017 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6018 % %
6019 % %
6020 % %
6021 + 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 %
6022 % %
6023 % %
6024 % %
6025 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6026 %
6027 % IsFuzzyEquivalencePixelInfo() returns true if the distance between two
6028 % colors is less than the specified distance in a linear three (or four)
6029 % dimensional color space.
6030 %
6031 % This implements the equivalent of:
6032 % fuzz < sqrt(color_distance^2 * u.a*v.a + alpha_distance^2)
6033 %
6034 % Which produces a multi-dimensional cone for that colorspace along the
6035 % transparency vector.
6036 %
6037 % For example for an RGB:
6038 % color_distance^2 = ( (u.r-v.r)^2 + (u.g-v.g)^2 + (u.b-v.b)^2 ) / 3
6039 %
6040 % See http://imagemagick.org/Usage/bugs/fuzz_distance/
6041 %
6042 % Hue colorspace distances need more work. Hue is not a distance, it is an
6043 % angle!
6044 %
6045 % A check that q is in the same color space as p should be made and the
6046 % appropriate mapping made. -- Anthony Thyssen 8 December 2010
6047 %
6048 % The format of the IsFuzzyEquivalencePixelInfo method is:
6049 %
6050 % MagickBooleanType IsFuzzyEquivalencePixelInfo(const PixelInfo *p,
6051 % const PixelInfo *q)
6052 %
6053 % A description of each parameter follows:
6054 %
6055 % o p: Pixel p.
6056 %
6057 % o q: Pixel q.
6058 %
6059 */
IsFuzzyEquivalencePixelInfo(const PixelInfo * p,const PixelInfo * q)6060 MagickExport MagickBooleanType IsFuzzyEquivalencePixelInfo(const PixelInfo *p,
6061 const PixelInfo *q)
6062 {
6063 double
6064 fuzz,
6065 pixel;
6066
6067 register double
6068 scale,
6069 distance;
6070
6071 fuzz=(double) MagickMax(MagickMax(p->fuzz,q->fuzz),(MagickRealType)
6072 MagickSQ1_2);
6073 fuzz*=fuzz;
6074 scale=1.0;
6075 distance=0.0;
6076 if ((p->alpha_trait != UndefinedPixelTrait) ||
6077 (q->alpha_trait != UndefinedPixelTrait))
6078 {
6079 /*
6080 Transparencies are involved - set alpha distance.
6081 */
6082 pixel=(p->alpha_trait != UndefinedPixelTrait ? p->alpha : OpaqueAlpha)-
6083 (q->alpha_trait != UndefinedPixelTrait ? q->alpha : OpaqueAlpha);
6084 distance=pixel*pixel;
6085 if (distance > fuzz)
6086 return(MagickFalse);
6087 /*
6088 Generate a alpha scaling factor to generate a 4D cone on colorspace.
6089 If one color is transparent, distance has no color component.
6090 */
6091 if (p->alpha_trait != UndefinedPixelTrait)
6092 scale=(QuantumScale*p->alpha);
6093 if (q->alpha_trait != UndefinedPixelTrait)
6094 scale*=(QuantumScale*q->alpha);
6095 if (scale <= MagickEpsilon )
6096 return(MagickTrue);
6097 }
6098 /*
6099 CMYK create a CMY cube with a multi-dimensional cone toward black.
6100 */
6101 if (p->colorspace == CMYKColorspace)
6102 {
6103 pixel=p->black-q->black;
6104 distance+=pixel*pixel*scale;
6105 if (distance > fuzz)
6106 return(MagickFalse);
6107 scale*=(double) (QuantumScale*(QuantumRange-p->black));
6108 scale*=(double) (QuantumScale*(QuantumRange-q->black));
6109 }
6110 /*
6111 RGB or CMY color cube.
6112 */
6113 distance*=3.0; /* rescale appropriately */
6114 fuzz*=3.0;
6115 pixel=p->red-q->red;
6116 if ((p->colorspace == HSLColorspace) || (p->colorspace == HSBColorspace) ||
6117 (p->colorspace == HWBColorspace))
6118 {
6119 /*
6120 This calculates a arc distance for hue-- it should be a vector
6121 angle of 'S'/'W' length with 'L'/'B' forming appropriate cones.
6122 In other words this is a hack - Anthony.
6123 */
6124 if (fabs((double) pixel) > (QuantumRange/2))
6125 pixel-=QuantumRange;
6126 pixel*=2;
6127 }
6128 distance+=pixel*pixel*scale;
6129 if (distance > fuzz)
6130 return(MagickFalse);
6131 pixel=p->green-q->green;
6132 distance+=pixel*pixel*scale;
6133 if (distance > fuzz)
6134 return(MagickFalse);
6135 pixel=p->blue-q->blue;
6136 distance+=pixel*pixel*scale;
6137 if (distance > fuzz)
6138 return(MagickFalse);
6139 return(MagickTrue);
6140 }
6141
6142 /*
6143 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6144 % %
6145 % %
6146 % %
6147 % S e t P i x e l C h a n n e l M a s k %
6148 % %
6149 % %
6150 % %
6151 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6152 %
6153 % SetPixelChannelMask() sets the pixel channel map from the specified channel
6154 % mask.
6155 %
6156 % The format of the SetPixelChannelMask method is:
6157 %
6158 % ChannelType SetPixelChannelMask(Image *image,
6159 % const ChannelType channel_mask)
6160 %
6161 % A description of each parameter follows:
6162 %
6163 % o image: the image.
6164 %
6165 % o channel_mask: the channel mask.
6166 %
6167 */
6168
LogPixelChannels(const Image * image)6169 static void LogPixelChannels(const Image *image)
6170 {
6171 register ssize_t
6172 i;
6173
6174 (void) LogMagickEvent(PixelEvent,GetMagickModule(),"%s[%08x]",
6175 image->filename,image->channel_mask);
6176 for (i=0; i < (ssize_t) image->number_channels; i++)
6177 {
6178 char
6179 channel_name[MagickPathExtent],
6180 traits[MagickPathExtent];
6181
6182 const char
6183 *name;
6184
6185 PixelChannel
6186 channel;
6187
6188 channel=GetPixelChannelChannel(image,i);
6189 switch (channel)
6190 {
6191 case RedPixelChannel:
6192 {
6193 name="red";
6194 if (image->colorspace == CMYKColorspace)
6195 name="cyan";
6196 if ((image->colorspace == LinearGRAYColorspace) ||
6197 (image->colorspace == GRAYColorspace))
6198 name="gray";
6199 break;
6200 }
6201 case GreenPixelChannel:
6202 {
6203 name="green";
6204 if (image->colorspace == CMYKColorspace)
6205 name="magenta";
6206 break;
6207 }
6208 case BluePixelChannel:
6209 {
6210 name="blue";
6211 if (image->colorspace == CMYKColorspace)
6212 name="yellow";
6213 break;
6214 }
6215 case BlackPixelChannel:
6216 {
6217 name="black";
6218 if (image->storage_class == PseudoClass)
6219 name="index";
6220 break;
6221 }
6222 case IndexPixelChannel:
6223 {
6224 name="index";
6225 break;
6226 }
6227 case AlphaPixelChannel:
6228 {
6229 name="alpha";
6230 break;
6231 }
6232 case ReadMaskPixelChannel:
6233 {
6234 name="read-mask";
6235 break;
6236 }
6237 case WriteMaskPixelChannel:
6238 {
6239 name="write-mask";
6240 break;
6241 }
6242 case CompositeMaskPixelChannel:
6243 {
6244 name="composite-mask";
6245 break;
6246 }
6247 case MetaPixelChannel:
6248 {
6249 name="meta";
6250 break;
6251 }
6252 default:
6253 name="undefined";
6254 }
6255 if (image->colorspace == UndefinedColorspace)
6256 {
6257 (void) FormatLocaleString(channel_name,MagickPathExtent,"%.20g",
6258 (double) channel);
6259 name=(const char *) channel_name;
6260 }
6261 *traits='\0';
6262 if ((GetPixelChannelTraits(image,channel) & UpdatePixelTrait) != 0)
6263 (void) ConcatenateMagickString(traits,"update,",MagickPathExtent);
6264 if ((GetPixelChannelTraits(image,channel) & BlendPixelTrait) != 0)
6265 (void) ConcatenateMagickString(traits,"blend,",MagickPathExtent);
6266 if ((GetPixelChannelTraits(image,channel) & CopyPixelTrait) != 0)
6267 (void) ConcatenateMagickString(traits,"copy,",MagickPathExtent);
6268 if (*traits == '\0')
6269 (void) ConcatenateMagickString(traits,"undefined,",MagickPathExtent);
6270 traits[strlen(traits)-1]='\0';
6271 (void) LogMagickEvent(PixelEvent,GetMagickModule()," %.20g: %s (%s)",
6272 (double) i,name,traits);
6273 }
6274 }
6275
SetPixelChannelMask(Image * image,const ChannelType channel_mask)6276 MagickExport ChannelType SetPixelChannelMask(Image *image,
6277 const ChannelType channel_mask)
6278 {
6279 #define GetChannelBit(mask,bit) (((size_t) (mask) >> (size_t) (bit)) & 0x01)
6280
6281 ChannelType
6282 mask;
6283
6284 register ssize_t
6285 i;
6286
6287 assert(image != (Image *) NULL);
6288 assert(image->signature == MagickCoreSignature);
6289 if (image->debug != MagickFalse)
6290 (void) LogMagickEvent(PixelEvent,GetMagickModule(),"%s[%08x]",
6291 image->filename,channel_mask);
6292 mask=image->channel_mask;
6293 image->channel_mask=channel_mask;
6294 for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
6295 {
6296 PixelChannel channel = GetPixelChannelChannel(image,i);
6297 if (GetChannelBit(channel_mask,channel) == 0)
6298 {
6299 SetPixelChannelTraits(image,channel,CopyPixelTrait);
6300 continue;
6301 }
6302 if (channel == AlphaPixelChannel)
6303 {
6304 if ((image->alpha_trait & CopyPixelTrait) != 0)
6305 {
6306 SetPixelChannelTraits(image,channel,CopyPixelTrait);
6307 continue;
6308 }
6309 SetPixelChannelTraits(image,channel,UpdatePixelTrait);
6310 continue;
6311 }
6312 if (image->alpha_trait != UndefinedPixelTrait)
6313 {
6314 SetPixelChannelTraits(image,channel,(const PixelTrait)
6315 (UpdatePixelTrait | BlendPixelTrait));
6316 continue;
6317 }
6318 SetPixelChannelTraits(image,channel,UpdatePixelTrait);
6319 }
6320 if (image->storage_class == PseudoClass)
6321 SetPixelChannelTraits(image,IndexPixelChannel,CopyPixelTrait);
6322 if ((image->channels & ReadMaskChannel) != 0)
6323 SetPixelChannelTraits(image,ReadMaskPixelChannel,CopyPixelTrait);
6324 if ((image->channels & WriteMaskChannel) != 0)
6325 SetPixelChannelTraits(image,WriteMaskPixelChannel,CopyPixelTrait);
6326 if ((image->channels & CompositeMaskChannel) != 0)
6327 SetPixelChannelTraits(image,CompositeMaskPixelChannel,CopyPixelTrait);
6328 if (image->debug != MagickFalse)
6329 LogPixelChannels(image);
6330 return(mask);
6331 }
6332
6333 /*
6334 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6335 % %
6336 % %
6337 % %
6338 % S e t P i x e l M e t a C h a n n e l s %
6339 % %
6340 % %
6341 % %
6342 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6343 %
6344 % SetPixelMetaChannels() sets the image meta channels.
6345 %
6346 % The format of the SetPixelMetaChannels method is:
6347 %
6348 % MagickBooleanType SetPixelMetaChannels(Image *image,
6349 % const size_t number_meta_channels,ExceptionInfo *exception)
6350 %
6351 % A description of each parameter follows:
6352 %
6353 % o image: the image.
6354 %
6355 % o number_meta_channels: the number of meta channels.
6356 %
6357 % o exception: return any errors or warnings in this structure.
6358 %
6359 */
SetPixelMetaChannels(Image * image,const size_t number_meta_channels,ExceptionInfo * exception)6360 MagickExport MagickBooleanType SetPixelMetaChannels(Image *image,
6361 const size_t number_meta_channels,ExceptionInfo *exception)
6362 {
6363 image->number_meta_channels=number_meta_channels;
6364 InitializePixelChannelMap(image);
6365 return(SyncImagePixelCache(image,exception));
6366 }
6367