1 //========================================================================
5 // This file is licensed under the GPLv2 or later
7 // Copyright (C) 2010, 2012 William Bader <williambader@hotmail.com>
8 // Copyright (C) 2012 Albert Astals Cid <aacid@kde.org>
9 // Copyright (C) 2012 Adrian Johnson <ajohnson@redneon.com>
10 // Copyright (C) 2012 Pino Toscano <pino@kde.org>
11 // Copyright (C) 2014 Steven Lee <roc.sky@gmail.com>
13 //========================================================================
15 #include "TiffWriter.h"
29 struct TiffWriterPrivate
{
30 TIFF
*f
; // LibTiff file context
31 int numRows
; // number of rows in the image
32 int curRow
; // number of rows written
33 const char *compressionString
; // compression type
34 TiffWriter::Format format
; // format of image data
37 TiffWriter::~TiffWriter()
42 TiffWriter::TiffWriter(Format formatA
)
44 priv
= new TiffWriterPrivate
;
48 priv
->compressionString
= NULL
;
49 priv
->format
= formatA
;
52 // Set the compression type
54 void TiffWriter::setCompressionString(const char *compressionStringArg
)
56 priv
->compressionString
= compressionStringArg
;
61 bool TiffWriter::init(FILE *openedFile
, int width
, int height
, int hDPI
, int vDPI
)
63 unsigned int compression
;
64 uint16 photometric
= 0;
65 uint32 rowsperstrip
= (uint32
) -1;
67 uint16 samplesperpixel
= 0;
68 const struct compression_name_tag
{
69 const char *compressionName
; // name of the compression option from the command line
70 unsigned int compressionCode
; // internal libtiff code
71 const char *compressionDescription
; // descriptive name
72 } compressionList
[] = {
73 { "none", COMPRESSION_NONE
, "no compression" },
74 { "ccittrle", COMPRESSION_CCITTRLE
, "CCITT modified Huffman RLE" },
75 { "ccittfax3", COMPRESSION_CCITTFAX3
,"CCITT Group 3 fax encoding" },
76 { "ccittt4", COMPRESSION_CCITT_T4
, "CCITT T.4 (TIFF 6 name)" },
77 { "ccittfax4", COMPRESSION_CCITTFAX4
, "CCITT Group 4 fax encoding" },
78 { "ccittt6", COMPRESSION_CCITT_T6
, "CCITT T.6 (TIFF 6 name)" },
79 { "lzw", COMPRESSION_LZW
, "Lempel-Ziv & Welch" },
80 { "ojpeg", COMPRESSION_OJPEG
, "!6.0 JPEG" },
81 { "jpeg", COMPRESSION_JPEG
, "%JPEG DCT compression" },
82 { "next", COMPRESSION_NEXT
, "NeXT 2-bit RLE" },
83 { "packbits", COMPRESSION_PACKBITS
, "Macintosh RLE" },
84 { "ccittrlew", COMPRESSION_CCITTRLEW
, "CCITT modified Huffman RLE w/ word alignment" },
85 { "deflate", COMPRESSION_DEFLATE
, "Deflate compression" },
86 { "adeflate", COMPRESSION_ADOBE_DEFLATE
, "Deflate compression, as recognized by Adobe" },
87 { "dcs", COMPRESSION_DCS
, "Kodak DCS encoding" },
88 { "jbig", COMPRESSION_JBIG
, "ISO JBIG" },
89 { "jp2000", COMPRESSION_JP2000
, "Leadtools JPEG2000" },
98 // Store the number of rows
100 priv
->numRows
= height
;
102 // Set the compression
104 compression
= COMPRESSION_NONE
;
106 if (priv
->compressionString
== NULL
|| strcmp(priv
->compressionString
, "") == 0) {
107 compression
= COMPRESSION_NONE
;
110 for (i
= 0; compressionList
[i
].compressionName
!= NULL
; i
++) {
111 if (strcmp(priv
->compressionString
, compressionList
[i
].compressionName
) == 0) {
112 compression
= compressionList
[i
].compressionCode
;
116 if (compressionList
[i
].compressionName
== NULL
) {
117 fprintf(stderr
, "TiffWriter: Unknown compression type '%.10s', using 'none'.\n", priv
->compressionString
);
118 fprintf(stderr
, "Known compression types (the tiff library might not support every type)\n");
119 for (i
= 0; compressionList
[i
].compressionName
!= NULL
; i
++) {
120 fprintf(stderr
, "%10s %s\n", compressionList
[i
].compressionName
, compressionList
[i
].compressionDescription
);
125 // Set bits per sample, samples per pixel, and photometric type from format
127 bitspersample
= (priv
->format
== MONOCHROME
? 1 : 8);
129 switch (priv
->format
) {
133 photometric
= PHOTOMETRIC_MINISBLACK
;
138 photometric
= PHOTOMETRIC_RGB
;
141 case RGBA_PREMULTIPLIED
:
143 photometric
= PHOTOMETRIC_RGB
;
148 photometric
= PHOTOMETRIC_SEPARATED
;
154 if (openedFile
== NULL
) {
155 fprintf(stderr
, "TiffWriter: No output file given.\n");
160 //Convert C Library handle to Win32 Handle
161 priv
->f
= TIFFFdOpen(_get_osfhandle(fileno(openedFile
)), "-", "w");
163 priv
->f
= TIFFFdOpen(fileno(openedFile
), "-", "w");
173 TIFFSetField(priv
->f
, TIFFTAG_IMAGEWIDTH
, width
);
174 TIFFSetField(priv
->f
, TIFFTAG_IMAGELENGTH
, height
);
175 TIFFSetField(priv
->f
, TIFFTAG_ORIENTATION
, ORIENTATION_TOPLEFT
);
176 TIFFSetField(priv
->f
, TIFFTAG_SAMPLESPERPIXEL
, samplesperpixel
);
177 TIFFSetField(priv
->f
, TIFFTAG_BITSPERSAMPLE
, bitspersample
);
178 TIFFSetField(priv
->f
, TIFFTAG_PLANARCONFIG
, PLANARCONFIG_CONTIG
);
179 TIFFSetField(priv
->f
, TIFFTAG_PHOTOMETRIC
, photometric
);
180 TIFFSetField(priv
->f
, TIFFTAG_COMPRESSION
, (uint16
) compression
);
181 TIFFSetField(priv
->f
, TIFFTAG_ROWSPERSTRIP
, TIFFDefaultStripSize(priv
->f
, rowsperstrip
));
182 TIFFSetField(priv
->f
, TIFFTAG_XRESOLUTION
, (double) hDPI
);
183 TIFFSetField(priv
->f
, TIFFTAG_YRESOLUTION
, (double) vDPI
);
184 TIFFSetField(priv
->f
, TIFFTAG_RESOLUTIONUNIT
, RESUNIT_INCH
);
186 if (priv
->format
== RGBA_PREMULTIPLIED
) {
187 uint16 extra
= EXTRASAMPLE_ASSOCALPHA
;
188 TIFFSetField(priv
->f
, TIFFTAG_EXTRASAMPLES
, 1, &extra
);
191 if (priv
->format
== CMYK
) {
192 TIFFSetField(priv
->f
, TIFFTAG_INKSET
, INKSET_CMYK
);
193 TIFFSetField(priv
->f
, TIFFTAG_NUMBEROFINKS
, 4);
199 bool TiffWriter::writePointers(unsigned char **rowPointers
, int rowCount
)
201 // Write all rows to the file
203 for (int row
= 0; row
< rowCount
; row
++) {
204 if (TIFFWriteScanline(priv
->f
, rowPointers
[row
], row
, 0) < 0) {
205 fprintf(stderr
, "TiffWriter: Error writing tiff row %d\n", row
);
213 bool TiffWriter::writeRow(unsigned char **rowData
)
217 if (TIFFWriteScanline(priv
->f
, *rowData
, priv
->curRow
, 0) < 0) {
218 fprintf(stderr
, "TiffWriter: Error writing tiff row %d\n", priv
->curRow
);
227 bool TiffWriter::close()