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-2021 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 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 *) AcquireMagickMemory(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) != MagickFalse)
222 ConvertRGBToCMYK(destination);
223 }
224 else
225 if (destination->colorspace == CMYKColorspace)
226 {
227 if (IssRGBCompatibleColorspace(image->colorspace) != MagickFalse)
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 const Quantum
514 *magick_restrict p;
515
516 ssize_t
517 x;
518
519 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 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 const Quantum
721 *magick_restrict p;
722
723 double
724 *magick_restrict q;
725
726 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 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 const Quantum
929 *magick_restrict p;
930
931 float
932 *magick_restrict q;
933
934 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 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 const Quantum
1136 *magick_restrict p;
1137
1138 ssize_t
1139 x;
1140
1141 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 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 const Quantum
1343 *magick_restrict p;
1344
1345 ssize_t
1346 x;
1347
1348 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 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 const Quantum
1552 *magick_restrict p;
1553
1554 Quantum
1555 *magick_restrict q;
1556
1557 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 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 const Quantum
1762 *magick_restrict p;
1763
1764 ssize_t
1765 x;
1766
1767 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 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 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 if (image->number_channels == 1)
2369 return(red);
2370 green=(MagickRealType) GetPixelGreen(image,pixel);
2371 blue=(MagickRealType) GetPixelBlue(image,pixel);
2372 switch (image->intensity)
2373 {
2374 case AveragePixelIntensityMethod:
2375 {
2376 intensity=(red+green+blue)/3.0;
2377 break;
2378 }
2379 case BrightnessPixelIntensityMethod:
2380 {
2381 intensity=MagickMax(MagickMax(red,green),blue);
2382 break;
2383 }
2384 case LightnessPixelIntensityMethod:
2385 {
2386 intensity=(MagickMin(MagickMin(red,green),blue)+
2387 MagickMax(MagickMax(red,green),blue))/2.0;
2388 break;
2389 }
2390 case MSPixelIntensityMethod:
2391 {
2392 intensity=(MagickRealType) (((double) red*red+green*green+blue*blue)/
2393 (3.0*QuantumRange));
2394 break;
2395 }
2396 case Rec601LumaPixelIntensityMethod:
2397 {
2398 if ((image->colorspace == RGBColorspace) ||
2399 (image->colorspace == LinearGRAYColorspace))
2400 {
2401 red=EncodePixelGamma(red);
2402 green=EncodePixelGamma(green);
2403 blue=EncodePixelGamma(blue);
2404 }
2405 intensity=0.298839*red+0.586811*green+0.114350*blue;
2406 break;
2407 }
2408 case Rec601LuminancePixelIntensityMethod:
2409 {
2410 if ((image->colorspace == sRGBColorspace) ||
2411 (image->colorspace == GRAYColorspace))
2412 {
2413 red=DecodePixelGamma(red);
2414 green=DecodePixelGamma(green);
2415 blue=DecodePixelGamma(blue);
2416 }
2417 intensity=0.298839*red+0.586811*green+0.114350*blue;
2418 break;
2419 }
2420 case Rec709LumaPixelIntensityMethod:
2421 default:
2422 {
2423 if ((image->colorspace == RGBColorspace) ||
2424 (image->colorspace == LinearGRAYColorspace))
2425 {
2426 red=EncodePixelGamma(red);
2427 green=EncodePixelGamma(green);
2428 blue=EncodePixelGamma(blue);
2429 }
2430 intensity=0.212656*red+0.715158*green+0.072186*blue;
2431 break;
2432 }
2433 case Rec709LuminancePixelIntensityMethod:
2434 {
2435 if ((image->colorspace == sRGBColorspace) ||
2436 (image->colorspace == GRAYColorspace))
2437 {
2438 red=DecodePixelGamma(red);
2439 green=DecodePixelGamma(green);
2440 blue=DecodePixelGamma(blue);
2441 }
2442 intensity=0.212656*red+0.715158*green+0.072186*blue;
2443 break;
2444 }
2445 case RMSPixelIntensityMethod:
2446 {
2447 intensity=(MagickRealType) (sqrt((double) red*red+green*green+blue*blue)/
2448 sqrt(3.0));
2449 break;
2450 }
2451 }
2452 return(intensity);
2453 }
2454
2455 /*
2456 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2457 % %
2458 % %
2459 % %
2460 % I m p o r t I m a g e P i x e l s %
2461 % %
2462 % %
2463 % %
2464 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2465 %
2466 % ImportImagePixels() accepts pixel data and stores in the image at the
2467 % location you specify. The method returns MagickTrue on success otherwise
2468 % MagickFalse if an error is encountered. The pixel data can be either char,
2469 % Quantum, short int, unsigned int, unsigned long long, float, or double in
2470 % the order specified by map.
2471 %
2472 % Suppose your want to upload the first scanline of a 640x480 image from
2473 % character data in red-green-blue order:
2474 %
2475 % ImportImagePixels(image,0,0,640,1,"RGB",CharPixel,pixels);
2476 %
2477 % The format of the ImportImagePixels method is:
2478 %
2479 % MagickBooleanType ImportImagePixels(Image *image,const ssize_t x,
2480 % const ssize_t y,const size_t width,const size_t height,
2481 % const char *map,const StorageType type,const void *pixels,
2482 % ExceptionInfo *exception)
2483 %
2484 % A description of each parameter follows:
2485 %
2486 % o image: the image.
2487 %
2488 % o x,y,width,height: These values define the perimeter
2489 % of a region of pixels you want to define.
2490 %
2491 % o map: This string reflects the expected ordering of the pixel array.
2492 % It can be any combination or order of R = red, G = green, B = blue,
2493 % A = alpha (0 is transparent), O = opacity (0 is opaque), C = cyan,
2494 % Y = yellow, M = magenta, K = black, I = intensity (for grayscale),
2495 % P = pad.
2496 %
2497 % o type: Define the data type of the pixels. Float and double types are
2498 % normalized to [0..1] otherwise [0..QuantumRange]. Choose from these
2499 % types: CharPixel (char *), DoublePixel (double *), FloatPixel (float *),
2500 % LongPixel (unsigned int *), LongLongPixel (unsigned long long *),
2501 % QuantumPixel (Quantum *), or ShortPixel (unsigned short *).
2502 %
2503 % o pixels: This array of values contain the pixel components as defined by
2504 % map and type. You must preallocate this array where the expected
2505 % length varies depending on the values of width, height, map, and type.
2506 %
2507 % o exception: return any errors or warnings in this structure.
2508 %
2509 */
2510
ImportCharPixel(Image * image,const RectangleInfo * roi,const char * magick_restrict map,const QuantumType * quantum_map,const void * pixels,ExceptionInfo * exception)2511 static MagickBooleanType ImportCharPixel(Image *image,const RectangleInfo *roi,
2512 const char *magick_restrict map,const QuantumType *quantum_map,
2513 const void *pixels,ExceptionInfo *exception)
2514 {
2515 const unsigned char
2516 *magick_restrict p;
2517
2518 Quantum
2519 *magick_restrict q;
2520
2521 ssize_t
2522 x;
2523
2524 size_t
2525 length;
2526
2527 ssize_t
2528 y;
2529
2530 p=(const unsigned char *) pixels;
2531 if (LocaleCompare(map,"BGR") == 0)
2532 {
2533 for (y=0; y < (ssize_t) roi->height; y++)
2534 {
2535 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
2536 if (q == (Quantum *) NULL)
2537 break;
2538 for (x=0; x < (ssize_t) roi->width; x++)
2539 {
2540 SetPixelBlue(image,ScaleCharToQuantum(*p++),q);
2541 SetPixelGreen(image,ScaleCharToQuantum(*p++),q);
2542 SetPixelRed(image,ScaleCharToQuantum(*p++),q);
2543 q+=GetPixelChannels(image);
2544 }
2545 if (SyncAuthenticPixels(image,exception) == MagickFalse)
2546 break;
2547 }
2548 return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
2549 }
2550 if (LocaleCompare(map,"BGRA") == 0)
2551 {
2552 for (y=0; y < (ssize_t) roi->height; y++)
2553 {
2554 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
2555 if (q == (Quantum *) NULL)
2556 break;
2557 for (x=0; x < (ssize_t) roi->width; x++)
2558 {
2559 SetPixelBlue(image,ScaleCharToQuantum(*p++),q);
2560 SetPixelGreen(image,ScaleCharToQuantum(*p++),q);
2561 SetPixelRed(image,ScaleCharToQuantum(*p++),q);
2562 SetPixelAlpha(image,ScaleCharToQuantum(*p++),q);
2563 q+=GetPixelChannels(image);
2564 }
2565 if (SyncAuthenticPixels(image,exception) == MagickFalse)
2566 break;
2567 }
2568 return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
2569 }
2570 if (LocaleCompare(map,"BGRO") == 0)
2571 {
2572 for (y=0; y < (ssize_t) roi->height; y++)
2573 {
2574 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
2575 if (q == (Quantum *) NULL)
2576 break;
2577 for (x=0; x < (ssize_t) roi->width; x++)
2578 {
2579 SetPixelBlue(image,ScaleCharToQuantum(*p++),q);
2580 SetPixelGreen(image,ScaleCharToQuantum(*p++),q);
2581 SetPixelRed(image,ScaleCharToQuantum(*p++),q);
2582 SetPixelAlpha(image,ScaleCharToQuantum(*p++),q);
2583 q+=GetPixelChannels(image);
2584 }
2585 if (SyncAuthenticPixels(image,exception) == MagickFalse)
2586 break;
2587 }
2588 return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
2589 }
2590 if (LocaleCompare(map,"BGRP") == 0)
2591 {
2592 for (y=0; y < (ssize_t) roi->height; y++)
2593 {
2594 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
2595 if (q == (Quantum *) NULL)
2596 break;
2597 for (x=0; x < (ssize_t) roi->width; x++)
2598 {
2599 SetPixelBlue(image,ScaleCharToQuantum(*p++),q);
2600 SetPixelGreen(image,ScaleCharToQuantum(*p++),q);
2601 SetPixelRed(image,ScaleCharToQuantum(*p++),q);
2602 p++;
2603 q+=GetPixelChannels(image);
2604 }
2605 if (SyncAuthenticPixels(image,exception) == MagickFalse)
2606 break;
2607 }
2608 return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
2609 }
2610 if (LocaleCompare(map,"I") == 0)
2611 {
2612 for (y=0; y < (ssize_t) roi->height; y++)
2613 {
2614 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
2615 if (q == (Quantum *) NULL)
2616 break;
2617 for (x=0; x < (ssize_t) roi->width; x++)
2618 {
2619 SetPixelGray(image,ScaleCharToQuantum(*p++),q);
2620 q+=GetPixelChannels(image);
2621 }
2622 if (SyncAuthenticPixels(image,exception) == MagickFalse)
2623 break;
2624 }
2625 return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
2626 }
2627 if (LocaleCompare(map,"RGB") == 0)
2628 {
2629 for (y=0; y < (ssize_t) roi->height; y++)
2630 {
2631 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
2632 if (q == (Quantum *) NULL)
2633 break;
2634 for (x=0; x < (ssize_t) roi->width; x++)
2635 {
2636 SetPixelRed(image,ScaleCharToQuantum(*p++),q);
2637 SetPixelGreen(image,ScaleCharToQuantum(*p++),q);
2638 SetPixelBlue(image,ScaleCharToQuantum(*p++),q);
2639 q+=GetPixelChannels(image);
2640 }
2641 if (SyncAuthenticPixels(image,exception) == MagickFalse)
2642 break;
2643 }
2644 return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
2645 }
2646 if (LocaleCompare(map,"RGBA") == 0)
2647 {
2648 for (y=0; y < (ssize_t) roi->height; y++)
2649 {
2650 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
2651 if (q == (Quantum *) NULL)
2652 break;
2653 for (x=0; x < (ssize_t) roi->width; x++)
2654 {
2655 SetPixelRed(image,ScaleCharToQuantum(*p++),q);
2656 SetPixelGreen(image,ScaleCharToQuantum(*p++),q);
2657 SetPixelBlue(image,ScaleCharToQuantum(*p++),q);
2658 SetPixelAlpha(image,ScaleCharToQuantum(*p++),q);
2659 q+=GetPixelChannels(image);
2660 }
2661 if (SyncAuthenticPixels(image,exception) == MagickFalse)
2662 break;
2663 }
2664 return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
2665 }
2666 if (LocaleCompare(map,"RGBO") == 0)
2667 {
2668 for (y=0; y < (ssize_t) roi->height; y++)
2669 {
2670 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
2671 if (q == (Quantum *) NULL)
2672 break;
2673 for (x=0; x < (ssize_t) roi->width; x++)
2674 {
2675 SetPixelRed(image,ScaleCharToQuantum(*p++),q);
2676 SetPixelGreen(image,ScaleCharToQuantum(*p++),q);
2677 SetPixelBlue(image,ScaleCharToQuantum(*p++),q);
2678 SetPixelAlpha(image,ScaleCharToQuantum(*p++),q);
2679 q+=GetPixelChannels(image);
2680 }
2681 if (SyncAuthenticPixels(image,exception) == MagickFalse)
2682 break;
2683 }
2684 return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
2685 }
2686 if (LocaleCompare(map,"RGBP") == 0)
2687 {
2688 for (y=0; y < (ssize_t) roi->height; y++)
2689 {
2690 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
2691 if (q == (Quantum *) NULL)
2692 break;
2693 for (x=0; x < (ssize_t) roi->width; x++)
2694 {
2695 SetPixelRed(image,ScaleCharToQuantum(*p++),q);
2696 SetPixelGreen(image,ScaleCharToQuantum(*p++),q);
2697 SetPixelBlue(image,ScaleCharToQuantum(*p++),q);
2698 p++;
2699 q+=GetPixelChannels(image);
2700 }
2701 if (SyncAuthenticPixels(image,exception) == MagickFalse)
2702 break;
2703 }
2704 return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
2705 }
2706 length=strlen(map);
2707 for (y=0; y < (ssize_t) roi->height; y++)
2708 {
2709 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
2710 if (q == (Quantum *) NULL)
2711 break;
2712 for (x=0; x < (ssize_t) roi->width; x++)
2713 {
2714 ssize_t
2715 i;
2716
2717 for (i=0; i < (ssize_t) length; i++)
2718 {
2719 switch (quantum_map[i])
2720 {
2721 case RedQuantum:
2722 case CyanQuantum:
2723 {
2724 SetPixelRed(image,ScaleCharToQuantum(*p),q);
2725 break;
2726 }
2727 case GreenQuantum:
2728 case MagentaQuantum:
2729 {
2730 SetPixelGreen(image,ScaleCharToQuantum(*p),q);
2731 break;
2732 }
2733 case BlueQuantum:
2734 case YellowQuantum:
2735 {
2736 SetPixelBlue(image,ScaleCharToQuantum(*p),q);
2737 break;
2738 }
2739 case AlphaQuantum:
2740 {
2741 SetPixelAlpha(image,ScaleCharToQuantum(*p),q);
2742 break;
2743 }
2744 case OpacityQuantum:
2745 {
2746 SetPixelAlpha(image,ScaleCharToQuantum(*p),q);
2747 break;
2748 }
2749 case BlackQuantum:
2750 {
2751 SetPixelBlack(image,ScaleCharToQuantum(*p),q);
2752 break;
2753 }
2754 case IndexQuantum:
2755 {
2756 SetPixelGray(image,ScaleCharToQuantum(*p),q);
2757 break;
2758 }
2759 default:
2760 break;
2761 }
2762 p++;
2763 }
2764 q+=GetPixelChannels(image);
2765 }
2766 if (SyncAuthenticPixels(image,exception) == MagickFalse)
2767 break;
2768 }
2769 return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
2770 }
2771
ImportDoublePixel(Image * image,const RectangleInfo * roi,const char * magick_restrict map,const QuantumType * quantum_map,const void * pixels,ExceptionInfo * exception)2772 static MagickBooleanType ImportDoublePixel(Image *image,
2773 const RectangleInfo *roi,const char *magick_restrict map,
2774 const QuantumType *quantum_map,const void *pixels,ExceptionInfo *exception)
2775 {
2776 const double
2777 *magick_restrict p;
2778
2779 Quantum
2780 *magick_restrict q;
2781
2782 ssize_t
2783 x;
2784
2785 size_t
2786 length;
2787
2788 ssize_t
2789 y;
2790
2791 p=(const double *) pixels;
2792 if (LocaleCompare(map,"BGR") == 0)
2793 {
2794 for (y=0; y < (ssize_t) roi->height; y++)
2795 {
2796 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
2797 if (q == (Quantum *) NULL)
2798 break;
2799 for (x=0; x < (ssize_t) roi->width; x++)
2800 {
2801 SetPixelBlue(image,ClampToQuantum(QuantumRange*(*p)),q);
2802 p++;
2803 SetPixelGreen(image,ClampToQuantum(QuantumRange*(*p)),q);
2804 p++;
2805 SetPixelRed(image,ClampToQuantum(QuantumRange*(*p)),q);
2806 p++;
2807 q+=GetPixelChannels(image);
2808 }
2809 if (SyncAuthenticPixels(image,exception) == MagickFalse)
2810 break;
2811 }
2812 return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
2813 }
2814 if (LocaleCompare(map,"BGRA") == 0)
2815 {
2816 for (y=0; y < (ssize_t) roi->height; y++)
2817 {
2818 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
2819 if (q == (Quantum *) NULL)
2820 break;
2821 for (x=0; x < (ssize_t) roi->width; x++)
2822 {
2823 SetPixelBlue(image,ClampToQuantum(QuantumRange*(*p)),q);
2824 p++;
2825 SetPixelGreen(image,ClampToQuantum(QuantumRange*(*p)),q);
2826 p++;
2827 SetPixelRed(image,ClampToQuantum(QuantumRange*(*p)),q);
2828 p++;
2829 SetPixelAlpha(image,ClampToQuantum(QuantumRange*(*p)),q);
2830 p++;
2831 q+=GetPixelChannels(image);
2832 }
2833 if (SyncAuthenticPixels(image,exception) == MagickFalse)
2834 break;
2835 }
2836 return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
2837 }
2838 if (LocaleCompare(map,"BGRP") == 0)
2839 {
2840 for (y=0; y < (ssize_t) roi->height; y++)
2841 {
2842 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
2843 if (q == (Quantum *) NULL)
2844 break;
2845 for (x=0; x < (ssize_t) roi->width; x++)
2846 {
2847 SetPixelBlue(image,ClampToQuantum(QuantumRange*(*p)),q);
2848 p++;
2849 SetPixelGreen(image,ClampToQuantum(QuantumRange*(*p)),q);
2850 p++;
2851 SetPixelRed(image,ClampToQuantum(QuantumRange*(*p)),q);
2852 p++;
2853 p++;
2854 q+=GetPixelChannels(image);
2855 }
2856 if (SyncAuthenticPixels(image,exception) == MagickFalse)
2857 break;
2858 }
2859 return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
2860 }
2861 if (LocaleCompare(map,"I") == 0)
2862 {
2863 for (y=0; y < (ssize_t) roi->height; y++)
2864 {
2865 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
2866 if (q == (Quantum *) NULL)
2867 break;
2868 for (x=0; x < (ssize_t) roi->width; x++)
2869 {
2870 SetPixelGray(image,ClampToQuantum(QuantumRange*(*p)),q);
2871 p++;
2872 q+=GetPixelChannels(image);
2873 }
2874 if (SyncAuthenticPixels(image,exception) == MagickFalse)
2875 break;
2876 }
2877 return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
2878 }
2879 if (LocaleCompare(map,"RGB") == 0)
2880 {
2881 for (y=0; y < (ssize_t) roi->height; y++)
2882 {
2883 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
2884 if (q == (Quantum *) NULL)
2885 break;
2886 for (x=0; x < (ssize_t) roi->width; x++)
2887 {
2888 SetPixelRed(image,ClampToQuantum(QuantumRange*(*p)),q);
2889 p++;
2890 SetPixelGreen(image,ClampToQuantum(QuantumRange*(*p)),q);
2891 p++;
2892 SetPixelBlue(image,ClampToQuantum(QuantumRange*(*p)),q);
2893 p++;
2894 q+=GetPixelChannels(image);
2895 }
2896 if (SyncAuthenticPixels(image,exception) == MagickFalse)
2897 break;
2898 }
2899 return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
2900 }
2901 if (LocaleCompare(map,"RGBA") == 0)
2902 {
2903 for (y=0; y < (ssize_t) roi->height; y++)
2904 {
2905 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
2906 if (q == (Quantum *) NULL)
2907 break;
2908 for (x=0; x < (ssize_t) roi->width; x++)
2909 {
2910 SetPixelRed(image,ClampToQuantum(QuantumRange*(*p)),q);
2911 p++;
2912 SetPixelGreen(image,ClampToQuantum(QuantumRange*(*p)),q);
2913 p++;
2914 SetPixelBlue(image,ClampToQuantum(QuantumRange*(*p)),q);
2915 p++;
2916 SetPixelAlpha(image,ClampToQuantum(QuantumRange*(*p)),q);
2917 p++;
2918 q+=GetPixelChannels(image);
2919 }
2920 if (SyncAuthenticPixels(image,exception) == MagickFalse)
2921 break;
2922 }
2923 return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
2924 }
2925 if (LocaleCompare(map,"RGBP") == 0)
2926 {
2927 for (y=0; y < (ssize_t) roi->height; y++)
2928 {
2929 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
2930 if (q == (Quantum *) NULL)
2931 break;
2932 for (x=0; x < (ssize_t) roi->width; x++)
2933 {
2934 SetPixelRed(image,ClampToQuantum(QuantumRange*(*p)),q);
2935 p++;
2936 SetPixelGreen(image,ClampToQuantum(QuantumRange*(*p)),q);
2937 p++;
2938 SetPixelBlue(image,ClampToQuantum(QuantumRange*(*p)),q);
2939 p++;
2940 q+=GetPixelChannels(image);
2941 }
2942 if (SyncAuthenticPixels(image,exception) == MagickFalse)
2943 break;
2944 }
2945 return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
2946 }
2947 length=strlen(map);
2948 for (y=0; y < (ssize_t) roi->height; y++)
2949 {
2950 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
2951 if (q == (Quantum *) NULL)
2952 break;
2953 for (x=0; x < (ssize_t) roi->width; x++)
2954 {
2955 ssize_t
2956 i;
2957
2958 for (i=0; i < (ssize_t) length; i++)
2959 {
2960 switch (quantum_map[i])
2961 {
2962 case RedQuantum:
2963 case CyanQuantum:
2964 {
2965 SetPixelRed(image,ClampToQuantum(QuantumRange*(*p)),q);
2966 break;
2967 }
2968 case GreenQuantum:
2969 case MagentaQuantum:
2970 {
2971 SetPixelGreen(image,ClampToQuantum(QuantumRange*(*p)),q);
2972 break;
2973 }
2974 case BlueQuantum:
2975 case YellowQuantum:
2976 {
2977 SetPixelBlue(image,ClampToQuantum(QuantumRange*(*p)),q);
2978 break;
2979 }
2980 case AlphaQuantum:
2981 {
2982 SetPixelAlpha(image,ClampToQuantum(QuantumRange*(*p)),q);
2983 break;
2984 }
2985 case OpacityQuantum:
2986 {
2987 SetPixelAlpha(image,ClampToQuantum(QuantumRange*(*p)),q);
2988 break;
2989 }
2990 case BlackQuantum:
2991 {
2992 SetPixelBlack(image,ClampToQuantum(QuantumRange*(*p)),q);
2993 break;
2994 }
2995 case IndexQuantum:
2996 {
2997 SetPixelGray(image,ClampToQuantum(QuantumRange*(*p)),q);
2998 break;
2999 }
3000 default:
3001 break;
3002 }
3003 p++;
3004 }
3005 q+=GetPixelChannels(image);
3006 }
3007 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3008 break;
3009 }
3010 return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
3011 }
3012
ImportFloatPixel(Image * image,const RectangleInfo * roi,const char * magick_restrict map,const QuantumType * quantum_map,const void * pixels,ExceptionInfo * exception)3013 static MagickBooleanType ImportFloatPixel(Image *image,const RectangleInfo *roi,
3014 const char *magick_restrict map,const QuantumType *quantum_map,
3015 const void *pixels,ExceptionInfo *exception)
3016 {
3017 const float
3018 *magick_restrict p;
3019
3020 Quantum
3021 *magick_restrict q;
3022
3023 ssize_t
3024 x;
3025
3026 size_t
3027 length;
3028
3029 ssize_t
3030 y;
3031
3032 p=(const float *) pixels;
3033 if (LocaleCompare(map,"BGR") == 0)
3034 {
3035 for (y=0; y < (ssize_t) roi->height; y++)
3036 {
3037 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
3038 if (q == (Quantum *) NULL)
3039 break;
3040 for (x=0; x < (ssize_t) roi->width; x++)
3041 {
3042 SetPixelBlue(image,ClampToQuantum(QuantumRange*(*p)),q);
3043 p++;
3044 SetPixelGreen(image,ClampToQuantum(QuantumRange*(*p)),q);
3045 p++;
3046 SetPixelRed(image,ClampToQuantum(QuantumRange*(*p)),q);
3047 p++;
3048 q+=GetPixelChannels(image);
3049 }
3050 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3051 break;
3052 }
3053 return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
3054 }
3055 if (LocaleCompare(map,"BGRA") == 0)
3056 {
3057 for (y=0; y < (ssize_t) roi->height; y++)
3058 {
3059 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
3060 if (q == (Quantum *) NULL)
3061 break;
3062 for (x=0; x < (ssize_t) roi->width; x++)
3063 {
3064 SetPixelBlue(image,ClampToQuantum(QuantumRange*(*p)),q);
3065 p++;
3066 SetPixelGreen(image,ClampToQuantum(QuantumRange*(*p)),q);
3067 p++;
3068 SetPixelRed(image,ClampToQuantum(QuantumRange*(*p)),q);
3069 p++;
3070 SetPixelAlpha(image,ClampToQuantum(QuantumRange*(*p)),q);
3071 p++;
3072 q+=GetPixelChannels(image);
3073 }
3074 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3075 break;
3076 }
3077 return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
3078 }
3079 if (LocaleCompare(map,"BGRP") == 0)
3080 {
3081 for (y=0; y < (ssize_t) roi->height; y++)
3082 {
3083 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
3084 if (q == (Quantum *) NULL)
3085 break;
3086 for (x=0; x < (ssize_t) roi->width; x++)
3087 {
3088 SetPixelBlue(image,ClampToQuantum(QuantumRange*(*p)),q);
3089 p++;
3090 SetPixelGreen(image,ClampToQuantum(QuantumRange*(*p)),q);
3091 p++;
3092 SetPixelRed(image,ClampToQuantum(QuantumRange*(*p)),q);
3093 p++;
3094 p++;
3095 q+=GetPixelChannels(image);
3096 }
3097 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3098 break;
3099 }
3100 return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
3101 }
3102 if (LocaleCompare(map,"I") == 0)
3103 {
3104 for (y=0; y < (ssize_t) roi->height; y++)
3105 {
3106 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
3107 if (q == (Quantum *) NULL)
3108 break;
3109 for (x=0; x < (ssize_t) roi->width; x++)
3110 {
3111 SetPixelGray(image,ClampToQuantum(QuantumRange*(*p)),q);
3112 p++;
3113 q+=GetPixelChannels(image);
3114 }
3115 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3116 break;
3117 }
3118 return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
3119 }
3120 if (LocaleCompare(map,"RGB") == 0)
3121 {
3122 for (y=0; y < (ssize_t) roi->height; y++)
3123 {
3124 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
3125 if (q == (Quantum *) NULL)
3126 break;
3127 for (x=0; x < (ssize_t) roi->width; x++)
3128 {
3129 SetPixelRed(image,ClampToQuantum(QuantumRange*(*p)),q);
3130 p++;
3131 SetPixelGreen(image,ClampToQuantum(QuantumRange*(*p)),q);
3132 p++;
3133 SetPixelBlue(image,ClampToQuantum(QuantumRange*(*p)),q);
3134 p++;
3135 q+=GetPixelChannels(image);
3136 }
3137 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3138 break;
3139 }
3140 return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
3141 }
3142 if (LocaleCompare(map,"RGBA") == 0)
3143 {
3144 for (y=0; y < (ssize_t) roi->height; y++)
3145 {
3146 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
3147 if (q == (Quantum *) NULL)
3148 break;
3149 for (x=0; x < (ssize_t) roi->width; x++)
3150 {
3151 SetPixelRed(image,ClampToQuantum(QuantumRange*(*p)),q);
3152 p++;
3153 SetPixelGreen(image,ClampToQuantum(QuantumRange*(*p)),q);
3154 p++;
3155 SetPixelBlue(image,ClampToQuantum(QuantumRange*(*p)),q);
3156 p++;
3157 SetPixelAlpha(image,ClampToQuantum(QuantumRange*(*p)),q);
3158 p++;
3159 q+=GetPixelChannels(image);
3160 }
3161 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3162 break;
3163 }
3164 return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
3165 }
3166 if (LocaleCompare(map,"RGBP") == 0)
3167 {
3168 for (y=0; y < (ssize_t) roi->height; y++)
3169 {
3170 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
3171 if (q == (Quantum *) NULL)
3172 break;
3173 for (x=0; x < (ssize_t) roi->width; x++)
3174 {
3175 SetPixelRed(image,ClampToQuantum(QuantumRange*(*p)),q);
3176 p++;
3177 SetPixelGreen(image,ClampToQuantum(QuantumRange*(*p)),q);
3178 p++;
3179 SetPixelBlue(image,ClampToQuantum(QuantumRange*(*p)),q);
3180 p++;
3181 q+=GetPixelChannels(image);
3182 }
3183 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3184 break;
3185 }
3186 return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
3187 }
3188 length=strlen(map);
3189 for (y=0; y < (ssize_t) roi->height; y++)
3190 {
3191 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
3192 if (q == (Quantum *) NULL)
3193 break;
3194 for (x=0; x < (ssize_t) roi->width; x++)
3195 {
3196 ssize_t
3197 i;
3198
3199 for (i=0; i < (ssize_t) length; i++)
3200 {
3201 switch (quantum_map[i])
3202 {
3203 case RedQuantum:
3204 case CyanQuantum:
3205 {
3206 SetPixelRed(image,ClampToQuantum(QuantumRange*(*p)),q);
3207 break;
3208 }
3209 case GreenQuantum:
3210 case MagentaQuantum:
3211 {
3212 SetPixelGreen(image,ClampToQuantum(QuantumRange*(*p)),q);
3213 break;
3214 }
3215 case BlueQuantum:
3216 case YellowQuantum:
3217 {
3218 SetPixelBlue(image,ClampToQuantum(QuantumRange*(*p)),q);
3219 break;
3220 }
3221 case AlphaQuantum:
3222 {
3223 SetPixelAlpha(image,ClampToQuantum(QuantumRange*(*p)),q);
3224 break;
3225 }
3226 case OpacityQuantum:
3227 {
3228 SetPixelAlpha(image,ClampToQuantum(QuantumRange*(*p)),q);
3229 break;
3230 }
3231 case BlackQuantum:
3232 {
3233 SetPixelBlack(image,ClampToQuantum(QuantumRange*(*p)),q);
3234 break;
3235 }
3236 case IndexQuantum:
3237 {
3238 SetPixelGray(image,ClampToQuantum(QuantumRange*(*p)),q);
3239 break;
3240 }
3241 default:
3242 break;
3243 }
3244 p++;
3245 }
3246 q+=GetPixelChannels(image);
3247 }
3248 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3249 break;
3250 }
3251 return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
3252 }
3253
ImportLongPixel(Image * image,const RectangleInfo * roi,const char * magick_restrict map,const QuantumType * quantum_map,const void * pixels,ExceptionInfo * exception)3254 static MagickBooleanType ImportLongPixel(Image *image,const RectangleInfo *roi,
3255 const char *magick_restrict map,const QuantumType *quantum_map,
3256 const void *pixels,ExceptionInfo *exception)
3257 {
3258 const unsigned int
3259 *magick_restrict p;
3260
3261 Quantum
3262 *magick_restrict q;
3263
3264 ssize_t
3265 x;
3266
3267 size_t
3268 length;
3269
3270 ssize_t
3271 y;
3272
3273 p=(const unsigned int *) pixels;
3274 if (LocaleCompare(map,"BGR") == 0)
3275 {
3276 for (y=0; y < (ssize_t) roi->height; y++)
3277 {
3278 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
3279 if (q == (Quantum *) NULL)
3280 break;
3281 for (x=0; x < (ssize_t) roi->width; x++)
3282 {
3283 SetPixelBlue(image,ScaleLongToQuantum(*p++),q);
3284 SetPixelGreen(image,ScaleLongToQuantum(*p++),q);
3285 SetPixelRed(image,ScaleLongToQuantum(*p++),q);
3286 q+=GetPixelChannels(image);
3287 }
3288 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3289 break;
3290 }
3291 return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
3292 }
3293 if (LocaleCompare(map,"BGRA") == 0)
3294 {
3295 for (y=0; y < (ssize_t) roi->height; y++)
3296 {
3297 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
3298 if (q == (Quantum *) NULL)
3299 break;
3300 for (x=0; x < (ssize_t) roi->width; x++)
3301 {
3302 SetPixelBlue(image,ScaleLongToQuantum(*p++),q);
3303 SetPixelGreen(image,ScaleLongToQuantum(*p++),q);
3304 SetPixelRed(image,ScaleLongToQuantum(*p++),q);
3305 SetPixelAlpha(image,ScaleLongToQuantum(*p++),q);
3306 q+=GetPixelChannels(image);
3307 }
3308 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3309 break;
3310 }
3311 return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
3312 }
3313 if (LocaleCompare(map,"BGRP") == 0)
3314 {
3315 for (y=0; y < (ssize_t) roi->height; y++)
3316 {
3317 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
3318 if (q == (Quantum *) NULL)
3319 break;
3320 for (x=0; x < (ssize_t) roi->width; x++)
3321 {
3322 SetPixelBlue(image,ScaleLongToQuantum(*p++),q);
3323 SetPixelGreen(image,ScaleLongToQuantum(*p++),q);
3324 SetPixelRed(image,ScaleLongToQuantum(*p++),q);
3325 p++;
3326 q+=GetPixelChannels(image);
3327 }
3328 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3329 break;
3330 }
3331 return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
3332 }
3333 if (LocaleCompare(map,"I") == 0)
3334 {
3335 for (y=0; y < (ssize_t) roi->height; y++)
3336 {
3337 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
3338 if (q == (Quantum *) NULL)
3339 break;
3340 for (x=0; x < (ssize_t) roi->width; x++)
3341 {
3342 SetPixelGray(image,ScaleLongToQuantum(*p++),q);
3343 q+=GetPixelChannels(image);
3344 }
3345 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3346 break;
3347 }
3348 return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
3349 }
3350 if (LocaleCompare(map,"RGB") == 0)
3351 {
3352 for (y=0; y < (ssize_t) roi->height; y++)
3353 {
3354 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
3355 if (q == (Quantum *) NULL)
3356 break;
3357 for (x=0; x < (ssize_t) roi->width; x++)
3358 {
3359 SetPixelRed(image,ScaleLongToQuantum(*p++),q);
3360 SetPixelGreen(image,ScaleLongToQuantum(*p++),q);
3361 SetPixelBlue(image,ScaleLongToQuantum(*p++),q);
3362 q+=GetPixelChannels(image);
3363 }
3364 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3365 break;
3366 }
3367 return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
3368 }
3369 if (LocaleCompare(map,"RGBA") == 0)
3370 {
3371 for (y=0; y < (ssize_t) roi->height; y++)
3372 {
3373 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
3374 if (q == (Quantum *) NULL)
3375 break;
3376 for (x=0; x < (ssize_t) roi->width; x++)
3377 {
3378 SetPixelRed(image,ScaleLongToQuantum(*p++),q);
3379 SetPixelGreen(image,ScaleLongToQuantum(*p++),q);
3380 SetPixelBlue(image,ScaleLongToQuantum(*p++),q);
3381 SetPixelAlpha(image,ScaleLongToQuantum(*p++),q);
3382 q+=GetPixelChannels(image);
3383 }
3384 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3385 break;
3386 }
3387 return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
3388 }
3389 if (LocaleCompare(map,"RGBP") == 0)
3390 {
3391 for (y=0; y < (ssize_t) roi->height; y++)
3392 {
3393 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
3394 if (q == (Quantum *) NULL)
3395 break;
3396 for (x=0; x < (ssize_t) roi->width; x++)
3397 {
3398 SetPixelRed(image,ScaleLongToQuantum(*p++),q);
3399 SetPixelGreen(image,ScaleLongToQuantum(*p++),q);
3400 SetPixelBlue(image,ScaleLongToQuantum(*p++),q);
3401 p++;
3402 q+=GetPixelChannels(image);
3403 }
3404 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3405 break;
3406 }
3407 return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
3408 }
3409 length=strlen(map);
3410 for (y=0; y < (ssize_t) roi->height; y++)
3411 {
3412 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
3413 if (q == (Quantum *) NULL)
3414 break;
3415 for (x=0; x < (ssize_t) roi->width; x++)
3416 {
3417 ssize_t
3418 i;
3419
3420 for (i=0; i < (ssize_t) length; i++)
3421 {
3422 switch (quantum_map[i])
3423 {
3424 case RedQuantum:
3425 case CyanQuantum:
3426 {
3427 SetPixelRed(image,ScaleLongToQuantum(*p),q);
3428 break;
3429 }
3430 case GreenQuantum:
3431 case MagentaQuantum:
3432 {
3433 SetPixelGreen(image,ScaleLongToQuantum(*p),q);
3434 break;
3435 }
3436 case BlueQuantum:
3437 case YellowQuantum:
3438 {
3439 SetPixelBlue(image,ScaleLongToQuantum(*p),q);
3440 break;
3441 }
3442 case AlphaQuantum:
3443 {
3444 SetPixelAlpha(image,ScaleLongToQuantum(*p),q);
3445 break;
3446 }
3447 case OpacityQuantum:
3448 {
3449 SetPixelAlpha(image,ScaleLongToQuantum(*p),q);
3450 break;
3451 }
3452 case BlackQuantum:
3453 {
3454 SetPixelBlack(image,ScaleLongToQuantum(*p),q);
3455 break;
3456 }
3457 case IndexQuantum:
3458 {
3459 SetPixelGray(image,ScaleLongToQuantum(*p),q);
3460 break;
3461 }
3462 default:
3463 break;
3464 }
3465 p++;
3466 }
3467 q+=GetPixelChannels(image);
3468 }
3469 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3470 break;
3471 }
3472 return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
3473 }
3474
ImportLongLongPixel(Image * image,const RectangleInfo * roi,const char * magick_restrict map,const QuantumType * quantum_map,const void * pixels,ExceptionInfo * exception)3475 static MagickBooleanType ImportLongLongPixel(Image *image,
3476 const RectangleInfo *roi,const char *magick_restrict map,
3477 const QuantumType *quantum_map,const void *pixels,ExceptionInfo *exception)
3478 {
3479 const MagickSizeType
3480 *magick_restrict p;
3481
3482 Quantum
3483 *magick_restrict q;
3484
3485 ssize_t
3486 x;
3487
3488 size_t
3489 length;
3490
3491 ssize_t
3492 y;
3493
3494 p=(const MagickSizeType *) pixels;
3495 if (LocaleCompare(map,"BGR") == 0)
3496 {
3497 for (y=0; y < (ssize_t) roi->height; y++)
3498 {
3499 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
3500 if (q == (Quantum *) NULL)
3501 break;
3502 for (x=0; x < (ssize_t) roi->width; x++)
3503 {
3504 SetPixelBlue(image,ScaleLongLongToQuantum(*p++),q);
3505 SetPixelGreen(image,ScaleLongLongToQuantum(*p++),q);
3506 SetPixelRed(image,ScaleLongLongToQuantum(*p++),q);
3507 q+=GetPixelChannels(image);
3508 }
3509 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3510 break;
3511 }
3512 return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
3513 }
3514 if (LocaleCompare(map,"BGRA") == 0)
3515 {
3516 for (y=0; y < (ssize_t) roi->height; y++)
3517 {
3518 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
3519 if (q == (Quantum *) NULL)
3520 break;
3521 for (x=0; x < (ssize_t) roi->width; x++)
3522 {
3523 SetPixelBlue(image,ScaleLongLongToQuantum(*p++),q);
3524 SetPixelGreen(image,ScaleLongLongToQuantum(*p++),q);
3525 SetPixelRed(image,ScaleLongLongToQuantum(*p++),q);
3526 SetPixelAlpha(image,ScaleLongLongToQuantum(*p++),q);
3527 q+=GetPixelChannels(image);
3528 }
3529 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3530 break;
3531 }
3532 return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
3533 }
3534 if (LocaleCompare(map,"BGRP") == 0)
3535 {
3536 for (y=0; y < (ssize_t) roi->height; y++)
3537 {
3538 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
3539 if (q == (Quantum *) NULL)
3540 break;
3541 for (x=0; x < (ssize_t) roi->width; x++)
3542 {
3543 SetPixelBlue(image,ScaleLongLongToQuantum(*p++),q);
3544 SetPixelGreen(image,ScaleLongLongToQuantum(*p++),q);
3545 SetPixelRed(image,ScaleLongLongToQuantum(*p++),q);
3546 p++;
3547 q+=GetPixelChannels(image);
3548 }
3549 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3550 break;
3551 }
3552 return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
3553 }
3554 if (LocaleCompare(map,"I") == 0)
3555 {
3556 for (y=0; y < (ssize_t) roi->height; y++)
3557 {
3558 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
3559 if (q == (Quantum *) NULL)
3560 break;
3561 for (x=0; x < (ssize_t) roi->width; x++)
3562 {
3563 SetPixelGray(image,ScaleLongLongToQuantum(*p++),q);
3564 q+=GetPixelChannels(image);
3565 }
3566 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3567 break;
3568 }
3569 return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
3570 }
3571 if (LocaleCompare(map,"RGB") == 0)
3572 {
3573 for (y=0; y < (ssize_t) roi->height; y++)
3574 {
3575 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
3576 if (q == (Quantum *) NULL)
3577 break;
3578 for (x=0; x < (ssize_t) roi->width; x++)
3579 {
3580 SetPixelRed(image,ScaleLongLongToQuantum(*p++),q);
3581 SetPixelGreen(image,ScaleLongLongToQuantum(*p++),q);
3582 SetPixelBlue(image,ScaleLongLongToQuantum(*p++),q);
3583 q+=GetPixelChannels(image);
3584 }
3585 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3586 break;
3587 }
3588 return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
3589 }
3590 if (LocaleCompare(map,"RGBA") == 0)
3591 {
3592 for (y=0; y < (ssize_t) roi->height; y++)
3593 {
3594 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
3595 if (q == (Quantum *) NULL)
3596 break;
3597 for (x=0; x < (ssize_t) roi->width; x++)
3598 {
3599 SetPixelRed(image,ScaleLongLongToQuantum(*p++),q);
3600 SetPixelGreen(image,ScaleLongLongToQuantum(*p++),q);
3601 SetPixelBlue(image,ScaleLongLongToQuantum(*p++),q);
3602 SetPixelAlpha(image,ScaleLongLongToQuantum(*p++),q);
3603 q+=GetPixelChannels(image);
3604 }
3605 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3606 break;
3607 }
3608 return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
3609 }
3610 if (LocaleCompare(map,"RGBP") == 0)
3611 {
3612 for (y=0; y < (ssize_t) roi->height; y++)
3613 {
3614 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
3615 if (q == (Quantum *) NULL)
3616 break;
3617 for (x=0; x < (ssize_t) roi->width; x++)
3618 {
3619 SetPixelRed(image,ScaleLongLongToQuantum(*p++),q);
3620 SetPixelGreen(image,ScaleLongLongToQuantum(*p++),q);
3621 SetPixelBlue(image,ScaleLongLongToQuantum(*p++),q);
3622 p++;
3623 q+=GetPixelChannels(image);
3624 }
3625 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3626 break;
3627 }
3628 return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
3629 }
3630 length=strlen(map);
3631 for (y=0; y < (ssize_t) roi->height; y++)
3632 {
3633 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
3634 if (q == (Quantum *) NULL)
3635 break;
3636 for (x=0; x < (ssize_t) roi->width; x++)
3637 {
3638 ssize_t
3639 i;
3640
3641 for (i=0; i < (ssize_t) length; i++)
3642 {
3643 switch (quantum_map[i])
3644 {
3645 case RedQuantum:
3646 case CyanQuantum:
3647 {
3648 SetPixelRed(image,ScaleLongLongToQuantum(*p),q);
3649 break;
3650 }
3651 case GreenQuantum:
3652 case MagentaQuantum:
3653 {
3654 SetPixelGreen(image,ScaleLongLongToQuantum(*p),q);
3655 break;
3656 }
3657 case BlueQuantum:
3658 case YellowQuantum:
3659 {
3660 SetPixelBlue(image,ScaleLongLongToQuantum(*p),q);
3661 break;
3662 }
3663 case AlphaQuantum:
3664 {
3665 SetPixelAlpha(image,ScaleLongLongToQuantum(*p),q);
3666 break;
3667 }
3668 case OpacityQuantum:
3669 {
3670 SetPixelAlpha(image,ScaleLongLongToQuantum(*p),q);
3671 break;
3672 }
3673 case BlackQuantum:
3674 {
3675 SetPixelBlack(image,ScaleLongLongToQuantum(*p),q);
3676 break;
3677 }
3678 case IndexQuantum:
3679 {
3680 SetPixelGray(image,ScaleLongLongToQuantum(*p),q);
3681 break;
3682 }
3683 default:
3684 break;
3685 }
3686 p++;
3687 }
3688 q+=GetPixelChannels(image);
3689 }
3690 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3691 break;
3692 }
3693 return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
3694 }
3695
ImportQuantumPixel(Image * image,const RectangleInfo * roi,const char * magick_restrict map,const QuantumType * quantum_map,const void * pixels,ExceptionInfo * exception)3696 static MagickBooleanType ImportQuantumPixel(Image *image,
3697 const RectangleInfo *roi,const char *magick_restrict map,
3698 const QuantumType *quantum_map,const void *pixels,ExceptionInfo *exception)
3699 {
3700 const Quantum
3701 *magick_restrict p;
3702
3703 Quantum
3704 *magick_restrict q;
3705
3706 ssize_t
3707 x;
3708
3709 size_t
3710 length;
3711
3712 ssize_t
3713 y;
3714
3715 p=(const Quantum *) pixels;
3716 if (LocaleCompare(map,"BGR") == 0)
3717 {
3718 for (y=0; y < (ssize_t) roi->height; y++)
3719 {
3720 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
3721 if (q == (Quantum *) NULL)
3722 break;
3723 for (x=0; x < (ssize_t) roi->width; x++)
3724 {
3725 SetPixelBlue(image,*p++,q);
3726 SetPixelGreen(image,*p++,q);
3727 SetPixelRed(image,*p++,q);
3728 q+=GetPixelChannels(image);
3729 }
3730 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3731 break;
3732 }
3733 return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
3734 }
3735 if (LocaleCompare(map,"BGRA") == 0)
3736 {
3737 for (y=0; y < (ssize_t) roi->height; y++)
3738 {
3739 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
3740 if (q == (Quantum *) NULL)
3741 break;
3742 for (x=0; x < (ssize_t) roi->width; x++)
3743 {
3744 SetPixelBlue(image,*p++,q);
3745 SetPixelGreen(image,*p++,q);
3746 SetPixelRed(image,*p++,q);
3747 SetPixelAlpha(image,*p++,q);
3748 q+=GetPixelChannels(image);
3749 }
3750 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3751 break;
3752 }
3753 return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
3754 }
3755 if (LocaleCompare(map,"BGRP") == 0)
3756 {
3757 for (y=0; y < (ssize_t) roi->height; y++)
3758 {
3759 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
3760 if (q == (Quantum *) NULL)
3761 break;
3762 for (x=0; x < (ssize_t) roi->width; x++)
3763 {
3764 SetPixelBlue(image,*p++,q);
3765 SetPixelGreen(image,*p++,q);
3766 SetPixelRed(image,*p++,q);
3767 p++;
3768 q+=GetPixelChannels(image);
3769 }
3770 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3771 break;
3772 }
3773 return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
3774 }
3775 if (LocaleCompare(map,"I") == 0)
3776 {
3777 for (y=0; y < (ssize_t) roi->height; y++)
3778 {
3779 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
3780 if (q == (Quantum *) NULL)
3781 break;
3782 for (x=0; x < (ssize_t) roi->width; x++)
3783 {
3784 SetPixelGray(image,*p++,q);
3785 q+=GetPixelChannels(image);
3786 }
3787 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3788 break;
3789 }
3790 return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
3791 }
3792 if (LocaleCompare(map,"RGB") == 0)
3793 {
3794 for (y=0; y < (ssize_t) roi->height; y++)
3795 {
3796 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
3797 if (q == (Quantum *) NULL)
3798 break;
3799 for (x=0; x < (ssize_t) roi->width; x++)
3800 {
3801 SetPixelRed(image,*p++,q);
3802 SetPixelGreen(image,*p++,q);
3803 SetPixelBlue(image,*p++,q);
3804 q+=GetPixelChannels(image);
3805 }
3806 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3807 break;
3808 }
3809 return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
3810 }
3811 if (LocaleCompare(map,"RGBA") == 0)
3812 {
3813 for (y=0; y < (ssize_t) roi->height; y++)
3814 {
3815 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
3816 if (q == (Quantum *) NULL)
3817 break;
3818 for (x=0; x < (ssize_t) roi->width; x++)
3819 {
3820 SetPixelRed(image,*p++,q);
3821 SetPixelGreen(image,*p++,q);
3822 SetPixelBlue(image,*p++,q);
3823 SetPixelAlpha(image,*p++,q);
3824 q+=GetPixelChannels(image);
3825 }
3826 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3827 break;
3828 }
3829 return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
3830 }
3831 if (LocaleCompare(map,"RGBP") == 0)
3832 {
3833 for (y=0; y < (ssize_t) roi->height; y++)
3834 {
3835 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
3836 if (q == (Quantum *) NULL)
3837 break;
3838 for (x=0; x < (ssize_t) roi->width; x++)
3839 {
3840 SetPixelRed(image,*p++,q);
3841 SetPixelGreen(image,*p++,q);
3842 SetPixelBlue(image,*p++,q);
3843 p++;
3844 q+=GetPixelChannels(image);
3845 }
3846 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3847 break;
3848 }
3849 return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
3850 }
3851 length=strlen(map);
3852 for (y=0; y < (ssize_t) roi->height; y++)
3853 {
3854 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
3855 if (q == (Quantum *) NULL)
3856 break;
3857 for (x=0; x < (ssize_t) roi->width; x++)
3858 {
3859 ssize_t
3860 i;
3861
3862 for (i=0; i < (ssize_t) length; i++)
3863 {
3864 switch (quantum_map[i])
3865 {
3866 case RedQuantum:
3867 case CyanQuantum:
3868 {
3869 SetPixelRed(image,*p,q);
3870 break;
3871 }
3872 case GreenQuantum:
3873 case MagentaQuantum:
3874 {
3875 SetPixelGreen(image,*p,q);
3876 break;
3877 }
3878 case BlueQuantum:
3879 case YellowQuantum:
3880 {
3881 SetPixelBlue(image,*p,q);
3882 break;
3883 }
3884 case AlphaQuantum:
3885 {
3886 SetPixelAlpha(image,*p,q);
3887 break;
3888 }
3889 case OpacityQuantum:
3890 {
3891 SetPixelAlpha(image,*p,q);
3892 break;
3893 }
3894 case BlackQuantum:
3895 {
3896 SetPixelBlack(image,*p,q);
3897 break;
3898 }
3899 case IndexQuantum:
3900 {
3901 SetPixelGray(image,*p,q);
3902 break;
3903 }
3904 default:
3905 break;
3906 }
3907 p++;
3908 }
3909 q+=GetPixelChannels(image);
3910 }
3911 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3912 break;
3913 }
3914 return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
3915 }
3916
ImportShortPixel(Image * image,const RectangleInfo * roi,const char * magick_restrict map,const QuantumType * quantum_map,const void * pixels,ExceptionInfo * exception)3917 static MagickBooleanType ImportShortPixel(Image *image,const RectangleInfo *roi,
3918 const char *magick_restrict map,const QuantumType *quantum_map,
3919 const void *pixels,ExceptionInfo *exception)
3920 {
3921 const unsigned short
3922 *magick_restrict p;
3923
3924 Quantum
3925 *magick_restrict q;
3926
3927 ssize_t
3928 x;
3929
3930 size_t
3931 length;
3932
3933 ssize_t
3934 y;
3935
3936 p=(const unsigned short *) pixels;
3937 if (LocaleCompare(map,"BGR") == 0)
3938 {
3939 for (y=0; y < (ssize_t) roi->height; y++)
3940 {
3941 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
3942 if (q == (Quantum *) NULL)
3943 break;
3944 for (x=0; x < (ssize_t) roi->width; x++)
3945 {
3946 SetPixelBlue(image,ScaleShortToQuantum(*p++),q);
3947 SetPixelGreen(image,ScaleShortToQuantum(*p++),q);
3948 SetPixelRed(image,ScaleShortToQuantum(*p++),q);
3949 q+=GetPixelChannels(image);
3950 }
3951 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3952 break;
3953 }
3954 return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
3955 }
3956 if (LocaleCompare(map,"BGRA") == 0)
3957 {
3958 for (y=0; y < (ssize_t) roi->height; y++)
3959 {
3960 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
3961 if (q == (Quantum *) NULL)
3962 break;
3963 for (x=0; x < (ssize_t) roi->width; x++)
3964 {
3965 SetPixelBlue(image,ScaleShortToQuantum(*p++),q);
3966 SetPixelGreen(image,ScaleShortToQuantum(*p++),q);
3967 SetPixelRed(image,ScaleShortToQuantum(*p++),q);
3968 SetPixelAlpha(image,ScaleShortToQuantum(*p++),q);
3969 q+=GetPixelChannels(image);
3970 }
3971 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3972 break;
3973 }
3974 return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
3975 }
3976 if (LocaleCompare(map,"BGRP") == 0)
3977 {
3978 for (y=0; y < (ssize_t) roi->height; y++)
3979 {
3980 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
3981 if (q == (Quantum *) NULL)
3982 break;
3983 for (x=0; x < (ssize_t) roi->width; x++)
3984 {
3985 SetPixelBlue(image,ScaleShortToQuantum(*p++),q);
3986 SetPixelGreen(image,ScaleShortToQuantum(*p++),q);
3987 SetPixelRed(image,ScaleShortToQuantum(*p++),q);
3988 p++;
3989 q+=GetPixelChannels(image);
3990 }
3991 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3992 break;
3993 }
3994 return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
3995 }
3996 if (LocaleCompare(map,"I") == 0)
3997 {
3998 for (y=0; y < (ssize_t) roi->height; y++)
3999 {
4000 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
4001 if (q == (Quantum *) NULL)
4002 break;
4003 for (x=0; x < (ssize_t) roi->width; x++)
4004 {
4005 SetPixelGray(image,ScaleShortToQuantum(*p++),q);
4006 q+=GetPixelChannels(image);
4007 }
4008 if (SyncAuthenticPixels(image,exception) == MagickFalse)
4009 break;
4010 }
4011 return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
4012 }
4013 if (LocaleCompare(map,"RGB") == 0)
4014 {
4015 for (y=0; y < (ssize_t) roi->height; y++)
4016 {
4017 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
4018 if (q == (Quantum *) NULL)
4019 break;
4020 for (x=0; x < (ssize_t) roi->width; x++)
4021 {
4022 SetPixelRed(image,ScaleShortToQuantum(*p++),q);
4023 SetPixelGreen(image,ScaleShortToQuantum(*p++),q);
4024 SetPixelBlue(image,ScaleShortToQuantum(*p++),q);
4025 q+=GetPixelChannels(image);
4026 }
4027 if (SyncAuthenticPixels(image,exception) == MagickFalse)
4028 break;
4029 }
4030 return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
4031 }
4032 if (LocaleCompare(map,"RGBA") == 0)
4033 {
4034 for (y=0; y < (ssize_t) roi->height; y++)
4035 {
4036 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
4037 if (q == (Quantum *) NULL)
4038 break;
4039 for (x=0; x < (ssize_t) roi->width; x++)
4040 {
4041 SetPixelRed(image,ScaleShortToQuantum(*p++),q);
4042 SetPixelGreen(image,ScaleShortToQuantum(*p++),q);
4043 SetPixelBlue(image,ScaleShortToQuantum(*p++),q);
4044 SetPixelAlpha(image,ScaleShortToQuantum(*p++),q);
4045 q+=GetPixelChannels(image);
4046 }
4047 if (SyncAuthenticPixels(image,exception) == MagickFalse)
4048 break;
4049 }
4050 return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
4051 }
4052 if (LocaleCompare(map,"RGBP") == 0)
4053 {
4054 for (y=0; y < (ssize_t) roi->height; y++)
4055 {
4056 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
4057 if (q == (Quantum *) NULL)
4058 break;
4059 for (x=0; x < (ssize_t) roi->width; x++)
4060 {
4061 SetPixelRed(image,ScaleShortToQuantum(*p++),q);
4062 SetPixelGreen(image,ScaleShortToQuantum(*p++),q);
4063 SetPixelBlue(image,ScaleShortToQuantum(*p++),q);
4064 p++;
4065 q+=GetPixelChannels(image);
4066 }
4067 if (SyncAuthenticPixels(image,exception) == MagickFalse)
4068 break;
4069 }
4070 return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
4071 }
4072 length=strlen(map);
4073 for (y=0; y < (ssize_t) roi->height; y++)
4074 {
4075 q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
4076 if (q == (Quantum *) NULL)
4077 break;
4078 for (x=0; x < (ssize_t) roi->width; x++)
4079 {
4080 ssize_t
4081 i;
4082
4083 for (i=0; i < (ssize_t) length; i++)
4084 {
4085 switch (quantum_map[i])
4086 {
4087 case RedQuantum:
4088 case CyanQuantum:
4089 {
4090 SetPixelRed(image,ScaleShortToQuantum(*p),q);
4091 break;
4092 }
4093 case GreenQuantum:
4094 case MagentaQuantum:
4095 {
4096 SetPixelGreen(image,ScaleShortToQuantum(*p),q);
4097 break;
4098 }
4099 case BlueQuantum:
4100 case YellowQuantum:
4101 {
4102 SetPixelBlue(image,ScaleShortToQuantum(*p),q);
4103 break;
4104 }
4105 case AlphaQuantum:
4106 {
4107 SetPixelAlpha(image,ScaleShortToQuantum(*p),q);
4108 break;
4109 }
4110 case OpacityQuantum:
4111 {
4112 SetPixelAlpha(image,ScaleShortToQuantum(*p),q);
4113 break;
4114 }
4115 case BlackQuantum:
4116 {
4117 SetPixelBlack(image,ScaleShortToQuantum(*p),q);
4118 break;
4119 }
4120 case IndexQuantum:
4121 {
4122 SetPixelGray(image,ScaleShortToQuantum(*p),q);
4123 break;
4124 }
4125 default:
4126 break;
4127 }
4128 p++;
4129 }
4130 q+=GetPixelChannels(image);
4131 }
4132 if (SyncAuthenticPixels(image,exception) == MagickFalse)
4133 break;
4134 }
4135 return(y < (ssize_t) roi->height ? MagickFalse : MagickTrue);
4136 }
4137
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)4138 MagickExport MagickBooleanType ImportImagePixels(Image *image,const ssize_t x,
4139 const ssize_t y,const size_t width,const size_t height,const char *map,
4140 const StorageType type,const void *pixels,ExceptionInfo *exception)
4141 {
4142 MagickBooleanType
4143 status;
4144
4145 QuantumType
4146 *quantum_map;
4147
4148 RectangleInfo
4149 roi;
4150
4151 ssize_t
4152 i;
4153
4154 size_t
4155 length;
4156
4157 /*
4158 Allocate image structure.
4159 */
4160 assert(image != (Image *) NULL);
4161 assert(image->signature == MagickCoreSignature);
4162 if (image->debug != MagickFalse)
4163 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
4164 length=strlen(map);
4165 quantum_map=(QuantumType *) AcquireQuantumMemory(length,sizeof(*quantum_map));
4166 if (quantum_map == (QuantumType *) NULL)
4167 ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
4168 image->filename);
4169 for (i=0; i < (ssize_t) length; i++)
4170 {
4171 switch (map[i])
4172 {
4173 case 'a':
4174 case 'A':
4175 {
4176 quantum_map[i]=AlphaQuantum;
4177 image->alpha_trait=BlendPixelTrait;
4178 break;
4179 }
4180 case 'B':
4181 case 'b':
4182 {
4183 quantum_map[i]=BlueQuantum;
4184 break;
4185 }
4186 case 'C':
4187 case 'c':
4188 {
4189 quantum_map[i]=CyanQuantum;
4190 (void) SetImageColorspace(image,CMYKColorspace,exception);
4191 break;
4192 }
4193 case 'g':
4194 case 'G':
4195 {
4196 quantum_map[i]=GreenQuantum;
4197 break;
4198 }
4199 case 'K':
4200 case 'k':
4201 {
4202 quantum_map[i]=BlackQuantum;
4203 (void) SetImageColorspace(image,CMYKColorspace,exception);
4204 break;
4205 }
4206 case 'I':
4207 case 'i':
4208 {
4209 quantum_map[i]=IndexQuantum;
4210 (void) SetImageColorspace(image,GRAYColorspace,exception);
4211 break;
4212 }
4213 case 'm':
4214 case 'M':
4215 {
4216 quantum_map[i]=MagentaQuantum;
4217 (void) SetImageColorspace(image,CMYKColorspace,exception);
4218 break;
4219 }
4220 case 'O':
4221 case 'o':
4222 {
4223 quantum_map[i]=OpacityQuantum;
4224 image->alpha_trait=BlendPixelTrait;
4225 break;
4226 }
4227 case 'P':
4228 case 'p':
4229 {
4230 quantum_map[i]=UndefinedQuantum;
4231 break;
4232 }
4233 case 'R':
4234 case 'r':
4235 {
4236 quantum_map[i]=RedQuantum;
4237 break;
4238 }
4239 case 'Y':
4240 case 'y':
4241 {
4242 quantum_map[i]=YellowQuantum;
4243 (void) SetImageColorspace(image,CMYKColorspace,exception);
4244 break;
4245 }
4246 default:
4247 {
4248 quantum_map=(QuantumType *) RelinquishMagickMemory(quantum_map);
4249 (void) ThrowMagickException(exception,GetMagickModule(),OptionError,
4250 "UnrecognizedPixelMap","`%s'",map);
4251 return(MagickFalse);
4252 }
4253 }
4254 }
4255 if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
4256 return(MagickFalse);
4257 /*
4258 Transfer the pixels from the pixel data to the image.
4259 */
4260 roi.width=width;
4261 roi.height=height;
4262 roi.x=x;
4263 roi.y=y;
4264 switch (type)
4265 {
4266 case CharPixel:
4267 {
4268 status=ImportCharPixel(image,&roi,map,quantum_map,pixels,exception);
4269 break;
4270 }
4271 case DoublePixel:
4272 {
4273 status=ImportDoublePixel(image,&roi,map,quantum_map,pixels,exception);
4274 break;
4275 }
4276 case FloatPixel:
4277 {
4278 status=ImportFloatPixel(image,&roi,map,quantum_map,pixels,exception);
4279 break;
4280 }
4281 case LongPixel:
4282 {
4283 status=ImportLongPixel(image,&roi,map,quantum_map,pixels,exception);
4284 break;
4285 }
4286 case LongLongPixel:
4287 {
4288 status=ImportLongLongPixel(image,&roi,map,quantum_map,pixels,exception);
4289 break;
4290 }
4291 case QuantumPixel:
4292 {
4293 status=ImportQuantumPixel(image,&roi,map,quantum_map,pixels,exception);
4294 break;
4295 }
4296 case ShortPixel:
4297 {
4298 status=ImportShortPixel(image,&roi,map,quantum_map,pixels,exception);
4299 break;
4300 }
4301 default:
4302 {
4303 (void) ThrowMagickException(exception,GetMagickModule(),OptionError,
4304 "UnrecognizedStorageType","`%d'",type);
4305 status=MagickFalse;
4306 }
4307 }
4308 quantum_map=(QuantumType *) RelinquishMagickMemory(quantum_map);
4309 return(status);
4310 }
4311
4312 /*
4313 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4314 % %
4315 % %
4316 % %
4317 + 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 %
4318 % %
4319 % %
4320 % %
4321 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4322 %
4323 % InitializePixelChannelMap() defines the standard pixel component map.
4324 %
4325 % The format of the InitializePixelChannelMap() method is:
4326 %
4327 % void InitializePixelChannelMap(Image *image)
4328 %
4329 % A description of each parameter follows:
4330 %
4331 % o image: the image.
4332 %
4333 */
InitializePixelChannelMap(Image * image)4334 MagickExport void InitializePixelChannelMap(Image *image)
4335 {
4336 PixelTrait
4337 trait;
4338
4339 ssize_t
4340 i;
4341
4342 ssize_t
4343 n;
4344
4345 assert(image != (Image *) NULL);
4346 assert(image->signature == MagickCoreSignature);
4347 (void) memset(image->channel_map,0,MaxPixelChannels*
4348 sizeof(*image->channel_map));
4349 trait=UpdatePixelTrait;
4350 if (image->alpha_trait != UndefinedPixelTrait)
4351 trait=(PixelTrait) (trait | BlendPixelTrait);
4352 n=0;
4353 if ((image->colorspace == LinearGRAYColorspace) ||
4354 (image->colorspace == GRAYColorspace))
4355 {
4356 SetPixelChannelAttributes(image,BluePixelChannel,trait,n);
4357 SetPixelChannelAttributes(image,GreenPixelChannel,trait,n);
4358 SetPixelChannelAttributes(image,RedPixelChannel,trait,n++);
4359 }
4360 else
4361 {
4362 SetPixelChannelAttributes(image,RedPixelChannel,trait,n++);
4363 SetPixelChannelAttributes(image,GreenPixelChannel,trait,n++);
4364 SetPixelChannelAttributes(image,BluePixelChannel,trait,n++);
4365 }
4366 if (image->colorspace == CMYKColorspace)
4367 SetPixelChannelAttributes(image,BlackPixelChannel,trait,n++);
4368 for (i=0; i < (ssize_t) image->number_meta_channels; i++)
4369 {
4370 SetPixelChannelAttributes(image,(PixelChannel) n,UpdatePixelTrait,n);
4371 n++;
4372 }
4373 if (image->alpha_trait != UndefinedPixelTrait)
4374 SetPixelChannelAttributes(image,AlphaPixelChannel,CopyPixelTrait,n++);
4375 if (image->storage_class == PseudoClass)
4376 SetPixelChannelAttributes(image,IndexPixelChannel,CopyPixelTrait,n++);
4377 if ((image->channels & ReadMaskChannel) != 0)
4378 SetPixelChannelAttributes(image,ReadMaskPixelChannel,CopyPixelTrait,n++);
4379 if ((image->channels & WriteMaskChannel) != 0)
4380 SetPixelChannelAttributes(image,WriteMaskPixelChannel,CopyPixelTrait,n++);
4381 if ((image->channels & CompositeMaskChannel) != 0)
4382 SetPixelChannelAttributes(image,CompositeMaskPixelChannel,CopyPixelTrait,
4383 n++);
4384 image->number_channels=(size_t) n;
4385 (void) SetPixelChannelMask(image,image->channel_mask);
4386 }
4387
4388 /*
4389 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4390 % %
4391 % %
4392 % %
4393 % I n t e r p o l a t e P i x e l C h a n n e l %
4394 % %
4395 % %
4396 % %
4397 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4398 %
4399 % InterpolatePixelChannel() applies a pixel interpolation method between a
4400 % floating point coordinate and the pixels surrounding that coordinate. No
4401 % pixel area resampling, or scaling of the result is performed.
4402 %
4403 % Interpolation is restricted to just the specified channel.
4404 %
4405 % The format of the InterpolatePixelChannel method is:
4406 %
4407 % MagickBooleanType InterpolatePixelChannel(
4408 % const Image *magick_restrict image,const CacheView *image_view,
4409 % const PixelChannel channel,const PixelInterpolateMethod method,
4410 % const double x,const double y,double *pixel,ExceptionInfo *exception)
4411 %
4412 % A description of each parameter follows:
4413 %
4414 % o image: the image.
4415 %
4416 % o image_view: the image view.
4417 %
4418 % o channel: the pixel channel to interpolate.
4419 %
4420 % o method: the pixel color interpolation method.
4421 %
4422 % o x,y: A double representing the current (x,y) position of the pixel.
4423 %
4424 % o pixel: return the interpolated pixel here.
4425 %
4426 % o exception: return any errors or warnings in this structure.
4427 %
4428 */
4429
CatromWeights(const double x,double (* weights)[4])4430 static inline void CatromWeights(const double x,double (*weights)[4])
4431 {
4432 double
4433 alpha,
4434 beta,
4435 gamma;
4436
4437 /*
4438 Nicolas Robidoux' 10 flops (4* + 5- + 1+) refactoring of the computation
4439 of the standard four 1D Catmull-Rom weights. The sampling location is
4440 assumed between the second and third input pixel locations, and x is the
4441 position relative to the second input pixel location. Formulas originally
4442 derived for the VIPS (Virtual Image Processing System) library.
4443 */
4444 alpha=(double) 1.0-x;
4445 beta=(double) (-0.5)*x*alpha;
4446 (*weights)[0]=alpha*beta;
4447 (*weights)[3]=x*beta;
4448 /*
4449 The following computation of the inner weights from the outer ones work
4450 for all Keys cubics.
4451 */
4452 gamma=(*weights)[3]-(*weights)[0];
4453 (*weights)[1]=alpha-(*weights)[0]+gamma;
4454 (*weights)[2]=x-(*weights)[3]-gamma;
4455 }
4456
SplineWeights(const double x,double (* weights)[4])4457 static inline void SplineWeights(const double x,double (*weights)[4])
4458 {
4459 double
4460 alpha,
4461 beta;
4462
4463 /*
4464 Nicolas Robidoux' 12 flops (6* + 5- + 1+) refactoring of the computation
4465 of the standard four 1D cubic B-spline smoothing weights. The sampling
4466 location is assumed between the second and third input pixel locations,
4467 and x is the position relative to the second input pixel location.
4468 */
4469 alpha=(double) 1.0-x;
4470 (*weights)[3]=(double) (1.0/6.0)*x*x*x;
4471 (*weights)[0]=(double) (1.0/6.0)*alpha*alpha*alpha;
4472 beta=(*weights)[3]-(*weights)[0];
4473 (*weights)[1]=alpha-(*weights)[0]+beta;
4474 (*weights)[2]=x-(*weights)[3]-beta;
4475 }
4476
MeshInterpolate(const PointInfo * delta,const double p,const double x,const double y)4477 static inline double MeshInterpolate(const PointInfo *delta,const double p,
4478 const double x,const double y)
4479 {
4480 return(delta->x*x+delta->y*y+(1.0-delta->x-delta->y)*p);
4481 }
4482
InterpolatePixelChannel(const Image * magick_restrict image,const CacheView_ * image_view,const PixelChannel channel,const PixelInterpolateMethod method,const double x,const double y,double * pixel,ExceptionInfo * exception)4483 MagickExport MagickBooleanType InterpolatePixelChannel(
4484 const Image *magick_restrict image,const CacheView_ *image_view,
4485 const PixelChannel channel,const PixelInterpolateMethod method,
4486 const double x,const double y,double *pixel,ExceptionInfo *exception)
4487 {
4488 double
4489 alpha[16],
4490 gamma,
4491 pixels[16];
4492
4493 MagickBooleanType
4494 status;
4495
4496 PixelInterpolateMethod
4497 interpolate;
4498
4499 PixelTrait
4500 traits;
4501
4502 const Quantum
4503 *magick_restrict p;
4504
4505 ssize_t
4506 i;
4507
4508 ssize_t
4509 x_offset,
4510 y_offset;
4511
4512 assert(image != (Image *) NULL);
4513 assert(image->signature == MagickCoreSignature);
4514 assert(image_view != (CacheView *) NULL);
4515 status=MagickTrue;
4516 *pixel=0.0;
4517 traits=GetPixelChannelTraits(image,channel);
4518 x_offset=CastDoubleToLong(floor(x));
4519 y_offset=CastDoubleToLong(floor(y));
4520 interpolate=method;
4521 if (interpolate == UndefinedInterpolatePixel)
4522 interpolate=image->interpolate;
4523 switch (interpolate)
4524 {
4525 case AverageInterpolatePixel: /* nearest 4 neighbours */
4526 case Average9InterpolatePixel: /* nearest 9 neighbours */
4527 case Average16InterpolatePixel: /* nearest 16 neighbours */
4528 {
4529 ssize_t
4530 count;
4531
4532 count=2; /* size of the area to average - default nearest 4 */
4533 if (interpolate == Average9InterpolatePixel)
4534 {
4535 count=3;
4536 x_offset=CastDoubleToLong(floor(x+0.5)-1.0);
4537 y_offset=CastDoubleToLong(floor(y+0.5)-1.0);
4538 }
4539 else
4540 if (interpolate == Average16InterpolatePixel)
4541 {
4542 count=4;
4543 x_offset--;
4544 y_offset--;
4545 }
4546 p=GetCacheViewVirtualPixels(image_view,x_offset,y_offset,(size_t) count,
4547 (size_t) count,exception);
4548 if (p == (const Quantum *) NULL)
4549 {
4550 status=MagickFalse;
4551 break;
4552 }
4553 count*=count; /* Number of pixels to average */
4554 if ((traits & BlendPixelTrait) == 0)
4555 for (i=0; i < (ssize_t) count; i++)
4556 {
4557 alpha[i]=1.0;
4558 pixels[i]=(double) p[i*GetPixelChannels(image)+channel];
4559 }
4560 else
4561 for (i=0; i < (ssize_t) count; i++)
4562 {
4563 alpha[i]=QuantumScale*GetPixelAlpha(image,p+i*
4564 GetPixelChannels(image));
4565 pixels[i]=alpha[i]*p[i*GetPixelChannels(image)+channel];
4566 }
4567 for (i=0; i < (ssize_t) count; i++)
4568 {
4569 gamma=PerceptibleReciprocal(alpha[i])/count;
4570 *pixel+=gamma*pixels[i];
4571 }
4572 break;
4573 }
4574 case BilinearInterpolatePixel:
4575 default:
4576 {
4577 PointInfo
4578 delta,
4579 epsilon;
4580
4581 p=GetCacheViewVirtualPixels(image_view,x_offset,y_offset,2,2,exception);
4582 if (p == (const Quantum *) NULL)
4583 {
4584 status=MagickFalse;
4585 break;
4586 }
4587 if ((traits & BlendPixelTrait) == 0)
4588 for (i=0; i < 4; i++)
4589 {
4590 alpha[i]=1.0;
4591 pixels[i]=(double) p[i*GetPixelChannels(image)+channel];
4592 }
4593 else
4594 for (i=0; i < 4; i++)
4595 {
4596 alpha[i]=QuantumScale*GetPixelAlpha(image,p+i*
4597 GetPixelChannels(image));
4598 pixels[i]=alpha[i]*p[i*GetPixelChannels(image)+channel];
4599 }
4600 delta.x=x-x_offset;
4601 delta.y=y-y_offset;
4602 epsilon.x=1.0-delta.x;
4603 epsilon.y=1.0-delta.y;
4604 gamma=((epsilon.y*(epsilon.x*alpha[0]+delta.x*alpha[1])+delta.y*
4605 (epsilon.x*alpha[2]+delta.x*alpha[3])));
4606 gamma=PerceptibleReciprocal(gamma);
4607 *pixel=gamma*(epsilon.y*(epsilon.x*pixels[0]+delta.x*pixels[1])+delta.y*
4608 (epsilon.x*pixels[2]+delta.x*pixels[3]));
4609 break;
4610 }
4611 case BlendInterpolatePixel:
4612 {
4613 p=GetCacheViewVirtualPixels(image_view,x_offset,y_offset,2,2,exception);
4614 if (p == (const Quantum *) NULL)
4615 {
4616 status=MagickFalse;
4617 break;
4618 }
4619 if ((traits & BlendPixelTrait) == 0)
4620 for (i=0; i < 4; i++)
4621 {
4622 alpha[i]=1.0;
4623 pixels[i]=(MagickRealType) p[i*GetPixelChannels(image)+channel];
4624 }
4625 else
4626 for (i=0; i < 4; i++)
4627 {
4628 alpha[i]=QuantumScale*GetPixelAlpha(image,p+i*
4629 GetPixelChannels(image));
4630 pixels[i]=alpha[i]*p[i*GetPixelChannels(image)+channel];
4631 }
4632 gamma=1.0; /* number of pixels blended together (its variable) */
4633 for (i=0; i <= 1L; i++) {
4634 if ((y-y_offset) >= 0.75)
4635 {
4636 alpha[i]=alpha[i+2]; /* take right pixels */
4637 pixels[i]=pixels[i+2];
4638 }
4639 else
4640 if ((y-y_offset) > 0.25)
4641 {
4642 gamma=2.0; /* blend both pixels in row */
4643 alpha[i]+=alpha[i+2]; /* add up alpha weights */
4644 pixels[i]+=pixels[i+2];
4645 }
4646 }
4647 if ((x-x_offset) >= 0.75)
4648 {
4649 alpha[0]=alpha[1]; /* take bottom row blend */
4650 pixels[0]=pixels[1];
4651 }
4652 else
4653 if ((x-x_offset) > 0.25)
4654 {
4655 gamma*=2.0; /* blend both rows */
4656 alpha[0]+=alpha[1]; /* add up alpha weights */
4657 pixels[0]+=pixels[1];
4658 }
4659 if (channel != AlphaPixelChannel)
4660 gamma=PerceptibleReciprocal(alpha[0]); /* (color) 1/alpha_weights */
4661 else
4662 gamma=PerceptibleReciprocal(gamma); /* (alpha) 1/number_of_pixels */
4663 *pixel=gamma*pixels[0];
4664 break;
4665 }
4666 case CatromInterpolatePixel:
4667 {
4668 double
4669 cx[4],
4670 cy[4];
4671
4672 p=GetCacheViewVirtualPixels(image_view,x_offset-1,y_offset-1,4,4,
4673 exception);
4674 if (p == (const Quantum *) NULL)
4675 {
4676 status=MagickFalse;
4677 break;
4678 }
4679 if ((traits & BlendPixelTrait) == 0)
4680 for (i=0; i < 16; i++)
4681 {
4682 alpha[i]=1.0;
4683 pixels[i]=(double) p[i*GetPixelChannels(image)+channel];
4684 }
4685 else
4686 for (i=0; i < 16; i++)
4687 {
4688 alpha[i]=QuantumScale*GetPixelAlpha(image,p+i*
4689 GetPixelChannels(image));
4690 pixels[i]=alpha[i]*p[i*GetPixelChannels(image)+channel];
4691 }
4692 CatromWeights((double) (x-x_offset),&cx);
4693 CatromWeights((double) (y-y_offset),&cy);
4694 gamma=(channel == AlphaPixelChannel ? (double) 1.0 :
4695 PerceptibleReciprocal(cy[0]*(cx[0]*alpha[0]+cx[1]*alpha[1]+cx[2]*
4696 alpha[2]+cx[3]*alpha[3])+cy[1]*(cx[0]*alpha[4]+cx[1]*alpha[5]+cx[2]*
4697 alpha[6]+cx[3]*alpha[7])+cy[2]*(cx[0]*alpha[8]+cx[1]*alpha[9]+cx[2]*
4698 alpha[10]+cx[3]*alpha[11])+cy[3]*(cx[0]*alpha[12]+cx[1]*alpha[13]+
4699 cx[2]*alpha[14]+cx[3]*alpha[15])));
4700 *pixel=gamma*(cy[0]*(cx[0]*pixels[0]+cx[1]*pixels[1]+cx[2]*pixels[2]+
4701 cx[3]*pixels[3])+cy[1]*(cx[0]*pixels[4]+cx[1]*pixels[5]+cx[2]*
4702 pixels[6]+cx[3]*pixels[7])+cy[2]*(cx[0]*pixels[8]+cx[1]*pixels[9]+
4703 cx[2]*pixels[10]+cx[3]*pixels[11])+cy[3]*(cx[0]*pixels[12]+cx[1]*
4704 pixels[13]+cx[2]*pixels[14]+cx[3]*pixels[15]));
4705 break;
4706 }
4707 case IntegerInterpolatePixel:
4708 {
4709 p=GetCacheViewVirtualPixels(image_view,x_offset,y_offset,1,1,exception);
4710 if (p == (const Quantum *) NULL)
4711 {
4712 status=MagickFalse;
4713 break;
4714 }
4715 *pixel=(double) GetPixelChannel(image,channel,p);
4716 break;
4717 }
4718 case NearestInterpolatePixel:
4719 {
4720 x_offset=CastDoubleToLong(floor(x+0.5));
4721 y_offset=CastDoubleToLong(floor(y+0.5));
4722 p=GetCacheViewVirtualPixels(image_view,x_offset,y_offset,1,1,exception);
4723 if (p == (const Quantum *) NULL)
4724 {
4725 status=MagickFalse;
4726 break;
4727 }
4728 *pixel=(double) GetPixelChannel(image,channel,p);
4729 break;
4730 }
4731 case MeshInterpolatePixel:
4732 {
4733 PointInfo
4734 delta,
4735 luminance;
4736
4737 p=GetCacheViewVirtualPixels(image_view,x_offset,y_offset,2,2,exception);
4738 if (p == (const Quantum *) NULL)
4739 {
4740 status=MagickFalse;
4741 break;
4742 }
4743 if ((traits & BlendPixelTrait) == 0)
4744 for (i=0; i < 4; i++)
4745 {
4746 alpha[i]=1.0;
4747 pixels[i]=(double) p[i*GetPixelChannels(image)+channel];
4748 }
4749 else
4750 for (i=0; i < 4; i++)
4751 {
4752 alpha[i]=QuantumScale*GetPixelAlpha(image,p+i*
4753 GetPixelChannels(image));
4754 pixels[i]=alpha[i]*p[i*GetPixelChannels(image)+channel];
4755 }
4756 delta.x=x-x_offset;
4757 delta.y=y-y_offset;
4758 luminance.x=GetPixelLuma(image,p)-(double)
4759 GetPixelLuma(image,p+3*GetPixelChannels(image));
4760 luminance.y=GetPixelLuma(image,p+GetPixelChannels(image))-(double)
4761 GetPixelLuma(image,p+2*GetPixelChannels(image));
4762 if (fabs((double) luminance.x) < fabs((double) luminance.y))
4763 {
4764 /*
4765 Diagonal 0-3 NW-SE.
4766 */
4767 if (delta.x <= delta.y)
4768 {
4769 /*
4770 Bottom-left triangle (pixel: 2, diagonal: 0-3).
4771 */
4772 delta.y=1.0-delta.y;
4773 gamma=MeshInterpolate(&delta,alpha[2],alpha[3],alpha[0]);
4774 gamma=PerceptibleReciprocal(gamma);
4775 *pixel=gamma*MeshInterpolate(&delta,pixels[2],pixels[3],
4776 pixels[0]);
4777 }
4778 else
4779 {
4780 /*
4781 Top-right triangle (pixel: 1, diagonal: 0-3).
4782 */
4783 delta.x=1.0-delta.x;
4784 gamma=MeshInterpolate(&delta,alpha[1],alpha[0],alpha[3]);
4785 gamma=PerceptibleReciprocal(gamma);
4786 *pixel=gamma*MeshInterpolate(&delta,pixels[1],pixels[0],
4787 pixels[3]);
4788 }
4789 }
4790 else
4791 {
4792 /*
4793 Diagonal 1-2 NE-SW.
4794 */
4795 if (delta.x <= (1.0-delta.y))
4796 {
4797 /*
4798 Top-left triangle (pixel: 0, diagonal: 1-2).
4799 */
4800 gamma=MeshInterpolate(&delta,alpha[0],alpha[1],alpha[2]);
4801 gamma=PerceptibleReciprocal(gamma);
4802 *pixel=gamma*MeshInterpolate(&delta,pixels[0],pixels[1],
4803 pixels[2]);
4804 }
4805 else
4806 {
4807 /*
4808 Bottom-right triangle (pixel: 3, diagonal: 1-2).
4809 */
4810 delta.x=1.0-delta.x;
4811 delta.y=1.0-delta.y;
4812 gamma=MeshInterpolate(&delta,alpha[3],alpha[2],alpha[1]);
4813 gamma=PerceptibleReciprocal(gamma);
4814 *pixel=gamma*MeshInterpolate(&delta,pixels[3],pixels[2],
4815 pixels[1]);
4816 }
4817 }
4818 break;
4819 }
4820 case SplineInterpolatePixel:
4821 {
4822 double
4823 cx[4],
4824 cy[4];
4825
4826 p=GetCacheViewVirtualPixels(image_view,x_offset-1,y_offset-1,4,4,
4827 exception);
4828 if (p == (const Quantum *) NULL)
4829 {
4830 status=MagickFalse;
4831 break;
4832 }
4833 if ((traits & BlendPixelTrait) == 0)
4834 for (i=0; i < 16; i++)
4835 {
4836 alpha[i]=1.0;
4837 pixels[i]=(double) p[i*GetPixelChannels(image)+channel];
4838 }
4839 else
4840 for (i=0; i < 16; i++)
4841 {
4842 alpha[i]=QuantumScale*GetPixelAlpha(image,p+i*
4843 GetPixelChannels(image));
4844 pixels[i]=alpha[i]*p[i*GetPixelChannels(image)+channel];
4845 }
4846 SplineWeights((double) (x-x_offset),&cx);
4847 SplineWeights((double) (y-y_offset),&cy);
4848 gamma=(channel == AlphaPixelChannel ? (double) 1.0 :
4849 PerceptibleReciprocal(cy[0]*(cx[0]*alpha[0]+cx[1]*alpha[1]+cx[2]*
4850 alpha[2]+cx[3]*alpha[3])+cy[1]*(cx[0]*alpha[4]+cx[1]*alpha[5]+cx[2]*
4851 alpha[6]+cx[3]*alpha[7])+cy[2]*(cx[0]*alpha[8]+cx[1]*alpha[9]+cx[2]*
4852 alpha[10]+cx[3]*alpha[11])+cy[3]*(cx[0]*alpha[12]+cx[1]*alpha[13]+
4853 cx[2]*alpha[14]+cx[3]*alpha[15])));
4854 *pixel=gamma*(cy[0]*(cx[0]*pixels[0]+cx[1]*pixels[1]+cx[2]*pixels[2]+
4855 cx[3]*pixels[3])+cy[1]*(cx[0]*pixels[4]+cx[1]*pixels[5]+cx[2]*
4856 pixels[6]+cx[3]*pixels[7])+cy[2]*(cx[0]*pixels[8]+cx[1]*pixels[9]+
4857 cx[2]*pixels[10]+cx[3]*pixels[11])+cy[3]*(cx[0]*pixels[12]+cx[1]*
4858 pixels[13]+cx[2]*pixels[14]+cx[3]*pixels[15]));
4859 break;
4860 }
4861 }
4862 return(status);
4863 }
4864
4865 /*
4866 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4867 % %
4868 % %
4869 % %
4870 % I n t e r p o l a t e P i x e l C h a n n e l s %
4871 % %
4872 % %
4873 % %
4874 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4875 %
4876 % InterpolatePixelChannels() applies a pixel interpolation method between a
4877 % floating point coordinate and the pixels surrounding that coordinate. No
4878 % pixel area resampling, or scaling of the result is performed.
4879 %
4880 % Interpolation is restricted to just the current channel setting of the
4881 % destination image into which the color is to be stored
4882 %
4883 % The format of the InterpolatePixelChannels method is:
4884 %
4885 % MagickBooleanType InterpolatePixelChannels(
4886 % const Image *magick_restrict source,const CacheView *source_view,
4887 % const Image *magick_restrict destination,
4888 % const PixelInterpolateMethod method,const double x,const double y,
4889 % Quantum *pixel,ExceptionInfo *exception)
4890 %
4891 % A description of each parameter follows:
4892 %
4893 % o source: the source.
4894 %
4895 % o source_view: the source view.
4896 %
4897 % o destination: the destination image, for the interpolated color
4898 %
4899 % o method: the pixel color interpolation method.
4900 %
4901 % o x,y: A double representing the current (x,y) position of the pixel.
4902 %
4903 % o pixel: return the interpolated pixel here.
4904 %
4905 % o exception: return any errors or warnings in this structure.
4906 %
4907 */
InterpolatePixelChannels(const Image * magick_restrict source,const CacheView_ * source_view,const Image * magick_restrict destination,const PixelInterpolateMethod method,const double x,const double y,Quantum * pixel,ExceptionInfo * exception)4908 MagickExport MagickBooleanType InterpolatePixelChannels(
4909 const Image *magick_restrict source,const CacheView_ *source_view,
4910 const Image *magick_restrict destination,const PixelInterpolateMethod method,
4911 const double x,const double y,Quantum *pixel,ExceptionInfo *exception)
4912 {
4913 MagickBooleanType
4914 status;
4915
4916 double
4917 alpha[16],
4918 gamma,
4919 pixels[16];
4920
4921 const Quantum
4922 *magick_restrict p;
4923
4924 ssize_t
4925 i;
4926
4927 ssize_t
4928 x_offset,
4929 y_offset;
4930
4931 PixelInterpolateMethod
4932 interpolate;
4933
4934 assert(source != (Image *) NULL);
4935 assert(source->signature == MagickCoreSignature);
4936 assert(source_view != (CacheView *) NULL);
4937 status=MagickTrue;
4938 x_offset=CastDoubleToLong(floor(x));
4939 y_offset=CastDoubleToLong(floor(y));
4940 interpolate=method;
4941 if (interpolate == UndefinedInterpolatePixel)
4942 interpolate=source->interpolate;
4943 switch (interpolate)
4944 {
4945 case AverageInterpolatePixel: /* nearest 4 neighbours */
4946 case Average9InterpolatePixel: /* nearest 9 neighbours */
4947 case Average16InterpolatePixel: /* nearest 16 neighbours */
4948 {
4949 ssize_t
4950 count;
4951
4952 count=2; /* size of the area to average - default nearest 4 */
4953 if (interpolate == Average9InterpolatePixel)
4954 {
4955 count=3;
4956 x_offset=CastDoubleToLong(floor(x+0.5)-1.0);
4957 y_offset=CastDoubleToLong(floor(y+0.5)-1.0);
4958 }
4959 else
4960 if (interpolate == Average16InterpolatePixel)
4961 {
4962 count=4;
4963 x_offset--;
4964 y_offset--;
4965 }
4966 p=GetCacheViewVirtualPixels(source_view,x_offset,y_offset,(size_t) count,
4967 (size_t) count,exception);
4968 if (p == (const Quantum *) NULL)
4969 {
4970 status=MagickFalse;
4971 break;
4972 }
4973 count*=count; /* Number of pixels to average */
4974 for (i=0; i < (ssize_t) GetPixelChannels(source); i++)
4975 {
4976 double
4977 sum;
4978
4979 ssize_t
4980 j;
4981
4982 PixelChannel channel = GetPixelChannelChannel(source,i);
4983 PixelTrait traits = GetPixelChannelTraits(source,channel);
4984 PixelTrait destination_traits=GetPixelChannelTraits(destination,
4985 channel);
4986 if ((traits == UndefinedPixelTrait) ||
4987 (destination_traits == UndefinedPixelTrait))
4988 continue;
4989 for (j=0; j < (ssize_t) count; j++)
4990 pixels[j]=(double) p[j*GetPixelChannels(source)+i];
4991 sum=0.0;
4992 if ((traits & BlendPixelTrait) == 0)
4993 {
4994 for (j=0; j < (ssize_t) count; j++)
4995 sum+=pixels[j];
4996 sum/=count;
4997 SetPixelChannel(destination,channel,ClampToQuantum(sum),pixel);
4998 continue;
4999 }
5000 for (j=0; j < (ssize_t) count; j++)
5001 {
5002 alpha[j]=QuantumScale*GetPixelAlpha(source,p+j*
5003 GetPixelChannels(source));
5004 pixels[j]*=alpha[j];
5005 gamma=PerceptibleReciprocal(alpha[j]);
5006 sum+=gamma*pixels[j];
5007 }
5008 sum/=count;
5009 SetPixelChannel(destination,channel,ClampToQuantum(sum),pixel);
5010 }
5011 break;
5012 }
5013 case BilinearInterpolatePixel:
5014 default:
5015 {
5016 p=GetCacheViewVirtualPixels(source_view,x_offset,y_offset,2,2,exception);
5017 if (p == (const Quantum *) NULL)
5018 {
5019 status=MagickFalse;
5020 break;
5021 }
5022 for (i=0; i < (ssize_t) GetPixelChannels(source); i++)
5023 {
5024 PointInfo
5025 delta,
5026 epsilon;
5027
5028 PixelChannel channel = GetPixelChannelChannel(source,i);
5029 PixelTrait traits = GetPixelChannelTraits(source,channel);
5030 PixelTrait destination_traits=GetPixelChannelTraits(destination,
5031 channel);
5032 if ((traits == UndefinedPixelTrait) ||
5033 (destination_traits == UndefinedPixelTrait))
5034 continue;
5035 delta.x=x-x_offset;
5036 delta.y=y-y_offset;
5037 epsilon.x=1.0-delta.x;
5038 epsilon.y=1.0-delta.y;
5039 pixels[0]=(double) p[i];
5040 pixels[1]=(double) p[GetPixelChannels(source)+i];
5041 pixels[2]=(double) p[2*GetPixelChannels(source)+i];
5042 pixels[3]=(double) p[3*GetPixelChannels(source)+i];
5043 if ((traits & BlendPixelTrait) == 0)
5044 {
5045 gamma=((epsilon.y*(epsilon.x+delta.x)+delta.y*(epsilon.x+delta.x)));
5046 gamma=PerceptibleReciprocal(gamma);
5047 SetPixelChannel(destination,channel,ClampToQuantum(gamma*(epsilon.y*
5048 (epsilon.x*pixels[0]+delta.x*pixels[1])+delta.y*(epsilon.x*
5049 pixels[2]+delta.x*pixels[3]))),pixel);
5050 continue;
5051 }
5052 alpha[0]=QuantumScale*GetPixelAlpha(source,p);
5053 alpha[1]=QuantumScale*GetPixelAlpha(source,p+GetPixelChannels(source));
5054 alpha[2]=QuantumScale*GetPixelAlpha(source,p+2*
5055 GetPixelChannels(source));
5056 alpha[3]=QuantumScale*GetPixelAlpha(source,p+3*
5057 GetPixelChannels(source));
5058 pixels[0]*=alpha[0];
5059 pixels[1]*=alpha[1];
5060 pixels[2]*=alpha[2];
5061 pixels[3]*=alpha[3];
5062 gamma=((epsilon.y*(epsilon.x*alpha[0]+delta.x*alpha[1])+delta.y*
5063 (epsilon.x*alpha[2]+delta.x*alpha[3])));
5064 gamma=PerceptibleReciprocal(gamma);
5065 SetPixelChannel(destination,channel,ClampToQuantum(gamma*(epsilon.y*
5066 (epsilon.x*pixels[0]+delta.x*pixels[1])+delta.y*(epsilon.x*pixels[2]+
5067 delta.x*pixels[3]))),pixel);
5068 }
5069 break;
5070 }
5071 case BlendInterpolatePixel:
5072 {
5073 p=GetCacheViewVirtualPixels(source_view,x_offset,y_offset,2,2,exception);
5074 if (p == (const Quantum *) NULL)
5075 {
5076 status=MagickFalse;
5077 break;
5078 }
5079 for (i=0; i < (ssize_t) GetPixelChannels(source); i++)
5080 {
5081 ssize_t
5082 j;
5083
5084 PixelChannel channel = GetPixelChannelChannel(source,i);
5085 PixelTrait traits = GetPixelChannelTraits(source,channel);
5086 PixelTrait destination_traits=GetPixelChannelTraits(destination,
5087 channel);
5088 if ((traits == UndefinedPixelTrait) ||
5089 (destination_traits == UndefinedPixelTrait))
5090 continue;
5091 if (source->alpha_trait != BlendPixelTrait)
5092 for (j=0; j < 4; j++)
5093 {
5094 alpha[j]=1.0;
5095 pixels[j]=(double) p[j*GetPixelChannels(source)+i];
5096 }
5097 else
5098 for (j=0; j < 4; j++)
5099 {
5100 alpha[j]=QuantumScale*GetPixelAlpha(source,p+j*
5101 GetPixelChannels(source));
5102 pixels[j]=(double) p[j*GetPixelChannels(source)+i];
5103 if (channel != AlphaPixelChannel)
5104 pixels[j]*=alpha[j];
5105 }
5106 gamma=1.0; /* number of pixels blended together (its variable) */
5107 for (j=0; j <= 1L; j++)
5108 {
5109 if ((y-y_offset) >= 0.75)
5110 {
5111 alpha[j]=alpha[j+2]; /* take right pixels */
5112 pixels[j]=pixels[j+2];
5113 }
5114 else
5115 if ((y-y_offset) > 0.25)
5116 {
5117 gamma=2.0; /* blend both pixels in row */
5118 alpha[j]+=alpha[j+2]; /* add up alpha weights */
5119 pixels[j]+=pixels[j+2];
5120 }
5121 }
5122 if ((x-x_offset) >= 0.75)
5123 {
5124 alpha[0]=alpha[1]; /* take bottom row blend */
5125 pixels[0]=pixels[1];
5126 }
5127 else
5128 if ((x-x_offset) > 0.25)
5129 {
5130 gamma*=2.0; /* blend both rows */
5131 alpha[0]+=alpha[1]; /* add up alpha weights */
5132 pixels[0]+=pixels[1];
5133 }
5134 if (channel != AlphaPixelChannel)
5135 gamma=PerceptibleReciprocal(alpha[0]); /* (color) 1/alpha_weights */
5136 else
5137 gamma=PerceptibleReciprocal(gamma); /* (alpha) 1/number_of_pixels */
5138 SetPixelChannel(destination,channel,ClampToQuantum(gamma*pixels[0]),
5139 pixel);
5140 }
5141 break;
5142 }
5143 case CatromInterpolatePixel:
5144 {
5145 double
5146 cx[4],
5147 cy[4];
5148
5149 p=GetCacheViewVirtualPixels(source_view,x_offset-1,y_offset-1,4,4,
5150 exception);
5151 if (p == (const Quantum *) NULL)
5152 {
5153 status=MagickFalse;
5154 break;
5155 }
5156 for (i=0; i < (ssize_t) GetPixelChannels(source); i++)
5157 {
5158 ssize_t
5159 j;
5160
5161 PixelChannel channel = GetPixelChannelChannel(source,i);
5162 PixelTrait traits = GetPixelChannelTraits(source,channel);
5163 PixelTrait destination_traits=GetPixelChannelTraits(destination,
5164 channel);
5165 if ((traits == UndefinedPixelTrait) ||
5166 (destination_traits == UndefinedPixelTrait))
5167 continue;
5168 if ((traits & BlendPixelTrait) == 0)
5169 for (j=0; j < 16; j++)
5170 {
5171 alpha[j]=1.0;
5172 pixels[j]=(double) p[j*GetPixelChannels(source)+i];
5173 }
5174 else
5175 for (j=0; j < 16; j++)
5176 {
5177 alpha[j]=QuantumScale*GetPixelAlpha(source,p+j*
5178 GetPixelChannels(source));
5179 pixels[j]=alpha[j]*p[j*GetPixelChannels(source)+i];
5180 }
5181 CatromWeights((double) (x-x_offset),&cx);
5182 CatromWeights((double) (y-y_offset),&cy);
5183 gamma=((traits & BlendPixelTrait) ? (double) (1.0) :
5184 PerceptibleReciprocal(cy[0]*(cx[0]*alpha[0]+cx[1]*alpha[1]+cx[2]*
5185 alpha[2]+cx[3]*alpha[3])+cy[1]*(cx[0]*alpha[4]+cx[1]*alpha[5]+cx[2]*
5186 alpha[6]+cx[3]*alpha[7])+cy[2]*(cx[0]*alpha[8]+cx[1]*alpha[9]+cx[2]*
5187 alpha[10]+cx[3]*alpha[11])+cy[3]*(cx[0]*alpha[12]+cx[1]*alpha[13]+
5188 cx[2]*alpha[14]+cx[3]*alpha[15])));
5189 SetPixelChannel(destination,channel,ClampToQuantum(gamma*(cy[0]*(cx[0]*
5190 pixels[0]+cx[1]*pixels[1]+cx[2]*pixels[2]+cx[3]*pixels[3])+cy[1]*
5191 (cx[0]*pixels[4]+cx[1]*pixels[5]+cx[2]*pixels[6]+cx[3]*pixels[7])+
5192 cy[2]*(cx[0]*pixels[8]+cx[1]*pixels[9]+cx[2]*pixels[10]+cx[3]*
5193 pixels[11])+cy[3]*(cx[0]*pixels[12]+cx[1]*pixels[13]+cx[2]*
5194 pixels[14]+cx[3]*pixels[15]))),pixel);
5195 }
5196 break;
5197 }
5198 case IntegerInterpolatePixel:
5199 {
5200 p=GetCacheViewVirtualPixels(source_view,x_offset,y_offset,1,1,exception);
5201 if (p == (const Quantum *) NULL)
5202 {
5203 status=MagickFalse;
5204 break;
5205 }
5206 for (i=0; i < (ssize_t) GetPixelChannels(source); i++)
5207 {
5208 PixelChannel channel = GetPixelChannelChannel(source,i);
5209 PixelTrait traits = GetPixelChannelTraits(source,channel);
5210 PixelTrait destination_traits=GetPixelChannelTraits(destination,
5211 channel);
5212 if ((traits == UndefinedPixelTrait) ||
5213 (destination_traits == UndefinedPixelTrait))
5214 continue;
5215 SetPixelChannel(destination,channel,p[i],pixel);
5216 }
5217 break;
5218 }
5219 case NearestInterpolatePixel:
5220 {
5221 x_offset=CastDoubleToLong(floor(x+0.5));
5222 y_offset=CastDoubleToLong(floor(y+0.5));
5223 p=GetCacheViewVirtualPixels(source_view,x_offset,y_offset,1,1,exception);
5224 if (p == (const Quantum *) NULL)
5225 {
5226 status=MagickFalse;
5227 break;
5228 }
5229 for (i=0; i < (ssize_t) GetPixelChannels(source); i++)
5230 {
5231 PixelChannel channel = GetPixelChannelChannel(source,i);
5232 PixelTrait traits = GetPixelChannelTraits(source,channel);
5233 PixelTrait destination_traits=GetPixelChannelTraits(destination,
5234 channel);
5235 if ((traits == UndefinedPixelTrait) ||
5236 (destination_traits == UndefinedPixelTrait))
5237 continue;
5238 SetPixelChannel(destination,channel,p[i],pixel);
5239 }
5240 break;
5241 }
5242 case MeshInterpolatePixel:
5243 {
5244 p=GetCacheViewVirtualPixels(source_view,x_offset,y_offset,2,2,exception);
5245 if (p == (const Quantum *) NULL)
5246 {
5247 status=MagickFalse;
5248 break;
5249 }
5250 for (i=0; i < (ssize_t) GetPixelChannels(source); i++)
5251 {
5252 PointInfo
5253 delta,
5254 luminance;
5255
5256 PixelChannel channel = GetPixelChannelChannel(source,i);
5257 PixelTrait traits = GetPixelChannelTraits(source,channel);
5258 PixelTrait destination_traits=GetPixelChannelTraits(destination,
5259 channel);
5260 if ((traits == UndefinedPixelTrait) ||
5261 (destination_traits == UndefinedPixelTrait))
5262 continue;
5263 pixels[0]=(double) p[i];
5264 pixels[1]=(double) p[GetPixelChannels(source)+i];
5265 pixels[2]=(double) p[2*GetPixelChannels(source)+i];
5266 pixels[3]=(double) p[3*GetPixelChannels(source)+i];
5267 if ((traits & BlendPixelTrait) == 0)
5268 {
5269 alpha[0]=1.0;
5270 alpha[1]=1.0;
5271 alpha[2]=1.0;
5272 alpha[3]=1.0;
5273 }
5274 else
5275 {
5276 alpha[0]=QuantumScale*GetPixelAlpha(source,p);
5277 alpha[1]=QuantumScale*GetPixelAlpha(source,p+
5278 GetPixelChannels(source));
5279 alpha[2]=QuantumScale*GetPixelAlpha(source,p+2*
5280 GetPixelChannels(source));
5281 alpha[3]=QuantumScale*GetPixelAlpha(source,p+3*
5282 GetPixelChannels(source));
5283 }
5284 delta.x=x-x_offset;
5285 delta.y=y-y_offset;
5286 luminance.x=fabs((double) (GetPixelLuma(source,p)-
5287 GetPixelLuma(source,p+3*GetPixelChannels(source))));
5288 luminance.y=fabs((double) (GetPixelLuma(source,p+
5289 GetPixelChannels(source))-GetPixelLuma(source,p+2*
5290 GetPixelChannels(source))));
5291 if (luminance.x < luminance.y)
5292 {
5293 /*
5294 Diagonal 0-3 NW-SE.
5295 */
5296 if (delta.x <= delta.y)
5297 {
5298 /*
5299 Bottom-left triangle (pixel: 2, diagonal: 0-3).
5300 */
5301 delta.y=1.0-delta.y;
5302 gamma=MeshInterpolate(&delta,alpha[2],alpha[3],alpha[0]);
5303 gamma=PerceptibleReciprocal(gamma);
5304 SetPixelChannel(destination,channel,ClampToQuantum(gamma*
5305 MeshInterpolate(&delta,pixels[2],pixels[3],pixels[0])),pixel);
5306 }
5307 else
5308 {
5309 /*
5310 Top-right triangle (pixel: 1, diagonal: 0-3).
5311 */
5312 delta.x=1.0-delta.x;
5313 gamma=MeshInterpolate(&delta,alpha[1],alpha[0],alpha[3]);
5314 gamma=PerceptibleReciprocal(gamma);
5315 SetPixelChannel(destination,channel,ClampToQuantum(gamma*
5316 MeshInterpolate(&delta,pixels[1],pixels[0],pixels[3])),pixel);
5317 }
5318 }
5319 else
5320 {
5321 /*
5322 Diagonal 1-2 NE-SW.
5323 */
5324 if (delta.x <= (1.0-delta.y))
5325 {
5326 /*
5327 Top-left triangle (pixel: 0, diagonal: 1-2).
5328 */
5329 gamma=MeshInterpolate(&delta,alpha[0],alpha[1],alpha[2]);
5330 gamma=PerceptibleReciprocal(gamma);
5331 SetPixelChannel(destination,channel,ClampToQuantum(gamma*
5332 MeshInterpolate(&delta,pixels[0],pixels[1],pixels[2])),pixel);
5333 }
5334 else
5335 {
5336 /*
5337 Bottom-right triangle (pixel: 3, diagonal: 1-2).
5338 */
5339 delta.x=1.0-delta.x;
5340 delta.y=1.0-delta.y;
5341 gamma=MeshInterpolate(&delta,alpha[3],alpha[2],alpha[1]);
5342 gamma=PerceptibleReciprocal(gamma);
5343 SetPixelChannel(destination,channel,ClampToQuantum(gamma*
5344 MeshInterpolate(&delta,pixels[3],pixels[2],pixels[1])),pixel);
5345 }
5346 }
5347 }
5348 break;
5349 }
5350 case SplineInterpolatePixel:
5351 {
5352 double
5353 cx[4],
5354 cy[4];
5355
5356 p=GetCacheViewVirtualPixels(source_view,x_offset-1,y_offset-1,4,4,
5357 exception);
5358 if (p == (const Quantum *) NULL)
5359 {
5360 status=MagickFalse;
5361 break;
5362 }
5363 for (i=0; i < (ssize_t) GetPixelChannels(source); i++)
5364 {
5365 ssize_t
5366 j;
5367
5368 PixelChannel channel = GetPixelChannelChannel(source,i);
5369 PixelTrait traits = GetPixelChannelTraits(source,channel);
5370 PixelTrait destination_traits=GetPixelChannelTraits(destination,
5371 channel);
5372 if ((traits == UndefinedPixelTrait) ||
5373 (destination_traits == UndefinedPixelTrait))
5374 continue;
5375 if ((traits & BlendPixelTrait) == 0)
5376 for (j=0; j < 16; j++)
5377 {
5378 alpha[j]=1.0;
5379 pixels[j]=(double) p[j*GetPixelChannels(source)+i];
5380 }
5381 else
5382 for (j=0; j < 16; j++)
5383 {
5384 alpha[j]=QuantumScale*GetPixelAlpha(source,p+j*
5385 GetPixelChannels(source));
5386 pixels[j]=alpha[j]*p[j*GetPixelChannels(source)+i];
5387 }
5388 SplineWeights((double) (x-x_offset),&cx);
5389 SplineWeights((double) (y-y_offset),&cy);
5390 gamma=((traits & BlendPixelTrait) ? (double) (1.0) :
5391 PerceptibleReciprocal(cy[0]*(cx[0]*alpha[0]+cx[1]*alpha[1]+cx[2]*
5392 alpha[2]+cx[3]*alpha[3])+cy[1]*(cx[0]*alpha[4]+cx[1]*alpha[5]+cx[2]*
5393 alpha[6]+cx[3]*alpha[7])+cy[2]*(cx[0]*alpha[8]+cx[1]*alpha[9]+cx[2]*
5394 alpha[10]+cx[3]*alpha[11])+cy[3]*(cx[0]*alpha[12]+cx[1]*alpha[13]+
5395 cx[2]*alpha[14]+cx[3]*alpha[15])));
5396 SetPixelChannel(destination,channel,ClampToQuantum(gamma*(cy[0]*(cx[0]*
5397 pixels[0]+cx[1]*pixels[1]+cx[2]*pixels[2]+cx[3]*pixels[3])+cy[1]*
5398 (cx[0]*pixels[4]+cx[1]*pixels[5]+cx[2]*pixels[6]+cx[3]*pixels[7])+
5399 cy[2]*(cx[0]*pixels[8]+cx[1]*pixels[9]+cx[2]*pixels[10]+cx[3]*
5400 pixels[11])+cy[3]*(cx[0]*pixels[12]+cx[1]*pixels[13]+cx[2]*
5401 pixels[14]+cx[3]*pixels[15]))),pixel);
5402 }
5403 break;
5404 }
5405 }
5406 return(status);
5407 }
5408
5409 /*
5410 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5411 % %
5412 % %
5413 % %
5414 % I n t e r p o l a t e P i x e l I n f o %
5415 % %
5416 % %
5417 % %
5418 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5419 %
5420 % InterpolatePixelInfo() applies a pixel interpolation method between a
5421 % floating point coordinate and the pixels surrounding that coordinate. No
5422 % pixel area resampling, or scaling of the result is performed.
5423 %
5424 % Interpolation is restricted to just RGBKA channels.
5425 %
5426 % The format of the InterpolatePixelInfo method is:
5427 %
5428 % MagickBooleanType InterpolatePixelInfo(const Image *image,
5429 % const CacheView *image_view,const PixelInterpolateMethod method,
5430 % const double x,const double y,PixelInfo *pixel,
5431 % ExceptionInfo *exception)
5432 %
5433 % A description of each parameter follows:
5434 %
5435 % o image: the image.
5436 %
5437 % o image_view: the image view.
5438 %
5439 % o method: the pixel color interpolation method.
5440 %
5441 % o x,y: A double representing the current (x,y) position of the pixel.
5442 %
5443 % o pixel: return the interpolated pixel here.
5444 %
5445 % o exception: return any errors or warnings in this structure.
5446 %
5447 */
5448
AlphaBlendPixelInfo(const Image * image,const Quantum * pixel,PixelInfo * pixel_info,double * alpha)5449 static inline void AlphaBlendPixelInfo(const Image *image,
5450 const Quantum *pixel,PixelInfo *pixel_info,double *alpha)
5451 {
5452 if (image->alpha_trait == UndefinedPixelTrait)
5453 {
5454 *alpha=1.0;
5455 pixel_info->red=(double) GetPixelRed(image,pixel);
5456 pixel_info->green=(double) GetPixelGreen(image,pixel);
5457 pixel_info->blue=(double) GetPixelBlue(image,pixel);
5458 pixel_info->black=0.0;
5459 if (image->colorspace == CMYKColorspace)
5460 pixel_info->black=(double) GetPixelBlack(image,pixel);
5461 pixel_info->alpha=(double) GetPixelAlpha(image,pixel);
5462 return;
5463 }
5464 *alpha=QuantumScale*GetPixelAlpha(image,pixel);
5465 pixel_info->red=(*alpha*GetPixelRed(image,pixel));
5466 pixel_info->green=(*alpha*GetPixelGreen(image,pixel));
5467 pixel_info->blue=(*alpha*GetPixelBlue(image,pixel));
5468 pixel_info->black=0.0;
5469 if (image->colorspace == CMYKColorspace)
5470 pixel_info->black=(*alpha*GetPixelBlack(image,pixel));
5471 pixel_info->alpha=(double) GetPixelAlpha(image,pixel);
5472 }
5473
InterpolatePixelInfo(const Image * image,const CacheView_ * image_view,const PixelInterpolateMethod method,const double x,const double y,PixelInfo * pixel,ExceptionInfo * exception)5474 MagickExport MagickBooleanType InterpolatePixelInfo(const Image *image,
5475 const CacheView_ *image_view,const PixelInterpolateMethod method,
5476 const double x,const double y,PixelInfo *pixel,ExceptionInfo *exception)
5477 {
5478 MagickBooleanType
5479 status;
5480
5481 double
5482 alpha[16],
5483 gamma;
5484
5485 PixelInfo
5486 pixels[16];
5487
5488 const Quantum
5489 *p;
5490
5491 ssize_t
5492 i;
5493
5494 ssize_t
5495 x_offset,
5496 y_offset;
5497
5498 PixelInterpolateMethod
5499 interpolate;
5500
5501 assert(image != (Image *) NULL);
5502 assert(image->signature == MagickCoreSignature);
5503 assert(image_view != (CacheView *) NULL);
5504 status=MagickTrue;
5505 x_offset=CastDoubleToLong(floor(x));
5506 y_offset=CastDoubleToLong(floor(y));
5507 interpolate=method;
5508 if (interpolate == UndefinedInterpolatePixel)
5509 interpolate=image->interpolate;
5510 GetPixelInfoPixel(image,(const Quantum *) NULL,pixel);
5511 (void) memset(&pixels,0,sizeof(pixels));
5512 switch (interpolate)
5513 {
5514 case AverageInterpolatePixel: /* nearest 4 neighbours */
5515 case Average9InterpolatePixel: /* nearest 9 neighbours */
5516 case Average16InterpolatePixel: /* nearest 16 neighbours */
5517 {
5518 ssize_t
5519 count;
5520
5521 count=2; /* size of the area to average - default nearest 4 */
5522 if (interpolate == Average9InterpolatePixel)
5523 {
5524 count=3;
5525 x_offset=CastDoubleToLong(floor(x+0.5)-1.0);
5526 y_offset=CastDoubleToLong(floor(y+0.5)-1.0);
5527 }
5528 else if (interpolate == Average16InterpolatePixel)
5529 {
5530 count=4;
5531 x_offset--;
5532 y_offset--;
5533 }
5534 p=GetCacheViewVirtualPixels(image_view,x_offset,y_offset,(size_t) count,
5535 (size_t) count,exception);
5536 if (p == (const Quantum *) NULL)
5537 {
5538 status=MagickFalse;
5539 break;
5540 }
5541 count*=count; /* number of pixels - square of size */
5542 for (i=0; i < (ssize_t) count; i++)
5543 {
5544 AlphaBlendPixelInfo(image,p,pixels,alpha);
5545 gamma=PerceptibleReciprocal(alpha[0]);
5546 pixel->red+=gamma*pixels[0].red;
5547 pixel->green+=gamma*pixels[0].green;
5548 pixel->blue+=gamma*pixels[0].blue;
5549 pixel->black+=gamma*pixels[0].black;
5550 pixel->alpha+=pixels[0].alpha;
5551 p += GetPixelChannels(image);
5552 }
5553 gamma=1.0/count; /* average weighting of each pixel in area */
5554 pixel->red*=gamma;
5555 pixel->green*=gamma;
5556 pixel->blue*=gamma;
5557 pixel->black*=gamma;
5558 pixel->alpha*=gamma;
5559 break;
5560 }
5561 case BackgroundInterpolatePixel:
5562 {
5563 *pixel=image->background_color; /* Copy PixelInfo Structure */
5564 break;
5565 }
5566 case BilinearInterpolatePixel:
5567 default:
5568 {
5569 PointInfo
5570 delta,
5571 epsilon;
5572
5573 p=GetCacheViewVirtualPixels(image_view,x_offset,y_offset,2,2,exception);
5574 if (p == (const Quantum *) NULL)
5575 {
5576 status=MagickFalse;
5577 break;
5578 }
5579 for (i=0; i < 4L; i++)
5580 AlphaBlendPixelInfo(image,p+i*GetPixelChannels(image),pixels+i,alpha+i);
5581 delta.x=x-x_offset;
5582 delta.y=y-y_offset;
5583 epsilon.x=1.0-delta.x;
5584 epsilon.y=1.0-delta.y;
5585 gamma=((epsilon.y*(epsilon.x*alpha[0]+delta.x*alpha[1])+delta.y*
5586 (epsilon.x*alpha[2]+delta.x*alpha[3])));
5587 gamma=PerceptibleReciprocal(gamma);
5588 pixel->red=gamma*(epsilon.y*(epsilon.x*pixels[0].red+delta.x*
5589 pixels[1].red)+delta.y*(epsilon.x*pixels[2].red+delta.x*pixels[3].red));
5590 pixel->green=gamma*(epsilon.y*(epsilon.x*pixels[0].green+delta.x*
5591 pixels[1].green)+delta.y*(epsilon.x*pixels[2].green+delta.x*
5592 pixels[3].green));
5593 pixel->blue=gamma*(epsilon.y*(epsilon.x*pixels[0].blue+delta.x*
5594 pixels[1].blue)+delta.y*(epsilon.x*pixels[2].blue+delta.x*
5595 pixels[3].blue));
5596 if (image->colorspace == CMYKColorspace)
5597 pixel->black=gamma*(epsilon.y*(epsilon.x*pixels[0].black+delta.x*
5598 pixels[1].black)+delta.y*(epsilon.x*pixels[2].black+delta.x*
5599 pixels[3].black));
5600 gamma=((epsilon.y*(epsilon.x+delta.x)+delta.y*(epsilon.x+delta.x)));
5601 gamma=PerceptibleReciprocal(gamma);
5602 pixel->alpha=gamma*(epsilon.y*(epsilon.x*pixels[0].alpha+delta.x*
5603 pixels[1].alpha)+delta.y*(epsilon.x*pixels[2].alpha+delta.x*
5604 pixels[3].alpha));
5605 break;
5606 }
5607 case BlendInterpolatePixel:
5608 {
5609 p=GetCacheViewVirtualPixels(image_view,x_offset,y_offset,2,2,exception);
5610 if (p == (const Quantum *) NULL)
5611 {
5612 status=MagickFalse;
5613 break;
5614 }
5615 for (i=0; i < 4L; i++)
5616 {
5617 GetPixelInfoPixel(image,p+i*GetPixelChannels(image),pixels+i);
5618 AlphaBlendPixelInfo(image,p+i*GetPixelChannels(image),pixels+i,alpha+i);
5619 }
5620 gamma=1.0; /* number of pixels blended together (its variable) */
5621 for (i=0; i <= 1L; i++)
5622 {
5623 if ((y-y_offset) >= 0.75)
5624 {
5625 alpha[i]=alpha[i+2]; /* take right pixels */
5626 pixels[i]=pixels[i+2];
5627 }
5628 else
5629 if ((y-y_offset) > 0.25)
5630 {
5631 gamma=2.0; /* blend both pixels in row */
5632 alpha[i]+=alpha[i+2]; /* add up alpha weights */
5633 pixels[i].red+=pixels[i+2].red;
5634 pixels[i].green+=pixels[i+2].green;
5635 pixels[i].blue+=pixels[i+2].blue;
5636 pixels[i].black+=pixels[i+2].black;
5637 pixels[i].alpha+=pixels[i+2].alpha;
5638 }
5639 }
5640 if ((x-x_offset) >= 0.75)
5641 {
5642 alpha[0]=alpha[1];
5643 pixels[0]=pixels[1];
5644 }
5645 else
5646 if ((x-x_offset) > 0.25)
5647 {
5648 gamma*=2.0; /* blend both rows */
5649 alpha[0]+= alpha[1]; /* add up alpha weights */
5650 pixels[0].red+=pixels[1].red;
5651 pixels[0].green+=pixels[1].green;
5652 pixels[0].blue+=pixels[1].blue;
5653 pixels[0].black+=pixels[1].black;
5654 pixels[0].alpha+=pixels[1].alpha;
5655 }
5656 gamma=1.0/gamma;
5657 alpha[0]=PerceptibleReciprocal(alpha[0]);
5658 pixel->red=alpha[0]*pixels[0].red;
5659 pixel->green=alpha[0]*pixels[0].green; /* divide by sum of alpha */
5660 pixel->blue=alpha[0]*pixels[0].blue;
5661 pixel->black=alpha[0]*pixels[0].black;
5662 pixel->alpha=gamma*pixels[0].alpha; /* divide by number of pixels */
5663 break;
5664 }
5665 case CatromInterpolatePixel:
5666 {
5667 double
5668 cx[4],
5669 cy[4];
5670
5671 p=GetCacheViewVirtualPixels(image_view,x_offset-1,y_offset-1,4,4,
5672 exception);
5673 if (p == (const Quantum *) NULL)
5674 {
5675 status=MagickFalse;
5676 break;
5677 }
5678 for (i=0; i < 16L; i++)
5679 AlphaBlendPixelInfo(image,p+i*GetPixelChannels(image),pixels+i,alpha+i);
5680 CatromWeights((double) (x-x_offset),&cx);
5681 CatromWeights((double) (y-y_offset),&cy);
5682 pixel->red=(cy[0]*(cx[0]*pixels[0].red+cx[1]*pixels[1].red+cx[2]*
5683 pixels[2].red+cx[3]*pixels[3].red)+cy[1]*(cx[0]*pixels[4].red+cx[1]*
5684 pixels[5].red+cx[2]*pixels[6].red+cx[3]*pixels[7].red)+cy[2]*(cx[0]*
5685 pixels[8].red+cx[1]*pixels[9].red+cx[2]*pixels[10].red+cx[3]*
5686 pixels[11].red)+cy[3]*(cx[0]*pixels[12].red+cx[1]*pixels[13].red+cx[2]*
5687 pixels[14].red+cx[3]*pixels[15].red));
5688 pixel->green=(cy[0]*(cx[0]*pixels[0].green+cx[1]*pixels[1].green+cx[2]*
5689 pixels[2].green+cx[3]*pixels[3].green)+cy[1]*(cx[0]*pixels[4].green+
5690 cx[1]*pixels[5].green+cx[2]*pixels[6].green+cx[3]*pixels[7].green)+
5691 cy[2]*(cx[0]*pixels[8].green+cx[1]*pixels[9].green+cx[2]*
5692 pixels[10].green+cx[3]*pixels[11].green)+cy[3]*(cx[0]*
5693 pixels[12].green+cx[1]*pixels[13].green+cx[2]*pixels[14].green+cx[3]*
5694 pixels[15].green));
5695 pixel->blue=(cy[0]*(cx[0]*pixels[0].blue+cx[1]*pixels[1].blue+cx[2]*
5696 pixels[2].blue+cx[3]*pixels[3].blue)+cy[1]*(cx[0]*pixels[4].blue+cx[1]*
5697 pixels[5].blue+cx[2]*pixels[6].blue+cx[3]*pixels[7].blue)+cy[2]*(cx[0]*
5698 pixels[8].blue+cx[1]*pixels[9].blue+cx[2]*pixels[10].blue+cx[3]*
5699 pixels[11].blue)+cy[3]*(cx[0]*pixels[12].blue+cx[1]*pixels[13].blue+
5700 cx[2]*pixels[14].blue+cx[3]*pixels[15].blue));
5701 if (image->colorspace == CMYKColorspace)
5702 pixel->black=(cy[0]*(cx[0]*pixels[0].black+cx[1]*pixels[1].black+cx[2]*
5703 pixels[2].black+cx[3]*pixels[3].black)+cy[1]*(cx[0]*pixels[4].black+
5704 cx[1]*pixels[5].black+cx[2]*pixels[6].black+cx[3]*pixels[7].black)+
5705 cy[2]*(cx[0]*pixels[8].black+cx[1]*pixels[9].black+cx[2]*
5706 pixels[10].black+cx[3]*pixels[11].black)+cy[3]*(cx[0]*
5707 pixels[12].black+cx[1]*pixels[13].black+cx[2]*pixels[14].black+cx[3]*
5708 pixels[15].black));
5709 pixel->alpha=(cy[0]*(cx[0]*pixels[0].alpha+cx[1]*pixels[1].alpha+cx[2]*
5710 pixels[2].alpha+cx[3]*pixels[3].alpha)+cy[1]*(cx[0]*pixels[4].alpha+
5711 cx[1]*pixels[5].alpha+cx[2]*pixels[6].alpha+cx[3]*pixels[7].alpha)+
5712 cy[2]*(cx[0]*pixels[8].alpha+cx[1]*pixels[9].alpha+cx[2]*
5713 pixels[10].alpha+cx[3]*pixels[11].alpha)+cy[3]*(cx[0]*pixels[12].alpha+
5714 cx[1]*pixels[13].alpha+cx[2]*pixels[14].alpha+cx[3]*pixels[15].alpha));
5715 break;
5716 }
5717 case IntegerInterpolatePixel:
5718 {
5719 p=GetCacheViewVirtualPixels(image_view,x_offset,y_offset,1,1,exception);
5720 if (p == (const Quantum *) NULL)
5721 {
5722 status=MagickFalse;
5723 break;
5724 }
5725 GetPixelInfoPixel(image,p,pixel);
5726 break;
5727 }
5728 case MeshInterpolatePixel:
5729 {
5730 PointInfo
5731 delta,
5732 luminance;
5733
5734 p=GetCacheViewVirtualPixels(image_view,x_offset,y_offset,2,2,exception);
5735 if (p == (const Quantum *) NULL)
5736 {
5737 status=MagickFalse;
5738 break;
5739 }
5740 delta.x=x-x_offset;
5741 delta.y=y-y_offset;
5742 luminance.x=GetPixelLuma(image,p)-(double)
5743 GetPixelLuma(image,p+3*GetPixelChannels(image));
5744 luminance.y=GetPixelLuma(image,p+GetPixelChannels(image))-(double)
5745 GetPixelLuma(image,p+2*GetPixelChannels(image));
5746 AlphaBlendPixelInfo(image,p,pixels+0,alpha+0);
5747 AlphaBlendPixelInfo(image,p+GetPixelChannels(image),pixels+1,alpha+1);
5748 AlphaBlendPixelInfo(image,p+2*GetPixelChannels(image),pixels+2,alpha+2);
5749 AlphaBlendPixelInfo(image,p+3*GetPixelChannels(image),pixels+3,alpha+3);
5750 if (fabs((double) luminance.x) < fabs((double) luminance.y))
5751 {
5752 /*
5753 Diagonal 0-3 NW-SE.
5754 */
5755 if (delta.x <= delta.y)
5756 {
5757 /*
5758 Bottom-left triangle (pixel: 2, diagonal: 0-3).
5759 */
5760 delta.y=1.0-delta.y;
5761 gamma=MeshInterpolate(&delta,alpha[2],alpha[3],alpha[0]);
5762 gamma=PerceptibleReciprocal(gamma);
5763 pixel->red=gamma*MeshInterpolate(&delta,pixels[2].red,
5764 pixels[3].red,pixels[0].red);
5765 pixel->green=gamma*MeshInterpolate(&delta,pixels[2].green,
5766 pixels[3].green,pixels[0].green);
5767 pixel->blue=gamma*MeshInterpolate(&delta,pixels[2].blue,
5768 pixels[3].blue,pixels[0].blue);
5769 if (image->colorspace == CMYKColorspace)
5770 pixel->black=gamma*MeshInterpolate(&delta,pixels[2].black,
5771 pixels[3].black,pixels[0].black);
5772 gamma=MeshInterpolate(&delta,1.0,1.0,1.0);
5773 pixel->alpha=gamma*MeshInterpolate(&delta,pixels[2].alpha,
5774 pixels[3].alpha,pixels[0].alpha);
5775 }
5776 else
5777 {
5778 /*
5779 Top-right triangle (pixel:1 , diagonal: 0-3).
5780 */
5781 delta.x=1.0-delta.x;
5782 gamma=MeshInterpolate(&delta,alpha[1],alpha[0],alpha[3]);
5783 gamma=PerceptibleReciprocal(gamma);
5784 pixel->red=gamma*MeshInterpolate(&delta,pixels[1].red,
5785 pixels[0].red,pixels[3].red);
5786 pixel->green=gamma*MeshInterpolate(&delta,pixels[1].green,
5787 pixels[0].green,pixels[3].green);
5788 pixel->blue=gamma*MeshInterpolate(&delta,pixels[1].blue,
5789 pixels[0].blue,pixels[3].blue);
5790 if (image->colorspace == CMYKColorspace)
5791 pixel->black=gamma*MeshInterpolate(&delta,pixels[1].black,
5792 pixels[0].black,pixels[3].black);
5793 gamma=MeshInterpolate(&delta,1.0,1.0,1.0);
5794 pixel->alpha=gamma*MeshInterpolate(&delta,pixels[1].alpha,
5795 pixels[0].alpha,pixels[3].alpha);
5796 }
5797 }
5798 else
5799 {
5800 /*
5801 Diagonal 1-2 NE-SW.
5802 */
5803 if (delta.x <= (1.0-delta.y))
5804 {
5805 /*
5806 Top-left triangle (pixel: 0, diagonal: 1-2).
5807 */
5808 gamma=MeshInterpolate(&delta,alpha[0],alpha[1],alpha[2]);
5809 gamma=PerceptibleReciprocal(gamma);
5810 pixel->red=gamma*MeshInterpolate(&delta,pixels[0].red,
5811 pixels[1].red,pixels[2].red);
5812 pixel->green=gamma*MeshInterpolate(&delta,pixels[0].green,
5813 pixels[1].green,pixels[2].green);
5814 pixel->blue=gamma*MeshInterpolate(&delta,pixels[0].blue,
5815 pixels[1].blue,pixels[2].blue);
5816 if (image->colorspace == CMYKColorspace)
5817 pixel->black=gamma*MeshInterpolate(&delta,pixels[0].black,
5818 pixels[1].black,pixels[2].black);
5819 gamma=MeshInterpolate(&delta,1.0,1.0,1.0);
5820 pixel->alpha=gamma*MeshInterpolate(&delta,pixels[0].alpha,
5821 pixels[1].alpha,pixels[2].alpha);
5822 }
5823 else
5824 {
5825 /*
5826 Bottom-right triangle (pixel: 3, diagonal: 1-2).
5827 */
5828 delta.x=1.0-delta.x;
5829 delta.y=1.0-delta.y;
5830 gamma=MeshInterpolate(&delta,alpha[3],alpha[2],alpha[1]);
5831 gamma=PerceptibleReciprocal(gamma);
5832 pixel->red=gamma*MeshInterpolate(&delta,pixels[3].red,
5833 pixels[2].red,pixels[1].red);
5834 pixel->green=gamma*MeshInterpolate(&delta,pixels[3].green,
5835 pixels[2].green,pixels[1].green);
5836 pixel->blue=gamma*MeshInterpolate(&delta,pixels[3].blue,
5837 pixels[2].blue,pixels[1].blue);
5838 if (image->colorspace == CMYKColorspace)
5839 pixel->black=gamma*MeshInterpolate(&delta,pixels[3].black,
5840 pixels[2].black,pixels[1].black);
5841 gamma=MeshInterpolate(&delta,1.0,1.0,1.0);
5842 pixel->alpha=gamma*MeshInterpolate(&delta,pixels[3].alpha,
5843 pixels[2].alpha,pixels[1].alpha);
5844 }
5845 }
5846 break;
5847 }
5848 case NearestInterpolatePixel:
5849 {
5850 x_offset=CastDoubleToLong(floor(x+0.5));
5851 y_offset=CastDoubleToLong(floor(y+0.5));
5852 p=GetCacheViewVirtualPixels(image_view,x_offset,y_offset,1,1,exception);
5853 if (p == (const Quantum *) NULL)
5854 {
5855 status=MagickFalse;
5856 break;
5857 }
5858 GetPixelInfoPixel(image,p,pixel);
5859 break;
5860 }
5861 case SplineInterpolatePixel:
5862 {
5863 double
5864 cx[4],
5865 cy[4];
5866
5867 p=GetCacheViewVirtualPixels(image_view,x_offset-1,y_offset-1,4,4,
5868 exception);
5869 if (p == (const Quantum *) NULL)
5870 {
5871 status=MagickFalse;
5872 break;
5873 }
5874 for (i=0; i < 16L; i++)
5875 AlphaBlendPixelInfo(image,p+i*GetPixelChannels(image),pixels+i,alpha+i);
5876 SplineWeights((double) (x-x_offset),&cx);
5877 SplineWeights((double) (y-y_offset),&cy);
5878 pixel->red=(cy[0]*(cx[0]*pixels[0].red+cx[1]*pixels[1].red+cx[2]*
5879 pixels[2].red+cx[3]*pixels[3].red)+cy[1]*(cx[0]*pixels[4].red+cx[1]*
5880 pixels[5].red+cx[2]*pixels[6].red+cx[3]*pixels[7].red)+cy[2]*(cx[0]*
5881 pixels[8].red+cx[1]*pixels[9].red+cx[2]*pixels[10].red+cx[3]*
5882 pixels[11].red)+cy[3]*(cx[0]*pixels[12].red+cx[1]*pixels[13].red+cx[2]*
5883 pixels[14].red+cx[3]*pixels[15].red));
5884 pixel->green=(cy[0]*(cx[0]*pixels[0].green+cx[1]*pixels[1].green+cx[2]*
5885 pixels[2].green+cx[3]*pixels[3].green)+cy[1]*(cx[0]*pixels[4].green+
5886 cx[1]*pixels[5].green+cx[2]*pixels[6].green+cx[3]*pixels[7].green)+
5887 cy[2]*(cx[0]*pixels[8].green+cx[1]*pixels[9].green+cx[2]*
5888 pixels[10].green+cx[3]*pixels[11].green)+cy[3]*(cx[0]*pixels[12].green+
5889 cx[1]*pixels[13].green+cx[2]*pixels[14].green+cx[3]*pixels[15].green));
5890 pixel->blue=(cy[0]*(cx[0]*pixels[0].blue+cx[1]*pixels[1].blue+cx[2]*
5891 pixels[2].blue+cx[3]*pixels[3].blue)+cy[1]*(cx[0]*pixels[4].blue+cx[1]*
5892 pixels[5].blue+cx[2]*pixels[6].blue+cx[3]*pixels[7].blue)+cy[2]*(cx[0]*
5893 pixels[8].blue+cx[1]*pixels[9].blue+cx[2]*pixels[10].blue+cx[3]*
5894 pixels[11].blue)+cy[3]*(cx[0]*pixels[12].blue+cx[1]*pixels[13].blue+
5895 cx[2]*pixels[14].blue+cx[3]*pixels[15].blue));
5896 if (image->colorspace == CMYKColorspace)
5897 pixel->black=(cy[0]*(cx[0]*pixels[0].black+cx[1]*pixels[1].black+cx[2]*
5898 pixels[2].black+cx[3]*pixels[3].black)+cy[1]*(cx[0]*pixels[4].black+
5899 cx[1]*pixels[5].black+cx[2]*pixels[6].black+cx[3]*pixels[7].black)+
5900 cy[2]*(cx[0]*pixels[8].black+cx[1]*pixels[9].black+cx[2]*
5901 pixels[10].black+cx[3]*pixels[11].black)+cy[3]*(cx[0]*
5902 pixels[12].black+cx[1]*pixels[13].black+cx[2]*pixels[14].black+cx[3]*
5903 pixels[15].black));
5904 pixel->alpha=(cy[0]*(cx[0]*pixels[0].alpha+cx[1]*pixels[1].alpha+cx[2]*
5905 pixels[2].alpha+cx[3]*pixels[3].alpha)+cy[1]*(cx[0]*pixels[4].alpha+
5906 cx[1]*pixels[5].alpha+cx[2]*pixels[6].alpha+cx[3]*pixels[7].alpha)+
5907 cy[2]*(cx[0]*pixels[8].alpha+cx[1]*pixels[9].alpha+cx[2]*
5908 pixels[10].alpha+cx[3]*pixels[11].alpha)+cy[3]*(cx[0]*pixels[12].alpha+
5909 cx[1]*pixels[13].alpha+cx[2]*pixels[14].alpha+cx[3]*pixels[15].alpha));
5910 break;
5911 }
5912 }
5913 return(status);
5914 }
5915
5916 /*
5917 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5918 % %
5919 % %
5920 % %
5921 + I s F u z z y E q u i v a l e n c e P i x e l %
5922 % %
5923 % %
5924 % %
5925 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5926 %
5927 % IsFuzzyEquivalencePixel() returns MagickTrue if the distance between two
5928 % pixels is less than the specified distance in a linear three (or four)
5929 % dimensional color space.
5930 %
5931 % The format of the IsFuzzyEquivalencePixel method is:
5932 %
5933 % void IsFuzzyEquivalencePixel(const Image *source,const Quantum *p,
5934 % const Image *destination,const Quantum *q)
5935 %
5936 % A description of each parameter follows:
5937 %
5938 % o source: the source image.
5939 %
5940 % o p: Pixel p.
5941 %
5942 % o destination: the destination image.
5943 %
5944 % o q: Pixel q.
5945 %
5946 */
IsFuzzyEquivalencePixel(const Image * source,const Quantum * p,const Image * destination,const Quantum * q)5947 MagickExport MagickBooleanType IsFuzzyEquivalencePixel(const Image *source,
5948 const Quantum *p,const Image *destination,const Quantum *q)
5949 {
5950 double
5951 fuzz,
5952 pixel;
5953
5954 double
5955 distance,
5956 scale;
5957
5958 fuzz=GetFuzzyColorDistance(source,destination);
5959 scale=1.0;
5960 distance=0.0;
5961 if (source->alpha_trait != UndefinedPixelTrait ||
5962 destination->alpha_trait != UndefinedPixelTrait)
5963 {
5964 /*
5965 Transparencies are involved - set alpha distance
5966 */
5967 pixel=GetPixelAlpha(source,p)-(double) GetPixelAlpha(destination,q);
5968 distance=pixel*pixel;
5969 if (distance > fuzz)
5970 return(MagickFalse);
5971 /*
5972 Generate a alpha scaling factor to generate a 4D cone on colorspace
5973 Note that if one color is transparent, distance has no color component.
5974 */
5975 if (source->alpha_trait != UndefinedPixelTrait)
5976 scale=QuantumScale*GetPixelAlpha(source,p);
5977 if (destination->alpha_trait != UndefinedPixelTrait)
5978 scale*=QuantumScale*GetPixelAlpha(destination,q);
5979 if (scale <= MagickEpsilon)
5980 return(MagickTrue);
5981 }
5982 /*
5983 RGB or CMY color cube
5984 */
5985 distance*=3.0; /* rescale appropriately */
5986 fuzz*=3.0;
5987 pixel=GetPixelRed(source,p)-(double) GetPixelRed(destination,q);
5988 if (IsHueCompatibleColorspace(source->colorspace) != MagickFalse)
5989 {
5990 /*
5991 Compute an arc distance for hue. It should be a vector angle of
5992 'S'/'W' length with 'L'/'B' forming appropriate cones.
5993 */
5994 if (fabs((double) pixel) > (QuantumRange/2))
5995 pixel-=QuantumRange;
5996 pixel*=2.0;
5997 }
5998 distance+=scale*pixel*pixel;
5999 if (distance > fuzz)
6000 return(MagickFalse);
6001 pixel=GetPixelGreen(source,p)-(double) GetPixelGreen(destination,q);
6002 distance+=scale*pixel*pixel;
6003 if (distance > fuzz)
6004 return(MagickFalse);
6005 pixel=GetPixelBlue(source,p)-(double) GetPixelBlue(destination,q);
6006 distance+=scale*pixel*pixel;
6007 if (distance > fuzz)
6008 return(MagickFalse);
6009 return(MagickTrue);
6010 }
6011
6012 /*
6013 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6014 % %
6015 % %
6016 % %
6017 + 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 %
6018 % %
6019 % %
6020 % %
6021 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6022 %
6023 % IsFuzzyEquivalencePixelInfo() returns true if the distance between two
6024 % colors is less than the specified distance in a linear three (or four)
6025 % dimensional color space.
6026 %
6027 % This implements the equivalent of:
6028 % fuzz < sqrt(color_distance^2 * u.a*v.a + alpha_distance^2)
6029 %
6030 % Which produces a multi-dimensional cone for that colorspace along the
6031 % transparency vector.
6032 %
6033 % For example for an RGB:
6034 % color_distance^2 = ( (u.r-v.r)^2 + (u.g-v.g)^2 + (u.b-v.b)^2 ) / 3
6035 %
6036 % See https://imagemagick.org/Usage/bugs/fuzz_distance/
6037 %
6038 % Hue colorspace distances need more work. Hue is not a distance, it is an
6039 % angle!
6040 %
6041 % A check that q is in the same color space as p should be made and the
6042 % appropriate mapping made. -- Anthony Thyssen 8 December 2010
6043 %
6044 % The format of the IsFuzzyEquivalencePixelInfo method is:
6045 %
6046 % MagickBooleanType IsFuzzyEquivalencePixelInfo(const PixelInfo *p,
6047 % const PixelInfo *q)
6048 %
6049 % A description of each parameter follows:
6050 %
6051 % o p: Pixel p.
6052 %
6053 % o q: Pixel q.
6054 %
6055 */
IsFuzzyEquivalencePixelInfo(const PixelInfo * p,const PixelInfo * q)6056 MagickExport MagickBooleanType IsFuzzyEquivalencePixelInfo(const PixelInfo *p,
6057 const PixelInfo *q)
6058 {
6059 double
6060 fuzz,
6061 pixel;
6062
6063 double
6064 scale,
6065 distance;
6066
6067 fuzz=(double) MagickMax(MagickMax(p->fuzz,q->fuzz),(MagickRealType)
6068 MagickSQ1_2);
6069 fuzz*=fuzz;
6070 scale=1.0;
6071 distance=0.0;
6072 if ((p->alpha_trait != UndefinedPixelTrait) ||
6073 (q->alpha_trait != UndefinedPixelTrait))
6074 {
6075 /*
6076 Transparencies are involved - set alpha distance.
6077 */
6078 pixel=(p->alpha_trait != UndefinedPixelTrait ? p->alpha : OpaqueAlpha)-
6079 (q->alpha_trait != UndefinedPixelTrait ? q->alpha : OpaqueAlpha);
6080 distance=pixel*pixel;
6081 if (distance > fuzz)
6082 return(MagickFalse);
6083 /*
6084 Generate a alpha scaling factor to generate a 4D cone on colorspace.
6085 If one color is transparent, distance has no color component.
6086 */
6087 if (p->alpha_trait != UndefinedPixelTrait)
6088 scale=(QuantumScale*p->alpha);
6089 if (q->alpha_trait != UndefinedPixelTrait)
6090 scale*=(QuantumScale*q->alpha);
6091 if (scale <= MagickEpsilon )
6092 return(MagickTrue);
6093 }
6094 /*
6095 CMYK create a CMY cube with a multi-dimensional cone toward black.
6096 */
6097 if (p->colorspace == CMYKColorspace)
6098 {
6099 pixel=p->black-q->black;
6100 distance+=pixel*pixel*scale;
6101 if (distance > fuzz)
6102 return(MagickFalse);
6103 scale*=(double) (QuantumScale*(QuantumRange-p->black));
6104 scale*=(double) (QuantumScale*(QuantumRange-q->black));
6105 }
6106 /*
6107 RGB or CMY color cube.
6108 */
6109 distance*=3.0; /* rescale appropriately */
6110 fuzz*=3.0;
6111 pixel=p->red-q->red;
6112 if (IsHueCompatibleColorspace(p->colorspace) != MagickFalse)
6113 {
6114 /*
6115 This calculates a arc distance for hue-- it should be a vector
6116 angle of 'S'/'W' length with 'L'/'B' forming appropriate cones.
6117 In other words this is a hack - Anthony.
6118 */
6119 if (fabs((double) pixel) > (QuantumRange/2))
6120 pixel-=QuantumRange;
6121 pixel*=2.0;
6122 }
6123 distance+=pixel*pixel*scale;
6124 if (distance > fuzz)
6125 return(MagickFalse);
6126 pixel=p->green-q->green;
6127 distance+=pixel*pixel*scale;
6128 if (distance > fuzz)
6129 return(MagickFalse);
6130 pixel=p->blue-q->blue;
6131 distance+=pixel*pixel*scale;
6132 if (distance > fuzz)
6133 return(MagickFalse);
6134 return(MagickTrue);
6135 }
6136
6137 /*
6138 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6139 % %
6140 % %
6141 % %
6142 % S e t P i x e l C h a n n e l M a s k %
6143 % %
6144 % %
6145 % %
6146 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6147 %
6148 % SetPixelChannelMask() sets the pixel channel map from the specified channel
6149 % mask.
6150 %
6151 % The format of the SetPixelChannelMask method is:
6152 %
6153 % ChannelType SetPixelChannelMask(Image *image,
6154 % const ChannelType channel_mask)
6155 %
6156 % A description of each parameter follows:
6157 %
6158 % o image: the image.
6159 %
6160 % o channel_mask: the channel mask.
6161 %
6162 */
6163
LogPixelChannels(const Image * image)6164 static void LogPixelChannels(const Image *image)
6165 {
6166 ssize_t
6167 i;
6168
6169 (void) LogMagickEvent(PixelEvent,GetMagickModule(),"%s[%08x]",
6170 image->filename,image->channel_mask);
6171 for (i=0; i < (ssize_t) image->number_channels; i++)
6172 {
6173 char
6174 channel_name[MagickPathExtent],
6175 traits[MagickPathExtent];
6176
6177 const char
6178 *name;
6179
6180 PixelChannel
6181 channel;
6182
6183 channel=GetPixelChannelChannel(image,i);
6184 switch (channel)
6185 {
6186 case RedPixelChannel:
6187 {
6188 name="red";
6189 if (image->colorspace == CMYKColorspace)
6190 name="cyan";
6191 if ((image->colorspace == LinearGRAYColorspace) ||
6192 (image->colorspace == GRAYColorspace))
6193 name="gray";
6194 break;
6195 }
6196 case GreenPixelChannel:
6197 {
6198 name="green";
6199 if (image->colorspace == CMYKColorspace)
6200 name="magenta";
6201 break;
6202 }
6203 case BluePixelChannel:
6204 {
6205 name="blue";
6206 if (image->colorspace == CMYKColorspace)
6207 name="yellow";
6208 break;
6209 }
6210 case BlackPixelChannel:
6211 {
6212 name="black";
6213 if (image->storage_class == PseudoClass)
6214 name="index";
6215 break;
6216 }
6217 case IndexPixelChannel:
6218 {
6219 name="index";
6220 break;
6221 }
6222 case AlphaPixelChannel:
6223 {
6224 name="alpha";
6225 break;
6226 }
6227 case ReadMaskPixelChannel:
6228 {
6229 name="read-mask";
6230 break;
6231 }
6232 case WriteMaskPixelChannel:
6233 {
6234 name="write-mask";
6235 break;
6236 }
6237 case CompositeMaskPixelChannel:
6238 {
6239 name="composite-mask";
6240 break;
6241 }
6242 case MetaPixelChannel:
6243 {
6244 name="meta";
6245 break;
6246 }
6247 default:
6248 name="undefined";
6249 }
6250 if (image->colorspace == UndefinedColorspace)
6251 {
6252 (void) FormatLocaleString(channel_name,MagickPathExtent,"%.20g",
6253 (double) channel);
6254 name=(const char *) channel_name;
6255 }
6256 *traits='\0';
6257 if ((GetPixelChannelTraits(image,channel) & UpdatePixelTrait) != 0)
6258 (void) ConcatenateMagickString(traits,"update,",MagickPathExtent);
6259 if ((GetPixelChannelTraits(image,channel) & BlendPixelTrait) != 0)
6260 (void) ConcatenateMagickString(traits,"blend,",MagickPathExtent);
6261 if ((GetPixelChannelTraits(image,channel) & CopyPixelTrait) != 0)
6262 (void) ConcatenateMagickString(traits,"copy,",MagickPathExtent);
6263 if (*traits == '\0')
6264 (void) ConcatenateMagickString(traits,"undefined,",MagickPathExtent);
6265 traits[strlen(traits)-1]='\0';
6266 (void) LogMagickEvent(PixelEvent,GetMagickModule()," %.20g: %s (%s)",
6267 (double) i,name,traits);
6268 }
6269 }
6270
SetPixelChannelMask(Image * image,const ChannelType channel_mask)6271 MagickExport ChannelType SetPixelChannelMask(Image *image,
6272 const ChannelType channel_mask)
6273 {
6274 #define GetChannelBit(mask,bit) (((size_t) (mask) >> (size_t) (bit)) & 0x01)
6275
6276 ChannelType
6277 mask;
6278
6279 ssize_t
6280 i;
6281
6282 assert(image != (Image *) NULL);
6283 assert(image->signature == MagickCoreSignature);
6284 if (image->debug != MagickFalse)
6285 (void) LogMagickEvent(PixelEvent,GetMagickModule(),"%s[%08x]",
6286 image->filename,channel_mask);
6287 mask=image->channel_mask;
6288 image->channel_mask=channel_mask;
6289 for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
6290 {
6291 PixelChannel channel = GetPixelChannelChannel(image,i);
6292 if (GetChannelBit(channel_mask,channel) == 0)
6293 {
6294 SetPixelChannelTraits(image,channel,CopyPixelTrait);
6295 continue;
6296 }
6297 if (channel == AlphaPixelChannel)
6298 {
6299 if ((image->alpha_trait & CopyPixelTrait) != 0)
6300 {
6301 SetPixelChannelTraits(image,channel,CopyPixelTrait);
6302 continue;
6303 }
6304 SetPixelChannelTraits(image,channel,UpdatePixelTrait);
6305 continue;
6306 }
6307 if (image->alpha_trait != UndefinedPixelTrait)
6308 {
6309 SetPixelChannelTraits(image,channel,(const PixelTrait)
6310 (UpdatePixelTrait | BlendPixelTrait));
6311 continue;
6312 }
6313 SetPixelChannelTraits(image,channel,UpdatePixelTrait);
6314 }
6315 if (image->storage_class == PseudoClass)
6316 SetPixelChannelTraits(image,IndexPixelChannel,CopyPixelTrait);
6317 if ((image->channels & ReadMaskChannel) != 0)
6318 SetPixelChannelTraits(image,ReadMaskPixelChannel,CopyPixelTrait);
6319 if ((image->channels & WriteMaskChannel) != 0)
6320 SetPixelChannelTraits(image,WriteMaskPixelChannel,CopyPixelTrait);
6321 if ((image->channels & CompositeMaskChannel) != 0)
6322 SetPixelChannelTraits(image,CompositeMaskPixelChannel,CopyPixelTrait);
6323 if (image->debug != MagickFalse)
6324 LogPixelChannels(image);
6325 return(mask);
6326 }
6327
6328 /*
6329 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6330 % %
6331 % %
6332 % %
6333 % S e t P i x e l M e t a C h a n n e l s %
6334 % %
6335 % %
6336 % %
6337 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6338 %
6339 % SetPixelMetaChannels() sets the image meta channels.
6340 %
6341 % The format of the SetPixelMetaChannels method is:
6342 %
6343 % MagickBooleanType SetPixelMetaChannels(Image *image,
6344 % const size_t number_meta_channels,ExceptionInfo *exception)
6345 %
6346 % A description of each parameter follows:
6347 %
6348 % o image: the image.
6349 %
6350 % o number_meta_channels: the number of meta channels.
6351 %
6352 % o exception: return any errors or warnings in this structure.
6353 %
6354 */
SetPixelMetaChannels(Image * image,const size_t number_meta_channels,ExceptionInfo * exception)6355 MagickExport MagickBooleanType SetPixelMetaChannels(Image *image,
6356 const size_t number_meta_channels,ExceptionInfo *exception)
6357 {
6358 image->number_meta_channels=number_meta_channels;
6359 InitializePixelChannelMap(image);
6360 return(SyncImagePixelCache(image,exception));
6361 }
6362
6363 /*
6364 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6365 % %
6366 % %
6367 % %
6368 % S o r t I m a g e P i x e l s %
6369 % %
6370 % %
6371 % %
6372 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6373 %
6374 % SortImagePixels() sorts pixels within each scanline in ascending order of
6375 % intensity.
6376 %
6377 % The format of the SortImagePixels method is:
6378 %
6379 % MagickBooleanType SortImagePixels(Image *image,ExceptionInfo *exception)
6380 %
6381 % A description of each parameter follows:
6382 %
6383 % o image: the image.
6384 %
6385 % o exception: return any errors or warnings in this structure.
6386 %
6387 */
SortImagePixels(Image * image,ExceptionInfo * exception)6388 MagickExport MagickBooleanType SortImagePixels(Image *image,
6389 ExceptionInfo *exception)
6390 {
6391 #define SolarizeImageTag "Solarize/Image"
6392
6393 CacheView
6394 *image_view;
6395
6396 MagickBooleanType
6397 status;
6398
6399 MagickOffsetType
6400 progress;
6401
6402 ssize_t
6403 y;
6404
6405 /*
6406 Sort image pixels.
6407 */
6408 assert(image != (Image *) NULL);
6409 assert(image->signature == MagickCoreSignature);
6410 if (image->debug != MagickFalse)
6411 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
6412 status=MagickTrue;
6413 progress=0;
6414 image_view=AcquireAuthenticCacheView(image,exception);
6415 #if defined(MAGICKCORE_OPENMP_SUPPORT)
6416 #pragma omp parallel for schedule(static) shared(progress,status) \
6417 magick_number_threads(image,image,image->rows,1)
6418 #endif
6419 for (y=0; y < (ssize_t) image->rows; y++)
6420 {
6421 Quantum
6422 *magick_restrict q;
6423
6424 ssize_t
6425 x;
6426
6427 if (status == MagickFalse)
6428 continue;
6429 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
6430 if (q == (Quantum *) NULL)
6431 {
6432 status=MagickFalse;
6433 continue;
6434 }
6435 for (x=0; x < (ssize_t) image->columns-1; x++)
6436 {
6437 MagickRealType
6438 current,
6439 previous;
6440
6441 ssize_t
6442 j;
6443
6444 previous=GetPixelIntensity(image,q);
6445 for (j=0; j < (ssize_t) (image->columns-x-1); j++)
6446 {
6447 current=GetPixelIntensity(image,q+(j+1)*GetPixelChannels(image));
6448 if (previous > current)
6449 {
6450 Quantum
6451 pixel[MaxPixelChannels];
6452
6453 /*
6454 Swap adjacent pixels.
6455 */
6456 (void) memcpy(pixel,q+j*GetPixelChannels(image),
6457 GetPixelChannels(image)*sizeof(Quantum));
6458 (void) memcpy(q+j*GetPixelChannels(image),q+(j+1)*
6459 GetPixelChannels(image),GetPixelChannels(image)*sizeof(Quantum));
6460 (void) memcpy(q+(j+1)*GetPixelChannels(image),pixel,
6461 GetPixelChannels(image)*sizeof(Quantum));
6462 }
6463 else
6464 previous=current;
6465 }
6466 }
6467 if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
6468 status=MagickFalse;
6469 if (image->progress_monitor != (MagickProgressMonitor) NULL)
6470 {
6471 MagickBooleanType
6472 proceed;
6473
6474 #if defined(MAGICKCORE_OPENMP_SUPPORT)
6475 #pragma omp atomic
6476 #endif
6477 progress++;
6478 proceed=SetImageProgress(image,SolarizeImageTag,progress,image->rows);
6479 if (proceed == MagickFalse)
6480 status=MagickFalse;
6481 }
6482 }
6483 image_view=DestroyCacheView(image_view);
6484 return(status);
6485 }
6486