2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
13 % Read/Write Irix RGB Image Format %
20 % Copyright 1999-2015 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 "MagickCore/studio.h"
43 #include "MagickCore/attribute.h"
44 #include "MagickCore/blob.h"
45 #include "MagickCore/blob-private.h"
46 #include "MagickCore/cache.h"
47 #include "MagickCore/color.h"
48 #include "MagickCore/color-private.h"
49 #include "MagickCore/colormap.h"
50 #include "MagickCore/colorspace.h"
51 #include "MagickCore/colorspace-private.h"
52 #include "MagickCore/exception.h"
53 #include "MagickCore/exception-private.h"
54 #include "MagickCore/image.h"
55 #include "MagickCore/image-private.h"
56 #include "MagickCore/list.h"
57 #include "MagickCore/magick.h"
58 #include "MagickCore/memory_.h"
59 #include "MagickCore/monitor.h"
60 #include "MagickCore/monitor-private.h"
61 #include "MagickCore/pixel-accessor.h"
62 #include "MagickCore/property.h"
63 #include "MagickCore/quantum-private.h"
64 #include "MagickCore/static.h"
65 #include "MagickCore/string_.h"
66 #include "MagickCore/module.h"
69 Typedef declaractions.
71 typedef struct _SGIInfo
102 Forward declarations.
104 static MagickBooleanType
105 WriteSGIImage(const ImageInfo *,Image *,ExceptionInfo *);
107 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
115 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
117 % IsSGI() returns MagickTrue if the image format type, identified by the
118 % magick string, is SGI.
120 % The format of the IsSGI method is:
122 % MagickBooleanType IsSGI(const unsigned char *magick,const size_t length)
124 % A description of each parameter follows:
126 % o magick: compare image format pattern against these bytes.
128 % o length: Specifies the length of the magick string.
131 static MagickBooleanType IsSGI(const unsigned char *magick,const size_t length)
135 if (memcmp(magick,"\001\332",2) == 0)
141 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
145 % R e a d S G I I m a g e %
149 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
151 % ReadSGIImage() reads a SGI RGB image file and returns it. It
152 % allocates the memory necessary for the new Image structure and returns a
153 % pointer to the new image.
155 % The format of the ReadSGIImage method is:
157 % Image *ReadSGIImage(const ImageInfo *image_info,ExceptionInfo *exception)
159 % A description of each parameter follows:
161 % o image_info: the image info.
163 % o exception: return any errors or warnings in this structure.
167 static MagickBooleanType SGIDecode(const size_t bytes_per_pixel,
168 ssize_t number_packets,unsigned char *packets,ssize_t number_pixels,
169 unsigned char *pixels)
171 register unsigned char
183 if (bytes_per_pixel == 2)
185 for ( ; number_pixels > 0; )
187 if (number_packets-- == 0)
189 pixel=(size_t) (*p++) << 8;
191 count=(ssize_t) (pixel & 0x7f);
194 if (count > (ssize_t) number_pixels)
196 number_pixels-=count;
197 if ((pixel & 0x80) != 0)
198 for ( ; count != 0; count--)
200 if (number_packets-- == 0)
208 pixel=(size_t) (*p++) << 8;
210 for ( ; count != 0; count--)
212 if (number_packets-- == 0)
214 *q=(unsigned char) (pixel >> 8);
215 *(q+1)=(unsigned char) pixel;
222 for ( ; number_pixels > 0; )
224 if (number_packets-- == 0)
226 pixel=(size_t) (*p++);
227 count=(ssize_t) (pixel & 0x7f);
230 if (count > (ssize_t) number_pixels)
232 number_pixels-=count;
233 if ((pixel & 0x80) != 0)
234 for ( ; count != 0; count--)
236 if (number_packets-- == 0)
243 if (number_packets-- == 0)
245 pixel=(size_t) (*p++);
246 for ( ; count != 0; count--)
248 *q=(unsigned char) pixel;
256 static Image *ReadSGIImage(const ImageInfo *image_info,ExceptionInfo *exception)
277 register unsigned char
298 assert(image_info != (const ImageInfo *) NULL);
299 assert(image_info->signature == MagickSignature);
300 if (image_info->debug != MagickFalse)
301 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
302 image_info->filename);
303 assert(exception != (ExceptionInfo *) NULL);
304 assert(exception->signature == MagickSignature);
305 image=AcquireImage(image_info,exception);
306 status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
307 if (status == MagickFalse)
309 image=DestroyImageList(image);
310 return((Image *) NULL);
313 Read SGI raster header.
315 iris_info.magic=ReadBlobMSBShort(image);
319 Verify SGI identifier.
321 if (iris_info.magic != 0x01DA)
322 ThrowReaderException(CorruptImageError,"ImproperImageHeader");
323 iris_info.storage=(unsigned char) ReadBlobByte(image);
324 switch (iris_info.storage)
326 case 0x00: image->compression=NoCompression; break;
327 case 0x01: image->compression=RLECompression; break;
329 ThrowReaderException(CorruptImageError,"ImproperImageHeader");
331 iris_info.bytes_per_pixel=(unsigned char) ReadBlobByte(image);
332 if ((iris_info.bytes_per_pixel == 0) || (iris_info.bytes_per_pixel > 2))
333 ThrowReaderException(CorruptImageError,"ImproperImageHeader");
334 iris_info.dimension=ReadBlobMSBShort(image);
335 iris_info.columns=ReadBlobMSBShort(image);
336 iris_info.rows=ReadBlobMSBShort(image);
337 iris_info.depth=ReadBlobMSBShort(image);
338 if ((iris_info.depth == 0) || (iris_info.depth > 4))
339 ThrowReaderException(CorruptImageError,"ImproperImageHeader");
340 iris_info.minimum_value=ReadBlobMSBLong(image);
341 iris_info.maximum_value=ReadBlobMSBLong(image);
342 iris_info.sans=ReadBlobMSBLong(image);
343 (void) ReadBlob(image,sizeof(iris_info.name),(unsigned char *)
345 iris_info.name[sizeof(iris_info.name)-1]='\0';
346 if (*iris_info.name != '\0')
347 (void) SetImageProperty(image,"label",iris_info.name,exception);
348 iris_info.pixel_format=ReadBlobMSBLong(image);
349 if (iris_info.pixel_format != 0)
350 ThrowReaderException(CorruptImageError,"ImproperImageHeader");
351 count=ReadBlob(image,sizeof(iris_info.filler),iris_info.filler);
353 image->columns=iris_info.columns;
354 image->rows=iris_info.rows;
355 image->depth=(size_t) MagickMin(iris_info.depth,MAGICKCORE_QUANTUM_DEPTH);
356 if (iris_info.pixel_format == 0)
357 image->depth=(size_t) MagickMin((size_t) 8*
358 iris_info.bytes_per_pixel,MAGICKCORE_QUANTUM_DEPTH);
359 if (iris_info.depth < 3)
361 image->storage_class=PseudoClass;
362 image->colors=iris_info.bytes_per_pixel > 1 ? 65535 : 256;
364 if ((image_info->ping != MagickFalse) && (image_info->number_scenes != 0))
365 if (image->scene >= (image_info->scene+image_info->number_scenes-1))
367 status=SetImageExtent(image,image->columns,image->rows,exception);
368 if (status == MagickFalse)
369 return(DestroyImageList(image));
373 bytes_per_pixel=(size_t) iris_info.bytes_per_pixel;
374 number_pixels=(MagickSizeType) iris_info.columns*iris_info.rows;
375 if ((4*bytes_per_pixel*number_pixels) != ((MagickSizeType) (size_t)
376 (4*bytes_per_pixel*number_pixels)))
377 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
378 pixel_info=AcquireVirtualMemory(iris_info.columns,iris_info.rows*4*
379 bytes_per_pixel*sizeof(*pixels));
380 if (pixel_info == (MemoryInfo *) NULL)
381 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
382 pixels=(unsigned char *) GetVirtualMemoryBlob(pixel_info);
383 if ((int) iris_info.storage != 0x01)
389 Read standard image format.
391 scanline=(unsigned char *) AcquireQuantumMemory(iris_info.columns,
392 bytes_per_pixel*sizeof(*scanline));
393 if (scanline == (unsigned char *) NULL)
394 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
395 for (z=0; z < (ssize_t) iris_info.depth; z++)
397 p=pixels+bytes_per_pixel*z;
398 for (y=0; y < (ssize_t) iris_info.rows; y++)
400 count=ReadBlob(image,bytes_per_pixel*iris_info.columns,scanline);
401 if (EOFBlob(image) != MagickFalse)
403 if (bytes_per_pixel == 2)
404 for (x=0; x < (ssize_t) iris_info.columns; x++)
407 *(p+1)=scanline[2*x+1];
411 for (x=0; x < (ssize_t) iris_info.columns; x++)
418 scanline=(unsigned char *) RelinquishMagickMemory(scanline);
439 Read runlength-encoded image format.
441 offsets=(ssize_t *) AcquireQuantumMemory((size_t) iris_info.rows,
442 iris_info.depth*sizeof(*offsets));
443 runlength=(size_t *) AcquireQuantumMemory(iris_info.rows,
444 iris_info.depth*sizeof(*runlength));
445 packet_info=AcquireVirtualMemory((size_t) iris_info.columns+10UL,4UL*
447 if ((offsets == (ssize_t *) NULL) ||
448 (runlength == (size_t *) NULL) ||
449 (packet_info == (MemoryInfo *) NULL))
451 if (offsets == (ssize_t *) NULL)
452 offsets=(ssize_t *) RelinquishMagickMemory(offsets);
453 if (runlength == (size_t *) NULL)
454 runlength=(size_t *) RelinquishMagickMemory(runlength);
455 if (packet_info == (MemoryInfo *) NULL)
456 packet_info=RelinquishVirtualMemory(packet_info);
457 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
459 packets=(unsigned char *) GetVirtualMemoryBlob(packet_info);
460 for (i=0; i < (ssize_t) (iris_info.rows*iris_info.depth); i++)
461 offsets[i]=(int) ReadBlobMSBLong(image);
462 for (i=0; i < (ssize_t) (iris_info.rows*iris_info.depth); i++)
464 runlength[i]=ReadBlobMSBLong(image);
465 if (runlength[i] > (4*(size_t) iris_info.columns+10))
466 ThrowReaderException(CorruptImageError,"ImproperImageHeader");
473 for (y=0; ((y < (ssize_t) iris_info.rows) && (data_order == 0)); y++)
474 for (z=0; ((z < (ssize_t) iris_info.depth) && (data_order == 0)); z++)
476 if (offsets[y+z*iris_info.rows] < offset)
478 offset=offsets[y+z*iris_info.rows];
480 offset=(ssize_t) TellBlob(image);
483 for (z=0; z < (ssize_t) iris_info.depth; z++)
486 for (y=0; y < (ssize_t) iris_info.rows; y++)
488 if (offset != offsets[y+z*iris_info.rows])
490 offset=offsets[y+z*iris_info.rows];
491 offset=(ssize_t) SeekBlob(image,(ssize_t) offset,SEEK_SET);
493 count=ReadBlob(image,(size_t) runlength[y+z*iris_info.rows],
495 if (EOFBlob(image) != MagickFalse)
497 offset+=(ssize_t) runlength[y+z*iris_info.rows];
498 status=SGIDecode(bytes_per_pixel,(ssize_t)
499 (runlength[y+z*iris_info.rows]/bytes_per_pixel),packets,
500 1L*iris_info.columns,p+bytes_per_pixel*z);
501 if (status == MagickFalse)
502 ThrowReaderException(CorruptImageError,"ImproperImageHeader");
503 p+=(iris_info.columns*4*bytes_per_pixel);
512 position=TellBlob(image);
514 for (y=0; y < (ssize_t) iris_info.rows; y++)
516 for (z=0; z < (ssize_t) iris_info.depth; z++)
518 if (offset != offsets[y+z*iris_info.rows])
520 offset=offsets[y+z*iris_info.rows];
521 offset=(ssize_t) SeekBlob(image,(ssize_t) offset,SEEK_SET);
523 count=ReadBlob(image,(size_t) runlength[y+z*iris_info.rows],
525 if (EOFBlob(image) != MagickFalse)
527 offset+=(ssize_t) runlength[y+z*iris_info.rows];
528 status=SGIDecode(bytes_per_pixel,(ssize_t)
529 (runlength[y+z*iris_info.rows]/bytes_per_pixel),packets,
530 1L*iris_info.columns,p+bytes_per_pixel*z);
531 if (status == MagickFalse)
532 ThrowReaderException(CorruptImageError,"ImproperImageHeader");
534 p+=(iris_info.columns*4*bytes_per_pixel);
536 offset=(ssize_t) SeekBlob(image,position,SEEK_SET);
538 packet_info=RelinquishVirtualMemory(packet_info);
539 runlength=(size_t *) RelinquishMagickMemory(runlength);
540 offsets=(ssize_t *) RelinquishMagickMemory(offsets);
543 Initialize image structure.
545 image->alpha_trait=iris_info.depth == 4 ? BlendPixelTrait :
547 image->columns=iris_info.columns;
548 image->rows=iris_info.rows;
550 Convert SGI raster image to pixel packets.
552 if (image->storage_class == DirectClass)
555 Convert SGI image to DirectClass pixel packets.
557 if (bytes_per_pixel == 2)
559 for (y=0; y < (ssize_t) image->rows; y++)
561 p=pixels+(image->rows-y-1)*8*image->columns;
562 q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
563 if (q == (Quantum *) NULL)
565 for (x=0; x < (ssize_t) image->columns; x++)
567 SetPixelRed(image,ScaleShortToQuantum((unsigned short)
568 ((*(p+0) << 8) | (*(p+1)))),q);
569 SetPixelGreen(image,ScaleShortToQuantum((unsigned short)
570 ((*(p+2) << 8) | (*(p+3)))),q);
571 SetPixelBlue(image,ScaleShortToQuantum((unsigned short)
572 ((*(p+4) << 8) | (*(p+5)))),q);
573 SetPixelAlpha(image,OpaqueAlpha,q);
574 if (image->alpha_trait != UndefinedPixelTrait)
575 SetPixelAlpha(image,ScaleShortToQuantum((unsigned short)
576 ((*(p+6) << 8) | (*(p+7)))),q);
578 q+=GetPixelChannels(image);
580 if (SyncAuthenticPixels(image,exception) == MagickFalse)
582 if (image->previous == (Image *) NULL)
584 status=SetImageProgress(image,LoadImageTag,(MagickOffsetType)
586 if (status == MagickFalse)
592 for (y=0; y < (ssize_t) image->rows; y++)
594 p=pixels+(image->rows-y-1)*4*image->columns;
595 q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
596 if (q == (Quantum *) NULL)
598 for (x=0; x < (ssize_t) image->columns; x++)
600 SetPixelRed(image,ScaleCharToQuantum(*p),q);
601 SetPixelGreen(image,ScaleCharToQuantum(*(p+1)),q);
602 SetPixelBlue(image,ScaleCharToQuantum(*(p+2)),q);
603 SetPixelAlpha(image,OpaqueAlpha,q);
604 if (image->alpha_trait != UndefinedPixelTrait)
605 SetPixelAlpha(image,ScaleCharToQuantum(*(p+3)),q);
607 q+=GetPixelChannels(image);
609 if (SyncAuthenticPixels(image,exception) == MagickFalse)
611 if (image->previous == (Image *) NULL)
613 status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y,
615 if (status == MagickFalse)
623 Create grayscale map.
625 if (AcquireImageColormap(image,image->colors,exception) == MagickFalse)
626 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
628 Convert SGI image to PseudoClass pixel packets.
630 if (bytes_per_pixel == 2)
632 for (y=0; y < (ssize_t) image->rows; y++)
634 p=pixels+(image->rows-y-1)*8*image->columns;
635 q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
636 if (q == (Quantum *) NULL)
638 for (x=0; x < (ssize_t) image->columns; x++)
642 SetPixelIndex(image,quantum,q);
644 q+=GetPixelChannels(image);
646 if (SyncAuthenticPixels(image,exception) == MagickFalse)
648 if (image->previous == (Image *) NULL)
650 status=SetImageProgress(image,LoadImageTag,(MagickOffsetType)
652 if (status == MagickFalse)
658 for (y=0; y < (ssize_t) image->rows; y++)
660 p=pixels+(image->rows-y-1)*4*image->columns;
661 q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
662 if (q == (Quantum *) NULL)
664 for (x=0; x < (ssize_t) image->columns; x++)
666 SetPixelIndex(image,*p,q);
668 q+=GetPixelChannels(image);
670 if (SyncAuthenticPixels(image,exception) == MagickFalse)
672 if (image->previous == (Image *) NULL)
674 status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y,
676 if (status == MagickFalse)
680 (void) SyncImage(image,exception);
682 pixel_info=RelinquishVirtualMemory(pixel_info);
683 if (EOFBlob(image) != MagickFalse)
685 ThrowFileException(exception,CorruptImageError,"UnexpectedEndOfFile",
690 Proceed to next image.
692 if (image_info->number_scenes != 0)
693 if (image->scene >= (image_info->scene+image_info->number_scenes-1))
695 iris_info.magic=ReadBlobMSBShort(image);
696 if (iris_info.magic == 0x01DA)
699 Allocate next image structure.
701 AcquireNextImage(image_info,image,exception);
702 if (GetNextImageInList(image) == (Image *) NULL)
704 image=DestroyImageList(image);
705 return((Image *) NULL);
707 image=SyncNextImageInList(image);
708 status=SetImageProgress(image,LoadImagesTag,TellBlob(image),
710 if (status == MagickFalse)
713 } while (iris_info.magic == 0x01DA);
714 (void) CloseBlob(image);
715 return(GetFirstImageInList(image));
719 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
723 % R e g i s t e r S G I I m a g e %
727 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
729 % RegisterSGIImage() adds properties for the SGI image format to
730 % the list of supported formats. The properties include the image format
731 % tag, a method to read and/or write the format, whether the format
732 % supports the saving of more than one frame to the same file or blob,
733 % whether the format supports native in-memory I/O, and a brief
734 % description of the format.
736 % The format of the RegisterSGIImage method is:
738 % size_t RegisterSGIImage(void)
741 ModuleExport size_t RegisterSGIImage(void)
746 entry=AcquireMagickInfo("SGI","SGI","Irix RGB image");
747 entry->decoder=(DecodeImageHandler *) ReadSGIImage;
748 entry->encoder=(EncodeImageHandler *) WriteSGIImage;
749 entry->magick=(IsImageFormatHandler *) IsSGI;
750 entry->flags|=CoderSeekableStreamFlag;
751 (void) RegisterMagickInfo(entry);
752 return(MagickImageCoderSignature);
756 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
760 % U n r e g i s t e r S G I I m a g e %
764 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
766 % UnregisterSGIImage() removes format registrations made by the
767 % SGI module from the list of supported formats.
769 % The format of the UnregisterSGIImage method is:
771 % UnregisterSGIImage(void)
774 ModuleExport void UnregisterSGIImage(void)
776 (void) UnregisterMagickInfo("SGI");
780 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
784 % W r i t e S G I I m a g e %
788 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
790 % WriteSGIImage() writes an image in SGI RGB encoded image format.
792 % The format of the WriteSGIImage method is:
794 % MagickBooleanType WriteSGIImage(const ImageInfo *image_info,
795 % Image *image,ExceptionInfo *exception)
797 % A description of each parameter follows.
799 % o image_info: the image info.
801 % o image: The image.
803 % o exception: return any errors or warnings in this structure.
807 static size_t SGIEncode(unsigned char *pixels,size_t length,
808 unsigned char *packets)
813 register unsigned char
828 while ((p < limit) && ((*(p-8) != *(p-4)) || (*(p-4) != *p)))
831 length=(size_t) (p-mark) >> 2;
834 runlength=(short) (length > 126 ? 126 : length);
836 *q++=(unsigned char) (0x80 | runlength);
837 for ( ; runlength > 0; runlength--)
845 while ((p < limit) && (*p == *mark))
847 length=(size_t) (p-mark) >> 2;
850 runlength=(short) (length > 126 ? 126 : length);
852 *q++=(unsigned char) runlength;
857 return((size_t) (q-packets));
860 static MagickBooleanType WriteSGIImage(const ImageInfo *image_info,Image *image,
861 ExceptionInfo *exception)
884 register const Quantum
891 register unsigned char
903 Open output image file.
905 assert(image_info != (const ImageInfo *) NULL);
906 assert(image_info->signature == MagickSignature);
907 assert(image != (Image *) NULL);
908 assert(image->signature == MagickSignature);
909 if (image->debug != MagickFalse)
910 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
911 if ((image->columns > 65535UL) || (image->rows > 65535UL))
912 ThrowWriterException(ImageError,"WidthOrHeightExceedsLimit");
913 assert(exception != (ExceptionInfo *) NULL);
914 assert(exception->signature == MagickSignature);
915 status=OpenBlob(image_info,image,WriteBinaryBlobMode,exception);
916 if (status == MagickFalse)
922 Initialize SGI raster file header.
924 (void) TransformImageColorspace(image,sRGBColorspace,exception);
925 (void) ResetMagickMemory(&iris_info,0,sizeof(iris_info));
926 iris_info.magic=0x01DA;
927 compression=image->compression;
928 if (image_info->compression != UndefinedCompression)
929 compression=image_info->compression;
930 if (image->depth > 8)
931 compression=NoCompression;
932 if (compression == NoCompression)
933 iris_info.storage=(unsigned char) 0x00;
935 iris_info.storage=(unsigned char) 0x01;
936 iris_info.bytes_per_pixel=(unsigned char) (image->depth > 8 ? 2 : 1);
937 iris_info.dimension=3;
938 iris_info.columns=(unsigned short) image->columns;
939 iris_info.rows=(unsigned short) image->rows;
940 if (image->alpha_trait != UndefinedPixelTrait)
944 if ((image_info->type != TrueColorType) &&
945 (SetImageGray(image,exception) != MagickFalse))
947 iris_info.dimension=2;
953 iris_info.minimum_value=0;
954 iris_info.maximum_value=(size_t) (image->depth <= 8 ?
955 1UL*ScaleQuantumToChar(QuantumRange) :
956 1UL*ScaleQuantumToShort(QuantumRange));
960 (void) WriteBlobMSBShort(image,iris_info.magic);
961 (void) WriteBlobByte(image,iris_info.storage);
962 (void) WriteBlobByte(image,iris_info.bytes_per_pixel);
963 (void) WriteBlobMSBShort(image,iris_info.dimension);
964 (void) WriteBlobMSBShort(image,iris_info.columns);
965 (void) WriteBlobMSBShort(image,iris_info.rows);
966 (void) WriteBlobMSBShort(image,iris_info.depth);
967 (void) WriteBlobMSBLong(image,(unsigned int) iris_info.minimum_value);
968 (void) WriteBlobMSBLong(image,(unsigned int) iris_info.maximum_value);
969 (void) WriteBlobMSBLong(image,(unsigned int) iris_info.sans);
970 value=GetImageProperty(image,"label",exception);
971 if (value != (const char *) NULL)
972 (void) CopyMagickString(iris_info.name,value,sizeof(iris_info.name));
973 (void) WriteBlob(image,sizeof(iris_info.name),(unsigned char *)
975 (void) WriteBlobMSBLong(image,(unsigned int) iris_info.pixel_format);
976 (void) WriteBlob(image,sizeof(iris_info.filler),iris_info.filler);
980 number_pixels=(MagickSizeType) image->columns*image->rows;
981 if ((4*iris_info.bytes_per_pixel*number_pixels) !=
982 ((MagickSizeType) (size_t) (4*iris_info.bytes_per_pixel*number_pixels)))
983 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
984 pixel_info=AcquireVirtualMemory((size_t) number_pixels,4*
985 iris_info.bytes_per_pixel*sizeof(*pixels));
986 if (pixel_info == (MemoryInfo *) NULL)
987 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
988 pixels=(unsigned char *) GetVirtualMemoryBlob(pixel_info);
990 Convert image pixels to uncompressed SGI pixels.
992 for (y=0; y < (ssize_t) image->rows; y++)
994 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
995 if (p == (const Quantum *) NULL)
997 if (image->depth <= 8)
998 for (x=0; x < (ssize_t) image->columns; x++)
1000 register unsigned char
1003 q=(unsigned char *) pixels;
1004 q+=((iris_info.rows-1)-y)*(4*iris_info.columns)+4*x;
1005 *q++=ScaleQuantumToChar(GetPixelRed(image,p));
1006 *q++=ScaleQuantumToChar(GetPixelGreen(image,p));
1007 *q++=ScaleQuantumToChar(GetPixelBlue(image,p));
1008 *q++=ScaleQuantumToChar(GetPixelAlpha(image,p));
1009 p+=GetPixelChannels(image);
1012 for (x=0; x < (ssize_t) image->columns; x++)
1014 register unsigned short
1017 q=(unsigned short *) pixels;
1018 q+=((iris_info.rows-1)-y)*(4*iris_info.columns)+4*x;
1019 *q++=ScaleQuantumToShort(GetPixelRed(image,p));
1020 *q++=ScaleQuantumToShort(GetPixelGreen(image,p));
1021 *q++=ScaleQuantumToShort(GetPixelBlue(image,p));
1022 *q++=ScaleQuantumToShort(GetPixelAlpha(image,p));
1023 p+=GetPixelChannels(image);
1025 if (image->previous == (Image *) NULL)
1027 status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
1029 if (status == MagickFalse)
1033 switch (compression)
1038 Write uncompressed SGI pixels.
1040 for (z=0; z < (ssize_t) iris_info.depth; z++)
1042 for (y=0; y < (ssize_t) iris_info.rows; y++)
1044 if (image->depth <= 8)
1045 for (x=0; x < (ssize_t) iris_info.columns; x++)
1047 register unsigned char
1050 q=(unsigned char *) pixels;
1051 q+=y*(4*iris_info.columns)+4*x+z;
1052 (void) WriteBlobByte(image,*q);
1055 for (x=0; x < (ssize_t) iris_info.columns; x++)
1057 register unsigned short
1060 q=(unsigned short *) pixels;
1061 q+=y*(4*iris_info.columns)+4*x+z;
1062 (void) WriteBlobMSBShort(image,*q);
1083 Convert SGI uncompressed pixels.
1085 offsets=(ssize_t *) AcquireQuantumMemory(iris_info.rows,
1086 iris_info.depth*sizeof(*offsets));
1087 runlength=(size_t *) AcquireQuantumMemory(iris_info.rows,
1088 iris_info.depth*sizeof(*runlength));
1089 packet_info=AcquireVirtualMemory((2*(size_t) iris_info.columns+10)*
1090 image->rows,4*sizeof(*packets));
1091 if ((offsets == (ssize_t *) NULL) ||
1092 (runlength == (size_t *) NULL) ||
1093 (packet_info == (MemoryInfo *) NULL))
1095 if (offsets != (ssize_t *) NULL)
1096 offsets=(ssize_t *) RelinquishMagickMemory(offsets);
1097 if (runlength != (size_t *) NULL)
1098 runlength=(size_t *) RelinquishMagickMemory(runlength);
1099 if (packet_info != (MemoryInfo *) NULL)
1100 packet_info=RelinquishVirtualMemory(packet_info);
1101 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
1103 packets=(unsigned char *) GetVirtualMemoryBlob(packet_info);
1104 offset=512+4*2*((ssize_t) iris_info.rows*iris_info.depth);
1107 for (y=0; y < (ssize_t) iris_info.rows; y++)
1109 for (z=0; z < (ssize_t) iris_info.depth; z++)
1111 length=SGIEncode(q+z,(size_t) iris_info.columns,packets+
1113 number_packets+=length;
1114 offsets[y+z*iris_info.rows]=offset;
1115 runlength[y+z*iris_info.rows]=(size_t) length;
1116 offset+=(ssize_t) length;
1118 q+=(iris_info.columns*4);
1121 Write out line start and length tables and runlength-encoded pixels.
1123 for (i=0; i < (ssize_t) (iris_info.rows*iris_info.depth); i++)
1124 (void) WriteBlobMSBLong(image,(unsigned int) offsets[i]);
1125 for (i=0; i < (ssize_t) (iris_info.rows*iris_info.depth); i++)
1126 (void) WriteBlobMSBLong(image,(unsigned int) runlength[i]);
1127 (void) WriteBlob(image,number_packets,packets);
1129 Relinquish resources.
1131 offsets=(ssize_t *) RelinquishMagickMemory(offsets);
1132 runlength=(size_t *) RelinquishMagickMemory(runlength);
1133 packet_info=RelinquishVirtualMemory(packet_info);
1137 pixel_info=RelinquishVirtualMemory(pixel_info);
1138 if (GetNextImageInList(image) == (Image *) NULL)
1140 image=SyncNextImageInList(image);
1141 status=SetImageProgress(image,SaveImagesTag,scene++,
1142 GetImageListLength(image));
1143 if (status == MagickFalse)
1145 } while (image_info->adjoin != MagickFalse);
1146 (void) CloseBlob(image);