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