Home | History | Annotate | Download | only in coders
      1 /*
      2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
      3 %                                                                             %
      4 %                                                                             %
      5 %                                                                             %
      6 %                  IIIII  N   N  L      IIIII  N   N  EEEEE                   %
      7 %                    I    NN  N  L        I    NN  N  E                       %
      8 %                    I    N N N  L        I    N N N  EEE                     %
      9 %                    I    N  NN  L        I    N  NN  E                       %
     10 %                  IIIII  N   N  LLLLL  IIIII  N   N  EEEEE                   %
     11 %                                                                             %
     12 %                                                                             %
     13 %                            Read Inline Images                               %
     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/client.h"
     47 #include "MagickCore/constitute.h"
     48 #include "MagickCore/display.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/option.h"
     57 #include "MagickCore/quantum-private.h"
     58 #include "MagickCore/static.h"
     59 #include "MagickCore/string_.h"
     60 #include "MagickCore/module.h"
     61 #include "MagickCore/utility.h"
     62 #include "MagickCore/xwindow.h"
     63 #include "MagickCore/xwindow-private.h"
     64 
     65 /*
     67   Forward declarations.
     68 */
     69 static MagickBooleanType
     70   WriteINLINEImage(const ImageInfo *,Image *,ExceptionInfo *);
     71 
     72 /*
     74 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     75 %                                                                             %
     76 %                                                                             %
     77 %                                                                             %
     78 %   R e a d I N L I N E I m a g e                                             %
     79 %                                                                             %
     80 %                                                                             %
     81 %                                                                             %
     82 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     83 %
     84 %  ReadINLINEImage() reads base64-encoded inlines images.
     85 %
     86 %  The format of the ReadINLINEImage method is:
     87 %
     88 %      Image *ReadINLINEImage(const ImageInfo *image_info,
     89 %        ExceptionInfo *exception)
     90 %
     91 %  A description of each parameter follows:
     92 %
     93 %    o image_info: the image info.
     94 %
     95 %    o exception: return any errors or warnings in this structure.
     96 %
     97 */
     98 static Image *ReadINLINEImage(const ImageInfo *image_info,
     99   ExceptionInfo *exception)
    100 {
    101   Image
    102     *image;
    103 
    104   MagickBooleanType
    105     status;
    106 
    107   register size_t
    108     i;
    109 
    110   size_t
    111     quantum;
    112 
    113   ssize_t
    114     count;
    115 
    116   unsigned char
    117     *inline_image;
    118 
    119   /*
    120     Open image file.
    121   */
    122   assert(image_info != (const ImageInfo *) NULL);
    123   assert(image_info->signature == MagickCoreSignature);
    124   if (image_info->debug != MagickFalse)
    125     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
    126       image_info->filename);
    127   assert(exception != (ExceptionInfo *) NULL);
    128   assert(exception->signature == MagickCoreSignature);
    129   if (LocaleCompare(image_info->magick,"DATA") == 0)
    130     {
    131       char
    132         *filename;
    133 
    134       Image
    135         *data_image;
    136 
    137       filename=AcquireString("data:");
    138       (void) ConcatenateMagickString(filename,image_info->filename,
    139         MagickPathExtent);
    140       data_image=ReadInlineImage(image_info,filename,exception);
    141       filename=DestroyString(filename);
    142       return(data_image);
    143     }
    144   image=AcquireImage(image_info,exception);
    145   status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
    146   if (status == MagickFalse)
    147     {
    148       image=DestroyImageList(image);
    149       return((Image *) NULL);
    150     }
    151   quantum=MagickMin((size_t) GetBlobSize(image),MagickMaxBufferExtent);
    152   if (quantum == 0)
    153     quantum=MagickMaxBufferExtent;
    154   inline_image=(unsigned char *) AcquireQuantumMemory(quantum,
    155     sizeof(*inline_image));
    156   count=0;
    157   for (i=0; inline_image != (unsigned char *) NULL; i+=count)
    158   {
    159     count=(ssize_t) ReadBlob(image,quantum,inline_image+i);
    160     if (count <= 0)
    161       {
    162         count=0;
    163         if (errno != EINTR)
    164           break;
    165       }
    166     if (~((size_t) i) < (quantum+1))
    167       {
    168         inline_image=(unsigned char *) RelinquishMagickMemory(inline_image);
    169         break;
    170       }
    171     inline_image=(unsigned char *) ResizeQuantumMemory(inline_image,i+count+
    172       quantum+1,sizeof(*inline_image));
    173   }
    174   if (inline_image == (unsigned char *) NULL)
    175     {
    176       (void) ThrowMagickException(exception,GetMagickModule(),
    177         ResourceLimitError,"MemoryAllocationFailed","`%s'",image->filename);
    178       return((Image *) NULL);
    179     }
    180   inline_image[i+count]='\0';
    181   image=DestroyImageList(image);
    182   image=ReadInlineImage(image_info,(char *) inline_image,exception);
    183   inline_image=(unsigned char *) RelinquishMagickMemory(inline_image);
    184   return(image);
    185 }
    186 
    187 /*
    189 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    190 %                                                                             %
    191 %                                                                             %
    192 %                                                                             %
    193 %   R e g i s t e r I N L I N E I m a g e                                     %
    194 %                                                                             %
    195 %                                                                             %
    196 %                                                                             %
    197 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    198 %
    199 %  RegisterINLINEImage() adds attributes for the INLINE image format to
    200 %  the list of supported formats.  The attributes include the image format
    201 %  tag, a method to read and/or write the format, whether the format
    202 %  supports the saving of more than one frame to the same file or blob,
    203 %  whether the format supports native in-memory I/O, and a brief
    204 %  description of the format.
    205 %
    206 %  The format of the RegisterINLINEImage method is:
    207 %
    208 %      size_t RegisterINLINEImage(void)
    209 %
    210 */
    211 ModuleExport size_t RegisterINLINEImage(void)
    212 {
    213   MagickInfo
    214     *entry;
    215 
    216   entry=AcquireMagickInfo("DATA","INLINE","Base64-encoded inline images");
    217   entry->decoder=(DecodeImageHandler *) ReadINLINEImage;
    218   entry->encoder=(EncodeImageHandler *) WriteINLINEImage;
    219   entry->format_type=ImplicitFormatType;
    220   (void) RegisterMagickInfo(entry);
    221   entry=AcquireMagickInfo("INLINE","INLINE","Base64-encoded inline images");
    222   entry->decoder=(DecodeImageHandler *) ReadINLINEImage;
    223   entry->encoder=(EncodeImageHandler *) WriteINLINEImage;
    224   entry->format_type=ImplicitFormatType;
    225   (void) RegisterMagickInfo(entry);
    226   return(MagickImageCoderSignature);
    227 }
    228 
    229 /*
    231 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    232 %                                                                             %
    233 %                                                                             %
    234 %                                                                             %
    235 %   U n r e g i s t e r I N L I N E I m a g e                                 %
    236 %                                                                             %
    237 %                                                                             %
    238 %                                                                             %
    239 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    240 %
    241 %  UnregisterINLINEImage() removes format registrations made by the
    242 %  INLINE module from the list of supported formats.
    243 %
    244 %  The format of the UnregisterINLINEImage method is:
    245 %
    246 %      UnregisterINLINEImage(void)
    247 %
    248 */
    249 ModuleExport void UnregisterINLINEImage(void)
    250 {
    251   (void) UnregisterMagickInfo("INLINE");
    252   (void) UnregisterMagickInfo("DATA");
    253 }
    254 
    255 /*
    257 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    258 %                                                                             %
    259 %                                                                             %
    260 %                                                                             %
    261 %   W r i t e I N L I N E I m a g e                                           %
    262 %                                                                             %
    263 %                                                                             %
    264 %                                                                             %
    265 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    266 %
    267 %  WriteINLINEImage() writes an image to a file in INLINE format (Base64).
    268 %
    269 %  The format of the WriteINLINEImage method is:
    270 %
    271 %      MagickBooleanType WriteINLINEImage(const ImageInfo *image_info,
    272 %        Image *image,ExceptionInfo *exception)
    273 %
    274 %  A description of each parameter follows.
    275 %
    276 %    o image_info: the image info.
    277 %
    278 %    o image:  The image.
    279 %
    280 %    o exception: return any errors or warnings in this structure.
    281 %
    282 */
    283 static MagickBooleanType WriteINLINEImage(const ImageInfo *image_info,
    284   Image *image,ExceptionInfo *exception)
    285 {
    286   char
    287     *base64,
    288     message[MagickPathExtent];
    289 
    290   const MagickInfo
    291     *magick_info;
    292 
    293   Image
    294     *write_image;
    295 
    296   ImageInfo
    297     *write_info;
    298 
    299   MagickBooleanType
    300     status;
    301 
    302   size_t
    303     blob_length,
    304     encode_length;
    305 
    306   unsigned char
    307     *blob;
    308 
    309   /*
    310     Convert image to base64-encoding.
    311   */
    312   assert(image_info != (const ImageInfo *) NULL);
    313   assert(image_info->signature == MagickCoreSignature);
    314   assert(image != (Image *) NULL);
    315   assert(image->signature == MagickCoreSignature);
    316   if (image->debug != MagickFalse)
    317     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
    318   write_info=CloneImageInfo(image_info);
    319   (void) SetImageInfo(write_info,1,exception);
    320   if (LocaleCompare(write_info->magick,"INLINE") == 0)
    321     (void) CopyMagickString(write_info->magick,image->magick,MagickPathExtent);
    322   magick_info=GetMagickInfo(write_info->magick,exception);
    323   if ((magick_info == (const MagickInfo *) NULL) ||
    324       (GetMagickMimeType(magick_info) == (const char *) NULL))
    325     ThrowWriterException(CorruptImageError,"ImageTypeNotSupported");
    326   (void) CopyMagickString(image->filename,write_info->filename,
    327     MagickPathExtent);
    328   blob_length=2048;
    329   write_image=CloneImage(image,0,0,MagickTrue,exception);
    330   if (write_image == (Image *) NULL)
    331     {
    332       write_info=DestroyImageInfo(write_info);
    333       return(MagickTrue);
    334     }
    335   blob=(unsigned char *) ImageToBlob(write_info,write_image,&blob_length,
    336     exception);
    337   write_image=DestroyImage(write_image);
    338   write_info=DestroyImageInfo(write_info);
    339   if (blob == (unsigned char *) NULL)
    340     return(MagickFalse);
    341   encode_length=0;
    342   base64=Base64Encode(blob,blob_length,&encode_length);
    343   blob=(unsigned char *) RelinquishMagickMemory(blob);
    344   if (base64 == (char *) NULL)
    345     ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
    346   /*
    347     Write base64-encoded image.
    348   */
    349   status=OpenBlob(image_info,image,WriteBinaryBlobMode,exception);
    350   if (status == MagickFalse)
    351     {
    352       base64=DestroyString(base64);
    353       return(status);
    354     }
    355   (void) FormatLocaleString(message,MagickPathExtent,"data:%s;base64,",
    356     GetMagickMimeType(magick_info));
    357   (void) WriteBlobString(image,message);
    358   (void) WriteBlobString(image,base64);
    359   base64=DestroyString(base64);
    360   return(MagickTrue);
    361 }
    362