2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
13 % Read/Write Raw RGB Image Format %
20 % Copyright 1999-2019 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 % https://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 "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"
70 static MagickBooleanType
71 WriteRGBImage(const ImageInfo *,Image *,ExceptionInfo *);
74 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
78 % R e a d R G B I m a g e %
82 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
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.
88 % The format of the ReadRGBImage method is:
90 % Image *ReadRGBImage(const ImageInfo *image_info,
91 % ExceptionInfo *exception)
93 % A description of each parameter follows:
95 % o image_info: the image info.
97 % o exception: return any errors or warnings in this structure.
100 static Image *ReadRGBImage(const ImageInfo *image_info,ExceptionInfo *exception)
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)
149 status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
150 if (status == MagickFalse)
152 image=DestroyImageList(image);
153 return((Image *) NULL);
155 if (DiscardBlobBytes(image,(MagickSizeType) image->offset) == MagickFalse)
156 ThrowFileException(exception,CorruptImageError,"UnexpectedEndOfFile",
160 Create virtual canvas to support cropping (i.e. image.rgb[100x100+10+20]).
162 canvas_image=CloneImage(image,image->extract_info.width,1,MagickFalse,
164 if(canvas_image == (Image *) NULL)
165 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
166 (void) SetImageVirtualPixelMethod(canvas_image,BlackVirtualPixelMethod,
168 quantum_info=AcquireQuantumInfo(image_info,canvas_image);
169 if (quantum_info == (QuantumInfo *) NULL)
171 canvas_image=DestroyImage(canvas_image);
172 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
174 quantum_type=RGBQuantum;
175 if (LocaleCompare(image_info->magick,"RGBA") == 0)
177 quantum_type=RGBAQuantum;
178 image->alpha_trait=BlendPixelTrait;
179 canvas_image->alpha_trait=BlendPixelTrait;
181 if (LocaleCompare(image_info->magick,"RGBO") == 0)
183 quantum_type=RGBOQuantum;
184 image->alpha_trait=BlendPixelTrait;
185 canvas_image->alpha_trait=BlendPixelTrait;
187 pixels=GetQuantumPixels(quantum_info);
188 if (image_info->number_scenes != 0)
189 while (image->scene < image_info->scene)
195 length=GetQuantumExtent(canvas_image,quantum_info,quantum_type);
196 for (y=0; y < (ssize_t) image->rows; y++)
198 stream=ReadBlobStream(image,length,pixels,&count);
199 if (count != (ssize_t) length)
211 Read pixels to virtual canvas image then push to image.
213 if ((image_info->ping != MagickFalse) && (image_info->number_scenes != 0))
214 if (image->scene >= (image_info->scene+image_info->number_scenes-1))
216 status=SetImageExtent(image,image->columns,image->rows,exception);
217 if (status == MagickFalse)
219 switch (image_info->interlace)
225 No interlacing: RGBRGBRGBRGBRGBRGB...
229 length=GetQuantumExtent(canvas_image,quantum_info,quantum_type);
230 stream=ReadBlobStream(image,length,pixels,&count);
232 for (y=0; y < (ssize_t) image->extract_info.height; y++)
234 register const Quantum
243 if (count != (ssize_t) length)
246 ThrowFileException(exception,CorruptImageError,
247 "UnexpectedEndOfFile",image->filename);
250 q=GetAuthenticPixels(canvas_image,0,0,canvas_image->columns,1,
252 if (q == (Quantum *) NULL)
254 length=ImportQuantumPixels(canvas_image,(CacheView *) NULL,
255 quantum_info,quantum_type,stream,exception);
256 if (SyncAuthenticPixels(canvas_image,exception) == MagickFalse)
258 if (((y-image->extract_info.y) >= 0) &&
259 ((y-image->extract_info.y) < (ssize_t) image->rows))
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))
267 for (x=0; x < (ssize_t) image->columns; x++)
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);
278 if (SyncAuthenticPixels(image,exception) == MagickFalse)
281 if (image->previous == (Image *) NULL)
283 status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y,
285 if (status == MagickFalse)
288 stream=ReadBlobStream(image,length,pixels,&count);
304 Line interlacing: RRR...GGG...BBB...RRR...GGG...BBB...
306 if (LocaleCompare(image_info->magick,"RGBO") == 0)
307 quantum_types[3]=OpacityQuantum;
310 length=GetQuantumExtent(canvas_image,quantum_info,RedQuantum);
311 stream=ReadBlobStream(image,length,pixels,&count);
313 for (y=0; y < (ssize_t) image->extract_info.height; y++)
315 for (i=0; i < (ssize_t) (image->alpha_trait != UndefinedPixelTrait ? 4 : 3); i++)
317 register const Quantum
326 if (count != (ssize_t) length)
329 ThrowFileException(exception,CorruptImageError,
330 "UnexpectedEndOfFile",image->filename);
333 quantum_type=quantum_types[i];
334 q=GetAuthenticPixels(canvas_image,0,0,canvas_image->columns,1,
336 if (q == (Quantum *) NULL)
338 length=ImportQuantumPixels(canvas_image,(CacheView *) NULL,
339 quantum_info,quantum_type,stream,exception);
340 if (SyncAuthenticPixels(canvas_image,exception) == MagickFalse)
342 if (((y-image->extract_info.y) >= 0) &&
343 ((y-image->extract_info.y) < (ssize_t) image->rows))
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))
351 for (x=0; x < (ssize_t) image->columns; x++)
353 switch (quantum_type)
357 SetPixelRed(image,GetPixelRed(canvas_image,p),q);
362 SetPixelGreen(image,GetPixelGreen(canvas_image,p),q);
367 SetPixelBlue(image,GetPixelBlue(canvas_image,p),q);
372 SetPixelOpacity(image,GetPixelOpacity(canvas_image,p),q);
377 SetPixelAlpha(image,GetPixelAlpha(canvas_image,p),q);
383 p+=GetPixelChannels(canvas_image);
384 q+=GetPixelChannels(image);
386 if (SyncAuthenticPixels(image,exception) == MagickFalse)
389 stream=ReadBlobStream(image,length,pixels,&count);
391 if (image->previous == (Image *) NULL)
393 status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y,
395 if (status == MagickFalse)
404 Plane interlacing: RRRRRR...GGGGGG...BBBBBB...
408 length=GetQuantumExtent(canvas_image,quantum_info,RedQuantum);
409 stream=ReadBlobStream(image,length,pixels,&count);
411 for (y=0; y < (ssize_t) image->extract_info.height; y++)
413 register const Quantum
422 if (count != (ssize_t) length)
425 ThrowFileException(exception,CorruptImageError,
426 "UnexpectedEndOfFile",image->filename);
429 q=GetAuthenticPixels(canvas_image,0,0,canvas_image->columns,1,
431 if (q == (Quantum *) NULL)
433 length=ImportQuantumPixels(canvas_image,(CacheView *) NULL,
434 quantum_info,RedQuantum,stream,exception);
435 if (SyncAuthenticPixels(canvas_image,exception) == MagickFalse)
437 if (((y-image->extract_info.y) >= 0) &&
438 ((y-image->extract_info.y) < (ssize_t) image->rows))
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))
446 for (x=0; x < (ssize_t) image->columns; x++)
448 SetPixelRed(image,GetPixelRed(canvas_image,p),q);
449 p+=GetPixelChannels(canvas_image);
450 q+=GetPixelChannels(image);
452 if (SyncAuthenticPixels(image,exception) == MagickFalse)
455 stream=ReadBlobStream(image,length,pixels,&count);
457 if (image->previous == (Image *) NULL)
459 status=SetImageProgress(image,LoadImageTag,1,6);
460 if (status == MagickFalse)
463 for (y=0; y < (ssize_t) image->extract_info.height; y++)
465 register const Quantum
474 if (count != (ssize_t) length)
477 ThrowFileException(exception,CorruptImageError,
478 "UnexpectedEndOfFile",image->filename);
481 q=GetAuthenticPixels(canvas_image,0,0,canvas_image->columns,1,
483 if (q == (Quantum *) NULL)
485 length=ImportQuantumPixels(canvas_image,(CacheView *) NULL,
486 quantum_info,GreenQuantum,stream,exception);
487 if (SyncAuthenticPixels(canvas_image,exception) == MagickFalse)
489 if (((y-image->extract_info.y) >= 0) &&
490 ((y-image->extract_info.y) < (ssize_t) image->rows))
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))
498 for (x=0; x < (ssize_t) image->columns; x++)
500 SetPixelGreen(image,GetPixelGreen(canvas_image,p),q);
501 p+=GetPixelChannels(canvas_image);
502 q+=GetPixelChannels(image);
504 if (SyncAuthenticPixels(image,exception) == MagickFalse)
507 stream=ReadBlobStream(image,length,pixels,&count);
509 if (image->previous == (Image *) NULL)
511 status=SetImageProgress(image,LoadImageTag,2,6);
512 if (status == MagickFalse)
515 for (y=0; y < (ssize_t) image->extract_info.height; y++)
517 register const Quantum
526 if (count != (ssize_t) length)
529 ThrowFileException(exception,CorruptImageError,
530 "UnexpectedEndOfFile",image->filename);
533 q=GetAuthenticPixels(canvas_image,0,0,canvas_image->columns,1,
535 if (q == (Quantum *) NULL)
537 length=ImportQuantumPixels(canvas_image,(CacheView *) NULL,
538 quantum_info,BlueQuantum,stream,exception);
539 if (SyncAuthenticPixels(canvas_image,exception) == MagickFalse)
541 if (((y-image->extract_info.y) >= 0) &&
542 ((y-image->extract_info.y) < (ssize_t) image->rows))
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))
550 for (x=0; x < (ssize_t) image->columns; x++)
552 SetPixelBlue(image,GetPixelBlue(canvas_image,p),q);
553 p+=GetPixelChannels(canvas_image);
554 q+=GetPixelChannels(image);
556 if (SyncAuthenticPixels(image,exception) == MagickFalse)
559 stream=ReadBlobStream(image,length,pixels,&count);
561 if (image->previous == (Image *) NULL)
563 status=SetImageProgress(image,LoadImageTag,4,6);
564 if (status == MagickFalse)
567 if (image->alpha_trait != UndefinedPixelTrait)
569 for (y=0; y < (ssize_t) image->extract_info.height; y++)
571 register const Quantum
580 if (count != (ssize_t) length)
583 ThrowFileException(exception,CorruptImageError,
584 "UnexpectedEndOfFile",image->filename);
587 q=GetAuthenticPixels(canvas_image,0,0,canvas_image->columns,1,
589 if (q == (Quantum *) NULL)
591 length=ImportQuantumPixels(canvas_image,(CacheView *) NULL,
592 quantum_info,AlphaQuantum,stream,exception);
593 if (SyncAuthenticPixels(canvas_image,exception) == MagickFalse)
595 if (((y-image->extract_info.y) >= 0) &&
596 ((y-image->extract_info.y) < (ssize_t) image->rows))
598 p=GetVirtualPixels(canvas_image,
599 canvas_image->extract_info.x,0,canvas_image->columns,1,
601 q=GetAuthenticPixels(image,0,y-image->extract_info.y,
602 image->columns,1,exception);
603 if ((p == (const Quantum *) NULL) || (q == (Quantum *) NULL))
605 for (x=0; x < (ssize_t) image->columns; x++)
607 SetPixelAlpha(image,GetPixelAlpha(canvas_image,p),q);
608 p+=GetPixelChannels(canvas_image);
609 q+=GetPixelChannels(image);
611 if (SyncAuthenticPixels(image,exception) == MagickFalse)
614 stream=ReadBlobStream(image,length,pixels,&count);
616 if (image->previous == (Image *) NULL)
618 status=SetImageProgress(image,LoadImageTag,5,6);
619 if (status == MagickFalse)
623 if (image->previous == (Image *) NULL)
625 status=SetImageProgress(image,LoadImageTag,6,6);
626 if (status == MagickFalse)
631 case PartitionInterlace:
634 Partition interlacing: RRRRRR..., GGGGGG..., BBBBBB...
636 AppendImageFormat("R",image->filename);
637 status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
638 if (status == MagickFalse)
640 if (DiscardBlobBytes(image,(MagickSizeType) image->offset) == MagickFalse)
643 ThrowFileException(exception,CorruptImageError,
644 "UnexpectedEndOfFile",image->filename);
647 length=GetQuantumExtent(canvas_image,quantum_info,RedQuantum);
648 for (i=0; i < (ssize_t) scene; i++)
650 for (y=0; y < (ssize_t) image->extract_info.height; y++)
652 stream=ReadBlobStream(image,length,pixels,&count);
653 if (count != (ssize_t) length)
656 if (count != (ssize_t) length)
659 stream=ReadBlobStream(image,length,pixels,&count);
660 for (y=0; y < (ssize_t) image->extract_info.height; y++)
662 register const Quantum
671 if (count != (ssize_t) length)
674 ThrowFileException(exception,CorruptImageError,
675 "UnexpectedEndOfFile",image->filename);
678 q=GetAuthenticPixels(canvas_image,0,0,canvas_image->columns,1,
680 if (q == (Quantum *) NULL)
682 length=ImportQuantumPixels(canvas_image,(CacheView *) NULL,
683 quantum_info,RedQuantum,stream,exception);
684 if (SyncAuthenticPixels(canvas_image,exception) == MagickFalse)
686 if (((y-image->extract_info.y) >= 0) &&
687 ((y-image->extract_info.y) < (ssize_t) image->rows))
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))
695 for (x=0; x < (ssize_t) image->columns; x++)
697 SetPixelRed(image,GetPixelRed(canvas_image,p),q);
698 p+=GetPixelChannels(canvas_image);
699 q+=GetPixelChannels(image);
701 if (SyncAuthenticPixels(image,exception) == MagickFalse)
704 stream=ReadBlobStream(image,length,pixels,&count);
706 if (image->previous == (Image *) NULL)
708 status=SetImageProgress(image,LoadImageTag,1,5);
709 if (status == MagickFalse)
712 (void) CloseBlob(image);
713 AppendImageFormat("G",image->filename);
714 status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
715 if (status == MagickFalse)
717 length=GetQuantumExtent(canvas_image,quantum_info,GreenQuantum);
718 for (i=0; i < (ssize_t) scene; i++)
720 for (y=0; y < (ssize_t) image->extract_info.height; y++)
722 stream=ReadBlobStream(image,length,pixels,&count);
723 if (count != (ssize_t) length)
726 if (count != (ssize_t) length)
729 stream=ReadBlobStream(image,length,pixels,&count);
730 for (y=0; y < (ssize_t) image->extract_info.height; y++)
732 register const Quantum
741 if (count != (ssize_t) length)
744 ThrowFileException(exception,CorruptImageError,
745 "UnexpectedEndOfFile",image->filename);
748 q=GetAuthenticPixels(canvas_image,0,0,canvas_image->columns,1,
750 if (q == (Quantum *) NULL)
752 length=ImportQuantumPixels(canvas_image,(CacheView *) NULL,
753 quantum_info,GreenQuantum,stream,exception);
754 if (SyncAuthenticPixels(canvas_image,exception) == MagickFalse)
756 if (((y-image->extract_info.y) >= 0) &&
757 ((y-image->extract_info.y) < (ssize_t) image->rows))
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))
765 for (x=0; x < (ssize_t) image->columns; x++)
767 SetPixelGreen(image,GetPixelGreen(canvas_image,p),q);
768 p+=GetPixelChannels(canvas_image);
769 q+=GetPixelChannels(image);
771 if (SyncAuthenticPixels(image,exception) == MagickFalse)
774 stream=ReadBlobStream(image,length,pixels,&count);
776 if (image->previous == (Image *) NULL)
778 status=SetImageProgress(image,LoadImageTag,2,5);
779 if (status == MagickFalse)
782 (void) CloseBlob(image);
783 AppendImageFormat("B",image->filename);
784 status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
785 if (status == MagickFalse)
787 length=GetQuantumExtent(canvas_image,quantum_info,BlueQuantum);
788 for (i=0; i < (ssize_t) scene; i++)
790 for (y=0; y < (ssize_t) image->extract_info.height; y++)
792 stream=ReadBlobStream(image,length,pixels,&count);
793 if (count != (ssize_t) length)
796 if (count != (ssize_t) length)
799 stream=ReadBlobStream(image,length,pixels,&count);
800 for (y=0; y < (ssize_t) image->extract_info.height; y++)
802 register const Quantum
811 if (count != (ssize_t) length)
814 ThrowFileException(exception,CorruptImageError,
815 "UnexpectedEndOfFile",image->filename);
818 q=GetAuthenticPixels(canvas_image,0,0,canvas_image->columns,1,
820 if (q == (Quantum *) NULL)
822 length=ImportQuantumPixels(canvas_image,(CacheView *) NULL,
823 quantum_info,BlueQuantum,stream,exception);
824 if (SyncAuthenticPixels(canvas_image,exception) == MagickFalse)
826 if (((y-image->extract_info.y) >= 0) &&
827 ((y-image->extract_info.y) < (ssize_t) image->rows))
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))
835 for (x=0; x < (ssize_t) image->columns; x++)
837 SetPixelBlue(image,GetPixelBlue(canvas_image,p),q);
838 p+=GetPixelChannels(canvas_image);
839 q+=GetPixelChannels(image);
841 if (SyncAuthenticPixels(image,exception) == MagickFalse)
844 stream=ReadBlobStream(image,length,pixels,&count);
846 if (image->previous == (Image *) NULL)
848 status=SetImageProgress(image,LoadImageTag,3,5);
849 if (status == MagickFalse)
852 if (image->alpha_trait != UndefinedPixelTrait)
854 (void) CloseBlob(image);
855 AppendImageFormat("A",image->filename);
856 status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
857 if (status == MagickFalse)
859 length=GetQuantumExtent(canvas_image,quantum_info,AlphaQuantum);
860 for (i=0; i < (ssize_t) scene; i++)
862 for (y=0; y < (ssize_t) image->extract_info.height; y++)
864 stream=ReadBlobStream(image,length,pixels,&count);
865 if (count != (ssize_t) length)
868 if (count != (ssize_t) length)
871 stream=ReadBlobStream(image,length,pixels,&count);
872 for (y=0; y < (ssize_t) image->extract_info.height; y++)
874 register const Quantum
883 if (count != (ssize_t) length)
886 ThrowFileException(exception,CorruptImageError,
887 "UnexpectedEndOfFile",image->filename);
890 q=GetAuthenticPixels(canvas_image,0,0,canvas_image->columns,1,
892 if (q == (Quantum *) NULL)
894 length=ImportQuantumPixels(canvas_image,(CacheView *) NULL,
895 quantum_info,BlueQuantum,stream,exception);
896 if (SyncAuthenticPixels(canvas_image,exception) == MagickFalse)
898 if (((y-image->extract_info.y) >= 0) &&
899 ((y-image->extract_info.y) < (ssize_t) image->rows))
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))
907 for (x=0; x < (ssize_t) image->columns; x++)
909 SetPixelAlpha(image,GetPixelAlpha(canvas_image,p),q);
910 p+=GetPixelChannels(canvas_image);
911 q+=GetPixelChannels(image);
913 if (SyncAuthenticPixels(image,exception) == MagickFalse)
916 stream=ReadBlobStream(image,length,pixels,&count);
918 if (image->previous == (Image *) NULL)
920 status=SetImageProgress(image,LoadImageTag,4,5);
921 if (status == MagickFalse)
925 (void) CloseBlob(image);
926 if (image->previous == (Image *) NULL)
928 status=SetImageProgress(image,LoadImageTag,5,5);
929 if (status == MagickFalse)
935 if (status == MagickFalse)
937 SetQuantumImageType(image,quantum_type);
939 Proceed to next image.
941 if (image_info->number_scenes != 0)
942 if (image->scene >= (image_info->scene+image_info->number_scenes-1))
944 if (count == (ssize_t) length)
947 Allocate next image structure.
949 AcquireNextImage(image_info,image,exception);
950 if (GetNextImageInList(image) == (Image *) NULL)
955 image=SyncNextImageInList(image);
956 status=SetImageProgress(image,LoadImagesTag,TellBlob(image),
958 if (status == MagickFalse)
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));
972 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
976 % R e a d R G B 5 6 5 I m a g e %
980 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
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.
986 % The format of the ReadGRAYImage method is:
988 % Image *ReadGRAYImage(const ImageInfo *image_info,
989 % ExceptionInfo *exception)
991 % A description of each parameter follows:
993 % o image_info: the image info.
995 % o exception: return any errors or warnings in this structure.
998 static Image *ReadRGB565Image(const ImageInfo *image_info,
999 ExceptionInfo *exception)
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");
1044 if (image_info->interlace != PartitionInterlace)
1046 status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
1047 if (status == MagickFalse)
1049 image=DestroyImageList(image);
1050 return((Image *) NULL);
1052 if (DiscardBlobBytes(image,(MagickSizeType) image->offset) == MagickFalse)
1053 ThrowFileException(exception,CorruptImageError,"UnexpectedEndOfFile",
1057 Create virtual canvas to support cropping (i.e. image.rgb[100x100+10+20]).
1059 canvas_image=CloneImage(image,image->extract_info.width,1,MagickFalse,
1061 if(canvas_image == (Image *) NULL)
1062 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
1063 (void) SetImageVirtualPixelMethod(canvas_image,BlackVirtualPixelMethod,
1065 quantum_info=AcquireQuantumInfo(image_info,canvas_image);
1066 if (quantum_info == (QuantumInfo *) NULL)
1068 canvas_image=DestroyImage(canvas_image);
1069 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
1071 quantum_type=GrayQuantum;
1072 pixels=GetQuantumPixels(quantum_info);
1073 if (image_info->number_scenes != 0)
1074 while (image->scene < image_info->scene)
1080 length=GetQuantumExtent(canvas_image,quantum_info,quantum_type);
1081 for (y=0; y < (ssize_t) image->rows; y++)
1083 stream=ReadBlobStream(image,length,pixels,&count);
1084 if (count != (ssize_t) length)
1096 Read pixels to virtual canvas image then push to image.
1098 if ((image_info->ping != MagickFalse) && (image_info->number_scenes != 0))
1099 if (image->scene >= (image_info->scene+image_info->number_scenes-1))
1101 status=SetImageExtent(image,image->columns,image->rows,exception);
1102 if (status == MagickFalse)
1105 No interlacing: GGG...
1109 length=GetQuantumExtent(canvas_image,quantum_info,quantum_type);
1110 stream=ReadBlobStream(image,length,pixels,&count);
1112 for (y=0; y < (ssize_t) image->extract_info.height; y++)
1114 register const Quantum
1123 if (count != (ssize_t) length)
1126 ThrowFileException(exception,CorruptImageError,
1127 "UnexpectedEndOfFile",image->filename);
1130 q=GetAuthenticPixels(canvas_image,0,0,canvas_image->columns,1,exception);
1131 if (q == (Quantum *) NULL)
1133 length=ImportQuantumPixels(canvas_image,(CacheView *) NULL,
1134 quantum_info,quantum_type,stream,exception);
1135 if (SyncAuthenticPixels(canvas_image,exception) == MagickFalse)
1137 if (((y-image->extract_info.y) >= 0) &&
1138 ((y-image->extract_info.y) < (ssize_t) image->rows))
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))
1146 for (x=0; x < (ssize_t) image->columns; x++)
1151 pixel=(unsigned short) ScaleQuantumToShort(GetPixelGray(
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);
1159 if (SyncAuthenticPixels(image,exception) == MagickFalse)
1162 if (image->previous == (Image *) NULL)
1164 status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y,
1166 if (status == MagickFalse)
1169 stream=ReadBlobStream(image,length,pixels,&count);
1171 if (status == MagickFalse)
1173 SetQuantumImageType(image,quantum_type);
1175 Proceed to next image.
1177 if (image_info->number_scenes != 0)
1178 if (image->scene >= (image_info->scene+image_info->number_scenes-1))
1180 if (count == (ssize_t) length)
1183 Allocate next image structure.
1185 AcquireNextImage(image_info,image,exception);
1186 if (GetNextImageInList(image) == (Image *) NULL)
1191 image=SyncNextImageInList(image);
1192 status=SetImageProgress(image,LoadImagesTag,TellBlob(image),
1193 GetBlobSize(image));
1194 if (status == MagickFalse)
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));
1208 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1212 % R e g i s t e r R G B I m a g e %
1216 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
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.
1225 % The format of the RegisterRGBImage method is:
1227 % size_t RegisterRGBImage(void)
1230 ModuleExport size_t RegisterRGBImage(void)
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);
1266 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1270 % U n r e g i s t e r R G B I m a g e %
1274 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1276 % UnregisterRGBImage() removes format registrations made by the RGB module
1277 % from the list of supported formats.
1279 % The format of the UnregisterRGBImage method is:
1281 % UnregisterRGBImage(void)
1284 ModuleExport void UnregisterRGBImage(void)
1286 (void) UnregisterMagickInfo("RGBO");
1287 (void) UnregisterMagickInfo("RGBA");
1288 (void) UnregisterMagickInfo("RGB");
1292 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1296 % W r i t e R G B I m a g e %
1300 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1302 % WriteRGBImage() writes an image to a file in the RGB, RGBA, or RGBO
1303 % rasterfile format.
1305 % The format of the WriteRGBImage method is:
1307 % MagickBooleanType WriteRGBImage(const ImageInfo *image_info,
1308 % Image *image,ExceptionInfo *exception)
1310 % A description of each parameter follows.
1312 % o image_info: the image info.
1314 % o image: The image.
1316 % o exception: return any errors or warnings in this structure.
1319 static MagickBooleanType WriteRGBImage(const ImageInfo *image_info,
1320 Image *image,ExceptionInfo *exception)
1346 Allocate memory for pixels.
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)
1357 Open output image file.
1359 status=OpenBlob(image_info,image,WriteBinaryBlobMode,exception);
1360 if (status == MagickFalse)
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;
1369 imageListLength=GetImageListLength(image);
1373 Convert MIFF to RGB raster pixels.
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)
1389 No interlacing: RGBRGBRGBRGBRGBRGB...
1391 for (y=0; y < (ssize_t) image->rows; y++)
1393 register const Quantum
1396 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
1397 if (p == (const Quantum *) NULL)
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)
1404 if (image->previous == (Image *) NULL)
1406 status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
1408 if (status == MagickFalse)
1417 Line interlacing: RRR...GGG...BBB...RRR...GGG...BBB...
1419 for (y=0; y < (ssize_t) image->rows; y++)
1421 register const Quantum
1424 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
1425 if (p == (const Quantum *) NULL)
1427 length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1428 RedQuantum,pixels,exception);
1429 count=WriteBlob(image,length,pixels);
1430 if (count != (ssize_t) length)
1432 length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1433 GreenQuantum,pixels,exception);
1434 count=WriteBlob(image,length,pixels);
1435 if (count != (ssize_t) length)
1437 length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1438 BlueQuantum,pixels,exception);
1439 count=WriteBlob(image,length,pixels);
1440 if (count != (ssize_t) length)
1442 if (quantum_type == RGBAQuantum)
1444 length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1445 AlphaQuantum,pixels,exception);
1446 count=WriteBlob(image,length,pixels);
1447 if (count != (ssize_t) length)
1450 if (quantum_type == RGBOQuantum)
1452 length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1453 OpacityQuantum,pixels,exception);
1454 count=WriteBlob(image,length,pixels);
1455 if (count != (ssize_t) length)
1458 if (image->previous == (Image *) NULL)
1460 status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
1462 if (status == MagickFalse)
1468 case PlaneInterlace:
1471 Plane interlacing: RRRRRR...GGGGGG...BBBBBB...
1473 for (y=0; y < (ssize_t) image->rows; y++)
1475 register const Quantum
1478 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
1479 if (p == (const Quantum *) NULL)
1481 length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1482 RedQuantum,pixels,exception);
1483 count=WriteBlob(image,length,pixels);
1484 if (count != (ssize_t) length)
1487 if (image->previous == (Image *) NULL)
1489 status=SetImageProgress(image,SaveImageTag,1,6);
1490 if (status == MagickFalse)
1493 for (y=0; y < (ssize_t) image->rows; y++)
1495 register const Quantum
1498 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
1499 if (p == (const Quantum *) NULL)
1501 length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1502 GreenQuantum,pixels,exception);
1503 count=WriteBlob(image,length,pixels);
1504 if (count != (ssize_t) length)
1507 if (image->previous == (Image *) NULL)
1509 status=SetImageProgress(image,SaveImageTag,2,6);
1510 if (status == MagickFalse)
1513 for (y=0; y < (ssize_t) image->rows; y++)
1515 register const Quantum
1518 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
1519 if (p == (const Quantum *) NULL)
1521 length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1522 BlueQuantum,pixels,exception);
1523 count=WriteBlob(image,length,pixels);
1524 if (count != (ssize_t) length)
1527 if (image->previous == (Image *) NULL)
1529 status=SetImageProgress(image,SaveImageTag,3,6);
1530 if (status == MagickFalse)
1533 if (quantum_type == RGBAQuantum)
1535 for (y=0; y < (ssize_t) image->rows; y++)
1537 register const Quantum
1540 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
1541 if (p == (const Quantum *) NULL)
1543 length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1544 AlphaQuantum,pixels,exception);
1545 count=WriteBlob(image,length,pixels);
1546 if (count != (ssize_t) length)
1549 if (image->previous == (Image *) NULL)
1551 status=SetImageProgress(image,SaveImageTag,5,6);
1552 if (status == MagickFalse)
1556 if (image_info->interlace == PartitionInterlace)
1557 (void) CopyMagickString(image->filename,image_info->filename,
1559 if (image->previous == (Image *) NULL)
1561 status=SetImageProgress(image,SaveImageTag,6,6);
1562 if (status == MagickFalse)
1567 case PartitionInterlace:
1570 Partition interlacing: RRRRRR..., GGGGGG..., BBBBBB...
1572 AppendImageFormat("R",image->filename);
1573 status=OpenBlob(image_info,image,scene == 0 ? WriteBinaryBlobMode :
1574 AppendBinaryBlobMode,exception);
1575 if (status == MagickFalse)
1577 for (y=0; y < (ssize_t) image->rows; y++)
1579 register const Quantum
1582 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
1583 if (p == (const Quantum *) NULL)
1585 length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1586 RedQuantum,pixels,exception);
1587 count=WriteBlob(image,length,pixels);
1588 if (count != (ssize_t) length)
1591 if (image->previous == (Image *) NULL)
1593 status=SetImageProgress(image,SaveImageTag,1,6);
1594 if (status == MagickFalse)
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)
1603 for (y=0; y < (ssize_t) image->rows; y++)
1605 register const Quantum
1608 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
1609 if (p == (const Quantum *) NULL)
1611 length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1612 GreenQuantum,pixels,exception);
1613 count=WriteBlob(image,length,pixels);
1614 if (count != (ssize_t) length)
1617 if (image->previous == (Image *) NULL)
1619 status=SetImageProgress(image,SaveImageTag,2,6);
1620 if (status == MagickFalse)
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)
1629 for (y=0; y < (ssize_t) image->rows; y++)
1631 register const Quantum
1634 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
1635 if (p == (const Quantum *) NULL)
1637 length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1638 BlueQuantum,pixels,exception);
1639 count=WriteBlob(image,length,pixels);
1640 if (count != (ssize_t) length)
1643 if (image->previous == (Image *) NULL)
1645 status=SetImageProgress(image,SaveImageTag,3,6);
1646 if (status == MagickFalse)
1649 if (quantum_type == RGBAQuantum)
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)
1657 for (y=0; y < (ssize_t) image->rows; y++)
1659 register const Quantum
1662 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
1663 if (p == (const Quantum *) NULL)
1665 length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1666 AlphaQuantum,pixels,exception);
1667 count=WriteBlob(image,length,pixels);
1668 if (count != (ssize_t) length)
1671 if (image->previous == (Image *) NULL)
1673 status=SetImageProgress(image,SaveImageTag,5,6);
1674 if (status == MagickFalse)
1678 (void) CloseBlob(image);
1679 (void) CopyMagickString(image->filename,image_info->filename,
1681 if (image->previous == (Image *) NULL)
1683 status=SetImageProgress(image,SaveImageTag,6,6);
1684 if (status == MagickFalse)
1690 quantum_info=DestroyQuantumInfo(quantum_info);
1691 if (GetNextImageInList(image) == (Image *) NULL)
1693 image=SyncNextImageInList(image);
1694 status=SetImageProgress(image,SaveImagesTag,scene++,imageListLength);
1695 if (status == MagickFalse)
1697 } while (image_info->adjoin != MagickFalse);
1698 (void) CloseBlob(image);