Home | History | Annotate | Download | only in coders
      1 /*
      2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
      3 %                                                                             %
      4 %                                                                             %
      5 %                                                                             %
      6 %                         M   M   OOO   N   N   OOO                           %
      7 %                         MM MM  O   O  NN  N  O   O                          %
      8 %                         M M M  O   O  N N N  O   O                          %
      9 %                         M   M  O   O  N  NN  O   O                          %
     10 %                         M   M   OOO   N   N   OOO                           %
     11 %                                                                             %
     12 %                                                                             %
     13 %                   Read/Write Raw Bi-Level Bitmap 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/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 
     67 /*
     69   Forward declarations.
     70 */
     71 static MagickBooleanType
     72   WriteMONOImage(const ImageInfo *,Image *,ExceptionInfo *);
     73 
     74 /*
     76 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     77 %                                                                             %
     78 %                                                                             %
     79 %                                                                             %
     80 %   R e a d M O N O I m a g e                                                 %
     81 %                                                                             %
     82 %                                                                             %
     83 %                                                                             %
     84 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     85 %
     86 %  ReadMONOImage() reads an image of raw bites in LSB order and returns
     87 %  it.  It allocates the memory necessary for the new Image structure and
     88 %  returns a pointer to the new image.
     89 %
     90 %  The format of the ReadMONOImage method is:
     91 %
     92 %      Image *ReadMONOImage(const ImageInfo *image_info,
     93 %        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 *ReadMONOImage(const ImageInfo *image_info,
    103   ExceptionInfo *exception)
    104 {
    105   Image
    106     *image;
    107 
    108   MagickBooleanType
    109     status;
    110 
    111   register Quantum
    112     *q;
    113 
    114   register ssize_t
    115     x;
    116 
    117   size_t
    118     bit,
    119     byte;
    120 
    121   ssize_t
    122     y;
    123 
    124   /*
    125     Open image file.
    126   */
    127   assert(image_info != (const ImageInfo *) NULL);
    128   assert(image_info->signature == MagickCoreSignature);
    129   if (image_info->debug != MagickFalse)
    130     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
    131       image_info->filename);
    132   assert(exception != (ExceptionInfo *) NULL);
    133   assert(exception->signature == MagickCoreSignature);
    134   image=AcquireImage(image_info,exception);
    135   if ((image->columns == 0) || (image->rows == 0))
    136     ThrowReaderException(OptionError,"MustSpecifyImageSize");
    137   status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
    138   if (status == MagickFalse)
    139     {
    140       image=DestroyImageList(image);
    141       return((Image *) NULL);
    142     }
    143   if (DiscardBlobBytes(image,image->offset) == MagickFalse)
    144     ThrowFileException(exception,CorruptImageError,"UnexpectedEndOfFile",
    145       image->filename);
    146   /*
    147     Initialize image colormap.
    148   */
    149   image->depth=1;
    150   if (AcquireImageColormap(image,2,exception) == MagickFalse)
    151     ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
    152   if (image_info->ping != MagickFalse)
    153     {
    154       (void) CloseBlob(image);
    155       return(GetFirstImageInList(image));
    156     }
    157   status=SetImageExtent(image,image->columns,image->rows,exception);
    158   if (status == MagickFalse)
    159     return(DestroyImageList(image));
    160   /*
    161     Convert bi-level image to pixel packets.
    162   */
    163   for (y=0; y < (ssize_t) image->rows; y++)
    164   {
    165     q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
    166     if (q == (Quantum *) NULL)
    167       break;
    168     bit=0;
    169     byte=0;
    170     for (x=0; x < (ssize_t) image->columns; x++)
    171     {
    172       if (bit == 0)
    173         byte=(size_t) ReadBlobByte(image);
    174       if (image_info->endian == LSBEndian)
    175         SetPixelIndex(image,((byte & 0x01) != 0) ? 0x00 : 0x01,q);
    176       else
    177         SetPixelIndex(image,((byte & 0x01) != 0) ? 0x01 : 0x00,q);
    178       bit++;
    179       if (bit == 8)
    180         bit=0;
    181       byte>>=1;
    182       q+=GetPixelChannels(image);
    183     }
    184     if (SyncAuthenticPixels(image,exception) == MagickFalse)
    185       break;
    186     status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y,
    187       image->rows);
    188     if (status == MagickFalse)
    189       break;
    190   }
    191   (void) SyncImage(image,exception);
    192   if (EOFBlob(image) != MagickFalse)
    193     ThrowFileException(exception,CorruptImageError,"UnexpectedEndOfFile",
    194       image->filename);
    195   (void) CloseBlob(image);
    196   return(GetFirstImageInList(image));
    197 }
    198 
    199 /*
    201 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    202 %                                                                             %
    203 %                                                                             %
    204 %                                                                             %
    205 %   R e g i s t e r M O N O I m a g e                                         %
    206 %                                                                             %
    207 %                                                                             %
    208 %                                                                             %
    209 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    210 %
    211 %  RegisterMONOImage() adds attributes for the MONO image format to
    212 %  the list of supported formats.  The attributes include the image format
    213 %  tag, a method to read and/or write the format, whether the format
    214 %  supports the saving of more than one frame to the same file or blob,
    215 %  whether the format supports native in-memory I/O, and a brief
    216 %  description of the format.
    217 %
    218 %  The format of the RegisterMONOImage method is:
    219 %
    220 %      size_t RegisterMONOImage(void)
    221 %
    222 */
    223 ModuleExport size_t RegisterMONOImage(void)
    224 {
    225   MagickInfo
    226     *entry;
    227 
    228   entry=AcquireMagickInfo("MONO","MONO","Raw bi-level bitmap");
    229   entry->decoder=(DecodeImageHandler *) ReadMONOImage;
    230   entry->encoder=(EncodeImageHandler *) WriteMONOImage;
    231   entry->flags|=CoderRawSupportFlag;
    232   entry->flags|=CoderEndianSupportFlag;
    233   entry->flags^=CoderAdjoinFlag;
    234   (void) RegisterMagickInfo(entry);
    235   return(MagickImageCoderSignature);
    236 }
    237 
    238 /*
    240 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    241 %                                                                             %
    242 %                                                                             %
    243 %                                                                             %
    244 %   U n r e g i s t e r M O N O I m a g e                                     %
    245 %                                                                             %
    246 %                                                                             %
    247 %                                                                             %
    248 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    249 %
    250 %  UnregisterMONOImage() removes format registrations made by the
    251 %  MONO module from the list of supported formats.
    252 %
    253 %  The format of the UnregisterMONOImage method is:
    254 %
    255 %      UnregisterMONOImage(void)
    256 %
    257 */
    258 ModuleExport void UnregisterMONOImage(void)
    259 {
    260   (void) UnregisterMagickInfo("MONO");
    261 }
    262 
    263 /*
    265 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    266 %                                                                             %
    267 %                                                                             %
    268 %                                                                             %
    269 %   W r i t e M O N O I m a g e                                               %
    270 %                                                                             %
    271 %                                                                             %
    272 %                                                                             %
    273 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    274 %
    275 %  WriteMONOImage() writes an image of raw bits in LSB order to a file.
    276 %
    277 %  The format of the WriteMONOImage method is:
    278 %
    279 %      MagickBooleanType WriteMONOImage(const ImageInfo *image_info,
    280 %        Image *image,ExceptionInfo *exception)
    281 %
    282 %  A description of each parameter follows.
    283 %
    284 %    o image_info: the image info.
    285 %
    286 %    o image:  The image.
    287 %
    288 %    o exception: return any errors or warnings in this structure.
    289 %
    290 */
    291 static MagickBooleanType WriteMONOImage(const ImageInfo *image_info,
    292   Image *image,ExceptionInfo *exception)
    293 {
    294   MagickBooleanType
    295     status;
    296 
    297   register const Quantum
    298     *p;
    299 
    300   register ssize_t
    301     x;
    302 
    303   size_t
    304     bit,
    305     byte;
    306 
    307   ssize_t
    308     y;
    309 
    310   /*
    311     Open output image file.
    312   */
    313   assert(image_info != (const ImageInfo *) NULL);
    314   assert(image_info->signature == MagickCoreSignature);
    315   assert(image != (Image *) NULL);
    316   assert(image->signature == MagickCoreSignature);
    317   if (image->debug != MagickFalse)
    318     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
    319   assert(exception != (ExceptionInfo *) NULL);
    320   assert(exception->signature == MagickCoreSignature);
    321   status=OpenBlob(image_info,image,WriteBinaryBlobMode,exception);
    322   if (status == MagickFalse)
    323     return(status);
    324   (void) TransformImageColorspace(image,sRGBColorspace,exception);
    325   /*
    326     Convert image to a bi-level image.
    327   */
    328   (void) SetImageType(image,BilevelType,exception);
    329   for (y=0; y < (ssize_t) image->rows; y++)
    330   {
    331     p=GetVirtualPixels(image,0,y,image->columns,1,exception);
    332     if (p == (const Quantum *) NULL)
    333       break;
    334     bit=0;
    335     byte=0;
    336     for (x=0; x < (ssize_t) image->columns; x++)
    337     {
    338       byte>>=1;
    339       if (image->endian == LSBEndian)
    340         {
    341           if (GetPixelLuma(image,p) < (QuantumRange/2.0))
    342             byte|=0x80;
    343         }
    344       else
    345         if (GetPixelLuma(image,p) >= (QuantumRange/2.0))
    346           byte|=0x80;
    347       bit++;
    348       if (bit == 8)
    349         {
    350           (void) WriteBlobByte(image,(unsigned char) byte);
    351           bit=0;
    352           byte=0;
    353         }
    354       p+=GetPixelChannels(image);
    355     }
    356     if (bit != 0)
    357       (void) WriteBlobByte(image,(unsigned char) (byte >> (8-bit)));
    358     status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
    359       image->rows);
    360     if (status == MagickFalse)
    361       break;
    362   }
    363   (void) CloseBlob(image);
    364   return(MagickTrue);
    365 }
    366