1 /*
2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3 % %
4 % %
5 % %
6 % RRRR GGGG BBBB %
7 % R R G B B %
8 % RRRR G GG BBBB %
9 % R R G G B B %
10 % R R GGG BBBB %
11 % %
12 % %
13 % Read/Write Raw RGB Image Format %
14 % %
15 % Software Design %
16 % Cristy %
17 % July 1992 %
18 % %
19 % %
20 % Copyright 1999-2020 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 WriteRGBImage(const ImageInfo *,Image *,ExceptionInfo *);
72
73 /*
74 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
75 % %
76 % %
77 % %
78 % R e a d R G B I m a g e %
79 % %
80 % %
81 % %
82 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
83 %
84 % ReadRGBImage() reads an image of raw RGB, RGBA, or RGBO 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 ReadRGBImage method is:
89 %
90 % Image *ReadRGBImage(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 */
ReadRGBImage(const ImageInfo * image_info,ExceptionInfo * exception)100 static Image *ReadRGBImage(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 register 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,(MagickSizeType) 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=RGBQuantum;
175 if (LocaleCompare(image_info->magick,"RGBA") == 0)
176 {
177 quantum_type=RGBAQuantum;
178 image->alpha_trait=BlendPixelTrait;
179 canvas_image->alpha_trait=BlendPixelTrait;
180 }
181 if (LocaleCompare(image_info->magick,"RGBO") == 0)
182 {
183 quantum_type=RGBOQuantum;
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: RGBRGBRGBRGBRGBRGB...
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 register const Quantum
235 *magick_restrict p;
236
237 register Quantum
238 *magick_restrict q;
239
240 register 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) || (q == (Quantum *) NULL))
266 break;
267 for (x=0; x < (ssize_t) image->columns; x++)
268 {
269 SetPixelRed(image,GetPixelRed(canvas_image,p),q);
270 SetPixelGreen(image,GetPixelGreen(canvas_image,p),q);
271 SetPixelBlue(image,GetPixelBlue(canvas_image,p),q);
272 SetPixelAlpha(image,OpaqueAlpha,q);
273 if (image->alpha_trait != UndefinedPixelTrait)
274 SetPixelAlpha(image,GetPixelAlpha(canvas_image,p),q);
275 p+=GetPixelChannels(canvas_image);
276 q+=GetPixelChannels(image);
277 }
278 if (SyncAuthenticPixels(image,exception) == MagickFalse)
279 break;
280 }
281 if (image->previous == (Image *) NULL)
282 {
283 status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y,
284 image->rows);
285 if (status == MagickFalse)
286 break;
287 }
288 stream=ReadBlobStream(image,length,pixels,&count);
289 }
290 break;
291 }
292 case LineInterlace:
293 {
294 static QuantumType
295 quantum_types[4] =
296 {
297 RedQuantum,
298 GreenQuantum,
299 BlueQuantum,
300 AlphaQuantum
301 };
302
303 /*
304 Line interlacing: RRR...GGG...BBB...RRR...GGG...BBB...
305 */
306 if (LocaleCompare(image_info->magick,"RGBO") == 0)
307 quantum_types[3]=OpacityQuantum;
308 if (scene == 0)
309 {
310 length=GetQuantumExtent(canvas_image,quantum_info,RedQuantum);
311 stream=ReadBlobStream(image,length,pixels,&count);
312 }
313 for (y=0; y < (ssize_t) image->extract_info.height; y++)
314 {
315 for (i=0; i < (ssize_t) (image->alpha_trait != UndefinedPixelTrait ? 4 : 3); i++)
316 {
317 register const Quantum
318 *magick_restrict p;
319
320 register Quantum
321 *magick_restrict q;
322
323 register ssize_t
324 x;
325
326 if (count != (ssize_t) length)
327 {
328 status=MagickFalse;
329 ThrowFileException(exception,CorruptImageError,
330 "UnexpectedEndOfFile",image->filename);
331 break;
332 }
333 quantum_type=quantum_types[i];
334 q=GetAuthenticPixels(canvas_image,0,0,canvas_image->columns,1,
335 exception);
336 if (q == (Quantum *) NULL)
337 break;
338 length=ImportQuantumPixels(canvas_image,(CacheView *) NULL,
339 quantum_info,quantum_type,(unsigned char *) stream,exception);
340 if (SyncAuthenticPixels(canvas_image,exception) == MagickFalse)
341 break;
342 if (((y-image->extract_info.y) >= 0) &&
343 ((y-image->extract_info.y) < (ssize_t) image->rows))
344 {
345 p=GetVirtualPixels(canvas_image,canvas_image->extract_info.x,
346 0,canvas_image->columns,1,exception);
347 q=GetAuthenticPixels(image,0,y-image->extract_info.y,
348 image->columns,1,exception);
349 if ((p == (const Quantum *) NULL) || (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 SetPixelOpacity(image,GetPixelOpacity(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 register const Quantum
414 *magick_restrict p;
415
416 register Quantum
417 *magick_restrict q;
418
419 register 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) || (q == (Quantum *) NULL))
445 break;
446 for (x=0; x < (ssize_t) image->columns; x++)
447 {
448 SetPixelRed(image,GetPixelRed(canvas_image,p),q);
449 p+=GetPixelChannels(canvas_image);
450 q+=GetPixelChannels(image);
451 }
452 if (SyncAuthenticPixels(image,exception) == MagickFalse)
453 break;
454 }
455 stream=ReadBlobStream(image,length,pixels,&count);
456 }
457 if (image->previous == (Image *) NULL)
458 {
459 status=SetImageProgress(image,LoadImageTag,1,6);
460 if (status == MagickFalse)
461 break;
462 }
463 for (y=0; y < (ssize_t) image->extract_info.height; y++)
464 {
465 register const Quantum
466 *magick_restrict p;
467
468 register Quantum
469 *magick_restrict q;
470
471 register ssize_t
472 x;
473
474 if (count != (ssize_t) length)
475 {
476 status=MagickFalse;
477 ThrowFileException(exception,CorruptImageError,
478 "UnexpectedEndOfFile",image->filename);
479 break;
480 }
481 q=GetAuthenticPixels(canvas_image,0,0,canvas_image->columns,1,
482 exception);
483 if (q == (Quantum *) NULL)
484 break;
485 length=ImportQuantumPixels(canvas_image,(CacheView *) NULL,
486 quantum_info,GreenQuantum,(unsigned char *) stream,exception);
487 if (SyncAuthenticPixels(canvas_image,exception) == MagickFalse)
488 break;
489 if (((y-image->extract_info.y) >= 0) &&
490 ((y-image->extract_info.y) < (ssize_t) image->rows))
491 {
492 p=GetVirtualPixels(canvas_image,canvas_image->extract_info.x,0,
493 canvas_image->columns,1,exception);
494 q=GetAuthenticPixels(image,0,y-image->extract_info.y,
495 image->columns,1,exception);
496 if ((p == (const Quantum *) NULL) || (q == (Quantum *) NULL))
497 break;
498 for (x=0; x < (ssize_t) image->columns; x++)
499 {
500 SetPixelGreen(image,GetPixelGreen(canvas_image,p),q);
501 p+=GetPixelChannels(canvas_image);
502 q+=GetPixelChannels(image);
503 }
504 if (SyncAuthenticPixels(image,exception) == MagickFalse)
505 break;
506 }
507 stream=ReadBlobStream(image,length,pixels,&count);
508 }
509 if (image->previous == (Image *) NULL)
510 {
511 status=SetImageProgress(image,LoadImageTag,2,6);
512 if (status == MagickFalse)
513 break;
514 }
515 for (y=0; y < (ssize_t) image->extract_info.height; y++)
516 {
517 register const Quantum
518 *magick_restrict p;
519
520 register Quantum
521 *magick_restrict q;
522
523 register ssize_t
524 x;
525
526 if (count != (ssize_t) length)
527 {
528 status=MagickFalse;
529 ThrowFileException(exception,CorruptImageError,
530 "UnexpectedEndOfFile",image->filename);
531 break;
532 }
533 q=GetAuthenticPixels(canvas_image,0,0,canvas_image->columns,1,
534 exception);
535 if (q == (Quantum *) NULL)
536 break;
537 length=ImportQuantumPixels(canvas_image,(CacheView *) NULL,
538 quantum_info,BlueQuantum,(unsigned char *) stream,exception);
539 if (SyncAuthenticPixels(canvas_image,exception) == MagickFalse)
540 break;
541 if (((y-image->extract_info.y) >= 0) &&
542 ((y-image->extract_info.y) < (ssize_t) image->rows))
543 {
544 p=GetVirtualPixels(canvas_image,canvas_image->extract_info.x,0,
545 canvas_image->columns,1,exception);
546 q=GetAuthenticPixels(image,0,y-image->extract_info.y,
547 image->columns,1,exception);
548 if ((p == (const Quantum *) NULL) || (q == (Quantum *) NULL))
549 break;
550 for (x=0; x < (ssize_t) image->columns; x++)
551 {
552 SetPixelBlue(image,GetPixelBlue(canvas_image,p),q);
553 p+=GetPixelChannels(canvas_image);
554 q+=GetPixelChannels(image);
555 }
556 if (SyncAuthenticPixels(image,exception) == MagickFalse)
557 break;
558 }
559 stream=ReadBlobStream(image,length,pixels,&count);
560 }
561 if (image->previous == (Image *) NULL)
562 {
563 status=SetImageProgress(image,LoadImageTag,4,6);
564 if (status == MagickFalse)
565 break;
566 }
567 if (image->alpha_trait != UndefinedPixelTrait)
568 {
569 for (y=0; y < (ssize_t) image->extract_info.height; y++)
570 {
571 register const Quantum
572 *magick_restrict p;
573
574 register Quantum
575 *magick_restrict q;
576
577 register ssize_t
578 x;
579
580 if (count != (ssize_t) length)
581 {
582 status=MagickFalse;
583 ThrowFileException(exception,CorruptImageError,
584 "UnexpectedEndOfFile",image->filename);
585 break;
586 }
587 q=GetAuthenticPixels(canvas_image,0,0,canvas_image->columns,1,
588 exception);
589 if (q == (Quantum *) NULL)
590 break;
591 length=ImportQuantumPixels(canvas_image,(CacheView *) NULL,
592 quantum_info,AlphaQuantum,(unsigned char *) stream,exception);
593 if (SyncAuthenticPixels(canvas_image,exception) == MagickFalse)
594 break;
595 if (((y-image->extract_info.y) >= 0) &&
596 ((y-image->extract_info.y) < (ssize_t) image->rows))
597 {
598 p=GetVirtualPixels(canvas_image,
599 canvas_image->extract_info.x,0,canvas_image->columns,1,
600 exception);
601 q=GetAuthenticPixels(image,0,y-image->extract_info.y,
602 image->columns,1,exception);
603 if ((p == (const Quantum *) NULL) || (q == (Quantum *) NULL))
604 break;
605 for (x=0; x < (ssize_t) image->columns; x++)
606 {
607 SetPixelAlpha(image,GetPixelAlpha(canvas_image,p),q);
608 p+=GetPixelChannels(canvas_image);
609 q+=GetPixelChannels(image);
610 }
611 if (SyncAuthenticPixels(image,exception) == MagickFalse)
612 break;
613 }
614 stream=ReadBlobStream(image,length,pixels,&count);
615 }
616 if (image->previous == (Image *) NULL)
617 {
618 status=SetImageProgress(image,LoadImageTag,5,6);
619 if (status == MagickFalse)
620 break;
621 }
622 }
623 if (image->previous == (Image *) NULL)
624 {
625 status=SetImageProgress(image,LoadImageTag,6,6);
626 if (status == MagickFalse)
627 break;
628 }
629 break;
630 }
631 case PartitionInterlace:
632 {
633 /*
634 Partition interlacing: RRRRRR..., GGGGGG..., BBBBBB...
635 */
636 AppendImageFormat("R",image->filename);
637 status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
638 if (status == MagickFalse)
639 break;
640 if (DiscardBlobBytes(image,(MagickSizeType) image->offset) == MagickFalse)
641 {
642 status=MagickFalse;
643 ThrowFileException(exception,CorruptImageError,
644 "UnexpectedEndOfFile",image->filename);
645 break;
646 }
647 length=GetQuantumExtent(canvas_image,quantum_info,RedQuantum);
648 for (i=0; i < (ssize_t) scene; i++)
649 {
650 for (y=0; y < (ssize_t) image->extract_info.height; y++)
651 {
652 stream=ReadBlobStream(image,length,pixels,&count);
653 if (count != (ssize_t) length)
654 break;
655 }
656 if (count != (ssize_t) length)
657 break;
658 }
659 stream=ReadBlobStream(image,length,pixels,&count);
660 for (y=0; y < (ssize_t) image->extract_info.height; y++)
661 {
662 register const Quantum
663 *magick_restrict p;
664
665 register Quantum
666 *magick_restrict q;
667
668 register ssize_t
669 x;
670
671 if (count != (ssize_t) length)
672 {
673 status=MagickFalse;
674 ThrowFileException(exception,CorruptImageError,
675 "UnexpectedEndOfFile",image->filename);
676 break;
677 }
678 q=GetAuthenticPixels(canvas_image,0,0,canvas_image->columns,1,
679 exception);
680 if (q == (Quantum *) NULL)
681 break;
682 length=ImportQuantumPixels(canvas_image,(CacheView *) NULL,
683 quantum_info,RedQuantum,(unsigned char *) stream,exception);
684 if (SyncAuthenticPixels(canvas_image,exception) == MagickFalse)
685 break;
686 if (((y-image->extract_info.y) >= 0) &&
687 ((y-image->extract_info.y) < (ssize_t) image->rows))
688 {
689 p=GetVirtualPixels(canvas_image,canvas_image->extract_info.x,0,
690 canvas_image->columns,1,exception);
691 q=GetAuthenticPixels(image,0,y-image->extract_info.y,
692 image->columns,1,exception);
693 if ((p == (const Quantum *) NULL) || (q == (Quantum *) NULL))
694 break;
695 for (x=0; x < (ssize_t) image->columns; x++)
696 {
697 SetPixelRed(image,GetPixelRed(canvas_image,p),q);
698 p+=GetPixelChannels(canvas_image);
699 q+=GetPixelChannels(image);
700 }
701 if (SyncAuthenticPixels(image,exception) == MagickFalse)
702 break;
703 }
704 stream=ReadBlobStream(image,length,pixels,&count);
705 }
706 if (image->previous == (Image *) NULL)
707 {
708 status=SetImageProgress(image,LoadImageTag,1,5);
709 if (status == MagickFalse)
710 break;
711 }
712 (void) CloseBlob(image);
713 AppendImageFormat("G",image->filename);
714 status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
715 if (status == MagickFalse)
716 break;
717 length=GetQuantumExtent(canvas_image,quantum_info,GreenQuantum);
718 for (i=0; i < (ssize_t) scene; i++)
719 {
720 for (y=0; y < (ssize_t) image->extract_info.height; y++)
721 {
722 stream=ReadBlobStream(image,length,pixels,&count);
723 if (count != (ssize_t) length)
724 break;
725 }
726 if (count != (ssize_t) length)
727 break;
728 }
729 stream=ReadBlobStream(image,length,pixels,&count);
730 for (y=0; y < (ssize_t) image->extract_info.height; y++)
731 {
732 register const Quantum
733 *magick_restrict p;
734
735 register Quantum
736 *magick_restrict q;
737
738 register ssize_t
739 x;
740
741 if (count != (ssize_t) length)
742 {
743 status=MagickFalse;
744 ThrowFileException(exception,CorruptImageError,
745 "UnexpectedEndOfFile",image->filename);
746 break;
747 }
748 q=GetAuthenticPixels(canvas_image,0,0,canvas_image->columns,1,
749 exception);
750 if (q == (Quantum *) NULL)
751 break;
752 length=ImportQuantumPixels(canvas_image,(CacheView *) NULL,
753 quantum_info,GreenQuantum,(unsigned char *) stream,exception);
754 if (SyncAuthenticPixels(canvas_image,exception) == MagickFalse)
755 break;
756 if (((y-image->extract_info.y) >= 0) &&
757 ((y-image->extract_info.y) < (ssize_t) image->rows))
758 {
759 p=GetVirtualPixels(canvas_image,canvas_image->extract_info.x,0,
760 canvas_image->columns,1,exception);
761 q=GetAuthenticPixels(image,0,y-image->extract_info.y,
762 image->columns,1,exception);
763 if ((p == (const Quantum *) NULL) || (q == (Quantum *) NULL))
764 break;
765 for (x=0; x < (ssize_t) image->columns; x++)
766 {
767 SetPixelGreen(image,GetPixelGreen(canvas_image,p),q);
768 p+=GetPixelChannels(canvas_image);
769 q+=GetPixelChannels(image);
770 }
771 if (SyncAuthenticPixels(image,exception) == MagickFalse)
772 break;
773 }
774 stream=ReadBlobStream(image,length,pixels,&count);
775 }
776 if (image->previous == (Image *) NULL)
777 {
778 status=SetImageProgress(image,LoadImageTag,2,5);
779 if (status == MagickFalse)
780 break;
781 }
782 (void) CloseBlob(image);
783 AppendImageFormat("B",image->filename);
784 status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
785 if (status == MagickFalse)
786 break;
787 length=GetQuantumExtent(canvas_image,quantum_info,BlueQuantum);
788 for (i=0; i < (ssize_t) scene; i++)
789 {
790 for (y=0; y < (ssize_t) image->extract_info.height; y++)
791 {
792 stream=ReadBlobStream(image,length,pixels,&count);
793 if (count != (ssize_t) length)
794 break;
795 }
796 if (count != (ssize_t) length)
797 break;
798 }
799 stream=ReadBlobStream(image,length,pixels,&count);
800 for (y=0; y < (ssize_t) image->extract_info.height; y++)
801 {
802 register const Quantum
803 *magick_restrict p;
804
805 register Quantum
806 *magick_restrict q;
807
808 register ssize_t
809 x;
810
811 if (count != (ssize_t) length)
812 {
813 status=MagickFalse;
814 ThrowFileException(exception,CorruptImageError,
815 "UnexpectedEndOfFile",image->filename);
816 break;
817 }
818 q=GetAuthenticPixels(canvas_image,0,0,canvas_image->columns,1,
819 exception);
820 if (q == (Quantum *) NULL)
821 break;
822 length=ImportQuantumPixels(canvas_image,(CacheView *) NULL,
823 quantum_info,BlueQuantum,(unsigned char *) stream,exception);
824 if (SyncAuthenticPixels(canvas_image,exception) == MagickFalse)
825 break;
826 if (((y-image->extract_info.y) >= 0) &&
827 ((y-image->extract_info.y) < (ssize_t) image->rows))
828 {
829 p=GetVirtualPixels(canvas_image,canvas_image->extract_info.x,0,
830 canvas_image->columns,1,exception);
831 q=GetAuthenticPixels(image,0,y-image->extract_info.y,
832 image->columns,1,exception);
833 if ((p == (const Quantum *) NULL) || (q == (Quantum *) NULL))
834 break;
835 for (x=0; x < (ssize_t) image->columns; x++)
836 {
837 SetPixelBlue(image,GetPixelBlue(canvas_image,p),q);
838 p+=GetPixelChannels(canvas_image);
839 q+=GetPixelChannels(image);
840 }
841 if (SyncAuthenticPixels(image,exception) == MagickFalse)
842 break;
843 }
844 stream=ReadBlobStream(image,length,pixels,&count);
845 }
846 if (image->previous == (Image *) NULL)
847 {
848 status=SetImageProgress(image,LoadImageTag,3,5);
849 if (status == MagickFalse)
850 break;
851 }
852 if (image->alpha_trait != UndefinedPixelTrait)
853 {
854 (void) CloseBlob(image);
855 AppendImageFormat("A",image->filename);
856 status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
857 if (status == MagickFalse)
858 break;
859 length=GetQuantumExtent(canvas_image,quantum_info,AlphaQuantum);
860 for (i=0; i < (ssize_t) scene; i++)
861 {
862 for (y=0; y < (ssize_t) image->extract_info.height; y++)
863 {
864 stream=ReadBlobStream(image,length,pixels,&count);
865 if (count != (ssize_t) length)
866 break;
867 }
868 if (count != (ssize_t) length)
869 break;
870 }
871 stream=ReadBlobStream(image,length,pixels,&count);
872 for (y=0; y < (ssize_t) image->extract_info.height; y++)
873 {
874 register const Quantum
875 *magick_restrict p;
876
877 register Quantum
878 *magick_restrict q;
879
880 register ssize_t
881 x;
882
883 if (count != (ssize_t) length)
884 {
885 status=MagickFalse;
886 ThrowFileException(exception,CorruptImageError,
887 "UnexpectedEndOfFile",image->filename);
888 break;
889 }
890 q=GetAuthenticPixels(canvas_image,0,0,canvas_image->columns,1,
891 exception);
892 if (q == (Quantum *) NULL)
893 break;
894 length=ImportQuantumPixels(canvas_image,(CacheView *) NULL,
895 quantum_info,BlueQuantum,(unsigned char *) stream,exception);
896 if (SyncAuthenticPixels(canvas_image,exception) == MagickFalse)
897 break;
898 if (((y-image->extract_info.y) >= 0) &&
899 ((y-image->extract_info.y) < (ssize_t) image->rows))
900 {
901 p=GetVirtualPixels(canvas_image,canvas_image->extract_info.x,
902 0,canvas_image->columns,1,exception);
903 q=GetAuthenticPixels(image,0,y-image->extract_info.y,
904 image->columns,1,exception);
905 if ((p == (const Quantum *) NULL) || (q == (Quantum *) NULL))
906 break;
907 for (x=0; x < (ssize_t) image->columns; x++)
908 {
909 SetPixelAlpha(image,GetPixelAlpha(canvas_image,p),q);
910 p+=GetPixelChannels(canvas_image);
911 q+=GetPixelChannels(image);
912 }
913 if (SyncAuthenticPixels(image,exception) == MagickFalse)
914 break;
915 }
916 stream=ReadBlobStream(image,length,pixels,&count);
917 }
918 if (image->previous == (Image *) NULL)
919 {
920 status=SetImageProgress(image,LoadImageTag,4,5);
921 if (status == MagickFalse)
922 break;
923 }
924 }
925 (void) CloseBlob(image);
926 if (image->previous == (Image *) NULL)
927 {
928 status=SetImageProgress(image,LoadImageTag,5,5);
929 if (status == MagickFalse)
930 break;
931 }
932 break;
933 }
934 }
935 if (status == MagickFalse)
936 break;
937 SetQuantumImageType(image,quantum_type);
938 /*
939 Proceed to next image.
940 */
941 if (image_info->number_scenes != 0)
942 if (image->scene >= (image_info->scene+image_info->number_scenes-1))
943 break;
944 if (count == (ssize_t) length)
945 {
946 /*
947 Allocate next image structure.
948 */
949 AcquireNextImage(image_info,image,exception);
950 if (GetNextImageInList(image) == (Image *) NULL)
951 {
952 status=MagickFalse;
953 break;
954 }
955 image=SyncNextImageInList(image);
956 status=SetImageProgress(image,LoadImagesTag,TellBlob(image),
957 GetBlobSize(image));
958 if (status == MagickFalse)
959 break;
960 }
961 scene++;
962 } while (count == (ssize_t) length);
963 quantum_info=DestroyQuantumInfo(quantum_info);
964 canvas_image=DestroyImage(canvas_image);
965 (void) CloseBlob(image);
966 if (status == MagickFalse)
967 return(DestroyImageList(image));
968 return(GetFirstImageInList(image));
969 }
970
971 /*
972 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
973 % %
974 % %
975 % %
976 % R e a d R G B 5 6 5 I m a g e %
977 % %
978 % %
979 % %
980 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
981 %
982 % ReadGRAYImage() reads an image of raw RGB 5-6-5 samples and returns it. It
983 % allocates the memory necessary for the new Image structure and returns a
984 % pointer to the new image.
985 %
986 % The format of the ReadGRAYImage method is:
987 %
988 % Image *ReadGRAYImage(const ImageInfo *image_info,
989 % ExceptionInfo *exception)
990 %
991 % A description of each parameter follows:
992 %
993 % o image_info: the image info.
994 %
995 % o exception: return any errors or warnings in this structure.
996 %
997 */
ReadRGB565Image(const ImageInfo * image_info,ExceptionInfo * exception)998 static Image *ReadRGB565Image(const ImageInfo *image_info,
999 ExceptionInfo *exception)
1000 {
1001 const void
1002 *stream;
1003
1004 Image
1005 *canvas_image,
1006 *image;
1007
1008 MagickBooleanType
1009 status;
1010
1011 MagickOffsetType
1012 scene;
1013
1014 QuantumInfo
1015 *quantum_info;
1016
1017 QuantumType
1018 quantum_type;
1019
1020 size_t
1021 length;
1022
1023 ssize_t
1024 count,
1025 y;
1026
1027 unsigned char
1028 *pixels;
1029
1030 /*
1031 Open image file.
1032 */
1033 assert(image_info != (const ImageInfo *) NULL);
1034 assert(image_info->signature == MagickCoreSignature);
1035 if (image_info->debug != MagickFalse)
1036 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
1037 image_info->filename);
1038 assert(exception != (ExceptionInfo *) NULL);
1039 assert(exception->signature == MagickCoreSignature);
1040 image=AcquireImage(image_info,exception);
1041 if ((image->columns == 0) || (image->rows == 0))
1042 ThrowReaderException(OptionError,"MustSpecifyImageSize");
1043 image->depth=16;
1044 if (image_info->interlace != PartitionInterlace)
1045 {
1046 status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
1047 if (status == MagickFalse)
1048 {
1049 image=DestroyImageList(image);
1050 return((Image *) NULL);
1051 }
1052 if (DiscardBlobBytes(image,(MagickSizeType) image->offset) == MagickFalse)
1053 ThrowFileException(exception,CorruptImageError,"UnexpectedEndOfFile",
1054 image->filename);
1055 }
1056 /*
1057 Create virtual canvas to support cropping (i.e. image.rgb[100x100+10+20]).
1058 */
1059 canvas_image=CloneImage(image,image->extract_info.width,1,MagickFalse,
1060 exception);
1061 if(canvas_image == (Image *) NULL)
1062 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
1063 (void) SetImageVirtualPixelMethod(canvas_image,BlackVirtualPixelMethod,
1064 exception);
1065 quantum_info=AcquireQuantumInfo(image_info,canvas_image);
1066 if (quantum_info == (QuantumInfo *) NULL)
1067 {
1068 canvas_image=DestroyImage(canvas_image);
1069 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
1070 }
1071 quantum_type=GrayQuantum;
1072 pixels=GetQuantumPixels(quantum_info);
1073 if (image_info->number_scenes != 0)
1074 while (image->scene < image_info->scene)
1075 {
1076 /*
1077 Skip to next image.
1078 */
1079 image->scene++;
1080 length=GetQuantumExtent(canvas_image,quantum_info,quantum_type);
1081 for (y=0; y < (ssize_t) image->rows; y++)
1082 {
1083 stream=ReadBlobStream(image,length,pixels,&count);
1084 if (count != (ssize_t) length)
1085 break;
1086 }
1087 }
1088 count=0;
1089 length=0;
1090 scene=0;
1091 status=MagickTrue;
1092 stream=NULL;
1093 do
1094 {
1095 /*
1096 Read pixels to virtual canvas image then push to image.
1097 */
1098 if ((image_info->ping != MagickFalse) && (image_info->number_scenes != 0))
1099 if (image->scene >= (image_info->scene+image_info->number_scenes-1))
1100 break;
1101 status=SetImageExtent(image,image->columns,image->rows,exception);
1102 if (status == MagickFalse)
1103 break;
1104 /*
1105 No interlacing: GGG...
1106 */
1107 if (scene == 0)
1108 {
1109 length=GetQuantumExtent(canvas_image,quantum_info,quantum_type);
1110 stream=ReadBlobStream(image,length,pixels,&count);
1111 }
1112 for (y=0; y < (ssize_t) image->extract_info.height; y++)
1113 {
1114 register const Quantum
1115 *magick_restrict p;
1116
1117 register Quantum
1118 *magick_restrict q;
1119
1120 register ssize_t
1121 x;
1122
1123 if (count != (ssize_t) length)
1124 {
1125 status=MagickFalse;
1126 ThrowFileException(exception,CorruptImageError,
1127 "UnexpectedEndOfFile",image->filename);
1128 break;
1129 }
1130 q=GetAuthenticPixels(canvas_image,0,0,canvas_image->columns,1,exception);
1131 if (q == (Quantum *) NULL)
1132 break;
1133 length=ImportQuantumPixels(canvas_image,(CacheView *) NULL,
1134 quantum_info,quantum_type,(unsigned char *) stream,exception);
1135 if (SyncAuthenticPixels(canvas_image,exception) == MagickFalse)
1136 break;
1137 if (((y-image->extract_info.y) >= 0) &&
1138 ((y-image->extract_info.y) < (ssize_t) image->rows))
1139 {
1140 p=GetVirtualPixels(canvas_image,canvas_image->extract_info.x,0,
1141 canvas_image->columns,1,exception);
1142 q=QueueAuthenticPixels(image,0,y-image->extract_info.y,
1143 image->columns,1,exception);
1144 if ((p == (const Quantum *) NULL) || (q == (Quantum *) NULL))
1145 break;
1146 for (x=0; x < (ssize_t) image->columns; x++)
1147 {
1148 unsigned short
1149 pixel;
1150
1151 pixel=(unsigned short) ScaleQuantumToShort(GetPixelGray(
1152 canvas_image,p));
1153 SetPixelRed(image,(Quantum) (((pixel >> 11) & 0x1f) << 11),q);
1154 SetPixelGreen(image,(Quantum) (((pixel >> 5) & 0x3f) << 10),q);
1155 SetPixelBlue(image,(Quantum) ((pixel & 0x1f) << 11),q);
1156 p+=GetPixelChannels(canvas_image);
1157 q+=GetPixelChannels(image);
1158 }
1159 if (SyncAuthenticPixels(image,exception) == MagickFalse)
1160 break;
1161 }
1162 if (image->previous == (Image *) NULL)
1163 {
1164 status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y,
1165 image->rows);
1166 if (status == MagickFalse)
1167 break;
1168 }
1169 stream=ReadBlobStream(image,length,pixels,&count);
1170 }
1171 if (status == MagickFalse)
1172 break;
1173 SetQuantumImageType(image,quantum_type);
1174 /*
1175 Proceed to next image.
1176 */
1177 if (image_info->number_scenes != 0)
1178 if (image->scene >= (image_info->scene+image_info->number_scenes-1))
1179 break;
1180 if (count == (ssize_t) length)
1181 {
1182 /*
1183 Allocate next image structure.
1184 */
1185 AcquireNextImage(image_info,image,exception);
1186 if (GetNextImageInList(image) == (Image *) NULL)
1187 {
1188 status=MagickFalse;
1189 break;
1190 }
1191 image=SyncNextImageInList(image);
1192 status=SetImageProgress(image,LoadImagesTag,TellBlob(image),
1193 GetBlobSize(image));
1194 if (status == MagickFalse)
1195 break;
1196 }
1197 scene++;
1198 } while (count == (ssize_t) length);
1199 quantum_info=DestroyQuantumInfo(quantum_info);
1200 canvas_image=DestroyImage(canvas_image);
1201 (void) CloseBlob(image);
1202 if (status == MagickFalse)
1203 return(DestroyImageList(image));
1204 return(GetFirstImageInList(image));
1205 }
1206
1207 /*
1208 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1209 % %
1210 % %
1211 % %
1212 % R e g i s t e r R G B I m a g e %
1213 % %
1214 % %
1215 % %
1216 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1217 %
1218 % RegisterRGBImage() adds attributes for the RGB image format to
1219 % the list of supported formats. The attributes include the image format
1220 % tag, a method to read and/or write the format, whether the format
1221 % supports the saving of more than one frame to the same file or blob,
1222 % whether the format supports native in-memory I/O, and a brief
1223 % description of the format.
1224 %
1225 % The format of the RegisterRGBImage method is:
1226 %
1227 % size_t RegisterRGBImage(void)
1228 %
1229 */
RegisterRGBImage(void)1230 ModuleExport size_t RegisterRGBImage(void)
1231 {
1232 MagickInfo
1233 *entry;
1234
1235 entry=AcquireMagickInfo("RGB","RGB",
1236 "Raw red, green, and blue samples");
1237 entry->decoder=(DecodeImageHandler *) ReadRGBImage;
1238 entry->encoder=(EncodeImageHandler *) WriteRGBImage;
1239 entry->flags|=CoderRawSupportFlag;
1240 entry->flags|=CoderEndianSupportFlag;
1241 (void) RegisterMagickInfo(entry);
1242 entry=AcquireMagickInfo("RGB","RGBA",
1243 "Raw red, green, blue, and alpha samples");
1244 entry->decoder=(DecodeImageHandler *) ReadRGBImage;
1245 entry->encoder=(EncodeImageHandler *) WriteRGBImage;
1246 entry->flags|=CoderRawSupportFlag;
1247 entry->flags|=CoderEndianSupportFlag;
1248 (void) RegisterMagickInfo(entry);
1249 entry=AcquireMagickInfo("RGB","RGBO",
1250 "Raw red, green, blue, and opacity samples");
1251 entry->decoder=(DecodeImageHandler *) ReadRGBImage;
1252 entry->encoder=(EncodeImageHandler *) WriteRGBImage;
1253 entry->flags|=CoderRawSupportFlag;
1254 entry->flags|=CoderEndianSupportFlag;
1255 (void) RegisterMagickInfo(entry);
1256 entry=AcquireMagickInfo("RGB","RGB565",
1257 "Raw red, green, blue samples in 565 format");
1258 entry->decoder=(DecodeImageHandler *) ReadRGB565Image;
1259 entry->flags|=CoderRawSupportFlag;
1260 entry->flags|=CoderEndianSupportFlag;
1261 (void) RegisterMagickInfo(entry);
1262 return(MagickImageCoderSignature);
1263 }
1264
1265 /*
1266 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1267 % %
1268 % %
1269 % %
1270 % U n r e g i s t e r R G B I m a g e %
1271 % %
1272 % %
1273 % %
1274 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1275 %
1276 % UnregisterRGBImage() removes format registrations made by the RGB module
1277 % from the list of supported formats.
1278 %
1279 % The format of the UnregisterRGBImage method is:
1280 %
1281 % UnregisterRGBImage(void)
1282 %
1283 */
UnregisterRGBImage(void)1284 ModuleExport void UnregisterRGBImage(void)
1285 {
1286 (void) UnregisterMagickInfo("RGBO");
1287 (void) UnregisterMagickInfo("RGBA");
1288 (void) UnregisterMagickInfo("RGB");
1289 }
1290
1291 /*
1292 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1293 % %
1294 % %
1295 % %
1296 % W r i t e R G B I m a g e %
1297 % %
1298 % %
1299 % %
1300 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1301 %
1302 % WriteRGBImage() writes an image to a file in the RGB, RGBA, or RGBO
1303 % rasterfile format.
1304 %
1305 % The format of the WriteRGBImage method is:
1306 %
1307 % MagickBooleanType WriteRGBImage(const ImageInfo *image_info,
1308 % Image *image,ExceptionInfo *exception)
1309 %
1310 % A description of each parameter follows.
1311 %
1312 % o image_info: the image info.
1313 %
1314 % o image: The image.
1315 %
1316 % o exception: return any errors or warnings in this structure.
1317 %
1318 */
WriteRGBImage(const ImageInfo * image_info,Image * image,ExceptionInfo * exception)1319 static MagickBooleanType WriteRGBImage(const ImageInfo *image_info,
1320 Image *image,ExceptionInfo *exception)
1321 {
1322 MagickBooleanType
1323 status;
1324
1325 MagickOffsetType
1326 scene;
1327
1328 QuantumInfo
1329 *quantum_info;
1330
1331 QuantumType
1332 quantum_type;
1333
1334 size_t
1335 imageListLength,
1336 length;
1337
1338 ssize_t
1339 count,
1340 y;
1341
1342 unsigned char
1343 *pixels;
1344
1345 /*
1346 Allocate memory for pixels.
1347 */
1348 assert(image_info != (const ImageInfo *) NULL);
1349 assert(image_info->signature == MagickCoreSignature);
1350 assert(image != (Image *) NULL);
1351 assert(image->signature == MagickCoreSignature);
1352 if (image->debug != MagickFalse)
1353 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1354 if (image_info->interlace != PartitionInterlace)
1355 {
1356 /*
1357 Open output image file.
1358 */
1359 status=OpenBlob(image_info,image,WriteBinaryBlobMode,exception);
1360 if (status == MagickFalse)
1361 return(status);
1362 }
1363 quantum_type=RGBQuantum;
1364 if (LocaleCompare(image_info->magick,"RGBA") == 0)
1365 quantum_type=RGBAQuantum;
1366 if (LocaleCompare(image_info->magick,"RGBO") == 0)
1367 quantum_type=RGBOQuantum;
1368 scene=0;
1369 imageListLength=GetImageListLength(image);
1370 do
1371 {
1372 /*
1373 Convert MIFF to RGB raster pixels.
1374 */
1375 (void) TransformImageColorspace(image,sRGBColorspace,exception);
1376 if ((LocaleCompare(image_info->magick,"RGBA") == 0) &&
1377 (image->alpha_trait == UndefinedPixelTrait))
1378 (void) SetImageAlphaChannel(image,OpaqueAlphaChannel,exception);
1379 quantum_info=AcquireQuantumInfo(image_info,image);
1380 if (quantum_info == (QuantumInfo *) NULL)
1381 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
1382 pixels=(unsigned char *) GetQuantumPixels(quantum_info);
1383 switch (image_info->interlace)
1384 {
1385 case NoInterlace:
1386 default:
1387 {
1388 /*
1389 No interlacing: RGBRGBRGBRGBRGBRGB...
1390 */
1391 for (y=0; y < (ssize_t) image->rows; y++)
1392 {
1393 register const Quantum
1394 *magick_restrict p;
1395
1396 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
1397 if (p == (const Quantum *) NULL)
1398 break;
1399 length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1400 quantum_type,pixels,exception);
1401 count=WriteBlob(image,length,pixels);
1402 if (count != (ssize_t) length)
1403 break;
1404 if (image->previous == (Image *) NULL)
1405 {
1406 status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
1407 image->rows);
1408 if (status == MagickFalse)
1409 break;
1410 }
1411 }
1412 break;
1413 }
1414 case LineInterlace:
1415 {
1416 /*
1417 Line interlacing: RRR...GGG...BBB...RRR...GGG...BBB...
1418 */
1419 for (y=0; y < (ssize_t) image->rows; y++)
1420 {
1421 register const Quantum
1422 *magick_restrict p;
1423
1424 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
1425 if (p == (const Quantum *) NULL)
1426 break;
1427 length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1428 RedQuantum,pixels,exception);
1429 count=WriteBlob(image,length,pixels);
1430 if (count != (ssize_t) length)
1431 break;
1432 length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1433 GreenQuantum,pixels,exception);
1434 count=WriteBlob(image,length,pixels);
1435 if (count != (ssize_t) length)
1436 break;
1437 length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1438 BlueQuantum,pixels,exception);
1439 count=WriteBlob(image,length,pixels);
1440 if (count != (ssize_t) length)
1441 break;
1442 if (quantum_type == RGBAQuantum)
1443 {
1444 length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1445 AlphaQuantum,pixels,exception);
1446 count=WriteBlob(image,length,pixels);
1447 if (count != (ssize_t) length)
1448 break;
1449 }
1450 if (quantum_type == RGBOQuantum)
1451 {
1452 length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1453 OpacityQuantum,pixels,exception);
1454 count=WriteBlob(image,length,pixels);
1455 if (count != (ssize_t) length)
1456 break;
1457 }
1458 if (image->previous == (Image *) NULL)
1459 {
1460 status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
1461 image->rows);
1462 if (status == MagickFalse)
1463 break;
1464 }
1465 }
1466 break;
1467 }
1468 case PlaneInterlace:
1469 {
1470 /*
1471 Plane interlacing: RRRRRR...GGGGGG...BBBBBB...
1472 */
1473 for (y=0; y < (ssize_t) image->rows; y++)
1474 {
1475 register const Quantum
1476 *magick_restrict p;
1477
1478 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
1479 if (p == (const Quantum *) NULL)
1480 break;
1481 length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1482 RedQuantum,pixels,exception);
1483 count=WriteBlob(image,length,pixels);
1484 if (count != (ssize_t) length)
1485 break;
1486 }
1487 if (image->previous == (Image *) NULL)
1488 {
1489 status=SetImageProgress(image,SaveImageTag,1,6);
1490 if (status == MagickFalse)
1491 break;
1492 }
1493 for (y=0; y < (ssize_t) image->rows; y++)
1494 {
1495 register const Quantum
1496 *magick_restrict p;
1497
1498 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
1499 if (p == (const Quantum *) NULL)
1500 break;
1501 length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1502 GreenQuantum,pixels,exception);
1503 count=WriteBlob(image,length,pixels);
1504 if (count != (ssize_t) length)
1505 break;
1506 }
1507 if (image->previous == (Image *) NULL)
1508 {
1509 status=SetImageProgress(image,SaveImageTag,2,6);
1510 if (status == MagickFalse)
1511 break;
1512 }
1513 for (y=0; y < (ssize_t) image->rows; y++)
1514 {
1515 register const Quantum
1516 *magick_restrict p;
1517
1518 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
1519 if (p == (const Quantum *) NULL)
1520 break;
1521 length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1522 BlueQuantum,pixels,exception);
1523 count=WriteBlob(image,length,pixels);
1524 if (count != (ssize_t) length)
1525 break;
1526 }
1527 if (image->previous == (Image *) NULL)
1528 {
1529 status=SetImageProgress(image,SaveImageTag,3,6);
1530 if (status == MagickFalse)
1531 break;
1532 }
1533 if (quantum_type == RGBAQuantum)
1534 {
1535 for (y=0; y < (ssize_t) image->rows; y++)
1536 {
1537 register const Quantum
1538 *magick_restrict p;
1539
1540 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
1541 if (p == (const Quantum *) NULL)
1542 break;
1543 length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1544 AlphaQuantum,pixels,exception);
1545 count=WriteBlob(image,length,pixels);
1546 if (count != (ssize_t) length)
1547 break;
1548 }
1549 if (image->previous == (Image *) NULL)
1550 {
1551 status=SetImageProgress(image,SaveImageTag,5,6);
1552 if (status == MagickFalse)
1553 break;
1554 }
1555 }
1556 if (image_info->interlace == PartitionInterlace)
1557 (void) CopyMagickString(image->filename,image_info->filename,
1558 MagickPathExtent);
1559 if (image->previous == (Image *) NULL)
1560 {
1561 status=SetImageProgress(image,SaveImageTag,6,6);
1562 if (status == MagickFalse)
1563 break;
1564 }
1565 break;
1566 }
1567 case PartitionInterlace:
1568 {
1569 /*
1570 Partition interlacing: RRRRRR..., GGGGGG..., BBBBBB...
1571 */
1572 AppendImageFormat("R",image->filename);
1573 status=OpenBlob(image_info,image,scene == 0 ? WriteBinaryBlobMode :
1574 AppendBinaryBlobMode,exception);
1575 if (status == MagickFalse)
1576 return(status);
1577 for (y=0; y < (ssize_t) image->rows; y++)
1578 {
1579 register const Quantum
1580 *magick_restrict p;
1581
1582 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
1583 if (p == (const Quantum *) NULL)
1584 break;
1585 length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1586 RedQuantum,pixels,exception);
1587 count=WriteBlob(image,length,pixels);
1588 if (count != (ssize_t) length)
1589 break;
1590 }
1591 if (image->previous == (Image *) NULL)
1592 {
1593 status=SetImageProgress(image,SaveImageTag,1,6);
1594 if (status == MagickFalse)
1595 break;
1596 }
1597 (void) CloseBlob(image);
1598 AppendImageFormat("G",image->filename);
1599 status=OpenBlob(image_info,image,scene == 0 ? WriteBinaryBlobMode :
1600 AppendBinaryBlobMode,exception);
1601 if (status == MagickFalse)
1602 return(status);
1603 for (y=0; y < (ssize_t) image->rows; y++)
1604 {
1605 register const Quantum
1606 *magick_restrict p;
1607
1608 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
1609 if (p == (const Quantum *) NULL)
1610 break;
1611 length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1612 GreenQuantum,pixels,exception);
1613 count=WriteBlob(image,length,pixels);
1614 if (count != (ssize_t) length)
1615 break;
1616 }
1617 if (image->previous == (Image *) NULL)
1618 {
1619 status=SetImageProgress(image,SaveImageTag,2,6);
1620 if (status == MagickFalse)
1621 break;
1622 }
1623 (void) CloseBlob(image);
1624 AppendImageFormat("B",image->filename);
1625 status=OpenBlob(image_info,image,scene == 0 ? WriteBinaryBlobMode :
1626 AppendBinaryBlobMode,exception);
1627 if (status == MagickFalse)
1628 return(status);
1629 for (y=0; y < (ssize_t) image->rows; y++)
1630 {
1631 register const Quantum
1632 *magick_restrict p;
1633
1634 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
1635 if (p == (const Quantum *) NULL)
1636 break;
1637 length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1638 BlueQuantum,pixels,exception);
1639 count=WriteBlob(image,length,pixels);
1640 if (count != (ssize_t) length)
1641 break;
1642 }
1643 if (image->previous == (Image *) NULL)
1644 {
1645 status=SetImageProgress(image,SaveImageTag,3,6);
1646 if (status == MagickFalse)
1647 break;
1648 }
1649 if (quantum_type == RGBAQuantum)
1650 {
1651 (void) CloseBlob(image);
1652 AppendImageFormat("A",image->filename);
1653 status=OpenBlob(image_info,image,scene == 0 ? WriteBinaryBlobMode :
1654 AppendBinaryBlobMode,exception);
1655 if (status == MagickFalse)
1656 return(status);
1657 for (y=0; y < (ssize_t) image->rows; y++)
1658 {
1659 register const Quantum
1660 *magick_restrict p;
1661
1662 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
1663 if (p == (const Quantum *) NULL)
1664 break;
1665 length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1666 AlphaQuantum,pixels,exception);
1667 count=WriteBlob(image,length,pixels);
1668 if (count != (ssize_t) length)
1669 break;
1670 }
1671 if (image->previous == (Image *) NULL)
1672 {
1673 status=SetImageProgress(image,SaveImageTag,5,6);
1674 if (status == MagickFalse)
1675 break;
1676 }
1677 }
1678 (void) CloseBlob(image);
1679 (void) CopyMagickString(image->filename,image_info->filename,
1680 MagickPathExtent);
1681 if (image->previous == (Image *) NULL)
1682 {
1683 status=SetImageProgress(image,SaveImageTag,6,6);
1684 if (status == MagickFalse)
1685 break;
1686 }
1687 break;
1688 }
1689 }
1690 quantum_info=DestroyQuantumInfo(quantum_info);
1691 if (GetNextImageInList(image) == (Image *) NULL)
1692 break;
1693 image=SyncNextImageInList(image);
1694 status=SetImageProgress(image,SaveImagesTag,scene++,imageListLength);
1695 if (status == MagickFalse)
1696 break;
1697 } while (image_info->adjoin != MagickFalse);
1698 (void) CloseBlob(image);
1699 return(MagickTrue);
1700 }
1701