Home | History | Annotate | Download | only in source
      1 /*
      2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
      3 %                                                                             %
      4 %                                                                             %
      5 %                                                                             %
      6 %                            M   M   GGGG  K   K                              %
      7 %                            MM MM  G      K  K                               %
      8 %                            M M M  G  GG  KKK                                %
      9 %                            M   M  G   G  K  K                               %
     10 %                            M   M   GGG   K   K                              %
     11 %                                                                             %
     12 %                                                                             %
     13 %                        Read/Write MGK Image Format.                         %
     14 %                                                                             %
     15 %                              Software Design                                %
     16 %                                Cristy                                  %
     17 %                                 July 1992                                   %
     18 %                                                                             %
     19 %                                                                             %
     20 %  Copyright 1999-2011 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 "magick/studio.h"
     44 #include "magick/blob.h"
     45 #include "magick/blob-private.h"
     46 #include "magick/cache.h"
     47 #include "magick/colorspace.h"
     48 #include "magick/exception.h"
     49 #include "magick/exception-private.h"
     50 #include "magick/image.h"
     51 #include "magick/image-private.h"
     52 #include "magick/list.h"
     53 #include "magick/magick.h"
     54 #include "magick/memory_.h"
     55 #include "magick/monitor.h"
     56 #include "magick/monitor-private.h"
     57 #include "magick/quantum-private.h"
     58 #include "magick/static.h"
     59 #include "magick/string_.h"
     60 #include "magick/module.h"
     61 
     62 /*
     64   Forward declarations.
     65 */
     66 static MagickBooleanType
     67   WriteMGKImage(const ImageInfo *,Image *);
     68 
     69 /*
     71 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     72 %                                                                             %
     73 %                                                                             %
     74 %                                                                             %
     75 %   I s M G K                                                                 %
     76 %                                                                             %
     77 %                                                                             %
     78 %                                                                             %
     79 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     80 %
     81 %  IsMGK() returns MagickTrue if the image format type, identified by the
     82 %  magick string, is MGK.
     83 %
     84 %  The format of the IsMGK method is:
     85 %
     86 %      MagickBooleanType IsMGK(const unsigned char *magick,const size_t length)
     87 %
     88 %  A description of each parameter follows:
     89 %
     90 %    o magick: This string is generally the first few bytes of an image file
     91 %      or blob.
     92 %
     93 %    o length: Specifies the length of the magick string.
     94 %
     95 */
     96 static MagickBooleanType IsMGK(const unsigned char *magick,const size_t length)
     97 {
     98   if (length < 7)
     99     return(MagickFalse);
    100   if (LocaleNCompare((char *) magick,"id=mgk",7) == 0)
    101     return(MagickTrue);
    102   return(MagickFalse);
    103 }
    104 
    105 /*
    107 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    108 %                                                                             %
    109 %                                                                             %
    110 %                                                                             %
    111 %   R e a d M G K I m a g e                                                   %
    112 %                                                                             %
    113 %                                                                             %
    114 %                                                                             %
    115 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    116 %
    117 %  ReadMGKImage() reads a MGK image file and returns it.  It allocates
    118 %  the memory necessary for the new Image structure and returns a pointer to
    119 %  the new image.
    120 %
    121 %  The format of the ReadMGKImage method is:
    122 %
    123 %      Image *ReadMGKImage(const ImageInfo *image_info,
    124 %        ExceptionInfo *exception)
    125 %
    126 %  A description of each parameter follows:
    127 %
    128 %    o image_info: the image info.
    129 %
    130 %    o exception: return any errors or warnings in this structure.
    131 %
    132 */
    133 static Image *ReadMGKImage(const ImageInfo *image_info,
    134   ExceptionInfo *exception)
    135 {
    136   char
    137     buffer[MagickPathExtent];
    138 
    139   Image
    140     *image;
    141 
    142   MagickBooleanType
    143     status;
    144 
    145   register ssize_t
    146     x;
    147 
    148   register PixelPacket
    149     *q;
    150 
    151   register unsigned char
    152     *p;
    153 
    154   ssize_t
    155     count,
    156     y;
    157 
    158   size_t
    159     columns,
    160     rows;
    161 
    162   unsigned char
    163     *pixels;
    164 
    165   /*
    166     Open image file.
    167   */
    168   assert(image_info != (const ImageInfo *) NULL);
    169   assert(image_info->signature == MagickSignature);
    170   if (image_info->debug != MagickFalse)
    171     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
    172       image_info->filename);
    173   assert(exception != (ExceptionInfo *) NULL);
    174   assert(exception->signature == MagickSignature);
    175   image=AcquireImage(image_info);
    176   status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
    177   if (status == MagickFalse)
    178     {
    179       image=DestroyImageList(image);
    180       return((Image *) NULL);
    181     }
    182   /*
    183     Read MGK image.
    184   */
    185   (void) ReadBlobString(image,buffer);  /* read magic number */
    186   if (IsMGK(buffer,7) == MagickFalse)
    187     ThrowReaderException(CorruptImageError,"ImproperImageHeader");
    188   (void) ReadBlobString(image,buffer);
    189   count=(ssize_t) sscanf(buffer,"%lu %lu\n",&columns,&rows);
    190   if (count <= 0)
    191     ThrowReaderException(CorruptImageError,"ImproperImageHeader");
    192   do
    193   {
    194     /*
    195       Initialize image structure.
    196     */
    197     image->columns=columns;
    198     image->rows=rows;
    199     image->depth=8;
    200     if ((image_info->ping != MagickFalse) && (image_info->number_scenes != 0))
    201       if (image->scene >= (image_info->scene+image_info->number_scenes-1))
    202         break;
    203     /*
    204       Convert MGK raster image to pixel packets.
    205     */
    206     if (SetImageExtent(image,0,0) == MagickFalse)
    207       {
    208         InheritException(exception,&image->exception);
    209         return(DestroyImageList(image));
    210       }
    211     pixels=(unsigned char *) AcquireQuantumMemory((size_t) image->columns,
    212       3UL*sizeof(*pixels));
    213     if (pixels == (unsigned char *) NULL)
    214       ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
    215     for (y=0; y < (ssize_t) image->rows; y++)
    216     {
    217       count=(ssize_t) ReadBlob(image,(size_t) (3*image->columns),pixels);
    218       if (count != (ssize_t) (3*image->columns))
    219         ThrowReaderException(CorruptImageError,"UnableToReadImageData");
    220       p=pixels;
    221       q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
    222       if (q == (PixelPacket *) NULL)
    223         break;
    224       for (x=0; x < (ssize_t) image->columns; x++)
    225       {
    226         SetPixelRed(q,ScaleCharToQuantum(*p++));
    227         SetPixelGreen(q,ScaleCharToQuantum(*p++));
    228         SetPixelBlue(q,ScaleCharToQuantum(*p++));
    229         q++;
    230       }
    231       if (SyncAuthenticPixels(image,exception) == MagickFalse)
    232         break;
    233       if ((image->previous == (Image *) NULL) &&
    234           (SetImageProgress(image,LoadImageTag,y,image->rows) == MagickFalse))
    235         break;
    236     }
    237     pixels=(unsigned char *) RelinquishMagickMemory(pixels);
    238     if (EOFBlob(image) != MagickFalse)
    239       {
    240         ThrowFileException(exception,CorruptImageError,"UnexpectedEndOfFile",
    241           image->filename);
    242         break;
    243       }
    244     /*
    245       Proceed to next image.
    246     */
    247     if (image_info->number_scenes != 0)
    248       if (image->scene >= (image_info->scene+image_info->number_scenes-1))
    249         break;
    250     *buffer='\0';
    251     (void) ReadBlobString(image,buffer);
    252     count=(ssize_t) sscanf(buffer,"%lu %lu\n",&columns,&rows);
    253     if (count > 0)
    254       {
    255         /*
    256           Allocate next image structure.
    257         */
    258         AcquireNextImage(image_info,image);
    259         if (GetNextImageInList(image) == (Image *) NULL)
    260           {
    261             image=DestroyImageList(image);
    262             return((Image *) NULL);
    263           }
    264         image=SyncNextImageInList(image);
    265         if (image->progress_monitor != (MagickProgressMonitor) NULL)
    266           {
    267             status=SetImageProgress(image,LoadImageTag,TellBlob(image),
    268               GetBlobSize(image));
    269             if (status == MagickFalse)
    270               break;
    271           }
    272       }
    273   } while (count > 0);
    274   (void) CloseBlob(image);
    275   return(GetFirstImageInList(image));
    276 }
    277 
    278 /*
    280 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    281 %                                                                             %
    282 %                                                                             %
    283 %                                                                             %
    284 %   R e g i s t e r M G K I m a g e                                           %
    285 %                                                                             %
    286 %                                                                             %
    287 %                                                                             %
    288 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    289 %
    290 %  RegisterMGKImage() adds attributes for the MGK image format to
    291 %  the list of supported formats.  The attributes include the image format
    292 %  tag, a method to read and/or write the format, whether the format
    293 %  supports the saving of more than one frame to the same file or blob,
    294 %  whether the format supports native in-memory I/O, and a brief
    295 %  description of the format.
    296 %
    297 %  The format of the RegisterMGKImage method is:
    298 %
    299 %      size_t RegisterMGKImage(void)
    300 %
    301 */
    302 ModuleExport size_t RegisterMGKImage(void)
    303 {
    304   MagickInfo
    305     *entry;
    306 
    307   entry=SetMagickInfo("MGK");
    308   entry->decoder=(DecodeImageHandler *) ReadMGKImage;
    309   entry->encoder=(EncodeImageHandler *) WriteMGKImage;
    310   entry->magick=(IsImageFormatHandler *) IsMGK;
    311   entry->description=ConstantString("MGK");
    312   entry->module=ConstantString("MGK");
    313   (void) RegisterMagickInfo(entry);
    314   return(MagickImageCoderSignature);
    315 }
    316 
    317 /*
    319 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    320 %                                                                             %
    321 %                                                                             %
    322 %                                                                             %
    323 %   U n r e g i s t e r M G K I m a g e                                       %
    324 %                                                                             %
    325 %                                                                             %
    326 %                                                                             %
    327 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    328 %
    329 %  UnregisterMGKImage() removes format registrations made by the
    330 %  MGK module from the list of supported formats.
    331 %
    332 %  The format of the UnregisterMGKImage method is:
    333 %
    334 %      UnregisterMGKImage(void)
    335 %
    336 */
    337 ModuleExport void UnregisterMGKImage(void)
    338 {
    339   (void) UnregisterMagickInfo("MGK");
    340 }
    341 
    342 /*
    344 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    345 %                                                                             %
    346 %                                                                             %
    347 %                                                                             %
    348 %   W r i t e M G K I m a g e                                                 %
    349 %                                                                             %
    350 %                                                                             %
    351 %                                                                             %
    352 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    353 %
    354 %  WriteMGKImage() writes an image to a file in red, green, and blue
    355 %  MGK rasterfile format.
    356 %
    357 %  The format of the WriteMGKImage method is:
    358 %
    359 %      MagickBooleanType WriteMGKImage(const ImageInfo *image_info,
    360 %        Image *image)
    361 %
    362 %  A description of each parameter follows.
    363 %
    364 %    o image_info: the image info.
    365 %
    366 %    o image:  The image.
    367 %
    368 */
    369 static MagickBooleanType WriteMGKImage(const ImageInfo *image_info,
    370   Image *image)
    371 {
    372   char
    373     buffer[MagickPathExtent];
    374 
    375   MagickBooleanType
    376     status;
    377 
    378   MagickOffsetType
    379     scene;
    380 
    381   register const PixelPacket
    382     *p;
    383 
    384   register ssize_t
    385     x;
    386 
    387   register unsigned char
    388     *q;
    389 
    390   ssize_t
    391     y;
    392 
    393   unsigned char
    394     *pixels;
    395 
    396   /*
    397     Open output image file.
    398   */
    399   assert(image_info != (const ImageInfo *) NULL);
    400   assert(image_info->signature == MagickSignature);
    401   assert(image != (Image *) NULL);
    402   assert(image->signature == MagickSignature);
    403   if (image->debug != MagickFalse)
    404     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
    405   status=OpenBlob(image_info,image,WriteBinaryBlobMode,&image->exception);
    406   if (status == MagickFalse)
    407     return(status);
    408   scene=0;
    409   do
    410   {
    411     /*
    412       Allocate memory for pixels.
    413     */
    414     if (image->colorspace != RGBColorspace)
    415       (void) SetImageColorspace(image,RGBColorspace);
    416     pixels=(unsigned char *) AcquireQuantumMemory((size_t) image->columns,
    417       3UL*sizeof(*pixels));
    418     if (pixels == (unsigned char *) NULL)
    419       ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
    420     /*
    421       Initialize raster file header.
    422     */
    423     (void) WriteBlobString(image,"id=mgk\n");
    424     (void) FormatMagickString(buffer,MagickPathExtent,"%lu %lu\n",image->columns,
    425       image->rows);
    426     (void) WriteBlobString(image,buffer);
    427     for (y=0; y < (ssize_t) image->rows; y++)
    428     {
    429       p=AcquireImagePixels(image,0,y,image->columns,1,&image->exception);
    430       if (p == (const PixelPacket *) NULL)
    431         break;
    432       q=pixels;
    433       for (x=0; x < (ssize_t) image->columns; x++)
    434       {
    435         *q++=ScaleQuantumToChar(GetRedSample(p));
    436         *q++=ScaleQuantumToChar(GetGreenSample(p));
    437         *q++=ScaleQuantumToChar(GetBlueSample(p));
    438         p++;
    439       }
    440       (void) WriteBlob(image,(size_t) (q-pixels),pixels);
    441       if ((image->previous == (Image *) NULL) &&
    442           (SetImageProgress(image,SaveImageTag,y,image->rows) == MagickFalse))
    443         break;
    444     }
    445     pixels=(unsigned char *) RelinquishMagickMemory(pixels);
    446     if (GetNextImageInList(image) == (Image *) NULL)
    447       break;
    448     image=SyncNextImageInList(image);
    449     status=SetImageProgress(image,SaveImagesTag,scene,
    450       GetImageListLength(image));
    451     if (status == MagickFalse)
    452       break;
    453     scene++;
    454   } while (image_info->adjoin != MagickFalse);
    455   (void) CloseBlob(image);
    456   return(MagickTrue);
    457 }
    458