Home | History | Annotate | Download | only in coders
      1 /*
      2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
      3 %                                                                             %
      4 %                                                                             %
      5 %                                                                             %
      6 %                             AAA    AAA   IIIII                              %
      7 %                            A   A  A   A    I                                %
      8 %                            AAAAA  AAAAA    I                                %
      9 %                            A   A  A   A    I                                %
     10 %                            A   A  A   A  IIIII                              %
     11 %                                                                             %
     12 %                                                                             %
     13 %                        Read/Write AAI X 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/blob.h"
     45 #include "MagickCore/blob-private.h"
     46 #include "MagickCore/cache.h"
     47 #include "MagickCore/colorspace.h"
     48 #include "MagickCore/colorspace-private.h"
     49 #include "MagickCore/exception.h"
     50 #include "MagickCore/exception-private.h"
     51 #include "MagickCore/image.h"
     52 #include "MagickCore/image-private.h"
     53 #include "MagickCore/list.h"
     54 #include "MagickCore/magick.h"
     55 #include "MagickCore/memory_.h"
     56 #include "MagickCore/monitor.h"
     57 #include "MagickCore/monitor-private.h"
     58 #include "MagickCore/pixel.h"
     59 #include "MagickCore/pixel-accessor.h"
     60 #include "MagickCore/quantum-private.h"
     61 #include "MagickCore/static.h"
     62 #include "MagickCore/string_.h"
     63 #include "MagickCore/module.h"
     64 
     65 /*
     67   Forward declarations.
     68 */
     69 static MagickBooleanType
     70   WriteAAIImage(const ImageInfo *,Image *,ExceptionInfo *);
     71 
     72 /*
     74 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     75 %                                                                             %
     76 %                                                                             %
     77 %                                                                             %
     78 %   R e a d A A I I m a g e                                                   %
     79 %                                                                             %
     80 %                                                                             %
     81 %                                                                             %
     82 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     83 %
     84 %  ReadAAIImage() reads an AAI Dune image file and returns it.  It
     85 %  allocates the memory necessary for the new Image structure and returns a
     86 %  pointer to the new image.
     87 %
     88 %  The format of the ReadAAIImage method is:
     89 %
     90 %      Image *ReadAAIImage(const ImageInfo *image_info,ExceptionInfo *exception)
     91 %
     92 %  A description of each parameter follows:
     93 %
     94 %    o image_info: the image info.
     95 %
     96 %    o exception: return any errors or warnings in this structure.
     97 %
     98 */
     99 static Image *ReadAAIImage(const ImageInfo *image_info,ExceptionInfo *exception)
    100 {
    101   Image
    102     *image;
    103 
    104   MagickBooleanType
    105     status;
    106 
    107   register ssize_t
    108     x;
    109 
    110   register Quantum
    111     *q;
    112 
    113   register unsigned char
    114     *p;
    115 
    116   size_t
    117     height,
    118     length,
    119     width;
    120 
    121   ssize_t
    122     count,
    123     y;
    124 
    125   unsigned char
    126     *pixels;
    127 
    128   /*
    129     Open image file.
    130   */
    131   assert(image_info != (const ImageInfo *) NULL);
    132   assert(image_info->signature == MagickCoreSignature);
    133   if (image_info->debug != MagickFalse)
    134     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
    135       image_info->filename);
    136   assert(exception != (ExceptionInfo *) NULL);
    137   assert(exception->signature == MagickCoreSignature);
    138   image=AcquireImage(image_info,exception);
    139   status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
    140   if (status == MagickFalse)
    141     {
    142       image=DestroyImageList(image);
    143       return((Image *) NULL);
    144     }
    145   /*
    146     Read AAI Dune image.
    147   */
    148   width=ReadBlobLSBLong(image);
    149   height=ReadBlobLSBLong(image);
    150   if (EOFBlob(image) != MagickFalse)
    151     ThrowReaderException(CorruptImageError,"ImproperImageHeader");
    152   if ((width == 0UL) || (height == 0UL))
    153     ThrowReaderException(CorruptImageError,"ImproperImageHeader");
    154   do
    155   {
    156     /*
    157       Convert AAI raster image to pixel packets.
    158     */
    159     image->columns=width;
    160     image->rows=height;
    161     image->depth=8;
    162     if ((image_info->ping != MagickFalse) && (image_info->number_scenes != 0))
    163       if (image->scene >= (image_info->scene+image_info->number_scenes-1))
    164         break;
    165     status=SetImageExtent(image,image->columns,image->rows,exception);
    166     if (status == MagickFalse)
    167       return(DestroyImageList(image));
    168     pixels=(unsigned char *) AcquireQuantumMemory(image->columns,
    169       4*sizeof(*pixels));
    170     if (pixels == (unsigned char *) NULL)
    171       ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
    172     length=(size_t) 4*image->columns;
    173     for (y=0; y < (ssize_t) image->rows; y++)
    174     {
    175       count=ReadBlob(image,length,pixels);
    176       if (count != (ssize_t) length)
    177         ThrowReaderException(CorruptImageError,"UnableToReadImageData");
    178       p=pixels;
    179       q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
    180       if (q == (Quantum *) NULL)
    181         break;
    182       for (x=0; x < (ssize_t) image->columns; x++)
    183       {
    184         SetPixelBlue(image,ScaleCharToQuantum(*p++),q);
    185         SetPixelGreen(image,ScaleCharToQuantum(*p++),q);
    186         SetPixelRed(image,ScaleCharToQuantum(*p++),q);
    187         if (*p == 254)
    188           *p=255;
    189         SetPixelAlpha(image,ScaleCharToQuantum(*p++),q);
    190         if (GetPixelAlpha(image,q) != OpaqueAlpha)
    191           image->alpha_trait=BlendPixelTrait;
    192         q+=GetPixelChannels(image);
    193       }
    194       if (SyncAuthenticPixels(image,exception) == MagickFalse)
    195         break;
    196       if (image->previous == (Image *) NULL)
    197         {
    198           status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y,
    199             image->rows);
    200           if (status == MagickFalse)
    201             break;
    202         }
    203     }
    204     pixels=(unsigned char *) RelinquishMagickMemory(pixels);
    205     if (EOFBlob(image) != MagickFalse)
    206       {
    207         ThrowFileException(exception,CorruptImageError,"UnexpectedEndOfFile",
    208           image->filename);
    209         break;
    210       }
    211     /*
    212       Proceed to next image.
    213     */
    214     if (image_info->number_scenes != 0)
    215       if (image->scene >= (image_info->scene+image_info->number_scenes-1))
    216         break;
    217     width=ReadBlobLSBLong(image);
    218     height=ReadBlobLSBLong(image);
    219     if ((width != 0UL) && (height != 0UL))
    220       {
    221         /*
    222           Allocate next image structure.
    223         */
    224         AcquireNextImage(image_info,image,exception);
    225         if (GetNextImageInList(image) == (Image *) NULL)
    226           {
    227             image=DestroyImageList(image);
    228             return((Image *) NULL);
    229           }
    230         image=SyncNextImageInList(image);
    231         status=SetImageProgress(image,LoadImagesTag,TellBlob(image),
    232           GetBlobSize(image));
    233         if (status == MagickFalse)
    234           break;
    235       }
    236   } while ((width != 0UL) && (height != 0UL));
    237   (void) CloseBlob(image);
    238   return(GetFirstImageInList(image));
    239 }
    240 
    241 /*
    243 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    244 %                                                                             %
    245 %                                                                             %
    246 %                                                                             %
    247 %   R e g i s t e r A A I I m a g e                                           %
    248 %                                                                             %
    249 %                                                                             %
    250 %                                                                             %
    251 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    252 %
    253 %  RegisterAAIImage() adds attributes for the AAI Dune image format to the list
    254 %  of supported formats.  The attributes include the image format tag, a
    255 %  method to read and/or write the format, whether the format supports the
    256 %  saving of more than one frame to the same file or blob, whether the format
    257 %  supports native in-memory I/O, and a brief description of the format.
    258 %
    259 %  The format of the RegisterAAIImage method is:
    260 %
    261 %      size_t RegisterAAIImage(void)
    262 %
    263 */
    264 ModuleExport size_t RegisterAAIImage(void)
    265 {
    266   MagickInfo
    267     *entry;
    268 
    269   entry=AcquireMagickInfo("AAI","AAI","AAI Dune image");
    270   entry->decoder=(DecodeImageHandler *) ReadAAIImage;
    271   entry->encoder=(EncodeImageHandler *) WriteAAIImage;
    272   (void) RegisterMagickInfo(entry);
    273   return(MagickImageCoderSignature);
    274 }
    275 
    276 /*
    278 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    279 %                                                                             %
    280 %                                                                             %
    281 %                                                                             %
    282 %   U n r e g i s t e r A A I I m a g e                                       %
    283 %                                                                             %
    284 %                                                                             %
    285 %                                                                             %
    286 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    287 %
    288 %  UnregisterAAIImage() removes format registrations made by the
    289 %  AAI module from the list of supported formats.
    290 %
    291 %  The format of the UnregisterAAIImage method is:
    292 %
    293 %      UnregisterAAIImage(void)
    294 %
    295 */
    296 ModuleExport void UnregisterAAIImage(void)
    297 {
    298   (void) UnregisterMagickInfo("AAI");
    299 }
    300 
    301 /*
    303 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    304 %                                                                             %
    305 %                                                                             %
    306 %                                                                             %
    307 %   W r i t e A A I I m a g e                                                 %
    308 %                                                                             %
    309 %                                                                             %
    310 %                                                                             %
    311 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    312 %
    313 %  WriteAAIImage() writes an image to a file in AAI Dune image format.
    314 %
    315 %  The format of the WriteAAIImage method is:
    316 %
    317 %      MagickBooleanType WriteAAIImage(const ImageInfo *image_info,
    318 %        Image *image,ExceptionInfo *exception)
    319 %
    320 %  A description of each parameter follows.
    321 %
    322 %    o image_info: the image info.
    323 %
    324 %    o image:  The image.
    325 %
    326 %    o exception: return any errors or warnings in this structure.
    327 %
    328 */
    329 static MagickBooleanType WriteAAIImage(const ImageInfo *image_info,Image *image,
    330   ExceptionInfo *exception)
    331 {
    332   MagickBooleanType
    333     status;
    334 
    335   MagickOffsetType
    336     scene;
    337 
    338   register const Quantum
    339     *magick_restrict p;
    340 
    341   register ssize_t
    342     x;
    343 
    344   register unsigned char
    345     *magick_restrict q;
    346 
    347   ssize_t
    348     count,
    349     y;
    350 
    351   unsigned char
    352     *pixels;
    353 
    354   /*
    355     Open output image file.
    356   */
    357   assert(image_info != (const ImageInfo *) NULL);
    358   assert(image_info->signature == MagickCoreSignature);
    359   assert(image != (Image *) NULL);
    360   assert(image->signature == MagickCoreSignature);
    361   if (image->debug != MagickFalse)
    362     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
    363   assert(exception != (ExceptionInfo *) NULL);
    364   assert(exception->signature == MagickCoreSignature);
    365   status=OpenBlob(image_info,image,WriteBinaryBlobMode,exception);
    366   if (status == MagickFalse)
    367     return(status);
    368   scene=0;
    369   do
    370   {
    371     /*
    372       Write AAI header.
    373     */
    374     (void) TransformImageColorspace(image,sRGBColorspace,exception);
    375     (void) WriteBlobLSBLong(image,(unsigned int) image->columns);
    376     (void) WriteBlobLSBLong(image,(unsigned int) image->rows);
    377     /*
    378       Allocate memory for pixels.
    379     */
    380     pixels=(unsigned char *) AcquireQuantumMemory(image->columns,
    381       4*sizeof(*pixels));
    382     if (pixels == (unsigned char *) NULL)
    383       ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
    384     /*
    385       Convert MIFF to AAI raster pixels.
    386     */
    387     for (y=0; y < (ssize_t) image->rows; y++)
    388     {
    389       p=GetVirtualPixels(image,0,y,image->columns,1,exception);
    390       if (p == (const Quantum *) NULL)
    391         break;
    392       q=pixels;
    393       for (x=0; x < (ssize_t) image->columns; x++)
    394       {
    395         *q++=ScaleQuantumToChar(GetPixelBlue(image,p));
    396         *q++=ScaleQuantumToChar(GetPixelGreen(image,p));
    397         *q++=ScaleQuantumToChar(GetPixelRed(image,p));
    398         *q=ScaleQuantumToChar((Quantum) (image->alpha_trait !=
    399           UndefinedPixelTrait ? GetPixelAlpha(image,p) : OpaqueAlpha));
    400         if (*q == 255)
    401           *q=254;
    402         p+=GetPixelChannels(image);
    403         q++;
    404       }
    405       count=WriteBlob(image,(size_t) (q-pixels),pixels);
    406       if (count != (ssize_t) (q-pixels))
    407         break;
    408       if (image->previous == (Image *) NULL)
    409         {
    410           status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
    411             image->rows);
    412           if (status == MagickFalse)
    413             break;
    414         }
    415     }
    416     pixels=(unsigned char *) RelinquishMagickMemory(pixels);
    417     if (GetNextImageInList(image) == (Image *) NULL)
    418       break;
    419     image=SyncNextImageInList(image);
    420     status=SetImageProgress(image,SaveImagesTag,scene++,
    421       GetImageListLength(image));
    422     if (status == MagickFalse)
    423       break;
    424   } while (image_info->adjoin != MagickFalse);
    425   (void) CloseBlob(image);
    426   return(MagickTrue);
    427 }
    428