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