2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6 % JJJJJ BBBB IIIII GGGG %
10 % JJJ BBBB IIIII GGG %
13 % Read/Write JBIG Image Format %
20 % Copyright 1999-2011 ImageMagick Studio LLC, a non-profit organization %
21 % dedicated to making software imaging solutions freely available. %
23 % You may not use this file except in compliance with the License. You may %
24 % obtain a copy of the License at %
26 % http://www.imagemagick.org/script/license.php %
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. %
34 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
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-feature.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/module.h"
67 #if defined(MAGICKCORE_JBIG_DELEGATE)
74 #if defined(MAGICKCORE_JBIG_DELEGATE)
75 static MagickBooleanType
76 WriteJBIGImage(const ImageInfo *,Image *,ExceptionInfo *);
79 #if defined(MAGICKCORE_JBIG_DELEGATE)
81 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
85 % R e a d J B I G I m a g e %
89 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
91 % ReadJBIGImage() reads a JBIG image file and returns it. It
92 % allocates the memory necessary for the new Image structure and returns a
93 % pointer to the new image.
95 % The format of the ReadJBIGImage method is:
97 % Image *ReadJBIGImage(const ImageInfo *image_info,
98 % ExceptionInfo *exception)
100 % A description of each parameter follows:
102 % o image_info: the image info.
104 % o exception: return any errors or warnings in this structure.
107 static Image *ReadJBIGImage(const ImageInfo *image_info,
108 ExceptionInfo *exception)
125 register unsigned char
143 assert(image_info != (const ImageInfo *) NULL);
144 assert(image_info->signature == MagickSignature);
145 if (image_info->debug != MagickFalse)
146 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
147 image_info->filename);
148 assert(exception != (ExceptionInfo *) NULL);
149 assert(exception->signature == MagickSignature);
150 image=AcquireImage(image_info,exception);
151 status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
152 if (status == MagickFalse)
154 image=DestroyImageList(image);
155 return((Image *) NULL);
158 Initialize JBIG toolkit.
160 jbg_dec_init(&jbig_info);
161 jbg_dec_maxsize(&jbig_info,(unsigned long) image->columns,(unsigned long)
163 image->columns=jbg_dec_getwidth(&jbig_info);
164 image->rows=jbg_dec_getheight(&jbig_info);
166 image->storage_class=PseudoClass;
171 buffer=(unsigned char *) AcquireQuantumMemory(MagickMaxBufferExtent,
173 if (buffer == (unsigned char *) NULL)
174 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
178 length=(ssize_t) ReadBlob(image,MagickMaxBufferExtent,buffer);
182 while ((length > 0) && ((status == JBG_EAGAIN) || (status == JBG_EOK)))
187 status=jbg_dec_in(&jbig_info,p,length,&count);
189 length-=(ssize_t) count;
191 } while ((status == JBG_EAGAIN) || (status == JBG_EOK));
195 image->columns=jbg_dec_getwidth(&jbig_info);
196 image->rows=jbg_dec_getheight(&jbig_info);
197 image->compression=JBIG2Compression;
198 if (AcquireImageColormap(image,2,exception) == MagickFalse)
200 buffer=(unsigned char *) RelinquishMagickMemory(buffer);
201 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
203 image->colormap[0].red=0;
204 image->colormap[0].green=0;
205 image->colormap[0].blue=0;
206 image->colormap[1].red=QuantumRange;
207 image->colormap[1].green=QuantumRange;
208 image->colormap[1].blue=QuantumRange;
209 image->x_resolution=300;
210 image->y_resolution=300;
211 if (image_info->ping != MagickFalse)
213 (void) CloseBlob(image);
214 return(GetFirstImageInList(image));
217 Convert X bitmap image to pixel packets.
219 p=jbg_dec_getimage(&jbig_info,0);
220 for (y=0; y < (ssize_t) image->rows; y++)
222 q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
223 if (q == (Quantum *) NULL)
227 for (x=0; x < (ssize_t) image->columns; x++)
231 index=(byte & 0x80) ? 0 : 1;
236 SetPixelIndex(image,index,q);
237 SetPixelPacket(image,image->colormap+(ssize_t) index,q);
238 q+=GetPixelChannels(image);
240 if (SyncAuthenticPixels(image,exception) == MagickFalse)
242 status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y,
244 if (status == MagickFalse)
250 jbg_dec_free(&jbig_info);
251 buffer=(unsigned char *) RelinquishMagickMemory(buffer);
252 (void) CloseBlob(image);
253 return(GetFirstImageInList(image));
258 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
262 % R e g i s t e r J B I G I m a g e %
266 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
268 % RegisterJBIGImage() adds attributes for the JBIG image format to
269 % the list of supported formats. The attributes include the image format
270 % tag, a method to read and/or write the format, whether the format
271 % supports the saving of more than one frame to the same file or blob,
272 % whether the format supports native in-memory I/O, and a brief
273 % description of the format.
275 % The format of the RegisterJBIGImage method is:
277 % size_t RegisterJBIGImage(void)
280 ModuleExport size_t RegisterJBIGImage(void)
282 #define JBIGDescription "Joint Bi-level Image experts Group interchange format"
285 version[MaxTextExtent];
291 #if defined(JBG_VERSION)
292 (void) CopyMagickString(version,JBG_VERSION,MaxTextExtent);
294 entry=SetMagickInfo("BIE");
295 #if defined(MAGICKCORE_JBIG_DELEGATE)
296 entry->decoder=(DecodeImageHandler *) ReadJBIGImage;
297 entry->encoder=(EncodeImageHandler *) WriteJBIGImage;
299 entry->adjoin=MagickFalse;
300 entry->description=ConstantString(JBIGDescription);
301 if (*version != '\0')
302 entry->version=ConstantString(version);
303 entry->module=ConstantString("JBIG");
304 (void) RegisterMagickInfo(entry);
305 entry=SetMagickInfo("JBG");
306 #if defined(MAGICKCORE_JBIG_DELEGATE)
307 entry->decoder=(DecodeImageHandler *) ReadJBIGImage;
308 entry->encoder=(EncodeImageHandler *) WriteJBIGImage;
310 entry->description=ConstantString(JBIGDescription);
311 if (*version != '\0')
312 entry->version=ConstantString(version);
313 entry->module=ConstantString("JBIG");
314 (void) RegisterMagickInfo(entry);
315 entry=SetMagickInfo("JBIG");
316 #if defined(MAGICKCORE_JBIG_DELEGATE)
317 entry->decoder=(DecodeImageHandler *) ReadJBIGImage;
318 entry->encoder=(EncodeImageHandler *) WriteJBIGImage;
320 entry->description=ConstantString(JBIGDescription);
321 if (*version != '\0')
322 entry->version=ConstantString(version);
323 entry->module=ConstantString("JBIG");
324 (void) RegisterMagickInfo(entry);
325 return(MagickImageCoderSignature);
329 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
333 % U n r e g i s t e r J B I G I m a g e %
337 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
339 % UnregisterJBIGImage() removes format registrations made by the
340 % JBIG module from the list of supported formats.
342 % The format of the UnregisterJBIGImage method is:
344 % UnregisterJBIGImage(void)
347 ModuleExport void UnregisterJBIGImage(void)
349 (void) UnregisterMagickInfo("BIE");
350 (void) UnregisterMagickInfo("JBG");
351 (void) UnregisterMagickInfo("JBIG");
354 #if defined(MAGICKCORE_JBIG_DELEGATE)
356 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
360 % W r i t e J B I G I m a g e %
364 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
366 % WriteJBIGImage() writes an image in the JBIG encoded image format.
368 % The format of the WriteJBIGImage method is:
370 % MagickBooleanType WriteJBIGImage(const ImageInfo *image_info,
371 % Image *image,ExceptionInfo *exception)
373 % A description of each parameter follows.
375 % o image_info: the image info.
377 % o image: The image.
379 % o exception: return any errors or warnings in this structure.
383 static void JBIGEncode(unsigned char *pixels,size_t length,void *data)
388 image=(Image *) data;
389 (void) WriteBlob(image,length,pixels);
392 static MagickBooleanType WriteJBIGImage(const ImageInfo *image_info,
393 Image *image,ExceptionInfo *exception)
404 register const Quantum
410 register unsigned char
430 assert(image_info != (const ImageInfo *) NULL);
431 assert(image_info->signature == MagickSignature);
432 assert(image != (Image *) NULL);
433 assert(image->signature == MagickSignature);
434 if (image->debug != MagickFalse)
435 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
436 assert(exception != (ExceptionInfo *) NULL);
437 assert(exception->signature == MagickSignature);
438 status=OpenBlob(image_info,image,WriteBinaryBlobMode,exception);
439 if (status == MagickFalse)
441 version=InterpretLocaleValue(JBG_VERSION,(char **) NULL);
448 if (IsRGBColorspace(image->colorspace) == MagickFalse)
449 (void) TransformImageColorspace(image,RGBColorspace);
450 number_packets=(image->columns+7)/8;
451 pixels=(unsigned char *) AcquireQuantumMemory(number_packets,
452 image->rows*sizeof(*pixels));
453 if (pixels == (unsigned char *) NULL)
454 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
456 Convert pixels to a bitmap.
458 (void) SetImageType(image,BilevelType,exception);
460 for (y=0; y < (ssize_t) image->rows; y++)
462 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
463 if (p == (const Quantum *) NULL)
467 for (x=0; x < (ssize_t) image->columns; x++)
470 if (GetPixelIntensity(image,p) < (QuantumRange/2.0))
479 p+=GetPixelChannels(image);
482 *q++=byte << (8-bit);
483 if (image->previous == (Image *) NULL)
485 status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
487 if (status == MagickFalse)
492 Initialize JBIG info structure.
494 jbg_enc_init(&jbig_info,(unsigned long) image->columns,(unsigned long)
495 image->rows,1,&pixels,(void (*)(unsigned char *,size_t,void *))
497 if (image_info->scene != 0)
498 jbg_enc_layers(&jbig_info,(int) image_info->scene);
507 if (image_info->density != (char *) NULL)
515 flags=ParseGeometry(image_info->density,&geometry_info);
516 x_resolution=geometry_info.rho;
517 y_resolution=geometry_info.sigma;
518 if ((flags & SigmaValue) == 0)
519 y_resolution=x_resolution;
521 if (image->units == PixelsPerCentimeterResolution)
523 x_resolution=(size_t) (100.0*2.54*x_resolution+0.5)/100.0;
524 y_resolution=(size_t) (100.0*2.54*y_resolution+0.5)/100.0;
526 (void) jbg_enc_lrlmax(&jbig_info,(unsigned long) x_resolution,
527 (unsigned long) y_resolution);
529 (void) jbg_enc_lrange(&jbig_info,-1,-1);
530 jbg_enc_options(&jbig_info,JBG_ILEAVE | JBG_SMID,JBG_TPDON | JBG_TPBON |
531 JBG_DPON,version < 1.6 ? -1 : 0,-1,-1);
535 jbg_enc_out(&jbig_info);
536 jbg_enc_free(&jbig_info);
537 pixels=(unsigned char *) RelinquishMagickMemory(pixels);
538 if (GetNextImageInList(image) == (Image *) NULL)
540 image=SyncNextImageInList(image);
541 status=SetImageProgress(image,SaveImagesTag,scene++,
542 GetImageListLength(image));
543 if (status == MagickFalse)
545 } while (image_info->adjoin != MagickFalse);
546 (void) CloseBlob(image);