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