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