2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
13 % Read/Write Raw RGB Image Format %
20 % Copyright 1999-2008 ImageMagick Studio LLC, a non-profit organization %
21 % dedicated to making software imaging solutions freely available. %
23 % You may not use this file except in compliance with the License. You may %
24 % obtain a copy of the License at %
26 % http://www.imagemagick.org/script/license.php %
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. %
34 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
42 #include "magick/studio.h"
43 #include "magick/blob.h"
44 #include "magick/blob-private.h"
45 #include "magick/cache.h"
46 #include "magick/colorspace.h"
47 #include "magick/constitute.h"
48 #include "magick/exception.h"
49 #include "magick/exception-private.h"
50 #include "magick/image.h"
51 #include "magick/image-private.h"
52 #include "magick/list.h"
53 #include "magick/magick.h"
54 #include "magick/memory_.h"
55 #include "magick/monitor.h"
56 #include "magick/monitor-private.h"
57 #include "magick/pixel-private.h"
58 #include "magick/quantum-private.h"
59 #include "magick/static.h"
60 #include "magick/statistic.h"
61 #include "magick/string_.h"
62 #include "magick/module.h"
63 #include "magick/utility.h"
68 static MagickBooleanType
69 WriteRGBImage(const ImageInfo *,Image *);
72 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
76 % R e a d R G B I m a g e %
80 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
82 % ReadRGBImage() reads an image of raw RGB or RGBA samples and returns it. It
83 % allocates the memory necessary for the new Image structure and returns a
84 % pointer to the new image.
86 % The format of the ReadRGBImage method is:
88 % Image *ReadRGBImage(const ImageInfo *image_info,ExceptionInfo *exception)
90 % A description of each parameter follows:
92 % o image_info: the image info.
94 % o exception: return any errors or warnings in this structure.
97 static Image *ReadRGBImage(const ImageInfo *image_info,ExceptionInfo *exception)
142 assert(image_info != (const ImageInfo *) NULL);
143 assert(image_info->signature == MagickSignature);
144 if (image_info->debug != MagickFalse)
145 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
146 image_info->filename);
147 assert(exception != (ExceptionInfo *) NULL);
148 assert(exception->signature == MagickSignature);
149 image=AcquireImage(image_info);
150 if ((image->columns == 0) || (image->rows == 0))
151 ThrowReaderException(OptionError,"MustSpecifyImageSize");
152 if (image_info->interlace != PartitionInterlace)
154 status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
155 if (status == MagickFalse)
157 image=DestroyImageList(image);
158 return((Image *) NULL);
160 for (i=0; i < image->offset; i++)
161 if (ReadBlobByte(image) == EOF)
163 ThrowFileException(exception,CorruptImageError,
164 "UnexpectedEndOfFile",image->filename);
169 Create virtual canvas to support cropping (i.e. image.rgb[100x100+10+20]).
171 canvas_image=CloneImage(image,image->extract_info.width,1,MagickFalse,
173 (void) SetImageVirtualPixelMethod(canvas_image,BlackVirtualPixelMethod);
174 quantum_info=AcquireQuantumInfo(image_info,canvas_image);
175 if (quantum_info == (QuantumInfo *) NULL)
176 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
177 pixels=GetQuantumPixels(quantum_info);
178 quantum_type=RGBQuantum;
179 for (i=0; i < 4; i++)
181 if (image_info->magick[i] == '\0')
183 switch(image_info->magick[i])
185 case 'R': quantum_types[i]=RedQuantum; break;
186 case 'G': quantum_types[i]=GreenQuantum; break;
187 case 'B': quantum_types[i]=BlueQuantum; break;
188 case 'A': quantum_types[i]=AlphaQuantum; break;
189 case 'O': quantum_types[i]=OpacityQuantum; break;
194 if (LocaleCompare(image_info->magick,"BGRA") == 0)
196 quantum_type=BGRAQuantum;
197 image->matte=MagickTrue;
199 if (LocaleCompare(image_info->magick,"RGBA") == 0)
201 quantum_type=RGBAQuantum;
202 image->matte=MagickTrue;
204 if (LocaleCompare(image_info->magick,"RGBO") == 0)
206 quantum_type=RGBOQuantum;
209 if (image_info->number_scenes != 0)
210 while (image->scene < image_info->scene)
216 length=GetQuantumExtent(canvas_image,quantum_info,quantum_type);
217 for (y=0; y < (ssize_t) image->rows; y++)
219 count=ReadBlob(image,length,pixels);
220 if (count != (ssize_t) length)
230 Read pixels to virtual canvas image then push to image.
232 if ((image_info->ping != MagickFalse) && (image_info->number_scenes != 0))
233 if (image->scene >= (image_info->scene+image_info->number_scenes-1))
235 switch (image_info->interlace)
241 No interlacing: RGBRGBRGBRGBRGBRGB...
245 length=GetQuantumExtent(canvas_image,quantum_info,quantum_type);
246 count=ReadBlob(image,length,pixels);
247 if (count != (ssize_t) length)
250 for (y=0; y < (ssize_t) image->extract_info.height; y++)
252 register const PixelPacket
261 if (count != (ssize_t) length)
263 ThrowFileException(exception,CorruptImageError,
264 "UnexpectedEndOfFile",image->filename);
267 q=GetAuthenticPixels(canvas_image,0,0,canvas_image->columns,1,
269 if (q == (PixelPacket *) NULL)
271 length=ImportQuantumPixels(canvas_image,(CacheView *) NULL,
272 quantum_info,quantum_type,pixels,exception);
273 if (SyncAuthenticPixels(canvas_image,exception) == MagickFalse)
275 if (((y-image->extract_info.y) >= 0) &&
276 ((y-image->extract_info.y) < (ssize_t) image->rows))
278 p=GetVirtualPixels(canvas_image,canvas_image->extract_info.x,0,
279 canvas_image->columns,1,exception);
280 q=QueueAuthenticPixels(image,0,y-image->extract_info.y,
281 image->columns,1,exception);
282 if ((p == (const PixelPacket *) NULL) ||
283 (q == (PixelPacket *) NULL))
285 for (x=0; x < (ssize_t) image->columns; x++)
287 qx[0]=GetRedPixelComponent(p);
288 qx[1]=GetGreenPixelComponent(p);
289 qx[2]=GetBluePixelComponent(p);
290 qx[3]=GetOpacityPixelComponent(p);
291 for (i=0; i < channels; i++)
292 switch(quantum_types[i])
294 case RedQuantum: q->red=qx[i]; break;
295 case GreenQuantum: q->green=qx[i]; break;
296 case BlueQuantum: q->blue=qx[i]; break;
297 case AlphaQuantum: q->opacity=qx[i]; break;
298 case OpacityQuantum: q->opacity=qx[i]; break;
304 if (SyncAuthenticPixels(image,exception) == MagickFalse)
307 if (image->previous == (Image *) NULL)
309 status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y,
311 if (status == MagickFalse)
314 count=ReadBlob(image,length,pixels);
321 Line interlacing: RRR...GGG...BBB...RRR...GGG...BBB...
325 length=GetQuantumExtent(canvas_image,quantum_info,quantum_types[0]);
326 count=ReadBlob(image,length,pixels);
328 for (y=0; y < (ssize_t) image->extract_info.height; y++)
330 register const PixelPacket
339 if (count != (ssize_t) length)
341 ThrowFileException(exception,CorruptImageError,
342 "UnexpectedEndOfFile",image->filename);
345 for (i=0; i < channels; i++)
347 q=GetAuthenticPixels(canvas_image,0,0,canvas_image->columns,1,
349 if (q == (PixelPacket *) NULL)
351 length=ImportQuantumPixels(canvas_image,(CacheView *) NULL,
352 quantum_info,quantum_types[i],pixels,exception);
353 if (SyncAuthenticPixels(canvas_image,exception) == MagickFalse)
355 if (((y-image->extract_info.y) >= 0) &&
356 ((y-image->extract_info.y) < (ssize_t) image->rows))
358 p=GetVirtualPixels(canvas_image,canvas_image->extract_info.x,
359 0,canvas_image->columns,1,exception);
360 q=GetAuthenticPixels(image,0,y-image->extract_info.y,
361 image->columns,1,exception);
362 if ((p == (const PixelPacket *) NULL) ||
363 (q == (PixelPacket *) NULL))
365 if (i == (channels - 1))
366 for (x=0; x < (ssize_t) image->columns; x++)
368 SetRedPixelComponent(q,GetRedPixelComponent(p));
369 SetGreenPixelComponent(q,GetGreenPixelComponent(p));
370 SetBluePixelComponent(q,GetBluePixelComponent(p));
371 SetOpacityPixelComponent(q,GetOpacityPixelComponent(p));
375 if (SyncAuthenticPixels(image,exception) == MagickFalse)
378 count=ReadBlob(image,length,pixels);
380 if (image->previous == (Image *) NULL)
382 status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y,
384 if (status == MagickFalse)
393 Plane interlacing: RRRRRR...GGGGGG...BBBBBB...
397 length=GetQuantumExtent(canvas_image,quantum_info,quantum_types[0]);
398 count=ReadBlob(image,length,pixels);
400 for (i=0; i < channels; i++)
402 for (y=0; y < (ssize_t) image->extract_info.height; y++)
404 register const PixelPacket
413 if (count != (ssize_t) length)
415 ThrowFileException(exception,CorruptImageError,
416 "UnexpectedEndOfFile",image->filename);
419 q=GetAuthenticPixels(canvas_image,0,0,canvas_image->columns,1,
421 if (q == (PixelPacket *) NULL)
423 length=ImportQuantumPixels(canvas_image,(CacheView *) NULL,
424 quantum_info,quantum_types[i],pixels,exception);
425 if (SyncAuthenticPixels(canvas_image,exception) == MagickFalse)
427 if (((y-image->extract_info.y) >= 0) &&
428 ((y-image->extract_info.y) < (ssize_t) image->rows))
430 p=GetVirtualPixels(canvas_image,canvas_image->extract_info.x,0,
431 canvas_image->columns,1,exception);
432 q=GetAuthenticPixels(image,0,y-image->extract_info.y,
433 image->columns,1,exception);
434 if ((p == (const PixelPacket *) NULL) ||
435 (q == (PixelPacket *) NULL))
437 for (x=0; x < (ssize_t) image->columns; x++)
439 switch(quantum_types[i])
443 SetRedPixelComponent(q,GetRedPixelComponent(p));
448 SetGreenPixelComponent(q,GetGreenPixelComponent(p));
453 SetBluePixelComponent(q,GetBluePixelComponent(p));
459 SetOpacityPixelComponent(q,GetOpacityPixelComponent(p));
468 if (SyncAuthenticPixels(image,exception) == MagickFalse)
471 count=ReadBlob(image,length,pixels);
473 if (image->previous == (Image *) NULL)
475 status=SetImageProgress(image,LoadImageTag,(i+1),5);
476 if (status == MagickFalse)
480 if (image->previous == (Image *) NULL)
482 status=SetImageProgress(image,LoadImageTag,5,5);
483 if (status == MagickFalse)
488 case PartitionInterlace:
491 Partition interlacing: RRRRRR..., GGGGGG..., BBBBBB...
493 for (i=0; i < channels; i++)
495 sfx[0]=image_info->magick[i];
496 AppendImageFormat(sfx,image->filename);
497 status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
498 if (status == MagickFalse)
500 canvas_image=DestroyImageList(canvas_image);
501 image=DestroyImageList(image);
502 return((Image *) NULL);
505 for (j=0; j < image->offset; j++)
506 if (ReadBlobByte(image) == EOF)
508 ThrowFileException(exception,CorruptImageError,
509 "UnexpectedEndOfFile",image->filename);
512 length=GetQuantumExtent(canvas_image,quantum_info,quantum_types[i]);
513 for (j=0; j < (ssize_t) scene; j++)
514 for (y=0; y < (ssize_t) image->extract_info.height; y++)
515 if (ReadBlob(image,length,pixels) != (ssize_t) length)
517 ThrowFileException(exception,CorruptImageError,
518 "UnexpectedEndOfFile",image->filename);
521 count=ReadBlob(image,length,pixels);
522 for (y=0; y < (ssize_t) image->extract_info.height; y++)
524 register const PixelPacket
533 if (count != (ssize_t) length)
535 ThrowFileException(exception,CorruptImageError,
536 "UnexpectedEndOfFile",image->filename);
539 q=GetAuthenticPixels(canvas_image,0,0,canvas_image->columns,1,
541 if (q == (PixelPacket *) NULL)
543 length=ImportQuantumPixels(canvas_image,(CacheView *) NULL,
544 quantum_info,quantum_types[i],pixels,exception);
545 if (SyncAuthenticPixels(canvas_image,exception) == MagickFalse)
547 if (((y-image->extract_info.y) >= 0) &&
548 ((y-image->extract_info.y) < (ssize_t) image->rows))
550 p=GetVirtualPixels(canvas_image,canvas_image->extract_info.x,0,
551 canvas_image->columns,1,exception);
552 q=GetAuthenticPixels(image,0,y-image->extract_info.y,
553 image->columns,1,exception);
554 if ((p == (const PixelPacket *) NULL) ||
555 (q == (PixelPacket *) NULL))
557 for (x=0; x < (ssize_t) image->columns; x++)
559 switch(quantum_types[i])
563 SetRedPixelComponent(q,GetRedPixelComponent(p));
568 SetGreenPixelComponent(q,GetGreenPixelComponent(p));
573 SetBluePixelComponent(q,GetBluePixelComponent(p));
579 SetOpacityPixelComponent(q,GetOpacityPixelComponent(p));
588 if (SyncAuthenticPixels(image,exception) == MagickFalse)
591 count=ReadBlob(image,length,pixels);
593 if (image->previous == (Image *) NULL)
595 status=SetImageProgress(image,LoadImageTag,(i+1),5);
596 if (status == MagickFalse)
599 if (i != (channels-1))
600 (void) CloseBlob(image);
602 if (image->previous == (Image *) NULL)
604 status=SetImageProgress(image,LoadImageTag,5,5);
605 if (status == MagickFalse)
611 SetQuantumImageType(image,quantum_type);
613 Proceed to next image.
615 if (image_info->number_scenes != 0)
616 if (image->scene >= (image_info->scene+image_info->number_scenes-1))
618 if (count == (ssize_t) length)
621 Allocate next image structure.
623 AcquireNextImage(image_info,image);
624 if (GetNextImageInList(image) == (Image *) NULL)
626 image=DestroyImageList(image);
627 return((Image *) NULL);
629 image=SyncNextImageInList(image);
630 status=SetImageProgress(image,LoadImagesTag,TellBlob(image),
632 if (status == MagickFalse)
636 } while (count == (ssize_t) length);
637 quantum_info=DestroyQuantumInfo(quantum_info);
638 InheritException(&image->exception,&canvas_image->exception);
639 canvas_image=DestroyImage(canvas_image);
640 (void) CloseBlob(image);
641 return(GetFirstImageInList(image));
645 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
649 % R e g i s t e r R G B I m a g e %
653 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
655 % RegisterRGBImage() adds attributes for the RGB or RGBA image format to
656 % the list of supported formats. The attributes include the image format
657 % tag, a method to read and/or write the format, whether the format
658 % supports the saving of more than one frame to the same file or blob,
659 % whether the format supports native in-memory I/O, and a brief
660 % description of the format.
662 % The format of the RegisterRGBImage method is:
664 % size_t RegisterRGBImage(void)
667 ModuleExport size_t RegisterRGBImage(void)
672 entry=SetMagickInfo("RGB");
673 entry->decoder=(DecodeImageHandler *) ReadRGBImage;
674 entry->encoder=(EncodeImageHandler *) WriteRGBImage;
675 entry->raw=MagickTrue;
676 entry->endian_support=MagickTrue;
677 entry->description=ConstantString("Raw red, green, and blue samples");
678 entry->module=ConstantString("RGB");
679 (void) RegisterMagickInfo(entry);
680 entry=SetMagickInfo("RBG");
681 entry->decoder=(DecodeImageHandler *) ReadRGBImage;
682 entry->encoder=(EncodeImageHandler *) WriteRGBImage;
683 entry->raw=MagickTrue;
684 entry->endian_support=MagickTrue;
685 entry->description=ConstantString("Raw red, blue, and green samples");
686 entry->module=ConstantString("RGB");
687 (void) RegisterMagickInfo(entry);
688 entry=SetMagickInfo("GRB");
689 entry->decoder=(DecodeImageHandler *) ReadRGBImage;
690 entry->encoder=(EncodeImageHandler *) WriteRGBImage;
691 entry->raw=MagickTrue;
692 entry->endian_support=MagickTrue;
693 entry->description=ConstantString("Raw green, red, and blue samples");
694 entry->module=ConstantString("RGB");
695 (void) RegisterMagickInfo(entry);
696 entry=SetMagickInfo("GBR");
697 entry->decoder=(DecodeImageHandler *) ReadRGBImage;
698 entry->encoder=(EncodeImageHandler *) WriteRGBImage;
699 entry->raw=MagickTrue;
700 entry->endian_support=MagickTrue;
701 entry->description=ConstantString("Raw green, blue, and red samples");
702 entry->module=ConstantString("RGB");
703 (void) RegisterMagickInfo(entry);
704 entry=SetMagickInfo("BRG");
705 entry->decoder=(DecodeImageHandler *) ReadRGBImage;
706 entry->encoder=(EncodeImageHandler *) WriteRGBImage;
707 entry->raw=MagickTrue;
708 entry->endian_support=MagickTrue;
709 entry->description=ConstantString("Raw blue, red, and green samples");
710 entry->module=ConstantString("RGB");
711 (void) RegisterMagickInfo(entry);
712 entry=SetMagickInfo("BGR");
713 entry->decoder=(DecodeImageHandler *) ReadRGBImage;
714 entry->encoder=(EncodeImageHandler *) WriteRGBImage;
715 entry->raw=MagickTrue;
716 entry->endian_support=MagickTrue;
717 entry->description=ConstantString("Raw blue, green, and red samples");
718 entry->module=ConstantString("RGB");
719 (void) RegisterMagickInfo(entry);
720 entry=SetMagickInfo("BGRA");
721 entry->decoder=(DecodeImageHandler *) ReadRGBImage;
722 entry->encoder=(EncodeImageHandler *) WriteRGBImage;
723 entry->raw=MagickTrue;
724 entry->endian_support=MagickTrue;
725 entry->description=ConstantString("Raw blue, green, red and alpha samples");
726 entry->module=ConstantString("RGB");
727 (void) RegisterMagickInfo(entry);
728 entry=SetMagickInfo("RGBA");
729 entry->decoder=(DecodeImageHandler *) ReadRGBImage;
730 entry->encoder=(EncodeImageHandler *) WriteRGBImage;
731 entry->raw=MagickTrue;
732 entry->endian_support=MagickTrue;
733 entry->description=ConstantString("Raw red, green, blue, and alpha samples");
734 entry->module=ConstantString("RGB");
735 (void) RegisterMagickInfo(entry);
736 entry=SetMagickInfo("RGBO");
737 entry->decoder=(DecodeImageHandler *) ReadRGBImage;
738 entry->encoder=(EncodeImageHandler *) WriteRGBImage;
739 entry->raw=MagickTrue;
740 entry->endian_support=MagickTrue;
741 entry->description=ConstantString("Raw red, green, blue, and opacity "
743 entry->module=ConstantString("RGB");
744 (void) RegisterMagickInfo(entry);
745 return(MagickImageCoderSignature);
749 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
753 % U n r e g i s t e r R G B I m a g e %
757 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
759 % UnregisterRGBImage() removes format registrations made by the
760 % RGB module from the list of supported formats.
762 % The format of the UnregisterRGBImage method is:
764 % UnregisterRGBImage(void)
767 ModuleExport void UnregisterRGBImage(void)
769 (void) UnregisterMagickInfo("RGBO");
770 (void) UnregisterMagickInfo("RGBA");
771 (void) UnregisterMagickInfo("BGR");
772 (void) UnregisterMagickInfo("BGRA");
773 (void) UnregisterMagickInfo("BRG");
774 (void) UnregisterMagickInfo("GBR");
775 (void) UnregisterMagickInfo("GRB");
776 (void) UnregisterMagickInfo("RBG");
777 (void) UnregisterMagickInfo("RGB");
781 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
785 % W r i t e R G B I m a g e %
789 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
791 % WriteRGBImage() writes an image to a file in the RGB or RGBA rasterfile
794 % The format of the WriteRGBImage method is:
796 % MagickBooleanType WriteRGBImage(const ImageInfo *image_info,Image *image)
798 % A description of each parameter follows.
800 % o image_info: the image info.
802 % o image: The image.
805 static MagickBooleanType WriteRGBImage(const ImageInfo *image_info,Image *image)
839 Allocate memory for pixels.
841 assert(image_info != (const ImageInfo *) NULL);
842 assert(image_info->signature == MagickSignature);
843 assert(image != (Image *) NULL);
844 assert(image->signature == MagickSignature);
845 if (image->debug != MagickFalse)
846 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
847 if (image_info->interlace != PartitionInterlace)
850 Open output image file.
852 status=OpenBlob(image_info,image,WriteBinaryBlobMode,&image->exception);
853 if (status == MagickFalse)
856 quantum_type=RGBQuantum;
857 if (LocaleCompare(image_info->magick,"BGRA") == 0)
859 quantum_type=BGRAQuantum;
860 image->matte=MagickTrue;
862 if (LocaleCompare(image_info->magick,"RGBA") == 0)
864 quantum_type=RGBAQuantum;
865 image->matte=MagickTrue;
867 if (LocaleCompare(image_info->magick,"RGBO") == 0)
869 quantum_type=RGBOQuantum;
872 for (i=0; i < 4; i++)
874 if (image_info->magick[i] == '\0')
876 switch(image_info->magick[i])
878 case 'R': quantum_types[i]=RedQuantum; break;
879 case 'G': quantum_types[i]=GreenQuantum; break;
880 case 'B': quantum_types[i]=BlueQuantum; break;
881 case 'A': quantum_types[i]=AlphaQuantum; break;
882 case 'O': quantum_types[i]=OpacityQuantum; break;
891 Convert MIFF to RGB raster pixels.
893 if (image->colorspace != RGBColorspace)
894 (void) TransformImageColorspace(image,RGBColorspace);
895 if ((LocaleCompare(image_info->magick,"RGBA") == 0) &&
896 (image->matte == MagickFalse))
897 (void) SetImageAlphaChannel(image,ResetAlphaChannel);
898 quantum_info=AcquireQuantumInfo(image_info,image);
899 if (quantum_info == (QuantumInfo *) NULL)
900 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
901 pixels=GetQuantumPixels(quantum_info);
902 switch (image_info->interlace)
917 No interlacing: RGBRGBRGBRGBRGBRGB...
919 image_view=AcquireCacheView(image);
920 for (y=0; y < (ssize_t) image->rows; y++)
928 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
930 if (q == (PixelPacket *) NULL)
932 for (x=0; x < (ssize_t) image->columns; x++)
939 for (i=0; i < channels; i++)
940 switch (quantum_types[i])
942 case RedQuantum: *qx[i]=px.red; break;
943 case GreenQuantum: *qx[i]=px.green; break;
944 case BlueQuantum: *qx[i]=px.blue; break;
945 case AlphaQuantum: *qx[i]=px.opacity; break;
946 case OpacityQuantum: *qx[i]=px.opacity; break;
951 length=ExportQuantumPixels(image,image_view,quantum_info,quantum_type,
952 pixels,&image->exception);
953 count=WriteBlob(image,length,pixels);
954 if (count != (ssize_t) length)
956 if (image->previous == (Image *) NULL)
958 status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
960 if (status == MagickFalse)
964 image_view=DestroyCacheView(image_view);
970 Line interlacing: RRR...GGG...BBB...RRR...GGG...BBB...
972 for (y=0; y < (ssize_t) image->rows; y++)
974 register const PixelPacket
977 p=GetVirtualPixels(image,0,y,image->columns,1,&image->exception);
978 if (p == (const PixelPacket *) NULL)
980 for (i=0; i < (ssize_t) channels; i++)
982 length=ExportQuantumPixels(image,(const CacheView *) NULL,
983 quantum_info,quantum_types[i],pixels,&image->exception);
984 count=WriteBlob(image,length,pixels);
985 if (count != (ssize_t) length)
988 if (image->previous == (Image *) NULL)
990 status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
992 if (status == MagickFalse)
1001 Plane interlacing: RRRRRR...GGGGGG...BBBBBB...
1003 for (i=0; i < (ssize_t) channels; i++)
1005 for (y=0; y < (ssize_t) image->rows; y++)
1007 register const PixelPacket
1010 p=GetVirtualPixels(image,0,y,image->columns,1,&image->exception);
1011 if (p == (const PixelPacket *) NULL)
1013 length=ExportQuantumPixels(image,(const CacheView *) NULL,
1014 quantum_info,quantum_types[i],pixels,&image->exception);
1015 count=WriteBlob(image,length,pixels);
1016 if (count != (ssize_t) length)
1019 if (image->previous == (Image *) NULL)
1021 status=SetImageProgress(image,SaveImageTag,(i+1),5);
1022 if (status == MagickFalse)
1026 if (image->previous == (Image *) NULL)
1028 status=SetImageProgress(image,SaveImageTag,5,5);
1029 if (status == MagickFalse)
1034 case PartitionInterlace:
1040 Partition interlacing: RRRRRR..., GGGGGG..., BBBBBB...
1042 for (i=0; i < (ssize_t) channels; i++)
1044 sfx[0]=image_info->magick[i];
1045 AppendImageFormat(sfx,image->filename);
1046 status=OpenBlob(image_info,image,scene == 0 ? WriteBinaryBlobMode :
1047 AppendBinaryBlobMode,&image->exception);
1048 if (status == MagickFalse)
1050 for (y=0; y < (ssize_t) image->rows; y++)
1052 register const PixelPacket
1055 p=GetVirtualPixels(image,0,y,image->columns,1,&image->exception);
1056 if (p == (const PixelPacket *) NULL)
1058 length=ExportQuantumPixels(image,(const CacheView *) NULL,
1059 quantum_info,quantum_types[i],pixels,&image->exception);
1060 count=WriteBlob(image,length,pixels);
1061 if (count != (ssize_t) length)
1064 if (image->previous == (Image *) NULL)
1066 status=SetImageProgress(image,SaveImageTag,(i+1),5);
1067 if (status == MagickFalse)
1070 (void) CloseBlob(image);
1072 (void) CopyMagickString(image->filename,image_info->filename,
1074 if (image->previous == (Image *) NULL)
1076 status=SetImageProgress(image,SaveImageTag,5,5);
1077 if (status == MagickFalse)
1083 quantum_info=DestroyQuantumInfo(quantum_info);
1084 if (GetNextImageInList(image) == (Image *) NULL)
1086 image=SyncNextImageInList(image);
1087 status=SetImageProgress(image,SaveImagesTag,scene++,
1088 GetImageListLength(image));
1089 if (status == MagickFalse)
1091 } while (image_info->adjoin != MagickFalse);
1092 (void) CloseBlob(image);