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 "magick/studio.h"
43 #include "magick/blob.h"
44 #include "magick/blob-private.h"
45 #include "magick/cache.h"
46 #include "magick/color-private.h"
47 #include "magick/colormap.h"
48 #include "magick/colorspace.h"
49 #include "magick/constitute.h"
50 #include "magick/exception.h"
51 #include "magick/exception-private.h"
52 #include "magick/geometry.h"
53 #include "magick/image.h"
54 #include "magick/image-private.h"
55 #include "magick/list.h"
56 #include "magick/magick.h"
57 #include "magick/memory_.h"
58 #include "magick/monitor.h"
59 #include "magick/monitor-private.h"
60 #include "magick/nt-feature.h"
61 #include "magick/quantum-private.h"
62 #include "magick/static.h"
63 #include "magick/string_.h"
64 #include "magick/module.h"
65 #if defined(MAGICKCORE_JBIG_DELEGATE)
72 #if defined(MAGICKCORE_JBIG_DELEGATE)
73 static MagickBooleanType
74 WriteJBIGImage(const ImageInfo *,Image *);
77 #if defined(MAGICKCORE_JBIG_DELEGATE)
79 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
83 % R e a d J B I G I m a g e %
87 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
89 % ReadJBIGImage() reads a JBIG image file and returns it. It
90 % allocates the memory necessary for the new Image structure and returns a
91 % pointer to the new image.
93 % The format of the ReadJBIGImage method is:
95 % Image *ReadJBIGImage(const ImageInfo *image_info,
96 % ExceptionInfo *exception)
98 % A description of each parameter follows:
100 % o image_info: the image info.
102 % o exception: return any errors or warnings in this structure.
105 static Image *ReadJBIGImage(const ImageInfo *image_info,
106 ExceptionInfo *exception)
126 register unsigned char
145 assert(image_info != (const ImageInfo *) NULL);
146 assert(image_info->signature == MagickSignature);
147 if (image_info->debug != MagickFalse)
148 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
149 image_info->filename);
150 assert(exception != (ExceptionInfo *) NULL);
151 assert(exception->signature == MagickSignature);
152 image=AcquireImage(image_info);
153 status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
154 if (status == MagickFalse)
156 image=DestroyImageList(image);
157 return((Image *) NULL);
160 Initialize JBIG toolkit.
162 jbg_dec_init(&jbig_info);
163 jbg_dec_maxsize(&jbig_info,(unsigned long) image->columns,(unsigned long)
165 image->columns=jbg_dec_getwidth(&jbig_info);
166 image->rows=jbg_dec_getheight(&jbig_info);
168 image->storage_class=PseudoClass;
173 buffer=(unsigned char *) AcquireQuantumMemory(MagickMaxBufferExtent,
175 if (buffer == (unsigned char *) NULL)
176 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
180 length=(ssize_t) ReadBlob(image,MagickMaxBufferExtent,buffer);
185 while ((length > 0) && ((status == JBG_EAGAIN) || (status == JBG_EOK)))
190 status=jbg_dec_in(&jbig_info,p,length,&count);
192 length-=(ssize_t) count;
194 } while ((status == JBG_EAGAIN) || (status == JBG_EOK));
198 image->columns=jbg_dec_getwidth(&jbig_info);
199 image->rows=jbg_dec_getheight(&jbig_info);
200 image->compression=JBIG2Compression;
201 if (AcquireImageColormap(image,2) == MagickFalse)
203 buffer=(unsigned char *) RelinquishMagickMemory(buffer);
204 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
206 image->colormap[0].red=0;
207 image->colormap[0].green=0;
208 image->colormap[0].blue=0;
209 image->colormap[1].red=QuantumRange;
210 image->colormap[1].green=QuantumRange;
211 image->colormap[1].blue=QuantumRange;
212 image->x_resolution=300;
213 image->y_resolution=300;
214 if (image_info->ping != MagickFalse)
216 (void) CloseBlob(image);
217 return(GetFirstImageInList(image));
220 Convert X bitmap image to pixel packets.
222 p=jbg_dec_getimage(&jbig_info,0);
223 for (y=0; y < (ssize_t) image->rows; y++)
225 q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
226 if (q == (PixelPacket *) NULL)
228 indexes=GetAuthenticIndexQueue(image);
231 for (x=0; x < (ssize_t) image->columns; x++)
235 index=(byte & 0x80) ? 0 : 1;
240 SetIndexPixelComponent(indexes+x,index);
241 SetRGBOPixelComponents(q,image->colormap+(ssize_t) index);
244 if (SyncAuthenticPixels(image,exception) == MagickFalse)
246 status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y,
248 if (status == MagickFalse)
254 jbg_dec_free(&jbig_info);
255 buffer=(unsigned char *) RelinquishMagickMemory(buffer);
256 (void) CloseBlob(image);
257 return(GetFirstImageInList(image));
262 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
266 % R e g i s t e r J B I G I m a g e %
270 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
272 % RegisterJBIGImage() adds attributes for the JBIG image format to
273 % the list of supported formats. The attributes include the image format
274 % tag, a method to read and/or write the format, whether the format
275 % supports the saving of more than one frame to the same file or blob,
276 % whether the format supports native in-memory I/O, and a brief
277 % description of the format.
279 % The format of the RegisterJBIGImage method is:
281 % size_t RegisterJBIGImage(void)
284 ModuleExport size_t RegisterJBIGImage(void)
286 #define JBIGDescription "Joint Bi-level Image experts Group interchange format"
289 version[MaxTextExtent];
295 #if defined(JBG_VERSION)
296 (void) CopyMagickString(version,JBG_VERSION,MaxTextExtent);
298 entry=SetMagickInfo("BIE");
299 #if defined(MAGICKCORE_JBIG_DELEGATE)
300 entry->decoder=(DecodeImageHandler *) ReadJBIGImage;
301 entry->encoder=(EncodeImageHandler *) WriteJBIGImage;
303 entry->adjoin=MagickFalse;
304 entry->description=ConstantString(JBIGDescription);
305 if (*version != '\0')
306 entry->version=ConstantString(version);
307 entry->module=ConstantString("JBIG");
308 (void) RegisterMagickInfo(entry);
309 entry=SetMagickInfo("JBG");
310 #if defined(MAGICKCORE_JBIG_DELEGATE)
311 entry->decoder=(DecodeImageHandler *) ReadJBIGImage;
312 entry->encoder=(EncodeImageHandler *) WriteJBIGImage;
314 entry->description=ConstantString(JBIGDescription);
315 if (*version != '\0')
316 entry->version=ConstantString(version);
317 entry->module=ConstantString("JBIG");
318 (void) RegisterMagickInfo(entry);
319 entry=SetMagickInfo("JBIG");
320 #if defined(MAGICKCORE_JBIG_DELEGATE)
321 entry->decoder=(DecodeImageHandler *) ReadJBIGImage;
322 entry->encoder=(EncodeImageHandler *) WriteJBIGImage;
324 entry->description=ConstantString(JBIGDescription);
325 if (*version != '\0')
326 entry->version=ConstantString(version);
327 entry->module=ConstantString("JBIG");
328 (void) RegisterMagickInfo(entry);
329 return(MagickImageCoderSignature);
333 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
337 % U n r e g i s t e r J B I G I m a g e %
341 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
343 % UnregisterJBIGImage() removes format registrations made by the
344 % JBIG module from the list of supported formats.
346 % The format of the UnregisterJBIGImage method is:
348 % UnregisterJBIGImage(void)
351 ModuleExport void UnregisterJBIGImage(void)
353 (void) UnregisterMagickInfo("BIE");
354 (void) UnregisterMagickInfo("JBG");
355 (void) UnregisterMagickInfo("JBIG");
358 #if defined(MAGICKCORE_JBIG_DELEGATE)
360 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
364 % W r i t e J B I G I m a g e %
368 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
370 % WriteJBIGImage() writes an image in the JBIG encoded image format.
372 % The format of the WriteJBIGImage method is:
374 % MagickBooleanType WriteJBIGImage(const ImageInfo *image_info,Image *image)
376 % A description of each parameter follows.
378 % o image_info: the image info.
380 % o image: The image.
385 static void JBIGEncode(unsigned char *pixels,size_t length,void *data)
390 image=(Image *) data;
391 (void) WriteBlob(image,length,pixels);
394 static MagickBooleanType WriteJBIGImage(const ImageInfo *image_info,
406 register const IndexPacket
409 register const PixelPacket
415 register unsigned char
435 assert(image_info != (const ImageInfo *) NULL);
436 assert(image_info->signature == MagickSignature);
437 assert(image != (Image *) NULL);
438 assert(image->signature == MagickSignature);
439 if (image->debug != MagickFalse)
440 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
441 status=OpenBlob(image_info,image,WriteBinaryBlobMode,&image->exception);
442 if (status == MagickFalse)
444 version=InterpretLocaleValue(JBG_VERSION,(char **) NULL);
451 if (image->colorspace != RGBColorspace)
452 (void) TransformImageColorspace(image,RGBColorspace);
453 number_packets=(image->columns+7)/8;
454 pixels=(unsigned char *) AcquireQuantumMemory(number_packets,
455 image->rows*sizeof(*pixels));
456 if (pixels == (unsigned char *) NULL)
457 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
459 Convert pixels to a bitmap.
461 (void) SetImageType(image,BilevelType);
463 for (y=0; y < (ssize_t) image->rows; y++)
465 p=GetVirtualPixels(image,0,y,image->columns,1,&image->exception);
466 if (p == (const PixelPacket *) NULL)
468 indexes=GetVirtualIndexQueue(image);
471 for (x=0; x < (ssize_t) image->columns; x++)
474 if (PixelIntensity(p) < (QuantumRange/2.0))
486 *q++=byte << (8-bit);
487 if (image->previous == (Image *) NULL)
489 status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
491 if (status == MagickFalse)
496 Initialize JBIG info structure.
498 jbg_enc_init(&jbig_info,(unsigned long) image->columns,(unsigned long)
499 image->rows,1,&pixels,(void (*)(unsigned char *,size_t,void *))
501 if (image_info->scene != 0)
502 jbg_enc_layers(&jbig_info,(int) image_info->scene);
515 if (image_info->density != (char *) NULL)
523 flags=ParseGeometry(image_info->density,&geometry_info);
524 x_resolution=geometry_info.rho;
525 y_resolution=geometry_info.sigma;
526 if ((flags & SigmaValue) == 0)
527 y_resolution=x_resolution;
529 if (image->units == PixelsPerCentimeterResolution)
531 x_resolution=(size_t) (100.0*2.54*x_resolution+0.5)/100.0;
532 y_resolution=(size_t) (100.0*2.54*y_resolution+0.5)/100.0;
534 (void) jbg_enc_lrlmax(&jbig_info,(unsigned long) x_resolution,
535 (unsigned long) y_resolution);
537 (void) jbg_enc_lrange(&jbig_info,-1,-1);
538 jbg_enc_options(&jbig_info,JBG_ILEAVE | JBG_SMID,JBG_TPDON | JBG_TPBON |
539 JBG_DPON,version < 1.6 ? -1 : 0,-1,-1);
543 jbg_enc_out(&jbig_info);
544 jbg_enc_free(&jbig_info);
545 pixels=(unsigned char *) RelinquishMagickMemory(pixels);
546 if (GetNextImageInList(image) == (Image *) NULL)
548 image=SyncNextImageInList(image);
549 status=SetImageProgress(image,SaveImagesTag,scene++,
550 GetImageListLength(image));
551 if (status == MagickFalse)
553 } while (image_info->adjoin != MagickFalse);
554 (void) CloseBlob(image);