Home | History | Annotate | Download | only in coders
      1 /*
      2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
      3 %                                                                             %
      4 %                                                                             %
      5 %                                                                             %
      6 %                        JJJJJ  BBBB   IIIII   GGGG                           %
      7 %                          J    B   B    I    G                               %
      8 %                          J    BBBB     I    G  GG                           %
      9 %                        J J    B   B    I    G   G                           %
     10 %                        JJJ    BBBB   IIIII   GGG                            %
     11 %                                                                             %
     12 %                                                                             %
     13 %                       Read/Write JBIG Image 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/constitute.h"
     53 #include "MagickCore/exception.h"
     54 #include "MagickCore/exception-private.h"
     55 #include "MagickCore/geometry.h"
     56 #include "MagickCore/image.h"
     57 #include "MagickCore/image-private.h"
     58 #include "MagickCore/list.h"
     59 #include "MagickCore/magick.h"
     60 #include "MagickCore/memory_.h"
     61 #include "MagickCore/monitor.h"
     62 #include "MagickCore/monitor-private.h"
     63 #include "MagickCore/nt-base-private.h"
     64 #include "MagickCore/pixel-accessor.h"
     65 #include "MagickCore/quantum-private.h"
     66 #include "MagickCore/static.h"
     67 #include "MagickCore/string_.h"
     68 #include "MagickCore/string-private.h"
     69 #include "MagickCore/module.h"
     70 #if defined(MAGICKCORE_JBIG_DELEGATE)
     71 #if defined(__cplusplus) || defined(c_plusplus)
     72 extern "C" {
     73 #endif
     74 #include "jbig.h"
     75 #if defined(__cplusplus) || defined(c_plusplus)
     76 }
     77 #endif
     78 #endif
     79 
     80 /*
     82   Forward declarations.
     83 */
     84 #if defined(MAGICKCORE_JBIG_DELEGATE)
     85 static MagickBooleanType
     86   WriteJBIGImage(const ImageInfo *,Image *,ExceptionInfo *);
     87 #endif
     88 
     89 #if defined(MAGICKCORE_JBIG_DELEGATE)
     91 /*
     92 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     93 %                                                                             %
     94 %                                                                             %
     95 %                                                                             %
     96 %   R e a d J B I G I m a g e                                                 %
     97 %                                                                             %
     98 %                                                                             %
     99 %                                                                             %
    100 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    101 %
    102 %  ReadJBIGImage() reads a JBIG image file and returns it.  It
    103 %  allocates the memory necessary for the new Image structure and returns a
    104 %  pointer to the new image.
    105 %
    106 %  The format of the ReadJBIGImage method is:
    107 %
    108 %      Image *ReadJBIGImage(const ImageInfo *image_info,
    109 %        ExceptionInfo *exception)
    110 %
    111 %  A description of each parameter follows:
    112 %
    113 %    o image_info: the image info.
    114 %
    115 %    o exception: return any errors or warnings in this structure.
    116 %
    117 */
    118 static Image *ReadJBIGImage(const ImageInfo *image_info,
    119   ExceptionInfo *exception)
    120 {
    121   Image
    122     *image;
    123 
    124   MagickStatusType
    125     status;
    126 
    127   Quantum
    128     index;
    129 
    130   register ssize_t
    131     x;
    132 
    133   register Quantum
    134     *q;
    135 
    136   register unsigned char
    137     *p;
    138 
    139   ssize_t
    140     length,
    141     y;
    142 
    143   struct jbg_dec_state
    144     jbig_info;
    145 
    146   unsigned char
    147     bit,
    148     *buffer,
    149     byte;
    150 
    151   /*
    152     Open image file.
    153   */
    154   assert(image_info != (const ImageInfo *) NULL);
    155   assert(image_info->signature == MagickCoreSignature);
    156   if (image_info->debug != MagickFalse)
    157     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
    158       image_info->filename);
    159   assert(exception != (ExceptionInfo *) NULL);
    160   assert(exception->signature == MagickCoreSignature);
    161   image=AcquireImage(image_info,exception);
    162   status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
    163   if (status == MagickFalse)
    164     {
    165       image=DestroyImageList(image);
    166       return((Image *) NULL);
    167     }
    168   /*
    169     Initialize JBIG toolkit.
    170   */
    171   jbg_dec_init(&jbig_info);
    172   jbg_dec_maxsize(&jbig_info,(unsigned long) image->columns,(unsigned long)
    173     image->rows);
    174   image->columns=jbg_dec_getwidth(&jbig_info);
    175   image->rows=jbg_dec_getheight(&jbig_info);
    176   image->depth=8;
    177   image->storage_class=PseudoClass;
    178   image->colors=2;
    179   /*
    180     Read JBIG file.
    181   */
    182   buffer=(unsigned char *) AcquireQuantumMemory(MagickMaxBufferExtent,
    183     sizeof(*buffer));
    184   if (buffer == (unsigned char *) NULL)
    185     {
    186       jbg_dec_free(&jbig_info);
    187       ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
    188     }
    189   status=JBG_EAGAIN;
    190   do
    191   {
    192     length=(ssize_t) ReadBlob(image,MagickMaxBufferExtent,buffer);
    193     if (length == 0)
    194       break;
    195     p=buffer;
    196     while ((length > 0) && ((status == JBG_EAGAIN) || (status == JBG_EOK)))
    197     {
    198       size_t
    199         count;
    200 
    201       status=jbg_dec_in(&jbig_info,p,length,&count);
    202       p+=count;
    203       length-=(ssize_t) count;
    204     }
    205   } while ((status == JBG_EAGAIN) || (status == JBG_EOK));
    206   /*
    207     Create colormap.
    208   */
    209   image->columns=jbg_dec_getwidth(&jbig_info);
    210   image->rows=jbg_dec_getheight(&jbig_info);
    211   image->compression=JBIG2Compression;
    212   if (AcquireImageColormap(image,2,exception) == MagickFalse)
    213     {
    214       jbg_dec_free(&jbig_info);
    215       buffer=(unsigned char *) RelinquishMagickMemory(buffer);
    216       ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
    217     }
    218   image->colormap[0].red=0;
    219   image->colormap[0].green=0;
    220   image->colormap[0].blue=0;
    221   image->colormap[1].red=QuantumRange;
    222   image->colormap[1].green=QuantumRange;
    223   image->colormap[1].blue=QuantumRange;
    224   image->resolution.x=300;
    225   image->resolution.y=300;
    226   if (image_info->ping != MagickFalse)
    227     {
    228       jbg_dec_free(&jbig_info);
    229       buffer=(unsigned char *) RelinquishMagickMemory(buffer);
    230       (void) CloseBlob(image);
    231       return(GetFirstImageInList(image));
    232     }
    233   status=SetImageExtent(image,image->columns,image->rows,exception);
    234   if (status == MagickFalse)
    235     {
    236       jbg_dec_free(&jbig_info);
    237       buffer=(unsigned char *) RelinquishMagickMemory(buffer);
    238       return(DestroyImageList(image));
    239     }
    240   /*
    241     Convert X bitmap image to pixel packets.
    242   */
    243   p=jbg_dec_getimage(&jbig_info,0);
    244   for (y=0; y < (ssize_t) image->rows; y++)
    245   {
    246     q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
    247     if (q == (Quantum *) NULL)
    248       break;
    249     bit=0;
    250     byte=0;
    251     for (x=0; x < (ssize_t) image->columns; x++)
    252     {
    253       if (bit == 0)
    254         byte=(*p++);
    255       index=(byte & 0x80) ? 0 : 1;
    256       bit++;
    257       byte<<=1;
    258       if (bit == 8)
    259         bit=0;
    260       SetPixelIndex(image,index,q);
    261       SetPixelViaPixelInfo(image,image->colormap+(ssize_t) index,q);
    262       q+=GetPixelChannels(image);
    263     }
    264     if (SyncAuthenticPixels(image,exception) == MagickFalse)
    265       break;
    266     status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y,
    267       image->rows);
    268     if (status == MagickFalse)
    269       break;
    270   }
    271   /*
    272     Free scale resource.
    273   */
    274   jbg_dec_free(&jbig_info);
    275   buffer=(unsigned char *) RelinquishMagickMemory(buffer);
    276   (void) CloseBlob(image);
    277   return(GetFirstImageInList(image));
    278 }
    279 #endif
    280 
    281 /*
    283 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    284 %                                                                             %
    285 %                                                                             %
    286 %                                                                             %
    287 %   R e g i s t e r J B I G I m a g e                                         %
    288 %                                                                             %
    289 %                                                                             %
    290 %                                                                             %
    291 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    292 %
    293 %  RegisterJBIGImage() adds attributes for the JBIG image format to
    294 %  the list of supported formats.  The attributes include the image format
    295 %  tag, a method to read and/or write the format, whether the format
    296 %  supports the saving of more than one frame to the same file or blob,
    297 %  whether the format supports native in-memory I/O, and a brief
    298 %  description of the format.
    299 %
    300 %  The format of the RegisterJBIGImage method is:
    301 %
    302 %      size_t RegisterJBIGImage(void)
    303 %
    304 */
    305 ModuleExport size_t RegisterJBIGImage(void)
    306 {
    307 #define JBIGDescription  "Joint Bi-level Image experts Group interchange format"
    308 
    309   char
    310     version[MagickPathExtent];
    311 
    312   MagickInfo
    313     *entry;
    314 
    315   *version='\0';
    316 #if defined(JBG_VERSION)
    317   (void) CopyMagickString(version,JBG_VERSION,MagickPathExtent);
    318 #endif
    319   entry=AcquireMagickInfo("JBIG","BIE",JBIGDescription);
    320 #if defined(MAGICKCORE_JBIG_DELEGATE)
    321   entry->decoder=(DecodeImageHandler *) ReadJBIGImage;
    322   entry->encoder=(EncodeImageHandler *) WriteJBIGImage;
    323 #endif
    324   entry->flags^=CoderAdjoinFlag;
    325   if (*version != '\0')
    326     entry->version=ConstantString(version);
    327   (void) RegisterMagickInfo(entry);
    328   entry=AcquireMagickInfo("JBIG","JBG",JBIGDescription);
    329 #if defined(MAGICKCORE_JBIG_DELEGATE)
    330   entry->decoder=(DecodeImageHandler *) ReadJBIGImage;
    331   entry->encoder=(EncodeImageHandler *) WriteJBIGImage;
    332 #endif
    333   if (*version != '\0')
    334     entry->version=ConstantString(version);
    335   (void) RegisterMagickInfo(entry);
    336   entry=AcquireMagickInfo("JBIG","JBIG",JBIGDescription);
    337 #if defined(MAGICKCORE_JBIG_DELEGATE)
    338   entry->decoder=(DecodeImageHandler *) ReadJBIGImage;
    339   entry->encoder=(EncodeImageHandler *) WriteJBIGImage;
    340 #endif
    341   if (*version != '\0')
    342     entry->version=ConstantString(version);
    343   (void) RegisterMagickInfo(entry);
    344   return(MagickImageCoderSignature);
    345 }
    346 
    347 /*
    349 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    350 %                                                                             %
    351 %                                                                             %
    352 %                                                                             %
    353 %   U n r e g i s t e r J B I G I m a g e                                     %
    354 %                                                                             %
    355 %                                                                             %
    356 %                                                                             %
    357 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    358 %
    359 %  UnregisterJBIGImage() removes format registrations made by the
    360 %  JBIG module from the list of supported formats.
    361 %
    362 %  The format of the UnregisterJBIGImage method is:
    363 %
    364 %      UnregisterJBIGImage(void)
    365 %
    366 */
    367 ModuleExport void UnregisterJBIGImage(void)
    368 {
    369   (void) UnregisterMagickInfo("BIE");
    370   (void) UnregisterMagickInfo("JBG");
    371   (void) UnregisterMagickInfo("JBIG");
    372 }
    373 
    374 #if defined(MAGICKCORE_JBIG_DELEGATE)
    376 /*
    377 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    378 %                                                                             %
    379 %                                                                             %
    380 %                                                                             %
    381 %   W r i t e J B I G I m a g e                                               %
    382 %                                                                             %
    383 %                                                                             %
    384 %                                                                             %
    385 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    386 %
    387 %  WriteJBIGImage() writes an image in the JBIG encoded image format.
    388 %
    389 %  The format of the WriteJBIGImage method is:
    390 %
    391 %      MagickBooleanType WriteJBIGImage(const ImageInfo *image_info,
    392 %        Image *image,ExceptionInfo *exception)
    393 %
    394 %  A description of each parameter follows.
    395 %
    396 %    o image_info: the image info.
    397 %
    398 %    o image:  The image.
    399 %
    400 %    o exception: return any errors or warnings in this structure.
    401 %
    402 */
    403 
    404 static void JBIGEncode(unsigned char *pixels,size_t length,void *data)
    405 {
    406   Image
    407     *image;
    408 
    409   image=(Image *) data;
    410   (void) WriteBlob(image,length,pixels);
    411 }
    412 
    413 static MagickBooleanType WriteJBIGImage(const ImageInfo *image_info,
    414   Image *image,ExceptionInfo *exception)
    415 {
    416   double
    417     version;
    418 
    419   MagickBooleanType
    420     status;
    421 
    422   MagickOffsetType
    423     scene;
    424 
    425   MemoryInfo
    426     *pixel_info;
    427 
    428   register const Quantum
    429     *p;
    430 
    431   register ssize_t
    432     x;
    433 
    434   register unsigned char
    435     *q;
    436 
    437   size_t
    438     number_packets;
    439 
    440   ssize_t
    441     y;
    442 
    443   struct jbg_enc_state
    444     jbig_info;
    445 
    446   unsigned char
    447     bit,
    448     byte,
    449     *pixels;
    450 
    451   /*
    452     Open image file.
    453   */
    454   assert(image_info != (const ImageInfo *) NULL);
    455   assert(image_info->signature == MagickCoreSignature);
    456   assert(image != (Image *) NULL);
    457   assert(image->signature == MagickCoreSignature);
    458   if (image->debug != MagickFalse)
    459     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
    460   assert(exception != (ExceptionInfo *) NULL);
    461   assert(exception->signature == MagickCoreSignature);
    462   status=OpenBlob(image_info,image,WriteBinaryBlobMode,exception);
    463   if (status == MagickFalse)
    464     return(status);
    465   version=StringToDouble(JBG_VERSION,(char **) NULL);
    466   scene=0;
    467   do
    468   {
    469     /*
    470       Allocate pixel data.
    471     */
    472     (void) TransformImageColorspace(image,sRGBColorspace,exception);
    473     number_packets=(image->columns+7)/8;
    474     pixel_info=AcquireVirtualMemory(number_packets,image->rows*sizeof(*pixels));
    475     if (pixel_info == (MemoryInfo *) NULL)
    476       ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
    477     pixels=(unsigned char *) GetVirtualMemoryBlob(pixel_info);
    478     /*
    479       Convert pixels to a bitmap.
    480     */
    481     (void) SetImageType(image,BilevelType,exception);
    482     q=pixels;
    483     for (y=0; y < (ssize_t) image->rows; y++)
    484     {
    485       p=GetVirtualPixels(image,0,y,image->columns,1,exception);
    486       if (p == (const Quantum *) NULL)
    487         break;
    488       bit=0;
    489       byte=0;
    490       for (x=0; x < (ssize_t) image->columns; x++)
    491       {
    492         byte<<=1;
    493         if (GetPixelLuma(image,p) < (QuantumRange/2.0))
    494           byte|=0x01;
    495         bit++;
    496         if (bit == 8)
    497           {
    498             *q++=byte;
    499             bit=0;
    500             byte=0;
    501           }
    502         p+=GetPixelChannels(image);
    503       }
    504       if (bit != 0)
    505         *q++=byte << (8-bit);
    506       if (image->previous == (Image *) NULL)
    507         {
    508           status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
    509             image->rows);
    510           if (status == MagickFalse)
    511             break;
    512         }
    513     }
    514     /*
    515       Initialize JBIG info structure.
    516     */
    517     jbg_enc_init(&jbig_info,(unsigned long) image->columns,(unsigned long)
    518       image->rows,1,&pixels,(void (*)(unsigned char *,size_t,void *))
    519       JBIGEncode,image);
    520     if (image_info->scene != 0)
    521       jbg_enc_layers(&jbig_info,(int) image_info->scene);
    522     else
    523       {
    524         size_t
    525           x_resolution,
    526           y_resolution;
    527 
    528         x_resolution=640;
    529         y_resolution=480;
    530         if (image_info->density != (char *) NULL)
    531           {
    532             GeometryInfo
    533               geometry_info;
    534 
    535             MagickStatusType
    536               flags;
    537 
    538             flags=ParseGeometry(image_info->density,&geometry_info);
    539             x_resolution=geometry_info.rho;
    540             y_resolution=geometry_info.sigma;
    541             if ((flags & SigmaValue) == 0)
    542               y_resolution=x_resolution;
    543           }
    544         if (image->units == PixelsPerCentimeterResolution)
    545           {
    546             x_resolution=(size_t) (100.0*2.54*x_resolution+0.5)/100.0;
    547             y_resolution=(size_t) (100.0*2.54*y_resolution+0.5)/100.0;
    548           }
    549         (void) jbg_enc_lrlmax(&jbig_info,(unsigned long) x_resolution,
    550           (unsigned long) y_resolution);
    551       }
    552     (void) jbg_enc_lrange(&jbig_info,-1,-1);
    553     jbg_enc_options(&jbig_info,JBG_ILEAVE | JBG_SMID,JBG_TPDON | JBG_TPBON |
    554       JBG_DPON,version < 1.6 ? -1 : 0,-1,-1);
    555     /*
    556       Write JBIG image.
    557     */
    558     jbg_enc_out(&jbig_info);
    559     jbg_enc_free(&jbig_info);
    560     pixel_info=RelinquishVirtualMemory(pixel_info);
    561     if (GetNextImageInList(image) == (Image *) NULL)
    562       break;
    563     image=SyncNextImageInList(image);
    564     status=SetImageProgress(image,SaveImagesTag,scene++,
    565       GetImageListLength(image));
    566     if (status == MagickFalse)
    567       break;
    568   } while (image_info->adjoin != MagickFalse);
    569   (void) CloseBlob(image);
    570   return(MagickTrue);
    571 }
    572 #endif
    573