1 /*
2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3 % %
4 % %
5 % %
6 % SSSSS TTTTT RRRR EEEEE AAA M M %
7 % SS T R R E A A MM MM %
8 % SSS T RRRR EEE AAAAA M M M %
9 % SS T R R E A A M M %
10 % SSSSS T R R EEEEE A A M M %
11 % %
12 % %
13 % MagickCore Pixel Stream Methods %
14 % %
15 % Software Design %
16 % Cristy %
17 % March 2000 %
18 % %
19 % %
20 % Copyright 1999-2021 ImageMagick Studio LLC, a non-profit organization %
21 % dedicated to making software imaging solutions freely available. %
22 % %
23 % You may not use this file except in compliance with the License. You may %
24 % obtain a copy of the License at %
25 % %
26 % https://imagemagick.org/script/license.php %
27 % %
28 % Unless required by applicable law or agreed to in writing, software %
29 % distributed under the License is distributed on an "AS IS" BASIS, %
30 % WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %
31 % See the License for the specific language governing permissions and %
32 % limitations under the License. %
33 % %
34 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
35 %
36 %
37 %
38 */
39
40 /*
41 Include declarations.
42 */
43 #include "MagickCore/studio.h"
44 #include "MagickCore/blob.h"
45 #include "MagickCore/blob-private.h"
46 #include "MagickCore/cache.h"
47 #include "MagickCore/cache-private.h"
48 #include "MagickCore/color-private.h"
49 #include "MagickCore/composite-private.h"
50 #include "MagickCore/constitute.h"
51 #include "MagickCore/exception.h"
52 #include "MagickCore/exception-private.h"
53 #include "MagickCore/geometry.h"
54 #include "MagickCore/memory_.h"
55 #include "MagickCore/memory-private.h"
56 #include "MagickCore/pixel.h"
57 #include "MagickCore/pixel-accessor.h"
58 #include "MagickCore/policy.h"
59 #include "MagickCore/quantum.h"
60 #include "MagickCore/quantum-private.h"
61 #include "MagickCore/semaphore.h"
62 #include "MagickCore/stream.h"
63 #include "MagickCore/stream-private.h"
64 #include "MagickCore/string_.h"
65
66 /*
67 Typedef declaractions.
68 */
69 struct _StreamInfo
70 {
71 const ImageInfo
72 *image_info;
73
74 const Image
75 *image;
76
77 Image
78 *stream;
79
80 QuantumInfo
81 *quantum_info;
82
83 char
84 *map;
85
86 StorageType
87 storage_type;
88
89 unsigned char
90 *pixels;
91
92 RectangleInfo
93 extract_info;
94
95 ssize_t
96 y;
97
98 ExceptionInfo
99 *exception;
100
101 const void
102 *client_data;
103
104 size_t
105 signature;
106 };
107
108 /*
109 Declare pixel cache interfaces.
110 */
111 #if defined(__cplusplus) || defined(c_plusplus)
112 extern "C" {
113 #endif
114
115 static const Quantum
116 *GetVirtualPixelStream(const Image *,const VirtualPixelMethod,const ssize_t,
117 const ssize_t,const size_t,const size_t,ExceptionInfo *);
118
119 static MagickBooleanType
120 StreamImagePixels(const StreamInfo *,const Image *,ExceptionInfo *),
121 SyncAuthenticPixelsStream(Image *,ExceptionInfo *);
122
123 static Quantum
124 *QueueAuthenticPixelsStream(Image *,const ssize_t,const ssize_t,const size_t,
125 const size_t,ExceptionInfo *);
126
127 #if defined(__cplusplus) || defined(c_plusplus)
128 }
129 #endif
130
131 static ssize_t
132 cache_anonymous_memory = (-1);
133
134 /*
135 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
136 % %
137 % %
138 % %
139 + A c q u i r e S t r e a m I n f o %
140 % %
141 % %
142 % %
143 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
144 %
145 % AcquireStreamInfo() allocates the StreamInfo structure.
146 %
147 % The format of the AcquireStreamInfo method is:
148 %
149 % StreamInfo *AcquireStreamInfo(const ImageInfo *image_info,
150 % ExceptionInfo *exception)
151 %
152 % A description of each parameter follows:
153 %
154 % o image_info: the image info.
155 %
156 % o exception: return any errors or warnings in this structure.
157 %
158 */
AcquireStreamInfo(const ImageInfo * image_info,ExceptionInfo * exception)159 MagickExport StreamInfo *AcquireStreamInfo(const ImageInfo *image_info,
160 ExceptionInfo *exception)
161 {
162 StreamInfo
163 *stream_info;
164
165 stream_info=(StreamInfo *) AcquireCriticalMemory(sizeof(*stream_info));
166 (void) memset(stream_info,0,sizeof(*stream_info));
167 stream_info->pixels=(unsigned char *) MagickAssumeAligned(
168 AcquireAlignedMemory(1,sizeof(*stream_info->pixels)));
169 if (stream_info->pixels == (unsigned char *) NULL)
170 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
171 stream_info->map=ConstantString("RGB");
172 stream_info->storage_type=CharPixel;
173 stream_info->stream=AcquireImage(image_info,exception);
174 stream_info->signature=MagickCoreSignature;
175 return(stream_info);
176 }
177
178 /*
179 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
180 % %
181 % %
182 % %
183 + D e s t r o y P i x e l S t r e a m %
184 % %
185 % %
186 % %
187 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
188 %
189 % DestroyPixelStream() deallocates memory associated with the pixel stream.
190 %
191 % The format of the DestroyPixelStream() method is:
192 %
193 % void DestroyPixelStream(Image *image)
194 %
195 % A description of each parameter follows:
196 %
197 % o image: the image.
198 %
199 */
200
RelinquishStreamPixels(CacheInfo * cache_info)201 static inline void RelinquishStreamPixels(CacheInfo *cache_info)
202 {
203 assert(cache_info != (CacheInfo *) NULL);
204 if (cache_info->pixels != (Quantum *) NULL)
205 {
206 if (cache_info->mapped == MagickFalse)
207 (void) RelinquishAlignedMemory(cache_info->pixels);
208 else
209 (void) UnmapBlob(cache_info->pixels,(size_t) cache_info->length);
210 }
211 cache_info->pixels=(Quantum *) NULL;
212 cache_info->metacontent=(void *) NULL;
213 cache_info->length=0;
214 cache_info->mapped=MagickFalse;
215 }
216
DestroyPixelStream(Image * image)217 static void DestroyPixelStream(Image *image)
218 {
219 CacheInfo
220 *cache_info;
221
222 MagickBooleanType
223 destroy;
224
225 assert(image != (Image *) NULL);
226 assert(image->signature == MagickCoreSignature);
227 if (image->debug != MagickFalse)
228 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
229 cache_info=(CacheInfo *) image->cache;
230 assert(cache_info->signature == MagickCoreSignature);
231 destroy=MagickFalse;
232 LockSemaphoreInfo(cache_info->semaphore);
233 cache_info->reference_count--;
234 if (cache_info->reference_count == 0)
235 destroy=MagickTrue;
236 UnlockSemaphoreInfo(cache_info->semaphore);
237 if (destroy == MagickFalse)
238 return;
239 RelinquishStreamPixels(cache_info);
240 if (cache_info->nexus_info != (NexusInfo **) NULL)
241 cache_info->nexus_info=DestroyPixelCacheNexus(cache_info->nexus_info,
242 cache_info->number_threads);
243 if (cache_info->file_semaphore != (SemaphoreInfo *) NULL)
244 RelinquishSemaphoreInfo(&cache_info->file_semaphore);
245 if (cache_info->semaphore != (SemaphoreInfo *) NULL)
246 RelinquishSemaphoreInfo(&cache_info->semaphore);
247 cache_info=(CacheInfo *) RelinquishAlignedMemory(cache_info);
248 }
249
250 /*
251 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
252 % %
253 % %
254 % %
255 + D e s t r o y S t r e a m I n f o %
256 % %
257 % %
258 % %
259 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
260 %
261 % DestroyStreamInfo() destroys memory associated with the StreamInfo
262 % structure.
263 %
264 % The format of the DestroyStreamInfo method is:
265 %
266 % StreamInfo *DestroyStreamInfo(StreamInfo *stream_info)
267 %
268 % A description of each parameter follows:
269 %
270 % o stream_info: the stream info.
271 %
272 */
DestroyStreamInfo(StreamInfo * stream_info)273 MagickExport StreamInfo *DestroyStreamInfo(StreamInfo *stream_info)
274 {
275 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
276 assert(stream_info != (StreamInfo *) NULL);
277 assert(stream_info->signature == MagickCoreSignature);
278 if (stream_info->map != (char *) NULL)
279 stream_info->map=DestroyString(stream_info->map);
280 if (stream_info->pixels != (unsigned char *) NULL)
281 stream_info->pixels=(unsigned char *) RelinquishAlignedMemory(
282 stream_info->pixels);
283 if (stream_info->stream != (Image *) NULL)
284 {
285 (void) CloseBlob(stream_info->stream);
286 stream_info->stream=DestroyImage(stream_info->stream);
287 }
288 if (stream_info->quantum_info != (QuantumInfo *) NULL)
289 stream_info->quantum_info=DestroyQuantumInfo(stream_info->quantum_info);
290 stream_info->signature=(~MagickCoreSignature);
291 stream_info=(StreamInfo *) RelinquishMagickMemory(stream_info);
292 return(stream_info);
293 }
294
295 /*
296 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
297 % %
298 % %
299 % %
300 + G e t A u t h e n t i c M e t a c o n t e n t F r o m S t r e a m %
301 % %
302 % %
303 % %
304 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
305 %
306 % GetAuthenticMetacontentFromStream() returns the metacontent corresponding
307 % with the last call to QueueAuthenticPixelsStream() or
308 % GetAuthenticPixelsStream().
309 %
310 % The format of the GetAuthenticMetacontentFromStream() method is:
311 %
312 % void *GetAuthenticMetacontentFromStream(const Image *image)
313 %
314 % A description of each parameter follows:
315 %
316 % o image: the image.
317 %
318 */
GetAuthenticMetacontentFromStream(const Image * image)319 static void *GetAuthenticMetacontentFromStream(const Image *image)
320 {
321 CacheInfo
322 *cache_info;
323
324 assert(image != (Image *) NULL);
325 assert(image->signature == MagickCoreSignature);
326 if (image->debug != MagickFalse)
327 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
328 cache_info=(CacheInfo *) image->cache;
329 assert(cache_info->signature == MagickCoreSignature);
330 return(cache_info->metacontent);
331 }
332
333 /*
334 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
335 % %
336 % %
337 % %
338 + G e t A u t h e n t i c P i x e l S t r e a m %
339 % %
340 % %
341 % %
342 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
343 %
344 % GetAuthenticPixelsStream() gets pixels from the in-memory or disk pixel
345 % cache as defined by the geometry parameters. A pointer to the pixels is
346 % returned if the pixels are transferred, otherwise a NULL is returned. For
347 % streams this method is a no-op.
348 %
349 % The format of the GetAuthenticPixelsStream() method is:
350 %
351 % Quantum *GetAuthenticPixelsStream(Image *image,const ssize_t x,
352 % const ssize_t y,const size_t columns,const size_t rows,
353 % ExceptionInfo *exception)
354 %
355 % A description of each parameter follows:
356 %
357 % o image: the image.
358 %
359 % o x,y,columns,rows: These values define the perimeter of a region of
360 % pixels.
361 %
362 % o exception: return any errors or warnings in this structure.
363 %
364 */
GetAuthenticPixelsStream(Image * image,const ssize_t x,const ssize_t y,const size_t columns,const size_t rows,ExceptionInfo * exception)365 static Quantum *GetAuthenticPixelsStream(Image *image,const ssize_t x,
366 const ssize_t y,const size_t columns,const size_t rows,
367 ExceptionInfo *exception)
368 {
369 Quantum
370 *pixels;
371
372 assert(image != (Image *) NULL);
373 assert(image->signature == MagickCoreSignature);
374 if (image->debug != MagickFalse)
375 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
376 pixels=QueueAuthenticPixelsStream(image,x,y,columns,rows,exception);
377 return(pixels);
378 }
379
380 /*
381 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
382 % %
383 % %
384 % %
385 + G e t A u t h e n t i c P i x e l F r o m S t e a m %
386 % %
387 % %
388 % %
389 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
390 %
391 % GetAuthenticPixelsFromStream() returns the pixels associated with the last
392 % call to QueueAuthenticPixelsStream() or GetAuthenticPixelsStream().
393 %
394 % The format of the GetAuthenticPixelsFromStream() method is:
395 %
396 % Quantum *GetAuthenticPixelsFromStream(const Image image)
397 %
398 % A description of each parameter follows:
399 %
400 % o image: the image.
401 %
402 */
GetAuthenticPixelsFromStream(const Image * image)403 static Quantum *GetAuthenticPixelsFromStream(const Image *image)
404 {
405 CacheInfo
406 *cache_info;
407
408 assert(image != (Image *) NULL);
409 assert(image->signature == MagickCoreSignature);
410 if (image->debug != MagickFalse)
411 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
412 cache_info=(CacheInfo *) image->cache;
413 assert(cache_info->signature == MagickCoreSignature);
414 return(cache_info->pixels);
415 }
416
417 /*
418 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
419 % %
420 % %
421 % %
422 + G e t O n e A u t h e n t i c P i x e l F r o m S t r e a m %
423 % %
424 % %
425 % %
426 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
427 %
428 % GetOneAuthenticPixelFromStream() returns a single pixel at the specified
429 % (x,y) location. The image background color is returned if an error occurs.
430 %
431 % The format of the GetOneAuthenticPixelFromStream() method is:
432 %
433 % MagickBooleanType GetOneAuthenticPixelFromStream(const Image image,
434 % const ssize_t x,const ssize_t y,Quantum *pixel,
435 % ExceptionInfo *exception)
436 %
437 % A description of each parameter follows:
438 %
439 % o image: the image.
440 %
441 % o pixel: return a pixel at the specified (x,y) location.
442 %
443 % o x,y: These values define the location of the pixel to return.
444 %
445 % o exception: return any errors or warnings in this structure.
446 %
447 */
GetOneAuthenticPixelFromStream(Image * image,const ssize_t x,const ssize_t y,Quantum * pixel,ExceptionInfo * exception)448 static MagickBooleanType GetOneAuthenticPixelFromStream(Image *image,
449 const ssize_t x,const ssize_t y,Quantum *pixel,ExceptionInfo *exception)
450 {
451 Quantum
452 *p;
453
454 ssize_t
455 i;
456
457 assert(image != (Image *) NULL);
458 assert(image->signature == MagickCoreSignature);
459 (void) memset(pixel,0,MaxPixelChannels*sizeof(*pixel));
460 p=GetAuthenticPixelsStream(image,x,y,1,1,exception);
461 if (p == (Quantum *) NULL)
462 {
463 pixel[RedPixelChannel]=ClampToQuantum(image->background_color.red);
464 pixel[GreenPixelChannel]=ClampToQuantum(image->background_color.green);
465 pixel[BluePixelChannel]=ClampToQuantum(image->background_color.blue);
466 pixel[BlackPixelChannel]=ClampToQuantum(image->background_color.black);
467 pixel[AlphaPixelChannel]=ClampToQuantum(image->background_color.alpha);
468 return(MagickFalse);
469 }
470 for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
471 {
472 PixelChannel channel = GetPixelChannelChannel(image,i);
473 pixel[channel]=p[i];
474 }
475 return(MagickTrue);
476 }
477
478 /*
479 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
480 % %
481 % %
482 % %
483 + G e t O n e V i r t u a l P i x e l F r o m S t r e a m %
484 % %
485 % %
486 % %
487 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
488 %
489 % GetOneVirtualPixelFromStream() returns a single pixel at the specified
490 % (x.y) location. The image background color is returned if an error occurs.
491 %
492 % The format of the GetOneVirtualPixelFromStream() method is:
493 %
494 % MagickBooleanType GetOneVirtualPixelFromStream(const Image image,
495 % const VirtualPixelMethod virtual_pixel_method,const ssize_t x,
496 % const ssize_t y,Quantum *pixel,ExceptionInfo *exception)
497 %
498 % A description of each parameter follows:
499 %
500 % o image: the image.
501 %
502 % o virtual_pixel_method: the virtual pixel method.
503 %
504 % o x,y: These values define the location of the pixel to return.
505 %
506 % o pixel: return a pixel at the specified (x,y) location.
507 %
508 % o exception: return any errors or warnings in this structure.
509 %
510 */
GetOneVirtualPixelFromStream(const Image * image,const VirtualPixelMethod virtual_pixel_method,const ssize_t x,const ssize_t y,Quantum * pixel,ExceptionInfo * exception)511 static MagickBooleanType GetOneVirtualPixelFromStream(const Image *image,
512 const VirtualPixelMethod virtual_pixel_method,const ssize_t x,const ssize_t y,
513 Quantum *pixel,ExceptionInfo *exception)
514 {
515 const Quantum
516 *p;
517
518 ssize_t
519 i;
520
521 assert(image != (Image *) NULL);
522 assert(image->signature == MagickCoreSignature);
523 (void) memset(pixel,0,MaxPixelChannels*sizeof(*pixel));
524 p=GetVirtualPixelStream(image,virtual_pixel_method,x,y,1,1,exception);
525 if (p == (const Quantum *) NULL)
526 {
527 pixel[RedPixelChannel]=ClampToQuantum(image->background_color.red);
528 pixel[GreenPixelChannel]=ClampToQuantum(image->background_color.green);
529 pixel[BluePixelChannel]=ClampToQuantum(image->background_color.blue);
530 pixel[BlackPixelChannel]=ClampToQuantum(image->background_color.black);
531 pixel[AlphaPixelChannel]=ClampToQuantum(image->background_color.alpha);
532 return(MagickFalse);
533 }
534 for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
535 {
536 PixelChannel channel = GetPixelChannelChannel(image,i);
537 pixel[channel]=p[i];
538 }
539 return(MagickTrue);
540 }
541
542 /*
543 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
544 % %
545 % %
546 % %
547 + G e t S t r e a m I n f o C l i e n t D a t a %
548 % %
549 % %
550 % %
551 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
552 %
553 % GetStreamInfoClientData() gets the stream info client data.
554 %
555 % The format of the GetStreamInfoClientData method is:
556 %
557 % const void *GetStreamInfoClientData(StreamInfo *stream_info)
558 %
559 % A description of each parameter follows:
560 %
561 % o stream_info: the stream info.
562 %
563 */
GetStreamInfoClientData(StreamInfo * stream_info)564 MagickPrivate const void *GetStreamInfoClientData(StreamInfo *stream_info)
565 {
566 assert(stream_info != (StreamInfo *) NULL);
567 assert(stream_info->signature == MagickCoreSignature);
568 return(stream_info->client_data);
569 }
570
571 /*
572 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
573 % %
574 % %
575 % %
576 + G e t V i r t u a l P i x e l s F r o m S t r e a m %
577 % %
578 % %
579 % %
580 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
581 %
582 % GetVirtualPixelsStream() returns the pixels associated with the last call to
583 % QueueAuthenticPixelsStream() or GetVirtualPixelStream().
584 %
585 % The format of the GetVirtualPixelsStream() method is:
586 %
587 % const Quantum *GetVirtualPixelsStream(const Image *image)
588 %
589 % A description of each parameter follows:
590 %
591 % o pixels: return the pixels associated corresponding with the last call to
592 % QueueAuthenticPixelsStream() or GetVirtualPixelStream().
593 %
594 % o image: the image.
595 %
596 */
GetVirtualPixelsStream(const Image * image)597 static const Quantum *GetVirtualPixelsStream(const Image *image)
598 {
599 CacheInfo
600 *cache_info;
601
602 assert(image != (Image *) NULL);
603 assert(image->signature == MagickCoreSignature);
604 if (image->debug != MagickFalse)
605 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
606 cache_info=(CacheInfo *) image->cache;
607 assert(cache_info->signature == MagickCoreSignature);
608 return(cache_info->pixels);
609 }
610
611 /*
612 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
613 % %
614 % %
615 % %
616 + G e t V i r t u a l I n d e x e s F r o m S t r e a m %
617 % %
618 % %
619 % %
620 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
621 %
622 % GetVirtualMetacontentFromStream() returns the associated pixel channels
623 % corresponding with the last call to QueueAuthenticPixelsStream() or
624 % GetVirtualPixelStream().
625 %
626 % The format of the GetVirtualMetacontentFromStream() method is:
627 %
628 % const void *GetVirtualMetacontentFromStream(const Image *image)
629 %
630 % A description of each parameter follows:
631 %
632 % o image: the image.
633 %
634 */
GetVirtualMetacontentFromStream(const Image * image)635 static const void *GetVirtualMetacontentFromStream(const Image *image)
636 {
637 CacheInfo
638 *cache_info;
639
640 assert(image != (Image *) NULL);
641 assert(image->signature == MagickCoreSignature);
642 if (image->debug != MagickFalse)
643 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
644 cache_info=(CacheInfo *) image->cache;
645 assert(cache_info->signature == MagickCoreSignature);
646 return(cache_info->metacontent);
647 }
648
649 /*
650 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
651 % %
652 % %
653 % %
654 + G e t V i r t u a l P i x e l S t r e a m %
655 % %
656 % %
657 % %
658 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
659 %
660 % GetVirtualPixelStream() gets pixels from the in-memory or disk pixel cache as
661 % defined by the geometry parameters. A pointer to the pixels is returned if
662 % the pixels are transferred, otherwise a NULL is returned. For streams this
663 % method is a no-op.
664 %
665 % The format of the GetVirtualPixelStream() method is:
666 %
667 % const Quantum *GetVirtualPixelStream(const Image *image,
668 % const VirtualPixelMethod virtual_pixel_method,const ssize_t x,
669 % const ssize_t y,const size_t columns,const size_t rows,
670 % ExceptionInfo *exception)
671 %
672 % A description of each parameter follows:
673 %
674 % o image: the image.
675 %
676 % o virtual_pixel_method: the virtual pixel method.
677 %
678 % o x,y,columns,rows: These values define the perimeter of a region of
679 % pixels.
680 %
681 % o exception: return any errors or warnings in this structure.
682 %
683 */
684
AcquireStreamPixels(CacheInfo * cache_info,ExceptionInfo * exception)685 static inline MagickBooleanType AcquireStreamPixels(CacheInfo *cache_info,
686 ExceptionInfo *exception)
687 {
688 if (cache_info->length != (MagickSizeType) ((size_t) cache_info->length))
689 return(MagickFalse);
690 if (cache_anonymous_memory < 0)
691 {
692 char
693 *value;
694
695 /*
696 Does the security policy require anonymous mapping for pixel cache?
697 */
698 cache_anonymous_memory=0;
699 value=GetPolicyValue("pixel-cache-memory");
700 if (value == (char *) NULL)
701 value=GetPolicyValue("cache:memory-map");
702 if (LocaleCompare(value,"anonymous") == 0)
703 {
704 #if defined(MAGICKCORE_HAVE_MMAP) && defined(MAP_ANONYMOUS)
705 cache_anonymous_memory=1;
706 #else
707 (void) ThrowMagickException(exception,GetMagickModule(),
708 MissingDelegateError,"DelegateLibrarySupportNotBuiltIn",
709 "'%s' (policy requires anonymous memory mapping)",
710 cache_info->filename);
711 #endif
712 }
713 value=DestroyString(value);
714 }
715 if (cache_anonymous_memory <= 0)
716 {
717 cache_info->mapped=MagickFalse;
718 cache_info->pixels=(Quantum *) MagickAssumeAligned(
719 AcquireAlignedMemory(1,(size_t) cache_info->length));
720 if (cache_info->pixels != (Quantum *) NULL)
721 (void) memset(cache_info->pixels,0,(size_t) cache_info->length);
722 }
723 else
724 {
725 cache_info->mapped=MagickTrue;
726 cache_info->pixels=(Quantum *) MapBlob(-1,IOMode,0,(size_t)
727 cache_info->length);
728 }
729 if (cache_info->pixels == (Quantum *) NULL)
730 {
731 (void) ThrowMagickException(exception,GetMagickModule(),
732 ResourceLimitError,"MemoryAllocationFailed","`%s'",
733 cache_info->filename);
734 return(MagickFalse);
735 }
736 return(MagickTrue);
737 }
738
GetVirtualPixelStream(const Image * image,const VirtualPixelMethod magick_unused (virtual_pixel_method),const ssize_t x,const ssize_t y,const size_t columns,const size_t rows,ExceptionInfo * exception)739 static const Quantum *GetVirtualPixelStream(const Image *image,
740 const VirtualPixelMethod magick_unused(virtual_pixel_method),const ssize_t x,
741 const ssize_t y,const size_t columns,const size_t rows,
742 ExceptionInfo *exception)
743 {
744 CacheInfo
745 *cache_info;
746
747 MagickBooleanType
748 status;
749
750 MagickSizeType
751 number_pixels;
752
753 size_t
754 length;
755
756 magick_unreferenced(virtual_pixel_method);
757
758 /*
759 Validate pixel cache geometry.
760 */
761 assert(image != (const Image *) NULL);
762 assert(image->signature == MagickCoreSignature);
763 if (image->debug != MagickFalse)
764 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
765 if ((x < 0) || (y < 0) ||
766 ((x+(ssize_t) columns) > (ssize_t) image->columns) ||
767 ((y+(ssize_t) rows) > (ssize_t) image->rows) ||
768 (columns == 0) || (rows == 0))
769 {
770 (void) ThrowMagickException(exception,GetMagickModule(),StreamError,
771 "ImageDoesNotContainTheStreamGeometry","`%s'",image->filename);
772 return((Quantum *) NULL);
773 }
774 cache_info=(CacheInfo *) image->cache;
775 assert(cache_info->signature == MagickCoreSignature);
776 /*
777 Pixels are stored in a temporary buffer until they are synced to the cache.
778 */
779 number_pixels=(MagickSizeType) columns*rows;
780 length=(size_t) number_pixels*cache_info->number_channels*sizeof(Quantum);
781 if (cache_info->number_channels == 0)
782 length=(size_t) number_pixels*sizeof(Quantum);
783 if (cache_info->metacontent_extent != 0)
784 length+=number_pixels*cache_info->metacontent_extent;
785 if (cache_info->pixels == (Quantum *) NULL)
786 {
787 cache_info->length=length;
788 status=AcquireStreamPixels(cache_info,exception);
789 if (status == MagickFalse)
790 {
791 cache_info->length=0;
792 return((Quantum *) NULL);
793 }
794 }
795 else
796 if (cache_info->length < length)
797 {
798 RelinquishStreamPixels(cache_info);
799 cache_info->length=length;
800 status=AcquireStreamPixels(cache_info,exception);
801 if (status == MagickFalse)
802 {
803 cache_info->length=0;
804 return((Quantum *) NULL);
805 }
806 }
807 cache_info->metacontent=(void *) NULL;
808 if (cache_info->metacontent_extent != 0)
809 cache_info->metacontent=(void *) (cache_info->pixels+number_pixels*
810 cache_info->number_channels);
811 return(cache_info->pixels);
812 }
813
814 /*
815 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
816 % %
817 % %
818 % %
819 + O p e n S t r e a m %
820 % %
821 % %
822 % %
823 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
824 %
825 % OpenStream() opens a stream for writing by the StreamImage() method.
826 %
827 % The format of the OpenStream method is:
828 %
829 % MagickBooleanType OpenStream(const ImageInfo *image_info,
830 % StreamInfo *stream_info,const char *filename,ExceptionInfo *exception)
831 %
832 % A description of each parameter follows:
833 %
834 % o image_info: the image info.
835 %
836 % o stream_info: the stream info.
837 %
838 % o filename: the stream filename.
839 %
840 % o exception: return any errors or warnings in this structure.
841 %
842 */
OpenStream(const ImageInfo * image_info,StreamInfo * stream_info,const char * filename,ExceptionInfo * exception)843 MagickExport MagickBooleanType OpenStream(const ImageInfo *image_info,
844 StreamInfo *stream_info,const char *filename,ExceptionInfo *exception)
845 {
846 MagickBooleanType
847 status;
848
849 (void) CopyMagickString(stream_info->stream->filename,filename,
850 MagickPathExtent);
851 status=OpenBlob(image_info,stream_info->stream,WriteBinaryBlobMode,exception);
852 return(status);
853 }
854
855 /*
856 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
857 % %
858 % %
859 % %
860 + Q u e u e A u t h e n t i c P i x e l s S t r e a m %
861 % %
862 % %
863 % %
864 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
865 %
866 % QueueAuthenticPixelsStream() allocates an area to store image pixels as
867 % defined by the region rectangle and returns a pointer to the area. This
868 % area is subsequently transferred from the pixel cache with method
869 % SyncAuthenticPixelsStream(). A pointer to the pixels is returned if the
870 % pixels are transferred, otherwise a NULL is returned.
871 %
872 % The format of the QueueAuthenticPixelsStream() method is:
873 %
874 % Quantum *QueueAuthenticPixelsStream(Image *image,const ssize_t x,
875 % const ssize_t y,const size_t columns,const size_t rows,
876 % ExceptionInfo *exception)
877 %
878 % A description of each parameter follows:
879 %
880 % o image: the image.
881 %
882 % o x,y,columns,rows: These values define the perimeter of a region of
883 % pixels.
884 %
885 */
886
ValidatePixelCacheMorphology(const Image * magick_restrict image)887 static inline MagickBooleanType ValidatePixelCacheMorphology(
888 const Image *magick_restrict image)
889 {
890 const CacheInfo
891 *magick_restrict cache_info;
892
893 const PixelChannelMap
894 *magick_restrict p,
895 *magick_restrict q;
896
897 /*
898 Does the image match the pixel cache morphology?
899 */
900 cache_info=(CacheInfo *) image->cache;
901 p=image->channel_map;
902 q=cache_info->channel_map;
903 if ((image->storage_class != cache_info->storage_class) ||
904 (image->colorspace != cache_info->colorspace) ||
905 (image->alpha_trait != cache_info->alpha_trait) ||
906 (image->channels != cache_info->channels) ||
907 (image->columns != cache_info->columns) ||
908 (image->rows != cache_info->rows) ||
909 (image->number_channels != cache_info->number_channels) ||
910 (memcmp(p,q,image->number_channels*sizeof(*p)) != 0) ||
911 (image->metacontent_extent != cache_info->metacontent_extent) ||
912 (cache_info->nexus_info == (NexusInfo **) NULL))
913 return(MagickFalse);
914 return(MagickTrue);
915 }
916
QueueAuthenticPixelsStream(Image * image,const ssize_t x,const ssize_t y,const size_t columns,const size_t rows,ExceptionInfo * exception)917 static Quantum *QueueAuthenticPixelsStream(Image *image,const ssize_t x,
918 const ssize_t y,const size_t columns,const size_t rows,
919 ExceptionInfo *exception)
920 {
921 CacheInfo
922 *cache_info;
923
924 MagickBooleanType
925 status;
926
927 MagickSizeType
928 number_pixels;
929
930 size_t
931 length;
932
933 StreamHandler
934 stream_handler;
935
936 /*
937 Validate pixel cache geometry.
938 */
939 assert(image != (Image *) NULL);
940 if ((x < 0) || (y < 0) ||
941 ((x+(ssize_t) columns) > (ssize_t) image->columns) ||
942 ((y+(ssize_t) rows) > (ssize_t) image->rows) ||
943 (columns == 0) || (rows == 0))
944 {
945 (void) ThrowMagickException(exception,GetMagickModule(),StreamError,
946 "ImageDoesNotContainTheStreamGeometry","`%s'",image->filename);
947 return((Quantum *) NULL);
948 }
949 stream_handler=GetBlobStreamHandler(image);
950 if (stream_handler == (StreamHandler) NULL)
951 {
952 (void) ThrowMagickException(exception,GetMagickModule(),StreamError,
953 "NoStreamHandlerIsDefined","`%s'",image->filename);
954 return((Quantum *) NULL);
955 }
956 cache_info=(CacheInfo *) image->cache;
957 assert(cache_info->signature == MagickCoreSignature);
958 if (ValidatePixelCacheMorphology(image) == MagickFalse)
959 {
960 if (cache_info->storage_class == UndefinedClass)
961 (void) stream_handler(image,(const void *) NULL,(size_t)
962 cache_info->columns);
963 cache_info->storage_class=image->storage_class;
964 cache_info->colorspace=image->colorspace;
965 cache_info->alpha_trait=image->alpha_trait;
966 cache_info->channels=image->channels;
967 cache_info->columns=image->columns;
968 cache_info->rows=image->rows;
969 cache_info->number_channels=image->number_channels;
970 InitializePixelChannelMap(image);
971 ResetPixelCacheChannels(image);
972 image->cache=cache_info;
973 }
974 /*
975 Pixels are stored in a temporary buffer until they are synced to the cache.
976 */
977 cache_info->columns=columns;
978 cache_info->rows=rows;
979 number_pixels=(MagickSizeType) columns*rows;
980 length=(size_t) number_pixels*cache_info->number_channels*sizeof(Quantum);
981 if (cache_info->number_channels == 0)
982 length=(size_t) number_pixels*sizeof(Quantum);
983 if (cache_info->metacontent_extent != 0)
984 length+=number_pixels*cache_info->metacontent_extent;
985 if (cache_info->pixels == (Quantum *) NULL)
986 {
987 cache_info->length=length;
988 status=AcquireStreamPixels(cache_info,exception);
989 if (status == MagickFalse)
990 {
991 cache_info->length=0;
992 return((Quantum *) NULL);
993 }
994 }
995 else
996 if (cache_info->length < length)
997 {
998 RelinquishStreamPixels(cache_info);
999 cache_info->length=length;
1000 status=AcquireStreamPixels(cache_info,exception);
1001 if (status == MagickFalse)
1002 {
1003 cache_info->length=0;
1004 return((Quantum *) NULL);
1005 }
1006 }
1007 cache_info->metacontent=(void *) NULL;
1008 if (cache_info->metacontent_extent != 0)
1009 cache_info->metacontent=(void *) (cache_info->pixels+number_pixels*
1010 cache_info->number_channels);
1011 return(cache_info->pixels);
1012 }
1013
1014 /*
1015 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1016 % %
1017 % %
1018 % %
1019 % R e a d S t r e a m %
1020 % %
1021 % %
1022 % %
1023 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1024 %
1025 % ReadStream() makes the image pixels available to a user supplied callback
1026 % method immediately upon reading a scanline with the ReadImage() method.
1027 %
1028 % The format of the ReadStream() method is:
1029 %
1030 % Image *ReadStream(const ImageInfo *image_info,StreamHandler stream,
1031 % ExceptionInfo *exception)
1032 %
1033 % A description of each parameter follows:
1034 %
1035 % o image_info: the image info.
1036 %
1037 % o stream: a callback method.
1038 %
1039 % o exception: return any errors or warnings in this structure.
1040 %
1041 */
ReadStream(const ImageInfo * image_info,StreamHandler stream,ExceptionInfo * exception)1042 MagickExport Image *ReadStream(const ImageInfo *image_info,StreamHandler stream,
1043 ExceptionInfo *exception)
1044 {
1045 CacheMethods
1046 cache_methods;
1047
1048 Image
1049 *image;
1050
1051 ImageInfo
1052 *read_info;
1053
1054 /*
1055 Stream image pixels.
1056 */
1057 assert(image_info != (ImageInfo *) NULL);
1058 assert(image_info->signature == MagickCoreSignature);
1059 if (image_info->debug != MagickFalse)
1060 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
1061 image_info->filename);
1062 assert(exception != (ExceptionInfo *) NULL);
1063 assert(exception->signature == MagickCoreSignature);
1064 read_info=CloneImageInfo(image_info);
1065 read_info->cache=AcquirePixelCache(0);
1066 GetPixelCacheMethods(&cache_methods);
1067 cache_methods.get_virtual_pixel_handler=GetVirtualPixelStream;
1068 cache_methods.get_virtual_pixels_handler=GetVirtualPixelsStream;
1069 cache_methods.get_virtual_metacontent_from_handler=
1070 GetVirtualMetacontentFromStream;
1071 cache_methods.get_authentic_pixels_handler=GetAuthenticPixelsStream;
1072 cache_methods.queue_authentic_pixels_handler=QueueAuthenticPixelsStream;
1073 cache_methods.sync_authentic_pixels_handler=SyncAuthenticPixelsStream;
1074 cache_methods.get_authentic_pixels_from_handler=GetAuthenticPixelsFromStream;
1075 cache_methods.get_authentic_metacontent_from_handler=
1076 GetAuthenticMetacontentFromStream;
1077 cache_methods.get_one_virtual_pixel_from_handler=GetOneVirtualPixelFromStream;
1078 cache_methods.get_one_authentic_pixel_from_handler=
1079 GetOneAuthenticPixelFromStream;
1080 cache_methods.destroy_pixel_handler=DestroyPixelStream;
1081 SetPixelCacheMethods(read_info->cache,&cache_methods);
1082 read_info->stream=stream;
1083 image=ReadImage(read_info,exception);
1084 if (image != (Image *) NULL)
1085 {
1086 InitializePixelChannelMap(image);
1087 ResetPixelCacheChannels(image);
1088 }
1089 read_info=DestroyImageInfo(read_info);
1090 return(image);
1091 }
1092
1093 /*
1094 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1095 % %
1096 % %
1097 % %
1098 + R e s e t S t r e a m A n o n y m o u s M e m o r y %
1099 % %
1100 % %
1101 % %
1102 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1103 %
1104 % ResetStreamAnonymousMemory() resets the anonymous_memory value.
1105 %
1106 % The format of the ResetStreamAnonymousMemory method is:
1107 %
1108 % void ResetStreamAnonymousMemory(void)
1109 %
1110 */
ResetStreamAnonymousMemory(void)1111 MagickPrivate void ResetStreamAnonymousMemory(void)
1112 {
1113 cache_anonymous_memory=0;
1114 }
1115
1116 /*
1117 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1118 % %
1119 % %
1120 % %
1121 + S e t S t r e a m I n f o C l i e n t D a t a %
1122 % %
1123 % %
1124 % %
1125 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1126 %
1127 % SetStreamInfoClientData() sets the stream info client data.
1128 %
1129 % The format of the SetStreamInfoClientData method is:
1130 %
1131 % void SetStreamInfoClientData(StreamInfo *stream_info,
1132 % const void *client_data)
1133 %
1134 % A description of each parameter follows:
1135 %
1136 % o stream_info: the stream info.
1137 %
1138 % o client_data: the client data.
1139 %
1140 */
SetStreamInfoClientData(StreamInfo * stream_info,const void * client_data)1141 MagickPrivate void SetStreamInfoClientData(StreamInfo *stream_info,
1142 const void *client_data)
1143 {
1144 assert(stream_info != (StreamInfo *) NULL);
1145 assert(stream_info->signature == MagickCoreSignature);
1146 stream_info->client_data=client_data;
1147 }
1148
1149 /*
1150 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1151 % %
1152 % %
1153 % %
1154 + S e t S t r e a m I n f o M a p %
1155 % %
1156 % %
1157 % %
1158 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1159 %
1160 % SetStreamInfoMap() sets the stream info map member.
1161 %
1162 % The format of the SetStreamInfoMap method is:
1163 %
1164 % void SetStreamInfoMap(StreamInfo *stream_info,const char *map)
1165 %
1166 % A description of each parameter follows:
1167 %
1168 % o stream_info: the stream info.
1169 %
1170 % o map: the map.
1171 %
1172 */
SetStreamInfoMap(StreamInfo * stream_info,const char * map)1173 MagickExport void SetStreamInfoMap(StreamInfo *stream_info,const char *map)
1174 {
1175 assert(stream_info != (StreamInfo *) NULL);
1176 assert(stream_info->signature == MagickCoreSignature);
1177 (void) CloneString(&stream_info->map,map);
1178 }
1179
1180 /*
1181 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1182 % %
1183 % %
1184 % %
1185 + S e t S t r e a m I n f o S t o r a g e T y p e %
1186 % %
1187 % %
1188 % %
1189 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1190 %
1191 % SetStreamInfoStorageType() sets the stream info storage type member.
1192 %
1193 % The format of the SetStreamInfoStorageType method is:
1194 %
1195 % void SetStreamInfoStorageType(StreamInfo *stream_info,
1196 % const StoreageType *storage_type)
1197 %
1198 % A description of each parameter follows:
1199 %
1200 % o stream_info: the stream info.
1201 %
1202 % o storage_type: the storage type.
1203 %
1204 */
SetStreamInfoStorageType(StreamInfo * stream_info,const StorageType storage_type)1205 MagickExport void SetStreamInfoStorageType(StreamInfo *stream_info,
1206 const StorageType storage_type)
1207 {
1208 assert(stream_info != (StreamInfo *) NULL);
1209 assert(stream_info->signature == MagickCoreSignature);
1210 stream_info->storage_type=storage_type;
1211 }
1212
1213 /*
1214 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1215 % %
1216 % %
1217 % %
1218 + S t r e a m I m a g e %
1219 % %
1220 % %
1221 % %
1222 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1223 %
1224 % StreamImage() streams pixels from an image and writes them in a user
1225 % defined format and storage type (e.g. RGBA as 8-bit unsigned char).
1226 %
1227 % The format of the StreamImage() method is:
1228 %
1229 % Image *StreamImage(const ImageInfo *image_info,
1230 % StreamInfo *stream_info,ExceptionInfo *exception)
1231 %
1232 % A description of each parameter follows:
1233 %
1234 % o image_info: the image info.
1235 %
1236 % o stream_info: the stream info.
1237 %
1238 % o exception: return any errors or warnings in this structure.
1239 %
1240 */
1241
1242 #if defined(__cplusplus) || defined(c_plusplus)
1243 extern "C" {
1244 #endif
1245
WriteStreamImage(const Image * image,const void * pixels,const size_t columns)1246 static size_t WriteStreamImage(const Image *image,const void *pixels,
1247 const size_t columns)
1248 {
1249 CacheInfo
1250 *cache_info;
1251
1252 RectangleInfo
1253 extract_info;
1254
1255 size_t
1256 length,
1257 packet_size;
1258
1259 ssize_t
1260 count;
1261
1262 StreamInfo
1263 *stream_info;
1264
1265 (void) pixels;
1266 stream_info=(StreamInfo *) image->client_data;
1267 switch (stream_info->storage_type)
1268 {
1269 default: packet_size=sizeof(unsigned char); break;
1270 case CharPixel: packet_size=sizeof(unsigned char); break;
1271 case DoublePixel: packet_size=sizeof(double); break;
1272 case FloatPixel: packet_size=sizeof(float); break;
1273 case LongPixel: packet_size=sizeof(unsigned int); break;
1274 case LongLongPixel: packet_size=sizeof(MagickSizeType); break;
1275 case QuantumPixel: packet_size=sizeof(Quantum); break;
1276 case ShortPixel: packet_size=sizeof(unsigned short); break;
1277 }
1278 cache_info=(CacheInfo *) image->cache;
1279 assert(cache_info->signature == MagickCoreSignature);
1280 packet_size*=strlen(stream_info->map);
1281 length=packet_size*cache_info->columns*cache_info->rows;
1282 if (image != stream_info->image)
1283 {
1284 ImageInfo
1285 *write_info;
1286
1287 /*
1288 Prepare stream for writing.
1289 */
1290 (void) RelinquishAlignedMemory(stream_info->pixels);
1291 stream_info->pixels=(unsigned char *) AcquireAlignedMemory(1,length);
1292 if (stream_info->pixels == (unsigned char *) NULL)
1293 return(0);
1294 (void) memset(stream_info->pixels,0,length);
1295 stream_info->image=image;
1296 write_info=CloneImageInfo(stream_info->image_info);
1297 (void) SetImageInfo(write_info,1,stream_info->exception);
1298 if (write_info->extract != (char *) NULL)
1299 (void) ParseAbsoluteGeometry(write_info->extract,
1300 &stream_info->extract_info);
1301 stream_info->y=0;
1302 write_info=DestroyImageInfo(write_info);
1303 }
1304 extract_info=stream_info->extract_info;
1305 if ((extract_info.width == 0) || (extract_info.height == 0))
1306 {
1307 /*
1308 Write all pixels to stream.
1309 */
1310 (void) StreamImagePixels(stream_info,image,stream_info->exception);
1311 count=WriteBlob(stream_info->stream,length,stream_info->pixels);
1312 stream_info->y++;
1313 return(count == 0 ? 0 : columns);
1314 }
1315 if ((stream_info->y < extract_info.y) ||
1316 (stream_info->y >= (ssize_t) (extract_info.y+extract_info.height)))
1317 {
1318 stream_info->y++;
1319 return(columns);
1320 }
1321 /*
1322 Write a portion of the pixel row to the stream.
1323 */
1324 (void) StreamImagePixels(stream_info,image,stream_info->exception);
1325 length=packet_size*extract_info.width;
1326 count=WriteBlob(stream_info->stream,length,stream_info->pixels+packet_size*
1327 extract_info.x);
1328 stream_info->y++;
1329 return(count == 0 ? 0 : columns);
1330 }
1331
1332 #if defined(__cplusplus) || defined(c_plusplus)
1333 }
1334 #endif
1335
StreamImage(const ImageInfo * image_info,StreamInfo * stream_info,ExceptionInfo * exception)1336 MagickExport Image *StreamImage(const ImageInfo *image_info,
1337 StreamInfo *stream_info,ExceptionInfo *exception)
1338 {
1339 Image
1340 *image;
1341
1342 ImageInfo
1343 *read_info;
1344
1345 assert(image_info != (const ImageInfo *) NULL);
1346 assert(image_info->signature == MagickCoreSignature);
1347 if (image_info->debug != MagickFalse)
1348 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
1349 image_info->filename);
1350 assert(stream_info != (StreamInfo *) NULL);
1351 assert(stream_info->signature == MagickCoreSignature);
1352 assert(exception != (ExceptionInfo *) NULL);
1353 read_info=CloneImageInfo(image_info);
1354 stream_info->image_info=image_info;
1355 stream_info->quantum_info=AcquireQuantumInfo(image_info,(Image *) NULL);
1356 if (stream_info->quantum_info == (QuantumInfo *) NULL)
1357 {
1358 read_info=DestroyImageInfo(read_info);
1359 return((Image *) NULL);
1360 }
1361 stream_info->exception=exception;
1362 read_info->client_data=(void *) stream_info;
1363 image=ReadStream(read_info,&WriteStreamImage,exception);
1364 read_info=DestroyImageInfo(read_info);
1365 stream_info->quantum_info=DestroyQuantumInfo(stream_info->quantum_info);
1366 stream_info->quantum_info=AcquireQuantumInfo(image_info,image);
1367 if (stream_info->quantum_info == (QuantumInfo *) NULL)
1368 image=DestroyImage(image);
1369 return(image);
1370 }
1371
1372 /*
1373 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1374 % %
1375 % %
1376 % %
1377 + S t r e a m I m a g e P i x e l s %
1378 % %
1379 % %
1380 % %
1381 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1382 %
1383 % StreamImagePixels() extracts pixel data from an image and returns it in the
1384 % stream_info->pixels structure in the format as defined by
1385 % stream_info->quantum_info->map and stream_info->quantum_info->storage_type.
1386 %
1387 % The format of the StreamImagePixels method is:
1388 %
1389 % MagickBooleanType StreamImagePixels(const StreamInfo *stream_info,
1390 % const Image *image,ExceptionInfo *exception)
1391 %
1392 % A description of each parameter follows:
1393 %
1394 % o stream_info: the stream info.
1395 %
1396 % o image: the image.
1397 %
1398 % o exception: return any errors or warnings in this structure.
1399 %
1400 */
StreamImagePixels(const StreamInfo * stream_info,const Image * image,ExceptionInfo * exception)1401 static MagickBooleanType StreamImagePixels(const StreamInfo *stream_info,
1402 const Image *image,ExceptionInfo *exception)
1403 {
1404 QuantumInfo
1405 *quantum_info;
1406
1407 QuantumType
1408 *quantum_map;
1409
1410 const Quantum
1411 *p;
1412
1413 ssize_t
1414 i,
1415 x;
1416
1417 size_t
1418 length;
1419
1420 assert(stream_info != (StreamInfo *) NULL);
1421 assert(stream_info->signature == MagickCoreSignature);
1422 assert(image != (Image *) NULL);
1423 assert(image->signature == MagickCoreSignature);
1424 if (image->debug != MagickFalse)
1425 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1426 length=strlen(stream_info->map);
1427 quantum_map=(QuantumType *) AcquireQuantumMemory(length,sizeof(*quantum_map));
1428 if (quantum_map == (QuantumType *) NULL)
1429 {
1430 (void) ThrowMagickException(exception,GetMagickModule(),
1431 ResourceLimitError,"MemoryAllocationFailed","`%s'",image->filename);
1432 return(MagickFalse);
1433 }
1434 (void) memset(quantum_map,0,length*sizeof(*quantum_map));
1435 for (i=0; i < (ssize_t) length; i++)
1436 {
1437 switch (stream_info->map[i])
1438 {
1439 case 'A':
1440 case 'a':
1441 {
1442 quantum_map[i]=AlphaQuantum;
1443 break;
1444 }
1445 case 'B':
1446 case 'b':
1447 {
1448 quantum_map[i]=BlueQuantum;
1449 break;
1450 }
1451 case 'C':
1452 case 'c':
1453 {
1454 quantum_map[i]=CyanQuantum;
1455 if (image->colorspace == CMYKColorspace)
1456 break;
1457 quantum_map=(QuantumType *) RelinquishMagickMemory(quantum_map);
1458 (void) ThrowMagickException(exception,GetMagickModule(),ImageError,
1459 "ColorSeparatedImageRequired","`%s'",stream_info->map);
1460 return(MagickFalse);
1461 }
1462 case 'g':
1463 case 'G':
1464 {
1465 quantum_map[i]=GreenQuantum;
1466 break;
1467 }
1468 case 'I':
1469 case 'i':
1470 {
1471 quantum_map[i]=IndexQuantum;
1472 break;
1473 }
1474 case 'K':
1475 case 'k':
1476 {
1477 quantum_map[i]=BlackQuantum;
1478 if (image->colorspace == CMYKColorspace)
1479 break;
1480 quantum_map=(QuantumType *) RelinquishMagickMemory(quantum_map);
1481 (void) ThrowMagickException(exception,GetMagickModule(),ImageError,
1482 "ColorSeparatedImageRequired","`%s'",stream_info->map);
1483 return(MagickFalse);
1484 }
1485 case 'M':
1486 case 'm':
1487 {
1488 quantum_map[i]=MagentaQuantum;
1489 if (image->colorspace == CMYKColorspace)
1490 break;
1491 quantum_map=(QuantumType *) RelinquishMagickMemory(quantum_map);
1492 (void) ThrowMagickException(exception,GetMagickModule(),ImageError,
1493 "ColorSeparatedImageRequired","`%s'",stream_info->map);
1494 return(MagickFalse);
1495 }
1496 case 'o':
1497 case 'O':
1498 {
1499 quantum_map[i]=OpacityQuantum;
1500 break;
1501 }
1502 case 'P':
1503 case 'p':
1504 {
1505 quantum_map[i]=UndefinedQuantum;
1506 break;
1507 }
1508 case 'R':
1509 case 'r':
1510 {
1511 quantum_map[i]=RedQuantum;
1512 break;
1513 }
1514 case 'Y':
1515 case 'y':
1516 {
1517 quantum_map[i]=YellowQuantum;
1518 if (image->colorspace == CMYKColorspace)
1519 break;
1520 quantum_map=(QuantumType *) RelinquishMagickMemory(quantum_map);
1521 (void) ThrowMagickException(exception,GetMagickModule(),ImageError,
1522 "ColorSeparatedImageRequired","`%s'",stream_info->map);
1523 return(MagickFalse);
1524 }
1525 default:
1526 {
1527 quantum_map=(QuantumType *) RelinquishMagickMemory(quantum_map);
1528 (void) ThrowMagickException(exception,GetMagickModule(),OptionError,
1529 "UnrecognizedPixelMap","`%s'",stream_info->map);
1530 return(MagickFalse);
1531 }
1532 }
1533 }
1534 quantum_info=stream_info->quantum_info;
1535 switch (stream_info->storage_type)
1536 {
1537 case CharPixel:
1538 {
1539 unsigned char
1540 *q;
1541
1542 q=(unsigned char *) stream_info->pixels;
1543 if (LocaleCompare(stream_info->map,"BGR") == 0)
1544 {
1545 p=GetAuthenticPixelQueue(image);
1546 if (p == (const Quantum *) NULL)
1547 break;
1548 for (x=0; x < (ssize_t) GetImageExtent(image); x++)
1549 {
1550 *q++=ScaleQuantumToChar(GetPixelBlue(image,p));
1551 *q++=ScaleQuantumToChar(GetPixelGreen(image,p));
1552 *q++=ScaleQuantumToChar(GetPixelRed(image,p));
1553 p+=GetPixelChannels(image);
1554 }
1555 break;
1556 }
1557 if (LocaleCompare(stream_info->map,"BGRA") == 0)
1558 {
1559 p=GetAuthenticPixelQueue(image);
1560 if (p == (const Quantum *) NULL)
1561 break;
1562 for (x=0; x < (ssize_t) GetImageExtent(image); x++)
1563 {
1564 *q++=ScaleQuantumToChar(GetPixelBlue(image,p));
1565 *q++=ScaleQuantumToChar(GetPixelGreen(image,p));
1566 *q++=ScaleQuantumToChar(GetPixelRed(image,p));
1567 *q++=ScaleQuantumToChar(GetPixelAlpha(image,p));
1568 p+=GetPixelChannels(image);
1569 }
1570 break;
1571 }
1572 if (LocaleCompare(stream_info->map,"BGRP") == 0)
1573 {
1574 p=GetAuthenticPixelQueue(image);
1575 if (p == (const Quantum *) NULL)
1576 break;
1577 for (x=0; x < (ssize_t) GetImageExtent(image); x++)
1578 {
1579 *q++=ScaleQuantumToChar(GetPixelBlue(image,p));
1580 *q++=ScaleQuantumToChar(GetPixelGreen(image,p));
1581 *q++=ScaleQuantumToChar(GetPixelRed(image,p));
1582 *q++=ScaleQuantumToChar((Quantum) 0);
1583 p+=GetPixelChannels(image);
1584 }
1585 break;
1586 }
1587 if (LocaleCompare(stream_info->map,"I") == 0)
1588 {
1589 p=GetAuthenticPixelQueue(image);
1590 if (p == (const Quantum *) NULL)
1591 break;
1592 for (x=0; x < (ssize_t) GetImageExtent(image); x++)
1593 {
1594 *q++=ScaleQuantumToChar(ClampToQuantum(GetPixelIntensity(image,p)));
1595 p+=GetPixelChannels(image);
1596 }
1597 break;
1598 }
1599 if (LocaleCompare(stream_info->map,"RGB") == 0)
1600 {
1601 p=GetAuthenticPixelQueue(image);
1602 if (p == (const Quantum *) NULL)
1603 break;
1604 for (x=0; x < (ssize_t) GetImageExtent(image); x++)
1605 {
1606 *q++=ScaleQuantumToChar(GetPixelRed(image,p));
1607 *q++=ScaleQuantumToChar(GetPixelGreen(image,p));
1608 *q++=ScaleQuantumToChar(GetPixelBlue(image,p));
1609 p+=GetPixelChannels(image);
1610 }
1611 break;
1612 }
1613 if (LocaleCompare(stream_info->map,"RGBA") == 0)
1614 {
1615 p=GetAuthenticPixelQueue(image);
1616 if (p == (const Quantum *) NULL)
1617 break;
1618 for (x=0; x < (ssize_t) GetImageExtent(image); x++)
1619 {
1620 *q++=ScaleQuantumToChar(GetPixelRed(image,p));
1621 *q++=ScaleQuantumToChar(GetPixelGreen(image,p));
1622 *q++=ScaleQuantumToChar(GetPixelBlue(image,p));
1623 *q++=ScaleQuantumToChar(GetPixelAlpha(image,p));
1624 p+=GetPixelChannels(image);
1625 }
1626 break;
1627 }
1628 if (LocaleCompare(stream_info->map,"RGBP") == 0)
1629 {
1630 p=GetAuthenticPixelQueue(image);
1631 if (p == (const Quantum *) NULL)
1632 break;
1633 for (x=0; x < (ssize_t) GetImageExtent(image); x++)
1634 {
1635 *q++=ScaleQuantumToChar(GetPixelRed(image,p));
1636 *q++=ScaleQuantumToChar(GetPixelGreen(image,p));
1637 *q++=ScaleQuantumToChar(GetPixelBlue(image,p));
1638 *q++=ScaleQuantumToChar((Quantum) 0);
1639 p+=GetPixelChannels(image);
1640 }
1641 break;
1642 }
1643 p=GetAuthenticPixelQueue(image);
1644 if (p == (const Quantum *) NULL)
1645 break;
1646 for (x=0; x < (ssize_t) GetImageExtent(image); x++)
1647 {
1648 for (i=0; i < (ssize_t) length; i++)
1649 {
1650 *q=0;
1651 switch (quantum_map[i])
1652 {
1653 case RedQuantum:
1654 case CyanQuantum:
1655 {
1656 *q=ScaleQuantumToChar(GetPixelRed(image,p));
1657 break;
1658 }
1659 case GreenQuantum:
1660 case MagentaQuantum:
1661 {
1662 *q=ScaleQuantumToChar(GetPixelGreen(image,p));
1663 break;
1664 }
1665 case BlueQuantum:
1666 case YellowQuantum:
1667 {
1668 *q=ScaleQuantumToChar(GetPixelBlue(image,p));
1669 break;
1670 }
1671 case AlphaQuantum:
1672 {
1673 *q=ScaleQuantumToChar(GetPixelAlpha(image,p));
1674 break;
1675 }
1676 case OpacityQuantum:
1677 {
1678 *q=ScaleQuantumToChar(GetPixelOpacity(image,p));
1679 break;
1680 }
1681 case BlackQuantum:
1682 {
1683 if (image->colorspace == CMYKColorspace)
1684 *q=ScaleQuantumToChar(GetPixelBlack(image,p));
1685 break;
1686 }
1687 case IndexQuantum:
1688 {
1689 *q=ScaleQuantumToChar(ClampToQuantum(GetPixelIntensity(image,p)));
1690 break;
1691 }
1692 default:
1693 break;
1694 }
1695 q++;
1696 }
1697 p+=GetPixelChannels(image);
1698 }
1699 break;
1700 }
1701 case DoublePixel:
1702 {
1703 double
1704 *q;
1705
1706 q=(double *) stream_info->pixels;
1707 if (LocaleCompare(stream_info->map,"BGR") == 0)
1708 {
1709 p=GetAuthenticPixelQueue(image);
1710 if (p == (const Quantum *) NULL)
1711 break;
1712 for (x=0; x < (ssize_t) GetImageExtent(image); x++)
1713 {
1714 *q++=(double) ((QuantumScale*GetPixelBlue(image,p))*
1715 quantum_info->scale+quantum_info->minimum);
1716 *q++=(double) ((QuantumScale*GetPixelGreen(image,p))*
1717 quantum_info->scale+quantum_info->minimum);
1718 *q++=(double) ((QuantumScale*GetPixelRed(image,p))*
1719 quantum_info->scale+quantum_info->minimum);
1720 p+=GetPixelChannels(image);
1721 }
1722 break;
1723 }
1724 if (LocaleCompare(stream_info->map,"BGRA") == 0)
1725 {
1726 p=GetAuthenticPixelQueue(image);
1727 if (p == (const Quantum *) NULL)
1728 break;
1729 for (x=0; x < (ssize_t) GetImageExtent(image); x++)
1730 {
1731 *q++=(double) ((QuantumScale*GetPixelBlue(image,p))*
1732 quantum_info->scale+quantum_info->minimum);
1733 *q++=(double) ((QuantumScale*GetPixelGreen(image,p))*
1734 quantum_info->scale+quantum_info->minimum);
1735 *q++=(double) ((QuantumScale*GetPixelRed(image,p))*
1736 quantum_info->scale+quantum_info->minimum);
1737 *q++=(double) ((QuantumScale*GetPixelAlpha(image,p))*
1738 quantum_info->scale+quantum_info->minimum);
1739 p+=GetPixelChannels(image);
1740 }
1741 break;
1742 }
1743 if (LocaleCompare(stream_info->map,"BGRP") == 0)
1744 {
1745 p=GetAuthenticPixelQueue(image);
1746 if (p == (const Quantum *) NULL)
1747 break;
1748 for (x=0; x < (ssize_t) GetImageExtent(image); x++)
1749 {
1750 *q++=(double) ((QuantumScale*GetPixelBlue(image,p))*
1751 quantum_info->scale+quantum_info->minimum);
1752 *q++=(double) ((QuantumScale*GetPixelGreen(image,p))*
1753 quantum_info->scale+quantum_info->minimum);
1754 *q++=(double) ((QuantumScale*GetPixelRed(image,p))*
1755 quantum_info->scale+quantum_info->minimum);
1756 *q++=0.0;
1757 p+=GetPixelChannels(image);
1758 }
1759 break;
1760 }
1761 if (LocaleCompare(stream_info->map,"I") == 0)
1762 {
1763 p=GetAuthenticPixelQueue(image);
1764 if (p == (const Quantum *) NULL)
1765 break;
1766 for (x=0; x < (ssize_t) GetImageExtent(image); x++)
1767 {
1768 *q++=(double) ((QuantumScale*GetPixelIntensity(image,p))*
1769 quantum_info->scale+quantum_info->minimum);
1770 p+=GetPixelChannels(image);
1771 }
1772 break;
1773 }
1774 if (LocaleCompare(stream_info->map,"RGB") == 0)
1775 {
1776 p=GetAuthenticPixelQueue(image);
1777 if (p == (const Quantum *) NULL)
1778 break;
1779 for (x=0; x < (ssize_t) GetImageExtent(image); x++)
1780 {
1781 *q++=(double) ((QuantumScale*GetPixelRed(image,p))*
1782 quantum_info->scale+quantum_info->minimum);
1783 *q++=(double) ((QuantumScale*GetPixelGreen(image,p))*
1784 quantum_info->scale+quantum_info->minimum);
1785 *q++=(double) ((QuantumScale*GetPixelBlue(image,p))*
1786 quantum_info->scale+quantum_info->minimum);
1787 p+=GetPixelChannels(image);
1788 }
1789 break;
1790 }
1791 if (LocaleCompare(stream_info->map,"RGBA") == 0)
1792 {
1793 p=GetAuthenticPixelQueue(image);
1794 if (p == (const Quantum *) NULL)
1795 break;
1796 for (x=0; x < (ssize_t) GetImageExtent(image); x++)
1797 {
1798 *q++=(double) ((QuantumScale*GetPixelRed(image,p))*
1799 quantum_info->scale+quantum_info->minimum);
1800 *q++=(double) ((QuantumScale*GetPixelGreen(image,p))*
1801 quantum_info->scale+quantum_info->minimum);
1802 *q++=(double) ((QuantumScale*GetPixelBlue(image,p))*
1803 quantum_info->scale+quantum_info->minimum);
1804 *q++=(double) ((QuantumScale*GetPixelAlpha(image,p))*
1805 quantum_info->scale+quantum_info->minimum);
1806 p+=GetPixelChannels(image);
1807 }
1808 break;
1809 }
1810 if (LocaleCompare(stream_info->map,"RGBP") == 0)
1811 {
1812 p=GetAuthenticPixelQueue(image);
1813 if (p == (const Quantum *) NULL)
1814 break;
1815 for (x=0; x < (ssize_t) GetImageExtent(image); x++)
1816 {
1817 *q++=(double) ((QuantumScale*GetPixelRed(image,p))*
1818 quantum_info->scale+quantum_info->minimum);
1819 *q++=(double) ((QuantumScale*GetPixelGreen(image,p))*
1820 quantum_info->scale+quantum_info->minimum);
1821 *q++=(double) ((QuantumScale*GetPixelBlue(image,p))*
1822 quantum_info->scale+quantum_info->minimum);
1823 *q++=0.0;
1824 p+=GetPixelChannels(image);
1825 }
1826 break;
1827 }
1828 p=GetAuthenticPixelQueue(image);
1829 if (p == (const Quantum *) NULL)
1830 break;
1831 for (x=0; x < (ssize_t) GetImageExtent(image); x++)
1832 {
1833 for (i=0; i < (ssize_t) length; i++)
1834 {
1835 *q=0;
1836 switch (quantum_map[i])
1837 {
1838 case RedQuantum:
1839 case CyanQuantum:
1840 {
1841 *q=(double) ((QuantumScale*GetPixelRed(image,p))*
1842 quantum_info->scale+quantum_info->minimum);
1843 break;
1844 }
1845 case GreenQuantum:
1846 case MagentaQuantum:
1847 {
1848 *q=(double) ((QuantumScale*GetPixelGreen(image,p))*
1849 quantum_info->scale+quantum_info->minimum);
1850 break;
1851 }
1852 case BlueQuantum:
1853 case YellowQuantum:
1854 {
1855 *q=(double) ((QuantumScale*GetPixelBlue(image,p))*
1856 quantum_info->scale+quantum_info->minimum);
1857 break;
1858 }
1859 case AlphaQuantum:
1860 {
1861 *q=(double) ((QuantumScale*GetPixelAlpha(image,p))*
1862 quantum_info->scale+quantum_info->minimum);
1863 break;
1864 }
1865 case OpacityQuantum:
1866 {
1867 *q=(double) ((QuantumScale*GetPixelOpacity(image,p))*
1868 quantum_info->scale+quantum_info->minimum);
1869 break;
1870 }
1871 case BlackQuantum:
1872 {
1873 if (image->colorspace == CMYKColorspace)
1874 *q=(double) ((QuantumScale*GetPixelBlack(image,p))*
1875 quantum_info->scale+quantum_info->minimum);
1876 break;
1877 }
1878 case IndexQuantum:
1879 {
1880 *q=(double) ((QuantumScale*GetPixelIntensity(image,p))*
1881 quantum_info->scale+quantum_info->minimum);
1882 break;
1883 }
1884 default:
1885 *q=0;
1886 }
1887 q++;
1888 }
1889 p+=GetPixelChannels(image);
1890 }
1891 break;
1892 }
1893 case FloatPixel:
1894 {
1895 float
1896 *q;
1897
1898 q=(float *) stream_info->pixels;
1899 if (LocaleCompare(stream_info->map,"BGR") == 0)
1900 {
1901 p=GetAuthenticPixelQueue(image);
1902 if (p == (const Quantum *) NULL)
1903 break;
1904 for (x=0; x < (ssize_t) GetImageExtent(image); x++)
1905 {
1906 *q++=(float) ((QuantumScale*GetPixelBlue(image,p))*
1907 quantum_info->scale+quantum_info->minimum);
1908 *q++=(float) ((QuantumScale*GetPixelGreen(image,p))*
1909 quantum_info->scale+quantum_info->minimum);
1910 *q++=(float) ((QuantumScale*GetPixelRed(image,p))*
1911 quantum_info->scale+quantum_info->minimum);
1912 p+=GetPixelChannels(image);
1913 }
1914 break;
1915 }
1916 if (LocaleCompare(stream_info->map,"BGRA") == 0)
1917 {
1918 p=GetAuthenticPixelQueue(image);
1919 if (p == (const Quantum *) NULL)
1920 break;
1921 for (x=0; x < (ssize_t) GetImageExtent(image); x++)
1922 {
1923 *q++=(float) ((QuantumScale*GetPixelBlue(image,p))*
1924 quantum_info->scale+quantum_info->minimum);
1925 *q++=(float) ((QuantumScale*GetPixelGreen(image,p))*
1926 quantum_info->scale+quantum_info->minimum);
1927 *q++=(float) ((QuantumScale*GetPixelRed(image,p))*
1928 quantum_info->scale+quantum_info->minimum);
1929 *q++=(float) ((QuantumScale*GetPixelAlpha(image,p))*
1930 quantum_info->scale+quantum_info->minimum);
1931 p+=GetPixelChannels(image);
1932 }
1933 break;
1934 }
1935 if (LocaleCompare(stream_info->map,"BGRP") == 0)
1936 {
1937 p=GetAuthenticPixelQueue(image);
1938 if (p == (const Quantum *) NULL)
1939 break;
1940 for (x=0; x < (ssize_t) GetImageExtent(image); x++)
1941 {
1942 *q++=(float) ((QuantumScale*GetPixelBlue(image,p))*
1943 quantum_info->scale+quantum_info->minimum);
1944 *q++=(float) ((QuantumScale*GetPixelGreen(image,p))*
1945 quantum_info->scale+quantum_info->minimum);
1946 *q++=(float) ((QuantumScale*GetPixelRed(image,p))*
1947 quantum_info->scale+quantum_info->minimum);
1948 *q++=0.0;
1949 p+=GetPixelChannels(image);
1950 }
1951 break;
1952 }
1953 if (LocaleCompare(stream_info->map,"I") == 0)
1954 {
1955 p=GetAuthenticPixelQueue(image);
1956 if (p == (const Quantum *) NULL)
1957 break;
1958 for (x=0; x < (ssize_t) GetImageExtent(image); x++)
1959 {
1960 *q++=(float) ((QuantumScale*GetPixelIntensity(image,p))*
1961 quantum_info->scale+quantum_info->minimum);
1962 p+=GetPixelChannels(image);
1963 }
1964 break;
1965 }
1966 if (LocaleCompare(stream_info->map,"RGB") == 0)
1967 {
1968 p=GetAuthenticPixelQueue(image);
1969 if (p == (const Quantum *) NULL)
1970 break;
1971 for (x=0; x < (ssize_t) GetImageExtent(image); x++)
1972 {
1973 *q++=(float) ((QuantumScale*GetPixelRed(image,p))*
1974 quantum_info->scale+quantum_info->minimum);
1975 *q++=(float) ((QuantumScale*GetPixelGreen(image,p))*
1976 quantum_info->scale+quantum_info->minimum);
1977 *q++=(float) ((QuantumScale*GetPixelBlue(image,p))*
1978 quantum_info->scale+quantum_info->minimum);
1979 p+=GetPixelChannels(image);
1980 }
1981 break;
1982 }
1983 if (LocaleCompare(stream_info->map,"RGBA") == 0)
1984 {
1985 p=GetAuthenticPixelQueue(image);
1986 if (p == (const Quantum *) NULL)
1987 break;
1988 for (x=0; x < (ssize_t) GetImageExtent(image); x++)
1989 {
1990 *q++=(float) ((QuantumScale*GetPixelRed(image,p))*
1991 quantum_info->scale+quantum_info->minimum);
1992 *q++=(float) ((QuantumScale*GetPixelGreen(image,p))*
1993 quantum_info->scale+quantum_info->minimum);
1994 *q++=(float) ((QuantumScale*GetPixelBlue(image,p))*
1995 quantum_info->scale+quantum_info->minimum);
1996 *q++=(float) ((QuantumScale*GetPixelAlpha(image,p))*
1997 quantum_info->scale+quantum_info->minimum);
1998 p+=GetPixelChannels(image);
1999 }
2000 break;
2001 }
2002 if (LocaleCompare(stream_info->map,"RGBP") == 0)
2003 {
2004 p=GetAuthenticPixelQueue(image);
2005 if (p == (const Quantum *) NULL)
2006 break;
2007 for (x=0; x < (ssize_t) GetImageExtent(image); x++)
2008 {
2009 *q++=(float) ((QuantumScale*GetPixelRed(image,p))*
2010 quantum_info->scale+quantum_info->minimum);
2011 *q++=(float) ((QuantumScale*GetPixelGreen(image,p))*
2012 quantum_info->scale+quantum_info->minimum);
2013 *q++=(float) ((QuantumScale*GetPixelBlue(image,p))*
2014 quantum_info->scale+quantum_info->minimum);
2015 *q++=0.0;
2016 p+=GetPixelChannels(image);
2017 }
2018 break;
2019 }
2020 p=GetAuthenticPixelQueue(image);
2021 if (p == (const Quantum *) NULL)
2022 break;
2023 for (x=0; x < (ssize_t) GetImageExtent(image); x++)
2024 {
2025 for (i=0; i < (ssize_t) length; i++)
2026 {
2027 *q=0;
2028 switch (quantum_map[i])
2029 {
2030 case RedQuantum:
2031 case CyanQuantum:
2032 {
2033 *q=(float) ((QuantumScale*GetPixelRed(image,p))*
2034 quantum_info->scale+quantum_info->minimum);
2035 break;
2036 }
2037 case GreenQuantum:
2038 case MagentaQuantum:
2039 {
2040 *q=(float) ((QuantumScale*GetPixelGreen(image,p))*
2041 quantum_info->scale+quantum_info->minimum);
2042 break;
2043 }
2044 case BlueQuantum:
2045 case YellowQuantum:
2046 {
2047 *q=(float) ((QuantumScale*GetPixelBlue(image,p))*
2048 quantum_info->scale+quantum_info->minimum);
2049 break;
2050 }
2051 case AlphaQuantum:
2052 {
2053 *q=(float) ((QuantumScale*GetPixelAlpha(image,p))*
2054 quantum_info->scale+quantum_info->minimum);
2055 break;
2056 }
2057 case OpacityQuantum:
2058 {
2059 *q=(float) ((QuantumScale*GetPixelOpacity(image,p))*
2060 quantum_info->scale+quantum_info->minimum);
2061 break;
2062 }
2063 case BlackQuantum:
2064 {
2065 if (image->colorspace == CMYKColorspace)
2066 *q=(float) ((QuantumScale*GetPixelBlack(image,p))*
2067 quantum_info->scale+quantum_info->minimum);
2068 break;
2069 }
2070 case IndexQuantum:
2071 {
2072 *q=(float) ((QuantumScale*GetPixelIntensity(image,p))*
2073 quantum_info->scale+quantum_info->minimum);
2074 break;
2075 }
2076 default:
2077 *q=0;
2078 }
2079 q++;
2080 }
2081 p+=GetPixelChannels(image);
2082 }
2083 break;
2084 }
2085 case LongPixel:
2086 {
2087 unsigned int
2088 *q;
2089
2090 q=(unsigned int *) stream_info->pixels;
2091 if (LocaleCompare(stream_info->map,"BGR") == 0)
2092 {
2093 p=GetAuthenticPixelQueue(image);
2094 if (p == (const Quantum *) NULL)
2095 break;
2096 for (x=0; x < (ssize_t) GetImageExtent(image); x++)
2097 {
2098 *q++=ScaleQuantumToLong(GetPixelBlue(image,p));
2099 *q++=ScaleQuantumToLong(GetPixelGreen(image,p));
2100 *q++=ScaleQuantumToLong(GetPixelRed(image,p));
2101 p+=GetPixelChannels(image);
2102 }
2103 break;
2104 }
2105 if (LocaleCompare(stream_info->map,"BGRA") == 0)
2106 {
2107 p=GetAuthenticPixelQueue(image);
2108 if (p == (const Quantum *) NULL)
2109 break;
2110 for (x=0; x < (ssize_t) GetImageExtent(image); x++)
2111 {
2112 *q++=ScaleQuantumToLong(GetPixelBlue(image,p));
2113 *q++=ScaleQuantumToLong(GetPixelGreen(image,p));
2114 *q++=ScaleQuantumToLong(GetPixelRed(image,p));
2115 *q++=ScaleQuantumToLong(GetPixelAlpha(image,p));
2116 p+=GetPixelChannels(image);
2117 }
2118 break;
2119 }
2120 if (LocaleCompare(stream_info->map,"BGRP") == 0)
2121 {
2122 p=GetAuthenticPixelQueue(image);
2123 if (p == (const Quantum *) NULL)
2124 break;
2125 for (x=0; x < (ssize_t) GetImageExtent(image); x++)
2126 {
2127 *q++=ScaleQuantumToLong(GetPixelBlue(image,p));
2128 *q++=ScaleQuantumToLong(GetPixelGreen(image,p));
2129 *q++=ScaleQuantumToLong(GetPixelRed(image,p));
2130 *q++=0;
2131 p+=GetPixelChannels(image);
2132 }
2133 break;
2134 }
2135 if (LocaleCompare(stream_info->map,"I") == 0)
2136 {
2137 p=GetAuthenticPixelQueue(image);
2138 if (p == (const Quantum *) NULL)
2139 break;
2140 for (x=0; x < (ssize_t) GetImageExtent(image); x++)
2141 {
2142 *q++=ScaleQuantumToLong(ClampToQuantum(GetPixelIntensity(image,p)));
2143 p+=GetPixelChannels(image);
2144 }
2145 break;
2146 }
2147 if (LocaleCompare(stream_info->map,"RGB") == 0)
2148 {
2149 p=GetAuthenticPixelQueue(image);
2150 if (p == (const Quantum *) NULL)
2151 break;
2152 for (x=0; x < (ssize_t) GetImageExtent(image); x++)
2153 {
2154 *q++=ScaleQuantumToLong(GetPixelRed(image,p));
2155 *q++=ScaleQuantumToLong(GetPixelGreen(image,p));
2156 *q++=ScaleQuantumToLong(GetPixelBlue(image,p));
2157 p+=GetPixelChannels(image);
2158 }
2159 break;
2160 }
2161 if (LocaleCompare(stream_info->map,"RGBA") == 0)
2162 {
2163 p=GetAuthenticPixelQueue(image);
2164 if (p == (const Quantum *) NULL)
2165 break;
2166 for (x=0; x < (ssize_t) GetImageExtent(image); x++)
2167 {
2168 *q++=ScaleQuantumToLong(GetPixelRed(image,p));
2169 *q++=ScaleQuantumToLong(GetPixelGreen(image,p));
2170 *q++=ScaleQuantumToLong(GetPixelBlue(image,p));
2171 *q++=ScaleQuantumToLong(GetPixelAlpha(image,p));
2172 p+=GetPixelChannels(image);
2173 }
2174 break;
2175 }
2176 if (LocaleCompare(stream_info->map,"RGBP") == 0)
2177 {
2178 p=GetAuthenticPixelQueue(image);
2179 if (p == (const Quantum *) NULL)
2180 break;
2181 for (x=0; x < (ssize_t) GetImageExtent(image); x++)
2182 {
2183 *q++=ScaleQuantumToLong(GetPixelRed(image,p));
2184 *q++=ScaleQuantumToLong(GetPixelGreen(image,p));
2185 *q++=ScaleQuantumToLong(GetPixelBlue(image,p));
2186 *q++=0;
2187 p+=GetPixelChannels(image);
2188 }
2189 break;
2190 }
2191 p=GetAuthenticPixelQueue(image);
2192 if (p == (const Quantum *) NULL)
2193 break;
2194 for (x=0; x < (ssize_t) GetImageExtent(image); x++)
2195 {
2196 for (i=0; i < (ssize_t) length; i++)
2197 {
2198 *q=0;
2199 switch (quantum_map[i])
2200 {
2201 case RedQuantum:
2202 case CyanQuantum:
2203 {
2204 *q=ScaleQuantumToLong(GetPixelRed(image,p));
2205 break;
2206 }
2207 case GreenQuantum:
2208 case MagentaQuantum:
2209 {
2210 *q=ScaleQuantumToLong(GetPixelGreen(image,p));
2211 break;
2212 }
2213 case BlueQuantum:
2214 case YellowQuantum:
2215 {
2216 *q=ScaleQuantumToLong(GetPixelBlue(image,p));
2217 break;
2218 }
2219 case AlphaQuantum:
2220 {
2221 *q=ScaleQuantumToLong(GetPixelAlpha(image,p));
2222 break;
2223 }
2224 case OpacityQuantum:
2225 {
2226 *q=ScaleQuantumToLong(GetPixelOpacity(image,p));
2227 break;
2228 }
2229 case BlackQuantum:
2230 {
2231 if (image->colorspace == CMYKColorspace)
2232 *q=ScaleQuantumToLong(GetPixelBlack(image,p));
2233 break;
2234 }
2235 case IndexQuantum:
2236 {
2237 *q=ScaleQuantumToLong(ClampToQuantum(GetPixelIntensity(image,p)));
2238 break;
2239 }
2240 default:
2241 break;
2242 }
2243 q++;
2244 }
2245 p+=GetPixelChannels(image);
2246 }
2247 break;
2248 }
2249 case LongLongPixel:
2250 {
2251 MagickSizeType
2252 *q;
2253
2254 q=(MagickSizeType *) stream_info->pixels;
2255 if (LocaleCompare(stream_info->map,"BGR") == 0)
2256 {
2257 p=GetAuthenticPixelQueue(image);
2258 if (p == (const Quantum *) NULL)
2259 break;
2260 for (x=0; x < (ssize_t) GetImageExtent(image); x++)
2261 {
2262 *q++=ScaleQuantumToLongLong(GetPixelBlue(image,p));
2263 *q++=ScaleQuantumToLongLong(GetPixelGreen(image,p));
2264 *q++=ScaleQuantumToLongLong(GetPixelRed(image,p));
2265 p+=GetPixelChannels(image);
2266 }
2267 break;
2268 }
2269 if (LocaleCompare(stream_info->map,"BGRA") == 0)
2270 {
2271 p=GetAuthenticPixelQueue(image);
2272 if (p == (const Quantum *) NULL)
2273 break;
2274 for (x=0; x < (ssize_t) GetImageExtent(image); x++)
2275 {
2276 *q++=ScaleQuantumToLongLong(GetPixelBlue(image,p));
2277 *q++=ScaleQuantumToLongLong(GetPixelGreen(image,p));
2278 *q++=ScaleQuantumToLongLong(GetPixelRed(image,p));
2279 *q++=ScaleQuantumToLongLong(GetPixelAlpha(image,p));
2280 p+=GetPixelChannels(image);
2281 }
2282 break;
2283 }
2284 if (LocaleCompare(stream_info->map,"BGRP") == 0)
2285 {
2286 p=GetAuthenticPixelQueue(image);
2287 if (p == (const Quantum *) NULL)
2288 break;
2289 for (x=0; x < (ssize_t) GetImageExtent(image); x++)
2290 {
2291 *q++=ScaleQuantumToLongLong(GetPixelBlue(image,p));
2292 *q++=ScaleQuantumToLongLong(GetPixelGreen(image,p));
2293 *q++=ScaleQuantumToLongLong(GetPixelRed(image,p));
2294 *q++=0U;
2295 p+=GetPixelChannels(image);
2296 }
2297 break;
2298 }
2299 if (LocaleCompare(stream_info->map,"I") == 0)
2300 {
2301 p=GetAuthenticPixelQueue(image);
2302 if (p == (const Quantum *) NULL)
2303 break;
2304 for (x=0; x < (ssize_t) GetImageExtent(image); x++)
2305 {
2306 *q++=ScaleQuantumToLongLong(ClampToQuantum(
2307 GetPixelIntensity(image,p)));
2308 p+=GetPixelChannels(image);
2309 }
2310 break;
2311 }
2312 if (LocaleCompare(stream_info->map,"RGB") == 0)
2313 {
2314 p=GetAuthenticPixelQueue(image);
2315 if (p == (const Quantum *) NULL)
2316 break;
2317 for (x=0; x < (ssize_t) GetImageExtent(image); x++)
2318 {
2319 *q++=ScaleQuantumToLongLong(GetPixelRed(image,p));
2320 *q++=ScaleQuantumToLongLong(GetPixelGreen(image,p));
2321 *q++=ScaleQuantumToLongLong(GetPixelBlue(image,p));
2322 p+=GetPixelChannels(image);
2323 }
2324 break;
2325 }
2326 if (LocaleCompare(stream_info->map,"RGBA") == 0)
2327 {
2328 p=GetAuthenticPixelQueue(image);
2329 if (p == (const Quantum *) NULL)
2330 break;
2331 for (x=0; x < (ssize_t) GetImageExtent(image); x++)
2332 {
2333 *q++=ScaleQuantumToLongLong(GetPixelRed(image,p));
2334 *q++=ScaleQuantumToLongLong(GetPixelGreen(image,p));
2335 *q++=ScaleQuantumToLongLong(GetPixelBlue(image,p));
2336 *q++=ScaleQuantumToLongLong(GetPixelAlpha(image,p));
2337 p+=GetPixelChannels(image);
2338 }
2339 break;
2340 }
2341 if (LocaleCompare(stream_info->map,"RGBP") == 0)
2342 {
2343 p=GetAuthenticPixelQueue(image);
2344 if (p == (const Quantum *) NULL)
2345 break;
2346 for (x=0; x < (ssize_t) GetImageExtent(image); x++)
2347 {
2348 *q++=ScaleQuantumToLongLong(GetPixelRed(image,p));
2349 *q++=ScaleQuantumToLongLong(GetPixelGreen(image,p));
2350 *q++=ScaleQuantumToLongLong(GetPixelBlue(image,p));
2351 *q++=0U;
2352 p+=GetPixelChannels(image);
2353 }
2354 break;
2355 }
2356 p=GetAuthenticPixelQueue(image);
2357 if (p == (const Quantum *) NULL)
2358 break;
2359 for (x=0; x < (ssize_t) GetImageExtent(image); x++)
2360 {
2361 for (i=0; i < (ssize_t) length; i++)
2362 {
2363 *q=0;
2364 switch (quantum_map[i])
2365 {
2366 case RedQuantum:
2367 case CyanQuantum:
2368 {
2369 *q=ScaleQuantumToLongLong(GetPixelRed(image,p));
2370 break;
2371 }
2372 case GreenQuantum:
2373 case MagentaQuantum:
2374 {
2375 *q=ScaleQuantumToLongLong(GetPixelGreen(image,p));
2376 break;
2377 }
2378 case BlueQuantum:
2379 case YellowQuantum:
2380 {
2381 *q=ScaleQuantumToLongLong(GetPixelBlue(image,p));
2382 break;
2383 }
2384 case AlphaQuantum:
2385 {
2386 *q=ScaleQuantumToLongLong(GetPixelAlpha(image,p));
2387 break;
2388 }
2389 case OpacityQuantum:
2390 {
2391 *q=ScaleQuantumToLongLong(GetPixelOpacity(image,p));
2392 break;
2393 }
2394 case BlackQuantum:
2395 {
2396 if (image->colorspace == CMYKColorspace)
2397 *q=ScaleQuantumToLongLong(GetPixelBlack(image,p));
2398 break;
2399 }
2400 case IndexQuantum:
2401 {
2402 *q=ScaleQuantumToLongLong(ClampToQuantum(
2403 GetPixelIntensity(image,p)));
2404 break;
2405 }
2406 default:
2407 *q=0;
2408 }
2409 q++;
2410 }
2411 p+=GetPixelChannels(image);
2412 }
2413 break;
2414 }
2415 case QuantumPixel:
2416 {
2417 Quantum
2418 *q;
2419
2420 q=(Quantum *) stream_info->pixels;
2421 if (LocaleCompare(stream_info->map,"BGR") == 0)
2422 {
2423 p=GetAuthenticPixelQueue(image);
2424 if (p == (const Quantum *) NULL)
2425 break;
2426 for (x=0; x < (ssize_t) GetImageExtent(image); x++)
2427 {
2428 *q++=GetPixelBlue(image,p);
2429 *q++=GetPixelGreen(image,p);
2430 *q++=GetPixelRed(image,p);
2431 p+=GetPixelChannels(image);
2432 }
2433 break;
2434 }
2435 if (LocaleCompare(stream_info->map,"BGRA") == 0)
2436 {
2437 p=GetAuthenticPixelQueue(image);
2438 if (p == (const Quantum *) NULL)
2439 break;
2440 for (x=0; x < (ssize_t) GetImageExtent(image); x++)
2441 {
2442 *q++=GetPixelBlue(image,p);
2443 *q++=GetPixelGreen(image,p);
2444 *q++=GetPixelRed(image,p);
2445 *q++=GetPixelAlpha(image,p);
2446 p+=GetPixelChannels(image);
2447 }
2448 break;
2449 }
2450 if (LocaleCompare(stream_info->map,"BGRP") == 0)
2451 {
2452 p=GetAuthenticPixelQueue(image);
2453 if (p == (const Quantum *) NULL)
2454 break;
2455 for (x=0; x < (ssize_t) GetImageExtent(image); x++)
2456 {
2457 *q++=GetPixelBlue(image,p);
2458 *q++=GetPixelGreen(image,p);
2459 *q++=GetPixelRed(image,p);
2460 *q++=(Quantum) 0;
2461 p+=GetPixelChannels(image);
2462 }
2463 break;
2464 }
2465 if (LocaleCompare(stream_info->map,"I") == 0)
2466 {
2467 p=GetAuthenticPixelQueue(image);
2468 if (p == (const Quantum *) NULL)
2469 break;
2470 for (x=0; x < (ssize_t) GetImageExtent(image); x++)
2471 {
2472 *q++=ClampToQuantum(GetPixelIntensity(image,p));
2473 p+=GetPixelChannels(image);
2474 }
2475 break;
2476 }
2477 if (LocaleCompare(stream_info->map,"RGB") == 0)
2478 {
2479 p=GetAuthenticPixelQueue(image);
2480 if (p == (const Quantum *) NULL)
2481 break;
2482 for (x=0; x < (ssize_t) GetImageExtent(image); x++)
2483 {
2484 *q++=GetPixelRed(image,p);
2485 *q++=GetPixelGreen(image,p);
2486 *q++=GetPixelBlue(image,p);
2487 p+=GetPixelChannels(image);
2488 }
2489 break;
2490 }
2491 if (LocaleCompare(stream_info->map,"RGBA") == 0)
2492 {
2493 p=GetAuthenticPixelQueue(image);
2494 if (p == (const Quantum *) NULL)
2495 break;
2496 for (x=0; x < (ssize_t) GetImageExtent(image); x++)
2497 {
2498 *q++=GetPixelRed(image,p);
2499 *q++=GetPixelGreen(image,p);
2500 *q++=GetPixelBlue(image,p);
2501 *q++=GetPixelAlpha(image,p);
2502 p+=GetPixelChannels(image);
2503 }
2504 break;
2505 }
2506 if (LocaleCompare(stream_info->map,"RGBP") == 0)
2507 {
2508 p=GetAuthenticPixelQueue(image);
2509 if (p == (const Quantum *) NULL)
2510 break;
2511 for (x=0; x < (ssize_t) GetImageExtent(image); x++)
2512 {
2513 *q++=GetPixelRed(image,p);
2514 *q++=GetPixelGreen(image,p);
2515 *q++=GetPixelBlue(image,p);
2516 *q++=(Quantum) 0;
2517 p+=GetPixelChannels(image);
2518 }
2519 break;
2520 }
2521 p=GetAuthenticPixelQueue(image);
2522 if (p == (const Quantum *) NULL)
2523 break;
2524 for (x=0; x < (ssize_t) GetImageExtent(image); x++)
2525 {
2526 for (i=0; i < (ssize_t) length; i++)
2527 {
2528 *q=(Quantum) 0;
2529 switch (quantum_map[i])
2530 {
2531 case RedQuantum:
2532 case CyanQuantum:
2533 {
2534 *q=GetPixelRed(image,p);
2535 break;
2536 }
2537 case GreenQuantum:
2538 case MagentaQuantum:
2539 {
2540 *q=GetPixelGreen(image,p);
2541 break;
2542 }
2543 case BlueQuantum:
2544 case YellowQuantum:
2545 {
2546 *q=GetPixelBlue(image,p);
2547 break;
2548 }
2549 case AlphaQuantum:
2550 {
2551 *q=GetPixelAlpha(image,p);
2552 break;
2553 }
2554 case OpacityQuantum:
2555 {
2556 *q=GetPixelOpacity(image,p);
2557 break;
2558 }
2559 case BlackQuantum:
2560 {
2561 if (image->colorspace == CMYKColorspace)
2562 *q=GetPixelBlack(image,p);
2563 break;
2564 }
2565 case IndexQuantum:
2566 {
2567 *q=ClampToQuantum(GetPixelIntensity(image,p));
2568 break;
2569 }
2570 default:
2571 *q=(Quantum) 0;
2572 }
2573 q++;
2574 }
2575 p+=GetPixelChannels(image);
2576 }
2577 break;
2578 }
2579 case ShortPixel:
2580 {
2581 unsigned short
2582 *q;
2583
2584 q=(unsigned short *) stream_info->pixels;
2585 if (LocaleCompare(stream_info->map,"BGR") == 0)
2586 {
2587 p=GetAuthenticPixelQueue(image);
2588 if (p == (const Quantum *) NULL)
2589 break;
2590 for (x=0; x < (ssize_t) GetImageExtent(image); x++)
2591 {
2592 *q++=ScaleQuantumToShort(GetPixelBlue(image,p));
2593 *q++=ScaleQuantumToShort(GetPixelGreen(image,p));
2594 *q++=ScaleQuantumToShort(GetPixelRed(image,p));
2595 p+=GetPixelChannels(image);
2596 }
2597 break;
2598 }
2599 if (LocaleCompare(stream_info->map,"BGRA") == 0)
2600 {
2601 p=GetAuthenticPixelQueue(image);
2602 if (p == (const Quantum *) NULL)
2603 break;
2604 for (x=0; x < (ssize_t) GetImageExtent(image); x++)
2605 {
2606 *q++=ScaleQuantumToShort(GetPixelBlue(image,p));
2607 *q++=ScaleQuantumToShort(GetPixelGreen(image,p));
2608 *q++=ScaleQuantumToShort(GetPixelRed(image,p));
2609 *q++=ScaleQuantumToShort(GetPixelAlpha(image,p));
2610 p+=GetPixelChannels(image);
2611 }
2612 break;
2613 }
2614 if (LocaleCompare(stream_info->map,"BGRP") == 0)
2615 {
2616 p=GetAuthenticPixelQueue(image);
2617 if (p == (const Quantum *) NULL)
2618 break;
2619 for (x=0; x < (ssize_t) GetImageExtent(image); x++)
2620 {
2621 *q++=ScaleQuantumToShort(GetPixelBlue(image,p));
2622 *q++=ScaleQuantumToShort(GetPixelGreen(image,p));
2623 *q++=ScaleQuantumToShort(GetPixelRed(image,p));
2624 *q++=0;
2625 p+=GetPixelChannels(image);
2626 }
2627 break;
2628 }
2629 if (LocaleCompare(stream_info->map,"I") == 0)
2630 {
2631 p=GetAuthenticPixelQueue(image);
2632 if (p == (const Quantum *) NULL)
2633 break;
2634 for (x=0; x < (ssize_t) GetImageExtent(image); x++)
2635 {
2636 *q++=ScaleQuantumToShort(ClampToQuantum(
2637 GetPixelIntensity(image,p)));
2638 p+=GetPixelChannels(image);
2639 }
2640 break;
2641 }
2642 if (LocaleCompare(stream_info->map,"RGB") == 0)
2643 {
2644 p=GetAuthenticPixelQueue(image);
2645 if (p == (const Quantum *) NULL)
2646 break;
2647 for (x=0; x < (ssize_t) GetImageExtent(image); x++)
2648 {
2649 *q++=ScaleQuantumToShort(GetPixelRed(image,p));
2650 *q++=ScaleQuantumToShort(GetPixelGreen(image,p));
2651 *q++=ScaleQuantumToShort(GetPixelBlue(image,p));
2652 p+=GetPixelChannels(image);
2653 }
2654 break;
2655 }
2656 if (LocaleCompare(stream_info->map,"RGBA") == 0)
2657 {
2658 p=GetAuthenticPixelQueue(image);
2659 if (p == (const Quantum *) NULL)
2660 break;
2661 for (x=0; x < (ssize_t) GetImageExtent(image); x++)
2662 {
2663 *q++=ScaleQuantumToShort(GetPixelRed(image,p));
2664 *q++=ScaleQuantumToShort(GetPixelGreen(image,p));
2665 *q++=ScaleQuantumToShort(GetPixelBlue(image,p));
2666 *q++=ScaleQuantumToShort(GetPixelAlpha(image,p));
2667 p+=GetPixelChannels(image);
2668 }
2669 break;
2670 }
2671 if (LocaleCompare(stream_info->map,"RGBP") == 0)
2672 {
2673 p=GetAuthenticPixelQueue(image);
2674 if (p == (const Quantum *) NULL)
2675 break;
2676 for (x=0; x < (ssize_t) GetImageExtent(image); x++)
2677 {
2678 *q++=ScaleQuantumToShort(GetPixelRed(image,p));
2679 *q++=ScaleQuantumToShort(GetPixelGreen(image,p));
2680 *q++=ScaleQuantumToShort(GetPixelBlue(image,p));
2681 *q++=0;
2682 p+=GetPixelChannels(image);
2683 }
2684 break;
2685 }
2686 p=GetAuthenticPixelQueue(image);
2687 if (p == (const Quantum *) NULL)
2688 break;
2689 for (x=0; x < (ssize_t) GetImageExtent(image); x++)
2690 {
2691 for (i=0; i < (ssize_t) length; i++)
2692 {
2693 *q=0;
2694 switch (quantum_map[i])
2695 {
2696 case RedQuantum:
2697 case CyanQuantum:
2698 {
2699 *q=ScaleQuantumToShort(GetPixelRed(image,p));
2700 break;
2701 }
2702 case GreenQuantum:
2703 case MagentaQuantum:
2704 {
2705 *q=ScaleQuantumToShort(GetPixelGreen(image,p));
2706 break;
2707 }
2708 case BlueQuantum:
2709 case YellowQuantum:
2710 {
2711 *q=ScaleQuantumToShort(GetPixelBlue(image,p));
2712 break;
2713 }
2714 case AlphaQuantum:
2715 {
2716 *q=ScaleQuantumToShort(GetPixelAlpha(image,p));
2717 break;
2718 }
2719 case OpacityQuantum:
2720 {
2721 *q=ScaleQuantumToShort(GetPixelOpacity(image,p));
2722 break;
2723 }
2724 case BlackQuantum:
2725 {
2726 if (image->colorspace == CMYKColorspace)
2727 *q=ScaleQuantumToShort(GetPixelBlack(image,p));
2728 break;
2729 }
2730 case IndexQuantum:
2731 {
2732 *q=ScaleQuantumToShort(ClampToQuantum(
2733 GetPixelIntensity(image,p)));
2734 break;
2735 }
2736 default:
2737 break;
2738 }
2739 q++;
2740 }
2741 p+=GetPixelChannels(image);
2742 }
2743 break;
2744 }
2745 default:
2746 {
2747 quantum_map=(QuantumType *) RelinquishMagickMemory(quantum_map);
2748 (void) ThrowMagickException(exception,GetMagickModule(),OptionError,
2749 "UnrecognizedPixelMap","`%s'",stream_info->map);
2750 break;
2751 }
2752 }
2753 quantum_map=(QuantumType *) RelinquishMagickMemory(quantum_map);
2754 return(MagickTrue);
2755 }
2756
2757 /*
2758 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2759 % %
2760 % %
2761 % %
2762 + S y n c A u t h e n t i c P i x e l s S t r e a m %
2763 % %
2764 % %
2765 % %
2766 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2767 %
2768 % SyncAuthenticPixelsStream() calls the user supplied callback method with
2769 % the latest stream of pixels.
2770 %
2771 % The format of the SyncAuthenticPixelsStream method is:
2772 %
2773 % MagickBooleanType SyncAuthenticPixelsStream(Image *image,
2774 % ExceptionInfo *exception)
2775 %
2776 % A description of each parameter follows:
2777 %
2778 % o image: the image.
2779 %
2780 % o exception: return any errors or warnings in this structure.
2781 %
2782 */
SyncAuthenticPixelsStream(Image * image,ExceptionInfo * exception)2783 static MagickBooleanType SyncAuthenticPixelsStream(Image *image,
2784 ExceptionInfo *exception)
2785 {
2786 CacheInfo
2787 *cache_info;
2788
2789 size_t
2790 length;
2791
2792 StreamHandler
2793 stream_handler;
2794
2795 assert(image != (Image *) NULL);
2796 assert(image->signature == MagickCoreSignature);
2797 if (image->debug != MagickFalse)
2798 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
2799 cache_info=(CacheInfo *) image->cache;
2800 assert(cache_info->signature == MagickCoreSignature);
2801 stream_handler=GetBlobStreamHandler(image);
2802 if (stream_handler == (StreamHandler) NULL)
2803 {
2804 (void) ThrowMagickException(exception,GetMagickModule(),StreamError,
2805 "NoStreamHandlerIsDefined","`%s'",image->filename);
2806 return(MagickFalse);
2807 }
2808 length=stream_handler(image,cache_info->pixels,(size_t) cache_info->columns);
2809 return(length == cache_info->columns ? MagickTrue : MagickFalse);
2810 }
2811
2812 /*
2813 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2814 % %
2815 % %
2816 % %
2817 % W r i t e S t r e a m %
2818 % %
2819 % %
2820 % %
2821 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2822 %
2823 % WriteStream() makes the image pixels available to a user supplied callback
2824 % method immediately upon writing pixel data with the WriteImage() method.
2825 %
2826 % The format of the WriteStream() method is:
2827 %
2828 % MagickBooleanType WriteStream(const ImageInfo *image_info,Image *,
2829 % StreamHandler stream,ExceptionInfo *exception)
2830 %
2831 % A description of each parameter follows:
2832 %
2833 % o image_info: the image info.
2834 %
2835 % o stream: A callback method.
2836 %
2837 % o exception: return any errors or warnings in this structure.
2838 %
2839 */
WriteStream(const ImageInfo * image_info,Image * image,StreamHandler stream,ExceptionInfo * exception)2840 MagickExport MagickBooleanType WriteStream(const ImageInfo *image_info,
2841 Image *image,StreamHandler stream,ExceptionInfo *exception)
2842 {
2843 ImageInfo
2844 *write_info;
2845
2846 MagickBooleanType
2847 status;
2848
2849 assert(image_info != (ImageInfo *) NULL);
2850 assert(image_info->signature == MagickCoreSignature);
2851 if (image_info->debug != MagickFalse)
2852 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
2853 image_info->filename);
2854 assert(image != (Image *) NULL);
2855 assert(image->signature == MagickCoreSignature);
2856 write_info=CloneImageInfo(image_info);
2857 *write_info->magick='\0';
2858 write_info->stream=stream;
2859 status=WriteImage(write_info,image,exception);
2860 write_info=DestroyImageInfo(write_info);
2861 return(status);
2862 }
2863