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) 71extern "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) 83static 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*/ 115static 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*/ 301ModuleExport 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*/ 362ModuleExport 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 398static 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 407static 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