| cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 1 | /* | 
 | 2 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | 
 | 3 | %                                                                             % | 
 | 4 | %                                                                             % | 
 | 5 | %                                                                             % | 
 | 6 | %                            SSSSS  U   U  N   N                              % | 
 | 7 | %                            SS     U   U  NN  N                              % | 
 | 8 | %                             SSS   U   U  N N N                              % | 
 | 9 | %                               SS  U   U  N  NN                              % | 
 | 10 | %                            SSSSS   UUU   N   N                              % | 
 | 11 | %                                                                             % | 
 | 12 | %                                                                             % | 
 | 13 | %                    Read/Write Sun Rasterfile Image Format                   % | 
 | 14 | %                                                                             % | 
 | 15 | %                              Software Design                                % | 
| cristy | de984cd | 2013-12-01 14:49:27 +0000 | [diff] [blame] | 16 | %                                   Cristy                                    % | 
| cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 17 | %                                 July 1992                                   % | 
 | 18 | %                                                                             % | 
 | 19 | %                                                                             % | 
| cristy | b56bb24 | 2014-11-25 17:12:48 +0000 | [diff] [blame] | 20 | %  Copyright 1999-2015 ImageMagick Studio LLC, a non-profit organization      % | 
| cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 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 | %    http://www.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 | */ | 
| cristy | 4c08aed | 2011-07-01 19:47:50 +0000 | [diff] [blame] | 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" | 
| cristy | 510d06a | 2011-07-06 23:43:54 +0000 | [diff] [blame] | 51 | #include "MagickCore/colorspace-private.h" | 
| cristy | 4c08aed | 2011-07-01 19:47:50 +0000 | [diff] [blame] | 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/quantum-private.h" | 
 | 63 | #include "MagickCore/static.h" | 
 | 64 | #include "MagickCore/string_.h" | 
 | 65 | #include "MagickCore/module.h" | 
| cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 66 |  | 
 | 67 | /* | 
 | 68 |   Forward declarations. | 
 | 69 | */ | 
 | 70 | static MagickBooleanType | 
| cristy | 3a37efd | 2011-08-28 20:31:03 +0000 | [diff] [blame] | 71 |   WriteSUNImage(const ImageInfo *,Image *,ExceptionInfo *); | 
| cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 72 |  | 
 | 73 | /* | 
 | 74 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | 
 | 75 | %                                                                             % | 
 | 76 | %                                                                             % | 
 | 77 | %                                                                             % | 
 | 78 | %   I s S U N                                                                 % | 
 | 79 | %                                                                             % | 
 | 80 | %                                                                             % | 
 | 81 | %                                                                             % | 
 | 82 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | 
 | 83 | % | 
 | 84 | %  IsSUN() returns MagickTrue if the image format type, identified by the | 
 | 85 | %  magick string, is SUN. | 
 | 86 | % | 
 | 87 | %  The format of the IsSUN method is: | 
 | 88 | % | 
 | 89 | %      MagickBooleanType IsSUN(const unsigned char *magick,const size_t length) | 
 | 90 | % | 
 | 91 | %  A description of each parameter follows: | 
 | 92 | % | 
 | 93 | %    o magick: compare image format pattern against these bytes. | 
 | 94 | % | 
 | 95 | %    o length: Specifies the length of the magick string. | 
 | 96 | % | 
 | 97 | */ | 
 | 98 | static MagickBooleanType IsSUN(const unsigned char *magick,const size_t length) | 
 | 99 | { | 
 | 100 |   if (length < 4) | 
 | 101 |     return(MagickFalse); | 
 | 102 |   if (memcmp(magick,"\131\246\152\225",4) == 0) | 
 | 103 |     return(MagickTrue); | 
 | 104 |   return(MagickFalse); | 
 | 105 | } | 
 | 106 |  | 
 | 107 | /* | 
 | 108 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | 
 | 109 | %                                                                             % | 
 | 110 | %                                                                             % | 
 | 111 | %                                                                             % | 
 | 112 | %   D e c o d e I m a g e                                                     % | 
 | 113 | %                                                                             % | 
 | 114 | %                                                                             % | 
 | 115 | %                                                                             % | 
 | 116 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | 
 | 117 | % | 
 | 118 | %  DecodeImage unpacks the packed image pixels into  runlength-encoded pixel | 
 | 119 | %  packets. | 
 | 120 | % | 
 | 121 | %  The format of the DecodeImage method is: | 
 | 122 | % | 
 | 123 | %      MagickBooleanType DecodeImage(const unsigned char *compressed_pixels, | 
 | 124 | %        const size_t length,unsigned char *pixels) | 
 | 125 | % | 
 | 126 | %  A description of each parameter follows: | 
 | 127 | % | 
 | 128 | %    o compressed_pixels:  The address of a byte (8 bits) array of compressed | 
 | 129 | %      pixel data. | 
 | 130 | % | 
 | 131 | %    o length:  An integer value that is the total number of bytes of the | 
 | 132 | %      source image (as just read by ReadBlob) | 
 | 133 | % | 
 | 134 | %    o pixels:  The address of a byte (8 bits) array of pixel data created by | 
 | 135 | %      the uncompression process.  The number of bytes in this array | 
 | 136 | %      must be at least equal to the number columns times the number of rows | 
 | 137 | %      of the source pixels. | 
 | 138 | % | 
 | 139 | */ | 
 | 140 | static MagickBooleanType DecodeImage(const unsigned char *compressed_pixels, | 
 | 141 |   const size_t length,unsigned char *pixels,size_t maxpixels) | 
 | 142 | { | 
 | 143 |   register const unsigned char | 
| cristy | c6da28e | 2011-04-28 01:41:35 +0000 | [diff] [blame] | 144 |     *l, | 
 | 145 |     *p; | 
| cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 146 |  | 
 | 147 |   register unsigned char | 
 | 148 |     *q; | 
 | 149 |  | 
 | 150 |   ssize_t | 
 | 151 |     count; | 
 | 152 |  | 
 | 153 |   unsigned char | 
 | 154 |     byte; | 
 | 155 |  | 
 | 156 |   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"..."); | 
 | 157 |   assert(compressed_pixels != (unsigned char *) NULL); | 
 | 158 |   assert(pixels != (unsigned char *) NULL); | 
 | 159 |   p=compressed_pixels; | 
 | 160 |   q=pixels; | 
 | 161 |   l=q+maxpixels; | 
 | 162 |   while (((size_t) (p-compressed_pixels) < length) && (q < l)) | 
 | 163 |   { | 
 | 164 |     byte=(*p++); | 
 | 165 |     if (byte != 128U) | 
 | 166 |       *q++=byte; | 
 | 167 |     else | 
 | 168 |       { | 
 | 169 |         /* | 
 | 170 |           Runlength-encoded packet: <count><byte> | 
 | 171 |         */ | 
 | 172 |         count=(ssize_t) (*p++); | 
 | 173 |         if (count > 0) | 
 | 174 |           byte=(*p++); | 
 | 175 |         while ((count >= 0) && (q < l)) | 
 | 176 |         { | 
 | 177 |           *q++=byte; | 
 | 178 |           count--; | 
 | 179 |         } | 
 | 180 |      } | 
 | 181 |   } | 
 | 182 |   return(MagickTrue); | 
 | 183 | } | 
 | 184 |  | 
 | 185 | /* | 
 | 186 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | 
 | 187 | %                                                                             % | 
 | 188 | %                                                                             % | 
 | 189 | %                                                                             % | 
 | 190 | %   R e a d S U N I m a g e                                                   % | 
 | 191 | %                                                                             % | 
 | 192 | %                                                                             % | 
 | 193 | %                                                                             % | 
 | 194 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | 
 | 195 | % | 
 | 196 | %  ReadSUNImage() reads a SUN image file and returns it.  It allocates | 
 | 197 | %  the memory necessary for the new Image structure and returns a pointer to | 
 | 198 | %  the new image. | 
 | 199 | % | 
 | 200 | %  The format of the ReadSUNImage method is: | 
 | 201 | % | 
 | 202 | %      Image *ReadSUNImage(const ImageInfo *image_info,ExceptionInfo *exception) | 
 | 203 | % | 
 | 204 | %  A description of each parameter follows: | 
 | 205 | % | 
 | 206 | %    o image_info: the image info. | 
 | 207 | % | 
 | 208 | %    o exception: return any errors or warnings in this structure. | 
 | 209 | % | 
 | 210 | */ | 
 | 211 | static Image *ReadSUNImage(const ImageInfo *image_info,ExceptionInfo *exception) | 
 | 212 | { | 
 | 213 | #define RMT_EQUAL_RGB  1 | 
 | 214 | #define RMT_NONE  0 | 
 | 215 | #define RMT_RAW  2 | 
 | 216 | #define RT_STANDARD  1 | 
 | 217 | #define RT_ENCODED  2 | 
 | 218 | #define RT_FORMAT_RGB  3 | 
 | 219 |  | 
 | 220 |   typedef struct _SUNInfo | 
 | 221 |   { | 
 | 222 |     unsigned int | 
 | 223 |       magic, | 
 | 224 |       width, | 
 | 225 |       height, | 
 | 226 |       depth, | 
 | 227 |       length, | 
 | 228 |       type, | 
 | 229 |       maptype, | 
 | 230 |       maplength; | 
 | 231 |   } SUNInfo; | 
 | 232 |  | 
 | 233 |   Image | 
 | 234 |     *image; | 
 | 235 |  | 
 | 236 |   int | 
 | 237 |     bit; | 
 | 238 |  | 
| cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 239 |   MagickBooleanType | 
 | 240 |     status; | 
 | 241 |  | 
 | 242 |   MagickSizeType | 
 | 243 |     number_pixels; | 
 | 244 |  | 
| cristy | 4c08aed | 2011-07-01 19:47:50 +0000 | [diff] [blame] | 245 |   register Quantum | 
| cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 246 |     *q; | 
 | 247 |  | 
| cristy | bb50337 | 2010-05-27 20:51:26 +0000 | [diff] [blame] | 248 |   register ssize_t | 
| cristy | e13c304 | 2011-03-03 01:30:05 +0000 | [diff] [blame] | 249 |     i, | 
 | 250 |     x; | 
| cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 251 |  | 
 | 252 |   register unsigned char | 
 | 253 |     *p; | 
 | 254 |  | 
 | 255 |   size_t | 
 | 256 |     length; | 
 | 257 |  | 
 | 258 |   ssize_t | 
| cristy | c6da28e | 2011-04-28 01:41:35 +0000 | [diff] [blame] | 259 |     count, | 
 | 260 |     y; | 
| cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 261 |  | 
 | 262 |   SUNInfo | 
 | 263 |     sun_info; | 
 | 264 |  | 
 | 265 |   unsigned char | 
 | 266 |     *sun_data, | 
 | 267 |     *sun_pixels; | 
 | 268 |  | 
 | 269 |   unsigned int | 
 | 270 |     bytes_per_line; | 
 | 271 |  | 
 | 272 |   /* | 
 | 273 |     Open image file. | 
 | 274 |   */ | 
 | 275 |   assert(image_info != (const ImageInfo *) NULL); | 
 | 276 |   assert(image_info->signature == MagickSignature); | 
 | 277 |   if (image_info->debug != MagickFalse) | 
 | 278 |     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s", | 
 | 279 |       image_info->filename); | 
 | 280 |   assert(exception != (ExceptionInfo *) NULL); | 
 | 281 |   assert(exception->signature == MagickSignature); | 
| cristy | 9950d57 | 2011-10-01 18:22:35 +0000 | [diff] [blame] | 282 |   image=AcquireImage(image_info,exception); | 
| cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 283 |   status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception); | 
 | 284 |   if (status == MagickFalse) | 
 | 285 |     { | 
 | 286 |       image=DestroyImageList(image); | 
 | 287 |       return((Image *) NULL); | 
 | 288 |     } | 
 | 289 |   /* | 
 | 290 |     Read SUN raster header. | 
 | 291 |   */ | 
 | 292 |   (void) ResetMagickMemory(&sun_info,0,sizeof(sun_info)); | 
 | 293 |   sun_info.magic=ReadBlobMSBLong(image); | 
 | 294 |   do | 
 | 295 |   { | 
 | 296 |     /* | 
 | 297 |       Verify SUN identifier. | 
 | 298 |     */ | 
 | 299 |     if (sun_info.magic != 0x59a66a95) | 
 | 300 |       ThrowReaderException(CorruptImageError,"ImproperImageHeader"); | 
 | 301 |     sun_info.width=ReadBlobMSBLong(image); | 
 | 302 |     sun_info.height=ReadBlobMSBLong(image); | 
 | 303 |     sun_info.depth=ReadBlobMSBLong(image); | 
 | 304 |     sun_info.length=ReadBlobMSBLong(image); | 
 | 305 |     sun_info.type=ReadBlobMSBLong(image); | 
 | 306 |     sun_info.maptype=ReadBlobMSBLong(image); | 
 | 307 |     sun_info.maplength=ReadBlobMSBLong(image); | 
| cristy | 22a6f21 | 2014-11-30 15:59:52 +0000 | [diff] [blame] | 308 |     if ((sun_info.type != RT_STANDARD) && (sun_info.type != RT_ENCODED) && | 
 | 309 |         (sun_info.type != RT_FORMAT_RGB)) | 
 | 310 |       ThrowReaderException(CoderError,"ImproperImageHeader"); | 
 | 311 |     if ((sun_info.maptype == RMT_NONE) && (sun_info.maplength != 0)) | 
 | 312 |       ThrowReaderException(CoderError,"ImproperImageHeader"); | 
| cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 313 |     if ((sun_info.depth == 0) || (sun_info.depth > 32)) | 
 | 314 |       ThrowReaderException(CorruptImageError,"ImproperImageHeader"); | 
| cristy | 22a6f21 | 2014-11-30 15:59:52 +0000 | [diff] [blame] | 315 |     if ((sun_info.maptype != RMT_NONE) && (sun_info.maptype != RMT_EQUAL_RGB) && | 
 | 316 |         (sun_info.maptype != RMT_RAW)) | 
 | 317 |       ThrowReaderException(CoderError,"ColormapTypeNotSupported"); | 
 | 318 |     image->columns=sun_info.width; | 
 | 319 |     image->rows=sun_info.height; | 
| cristy | acee812 | 2009-11-19 02:04:10 +0000 | [diff] [blame] | 320 |     image->depth=sun_info.depth <= 8 ? sun_info.depth : | 
 | 321 |       MAGICKCORE_QUANTUM_DEPTH; | 
| cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 322 |     if (sun_info.depth < 24) | 
 | 323 |       { | 
| cristy | eaedf06 | 2010-05-29 22:36:02 +0000 | [diff] [blame] | 324 |         size_t | 
 | 325 |           one; | 
 | 326 |  | 
| cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 327 |         image->storage_class=PseudoClass; | 
 | 328 |         image->colors=sun_info.maplength; | 
| cristy | eaedf06 | 2010-05-29 22:36:02 +0000 | [diff] [blame] | 329 |         one=1; | 
| cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 330 |         if (sun_info.maptype == RMT_NONE) | 
| cristy | eaedf06 | 2010-05-29 22:36:02 +0000 | [diff] [blame] | 331 |           image->colors=one << sun_info.depth; | 
| cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 332 |         if (sun_info.maptype == RMT_EQUAL_RGB) | 
 | 333 |           image->colors=sun_info.maplength/3; | 
 | 334 |       } | 
 | 335 |     switch (sun_info.maptype) | 
 | 336 |     { | 
 | 337 |       case RMT_NONE: | 
 | 338 |       { | 
 | 339 |         if (sun_info.depth < 24) | 
 | 340 |           { | 
 | 341 |             /* | 
 | 342 |               Create linear color ramp. | 
 | 343 |             */ | 
| cristy | 018f07f | 2011-09-04 21:15:19 +0000 | [diff] [blame] | 344 |             if (AcquireImageColormap(image,image->colors,exception) == MagickFalse) | 
| cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 345 |               ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed"); | 
 | 346 |           } | 
 | 347 |         break; | 
 | 348 |       } | 
 | 349 |       case RMT_EQUAL_RGB: | 
 | 350 |       { | 
 | 351 |         unsigned char | 
 | 352 |           *sun_colormap; | 
 | 353 |  | 
 | 354 |         /* | 
 | 355 |           Read SUN raster colormap. | 
 | 356 |         */ | 
| cristy | 018f07f | 2011-09-04 21:15:19 +0000 | [diff] [blame] | 357 |         if (AcquireImageColormap(image,image->colors,exception) == MagickFalse) | 
| cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 358 |           ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed"); | 
 | 359 |         sun_colormap=(unsigned char *) AcquireQuantumMemory(image->colors, | 
 | 360 |           sizeof(*sun_colormap)); | 
 | 361 |         if (sun_colormap == (unsigned char *) NULL) | 
 | 362 |           ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed"); | 
 | 363 |         count=ReadBlob(image,image->colors,sun_colormap); | 
| cristy | 22a6f21 | 2014-11-30 15:59:52 +0000 | [diff] [blame] | 364 |         if (count != (ssize_t) image->colors) | 
 | 365 |           ThrowReaderException(CorruptImageError,"UnexpectedEndOfFile"); | 
| cristy | bb50337 | 2010-05-27 20:51:26 +0000 | [diff] [blame] | 366 |         for (i=0; i < (ssize_t) image->colors; i++) | 
| cristy | 22a6f21 | 2014-11-30 15:59:52 +0000 | [diff] [blame] | 367 |           image->colormap[i].red=(MagickRealType) ScaleCharToQuantum( | 
 | 368 |             sun_colormap[i]); | 
| cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 369 |         count=ReadBlob(image,image->colors,sun_colormap); | 
| cristy | 22a6f21 | 2014-11-30 15:59:52 +0000 | [diff] [blame] | 370 |         if (count != (ssize_t) image->colors) | 
 | 371 |           ThrowReaderException(CorruptImageError,"UnexpectedEndOfFile"); | 
| cristy | bb50337 | 2010-05-27 20:51:26 +0000 | [diff] [blame] | 372 |         for (i=0; i < (ssize_t) image->colors; i++) | 
| cristy | 22a6f21 | 2014-11-30 15:59:52 +0000 | [diff] [blame] | 373 |           image->colormap[i].green=(MagickRealType) ScaleCharToQuantum( | 
 | 374 |             sun_colormap[i]); | 
| cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 375 |         count=ReadBlob(image,image->colors,sun_colormap); | 
| cristy | 22a6f21 | 2014-11-30 15:59:52 +0000 | [diff] [blame] | 376 |         if (count != (ssize_t) image->colors) | 
 | 377 |           ThrowReaderException(CorruptImageError,"UnexpectedEndOfFile"); | 
| cristy | bb50337 | 2010-05-27 20:51:26 +0000 | [diff] [blame] | 378 |         for (i=0; i < (ssize_t) image->colors; i++) | 
| cristy | 22a6f21 | 2014-11-30 15:59:52 +0000 | [diff] [blame] | 379 |           image->colormap[i].blue=(MagickRealType) ScaleCharToQuantum( | 
 | 380 |             sun_colormap[i]); | 
| cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 381 |         sun_colormap=(unsigned char *) RelinquishMagickMemory(sun_colormap); | 
 | 382 |         break; | 
 | 383 |       } | 
 | 384 |       case RMT_RAW: | 
 | 385 |       { | 
 | 386 |         unsigned char | 
 | 387 |           *sun_colormap; | 
 | 388 |  | 
 | 389 |         /* | 
 | 390 |           Read SUN raster colormap. | 
 | 391 |         */ | 
 | 392 |         sun_colormap=(unsigned char *) AcquireQuantumMemory(sun_info.maplength, | 
 | 393 |           sizeof(*sun_colormap)); | 
 | 394 |         if (sun_colormap == (unsigned char *) NULL) | 
 | 395 |           ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed"); | 
 | 396 |         count=ReadBlob(image,sun_info.maplength,sun_colormap); | 
| cristy | 22a6f21 | 2014-11-30 15:59:52 +0000 | [diff] [blame] | 397 |         if (count != (ssize_t) sun_info.maplength) | 
 | 398 |           ThrowReaderException(CorruptImageError,"UnexpectedEndOfFile"); | 
| cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 399 |         sun_colormap=(unsigned char *) RelinquishMagickMemory(sun_colormap); | 
 | 400 |         break; | 
 | 401 |       } | 
 | 402 |       default: | 
 | 403 |         ThrowReaderException(CoderError,"ColormapTypeNotSupported"); | 
 | 404 |     } | 
| cristy | 22a6f21 | 2014-11-30 15:59:52 +0000 | [diff] [blame] | 405 |     image->alpha_trait=sun_info.depth == 32 ? BlendPixelTrait : | 
| cristy | b0a657e | 2012-08-29 00:45:37 +0000 | [diff] [blame] | 406 |       UndefinedPixelTrait; | 
| cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 407 |     image->columns=sun_info.width; | 
 | 408 |     image->rows=sun_info.height; | 
 | 409 |     if (image_info->ping != MagickFalse) | 
 | 410 |       { | 
 | 411 |         (void) CloseBlob(image); | 
 | 412 |         return(GetFirstImageInList(image)); | 
 | 413 |       } | 
 | 414 |     if ((sun_info.length*sizeof(*sun_data))/sizeof(*sun_data) != | 
 | 415 |         sun_info.length || !sun_info.length) | 
 | 416 |       ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed"); | 
 | 417 |     number_pixels=(MagickSizeType) image->columns*image->rows; | 
| cristy | 815b2dd | 2012-09-21 11:22:29 +0000 | [diff] [blame] | 418 |     if ((sun_info.type != RT_ENCODED) && (sun_info.depth >= 8) && | 
| cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 419 |         ((number_pixels*((sun_info.depth+7)/8)) > sun_info.length)) | 
 | 420 |       ThrowReaderException(CorruptImageError,"ImproperImageHeader"); | 
 | 421 |     sun_data=(unsigned char *) AcquireQuantumMemory((size_t) sun_info.length, | 
 | 422 |       sizeof(*sun_data)); | 
 | 423 |     if (sun_data == (unsigned char *) NULL) | 
 | 424 |       ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed"); | 
 | 425 |     count=(ssize_t) ReadBlob(image,sun_info.length,sun_data); | 
| cristy | 22a6f21 | 2014-11-30 15:59:52 +0000 | [diff] [blame] | 426 |     if (count != (ssize_t) sun_info.length) | 
| cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 427 |       ThrowReaderException(CorruptImageError,"UnableToReadImageData"); | 
 | 428 |     sun_pixels=sun_data; | 
 | 429 |     bytes_per_line=0; | 
 | 430 |     if (sun_info.type == RT_ENCODED) | 
 | 431 |       { | 
| cristy | bb50337 | 2010-05-27 20:51:26 +0000 | [diff] [blame] | 432 |         size_t | 
| cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 433 |           height; | 
 | 434 |  | 
 | 435 |         /* | 
 | 436 |           Read run-length encoded raster pixels. | 
 | 437 |         */ | 
 | 438 |         height=sun_info.height; | 
 | 439 |         bytes_per_line=sun_info.width*sun_info.depth; | 
 | 440 |         if ((height == 0) || (sun_info.width == 0) || (sun_info.depth == 0) || | 
 | 441 |             ((bytes_per_line/sun_info.depth) != sun_info.width)) | 
 | 442 |           ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed"); | 
 | 443 |         bytes_per_line+=15; | 
 | 444 |         bytes_per_line<<=1; | 
 | 445 |         if ((bytes_per_line >> 1) != (sun_info.width*sun_info.depth+15)) | 
 | 446 |           ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed"); | 
 | 447 |         bytes_per_line>>=4; | 
 | 448 |         sun_pixels=(unsigned char *) AcquireQuantumMemory(height, | 
 | 449 |           bytes_per_line*sizeof(*sun_pixels)); | 
 | 450 |         if (sun_pixels == (unsigned char *) NULL) | 
 | 451 |           ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed"); | 
| cristy | 22a6f21 | 2014-11-30 15:59:52 +0000 | [diff] [blame] | 452 |         (void) DecodeImage(sun_data,sun_info.length,sun_pixels,bytes_per_line* | 
 | 453 |           height); | 
| cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 454 |         sun_data=(unsigned char *) RelinquishMagickMemory(sun_data); | 
 | 455 |       } | 
 | 456 |     /* | 
 | 457 |       Convert SUN raster image to pixel packets. | 
 | 458 |     */ | 
 | 459 |     p=sun_pixels; | 
 | 460 |     if (sun_info.depth == 1) | 
| cristy | bb50337 | 2010-05-27 20:51:26 +0000 | [diff] [blame] | 461 |       for (y=0; y < (ssize_t) image->rows; y++) | 
| cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 462 |       { | 
 | 463 |         q=QueueAuthenticPixels(image,0,y,image->columns,1,exception); | 
| cristy | acd2ed2 | 2011-08-30 01:44:23 +0000 | [diff] [blame] | 464 |         if (q == (Quantum *) NULL) | 
| cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 465 |           break; | 
| cristy | bb50337 | 2010-05-27 20:51:26 +0000 | [diff] [blame] | 466 |         for (x=0; x < ((ssize_t) image->columns-7); x+=8) | 
| cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 467 |         { | 
 | 468 |           for (bit=7; bit >= 0; bit--) | 
| cristy | 4c08aed | 2011-07-01 19:47:50 +0000 | [diff] [blame] | 469 |           { | 
| cristy | 22a6f21 | 2014-11-30 15:59:52 +0000 | [diff] [blame] | 470 |             SetPixelIndex(image,(Quantum) ((*p) & (0x01 << bit) ? 0x00 : 0x01), | 
 | 471 |               q); | 
| cristy | ed23157 | 2011-07-14 02:18:59 +0000 | [diff] [blame] | 472 |             q+=GetPixelChannels(image); | 
| cristy | 4c08aed | 2011-07-01 19:47:50 +0000 | [diff] [blame] | 473 |           } | 
| cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 474 |           p++; | 
 | 475 |         } | 
 | 476 |         if ((image->columns % 8) != 0) | 
 | 477 |           { | 
| cristy | 22a6f21 | 2014-11-30 15:59:52 +0000 | [diff] [blame] | 478 |             for (bit=7; bit >= (int) (8-(image->columns % 8)); bit--) | 
| cristy | 4c08aed | 2011-07-01 19:47:50 +0000 | [diff] [blame] | 479 |             { | 
| cristy | 22a6f21 | 2014-11-30 15:59:52 +0000 | [diff] [blame] | 480 |               SetPixelIndex(image,(Quantum) ((*p) & (0x01 << bit) ? 0x00 : | 
 | 481 |                 0x01),q); | 
| cristy | ed23157 | 2011-07-14 02:18:59 +0000 | [diff] [blame] | 482 |               q+=GetPixelChannels(image); | 
| cristy | 4c08aed | 2011-07-01 19:47:50 +0000 | [diff] [blame] | 483 |             } | 
| cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 484 |             p++; | 
 | 485 |           } | 
 | 486 |         if ((((image->columns/8)+(image->columns % 8 ? 1 : 0)) % 2) != 0) | 
 | 487 |           p++; | 
 | 488 |         if (SyncAuthenticPixels(image,exception) == MagickFalse) | 
 | 489 |           break; | 
 | 490 |         if (image->previous == (Image *) NULL) | 
 | 491 |           { | 
| cristy | cee9711 | 2010-05-28 00:44:52 +0000 | [diff] [blame] | 492 |             status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y, | 
| cristy | e13c304 | 2011-03-03 01:30:05 +0000 | [diff] [blame] | 493 |               image->rows); | 
| cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 494 |             if (status == MagickFalse) | 
 | 495 |               break; | 
 | 496 |           } | 
 | 497 |       } | 
 | 498 |     else | 
 | 499 |       if (image->storage_class == PseudoClass) | 
 | 500 |         { | 
| cristy | 0fa1546 | 2014-12-01 23:11:58 +0000 | [diff] [blame^] | 501 |           if (bytes_per_line == 0) | 
 | 502 |             bytes_per_line=image->columns; | 
| cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 503 |           length=image->rows*(image->columns+image->columns % 2); | 
 | 504 |           if (((sun_info.type == RT_ENCODED) && | 
 | 505 |                (length > (bytes_per_line*image->rows))) || | 
 | 506 |               ((sun_info.type != RT_ENCODED) && (length > sun_info.length))) | 
| cristy | 0fa1546 | 2014-12-01 23:11:58 +0000 | [diff] [blame^] | 507 |             ThrowReaderException(CorruptImageError,"UnableToReadImageData"); | 
| cristy | bb50337 | 2010-05-27 20:51:26 +0000 | [diff] [blame] | 508 |           for (y=0; y < (ssize_t) image->rows; y++) | 
| cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 509 |           { | 
 | 510 |             q=QueueAuthenticPixels(image,0,y,image->columns,1,exception); | 
| cristy | acd2ed2 | 2011-08-30 01:44:23 +0000 | [diff] [blame] | 511 |             if (q == (Quantum *) NULL) | 
| cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 512 |               break; | 
| cristy | bb50337 | 2010-05-27 20:51:26 +0000 | [diff] [blame] | 513 |             for (x=0; x < (ssize_t) image->columns; x++) | 
| cristy | 4c08aed | 2011-07-01 19:47:50 +0000 | [diff] [blame] | 514 |             { | 
 | 515 |               SetPixelIndex(image,*p++,q); | 
| cristy | ed23157 | 2011-07-14 02:18:59 +0000 | [diff] [blame] | 516 |               q+=GetPixelChannels(image); | 
| cristy | 4c08aed | 2011-07-01 19:47:50 +0000 | [diff] [blame] | 517 |             } | 
| cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 518 |             if ((image->columns % 2) != 0) | 
 | 519 |               p++; | 
 | 520 |             if (SyncAuthenticPixels(image,exception) == MagickFalse) | 
 | 521 |               break; | 
 | 522 |             if (image->previous == (Image *) NULL) | 
 | 523 |               { | 
| cristy | cee9711 | 2010-05-28 00:44:52 +0000 | [diff] [blame] | 524 |                 status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y, | 
 | 525 |                 image->rows); | 
| cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 526 |                 if (status == MagickFalse) | 
 | 527 |                   break; | 
 | 528 |               } | 
 | 529 |           } | 
 | 530 |         } | 
 | 531 |       else | 
 | 532 |         { | 
| cristy | acee812 | 2009-11-19 02:04:10 +0000 | [diff] [blame] | 533 |           size_t | 
 | 534 |             bytes_per_pixel; | 
 | 535 |  | 
 | 536 |           bytes_per_pixel=3; | 
| cristy | 35553db | 2014-11-23 15:43:29 +0000 | [diff] [blame] | 537 |           if (image->alpha_trait == BlendPixelTrait) | 
| cristy | acee812 | 2009-11-19 02:04:10 +0000 | [diff] [blame] | 538 |             bytes_per_pixel++; | 
| cristy | 0fa1546 | 2014-12-01 23:11:58 +0000 | [diff] [blame^] | 539 |           if (bytes_per_line == 0) | 
 | 540 |             bytes_per_line=bytes_per_pixel*image->columns; | 
| cristy | acee812 | 2009-11-19 02:04:10 +0000 | [diff] [blame] | 541 |           length=image->rows*((bytes_per_line*image->columns)+ | 
 | 542 |             image->columns % 2); | 
| cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 543 |           if (((sun_info.type == RT_ENCODED) && | 
 | 544 |                (length > (bytes_per_line*image->rows))) || | 
 | 545 |               ((sun_info.type != RT_ENCODED) && (length > sun_info.length))) | 
| cristy | 0fa1546 | 2014-12-01 23:11:58 +0000 | [diff] [blame^] | 546 |             ThrowReaderException(CorruptImageError,"UnableToReadImageData"); | 
| cristy | bb50337 | 2010-05-27 20:51:26 +0000 | [diff] [blame] | 547 |           for (y=0; y < (ssize_t) image->rows; y++) | 
| cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 548 |           { | 
 | 549 |             q=QueueAuthenticPixels(image,0,y,image->columns,1,exception); | 
| cristy | acd2ed2 | 2011-08-30 01:44:23 +0000 | [diff] [blame] | 550 |             if (q == (Quantum *) NULL) | 
| cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 551 |               break; | 
| cristy | bb50337 | 2010-05-27 20:51:26 +0000 | [diff] [blame] | 552 |             for (x=0; x < (ssize_t) image->columns; x++) | 
| cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 553 |             { | 
| cristy | 35553db | 2014-11-23 15:43:29 +0000 | [diff] [blame] | 554 |               if (image->alpha_trait == BlendPixelTrait) | 
| cristy | 4c08aed | 2011-07-01 19:47:50 +0000 | [diff] [blame] | 555 |                 SetPixelAlpha(image,ScaleCharToQuantum(*p++),q); | 
| cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 556 |               if (sun_info.type == RT_STANDARD) | 
 | 557 |                 { | 
| cristy | 4c08aed | 2011-07-01 19:47:50 +0000 | [diff] [blame] | 558 |                   SetPixelBlue(image,ScaleCharToQuantum(*p++),q); | 
 | 559 |                   SetPixelGreen(image,ScaleCharToQuantum(*p++),q); | 
 | 560 |                   SetPixelRed(image,ScaleCharToQuantum(*p++),q); | 
| cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 561 |                 } | 
 | 562 |               else | 
 | 563 |                 { | 
| cristy | 4c08aed | 2011-07-01 19:47:50 +0000 | [diff] [blame] | 564 |                   SetPixelRed(image,ScaleCharToQuantum(*p++),q); | 
 | 565 |                   SetPixelGreen(image,ScaleCharToQuantum(*p++),q); | 
 | 566 |                   SetPixelBlue(image,ScaleCharToQuantum(*p++),q); | 
| cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 567 |                 } | 
 | 568 |               if (image->colors != 0) | 
 | 569 |                 { | 
| cristy | 22a6f21 | 2014-11-30 15:59:52 +0000 | [diff] [blame] | 570 |                   SetPixelRed(image,ClampToQuantum(image->colormap[(ssize_t) | 
 | 571 |                     GetPixelRed(image,q)].red),q); | 
 | 572 |                   SetPixelGreen(image,ClampToQuantum(image->colormap[(ssize_t) | 
 | 573 |                     GetPixelGreen(image,q)].green),q); | 
 | 574 |                   SetPixelBlue(image,ClampToQuantum(image->colormap[(ssize_t) | 
 | 575 |                     GetPixelBlue(image,q)].blue),q); | 
| cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 576 |                 } | 
| cristy | ed23157 | 2011-07-14 02:18:59 +0000 | [diff] [blame] | 577 |               q+=GetPixelChannels(image); | 
| cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 578 |             } | 
| cristy | acee812 | 2009-11-19 02:04:10 +0000 | [diff] [blame] | 579 |             if (((bytes_per_pixel*image->columns) % 2) != 0) | 
| cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 580 |               p++; | 
 | 581 |             if (SyncAuthenticPixels(image,exception) == MagickFalse) | 
 | 582 |               break; | 
 | 583 |             if (image->previous == (Image *) NULL) | 
 | 584 |               { | 
| cristy | cee9711 | 2010-05-28 00:44:52 +0000 | [diff] [blame] | 585 |                 status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y, | 
 | 586 |                 image->rows); | 
| cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 587 |                 if (status == MagickFalse) | 
 | 588 |                   break; | 
 | 589 |               } | 
 | 590 |           } | 
 | 591 |         } | 
 | 592 |     if (image->storage_class == PseudoClass) | 
| cristy | ea1a8aa | 2011-10-20 13:24:06 +0000 | [diff] [blame] | 593 |       (void) SyncImage(image,exception); | 
| cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 594 |     sun_pixels=(unsigned char *) RelinquishMagickMemory(sun_pixels); | 
 | 595 |     if (EOFBlob(image) != MagickFalse) | 
 | 596 |       { | 
 | 597 |         ThrowFileException(exception,CorruptImageError,"UnexpectedEndOfFile", | 
 | 598 |           image->filename); | 
 | 599 |         break; | 
 | 600 |       } | 
 | 601 |     /* | 
 | 602 |       Proceed to next image. | 
 | 603 |     */ | 
 | 604 |     if (image_info->number_scenes != 0) | 
 | 605 |       if (image->scene >= (image_info->scene+image_info->number_scenes-1)) | 
 | 606 |         break; | 
 | 607 |     sun_info.magic=ReadBlobMSBLong(image); | 
 | 608 |     if (sun_info.magic == 0x59a66a95) | 
 | 609 |       { | 
 | 610 |         /* | 
 | 611 |           Allocate next image structure. | 
 | 612 |         */ | 
| cristy | 9950d57 | 2011-10-01 18:22:35 +0000 | [diff] [blame] | 613 |         AcquireNextImage(image_info,image,exception); | 
| cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 614 |         if (GetNextImageInList(image) == (Image *) NULL) | 
 | 615 |           { | 
 | 616 |             image=DestroyImageList(image); | 
 | 617 |             return((Image *) NULL); | 
 | 618 |           } | 
 | 619 |         image=SyncNextImageInList(image); | 
 | 620 |         status=SetImageProgress(image,LoadImagesTag,TellBlob(image), | 
 | 621 |           GetBlobSize(image)); | 
 | 622 |         if (status == MagickFalse) | 
 | 623 |           break; | 
 | 624 |       } | 
 | 625 |   } while (sun_info.magic == 0x59a66a95); | 
 | 626 |   (void) CloseBlob(image); | 
 | 627 |   return(GetFirstImageInList(image)); | 
 | 628 | } | 
 | 629 |  | 
 | 630 | /* | 
 | 631 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | 
 | 632 | %                                                                             % | 
 | 633 | %                                                                             % | 
 | 634 | %                                                                             % | 
 | 635 | %   R e g i s t e r S U N I m a g e                                           % | 
 | 636 | %                                                                             % | 
 | 637 | %                                                                             % | 
 | 638 | %                                                                             % | 
 | 639 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | 
 | 640 | % | 
 | 641 | %  RegisterSUNImage() adds attributes for the SUN image format to | 
 | 642 | %  the list of supported formats.  The attributes include the image format | 
 | 643 | %  tag, a method to read and/or write the format, whether the format | 
 | 644 | %  supports the saving of more than one frame to the same file or blob, | 
 | 645 | %  whether the format supports native in-memory I/O, and a brief | 
 | 646 | %  description of the format. | 
 | 647 | % | 
 | 648 | %  The format of the RegisterSUNImage method is: | 
 | 649 | % | 
| cristy | bb50337 | 2010-05-27 20:51:26 +0000 | [diff] [blame] | 650 | %      size_t RegisterSUNImage(void) | 
| cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 651 | % | 
 | 652 | */ | 
| cristy | bb50337 | 2010-05-27 20:51:26 +0000 | [diff] [blame] | 653 | ModuleExport size_t RegisterSUNImage(void) | 
| cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 654 | { | 
 | 655 |   MagickInfo | 
 | 656 |     *entry; | 
 | 657 |  | 
 | 658 |   entry=SetMagickInfo("RAS"); | 
 | 659 |   entry->decoder=(DecodeImageHandler *) ReadSUNImage; | 
 | 660 |   entry->encoder=(EncodeImageHandler *) WriteSUNImage; | 
 | 661 |   entry->magick=(IsImageFormatHandler *) IsSUN; | 
 | 662 |   entry->description=ConstantString("SUN Rasterfile"); | 
 | 663 |   entry->module=ConstantString("SUN"); | 
 | 664 |   (void) RegisterMagickInfo(entry); | 
 | 665 |   entry=SetMagickInfo("SUN"); | 
 | 666 |   entry->decoder=(DecodeImageHandler *) ReadSUNImage; | 
 | 667 |   entry->encoder=(EncodeImageHandler *) WriteSUNImage; | 
 | 668 |   entry->description=ConstantString("SUN Rasterfile"); | 
 | 669 |   entry->module=ConstantString("SUN"); | 
 | 670 |   (void) RegisterMagickInfo(entry); | 
 | 671 |   return(MagickImageCoderSignature); | 
 | 672 | } | 
 | 673 |  | 
 | 674 | /* | 
 | 675 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | 
 | 676 | %                                                                             % | 
 | 677 | %                                                                             % | 
 | 678 | %                                                                             % | 
 | 679 | %   U n r e g i s t e r S U N I m a g e                                       % | 
 | 680 | %                                                                             % | 
 | 681 | %                                                                             % | 
 | 682 | %                                                                             % | 
 | 683 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | 
 | 684 | % | 
 | 685 | %  UnregisterSUNImage() removes format registrations made by the | 
 | 686 | %  SUN module from the list of supported formats. | 
 | 687 | % | 
 | 688 | %  The format of the UnregisterSUNImage method is: | 
 | 689 | % | 
 | 690 | %      UnregisterSUNImage(void) | 
 | 691 | % | 
 | 692 | */ | 
 | 693 | ModuleExport void UnregisterSUNImage(void) | 
 | 694 | { | 
 | 695 |   (void) UnregisterMagickInfo("RAS"); | 
 | 696 |   (void) UnregisterMagickInfo("SUN"); | 
 | 697 | } | 
 | 698 |  | 
 | 699 | /* | 
 | 700 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | 
 | 701 | %                                                                             % | 
 | 702 | %                                                                             % | 
 | 703 | %                                                                             % | 
 | 704 | %   W r i t e S U N I m a g e                                                 % | 
 | 705 | %                                                                             % | 
 | 706 | %                                                                             % | 
 | 707 | %                                                                             % | 
 | 708 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | 
 | 709 | % | 
 | 710 | %  WriteSUNImage() writes an image in the SUN rasterfile format. | 
 | 711 | % | 
 | 712 | %  The format of the WriteSUNImage method is: | 
 | 713 | % | 
| cristy | 3a37efd | 2011-08-28 20:31:03 +0000 | [diff] [blame] | 714 | %      MagickBooleanType WriteSUNImage(const ImageInfo *image_info, | 
 | 715 | %        Image *image,ExceptionInfo *exception) | 
| cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 716 | % | 
 | 717 | %  A description of each parameter follows. | 
 | 718 | % | 
 | 719 | %    o image_info: the image info. | 
 | 720 | % | 
 | 721 | %    o image:  The image. | 
 | 722 | % | 
| cristy | 3a37efd | 2011-08-28 20:31:03 +0000 | [diff] [blame] | 723 | %    o exception: return any errors or warnings in this structure. | 
 | 724 | % | 
| cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 725 | */ | 
| cristy | 3a37efd | 2011-08-28 20:31:03 +0000 | [diff] [blame] | 726 | static MagickBooleanType WriteSUNImage(const ImageInfo *image_info,Image *image, | 
 | 727 |   ExceptionInfo *exception) | 
| cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 728 | { | 
 | 729 | #define RMT_EQUAL_RGB  1 | 
 | 730 | #define RMT_NONE  0 | 
 | 731 | #define RMT_RAW  2 | 
 | 732 | #define RT_STANDARD  1 | 
 | 733 | #define RT_FORMAT_RGB  3 | 
 | 734 |  | 
 | 735 |   typedef struct _SUNInfo | 
 | 736 |   { | 
 | 737 |     unsigned int | 
 | 738 |       magic, | 
 | 739 |       width, | 
 | 740 |       height, | 
 | 741 |       depth, | 
 | 742 |       length, | 
 | 743 |       type, | 
 | 744 |       maptype, | 
 | 745 |       maplength; | 
 | 746 |   } SUNInfo; | 
 | 747 |  | 
| cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 748 |   MagickBooleanType | 
 | 749 |     status; | 
 | 750 |  | 
 | 751 |   MagickOffsetType | 
 | 752 |     scene; | 
 | 753 |  | 
 | 754 |   MagickSizeType | 
 | 755 |     number_pixels; | 
 | 756 |  | 
| cristy | 4c08aed | 2011-07-01 19:47:50 +0000 | [diff] [blame] | 757 |   register const Quantum | 
| cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 758 |     *p; | 
 | 759 |  | 
| cristy | bb50337 | 2010-05-27 20:51:26 +0000 | [diff] [blame] | 760 |   register ssize_t | 
| cristy | e13c304 | 2011-03-03 01:30:05 +0000 | [diff] [blame] | 761 |     i, | 
| cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 762 |     x; | 
 | 763 |  | 
| cristy | e13c304 | 2011-03-03 01:30:05 +0000 | [diff] [blame] | 764 |   ssize_t | 
 | 765 |     y; | 
| cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 766 |  | 
 | 767 |   SUNInfo | 
 | 768 |     sun_info; | 
 | 769 |  | 
 | 770 |   /* | 
 | 771 |     Open output image file. | 
 | 772 |   */ | 
 | 773 |   assert(image_info != (const ImageInfo *) NULL); | 
 | 774 |   assert(image_info->signature == MagickSignature); | 
 | 775 |   assert(image != (Image *) NULL); | 
 | 776 |   assert(image->signature == MagickSignature); | 
 | 777 |   if (image->debug != MagickFalse) | 
 | 778 |     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); | 
| cristy | 3a37efd | 2011-08-28 20:31:03 +0000 | [diff] [blame] | 779 |   assert(exception != (ExceptionInfo *) NULL); | 
 | 780 |   assert(exception->signature == MagickSignature); | 
 | 781 |   status=OpenBlob(image_info,image,WriteBinaryBlobMode,exception); | 
| cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 782 |   if (status == MagickFalse) | 
 | 783 |     return(status); | 
 | 784 |   scene=0; | 
 | 785 |   do | 
 | 786 |   { | 
 | 787 |     /* | 
 | 788 |       Initialize SUN raster file header. | 
 | 789 |     */ | 
| cristy | af8d391 | 2014-02-21 14:50:33 +0000 | [diff] [blame] | 790 |     (void) TransformImageColorspace(image,sRGBColorspace,exception); | 
| cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 791 |     sun_info.magic=0x59a66a95; | 
 | 792 |     if ((image->columns != (unsigned int) image->columns) || | 
 | 793 |         (image->rows != (unsigned int) image->rows)) | 
 | 794 |       ThrowWriterException(ImageError,"WidthOrHeightExceedsLimit"); | 
 | 795 |     sun_info.width=(unsigned int) image->columns; | 
 | 796 |     sun_info.height=(unsigned int) image->rows; | 
| cristy | 22a6f21 | 2014-11-30 15:59:52 +0000 | [diff] [blame] | 797 |     sun_info.type=(unsigned int) | 
| cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 798 |       (image->storage_class == DirectClass ? RT_FORMAT_RGB : RT_STANDARD); | 
 | 799 |     sun_info.maptype=RMT_NONE; | 
 | 800 |     sun_info.maplength=0; | 
 | 801 |     number_pixels=(MagickSizeType) image->columns*image->rows; | 
 | 802 |     if ((4*number_pixels) != (size_t) (4*number_pixels)) | 
 | 803 |       ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed"); | 
 | 804 |     if (image->storage_class == DirectClass) | 
 | 805 |       { | 
 | 806 |         /* | 
 | 807 |           Full color SUN raster. | 
 | 808 |         */ | 
| cristy | 35553db | 2014-11-23 15:43:29 +0000 | [diff] [blame] | 809 |         sun_info.depth=(unsigned int) image->alpha_trait == BlendPixelTrait ? | 
| cristy | dc2d327 | 2013-02-12 14:00:44 +0000 | [diff] [blame] | 810 |           32U : 24U; | 
| cristy | 35553db | 2014-11-23 15:43:29 +0000 | [diff] [blame] | 811 |         sun_info.length=(unsigned int) ((image->alpha_trait == BlendPixelTrait ? | 
| cristy | dc2d327 | 2013-02-12 14:00:44 +0000 | [diff] [blame] | 812 |           4 : 3)*number_pixels); | 
| cristy | eaedf06 | 2010-05-29 22:36:02 +0000 | [diff] [blame] | 813 |         sun_info.length+=sun_info.length & 0x01 ? (unsigned int) image->rows : | 
 | 814 |           0; | 
| cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 815 |       } | 
 | 816 |     else | 
| cristy | 3a37efd | 2011-08-28 20:31:03 +0000 | [diff] [blame] | 817 |       if (IsImageMonochrome(image,exception) != MagickFalse) | 
| cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 818 |         { | 
 | 819 |           /* | 
 | 820 |             Monochrome SUN raster. | 
 | 821 |           */ | 
 | 822 |           sun_info.depth=1; | 
 | 823 |           sun_info.length=(unsigned int) (((image->columns+7) >> 3)* | 
 | 824 |             image->rows); | 
| cristy | f9cca6a | 2010-06-04 23:49:28 +0000 | [diff] [blame] | 825 |           sun_info.length+=(unsigned int) (((image->columns/8)+(image->columns % | 
 | 826 |             8 ? 1 : 0)) % 2 ? image->rows : 0); | 
| cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 827 |         } | 
 | 828 |       else | 
 | 829 |         { | 
 | 830 |           /* | 
 | 831 |             Colormapped SUN raster. | 
 | 832 |           */ | 
 | 833 |           sun_info.depth=8; | 
 | 834 |           sun_info.length=(unsigned int) number_pixels; | 
| cristy | f9cca6a | 2010-06-04 23:49:28 +0000 | [diff] [blame] | 835 |           sun_info.length+=(unsigned int) (image->columns & 0x01 ? image->rows : | 
 | 836 |             0); | 
| cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 837 |           sun_info.maptype=RMT_EQUAL_RGB; | 
 | 838 |           sun_info.maplength=(unsigned int) (3*image->colors); | 
 | 839 |         } | 
 | 840 |     /* | 
 | 841 |       Write SUN header. | 
 | 842 |     */ | 
 | 843 |     (void) WriteBlobMSBLong(image,sun_info.magic); | 
 | 844 |     (void) WriteBlobMSBLong(image,sun_info.width); | 
 | 845 |     (void) WriteBlobMSBLong(image,sun_info.height); | 
 | 846 |     (void) WriteBlobMSBLong(image,sun_info.depth); | 
 | 847 |     (void) WriteBlobMSBLong(image,sun_info.length); | 
 | 848 |     (void) WriteBlobMSBLong(image,sun_info.type); | 
 | 849 |     (void) WriteBlobMSBLong(image,sun_info.maptype); | 
 | 850 |     (void) WriteBlobMSBLong(image,sun_info.maplength); | 
 | 851 |     /* | 
 | 852 |       Convert MIFF to SUN raster pixels. | 
 | 853 |     */ | 
 | 854 |     x=0; | 
 | 855 |     y=0; | 
 | 856 |     if (image->storage_class == DirectClass) | 
 | 857 |       { | 
 | 858 |         register unsigned char | 
 | 859 |           *q; | 
 | 860 |  | 
 | 861 |         size_t | 
| cristy | acee812 | 2009-11-19 02:04:10 +0000 | [diff] [blame] | 862 |           bytes_per_pixel, | 
| cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 863 |           length; | 
 | 864 |  | 
 | 865 |         unsigned char | 
 | 866 |           *pixels; | 
 | 867 |  | 
 | 868 |         /* | 
 | 869 |           Allocate memory for pixels. | 
 | 870 |         */ | 
| cristy | acee812 | 2009-11-19 02:04:10 +0000 | [diff] [blame] | 871 |         bytes_per_pixel=3; | 
| cristy | 35553db | 2014-11-23 15:43:29 +0000 | [diff] [blame] | 872 |         if (image->alpha_trait == BlendPixelTrait) | 
| cristy | acee812 | 2009-11-19 02:04:10 +0000 | [diff] [blame] | 873 |           bytes_per_pixel++; | 
| cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 874 |         length=image->columns; | 
 | 875 |         pixels=(unsigned char *) AcquireQuantumMemory(length,4*sizeof(*pixels)); | 
 | 876 |         if (pixels == (unsigned char *) NULL) | 
 | 877 |           ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed"); | 
 | 878 |         /* | 
 | 879 |           Convert DirectClass packet to SUN RGB pixel. | 
 | 880 |         */ | 
| cristy | bb50337 | 2010-05-27 20:51:26 +0000 | [diff] [blame] | 881 |         for (y=0; y < (ssize_t) image->rows; y++) | 
| cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 882 |         { | 
| cristy | 3a37efd | 2011-08-28 20:31:03 +0000 | [diff] [blame] | 883 |           p=GetVirtualPixels(image,0,y,image->columns,1,exception); | 
| cristy | 4c08aed | 2011-07-01 19:47:50 +0000 | [diff] [blame] | 884 |           if (p == (const Quantum *) NULL) | 
| cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 885 |             break; | 
 | 886 |           q=pixels; | 
| cristy | bb50337 | 2010-05-27 20:51:26 +0000 | [diff] [blame] | 887 |           for (x=0; x < (ssize_t) image->columns; x++) | 
| cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 888 |           { | 
| cristy | 35553db | 2014-11-23 15:43:29 +0000 | [diff] [blame] | 889 |             if (image->alpha_trait == BlendPixelTrait) | 
| cristy | 4c08aed | 2011-07-01 19:47:50 +0000 | [diff] [blame] | 890 |               *q++=ScaleQuantumToChar(GetPixelAlpha(image,p)); | 
 | 891 |             *q++=ScaleQuantumToChar(GetPixelRed(image,p)); | 
 | 892 |             *q++=ScaleQuantumToChar(GetPixelGreen(image,p)); | 
 | 893 |             *q++=ScaleQuantumToChar(GetPixelBlue(image,p)); | 
| cristy | ed23157 | 2011-07-14 02:18:59 +0000 | [diff] [blame] | 894 |             p+=GetPixelChannels(image); | 
| cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 895 |           } | 
| cristy | acee812 | 2009-11-19 02:04:10 +0000 | [diff] [blame] | 896 |           if (((bytes_per_pixel*image->columns) & 0x01) != 0) | 
 | 897 |             *q++='\0';  /* pad scanline */ | 
| cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 898 |           (void) WriteBlob(image,(size_t) (q-pixels),pixels); | 
 | 899 |           if (image->previous == (Image *) NULL) | 
 | 900 |             { | 
| cristy | cee9711 | 2010-05-28 00:44:52 +0000 | [diff] [blame] | 901 |               status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y, | 
 | 902 |                 image->rows); | 
| cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 903 |               if (status == MagickFalse) | 
 | 904 |                 break; | 
 | 905 |             } | 
 | 906 |         } | 
 | 907 |         pixels=(unsigned char *) RelinquishMagickMemory(pixels); | 
 | 908 |       } | 
 | 909 |     else | 
| cristy | 3a37efd | 2011-08-28 20:31:03 +0000 | [diff] [blame] | 910 |       if (IsImageMonochrome(image,exception) != MagickFalse) | 
| cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 911 |         { | 
 | 912 |           register unsigned char | 
 | 913 |             bit, | 
 | 914 |             byte; | 
 | 915 |  | 
 | 916 |           /* | 
 | 917 |             Convert PseudoClass image to a SUN monochrome image. | 
 | 918 |           */ | 
| cristy | 018f07f | 2011-09-04 21:15:19 +0000 | [diff] [blame] | 919 |           (void) SetImageType(image,BilevelType,exception); | 
| cristy | bb50337 | 2010-05-27 20:51:26 +0000 | [diff] [blame] | 920 |           for (y=0; y < (ssize_t) image->rows; y++) | 
| cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 921 |           { | 
| cristy | 3a37efd | 2011-08-28 20:31:03 +0000 | [diff] [blame] | 922 |             p=GetVirtualPixels(image,0,y,image->columns,1,exception); | 
| cristy | 4c08aed | 2011-07-01 19:47:50 +0000 | [diff] [blame] | 923 |             if (p == (const Quantum *) NULL) | 
| cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 924 |               break; | 
| cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 925 |             bit=0; | 
 | 926 |             byte=0; | 
| cristy | bb50337 | 2010-05-27 20:51:26 +0000 | [diff] [blame] | 927 |             for (x=0; x < (ssize_t) image->columns; x++) | 
| cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 928 |             { | 
 | 929 |               byte<<=1; | 
| cristy | d032322 | 2013-04-07 16:13:21 +0000 | [diff] [blame] | 930 |               if (GetPixelLuma(image,p) < (QuantumRange/2.0)) | 
| cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 931 |                 byte|=0x01; | 
 | 932 |               bit++; | 
 | 933 |               if (bit == 8) | 
 | 934 |                 { | 
 | 935 |                   (void) WriteBlobByte(image,byte); | 
 | 936 |                   bit=0; | 
 | 937 |                   byte=0; | 
 | 938 |                 } | 
| cristy | ed23157 | 2011-07-14 02:18:59 +0000 | [diff] [blame] | 939 |               p+=GetPixelChannels(image); | 
| cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 940 |             } | 
 | 941 |             if (bit != 0) | 
 | 942 |               (void) WriteBlobByte(image,(unsigned char) (byte << (8-bit))); | 
 | 943 |             if ((((image->columns/8)+ | 
 | 944 |                 (image->columns % 8 ? 1 : 0)) % 2) != 0) | 
 | 945 |               (void) WriteBlobByte(image,0);  /* pad scanline */ | 
 | 946 |             if (image->previous == (Image *) NULL) | 
 | 947 |               { | 
| cristy | cee9711 | 2010-05-28 00:44:52 +0000 | [diff] [blame] | 948 |                 status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y, | 
 | 949 |                 image->rows); | 
| cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 950 |                 if (status == MagickFalse) | 
 | 951 |                   break; | 
 | 952 |               } | 
 | 953 |           } | 
 | 954 |         } | 
 | 955 |       else | 
 | 956 |         { | 
 | 957 |           /* | 
 | 958 |             Dump colormap to file. | 
 | 959 |           */ | 
| cristy | bb50337 | 2010-05-27 20:51:26 +0000 | [diff] [blame] | 960 |           for (i=0; i < (ssize_t) image->colors; i++) | 
| cristy | c6da28e | 2011-04-28 01:41:35 +0000 | [diff] [blame] | 961 |             (void) WriteBlobByte(image,ScaleQuantumToChar( | 
| cristy | 22a6f21 | 2014-11-30 15:59:52 +0000 | [diff] [blame] | 962 |               ClampToQuantum(image->colormap[i].red))); | 
| cristy | bb50337 | 2010-05-27 20:51:26 +0000 | [diff] [blame] | 963 |           for (i=0; i < (ssize_t) image->colors; i++) | 
| cristy | c6da28e | 2011-04-28 01:41:35 +0000 | [diff] [blame] | 964 |             (void) WriteBlobByte(image,ScaleQuantumToChar( | 
| cristy | 22a6f21 | 2014-11-30 15:59:52 +0000 | [diff] [blame] | 965 |               ClampToQuantum(image->colormap[i].green))); | 
| cristy | bb50337 | 2010-05-27 20:51:26 +0000 | [diff] [blame] | 966 |           for (i=0; i < (ssize_t) image->colors; i++) | 
| cristy | c6da28e | 2011-04-28 01:41:35 +0000 | [diff] [blame] | 967 |             (void) WriteBlobByte(image,ScaleQuantumToChar( | 
| cristy | 22a6f21 | 2014-11-30 15:59:52 +0000 | [diff] [blame] | 968 |               ClampToQuantum(image->colormap[i].blue))); | 
| cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 969 |           /* | 
 | 970 |             Convert PseudoClass packet to SUN colormapped pixel. | 
 | 971 |           */ | 
| cristy | bb50337 | 2010-05-27 20:51:26 +0000 | [diff] [blame] | 972 |           for (y=0; y < (ssize_t) image->rows; y++) | 
| cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 973 |           { | 
| cristy | 3a37efd | 2011-08-28 20:31:03 +0000 | [diff] [blame] | 974 |             p=GetVirtualPixels(image,0,y,image->columns,1,exception); | 
| cristy | 4c08aed | 2011-07-01 19:47:50 +0000 | [diff] [blame] | 975 |             if (p == (const Quantum *) NULL) | 
| cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 976 |               break; | 
| cristy | bb50337 | 2010-05-27 20:51:26 +0000 | [diff] [blame] | 977 |             for (x=0; x < (ssize_t) image->columns; x++) | 
| cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 978 |             { | 
| cristy | c6da28e | 2011-04-28 01:41:35 +0000 | [diff] [blame] | 979 |               (void) WriteBlobByte(image,(unsigned char) | 
| cristy | 4c08aed | 2011-07-01 19:47:50 +0000 | [diff] [blame] | 980 |                 GetPixelIndex(image,p)); | 
| cristy | ed23157 | 2011-07-14 02:18:59 +0000 | [diff] [blame] | 981 |               p+=GetPixelChannels(image); | 
| cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 982 |             } | 
| cristy | acee812 | 2009-11-19 02:04:10 +0000 | [diff] [blame] | 983 |             if (image->columns & 0x01) | 
| cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 984 |               (void) WriteBlobByte(image,0);  /* pad scanline */ | 
 | 985 |             if (image->previous == (Image *) NULL) | 
 | 986 |               { | 
| cristy | cee9711 | 2010-05-28 00:44:52 +0000 | [diff] [blame] | 987 |                 status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y, | 
| cristy | c6da28e | 2011-04-28 01:41:35 +0000 | [diff] [blame] | 988 |                   image->rows); | 
| cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 989 |                 if (status == MagickFalse) | 
 | 990 |                   break; | 
 | 991 |               } | 
 | 992 |           } | 
 | 993 |         } | 
 | 994 |     if (GetNextImageInList(image) == (Image *) NULL) | 
 | 995 |       break; | 
 | 996 |     image=SyncNextImageInList(image); | 
 | 997 |     status=SetImageProgress(image,SaveImagesTag,scene++, | 
 | 998 |       GetImageListLength(image)); | 
 | 999 |     if (status == MagickFalse) | 
 | 1000 |       break; | 
 | 1001 |   } while (image_info->adjoin != MagickFalse); | 
 | 1002 |   (void) CloseBlob(image); | 
 | 1003 |   return(MagickTrue); | 
 | 1004 | } |