1 /*
2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3 % %
4 % %
5 % %
6 % BBBB GGGG RRRR %
7 % B B G R R %
8 % BBBB G GG RRRR %
9 % B B G G R R %
10 % BBBB GGG R R %
11 % %
12 % %
13 % Read/Write Raw BGR Image Format %
14 % %
15 % Software Design %
16 % Cristy %
17 % July 1992 %
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 Include declarations.
41 */
42 #include "MagickCore/studio.h"
43 #include "MagickCore/blob.h"
44 #include "MagickCore/blob-private.h"
45 #include "MagickCore/cache.h"
46 #include "MagickCore/channel.h"
47 #include "MagickCore/colorspace.h"
48 #include "MagickCore/colorspace-private.h"
49 #include "MagickCore/constitute.h"
50 #include "MagickCore/exception.h"
51 #include "MagickCore/exception-private.h"
52 #include "MagickCore/image.h"
53 #include "MagickCore/image-private.h"
54 #include "MagickCore/list.h"
55 #include "MagickCore/magick.h"
56 #include "MagickCore/memory_.h"
57 #include "MagickCore/monitor.h"
58 #include "MagickCore/monitor-private.h"
59 #include "MagickCore/pixel-accessor.h"
60 #include "MagickCore/quantum-private.h"
61 #include "MagickCore/static.h"
62 #include "MagickCore/statistic.h"
63 #include "MagickCore/string_.h"
64 #include "MagickCore/module.h"
65 #include "MagickCore/utility.h"
66
67 /*
68 Forward declarations.
69 */
70 static MagickBooleanType
71 WriteBGRImage(const ImageInfo *,Image *,ExceptionInfo *);
72
73 /*
74 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
75 % %
76 % %
77 % %
78 % R e a d B G R I m a g e %
79 % %
80 % %
81 % %
82 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
83 %
84 % ReadBGRImage() reads an image of raw BGR, or BGRA samples and returns
85 % it. It allocates the memory necessary for the new Image structure and
86 % returns a pointer to the new image.
87 %
88 % The format of the ReadBGRImage method is:
89 %
90 % Image *ReadBGRImage(const ImageInfo *image_info,
91 % ExceptionInfo *exception)
92 %
93 % A description of each parameter follows:
94 %
95 % o image_info: the image info.
96 %
97 % o exception: return any errors or warnings in this structure.
98 %
99 */
ReadBGRImage(const ImageInfo * image_info,ExceptionInfo * exception)100 static Image *ReadBGRImage(const ImageInfo *image_info,ExceptionInfo *exception)
101 {
102 const void
103 *stream;
104
105 Image
106 *canvas_image,
107 *image;
108
109 MagickBooleanType
110 status;
111
112 MagickOffsetType
113 scene;
114
115 QuantumInfo
116 *quantum_info;
117
118 QuantumType
119 quantum_type;
120
121 ssize_t
122 i;
123
124 size_t
125 length;
126
127 ssize_t
128 count,
129 y;
130
131 unsigned char
132 *pixels;
133
134 /*
135 Open image file.
136 */
137 assert(image_info != (const ImageInfo *) NULL);
138 assert(image_info->signature == MagickCoreSignature);
139 if (image_info->debug != MagickFalse)
140 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
141 image_info->filename);
142 assert(exception != (ExceptionInfo *) NULL);
143 assert(exception->signature == MagickCoreSignature);
144 image=AcquireImage(image_info,exception);
145 if ((image->columns == 0) || (image->rows == 0))
146 ThrowReaderException(OptionError,"MustSpecifyImageSize");
147 if (image_info->interlace != PartitionInterlace)
148 {
149 status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
150 if (status == MagickFalse)
151 {
152 image=DestroyImageList(image);
153 return((Image *) NULL);
154 }
155 if (DiscardBlobBytes(image,image->offset) == MagickFalse)
156 ThrowFileException(exception,CorruptImageError,"UnexpectedEndOfFile",
157 image->filename);
158 }
159 /*
160 Create virtual canvas to support cropping (i.e. image.rgb[100x100+10+20]).
161 */
162 canvas_image=CloneImage(image,image->extract_info.width,1,MagickFalse,
163 exception);
164 if (canvas_image == (Image *) NULL)
165 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
166 (void) SetImageVirtualPixelMethod(canvas_image,BlackVirtualPixelMethod,
167 exception);
168 quantum_info=AcquireQuantumInfo(image_info,canvas_image);
169 if (quantum_info == (QuantumInfo *) NULL)
170 {
171 canvas_image=DestroyImage(canvas_image);
172 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
173 }
174 quantum_type=BGRQuantum;
175 if (LocaleCompare(image_info->magick,"BGRA") == 0)
176 {
177 quantum_type=BGRAQuantum;
178 image->alpha_trait=BlendPixelTrait;
179 canvas_image->alpha_trait=BlendPixelTrait;
180 }
181 if (LocaleCompare(image_info->magick,"BGRO") == 0)
182 {
183 quantum_type=BGROQuantum;
184 image->alpha_trait=BlendPixelTrait;
185 canvas_image->alpha_trait=BlendPixelTrait;
186 }
187 pixels=GetQuantumPixels(quantum_info);
188 if (image_info->number_scenes != 0)
189 while (image->scene < image_info->scene)
190 {
191 /*
192 Skip to next image.
193 */
194 image->scene++;
195 length=GetQuantumExtent(canvas_image,quantum_info,quantum_type);
196 for (y=0; y < (ssize_t) image->rows; y++)
197 {
198 stream=ReadBlobStream(image,length,pixels,&count);
199 if (count != (ssize_t) length)
200 break;
201 }
202 }
203 count=0;
204 length=0;
205 scene=0;
206 status=MagickTrue;
207 stream=NULL;
208 do
209 {
210 /*
211 Read pixels to virtual canvas image then push to image.
212 */
213 if ((image_info->ping != MagickFalse) && (image_info->number_scenes != 0))
214 if (image->scene >= (image_info->scene+image_info->number_scenes-1))
215 break;
216 status=SetImageExtent(image,image->columns,image->rows,exception);
217 if (status == MagickFalse)
218 break;
219 switch (image_info->interlace)
220 {
221 case NoInterlace:
222 default:
223 {
224 /*
225 No interlacing: BGRBGRBGRBGRBGRBGR...
226 */
227 if (scene == 0)
228 {
229 length=GetQuantumExtent(canvas_image,quantum_info,quantum_type);
230 stream=ReadBlobStream(image,length,pixels,&count);
231 }
232 for (y=0; y < (ssize_t) image->extract_info.height; y++)
233 {
234 const Quantum
235 *magick_restrict p;
236
237 Quantum
238 *magick_restrict q;
239
240 ssize_t
241 x;
242
243 if (count != (ssize_t) length)
244 {
245 status=MagickFalse;
246 ThrowFileException(exception,CorruptImageError,
247 "UnexpectedEndOfFile",image->filename);
248 break;
249 }
250 q=GetAuthenticPixels(canvas_image,0,0,canvas_image->columns,1,
251 exception);
252 if (q == (Quantum *) NULL)
253 break;
254 length=ImportQuantumPixels(canvas_image,(CacheView *) NULL,
255 quantum_info,quantum_type,(unsigned char *) stream,exception);
256 if (SyncAuthenticPixels(canvas_image,exception) == MagickFalse)
257 break;
258 if (((y-image->extract_info.y) >= 0) &&
259 ((y-image->extract_info.y) < (ssize_t) image->rows))
260 {
261 p=GetVirtualPixels(canvas_image,canvas_image->extract_info.x,0,
262 canvas_image->columns,1,exception);
263 q=QueueAuthenticPixels(image,0,y-image->extract_info.y,
264 image->columns,1,exception);
265 if ((p == (const Quantum *) NULL) ||
266 (q == (Quantum *) NULL))
267 break;
268 for (x=0; x < (ssize_t) image->columns; x++)
269 {
270 SetPixelRed(image,GetPixelRed(canvas_image,p),q);
271 SetPixelGreen(image,GetPixelGreen(canvas_image,p),q);
272 SetPixelBlue(image,GetPixelBlue(canvas_image,p),q);
273 SetPixelAlpha(image,OpaqueAlpha,q);
274 if (image->alpha_trait != UndefinedPixelTrait)
275 SetPixelAlpha(image,GetPixelAlpha(canvas_image,p),q);
276 p+=GetPixelChannels(canvas_image);
277 q+=GetPixelChannels(image);
278 }
279 if (SyncAuthenticPixels(image,exception) == MagickFalse)
280 break;
281 }
282 if (image->previous == (Image *) NULL)
283 {
284 status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y,
285 image->rows);
286 if (status == MagickFalse)
287 break;
288 }
289 stream=ReadBlobStream(image,length,pixels,&count);
290 }
291 break;
292 }
293 case LineInterlace:
294 {
295 static QuantumType
296 quantum_types[4] =
297 {
298 BlueQuantum,
299 GreenQuantum,
300 RedQuantum,
301 AlphaQuantum
302 };
303
304 /*
305 Line interlacing: BBB...GGG...RRR...RRR...GGG...BBB...
306 */
307 if (scene == 0)
308 {
309 length=GetQuantumExtent(canvas_image,quantum_info,RedQuantum);
310 stream=ReadBlobStream(image,length,pixels,&count);
311 }
312 for (y=0; y < (ssize_t) image->extract_info.height; y++)
313 {
314 const Quantum
315 *magick_restrict p;
316
317 Quantum
318 *magick_restrict q;
319
320 ssize_t
321 x;
322
323 if (count != (ssize_t) length)
324 {
325 status=MagickFalse;
326 ThrowFileException(exception,CorruptImageError,
327 "UnexpectedEndOfFile",image->filename);
328 break;
329 }
330 for (i=0; i < (ssize_t) (image->alpha_trait != UndefinedPixelTrait ? 4 : 3); i++)
331 {
332 quantum_type=quantum_types[i];
333 q=GetAuthenticPixels(canvas_image,0,0,canvas_image->columns,1,
334 exception);
335 if (q == (Quantum *) NULL)
336 break;
337 length=ImportQuantumPixels(canvas_image,(CacheView *) NULL,
338 quantum_info,quantum_type,(unsigned char *) stream,exception);
339 if (SyncAuthenticPixels(canvas_image,exception) == MagickFalse)
340 break;
341 if (((y-image->extract_info.y) >= 0) &&
342 ((y-image->extract_info.y) < (ssize_t) image->rows))
343 {
344 p=GetVirtualPixels(canvas_image,canvas_image->extract_info.x,0,
345 canvas_image->columns,1,exception);
346 q=GetAuthenticPixels(image,0,y-image->extract_info.y,
347 image->columns,1,exception);
348 if ((p == (const Quantum *) NULL) ||
349 (q == (Quantum *) NULL))
350 break;
351 for (x=0; x < (ssize_t) image->columns; x++)
352 {
353 switch (quantum_type)
354 {
355 case RedQuantum:
356 {
357 SetPixelRed(image,GetPixelRed(canvas_image,p),q);
358 break;
359 }
360 case GreenQuantum:
361 {
362 SetPixelGreen(image,GetPixelGreen(canvas_image,p),q);
363 break;
364 }
365 case BlueQuantum:
366 {
367 SetPixelBlue(image,GetPixelBlue(canvas_image,p),q);
368 break;
369 }
370 case OpacityQuantum:
371 {
372 SetPixelAlpha(image,GetPixelAlpha(canvas_image,p),q);
373 break;
374 }
375 case AlphaQuantum:
376 {
377 SetPixelAlpha(image,GetPixelAlpha(canvas_image,p),q);
378 break;
379 }
380 default:
381 break;
382 }
383 p+=GetPixelChannels(canvas_image);
384 q+=GetPixelChannels(image);
385 }
386 if (SyncAuthenticPixels(image,exception) == MagickFalse)
387 break;
388 }
389 stream=ReadBlobStream(image,length,pixels,&count);
390 }
391 if (image->previous == (Image *) NULL)
392 {
393 status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y,
394 image->rows);
395 if (status == MagickFalse)
396 break;
397 }
398 }
399 break;
400 }
401 case PlaneInterlace:
402 {
403 /*
404 Plane interlacing: RRRRRR...GGGGGG...BBBBBB...
405 */
406 if (scene == 0)
407 {
408 length=GetQuantumExtent(canvas_image,quantum_info,RedQuantum);
409 stream=ReadBlobStream(image,length,pixels,&count);
410 }
411 for (y=0; y < (ssize_t) image->extract_info.height; y++)
412 {
413 const Quantum
414 *magick_restrict p;
415
416 Quantum
417 *magick_restrict q;
418
419 ssize_t
420 x;
421
422 if (count != (ssize_t) length)
423 {
424 status=MagickFalse;
425 ThrowFileException(exception,CorruptImageError,
426 "UnexpectedEndOfFile",image->filename);
427 break;
428 }
429 q=GetAuthenticPixels(canvas_image,0,0,canvas_image->columns,1,
430 exception);
431 if (q == (Quantum *) NULL)
432 break;
433 length=ImportQuantumPixels(canvas_image,(CacheView *) NULL,
434 quantum_info,RedQuantum,(unsigned char *) stream,exception);
435 if (SyncAuthenticPixels(canvas_image,exception) == MagickFalse)
436 break;
437 if (((y-image->extract_info.y) >= 0) &&
438 ((y-image->extract_info.y) < (ssize_t) image->rows))
439 {
440 p=GetVirtualPixels(canvas_image,canvas_image->extract_info.x,0,
441 canvas_image->columns,1,exception);
442 q=GetAuthenticPixels(image,0,y-image->extract_info.y,
443 image->columns,1,exception);
444 if ((p == (const Quantum *) NULL) ||
445 (q == (Quantum *) NULL))
446 break;
447 for (x=0; x < (ssize_t) image->columns; x++)
448 {
449 SetPixelRed(image,GetPixelRed(canvas_image,p),q);
450 p+=GetPixelChannels(canvas_image);
451 q+=GetPixelChannels(image);
452 }
453 if (SyncAuthenticPixels(image,exception) == MagickFalse)
454 break;
455 }
456 stream=ReadBlobStream(image,length,pixels,&count);
457 }
458 if (image->previous == (Image *) NULL)
459 {
460 status=SetImageProgress(image,LoadImageTag,1,6);
461 if (status == MagickFalse)
462 break;
463 }
464 for (y=0; y < (ssize_t) image->extract_info.height; y++)
465 {
466 const Quantum
467 *magick_restrict p;
468
469 Quantum
470 *magick_restrict q;
471
472 ssize_t
473 x;
474
475 if (count != (ssize_t) length)
476 {
477 status=MagickFalse;
478 ThrowFileException(exception,CorruptImageError,
479 "UnexpectedEndOfFile",image->filename);
480 break;
481 }
482 q=GetAuthenticPixels(canvas_image,0,0,canvas_image->columns,1,
483 exception);
484 if (q == (Quantum *) NULL)
485 break;
486 length=ImportQuantumPixels(canvas_image,(CacheView *) NULL,
487 quantum_info,GreenQuantum,(unsigned char *) stream,exception);
488 if (SyncAuthenticPixels(canvas_image,exception) == MagickFalse)
489 break;
490 if (((y-image->extract_info.y) >= 0) &&
491 ((y-image->extract_info.y) < (ssize_t) image->rows))
492 {
493 p=GetVirtualPixels(canvas_image,canvas_image->extract_info.x,0,
494 canvas_image->columns,1,exception);
495 q=GetAuthenticPixels(image,0,y-image->extract_info.y,
496 image->columns,1,exception);
497 if ((p == (const Quantum *) NULL) ||
498 (q == (Quantum *) NULL))
499 break;
500 for (x=0; x < (ssize_t) image->columns; x++)
501 {
502 SetPixelGreen(image,GetPixelGreen(canvas_image,p),q);
503 p+=GetPixelChannels(canvas_image);
504 q+=GetPixelChannels(image);
505 }
506 if (SyncAuthenticPixels(image,exception) == MagickFalse)
507 break;
508 }
509 stream=ReadBlobStream(image,length,pixels,&count);
510 }
511 if (image->previous == (Image *) NULL)
512 {
513 status=SetImageProgress(image,LoadImageTag,2,6);
514 if (status == MagickFalse)
515 break;
516 }
517 for (y=0; y < (ssize_t) image->extract_info.height; y++)
518 {
519 const Quantum
520 *magick_restrict p;
521
522 Quantum
523 *magick_restrict q;
524
525 ssize_t
526 x;
527
528 if (count != (ssize_t) length)
529 {
530 status=MagickFalse;
531 ThrowFileException(exception,CorruptImageError,
532 "UnexpectedEndOfFile",image->filename);
533 break;
534 }
535 q=GetAuthenticPixels(canvas_image,0,0,canvas_image->columns,1,
536 exception);
537 if (q == (Quantum *) NULL)
538 break;
539 length=ImportQuantumPixels(canvas_image,(CacheView *) NULL,
540 quantum_info,BlueQuantum,(unsigned char *) stream,exception);
541 if (SyncAuthenticPixels(canvas_image,exception) == MagickFalse)
542 break;
543 if (((y-image->extract_info.y) >= 0) &&
544 ((y-image->extract_info.y) < (ssize_t) image->rows))
545 {
546 p=GetVirtualPixels(canvas_image,canvas_image->extract_info.x,0,
547 canvas_image->columns,1,exception);
548 q=GetAuthenticPixels(image,0,y-image->extract_info.y,
549 image->columns,1,exception);
550 if ((p == (const Quantum *) NULL) ||
551 (q == (Quantum *) NULL))
552 break;
553 for (x=0; x < (ssize_t) image->columns; x++)
554 {
555 SetPixelBlue(image,GetPixelBlue(canvas_image,p),q);
556 p+=GetPixelChannels(canvas_image);
557 q+=GetPixelChannels(image);
558 }
559 if (SyncAuthenticPixels(image,exception) == MagickFalse)
560 break;
561 }
562 stream=ReadBlobStream(image,length,pixels,&count);
563 }
564 if (image->previous == (Image *) NULL)
565 {
566 status=SetImageProgress(image,LoadImageTag,3,6);
567 if (status == MagickFalse)
568 break;
569 }
570 if (image->previous == (Image *) NULL)
571 {
572 status=SetImageProgress(image,LoadImageTag,4,6);
573 if (status == MagickFalse)
574 break;
575 }
576 if (image->alpha_trait != UndefinedPixelTrait)
577 {
578 for (y=0; y < (ssize_t) image->extract_info.height; y++)
579 {
580 const Quantum
581 *magick_restrict p;
582
583 Quantum
584 *magick_restrict q;
585
586 ssize_t
587 x;
588
589 if (count != (ssize_t) length)
590 {
591 status=MagickFalse;
592 ThrowFileException(exception,CorruptImageError,
593 "UnexpectedEndOfFile",image->filename);
594 break;
595 }
596 q=GetAuthenticPixels(canvas_image,0,0,canvas_image->columns,1,
597 exception);
598 if (q == (Quantum *) NULL)
599 break;
600 length=ImportQuantumPixels(canvas_image,(CacheView *) NULL,
601 quantum_info,AlphaQuantum,(unsigned char *) stream,exception);
602 if (SyncAuthenticPixels(canvas_image,exception) == MagickFalse)
603 break;
604 if (((y-image->extract_info.y) >= 0) &&
605 ((y-image->extract_info.y) < (ssize_t) image->rows))
606 {
607 p=GetVirtualPixels(canvas_image,
608 canvas_image->extract_info.x,0,canvas_image->columns,1,
609 exception);
610 q=GetAuthenticPixels(image,0,y-image->extract_info.y,
611 image->columns,1,exception);
612 if ((p == (const Quantum *) NULL) ||
613 (q == (Quantum *) NULL))
614 break;
615 for (x=0; x < (ssize_t) image->columns; x++)
616 {
617 SetPixelAlpha(image,GetPixelAlpha(canvas_image,p),q);
618 p+=GetPixelChannels(canvas_image);
619 q+=GetPixelChannels(image);
620 }
621 if (SyncAuthenticPixels(image,exception) == MagickFalse)
622 break;
623 }
624 stream=ReadBlobStream(image,length,pixels,&count);
625 }
626 if (image->previous == (Image *) NULL)
627 {
628 status=SetImageProgress(image,LoadImageTag,5,6);
629 if (status == MagickFalse)
630 break;
631 }
632 }
633 if (image->previous == (Image *) NULL)
634 {
635 status=SetImageProgress(image,LoadImageTag,6,6);
636 if (status == MagickFalse)
637 break;
638 }
639 break;
640 }
641 case PartitionInterlace:
642 {
643 /*
644 Partition interlacing: BBBBBB..., GGGGGG..., RRRRRR...
645 */
646 AppendImageFormat("B",image->filename);
647 status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
648 if (status == MagickFalse)
649 break;
650 if (DiscardBlobBytes(image,(MagickSizeType) image->offset) == MagickFalse)
651 {
652 status=MagickFalse;
653 ThrowFileException(exception,CorruptImageError,
654 "UnexpectedEndOfFile",image->filename);
655 break;
656 }
657 length=GetQuantumExtent(canvas_image,quantum_info,BlueQuantum);
658 for (i=0; i < (ssize_t) scene; i++)
659 {
660 for (y=0; y < (ssize_t) image->extract_info.height; y++)
661 {
662 stream=ReadBlobStream(image,length,pixels,&count);
663 if (count != (ssize_t) length)
664 break;
665 }
666 if (count != (ssize_t) length)
667 break;
668 }
669 stream=ReadBlobStream(image,length,pixels,&count);
670 for (y=0; y < (ssize_t) image->extract_info.height; y++)
671 {
672 const Quantum
673 *magick_restrict p;
674
675 Quantum
676 *magick_restrict q;
677
678 ssize_t
679 x;
680
681 if (count != (ssize_t) length)
682 {
683 status=MagickFalse;
684 ThrowFileException(exception,CorruptImageError,
685 "UnexpectedEndOfFile",image->filename);
686 break;
687 }
688 q=GetAuthenticPixels(canvas_image,0,0,canvas_image->columns,1,
689 exception);
690 if (q == (Quantum *) NULL)
691 break;
692 length=ImportQuantumPixels(canvas_image,(CacheView *) NULL,
693 quantum_info,BlueQuantum,(unsigned char *) stream,exception);
694 if (SyncAuthenticPixels(canvas_image,exception) == MagickFalse)
695 break;
696 if (((y-image->extract_info.y) >= 0) &&
697 ((y-image->extract_info.y) < (ssize_t) image->rows))
698 {
699 p=GetVirtualPixels(canvas_image,canvas_image->extract_info.x,0,
700 canvas_image->columns,1,exception);
701 q=GetAuthenticPixels(image,0,y-image->extract_info.y,
702 image->columns,1,exception);
703 if ((p == (const Quantum *) NULL) ||
704 (q == (Quantum *) NULL))
705 break;
706 for (x=0; x < (ssize_t) image->columns; x++)
707 {
708 SetPixelRed(image,GetPixelRed(canvas_image,p),q);
709 p+=GetPixelChannels(canvas_image);
710 q+=GetPixelChannels(image);
711 }
712 if (SyncAuthenticPixels(image,exception) == MagickFalse)
713 break;
714 }
715 stream=ReadBlobStream(image,length,pixels,&count);
716 }
717 if (image->previous == (Image *) NULL)
718 {
719 status=SetImageProgress(image,LoadImageTag,1,5);
720 if (status == MagickFalse)
721 break;
722 }
723 (void) CloseBlob(image);
724 AppendImageFormat("G",image->filename);
725 status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
726 if (status == MagickFalse)
727 break;
728 length=GetQuantumExtent(canvas_image,quantum_info,GreenQuantum);
729 for (i=0; i < (ssize_t) scene; i++)
730 {
731 for (y=0; y < (ssize_t) image->extract_info.height; y++)
732 {
733 stream=ReadBlobStream(image,length,pixels,&count);
734 if (count != (ssize_t) length)
735 break;
736 }
737 if (count != (ssize_t) length)
738 break;
739 }
740 stream=ReadBlobStream(image,length,pixels,&count);
741 for (y=0; y < (ssize_t) image->extract_info.height; y++)
742 {
743 const Quantum
744 *magick_restrict p;
745
746 Quantum
747 *magick_restrict q;
748
749 ssize_t
750 x;
751
752 if (count != (ssize_t) length)
753 {
754 status=MagickFalse;
755 ThrowFileException(exception,CorruptImageError,
756 "UnexpectedEndOfFile",image->filename);
757 break;
758 }
759 q=GetAuthenticPixels(canvas_image,0,0,canvas_image->columns,1,
760 exception);
761 if (q == (Quantum *) NULL)
762 break;
763 length=ImportQuantumPixels(canvas_image,(CacheView *) NULL,
764 quantum_info,GreenQuantum,(unsigned char *) stream,exception);
765 if (SyncAuthenticPixels(canvas_image,exception) == MagickFalse)
766 break;
767 if (((y-image->extract_info.y) >= 0) &&
768 ((y-image->extract_info.y) < (ssize_t) image->rows))
769 {
770 p=GetVirtualPixels(canvas_image,canvas_image->extract_info.x,0,
771 canvas_image->columns,1,exception);
772 q=GetAuthenticPixels(image,0,y-image->extract_info.y,
773 image->columns,1,exception);
774 if ((p == (const Quantum *) NULL) ||
775 (q == (Quantum *) NULL))
776 break;
777 for (x=0; x < (ssize_t) image->columns; x++)
778 {
779 SetPixelGreen(image,GetPixelGreen(canvas_image,p),q);
780 p+=GetPixelChannels(canvas_image);
781 q+=GetPixelChannels(image);
782 }
783 if (SyncAuthenticPixels(image,exception) == MagickFalse)
784 break;
785 }
786 stream=ReadBlobStream(image,length,pixels,&count);
787 }
788 if (image->previous == (Image *) NULL)
789 {
790 status=SetImageProgress(image,LoadImageTag,2,5);
791 if (status == MagickFalse)
792 break;
793 }
794 (void) CloseBlob(image);
795 AppendImageFormat("R",image->filename);
796 status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
797 if (status == MagickFalse)
798 break;
799 length=GetQuantumExtent(canvas_image,quantum_info,RedQuantum);
800 for (i=0; i < (ssize_t) scene; i++)
801 {
802 for (y=0; y < (ssize_t) image->extract_info.height; y++)
803 {
804 stream=ReadBlobStream(image,length,pixels,&count);
805 if (count != (ssize_t) length)
806 break;
807 }
808 if (count != (ssize_t) length)
809 break;
810 }
811 stream=ReadBlobStream(image,length,pixels,&count);
812 for (y=0; y < (ssize_t) image->extract_info.height; y++)
813 {
814 const Quantum
815 *magick_restrict p;
816
817 Quantum
818 *magick_restrict q;
819
820 ssize_t
821 x;
822
823 if (count != (ssize_t) length)
824 {
825 status=MagickFalse;
826 ThrowFileException(exception,CorruptImageError,
827 "UnexpectedEndOfFile",image->filename);
828 break;
829 }
830 q=GetAuthenticPixels(canvas_image,0,0,canvas_image->columns,1,
831 exception);
832 if (q == (Quantum *) NULL)
833 break;
834 length=ImportQuantumPixels(canvas_image,(CacheView *) NULL,
835 quantum_info,RedQuantum,(unsigned char *) stream,exception);
836 if (SyncAuthenticPixels(canvas_image,exception) == MagickFalse)
837 break;
838 if (((y-image->extract_info.y) >= 0) &&
839 ((y-image->extract_info.y) < (ssize_t) image->rows))
840 {
841 p=GetVirtualPixels(canvas_image,canvas_image->extract_info.x,0,
842 canvas_image->columns,1,exception);
843 q=GetAuthenticPixels(image,0,y-image->extract_info.y,
844 image->columns,1,exception);
845 if ((p == (const Quantum *) NULL) ||
846 (q == (Quantum *) NULL))
847 break;
848 for (x=0; x < (ssize_t) image->columns; x++)
849 {
850 SetPixelBlue(image,GetPixelBlue(canvas_image,p),q);
851 p+=GetPixelChannels(canvas_image);
852 q+=GetPixelChannels(image);
853 }
854 if (SyncAuthenticPixels(image,exception) == MagickFalse)
855 break;
856 }
857 stream=ReadBlobStream(image,length,pixels,&count);
858 }
859 if (image->previous == (Image *) NULL)
860 {
861 status=SetImageProgress(image,LoadImageTag,3,5);
862 if (status == MagickFalse)
863 break;
864 }
865 if (image->alpha_trait != UndefinedPixelTrait)
866 {
867 (void) CloseBlob(image);
868 AppendImageFormat("A",image->filename);
869 status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
870 if (status == MagickFalse)
871 break;
872 length=GetQuantumExtent(canvas_image,quantum_info,AlphaQuantum);
873 for (i=0; i < (ssize_t) scene; i++)
874 {
875 for (y=0; y < (ssize_t) image->extract_info.height; y++)
876 {
877 stream=ReadBlobStream(image,length,pixels,&count);
878 if (count != (ssize_t) length)
879 break;
880 }
881 if (count != (ssize_t) length)
882 break;
883 }
884 stream=ReadBlobStream(image,length,pixels,&count);
885 for (y=0; y < (ssize_t) image->extract_info.height; y++)
886 {
887 const Quantum
888 *magick_restrict p;
889
890 Quantum
891 *magick_restrict q;
892
893 ssize_t
894 x;
895
896 if (count != (ssize_t) length)
897 {
898 status=MagickFalse;
899 ThrowFileException(exception,CorruptImageError,
900 "UnexpectedEndOfFile",image->filename);
901 break;
902 }
903 q=GetAuthenticPixels(canvas_image,0,0,canvas_image->columns,1,
904 exception);
905 if (q == (Quantum *) NULL)
906 break;
907 length=ImportQuantumPixels(canvas_image,(CacheView *) NULL,
908 quantum_info,BlueQuantum,(unsigned char *) stream,exception);
909 if (SyncAuthenticPixels(canvas_image,exception) == MagickFalse)
910 break;
911 if (((y-image->extract_info.y) >= 0) &&
912 ((y-image->extract_info.y) < (ssize_t) image->rows))
913 {
914 p=GetVirtualPixels(canvas_image,canvas_image->extract_info.x,
915 0,canvas_image->columns,1,exception);
916 q=GetAuthenticPixels(image,0,y-image->extract_info.y,
917 image->columns,1,exception);
918 if ((p == (const Quantum *) NULL) ||
919 (q == (Quantum *) NULL))
920 break;
921 for (x=0; x < (ssize_t) image->columns; x++)
922 {
923 SetPixelAlpha(image,GetPixelAlpha(canvas_image,p),q);
924 p+=GetPixelChannels(canvas_image);
925 q+=GetPixelChannels(image);
926 }
927 if (SyncAuthenticPixels(image,exception) == MagickFalse)
928 break;
929 }
930 stream=ReadBlobStream(image,length,pixels,&count);
931 }
932 if (image->previous == (Image *) NULL)
933 {
934 status=SetImageProgress(image,LoadImageTag,4,5);
935 if (status == MagickFalse)
936 break;
937 }
938 }
939 (void) CloseBlob(image);
940 if (image->previous == (Image *) NULL)
941 {
942 status=SetImageProgress(image,LoadImageTag,5,5);
943 if (status == MagickFalse)
944 break;
945 }
946 break;
947 }
948 }
949 if (status == MagickFalse)
950 break;
951 SetQuantumImageType(image,quantum_type);
952 /*
953 Proceed to next image.
954 */
955 if (image_info->number_scenes != 0)
956 if (image->scene >= (image_info->scene+image_info->number_scenes-1))
957 break;
958 if (count == (ssize_t) length)
959 {
960 /*
961 Allocate next image structure.
962 */
963 AcquireNextImage(image_info,image,exception);
964 if (GetNextImageInList(image) == (Image *) NULL)
965 {
966 status=MagickFalse;
967 break;
968 }
969 image=SyncNextImageInList(image);
970 status=SetImageProgress(image,LoadImagesTag,TellBlob(image),
971 GetBlobSize(image));
972 if (status == MagickFalse)
973 break;
974 }
975 scene++;
976 } while (count == (ssize_t) length);
977 quantum_info=DestroyQuantumInfo(quantum_info);
978 canvas_image=DestroyImage(canvas_image);
979 (void) CloseBlob(image);
980 if (status == MagickFalse)
981 return(DestroyImageList(image));
982 return(GetFirstImageInList(image));
983 }
984
985 /*
986 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
987 % %
988 % %
989 % %
990 % R e g i s t e r B G R I m a g e %
991 % %
992 % %
993 % %
994 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
995 %
996 % RegisterBGRImage() adds attributes for the BGR image format to
997 % the list of supported formats. The attributes include the image format
998 % tag, a method to read and/or write the format, whether the format
999 % supports the saving of more than one frame to the same file or blob,
1000 % whether the format supports native in-memory I/O, and a brief
1001 % description of the format.
1002 %
1003 % The format of the RegisterBGRImage method is:
1004 %
1005 % size_t RegisterBGRImage(void)
1006 %
1007 */
RegisterBGRImage(void)1008 ModuleExport size_t RegisterBGRImage(void)
1009 {
1010 MagickInfo
1011 *entry;
1012
1013 entry=AcquireMagickInfo("BGR","BGR","Raw blue, green, and red samples");
1014 entry->decoder=(DecodeImageHandler *) ReadBGRImage;
1015 entry->encoder=(EncodeImageHandler *) WriteBGRImage;
1016 entry->flags|=CoderRawSupportFlag;
1017 entry->flags|=CoderEndianSupportFlag;
1018 (void) RegisterMagickInfo(entry);
1019 entry=AcquireMagickInfo("BGR","BGRA",
1020 "Raw blue, green, red, and alpha samples");
1021 entry->decoder=(DecodeImageHandler *) ReadBGRImage;
1022 entry->encoder=(EncodeImageHandler *) WriteBGRImage;
1023 entry->flags|=CoderRawSupportFlag;
1024 entry->flags|=CoderEndianSupportFlag;
1025 (void) RegisterMagickInfo(entry);
1026 entry=AcquireMagickInfo("BGR","BGRO",
1027 "Raw blue, green, red, and opacity samples");
1028 entry->decoder=(DecodeImageHandler *) ReadBGRImage;
1029 entry->encoder=(EncodeImageHandler *) WriteBGRImage;
1030 entry->flags|=CoderRawSupportFlag;
1031 entry->flags|=CoderEndianSupportFlag;
1032 (void) RegisterMagickInfo(entry);
1033 return(MagickImageCoderSignature);
1034 }
1035
1036 /*
1037 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1038 % %
1039 % %
1040 % %
1041 % U n r e g i s t e r B G R I m a g e %
1042 % %
1043 % %
1044 % %
1045 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1046 %
1047 % UnregisterBGRImage() removes format registrations made by the BGR module
1048 % from the list of supported formats.
1049 %
1050 % The format of the UnregisterBGRImage method is:
1051 %
1052 % UnregisterBGRImage(void)
1053 %
1054 */
UnregisterBGRImage(void)1055 ModuleExport void UnregisterBGRImage(void)
1056 {
1057 (void) UnregisterMagickInfo("BGRA");
1058 (void) UnregisterMagickInfo("BGR");
1059 }
1060
1061 /*
1062 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1063 % %
1064 % %
1065 % %
1066 % W r i t e B G R I m a g e %
1067 % %
1068 % %
1069 % %
1070 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1071 %
1072 % WriteBGRImage() writes an image to a file in the BGR or BGRA
1073 % rasterfile format.
1074 %
1075 % The format of the WriteBGRImage method is:
1076 %
1077 % MagickBooleanType WriteBGRImage(const ImageInfo *image_info,
1078 % Image *image,ExceptionInfo *exception)
1079 %
1080 % A description of each parameter follows.
1081 %
1082 % o image_info: the image info.
1083 %
1084 % o image: The image.
1085 %
1086 % o exception: return any errors or warnings in this structure.
1087 %
1088 */
WriteBGRImage(const ImageInfo * image_info,Image * image,ExceptionInfo * exception)1089 static MagickBooleanType WriteBGRImage(const ImageInfo *image_info,Image *image,
1090 ExceptionInfo *exception)
1091 {
1092 MagickBooleanType
1093 status;
1094
1095 MagickOffsetType
1096 scene;
1097
1098 QuantumInfo
1099 *quantum_info;
1100
1101 QuantumType
1102 quantum_type;
1103
1104 size_t
1105 length;
1106
1107 size_t
1108 imageListLength;
1109
1110 ssize_t
1111 count,
1112 y;
1113
1114 unsigned char
1115 *pixels;
1116
1117 /*
1118 Allocate memory for pixels.
1119 */
1120 assert(image_info != (const ImageInfo *) NULL);
1121 assert(image_info->signature == MagickCoreSignature);
1122 assert(image != (Image *) NULL);
1123 assert(image->signature == MagickCoreSignature);
1124 if (image->debug != MagickFalse)
1125 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1126 if (image_info->interlace != PartitionInterlace)
1127 {
1128 /*
1129 Open output image file.
1130 */
1131 assert(exception != (ExceptionInfo *) NULL);
1132 assert(exception->signature == MagickCoreSignature);
1133 status=OpenBlob(image_info,image,WriteBinaryBlobMode,exception);
1134 if (status == MagickFalse)
1135 return(status);
1136 }
1137 quantum_type=BGRQuantum;
1138 if (LocaleCompare(image_info->magick,"BGRA") == 0)
1139 {
1140 quantum_type=BGRAQuantum;
1141 image->alpha_trait=BlendPixelTrait;
1142 }
1143 scene=0;
1144 imageListLength=GetImageListLength(image);
1145 do
1146 {
1147 /*
1148 Convert MIFF to BGR raster pixels.
1149 */
1150 (void) TransformImageColorspace(image,sRGBColorspace,exception);
1151 if ((LocaleCompare(image_info->magick,"BGRA") == 0) &&
1152 (image->alpha_trait == UndefinedPixelTrait))
1153 (void) SetImageAlphaChannel(image,OpaqueAlphaChannel,exception);
1154 quantum_info=AcquireQuantumInfo(image_info,image);
1155 if (quantum_info == (QuantumInfo *) NULL)
1156 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
1157 pixels=(unsigned char *) GetQuantumPixels(quantum_info);
1158 switch (image_info->interlace)
1159 {
1160 case NoInterlace:
1161 default:
1162 {
1163 /*
1164 No interlacing: BGRBGRBGRBGRBGRBGR...
1165 */
1166 for (y=0; y < (ssize_t) image->rows; y++)
1167 {
1168 const Quantum
1169 *magick_restrict p;
1170
1171 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
1172 if (p == (const Quantum *) NULL)
1173 break;
1174 length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1175 quantum_type,pixels,exception);
1176 count=WriteBlob(image,length,pixels);
1177 if (count != (ssize_t) length)
1178 break;
1179 if (image->previous == (Image *) NULL)
1180 {
1181 status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
1182 image->rows);
1183 if (status == MagickFalse)
1184 break;
1185 }
1186 }
1187 break;
1188 }
1189 case LineInterlace:
1190 {
1191 /*
1192 Line interlacing: BBB...GGG...RRR...RRR...GGG...BBB...
1193 */
1194 for (y=0; y < (ssize_t) image->rows; y++)
1195 {
1196 const Quantum
1197 *magick_restrict p;
1198
1199 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
1200 if (p == (const Quantum *) NULL)
1201 break;
1202 length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1203 BlueQuantum,pixels,exception);
1204 count=WriteBlob(image,length,pixels);
1205 if (count != (ssize_t) length)
1206 break;
1207 length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1208 GreenQuantum,pixels,exception);
1209 count=WriteBlob(image,length,pixels);
1210 if (count != (ssize_t) length)
1211 break;
1212 length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1213 RedQuantum,pixels,exception);
1214 count=WriteBlob(image,length,pixels);
1215 if (count != (ssize_t) length)
1216 break;
1217 if (quantum_type == BGRAQuantum)
1218 {
1219 length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1220 AlphaQuantum,pixels,exception);
1221 count=WriteBlob(image,length,pixels);
1222 if (count != (ssize_t) length)
1223 break;
1224 }
1225 if (image->previous == (Image *) NULL)
1226 {
1227 status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
1228 image->rows);
1229 if (status == MagickFalse)
1230 break;
1231 }
1232 }
1233 break;
1234 }
1235 case PlaneInterlace:
1236 {
1237 /*
1238 Plane interlacing: RRRRRR...GGGGGG...BBBBBB...
1239 */
1240 for (y=0; y < (ssize_t) image->rows; y++)
1241 {
1242 const Quantum
1243 *magick_restrict p;
1244
1245 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
1246 if (p == (const Quantum *) NULL)
1247 break;
1248 length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1249 RedQuantum,pixels,exception);
1250 count=WriteBlob(image,length,pixels);
1251 if (count != (ssize_t) length)
1252 break;
1253 }
1254 if (image->previous == (Image *) NULL)
1255 {
1256 status=SetImageProgress(image,SaveImageTag,1,6);
1257 if (status == MagickFalse)
1258 break;
1259 }
1260 for (y=0; y < (ssize_t) image->rows; y++)
1261 {
1262 const Quantum
1263 *magick_restrict p;
1264
1265 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
1266 if (p == (const Quantum *) NULL)
1267 break;
1268 length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1269 GreenQuantum,pixels,exception);
1270 count=WriteBlob(image,length,pixels);
1271 if (count != (ssize_t) length)
1272 break;
1273 }
1274 if (image->previous == (Image *) NULL)
1275 {
1276 status=SetImageProgress(image,SaveImageTag,2,6);
1277 if (status == MagickFalse)
1278 break;
1279 }
1280 for (y=0; y < (ssize_t) image->rows; y++)
1281 {
1282 const Quantum
1283 *magick_restrict p;
1284
1285 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
1286 if (p == (const Quantum *) NULL)
1287 break;
1288 length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1289 BlueQuantum,pixels,exception);
1290 count=WriteBlob(image,length,pixels);
1291 if (count != (ssize_t) length)
1292 break;
1293 }
1294 if (image->previous == (Image *) NULL)
1295 {
1296 status=SetImageProgress(image,SaveImageTag,3,6);
1297 if (status == MagickFalse)
1298 break;
1299 }
1300 if (quantum_type == BGRAQuantum)
1301 {
1302 for (y=0; y < (ssize_t) image->rows; y++)
1303 {
1304 const Quantum
1305 *magick_restrict p;
1306
1307 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
1308 if (p == (const Quantum *) NULL)
1309 break;
1310 length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1311 AlphaQuantum,pixels,exception);
1312 count=WriteBlob(image,length,pixels);
1313 if (count != (ssize_t) length)
1314 break;
1315 }
1316 if (image->previous == (Image *) NULL)
1317 {
1318 status=SetImageProgress(image,SaveImageTag,5,6);
1319 if (status == MagickFalse)
1320 break;
1321 }
1322 }
1323 if (image_info->interlace == PartitionInterlace)
1324 (void) CopyMagickString(image->filename,image_info->filename,
1325 MagickPathExtent);
1326 if (image->previous == (Image *) NULL)
1327 {
1328 status=SetImageProgress(image,SaveImageTag,6,6);
1329 if (status == MagickFalse)
1330 break;
1331 }
1332 break;
1333 }
1334 case PartitionInterlace:
1335 {
1336 /*
1337 Partition interlacing: BBBBBB..., GGGGGG..., RRRRRR...
1338 */
1339 AppendImageFormat("B",image->filename);
1340 status=OpenBlob(image_info,image,scene == 0 ? WriteBinaryBlobMode :
1341 AppendBinaryBlobMode,exception);
1342 if (status == MagickFalse)
1343 return(status);
1344 for (y=0; y < (ssize_t) image->rows; y++)
1345 {
1346 const Quantum
1347 *magick_restrict p;
1348
1349 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
1350 if (p == (const Quantum *) NULL)
1351 break;
1352 length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1353 BlueQuantum,pixels,exception);
1354 count=WriteBlob(image,length,pixels);
1355 if (count != (ssize_t) length)
1356 break;
1357 }
1358 if (image->previous == (Image *) NULL)
1359 {
1360 status=SetImageProgress(image,SaveImageTag,1,6);
1361 if (status == MagickFalse)
1362 break;
1363 }
1364 (void) CloseBlob(image);
1365 AppendImageFormat("G",image->filename);
1366 status=OpenBlob(image_info,image,scene == 0 ? WriteBinaryBlobMode :
1367 AppendBinaryBlobMode,exception);
1368 if (status == MagickFalse)
1369 return(status);
1370 for (y=0; y < (ssize_t) image->rows; y++)
1371 {
1372 const Quantum
1373 *magick_restrict p;
1374
1375 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
1376 if (p == (const Quantum *) NULL)
1377 break;
1378 length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1379 GreenQuantum,pixels,exception);
1380 count=WriteBlob(image,length,pixels);
1381 if (count != (ssize_t) length)
1382 break;
1383 }
1384 if (image->previous == (Image *) NULL)
1385 {
1386 status=SetImageProgress(image,SaveImageTag,2,6);
1387 if (status == MagickFalse)
1388 break;
1389 }
1390 (void) CloseBlob(image);
1391 AppendImageFormat("R",image->filename);
1392 status=OpenBlob(image_info,image,scene == 0 ? WriteBinaryBlobMode :
1393 AppendBinaryBlobMode,exception);
1394 if (status == MagickFalse)
1395 return(status);
1396 for (y=0; y < (ssize_t) image->rows; y++)
1397 {
1398 const Quantum
1399 *magick_restrict p;
1400
1401 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
1402 if (p == (const Quantum *) NULL)
1403 break;
1404 length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1405 RedQuantum,pixels,exception);
1406 count=WriteBlob(image,length,pixels);
1407 if (count != (ssize_t) length)
1408 break;
1409 }
1410 if (image->previous == (Image *) NULL)
1411 {
1412 status=SetImageProgress(image,SaveImageTag,3,6);
1413 if (status == MagickFalse)
1414 break;
1415 }
1416 (void) CloseBlob(image);
1417 if (quantum_type == BGRAQuantum)
1418 {
1419 (void) CloseBlob(image);
1420 AppendImageFormat("A",image->filename);
1421 status=OpenBlob(image_info,image,scene == 0 ? WriteBinaryBlobMode :
1422 AppendBinaryBlobMode,exception);
1423 if (status == MagickFalse)
1424 return(status);
1425 for (y=0; y < (ssize_t) image->rows; y++)
1426 {
1427 const Quantum
1428 *magick_restrict p;
1429
1430 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
1431 if (p == (const Quantum *) NULL)
1432 break;
1433 length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1434 AlphaQuantum,pixels,exception);
1435 count=WriteBlob(image,length,pixels);
1436 if (count != (ssize_t) length)
1437 break;
1438 }
1439 if (image->previous == (Image *) NULL)
1440 {
1441 status=SetImageProgress(image,SaveImageTag,5,6);
1442 if (status == MagickFalse)
1443 break;
1444 }
1445 }
1446 (void) CloseBlob(image);
1447 (void) CopyMagickString(image->filename,image_info->filename,
1448 MagickPathExtent);
1449 if (image->previous == (Image *) NULL)
1450 {
1451 status=SetImageProgress(image,SaveImageTag,6,6);
1452 if (status == MagickFalse)
1453 break;
1454 }
1455 break;
1456 }
1457 }
1458 quantum_info=DestroyQuantumInfo(quantum_info);
1459 if (GetNextImageInList(image) == (Image *) NULL)
1460 break;
1461 image=SyncNextImageInList(image);
1462 status=SetImageProgress(image,SaveImagesTag,scene++,imageListLength);
1463 if (status == MagickFalse)
1464 break;
1465 } while (image_info->adjoin != MagickFalse);
1466 (void) CloseBlob(image);
1467 return(MagickTrue);
1468 }
1469