Home | History | Annotate | Download | only in coders
      1 /*
      2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
      3 %                                                                             %
      4 %                                                                             %
      5 %                                                                             %
      6 %                            RRRR    GGG   FFFFF                              %
      7 %                            R   R  G      F                                  %
      8 %                            RRRR   G  GG  FFF                                %
      9 %                            R  R   G   G  F                                  %
     10 %                            R   R   GGG   F                                  %
     11 %                                                                             %
     12 %                                                                             %
     13 %                  Read/Write LEGO Mindstorms EV3 Robot Graphics File         %
     14 %                                                                             %
     15 %                              Software Design                                %
     16 %                               Brian Wheeler                                 %
     17 %                               August 2013                                   %
     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/attribute.h"
     45 #include "MagickCore/blob.h"
     46 #include "MagickCore/blob-private.h"
     47 #include "MagickCore/cache.h"
     48 #include "MagickCore/color-private.h"
     49 #include "MagickCore/colormap.h"
     50 #include "MagickCore/colorspace.h"
     51 #include "MagickCore/colorspace-private.h"
     52 #include "MagickCore/exception.h"
     53 #include "MagickCore/exception-private.h"
     54 #include "MagickCore/image.h"
     55 #include "MagickCore/image-private.h"
     56 #include "MagickCore/list.h"
     57 #include "MagickCore/magick.h"
     58 #include "MagickCore/memory_.h"
     59 #include "MagickCore/monitor.h"
     60 #include "MagickCore/monitor-private.h"
     61 #include "MagickCore/pixel-accessor.h"
     62 #include "MagickCore/quantum-private.h"
     63 #include "MagickCore/static.h"
     64 #include "MagickCore/string_.h"
     65 #include "MagickCore/module.h"
     66 #include "MagickCore/utility.h"
     67 
     68 /*
     70   Forward declarations.
     71 */
     72 static MagickBooleanType
     73   WriteRGFImage(const ImageInfo *,Image *,ExceptionInfo *);
     74 
     75 /*
     77 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     78 %                                                                             %
     79 %                                                                             %
     80 %                                                                             %
     81 %   R e a d X B M I m a g e                                                   %
     82 %                                                                             %
     83 %                                                                             %
     84 %                                                                             %
     85 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     86 %
     87 %  ReadRGFImage() reads an RGF bitmap image file and returns it.  It
     88 %  allocates the memory necessary for the new Image structure and returns a
     89 %  pointer to the new image.
     90 %
     91 %  The format of the ReadRGFImage method is:
     92 %
     93 %      Image *ReadRGFImage(const ImageInfo *image_info,ExceptionInfo *exception)
     94 %
     95 %  A description of each parameter follows:
     96 %
     97 %    o image_info: the image info.
     98 %
     99 %    o exception: return any errors or warnings in this structure.
    100 %
    101 */
    102 static Image *ReadRGFImage(const ImageInfo *image_info,ExceptionInfo *exception)
    103 {
    104   Image
    105     *image;
    106 
    107   int
    108     bit;
    109 
    110   MagickBooleanType
    111     status;
    112 
    113   register ssize_t
    114     i,
    115     x;
    116 
    117   register Quantum
    118     *q;
    119 
    120   register unsigned char
    121     *p;
    122 
    123   ssize_t
    124     y;
    125 
    126   unsigned char
    127     byte,
    128     *data;
    129 
    130   /*
    131     Open image file.
    132   */
    133   assert(image_info != (const ImageInfo *) NULL);
    134   assert(image_info->signature == MagickCoreSignature);
    135   if (image_info->debug != MagickFalse)
    136     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
    137       image_info->filename);
    138   assert(exception != (ExceptionInfo *) NULL);
    139   assert(exception->signature == MagickCoreSignature);
    140   image=AcquireImage(image_info,exception);
    141   status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
    142   if (status == MagickFalse)
    143     {
    144       image=DestroyImageList(image);
    145       return((Image *) NULL);
    146     }
    147   /*
    148     Read RGF header.
    149   */
    150   image->columns = (unsigned long) ReadBlobByte(image);
    151   image->rows = (unsigned long) ReadBlobByte(image);
    152   image->depth=8;
    153   image->storage_class=PseudoClass;
    154   image->colors=2;
    155   /*
    156     Initialize image structure.
    157   */
    158   if (AcquireImageColormap(image,image->colors,exception) == MagickFalse)
    159     ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
    160   /*
    161     Initialize colormap.
    162   */
    163   image->colormap[0].red=QuantumRange;
    164   image->colormap[0].green=QuantumRange;
    165   image->colormap[0].blue=QuantumRange;
    166   image->colormap[1].red=(Quantum) 0;
    167   image->colormap[1].green=(Quantum) 0;
    168   image->colormap[1].blue=(Quantum) 0;
    169   if (image_info->ping != MagickFalse)
    170     {
    171       (void) CloseBlob(image);
    172       return(GetFirstImageInList(image));
    173     }
    174   status=SetImageExtent(image,image->columns,image->rows,exception);
    175   if (status == MagickFalse)
    176     return(DestroyImageList(image));
    177   /*
    178     Read hex image data.
    179   */
    180   data=(unsigned char *) AcquireQuantumMemory(image->rows,image->columns*
    181     sizeof(*data));
    182   if (data == (unsigned char *) NULL)
    183     ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
    184   p=data;
    185   for (i=0; i < (ssize_t) (image->columns * image->rows); i++)
    186     {
    187       *p++=ReadBlobByte(image);
    188     }
    189 
    190   /*
    191     Convert RGF image to pixel packets.
    192   */
    193   p=data;
    194   for (y=0; y < (ssize_t) image->rows; y++)
    195   {
    196     q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
    197     if (q == (Quantum *) NULL)
    198       break;
    199     bit=0;
    200     byte=0;
    201     for (x=0; x < (ssize_t) image->columns; x++)
    202     {
    203       if (bit == 0)
    204         byte=(size_t) (*p++);
    205       SetPixelIndex(image,(Quantum) ((byte & 0x01) != 0 ? 0x01 : 0x00),q);
    206       bit++;
    207       byte>>=1;
    208       if (bit == 8)
    209         bit=0;
    210       q+=GetPixelChannels(image);
    211     }
    212     if (SyncAuthenticPixels(image,exception) == MagickFalse)
    213       break;
    214     status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y,
    215       image->rows);
    216     if (status == MagickFalse)
    217       break;
    218   }
    219   data=(unsigned char *) RelinquishMagickMemory(data);
    220   (void) SyncImage(image,exception);
    221   (void) CloseBlob(image);
    222   return(GetFirstImageInList(image));
    223 }
    224 
    225 /*
    227 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    228 %                                                                             %
    229 %                                                                             %
    230 %                                                                             %
    231 %   R e g i s t e r R G F I m a g e                                           %
    232 %                                                                             %
    233 %                                                                             %
    234 %                                                                             %
    235 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    236 %
    237 %  RegisterRGFImage() adds attributes for the RGF image format to
    238 %  the list of supported formats.  The attributes include the image format
    239 %  tag, a method to read and/or write the format, whether the format
    240 %  supports the saving of more than one frame to the same file or blob,
    241 %  whether the format supports native in-memory I/O, and a brief
    242 %  description of the format.
    243 %
    244 %  The format of the RegisterRGFImage method is:
    245 %
    246 %      size_t RegisterRGFImage(void)
    247 %
    248 */
    249 ModuleExport size_t RegisterRGFImage(void)
    250 {
    251   MagickInfo
    252     *entry;
    253 
    254   entry=AcquireMagickInfo("RGF","RGF",
    255     "LEGO Mindstorms EV3 Robot Graphic Format (black and white)");
    256   entry->decoder=(DecodeImageHandler *) ReadRGFImage;
    257   entry->encoder=(EncodeImageHandler *) WriteRGFImage;
    258   entry->flags^=CoderAdjoinFlag;
    259   (void) RegisterMagickInfo(entry);
    260   return(MagickImageCoderSignature);
    261 }
    262 
    263 /*
    265 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    266 %                                                                             %
    267 %                                                                             %
    268 %                                                                             %
    269 %   U n r e g i s t e r R G F I m a g e                                       %
    270 %                                                                             %
    271 %                                                                             %
    272 %                                                                             %
    273 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    274 %
    275 %  UnregisterRGFImage() removes format registrations made by the
    276 %  RGF module from the list of supported formats.
    277 %
    278 %  The format of the UnregisterRGFImage method is:
    279 %
    280 %      UnregisterRGFImage(void)
    281 %
    282 */
    283 ModuleExport void UnregisterRGFImage(void)
    284 {
    285   (void) UnregisterMagickInfo("RGF");
    286 }
    287 
    288 /*
    290 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    291 %                                                                             %
    292 %                                                                             %
    293 %                                                                             %
    294 %   W r i t e R G F I m a g e                                                 %
    295 %                                                                             %
    296 %                                                                             %
    297 %                                                                             %
    298 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    299 %
    300 %  WriteRGFImage() writes an image to a file in the X bitmap format.
    301 %
    302 %  The format of the WriteRGFImage method is:
    303 %
    304 %      MagickBooleanType WriteRGFImage(const ImageInfo *image_info,
    305 %        Image *image,ExceptionInfo *exception)
    306 %
    307 %  A description of each parameter follows.
    308 %
    309 %    o image_info: the image info.
    310 %
    311 %    o image:  The image.
    312 %
    313 %    o exception: return any errors or warnings in this structure.
    314 %
    315 */
    316 static MagickBooleanType WriteRGFImage(const ImageInfo *image_info,Image *image,
    317   ExceptionInfo *exception)
    318 {
    319   MagickBooleanType
    320     status;
    321 
    322   register const Quantum
    323     *p;
    324 
    325   register ssize_t
    326     x;
    327 
    328   size_t
    329     bit,
    330     byte;
    331 
    332   ssize_t
    333     y;
    334 
    335   /*
    336     Open output image file.
    337   */
    338   assert(image_info != (const ImageInfo *) NULL);
    339   assert(image_info->signature == MagickCoreSignature);
    340   assert(image != (Image *) NULL);
    341   assert(image->signature == MagickCoreSignature);
    342   if (image->debug != MagickFalse)
    343     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
    344   assert(exception != (ExceptionInfo *) NULL);
    345   assert(exception->signature == MagickCoreSignature);
    346   status=OpenBlob(image_info,image,WriteBinaryBlobMode,exception);
    347   if (status == MagickFalse)
    348   return(status);
    349     (void) TransformImageColorspace(image,sRGBColorspace,exception);
    350   if((image->columns > 255L) || (image->rows > 255L))
    351     ThrowWriterException(ImageError,"Dimensions must be less than 255x255");
    352   /*
    353     Write header (just the image dimensions)
    354    */
    355   (void) WriteBlobByte(image,image->columns & 0xff);
    356   (void) WriteBlobByte(image,image->rows & 0xff);
    357   /*
    358     Convert MIFF to bit pixels.
    359   */
    360   (void) SetImageType(image,BilevelType,exception);
    361   x=0;
    362   y=0;
    363   for (y=0; y < (ssize_t) image->rows; y++)
    364   {
    365     p=GetVirtualPixels(image,0,y,image->columns,1,exception);
    366     if (p == (const Quantum *) NULL)
    367       break;
    368     bit=0;
    369     byte=0;
    370     for (x=0; x < (ssize_t) image->columns; x++)
    371     {
    372       byte>>=1;
    373       if (GetPixelLuma(image,p) < (QuantumRange/2.0))
    374         byte|=0x80;
    375       bit++;
    376       if (bit == 8)
    377         {
    378           /*
    379             Write a bitmap byte to the image file.
    380           */
    381           (void) WriteBlobByte(image,(unsigned char) byte);
    382           bit=0;
    383           byte=0;
    384         }
    385       p+=GetPixelChannels(image);
    386     }
    387     if (bit != 0)
    388       (void) WriteBlobByte(image,(unsigned char) byte);
    389     status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
    390       image->rows);
    391     if (status == MagickFalse)
    392       break;
    393   }
    394   (void) CloseBlob(image);
    395   return(MagickTrue);
    396 }
    397