blob: 6dd1ff1884b193e25a1816cda80523fcbd610af5 [file] [log] [blame]
cristy3ed852e2009-09-05 21:47:34 +00001/*
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
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
62/*
63 Typedef declaractions.
64*/
65struct _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
104/*
105 Declare pixel cache interfaces.
106*/
107#if defined(__cplusplus) || defined(c_plusplus)
108extern "C" {
109#endif
110
111static const PixelPacket
112 *GetVirtualPixelStream(const Image *,const VirtualPixelMethod,const long,
113 const long,const unsigned long,const unsigned long,ExceptionInfo *);
114
115static MagickBooleanType
116 StreamImagePixels(const StreamInfo *,const Image *,ExceptionInfo *),
117 SyncAuthenticPixelsStream(Image *,ExceptionInfo *);
118
119static 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
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*/
149MagickExport 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
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
192static 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
205static 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
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*/
261MagickExport 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
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*/
306static 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
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*/
352static 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
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*/
390static 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
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*/
434static 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
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*/
483static 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
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*/
522MagickExport 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
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*/
555static 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
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*/
592static 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
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
642static 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
666static 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
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*/
759MagickExport 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
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*/
801static 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
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*/
908MagickExport 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
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*/
978MagickExport 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
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*/
1010MagickExport 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
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*/
1042MagickExport 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
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)
1080extern "C" {
1081#endif
1082
1083static 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
1167MagickExport 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
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*/
1225static 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
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*/
2617static 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
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*/
2672MagickExport 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}