1 /* 2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 3 % % 4 % % 5 % % 6 % RRRR L AAA % 7 % R R L A A % 8 % RRRR L AAAAA % 9 % R R L A A % 10 % R R LLLLL A A % 11 % % 12 % % 13 % Read Alias/Wavefront Image Format % 14 % % 15 % Software Design % 16 % Cristy % 17 % July 1992 % 18 % % 19 % % 20 % Copyright 1999-2016 ImageMagick Studio LLC, a non-profit organization % 21 % dedicated to making software imaging solutions freely available. % 22 % % 23 % You may not use this file except in compliance with the License. You may % 24 % obtain a copy of the License at % 25 % % 26 % 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 /* 41 Include declarations. 42 */ 43 #include "MagickCore/studio.h" 44 #include "MagickCore/property.h" 45 #include "MagickCore/blob.h" 46 #include "MagickCore/blob-private.h" 47 #include "MagickCore/cache.h" 48 #include "MagickCore/exception.h" 49 #include "MagickCore/exception-private.h" 50 #include "MagickCore/image.h" 51 #include "MagickCore/image-private.h" 52 #include "MagickCore/list.h" 53 #include "MagickCore/magick.h" 54 #include "MagickCore/memory_.h" 55 #include "MagickCore/monitor.h" 56 #include "MagickCore/monitor-private.h" 57 #include "MagickCore/pixel-accessor.h" 58 #include "MagickCore/quantum-private.h" 59 #include "MagickCore/static.h" 60 #include "MagickCore/string_.h" 61 #include "MagickCore/module.h" 62 63 /* 65 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 66 % % 67 % % 68 % % 69 % R e a d R L A I m a g e % 70 % % 71 % % 72 % % 73 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 74 % 75 % ReadRLAImage() reads a run-length encoded Wavefront RLA image file 76 % and returns it. It allocates the memory necessary for the new Image 77 % structure and returns a pointer to the new image. 78 % 79 % Note: This module was contributed by Lester Vecsey (master (at) internexus.net). 80 % 81 % The format of the ReadRLAImage method is: 82 % 83 % Image *ReadRLAImage(const ImageInfo *image_info,ExceptionInfo *exception) 84 % 85 % A description of each parameter follows: 86 % 87 % o image_info: the image info. 88 % 89 % o exception: return any errors or warnings in this structure. 90 % 91 */ 92 static Image *ReadRLAImage(const ImageInfo *image_info,ExceptionInfo *exception) 93 { 94 typedef struct _WindowFrame 95 { 96 short 97 left, 98 right, 99 bottom, 100 top; 101 } WindowFrame; 102 103 typedef struct _RLAInfo 104 { 105 WindowFrame 106 window, 107 active_window; 108 109 short 110 frame, 111 storage_type, 112 number_channels, 113 number_matte_channels, 114 number_auxiliary_channels, 115 revision; 116 117 char 118 gamma[16+1], 119 red_primary[24+1], 120 green_primary[24+1], 121 blue_primary[24+1], 122 white_point[24+1]; 123 124 int 125 job_number; 126 127 char 128 name[128+1], 129 description[128+1], 130 program[64+1], 131 machine[32+1], 132 user[32+1], 133 date[20+1], 134 aspect[24+1], 135 aspect_ratio[8+1], 136 chan[32+1]; 137 138 short 139 field; 140 141 char 142 time[12], 143 filter[32]; 144 145 short 146 bits_per_channel, 147 matte_type, 148 matte_bits, 149 auxiliary_type, 150 auxiliary_bits; 151 152 char 153 auxiliary[32+1], 154 space[36+1]; 155 156 int 157 next; 158 } RLAInfo; 159 160 Image 161 *image; 162 163 int 164 channel, 165 length, 166 runlength; 167 168 MagickBooleanType 169 status; 170 171 MagickOffsetType 172 offset, 173 *scanlines; 174 175 register ssize_t 176 i, 177 x; 178 179 register Quantum 180 *q; 181 182 ssize_t 183 count, 184 y; 185 186 RLAInfo 187 rla_info; 188 189 unsigned char 190 byte; 191 192 /* 193 Open image file. 194 */ 195 assert(image_info != (const ImageInfo *) NULL); 196 assert(image_info->signature == MagickCoreSignature); 197 if (image_info->debug != MagickFalse) 198 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s", 199 image_info->filename); 200 assert(exception != (ExceptionInfo *) NULL); 201 assert(exception->signature == MagickCoreSignature); 202 image=AcquireImage(image_info,exception); 203 status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception); 204 if (status == MagickFalse) 205 { 206 image=DestroyImageList(image); 207 return((Image *) NULL); 208 } 209 (void) ResetMagickMemory(&rla_info,0,sizeof(rla_info)); 210 rla_info.window.left=(short) ReadBlobMSBShort(image); 211 rla_info.window.right=(short) ReadBlobMSBShort(image); 212 rla_info.window.bottom=(short) ReadBlobMSBShort(image); 213 rla_info.window.top=(short) ReadBlobMSBShort(image); 214 rla_info.active_window.left=(short) ReadBlobMSBShort(image); 215 rla_info.active_window.right=(short) ReadBlobMSBShort(image); 216 rla_info.active_window.bottom=(short) ReadBlobMSBShort(image); 217 rla_info.active_window.top=(short) ReadBlobMSBShort(image); 218 rla_info.frame=(short) ReadBlobMSBShort(image); 219 rla_info.storage_type=(short) ReadBlobMSBShort(image); 220 rla_info.number_channels=(short) ReadBlobMSBShort(image); 221 rla_info.number_matte_channels=(short) ReadBlobMSBShort(image); 222 if (rla_info.number_channels == 0) 223 rla_info.number_channels=3; 224 rla_info.number_channels+=rla_info.number_matte_channels; 225 rla_info.number_auxiliary_channels=(short) ReadBlobMSBShort(image); 226 rla_info.revision=(short) ReadBlobMSBShort(image); 227 count=ReadBlob(image,16,(unsigned char *) rla_info.gamma); 228 count=ReadBlob(image,24,(unsigned char *) rla_info.red_primary); 229 count=ReadBlob(image,24,(unsigned char *) rla_info.green_primary); 230 count=ReadBlob(image,24,(unsigned char *) rla_info.blue_primary); 231 count=ReadBlob(image,24,(unsigned char *) rla_info.white_point); 232 rla_info.job_number=ReadBlobMSBSignedLong(image); 233 count=ReadBlob(image,128,(unsigned char *) rla_info.name); 234 count=ReadBlob(image,128,(unsigned char *) rla_info.description); 235 rla_info.description[127]='\0'; 236 count=ReadBlob(image,64,(unsigned char *) rla_info.program); 237 count=ReadBlob(image,32,(unsigned char *) rla_info.machine); 238 count=ReadBlob(image,32,(unsigned char *) rla_info.user); 239 count=ReadBlob(image,20,(unsigned char *) rla_info.date); 240 count=ReadBlob(image,24,(unsigned char *) rla_info.aspect); 241 count=ReadBlob(image,8,(unsigned char *) rla_info.aspect_ratio); 242 count=ReadBlob(image,32,(unsigned char *) rla_info.chan); 243 rla_info.field=(short) ReadBlobMSBShort(image); 244 count=ReadBlob(image,12,(unsigned char *) rla_info.time); 245 count=ReadBlob(image,32,(unsigned char *) rla_info.filter); 246 rla_info.bits_per_channel=(short) ReadBlobMSBShort(image); 247 rla_info.matte_type=(short) ReadBlobMSBShort(image); 248 rla_info.matte_bits=(short) ReadBlobMSBShort(image); 249 rla_info.auxiliary_type=(short) ReadBlobMSBShort(image); 250 rla_info.auxiliary_bits=(short) ReadBlobMSBShort(image); 251 count=ReadBlob(image,32,(unsigned char *) rla_info.auxiliary); 252 count=ReadBlob(image,36,(unsigned char *) rla_info.space); 253 if ((size_t) count != 36) 254 ThrowReaderException(CorruptImageError,"UnableToReadImageData"); 255 rla_info.next=ReadBlobMSBSignedLong(image); 256 /* 257 Initialize image structure. 258 */ 259 image->alpha_trait=rla_info.number_matte_channels != 0 ? BlendPixelTrait : 260 UndefinedPixelTrait; 261 image->columns=(size_t) (rla_info.active_window.right- 262 rla_info.active_window.left+1); 263 image->rows=(size_t) (rla_info.active_window.top- 264 rla_info.active_window.bottom+1); 265 if (image_info->ping != MagickFalse) 266 { 267 (void) CloseBlob(image); 268 return(GetFirstImageInList(image)); 269 } 270 status=SetImageExtent(image,image->columns,image->rows,exception); 271 if (status == MagickFalse) 272 return(DestroyImageList(image)); 273 scanlines=(MagickOffsetType *) AcquireQuantumMemory(image->rows, 274 sizeof(*scanlines)); 275 if (scanlines == (MagickOffsetType *) NULL) 276 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed"); 277 if (*rla_info.description != '\0') 278 (void) SetImageProperty(image,"comment",rla_info.description,exception); 279 /* 280 Read offsets to each scanline data. 281 */ 282 for (i=0; i < (ssize_t) image->rows; i++) 283 scanlines[i]=(MagickOffsetType) ReadBlobMSBSignedLong(image); 284 /* 285 Read image data. 286 */ 287 x=0; 288 for (y=0; y < (ssize_t) image->rows; y++) 289 { 290 offset=SeekBlob(image,scanlines[image->rows-y-1],SEEK_SET); 291 if (offset < 0) 292 ThrowReaderException(CorruptImageError,"ImproperImageHeader"); 293 for (channel=0; channel < (int) rla_info.number_channels; channel++) 294 { 295 length=ReadBlobMSBSignedShort(image); 296 while (length > 0) 297 { 298 byte=(unsigned char) ReadBlobByte(image); 299 runlength=byte; 300 if (byte > 127) 301 runlength=byte-256; 302 length--; 303 if (length == 0) 304 break; 305 if (runlength < 0) 306 { 307 while (runlength < 0) 308 { 309 q=GetAuthenticPixels(image,(ssize_t) (x % image->columns), 310 (ssize_t) (y % image->rows),1,1,exception); 311 if (q == (Quantum *) NULL) 312 break; 313 byte=(unsigned char) ReadBlobByte(image); 314 length--; 315 switch (channel) 316 { 317 case 0: 318 { 319 SetPixelRed(image,ScaleCharToQuantum(byte),q); 320 break; 321 } 322 case 1: 323 { 324 SetPixelGreen(image,ScaleCharToQuantum(byte),q); 325 break; 326 } 327 case 2: 328 { 329 SetPixelBlue(image,ScaleCharToQuantum(byte),q); 330 break; 331 } 332 case 3: 333 default: 334 { 335 SetPixelAlpha(image,ScaleCharToQuantum(byte),q); 336 break; 337 } 338 } 339 if (SyncAuthenticPixels(image,exception) == MagickFalse) 340 break; 341 x++; 342 runlength++; 343 } 344 continue; 345 } 346 byte=(unsigned char) ReadBlobByte(image); 347 length--; 348 runlength++; 349 do 350 { 351 q=GetAuthenticPixels(image,(ssize_t) (x % image->columns), 352 (ssize_t) (y % image->rows),1,1,exception); 353 if (q == (Quantum *) NULL) 354 break; 355 switch (channel) 356 { 357 case 0: 358 { 359 SetPixelRed(image,ScaleCharToQuantum(byte),q); 360 break; 361 } 362 case 1: 363 { 364 SetPixelGreen(image,ScaleCharToQuantum(byte),q); 365 break; 366 } 367 case 2: 368 { 369 SetPixelBlue(image,ScaleCharToQuantum(byte),q); 370 break; 371 } 372 case 3: 373 default: 374 { 375 SetPixelAlpha(image,ScaleCharToQuantum(byte),q); 376 break; 377 } 378 } 379 if (SyncAuthenticPixels(image,exception) == MagickFalse) 380 break; 381 x++; 382 runlength--; 383 } 384 while (runlength > 0); 385 } 386 } 387 status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y, 388 image->rows); 389 if (status == MagickFalse) 390 break; 391 } 392 if (EOFBlob(image) != MagickFalse) 393 ThrowFileException(exception,CorruptImageError,"UnexpectedEndOfFile", 394 image->filename); 395 scanlines=(MagickOffsetType *) RelinquishMagickMemory(scanlines); 396 (void) CloseBlob(image); 397 return(GetFirstImageInList(image)); 398 } 399 400 /* 402 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 403 % % 404 % % 405 % % 406 % R e g i s t e r R L A I m a g e % 407 % % 408 % % 409 % % 410 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 411 % 412 % RegisterRLAImage() adds attributes for the RLA image format to 413 % the list of supported formats. The attributes include the image format 414 % tag, a method to read and/or write the format, whether the format 415 % supports the saving of more than one frame to the same file or blob, 416 % whether the format supports native in-memory I/O, and a brief 417 % description of the format. 418 % 419 % The format of the RegisterRLAImage method is: 420 % 421 % size_t RegisterRLAImage(void) 422 % 423 */ 424 ModuleExport size_t RegisterRLAImage(void) 425 { 426 MagickInfo 427 *entry; 428 429 entry=AcquireMagickInfo("RLA","RLA","Alias/Wavefront image"); 430 entry->decoder=(DecodeImageHandler *) ReadRLAImage; 431 entry->flags^=CoderAdjoinFlag; 432 entry->flags|=CoderSeekableStreamFlag; 433 (void) RegisterMagickInfo(entry); 434 return(MagickImageCoderSignature); 435 } 436 437 /* 439 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 440 % % 441 % % 442 % % 443 % U n r e g i s t e r R L A I m a g e % 444 % % 445 % % 446 % % 447 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 448 % 449 % UnregisterRLAImage() removes format registrations made by the 450 % RLA module from the list of supported formats. 451 % 452 % The format of the UnregisterRLAImage method is: 453 % 454 % UnregisterRLAImage(void) 455 % 456 */ 457 ModuleExport void UnregisterRLAImage(void) 458 { 459 (void) UnregisterMagickInfo("RLA"); 460 } 461