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