source: ImageMagick/trunk/coders/jbig.c @ 8316

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