| 149 | | |
| 150 | | static inline size_t WriteCALSLSBLong(FILE *file,const unsigned int value) |
| 151 | | { |
| 152 | | unsigned char |
| 153 | | buffer[4]; |
| 154 | | |
| 155 | | buffer[0]=(unsigned char) value; |
| 156 | | buffer[1]=(unsigned char) (value >> 8); |
| 157 | | buffer[2]=(unsigned char) (value >> 16); |
| 158 | | buffer[3]=(unsigned char) (value >> 24); |
| 159 | | return(fwrite(buffer,1,4,file)); |
| 160 | | } |
| 161 | | |
| 162 | | #if defined(MAGICKCORE_TIFF_DELEGATE) |
| 163 | | static Image *Huffman2DDecodeImage(const ImageInfo *image_info,Image *image, |
| 164 | | ExceptionInfo *exception) |
| 165 | | { |
| 166 | | char |
| 167 | | filename[MaxTextExtent]; |
| 168 | | |
| 169 | | FILE |
| 170 | | *file; |
| 171 | | |
| 172 | | Image |
| 173 | | *huffman_image; |
| 174 | | |
| 175 | | ImageInfo |
| 176 | | *read_info; |
| 177 | | |
| 178 | | int |
| 179 | | c, |
| 180 | | unique_file; |
| 181 | | |
| 182 | | size_t |
| 183 | | length; |
| 184 | | |
| 185 | | ssize_t |
| 186 | | offset, |
| 187 | | strip_offset; |
| 188 | | |
| 189 | | /* |
| 190 | | Write CALS facsimile document wrapped as a TIFF image file. |
| 191 | | */ |
| 192 | | file=(FILE *) NULL; |
| 193 | | unique_file=AcquireUniqueFileResource(filename); |
| 194 | | if (unique_file != -1) |
| 195 | | file=fdopen(unique_file,"wb"); |
| 196 | | if ((unique_file == -1) || (file == (FILE *) NULL)) |
| 197 | | ThrowImageException(FileOpenError,"UnableToCreateTemporaryFile"); |
| 198 | | length=fwrite("\111\111\052\000\010\000\000\000\016\000",1,10,file); |
| 199 | | length=fwrite("\376\000\003\000\001\000\000\000\000\000\000\000",1,12,file); |
| 200 | | length=fwrite("\000\001\004\000\001\000\000\000",1,8,file); |
| 201 | | length=WriteCALSLSBLong(file,image->columns); |
| 202 | | length=fwrite("\001\001\004\000\001\000\000\000",1,8,file); |
| 203 | | length=WriteCALSLSBLong(file,image->rows); |
| 204 | | length=fwrite("\002\001\003\000\001\000\000\000\001\000\000\000",1,12,file); |
| 205 | | length=fwrite("\003\001\003\000\001\000\000\000\004\000\000\000",1,12,file); |
| 206 | | length=fwrite("\006\001\003\000\001\000\000\000\000\000\000\000",1,12,file); |
| 207 | | length=fwrite("\021\001\003\000\001\000\000\000",1,8,file); |
| 208 | | strip_offset=10+(12*14)+4+8; |
| 209 | | length=WriteCALSLSBLong(file,(unsigned long) strip_offset); |
| 210 | | length=fwrite("\022\001\003\000\001\000\000\000",1,8,file); |
| 211 | | length=WriteCALSLSBLong(file,(unsigned long) image->orientation); |
| 212 | | length=fwrite("\025\001\003\000\001\000\000\000\001\000\000\000",1,12,file); |
| 213 | | length=fwrite("\026\001\004\000\001\000\000\000",1,8,file); |
| 214 | | length=WriteCALSLSBLong(file,image->columns); |
| 215 | | length=fwrite("\027\001\004\000\001\000\000\000\000\000\000\000",1,12,file); |
| 216 | | offset=(ssize_t) ftell(file)-4; |
| 217 | | length=fwrite("\032\001\005\000\001\000\000\000",1,8,file); |
| 218 | | length=WriteCALSLSBLong(file,(unsigned long) (strip_offset-8)); |
| 219 | | length=fwrite("\033\001\005\000\001\000\000\000",1,8,file); |
| 220 | | length=WriteCALSLSBLong(file,(unsigned long) (strip_offset-8)); |
| 221 | | length=fwrite("\050\001\003\000\001\000\000\000\002\000\000\000",1,12,file); |
| 222 | | length=fwrite("\000\000\000\000",1,4,file); |
| 223 | | length=WriteCALSLSBLong(file,image->x_resolution); |
| 224 | | length=WriteCALSLSBLong(file,1); |
| 225 | | for (length=0; (c=ReadBlobByte(image)) != EOF; length++) |
| 226 | | (void) fputc(c,file); |
| 227 | | (void) CloseBlob(image); |
| 228 | | offset=(ssize_t) fseek(file,(long) offset,SEEK_SET); |
| 229 | | length=WriteCALSLSBLong(file,(unsigned int) length); |
| 230 | | (void) fclose(file); |
| 231 | | /* |
| 232 | | Read TIFF image. |
| 233 | | */ |
| 234 | | read_info=CloneImageInfo(image_info); |
| 235 | | SetImageInfoBlob(read_info,(void *) NULL,0); |
| 236 | | (void) FormatMagickString(read_info->filename,MaxTextExtent,"tiff:%.1024s", |
| 237 | | filename); |
| 238 | | huffman_image=ReadImage(read_info,exception); |
| 239 | | if (huffman_image != (Image *) NULL) |
| 240 | | { |
| 241 | | (void) CopyMagickString(huffman_image->filename,image_info->filename, |
| 242 | | MaxTextExtent); |
| 243 | | (void) CopyMagickString(huffman_image->magick_filename, |
| 244 | | image_info->filename,MaxTextExtent); |
| 245 | | (void) CopyMagickString(huffman_image->magick,"CALS",MaxTextExtent); |
| 246 | | } |
| 247 | | read_info=DestroyImageInfo(read_info); |
| 248 | | (void) RelinquishUniqueFileResource(filename); |
| 249 | | return(huffman_image); |
| 250 | | } |
| 251 | | #else |
| 252 | | static Image *Huffman2DDecodeImage(const ImageInfo *magick_unused(image_info), |
| 253 | | Image *image,ExceptionInfo *exception) |
| 254 | | { |
| 255 | | assert(image != (Image *) NULL); |
| 256 | | assert(image->signature == MagickSignature); |
| 257 | | (void) ThrowMagickException(exception,GetMagickModule(),MissingDelegateError, |
| 258 | | "DelegateLibrarySupportNotBuiltIn","`%s' (TIFF)",image->filename); |
| 259 | | return((Image *) NULL); |
| 260 | | } |
| 261 | | #endif |
| 262 | | |
| 368 | | (void) CloseBlob(huffman_image); |
| 369 | | if (huffman_image == (Image *) NULL) |
| 370 | | return(huffman_image); |
| 371 | | return(GetFirstImageInList(huffman_image)); |
| | 261 | read_info=CloneImageInfo(image_info); |
| | 262 | SetImageInfoBlob(read_info,(void *) NULL,0); |
| | 263 | (void) FormatMagickString(read_info->filename,MaxTextExtent,"group4:%.1024s", |
| | 264 | filename); |
| | 265 | (void) FormatMagickString(message,MaxTextExtent,"%lux%lu",width,height); |
| | 266 | read_info->size=ConstantString(message); |
| | 267 | (void) FormatMagickString(message,MaxTextExtent,"%lu",density); |
| | 268 | read_info->density=ConstantString(message); |
| | 269 | read_info->orientation=(OrientationType) orientation; |
| | 270 | image=ReadImage(read_info,exception); |
| | 271 | if (image != (Image *) NULL) |
| | 272 | { |
| | 273 | (void) CopyMagickString(image->filename,image_info->filename, |
| | 274 | MaxTextExtent); |
| | 275 | (void) CopyMagickString(image->magick_filename,image_info->filename, |
| | 276 | MaxTextExtent); |
| | 277 | (void) CopyMagickString(image->magick,"CALS",MaxTextExtent); |
| | 278 | } |
| | 279 | read_info=DestroyImageInfo(read_info); |
| | 280 | (void) RelinquishUniqueFileResource(filename); |
| | 281 | return(image); |
| 489 | | #if defined(MAGICKCORE_TIFF_DELEGATE) |
| 490 | | static MagickBooleanType Huffman2DEncodeImage(const ImageInfo *image_info, |
| 491 | | Image *image,Image *inject_image) |
| 492 | | { |
| 493 | | char |
| 494 | | filename[MaxTextExtent]; |
| 495 | | |
| 496 | | FILE |
| 497 | | *file; |
| 498 | | |
| 499 | | Image |
| 500 | | *huffman_image; |
| 501 | | |
| 502 | | ImageInfo |
| 503 | | *write_info; |
| 504 | | |
| 505 | | int |
| 506 | | unique_file; |
| 507 | | |
| 508 | | MagickBooleanType |
| 509 | | status; |
| 510 | | |
| 511 | | register long |
| 512 | | i; |
| 513 | | |
| 514 | | ssize_t |
| 515 | | count; |
| 516 | | |
| 517 | | TIFF |
| 518 | | *tiff; |
| 519 | | |
| 520 | | uint16 |
| 521 | | fillorder; |
| 522 | | |
| 523 | | uint32 |
| 524 | | *byte_count, |
| 525 | | strip_size; |
| 526 | | |
| 527 | | unsigned char |
| 528 | | *buffer; |
| 529 | | |
| 530 | | /* |
| 531 | | Write image as CCITTFax4 TIFF image to a temporary file. |
| 532 | | */ |
| 533 | | assert(image_info != (const ImageInfo *) NULL); |
| 534 | | assert(image_info->signature == MagickSignature); |
| 535 | | assert(image != (Image *) NULL); |
| 536 | | assert(image->signature == MagickSignature); |
| 537 | | if (image->debug != MagickFalse) |
| 538 | | (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); |
| 539 | | assert(inject_image != (Image *) NULL); |
| 540 | | assert(inject_image->signature == MagickSignature); |
| 541 | | huffman_image=CloneImage(inject_image,0,0,MagickTrue,&image->exception); |
| 542 | | if (huffman_image == (Image *) NULL) |
| 543 | | return(MagickFalse); |
| 544 | | file=(FILE *) NULL; |
| 545 | | unique_file=AcquireUniqueFileResource(filename); |
| 546 | | if (unique_file != -1) |
| 547 | | file=fdopen(unique_file,"wb"); |
| 548 | | if ((unique_file == -1) || (file == (FILE *) NULL)) |
| 549 | | { |
| 550 | | ThrowFileException(&image->exception,FileOpenError, |
| 551 | | "UnableToCreateTemporaryFile",filename); |
| 552 | | return(MagickFalse); |
| 553 | | } |
| 554 | | (void) FormatMagickString(huffman_image->filename,MaxTextExtent,"tiff:%s", |
| 555 | | filename); |
| 556 | | write_info=CloneImageInfo(image_info); |
| 557 | | SetImageInfoFile(write_info,file); |
| 558 | | write_info->compression=Group4Compression; |
| 559 | | write_info->type=BilevelType; |
| 560 | | (void) SetImageOption(write_info,"quantum:polarity","min-is-white"); |
| 561 | | status=WriteImage(write_info,huffman_image); |
| 562 | | (void) fflush(file); |
| 563 | | write_info=DestroyImageInfo(write_info); |
| 564 | | if (status == MagickFalse) |
| 565 | | { |
| 566 | | (void) RelinquishUniqueFileResource(filename); |
| 567 | | return(MagickFalse); |
| 568 | | } |
| 569 | | tiff=TIFFOpen(filename,"rb"); |
| 570 | | if (tiff == (TIFF *) NULL) |
| 571 | | { |
| 572 | | huffman_image=DestroyImage(huffman_image); |
| 573 | | (void) fclose(file); |
| 574 | | (void) RelinquishUniqueFileResource(filename); |
| 575 | | ThrowFileException(&image->exception,FileOpenError,"UnableToOpenFile", |
| 576 | | image_info->filename); |
| 577 | | return(MagickFalse); |
| 578 | | } |
| 579 | | /* |
| 580 | | Allocate raw strip buffer. |
| 581 | | */ |
| 582 | | byte_count=0; |
| 583 | | (void) TIFFGetField(tiff,TIFFTAG_STRIPBYTECOUNTS,&byte_count); |
| 584 | | strip_size=byte_count[0]; |
| 585 | | for (i=1; i < (long) TIFFNumberOfStrips(tiff); i++) |
| 586 | | if (byte_count[i] > strip_size) |
| 587 | | strip_size=byte_count[i]; |
| 588 | | buffer=(unsigned char *) AcquireQuantumMemory((size_t) strip_size, |
| 589 | | sizeof(*buffer)); |
| 590 | | if (buffer == (unsigned char *) NULL) |
| 591 | | { |
| 592 | | TIFFClose(tiff); |
| 593 | | huffman_image=DestroyImage(huffman_image); |
| 594 | | (void) fclose(file); |
| 595 | | (void) RelinquishUniqueFileResource(filename); |
| 596 | | ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed", |
| 597 | | image_info->filename); |
| 598 | | } |
| 599 | | /* |
| 600 | | Compress runlength encoded to 2D Huffman pixels. |
| 601 | | */ |
| 602 | | fillorder=FILLORDER_LSB2MSB; |
| 603 | | (void) TIFFGetFieldDefaulted(tiff,TIFFTAG_FILLORDER,&fillorder); |
| 604 | | for (i=0; i < (long) TIFFNumberOfStrips(tiff); i++) |
| 605 | | { |
| 606 | | count=(ssize_t) TIFFReadRawStrip(tiff,(uint32) i,buffer,(long) |
| 607 | | byte_count[i]); |
| 608 | | if (fillorder == FILLORDER_LSB2MSB) |
| 609 | | TIFFReverseBits(buffer,(unsigned long) count); |
| 610 | | (void) WriteBlob(image,(size_t) count,buffer); |
| 611 | | } |
| 612 | | buffer=(unsigned char *) RelinquishMagickMemory(buffer); |
| 613 | | TIFFClose(tiff); |
| 614 | | huffman_image=DestroyImage(huffman_image); |
| 615 | | (void) fclose(file); |
| 616 | | (void) RelinquishUniqueFileResource(filename); |
| 617 | | return(MagickTrue); |
| 618 | | } |
| 619 | | #else |
| 620 | | static MagickBooleanType Huffman2DEncodeImage(const ImageInfo *image_info, |
| 621 | | Image *image,Image *inject_image) |
| 622 | | { |
| 623 | | assert(image_info != (const ImageInfo *) NULL); |
| 624 | | assert(image_info->signature == MagickSignature); |
| 625 | | assert(image != (Image *) NULL); |
| 626 | | assert(image->signature == MagickSignature); |
| 627 | | if (image->debug != MagickFalse) |
| 628 | | (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); |
| 629 | | assert(inject_image != (Image *) NULL); |
| 630 | | assert(inject_image->signature == MagickSignature); |
| 631 | | (void) ThrowMagickException(&image->exception,GetMagickModule(), |
| 632 | | MissingDelegateError,"DelegateLibrarySupportNotBuiltIn","`%s' (TIFF)", |
| 633 | | image->filename); |
| 634 | | return(MagickFalse); |
| 635 | | } |
| 636 | | #endif |
| 637 | | |
| 778 | | (void) WriteBlob(image,128,(unsigned char *) buffer); |
| 779 | | status=Huffman2DEncodeImage(image_info,image,image); |
| | 551 | (void) WriteBlob(image,128,(unsigned char *) header); |
| | 552 | /* |
| | 553 | Write CALS pixels. |
| | 554 | */ |
| | 555 | write_info=CloneImageInfo(image_info); |
| | 556 | (void) CopyMagickString(write_info->filename,"GROUP4:",MaxTextExtent); |
| | 557 | (void) CopyMagickString(write_info->magick,"GROUP4",MaxTextExtent); |
| | 558 | group4_image=CloneImage(image,0,0,MagickTrue,&image->exception); |
| | 559 | if (group4_image == (Image *) NULL) |
| | 560 | { |
| | 561 | (void) CloseBlob(image); |
| | 562 | return(MagickFalse); |
| | 563 | } |
| | 564 | group4=(unsigned char *) ImageToBlob(write_info,group4_image,&length, |
| | 565 | &image->exception); |
| | 566 | group4_image=DestroyImage(group4_image); |
| | 567 | if (group4 == (unsigned char *) NULL) |
| | 568 | { |
| | 569 | (void) CloseBlob(image); |
| | 570 | return(MagickFalse); |
| | 571 | } |
| | 572 | write_info=DestroyImageInfo(write_info); |
| | 573 | if (WriteBlob(image,length,group4) != (ssize_t) length) |
| | 574 | status=MagickFalse; |
| | 575 | group4=(unsigned char *) RelinquishMagickMemory(group4); |