Home | History | Annotate | Download | only in coders
      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