| | 234 | |
| | 235 | #if defined(MAGICKCORE_TIFF_DELEGATE) |
| | 236 | /* |
| | 237 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
| | 238 | % % |
| | 239 | % % |
| | 240 | % % |
| | 241 | % R e a d G R O U P 4 I m a g e % |
| | 242 | % % |
| | 243 | % % |
| | 244 | % % |
| | 245 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
| | 246 | % |
| | 247 | % ReadGROUP4Image() reads a raw CCITT Group 4 image file and returns it. It |
| | 248 | % allocates the memory necessary for the new Image structure and returns a |
| | 249 | % pointer to the new image. |
| | 250 | % |
| | 251 | % The format of the ReadGROUP4Image method is: |
| | 252 | % |
| | 253 | % Image *ReadGROUP4Image(const ImageInfo *image_info, |
| | 254 | % ExceptionInfo *exception) |
| | 255 | % |
| | 256 | % A description of each parameter follows: |
| | 257 | % |
| | 258 | % o image_info: the image info. |
| | 259 | % |
| | 260 | % o exception: return any errors or warnings in this structure. |
| | 261 | % |
| | 262 | */ |
| | 263 | |
| | 264 | static inline size_t WriteLSBLong(FILE *file,const unsigned int value) |
| | 265 | { |
| | 266 | unsigned char |
| | 267 | buffer[4]; |
| | 268 | |
| | 269 | buffer[0]=(unsigned char) value; |
| | 270 | buffer[1]=(unsigned char) (value >> 8); |
| | 271 | buffer[2]=(unsigned char) (value >> 16); |
| | 272 | buffer[3]=(unsigned char) (value >> 24); |
| | 273 | return(fwrite(buffer,1,4,file)); |
| | 274 | } |
| | 275 | |
| | 276 | static Image *ReadGROUP4Image(const ImageInfo *image_info, |
| | 277 | ExceptionInfo *exception) |
| | 278 | { |
| | 279 | char |
| | 280 | filename[MaxTextExtent]; |
| | 281 | |
| | 282 | FILE |
| | 283 | *file; |
| | 284 | |
| | 285 | Image |
| | 286 | *image; |
| | 287 | |
| | 288 | ImageInfo |
| | 289 | *read_info; |
| | 290 | |
| | 291 | int |
| | 292 | c, |
| | 293 | unique_file; |
| | 294 | |
| | 295 | MagickBooleanType |
| | 296 | status; |
| | 297 | |
| | 298 | size_t |
| | 299 | length; |
| | 300 | |
| | 301 | ssize_t |
| | 302 | offset, |
| | 303 | strip_offset; |
| | 304 | |
| | 305 | /* |
| | 306 | Open image file. |
| | 307 | */ |
| | 308 | assert(image_info != (const ImageInfo *) NULL); |
| | 309 | assert(image_info->signature == MagickSignature); |
| | 310 | if (image_info->debug != MagickFalse) |
| | 311 | (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s", |
| | 312 | image_info->filename); |
| | 313 | assert(exception != (ExceptionInfo *) NULL); |
| | 314 | assert(exception->signature == MagickSignature); |
| | 315 | image=AcquireImage(image_info); |
| | 316 | status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception); |
| | 317 | if (status == MagickFalse) |
| | 318 | { |
| | 319 | image=DestroyImageList(image); |
| | 320 | return((Image *) NULL); |
| | 321 | } |
| | 322 | /* |
| | 323 | Write raw CCITT Group 4 wrapped as a TIFF image file. |
| | 324 | */ |
| | 325 | file=(FILE *) NULL; |
| | 326 | unique_file=AcquireUniqueFileResource(filename); |
| | 327 | if (unique_file != -1) |
| | 328 | file=fdopen(unique_file,"wb"); |
| | 329 | if ((unique_file == -1) || (file == (FILE *) NULL)) |
| | 330 | ThrowImageException(FileOpenError,"UnableToCreateTemporaryFile"); |
| | 331 | length=fwrite("\111\111\052\000\010\000\000\000\016\000",1,10,file); |
| | 332 | length=fwrite("\376\000\003\000\001\000\000\000\000\000\000\000",1,12,file); |
| | 333 | length=fwrite("\000\001\004\000\001\000\000\000",1,8,file); |
| | 334 | length=WriteLSBLong(file,image->columns); |
| | 335 | length=fwrite("\001\001\004\000\001\000\000\000",1,8,file); |
| | 336 | length=WriteLSBLong(file,image->rows); |
| | 337 | length=fwrite("\002\001\003\000\001\000\000\000\001\000\000\000",1,12,file); |
| | 338 | length=fwrite("\003\001\003\000\001\000\000\000\004\000\000\000",1,12,file); |
| | 339 | length=fwrite("\006\001\003\000\001\000\000\000\000\000\000\000",1,12,file); |
| | 340 | length=fwrite("\021\001\003\000\001\000\000\000",1,8,file); |
| | 341 | strip_offset=10+(12*14)+4+8; |
| | 342 | length=WriteLSBLong(file,(unsigned long) strip_offset); |
| | 343 | length=fwrite("\022\001\003\000\001\000\000\000",1,8,file); |
| | 344 | length=WriteLSBLong(file,(unsigned long) image->orientation); |
| | 345 | length=fwrite("\025\001\003\000\001\000\000\000\001\000\000\000",1,12,file); |
| | 346 | length=fwrite("\026\001\004\000\001\000\000\000",1,8,file); |
| | 347 | length=WriteLSBLong(file,image->columns); |
| | 348 | length=fwrite("\027\001\004\000\001\000\000\000\000\000\000\000",1,12,file); |
| | 349 | offset=(ssize_t) ftell(file)-4; |
| | 350 | length=fwrite("\032\001\005\000\001\000\000\000",1,8,file); |
| | 351 | length=WriteLSBLong(file,(unsigned long) (strip_offset-8)); |
| | 352 | length=fwrite("\033\001\005\000\001\000\000\000",1,8,file); |
| | 353 | length=WriteLSBLong(file,(unsigned long) (strip_offset-8)); |
| | 354 | length=fwrite("\050\001\003\000\001\000\000\000\002\000\000\000",1,12,file); |
| | 355 | length=fwrite("\000\000\000\000",1,4,file); |
| | 356 | length=WriteLSBLong(file,image->x_resolution); |
| | 357 | length=WriteLSBLong(file,1); |
| | 358 | for (length=0; (c=ReadBlobByte(image)) != EOF; length++) |
| | 359 | (void) fputc(c,file); |
| | 360 | offset=(ssize_t) fseek(file,(long) offset,SEEK_SET); |
| | 361 | length=WriteLSBLong(file,(unsigned int) length); |
| | 362 | (void) fclose(file); |
| | 363 | (void) CloseBlob(image); |
| | 364 | image=DestroyImage(image); |
| | 365 | /* |
| | 366 | Read TIFF image. |
| | 367 | */ |
| | 368 | read_info=CloneImageInfo(image_info); |
| | 369 | SetImageInfoBlob(read_info,(void *) NULL,0); |
| | 370 | (void) FormatMagickString(read_info->filename,MaxTextExtent,"%.1024s", |
| | 371 | filename); |
| | 372 | image=ReadTIFFImage(read_info,exception); |
| | 373 | read_info=DestroyImageInfo(read_info); |
| | 374 | if (image != (Image *) NULL) |
| | 375 | { |
| | 376 | (void) CopyMagickString(image->filename,image_info->filename, |
| | 377 | MaxTextExtent); |
| | 378 | (void) CopyMagickString(image->magick_filename,image_info->filename, |
| | 379 | MaxTextExtent); |
| | 380 | (void) CopyMagickString(image->magick,"GROUP4",MaxTextExtent); |
| | 381 | } |
| | 382 | (void) RelinquishUniqueFileResource(filename); |
| | 383 | return(image); |
| | 384 | } |
| | 385 | #endif |
| | 1792 | |
| | 1793 | #if defined(MAGICKCORE_TIFF_DELEGATE) |
| | 1794 | /* |
| | 1795 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
| | 1796 | % % |
| | 1797 | % % |
| | 1798 | % % |
| | 1799 | % W r i t e G R O U P 4 I m a g e % |
| | 1800 | % % |
| | 1801 | % % |
| | 1802 | % % |
| | 1803 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
| | 1804 | % |
| | 1805 | % WriteGROUP4Image() writes an image in the raw CCITT Group 4 image format. |
| | 1806 | % |
| | 1807 | % The format of the WriteGROUP4Image method is: |
| | 1808 | % |
| | 1809 | % MagickBooleanType WriteGROUP4Image(const ImageInfo *image_info, |
| | 1810 | % Image *image) |
| | 1811 | % |
| | 1812 | % A description of each parameter follows: |
| | 1813 | % |
| | 1814 | % o image_info: the image info. |
| | 1815 | % |
| | 1816 | % o image: The image. |
| | 1817 | % |
| | 1818 | */ |
| | 1819 | static MagickBooleanType WriteGROUP4Image(const ImageInfo *image_info, |
| | 1820 | Image *image) |
| | 1821 | { |
| | 1822 | char |
| | 1823 | filename[MaxTextExtent]; |
| | 1824 | |
| | 1825 | FILE |
| | 1826 | *file; |
| | 1827 | |
| | 1828 | Image |
| | 1829 | *huffman_image; |
| | 1830 | |
| | 1831 | ImageInfo |
| | 1832 | *write_info; |
| | 1833 | |
| | 1834 | int |
| | 1835 | unique_file; |
| | 1836 | |
| | 1837 | MagickBooleanType |
| | 1838 | status; |
| | 1839 | |
| | 1840 | register long |
| | 1841 | i; |
| | 1842 | |
| | 1843 | ssize_t |
| | 1844 | count; |
| | 1845 | |
| | 1846 | TIFF |
| | 1847 | *tiff; |
| | 1848 | |
| | 1849 | uint16 |
| | 1850 | fillorder; |
| | 1851 | |
| | 1852 | uint32 |
| | 1853 | *byte_count, |
| | 1854 | strip_size; |
| | 1855 | |
| | 1856 | unsigned char |
| | 1857 | *buffer; |
| | 1858 | |
| | 1859 | /* |
| | 1860 | Write image as CCITT Group4 TIFF image to a temporary file. |
| | 1861 | */ |
| | 1862 | assert(image_info != (const ImageInfo *) NULL); |
| | 1863 | assert(image_info->signature == MagickSignature); |
| | 1864 | assert(image != (Image *) NULL); |
| | 1865 | assert(image->signature == MagickSignature); |
| | 1866 | if (image->debug != MagickFalse) |
| | 1867 | (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); |
| | 1868 | status=OpenBlob(image_info,image,WriteBinaryBlobMode,&image->exception); |
| | 1869 | if (status == MagickFalse) |
| | 1870 | return(status); |
| | 1871 | huffman_image=CloneImage(image,0,0,MagickTrue,&image->exception); |
| | 1872 | if (huffman_image == (Image *) NULL) |
| | 1873 | { |
| | 1874 | (void) CloseBlob(image); |
| | 1875 | return(MagickFalse); |
| | 1876 | } |
| | 1877 | file=(FILE *) NULL; |
| | 1878 | unique_file=AcquireUniqueFileResource(filename); |
| | 1879 | if (unique_file != -1) |
| | 1880 | file=fdopen(unique_file,"wb"); |
| | 1881 | if ((unique_file == -1) || (file == (FILE *) NULL)) |
| | 1882 | { |
| | 1883 | ThrowFileException(&image->exception,FileOpenError, |
| | 1884 | "UnableToCreateTemporaryFile",filename); |
| | 1885 | return(MagickFalse); |
| | 1886 | } |
| | 1887 | (void) FormatMagickString(huffman_image->filename,MaxTextExtent,"tiff:%s", |
| | 1888 | filename); |
| | 1889 | (void) SetImageType(huffman_image,BilevelType); |
| | 1890 | write_info=CloneImageInfo(image_info); |
| | 1891 | SetImageInfoFile(write_info,file); |
| | 1892 | write_info->compression=Group4Compression; |
| | 1893 | write_info->type=BilevelType; |
| | 1894 | (void) SetImageOption(write_info,"quantum:polarity","min-is-white"); |
| | 1895 | status=WriteTIFFImage(write_info,huffman_image); |
| | 1896 | (void) fflush(file); |
| | 1897 | write_info=DestroyImageInfo(write_info); |
| | 1898 | if (status == MagickFalse) |
| | 1899 | { |
| | 1900 | InheritException(&image->exception,&huffman_image->exception); |
| | 1901 | huffman_image=DestroyImage(huffman_image); |
| | 1902 | (void) fclose(file); |
| | 1903 | (void) RelinquishUniqueFileResource(filename); |
| | 1904 | return(MagickFalse); |
| | 1905 | } |
| | 1906 | tiff=TIFFOpen(filename,"rb"); |
| | 1907 | if (tiff == (TIFF *) NULL) |
| | 1908 | { |
| | 1909 | huffman_image=DestroyImage(huffman_image); |
| | 1910 | (void) fclose(file); |
| | 1911 | (void) RelinquishUniqueFileResource(filename); |
| | 1912 | ThrowFileException(&image->exception,FileOpenError,"UnableToOpenFile", |
| | 1913 | image_info->filename); |
| | 1914 | return(MagickFalse); |
| | 1915 | } |
| | 1916 | /* |
| | 1917 | Allocate raw strip buffer. |
| | 1918 | */ |
| | 1919 | byte_count=0; |
| | 1920 | (void) TIFFGetField(tiff,TIFFTAG_STRIPBYTECOUNTS,&byte_count); |
| | 1921 | strip_size=byte_count[0]; |
| | 1922 | for (i=1; i < (long) TIFFNumberOfStrips(tiff); i++) |
| | 1923 | if (byte_count[i] > strip_size) |
| | 1924 | strip_size=byte_count[i]; |
| | 1925 | buffer=(unsigned char *) AcquireQuantumMemory((size_t) strip_size, |
| | 1926 | sizeof(*buffer)); |
| | 1927 | if (buffer == (unsigned char *) NULL) |
| | 1928 | { |
| | 1929 | TIFFClose(tiff); |
| | 1930 | huffman_image=DestroyImage(huffman_image); |
| | 1931 | (void) fclose(file); |
| | 1932 | (void) RelinquishUniqueFileResource(filename); |
| | 1933 | ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed", |
| | 1934 | image_info->filename); |
| | 1935 | } |
| | 1936 | /* |
| | 1937 | Compress runlength encoded to 2D Huffman pixels. |
| | 1938 | */ |
| | 1939 | fillorder=FILLORDER_LSB2MSB; |
| | 1940 | (void) TIFFGetFieldDefaulted(tiff,TIFFTAG_FILLORDER,&fillorder); |
| | 1941 | for (i=0; i < (long) TIFFNumberOfStrips(tiff); i++) |
| | 1942 | { |
| | 1943 | count=(ssize_t) TIFFReadRawStrip(tiff,(uint32) i,buffer,(long) |
| | 1944 | byte_count[i]); |
| | 1945 | if (fillorder == FILLORDER_LSB2MSB) |
| | 1946 | TIFFReverseBits(buffer,(unsigned long) count); |
| | 1947 | if (WriteBlob(image,(size_t) count,buffer) != count) |
| | 1948 | status=MagickFalse; |
| | 1949 | } |
| | 1950 | buffer=(unsigned char *) RelinquishMagickMemory(buffer); |
| | 1951 | TIFFClose(tiff); |
| | 1952 | huffman_image=DestroyImage(huffman_image); |
| | 1953 | (void) fclose(file); |
| | 1954 | (void) RelinquishUniqueFileResource(filename); |
| | 1955 | (void) CloseBlob(image); |
| | 1956 | return(status); |
| | 1957 | } |
| | 1958 | #endif |