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