2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6 % JJJJJ BBBB IIIII GGGG %
10 % JJJ BBBB IIIII GGG %
13 % Read/Write JBIG Image Format %
20 % Copyright 1999-2014 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/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)
76 #if defined(MAGICKCORE_JBIG_DELEGATE)
77 static MagickBooleanType
78 WriteJBIGImage(const ImageInfo *,Image *,ExceptionInfo *);
81 #if defined(MAGICKCORE_JBIG_DELEGATE)
83 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
87 % R e a d J B I G I m a g e %
91 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
93 % ReadJBIGImage() reads a JBIG image file and returns it. It
94 % allocates the memory necessary for the new Image structure and returns a
95 % pointer to the new image.
97 % The format of the ReadJBIGImage method is:
99 % Image *ReadJBIGImage(const ImageInfo *image_info,
100 % ExceptionInfo *exception)
102 % A description of each parameter follows:
104 % o image_info: the image info.
106 % o exception: return any errors or warnings in this structure.
109 static Image *ReadJBIGImage(const ImageInfo *image_info,
110 ExceptionInfo *exception)
127 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,exception);
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);
184 while ((length > 0) && ((status == JBG_EAGAIN) || (status == JBG_EOK)))
189 status=jbg_dec_in(&jbig_info,p,length,&count);
191 length-=(ssize_t) count;
193 } while ((status == JBG_EAGAIN) || (status == JBG_EOK));
197 image->columns=jbg_dec_getwidth(&jbig_info);
198 image->rows=jbg_dec_getheight(&jbig_info);
199 image->compression=JBIG2Compression;
200 if (AcquireImageColormap(image,2,exception) == MagickFalse)
202 buffer=(unsigned char *) RelinquishMagickMemory(buffer);
203 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
205 image->colormap[0].red=0;
206 image->colormap[0].green=0;
207 image->colormap[0].blue=0;
208 image->colormap[1].red=QuantumRange;
209 image->colormap[1].green=QuantumRange;
210 image->colormap[1].blue=QuantumRange;
211 image->resolution.x=300;
212 image->resolution.y=300;
213 if (image_info->ping != MagickFalse)
215 (void) CloseBlob(image);
216 return(GetFirstImageInList(image));
219 Convert X bitmap image to pixel packets.
221 p=jbg_dec_getimage(&jbig_info,0);
222 for (y=0; y < (ssize_t) image->rows; y++)
224 q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
225 if (q == (Quantum *) NULL)
229 for (x=0; x < (ssize_t) image->columns; x++)
233 index=(byte & 0x80) ? 0 : 1;
238 SetPixelIndex(image,index,q);
239 SetPixelInfoPixel(image,image->colormap+(ssize_t) index,q);
240 q+=GetPixelChannels(image);
242 if (SyncAuthenticPixels(image,exception) == MagickFalse)
244 status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y,
246 if (status == MagickFalse)
252 jbg_dec_free(&jbig_info);
253 buffer=(unsigned char *) RelinquishMagickMemory(buffer);
254 (void) CloseBlob(image);
255 return(GetFirstImageInList(image));
260 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
264 % R e g i s t e r J B I G I m a g e %
268 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
270 % RegisterJBIGImage() adds attributes for the JBIG image format to
271 % the list of supported formats. The attributes include the image format
272 % tag, a method to read and/or write the format, whether the format
273 % supports the saving of more than one frame to the same file or blob,
274 % whether the format supports native in-memory I/O, and a brief
275 % description of the format.
277 % The format of the RegisterJBIGImage method is:
279 % size_t RegisterJBIGImage(void)
282 ModuleExport size_t RegisterJBIGImage(void)
284 #define JBIGDescription "Joint Bi-level Image experts Group interchange format"
287 version[MaxTextExtent];
293 #if defined(JBG_VERSION)
294 (void) CopyMagickString(version,JBG_VERSION,MaxTextExtent);
296 entry=SetMagickInfo("BIE");
297 #if defined(MAGICKCORE_JBIG_DELEGATE)
298 entry->decoder=(DecodeImageHandler *) ReadJBIGImage;
299 entry->encoder=(EncodeImageHandler *) WriteJBIGImage;
301 entry->adjoin=MagickFalse;
302 entry->description=ConstantString(JBIGDescription);
303 if (*version != '\0')
304 entry->version=ConstantString(version);
305 entry->module=ConstantString("JBIG");
306 (void) RegisterMagickInfo(entry);
307 entry=SetMagickInfo("JBG");
308 #if defined(MAGICKCORE_JBIG_DELEGATE)
309 entry->decoder=(DecodeImageHandler *) ReadJBIGImage;
310 entry->encoder=(EncodeImageHandler *) WriteJBIGImage;
312 entry->description=ConstantString(JBIGDescription);
313 if (*version != '\0')
314 entry->version=ConstantString(version);
315 entry->module=ConstantString("JBIG");
316 (void) RegisterMagickInfo(entry);
317 entry=SetMagickInfo("JBIG");
318 #if defined(MAGICKCORE_JBIG_DELEGATE)
319 entry->decoder=(DecodeImageHandler *) ReadJBIGImage;
320 entry->encoder=(EncodeImageHandler *) WriteJBIGImage;
322 entry->description=ConstantString(JBIGDescription);
323 if (*version != '\0')
324 entry->version=ConstantString(version);
325 entry->module=ConstantString("JBIG");
326 (void) RegisterMagickInfo(entry);
327 return(MagickImageCoderSignature);
331 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
335 % U n r e g i s t e r J B I G I m a g e %
339 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
341 % UnregisterJBIGImage() removes format registrations made by the
342 % JBIG module from the list of supported formats.
344 % The format of the UnregisterJBIGImage method is:
346 % UnregisterJBIGImage(void)
349 ModuleExport void UnregisterJBIGImage(void)
351 (void) UnregisterMagickInfo("BIE");
352 (void) UnregisterMagickInfo("JBG");
353 (void) UnregisterMagickInfo("JBIG");
356 #if defined(MAGICKCORE_JBIG_DELEGATE)
358 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
362 % W r i t e J B I G I m a g e %
366 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
368 % WriteJBIGImage() writes an image in the JBIG encoded image format.
370 % The format of the WriteJBIGImage method is:
372 % MagickBooleanType WriteJBIGImage(const ImageInfo *image_info,
373 % Image *image,ExceptionInfo *exception)
375 % A description of each parameter follows.
377 % o image_info: the image info.
379 % o image: The image.
381 % o exception: return any errors or warnings in this structure.
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,
395 Image *image,ExceptionInfo *exception)
409 register const Quantum
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 assert(exception != (ExceptionInfo *) NULL);
442 assert(exception->signature == MagickSignature);
443 status=OpenBlob(image_info,image,WriteBinaryBlobMode,exception);
444 if (status == MagickFalse)
446 version=StringToDouble(JBG_VERSION,(char **) NULL);
453 if (IssRGBCompatibleColorspace(image->colorspace) == MagickFalse)
454 (void) TransformImageColorspace(image,sRGBColorspace,exception);
455 number_packets=(image->columns+7)/8;
456 pixel_info=AcquireVirtualMemory(number_packets,image->rows*sizeof(*pixels));
457 if (pixel_info == (MemoryInfo *) NULL)
458 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
459 pixels=(unsigned char *) GetVirtualMemoryBlob(pixel_info);
461 Convert pixels to a bitmap.
463 (void) SetImageType(image,BilevelType,exception);
465 for (y=0; y < (ssize_t) image->rows; y++)
467 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
468 if (p == (const Quantum *) NULL)
472 for (x=0; x < (ssize_t) image->columns; x++)
475 if (GetPixelLuma(image,p) < (QuantumRange/2.0))
484 p+=GetPixelChannels(image);
487 *q++=byte << (8-bit);
488 if (image->previous == (Image *) NULL)
490 status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
492 if (status == MagickFalse)
497 Initialize JBIG info structure.
499 jbg_enc_init(&jbig_info,(unsigned long) image->columns,(unsigned long)
500 image->rows,1,&pixels,(void (*)(unsigned char *,size_t,void *))
502 if (image_info->scene != 0)
503 jbg_enc_layers(&jbig_info,(int) image_info->scene);
512 if (image_info->density != (char *) NULL)
520 flags=ParseGeometry(image_info->density,&geometry_info);
521 x_resolution=geometry_info.rho;
522 y_resolution=geometry_info.sigma;
523 if ((flags & SigmaValue) == 0)
524 y_resolution=x_resolution;
526 if (image->units == PixelsPerCentimeterResolution)
528 x_resolution=(size_t) (100.0*2.54*x_resolution+0.5)/100.0;
529 y_resolution=(size_t) (100.0*2.54*y_resolution+0.5)/100.0;
531 (void) jbg_enc_lrlmax(&jbig_info,(unsigned long) x_resolution,
532 (unsigned long) y_resolution);
534 (void) jbg_enc_lrange(&jbig_info,-1,-1);
535 jbg_enc_options(&jbig_info,JBG_ILEAVE | JBG_SMID,JBG_TPDON | JBG_TPBON |
536 JBG_DPON,version < 1.6 ? -1 : 0,-1,-1);
540 jbg_enc_out(&jbig_info);
541 jbg_enc_free(&jbig_info);
542 pixel_info=RelinquishVirtualMemory(pixel_info);
543 if (GetNextImageInList(image) == (Image *) NULL)
545 image=SyncNextImageInList(image);
546 status=SetImageProgress(image,SaveImagesTag,scene++,
547 GetImageListLength(image));
548 if (status == MagickFalse)
550 } while (image_info->adjoin != MagickFalse);
551 (void) CloseBlob(image);