Home | History | Annotate | Download | only in coders
      1 /*
      2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
      3 %                                                                             %
      4 %                                                                             %
      5 %                                                                             %
      6 %                            M   M  V   V   GGGG                              %
      7 %                            MM MM  V   V  G                                  %
      8 %                            M M M  V   V  G GG                               %
      9 %                            M   M   V V   G   G                              %
     10 %                            M   M    V     GGG                               %
     11 %                                                                             %
     12 %                                                                             %
     13 %                 Read/Write Magick Vector Graphics Metafiles.                %
     14 %                                                                             %
     15 %                              Software Design                                %
     16 %                                   Cristy                                    %
     17 %                                 April 2000                                  %
     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/artifact.h"
     45 #include "MagickCore/blob.h"
     46 #include "MagickCore/blob-private.h"
     47 #include "MagickCore/draw.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/module.h"
     56 #include "MagickCore/property.h"
     57 #include "MagickCore/quantum-private.h"
     58 #include "MagickCore/static.h"
     59 #include "MagickCore/string_.h"
     60 
     61 /*
     63   Forward declarations.
     64 */
     65 static MagickBooleanType
     66   WriteMVGImage(const ImageInfo *,Image *,ExceptionInfo *);
     67 
     68 /*
     70 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     71 %                                                                             %
     72 %                                                                             %
     73 %                                                                             %
     74 %   I s M V G                                                                 %
     75 %                                                                             %
     76 %                                                                             %
     77 %                                                                             %
     78 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     79 %
     80 %  IsMVG() returns MagickTrue if the image format type, identified by the
     81 %  magick string, is MVG.
     82 %
     83 %  The format of the IsMVG method is:
     84 %
     85 %      MagickBooleanType IsMVG(const unsigned char *magick,const size_t length)
     86 %
     87 %  A description of each parameter follows:
     88 %
     89 %    o magick: compare image format pattern against these bytes.
     90 %
     91 %    o length: Specifies the length of the magick string.
     92 %
     93 */
     94 static MagickBooleanType IsMVG(const unsigned char *magick,const size_t length)
     95 {
     96   if (length < 20)
     97     return(MagickFalse);
     98   if (LocaleNCompare((const char *) magick,"push graphic-context",20) == 0)
     99     return(MagickTrue);
    100   return(MagickFalse);
    101 }
    102 
    103 /*
    105 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    106 %                                                                             %
    107 %                                                                             %
    108 %                                                                             %
    109 %   R e a d M V G I m a g e                                                   %
    110 %                                                                             %
    111 %                                                                             %
    112 %                                                                             %
    113 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    114 %
    115 %  ReadMVGImage creates a gradient image and initializes it to
    116 %  the X server color range as specified by the filename.  It allocates the
    117 %  memory necessary for the new Image structure and returns a pointer to the
    118 %  new image.
    119 %
    120 %  The format of the ReadMVGImage method is:
    121 %
    122 %      Image *ReadMVGImage(const ImageInfo *image_info,ExceptionInfo *exception)
    123 %
    124 %  A description of each parameter follows:
    125 %
    126 %    o image_info: the image info.
    127 %
    128 %    o exception: return any errors or warnings in this structure.
    129 %
    130 */
    131 static Image *ReadMVGImage(const ImageInfo *image_info,ExceptionInfo *exception)
    132 {
    133 #define BoundingBox  "viewbox"
    134 
    135   DrawInfo
    136     *draw_info;
    137 
    138   Image
    139     *image;
    140 
    141   MagickBooleanType
    142     status;
    143 
    144   /*
    145     Open image.
    146   */
    147   assert(image_info != (const ImageInfo *) NULL);
    148   assert(image_info->signature == MagickCoreSignature);
    149   if (image_info->debug != MagickFalse)
    150     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
    151       image_info->filename);
    152   assert(exception != (ExceptionInfo *) NULL);
    153   assert(exception->signature == MagickCoreSignature);
    154   image=AcquireImage(image_info,exception);
    155   status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
    156   if (status == MagickFalse)
    157     {
    158       image=DestroyImageList(image);
    159       return((Image *) NULL);
    160     }
    161   if ((image->columns == 0) || (image->rows == 0))
    162     {
    163       char
    164         primitive[MagickPathExtent];
    165 
    166       register char
    167         *p;
    168 
    169       SegmentInfo
    170         bounds;
    171 
    172       /*
    173         Determine size of image canvas.
    174       */
    175       while (ReadBlobString(image,primitive) != (char *) NULL)
    176       {
    177         for (p=primitive; (*p == ' ') || (*p == '\t'); p++) ;
    178         if (LocaleNCompare(BoundingBox,p,strlen(BoundingBox)) != 0)
    179           continue;
    180         (void) sscanf(p,"viewbox %lf %lf %lf %lf",&bounds.x1,&bounds.y1,
    181           &bounds.x2,&bounds.y2);
    182         image->columns=(size_t) floor((bounds.x2-bounds.x1)+0.5);
    183         image->rows=(size_t) floor((bounds.y2-bounds.y1)+0.5);
    184         break;
    185       }
    186     }
    187   if ((image->columns == 0) || (image->rows == 0))
    188     ThrowReaderException(OptionError,"MustSpecifyImageSize");
    189   draw_info=CloneDrawInfo(image_info,(DrawInfo *) NULL);
    190   draw_info->affine.sx=image->resolution.x == 0.0 ? 1.0 : image->resolution.x/
    191     DefaultResolution;
    192   draw_info->affine.sy=image->resolution.y == 0.0 ? 1.0 : image->resolution.y/
    193     DefaultResolution;
    194   image->columns=(size_t) (draw_info->affine.sx*image->columns);
    195   image->rows=(size_t) (draw_info->affine.sy*image->rows);
    196   status=SetImageExtent(image,image->columns,image->rows,exception);
    197   if (status == MagickFalse)
    198     return(DestroyImageList(image));
    199   if (SetImageBackgroundColor(image,exception) == MagickFalse)
    200     {
    201       image=DestroyImageList(image);
    202       return((Image *) NULL);
    203     }
    204   /*
    205     Render drawing.
    206   */
    207   if (GetBlobStreamData(image) == (unsigned char *) NULL)
    208     draw_info->primitive=FileToString(image->filename,~0UL,exception);
    209   else
    210     {
    211       draw_info->primitive=(char *) AcquireMagickMemory(GetBlobSize(image)+1);
    212       if (draw_info->primitive != (char *) NULL)
    213         {
    214           CopyMagickMemory(draw_info->primitive,GetBlobStreamData(image),
    215             GetBlobSize(image));
    216           draw_info->primitive[GetBlobSize(image)]='\0';
    217         }
    218      }
    219   if (draw_info->primitive == (char *) NULL)
    220     ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
    221   (void) DrawImage(image,draw_info,exception);
    222   draw_info=DestroyDrawInfo(draw_info);
    223   (void) CloseBlob(image);
    224   return(GetFirstImageInList(image));
    225 }
    226 
    227 /*
    229 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    230 %                                                                             %
    231 %                                                                             %
    232 %                                                                             %
    233 %   R e g i s t e r M V G I m a g e                                           %
    234 %                                                                             %
    235 %                                                                             %
    236 %                                                                             %
    237 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    238 %
    239 %  RegisterMVGImage() adds properties for the MVG image format
    240 %  to the list of supported formats.  The properties include the image format
    241 %  tag, a method to read and/or write the format, whether the format
    242 %  supports the saving of more than one frame to the same file or blob,
    243 %  whether the format supports native in-memory I/O, and a brief
    244 %  description of the format.
    245 %
    246 %  The format of the RegisterMVGImage method is:
    247 %
    248 %      size_t RegisterMVGImage(void)
    249 %
    250 */
    251 ModuleExport size_t RegisterMVGImage(void)
    252 {
    253   MagickInfo
    254     *entry;
    255 
    256   entry=AcquireMagickInfo("MVG","MVG","Magick Vector Graphics");
    257   entry->decoder=(DecodeImageHandler *) ReadMVGImage;
    258   entry->encoder=(EncodeImageHandler *) WriteMVGImage;
    259   entry->magick=(IsImageFormatHandler *) IsMVG;
    260   entry->format_type=ImplicitFormatType;
    261   entry->flags^=CoderAdjoinFlag;
    262   entry->flags|=CoderSeekableStreamFlag;
    263   (void) RegisterMagickInfo(entry);
    264   return(MagickImageCoderSignature);
    265 }
    266 
    267 /*
    269 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    270 %                                                                             %
    271 %                                                                             %
    272 %                                                                             %
    273 %   U n r e g i s t e r M V G I m a g e                                       %
    274 %                                                                             %
    275 %                                                                             %
    276 %                                                                             %
    277 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    278 %
    279 %  UnregisterMVGImage() removes format registrations made by the
    280 %  MVG module from the list of supported formats.
    281 %
    282 %  The format of the UnregisterMVGImage method is:
    283 %
    284 %      UnregisterMVGImage(void)
    285 %
    286 */
    287 ModuleExport void UnregisterMVGImage(void)
    288 {
    289   (void) UnregisterMagickInfo("MVG");
    290 }
    291 
    292 /*
    294 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    295 %                                                                             %
    296 %                                                                             %
    297 %                                                                             %
    298 %   W r i t e M V G I m a g e                                                 %
    299 %                                                                             %
    300 %                                                                             %
    301 %                                                                             %
    302 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    303 %
    304 %  WriteMVGImage() writes an image to a file in MVG image format.
    305 %
    306 %  The format of the WriteMVGImage method is:
    307 %
    308 %      MagickBooleanType WriteMVGImage(const ImageInfo *image_info,
    309 %        Image *image,ExceptionInfo *exception)
    310 %
    311 %  A description of each parameter follows.
    312 %
    313 %    o image_info: the image info.
    314 %
    315 %    o image:  The image.
    316 %
    317 %    o exception: return any errors or warnings in this structure.
    318 %
    319 */
    320 static MagickBooleanType WriteMVGImage(const ImageInfo *image_info,Image *image,
    321   ExceptionInfo *exception)
    322 {
    323   const char
    324     *value;
    325 
    326   MagickBooleanType
    327     status;
    328 
    329   /*
    330     Open output image file.
    331   */
    332   assert(image_info != (const ImageInfo *) NULL);
    333   assert(image_info->signature == MagickCoreSignature);
    334   assert(image != (Image *) NULL);
    335   assert(image->signature == MagickCoreSignature);
    336   if (image->debug != MagickFalse)
    337     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
    338   value=GetImageArtifact(image,"MVG");
    339   if (value == (const char *) NULL)
    340     ThrowWriterException(OptionError,"NoImageVectorGraphics");
    341   status=OpenBlob(image_info,image,WriteBlobMode,exception);
    342   if (status == MagickFalse)
    343     return(status);
    344   (void) WriteBlob(image,strlen(value),(const unsigned char *) value);
    345   (void) CloseBlob(image);
    346   return(MagickTrue);
    347 }
    348