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