]> granicus.if.org Git - imagemagick/blob - coders/jbig.c
(no commit message)
[imagemagick] / coders / jbig.c
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 \f
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 \f
72 /*
73   Forward declarations.
74 */
75 #if defined(MAGICKCORE_JBIG_DELEGATE)
76 static MagickBooleanType
77   WriteJBIGImage(const ImageInfo *,Image *,ExceptionInfo *);
78 #endif
79 \f
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 */
108 static 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 \f
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 */
281 ModuleExport 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 \f
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 */
348 ModuleExport void UnregisterJBIGImage(void)
349 {
350   (void) UnregisterMagickInfo("BIE");
351   (void) UnregisterMagickInfo("JBG");
352   (void) UnregisterMagickInfo("JBIG");
353 }
354 \f
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
384 static 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
393 static 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       (void) TransformImageColorspace(image,sRGBColorspace,exception);
451     number_packets=(image->columns+7)/8;
452     pixels=(unsigned char *) AcquireQuantumMemory(number_packets,
453       image->rows*sizeof(*pixels));
454     if (pixels == (unsigned char *) NULL)
455       ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
456     /*
457       Convert pixels to a bitmap.
458     */
459     (void) SetImageType(image,BilevelType,exception);
460     q=pixels;
461     for (y=0; y < (ssize_t) image->rows; y++)
462     {
463       p=GetVirtualPixels(image,0,y,image->columns,1,exception);
464       if (p == (const Quantum *) NULL)
465         break;
466       bit=0;
467       byte=0;
468       for (x=0; x < (ssize_t) image->columns; x++)
469       {
470         byte<<=1;
471         if (GetPixelIntensity(image,p) < (QuantumRange/2.0))
472           byte|=0x01;
473         bit++;
474         if (bit == 8)
475           {
476             *q++=byte;
477             bit=0;
478             byte=0;
479           }
480         p+=GetPixelChannels(image);
481       }
482       if (bit != 0)
483         *q++=byte << (8-bit);
484       if (image->previous == (Image *) NULL)
485         {
486           status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
487             image->rows);
488           if (status == MagickFalse)
489             break;
490         }
491     }
492     /*
493       Initialize JBIG info structure.
494     */
495     jbg_enc_init(&jbig_info,(unsigned long) image->columns,(unsigned long)
496       image->rows,1,&pixels,(void (*)(unsigned char *,size_t,void *))
497       JBIGEncode,image);
498     if (image_info->scene != 0)
499       jbg_enc_layers(&jbig_info,(int) image_info->scene);
500     else
501       {
502         size_t
503           x_resolution,
504           y_resolution;
505
506         x_resolution=640;
507         y_resolution=480;
508         if (image_info->density != (char *) NULL)
509           {
510             GeometryInfo
511               geometry_info;
512
513             MagickStatusType
514               flags;
515
516             flags=ParseGeometry(image_info->density,&geometry_info);
517             x_resolution=geometry_info.rho;
518             y_resolution=geometry_info.sigma;
519             if ((flags & SigmaValue) == 0)
520               y_resolution=x_resolution;
521           }
522         if (image->units == PixelsPerCentimeterResolution)
523           {
524             x_resolution=(size_t) (100.0*2.54*x_resolution+0.5)/100.0;
525             y_resolution=(size_t) (100.0*2.54*y_resolution+0.5)/100.0;
526           }
527         (void) jbg_enc_lrlmax(&jbig_info,(unsigned long) x_resolution,
528           (unsigned long) y_resolution);
529       }
530     (void) jbg_enc_lrange(&jbig_info,-1,-1);
531     jbg_enc_options(&jbig_info,JBG_ILEAVE | JBG_SMID,JBG_TPDON | JBG_TPBON |
532       JBG_DPON,version < 1.6 ? -1 : 0,-1,-1);
533     /*
534       Write JBIG image.
535     */
536     jbg_enc_out(&jbig_info);
537     jbg_enc_free(&jbig_info);
538     pixels=(unsigned char *) RelinquishMagickMemory(pixels);
539     if (GetNextImageInList(image) == (Image *) NULL)
540       break;
541     image=SyncNextImageInList(image);
542     status=SetImageProgress(image,SaveImagesTag,scene++,
543       GetImageListLength(image));
544     if (status == MagickFalse)
545       break;
546   } while (image_info->adjoin != MagickFalse);
547   (void) CloseBlob(image);
548   return(MagickTrue);
549 }
550 #endif