Skip to content

Commit 2d9b0c2

Browse files
author
Dmitry Trusevich
committed
Port Png and Tiff Writers from Itext5
(DEVSIX-484)
1 parent 26f2925 commit 2d9b0c2

File tree

8 files changed

+986
-6
lines changed

8 files changed

+986
-6
lines changed

io/src/main/java/com/itextpdf/io/IOException.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ public class IOException extends RuntimeException {
3535
public static final String CcittCompressionTypeMustBeCcittg4Ccittg3_1dOrCcittg3_2d = "ccitt.compression.type.must.be.ccittg4.ccittg3.1d.or.ccittg3.2d";
3636
public static final String ComponentsMustBe1_3Or4 = "components.must.be.1.3.or.4";
3737
public static final String Compression1IsNotSupported = "compression {0} is.not.supported";
38+
public static final String ColorDepthIsNotSupported = "the.color.depth {0} is.not.supported";
39+
public static final String ColorSpaceIsNotSupported = "the.color.space {0} is.not.supported";
3840
public static final String CompressionJpegIsOnlySupportedWithASingleStripThisImageHas1Strips = "compression.jpeg.is.only.supported.with.a.single.strip.this.image.has {0} strips";
3941
public static final String DirectoryNumberTooLarge = "directory.number.too.large";
4042
public static final String EolCodeWordEncounteredInBlackRun = "eol.code.word.encountered.in.black.run";
@@ -79,6 +81,7 @@ public class IOException extends RuntimeException {
7981
public static final String JpegImageException = "jpeg.image.exception";
8082
public static final String Jpeg2000ImageException = "jpeg2000.image.exception";
8183
public static final String MissingTagSForOjpegCompression = "missing.tag.s.for.ojpeg.compression";
84+
public static final String NValueIsNotSupported = "N.value.1.is.not.supported";
8285
public static final String PageNumberMustBeGtEq1 = "page.number.must.be.gt.eq {0}";
8386
public static final String PdfEncodings = "pdf.encodings";
8487
public static final String PdfHeaderNotFound = "pdf.header.not.found";
Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
package com.itextpdf.io.codec;
2+
3+
import java.io.IOException;
4+
import java.io.OutputStream;
5+
6+
/**
7+
* Came from GIFEncoder initially.
8+
* Modified - to allow for output compressed data without the block counts
9+
* which breakup the compressed data stream for GIF.
10+
*/
11+
class BitFile {
12+
13+
OutputStream output;
14+
15+
byte buffer[];
16+
17+
int index;
18+
19+
// bits left at current index that are avail.
20+
int bitsLeft;
21+
22+
/**
23+
* note this also indicates gif format BITFile.
24+
**/
25+
boolean blocks = false;
26+
27+
/**
28+
* @param output destination for output data
29+
* @param blocks GIF LZW requires block counts for output data
30+
**/
31+
public BitFile(OutputStream output, boolean blocks) {
32+
this.output = output;
33+
this.blocks = blocks;
34+
buffer = new byte[256];
35+
index = 0;
36+
bitsLeft = 8;
37+
}
38+
39+
public void flush() throws IOException {
40+
int numBytes = index + (bitsLeft == 8 ? 0 : 1);
41+
if (numBytes > 0) {
42+
if (blocks)
43+
output.write(numBytes);
44+
output.write(buffer, 0, numBytes);
45+
buffer[0] = 0;
46+
index = 0;
47+
bitsLeft = 8;
48+
}
49+
}
50+
51+
public void writeBits(int bits, int numbits) throws IOException {
52+
int bitsWritten = 0;
53+
int numBytes = 255; // gif block count
54+
do {
55+
// This handles the GIF block count stuff
56+
if ((index == 254 && bitsLeft == 0) || index > 254) {
57+
if (blocks)
58+
output.write(numBytes);
59+
60+
output.write(buffer, 0, numBytes);
61+
62+
buffer[0] = 0;
63+
index = 0;
64+
bitsLeft = 8;
65+
}
66+
67+
if (numbits <= bitsLeft) // bits contents fit in current index byte
68+
{
69+
if (blocks) // GIF
70+
{
71+
buffer[index] |= (bits & ((1 << numbits) - 1)) << (8 - bitsLeft);
72+
bitsWritten += numbits;
73+
bitsLeft -= numbits;
74+
numbits = 0;
75+
} else {
76+
buffer[index] |= (bits & ((1 << numbits) - 1)) << (bitsLeft - numbits);
77+
bitsWritten += numbits;
78+
bitsLeft -= numbits;
79+
numbits = 0;
80+
81+
}
82+
} else // bits overflow from current byte to next.
83+
{
84+
if (blocks) // GIF
85+
{
86+
// if bits > space left in current byte then the lowest order bits
87+
// of code are taken and put in current byte and rest put in next.
88+
buffer[index] |= (bits & ((1 << bitsLeft) - 1)) << (8 - bitsLeft);
89+
bitsWritten += bitsLeft;
90+
bits >>= bitsLeft;
91+
numbits -= bitsLeft;
92+
buffer[++index] = 0;
93+
bitsLeft = 8;
94+
} else {
95+
// if bits > space left in current byte then the highest order bits
96+
// of code are taken and put in current byte and rest put in next.
97+
// at highest order bit location !!
98+
int topbits = (bits >>> (numbits - bitsLeft)) & ((1 << bitsLeft) - 1);
99+
buffer[index] |= topbits;
100+
numbits -= bitsLeft; // ok this many bits gone off the top
101+
bitsWritten += bitsLeft;
102+
buffer[++index] = 0; // next index
103+
bitsLeft = 8;
104+
}
105+
}
106+
107+
} while (numbits != 0);
108+
}
109+
}
Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
package com.itextpdf.io.codec;
2+
3+
4+
import java.io.IOException;
5+
import java.io.OutputStream;
6+
7+
/**
8+
* Modified from original LZWCompressor to change interface to passing a
9+
* buffer of data to be compressed.
10+
*/
11+
public class LZWCompressor {
12+
/**
13+
* base underlying code size of data being compressed 8 for TIFF, 1 to 8 for GIF
14+
**/
15+
int codeSize_;
16+
17+
/**
18+
* reserved clear code based on code size
19+
**/
20+
int clearCode_;
21+
22+
/**
23+
* reserved end of data code based on code size
24+
**/
25+
int endOfInfo_;
26+
27+
/**
28+
* current number bits output for each code
29+
**/
30+
int numBits_;
31+
32+
/**
33+
* limit at which current number of bits code size has to be increased
34+
**/
35+
int limit_;
36+
37+
/**
38+
* the prefix code which represents the predecessor string to current input point
39+
**/
40+
short prefix_;
41+
42+
/**
43+
* output destination for bit codes
44+
**/
45+
BitFile bf_;
46+
47+
/**
48+
* general purpose LZW string table
49+
**/
50+
LZWStringTable lzss_;
51+
52+
/**
53+
* modify the limits of the code values in LZW encoding due to TIFF bug / feature
54+
**/
55+
boolean tiffFudge_;
56+
57+
/**
58+
* @param out destination for compressed data
59+
* @param codeSize the initial code size for the LZW compressor
60+
* @param TIFF flag indicating that TIFF lzw fudge needs to be applied
61+
* @throws IOException if underlying output stream error
62+
**/
63+
public LZWCompressor(OutputStream out, int codeSize, boolean TIFF) throws IOException {
64+
bf_ = new BitFile(out, !TIFF); // set flag for GIF as NOT tiff
65+
codeSize_ = codeSize;
66+
tiffFudge_ = TIFF;
67+
clearCode_ = 1 << codeSize_;
68+
endOfInfo_ = clearCode_ + 1;
69+
numBits_ = codeSize_ + 1;
70+
71+
limit_ = (1 << numBits_) - 1;
72+
if (tiffFudge_)
73+
--limit_;
74+
75+
prefix_ = (short) 0xFFFF;
76+
lzss_ = new LZWStringTable();
77+
lzss_.ClearTable(codeSize_);
78+
bf_.writeBits(clearCode_, numBits_);
79+
}
80+
81+
/**
82+
* @param buf data to be compressed to output stream
83+
* @throws IOException if underlying output stream error
84+
**/
85+
public void compress(byte[] buf, int offset, int length)
86+
throws IOException {
87+
int idx;
88+
byte c;
89+
short index;
90+
91+
int maxOffset = offset + length;
92+
for (idx = offset; idx < maxOffset; ++idx) {
93+
c = buf[idx];
94+
if ((index = lzss_.FindCharString(prefix_, c)) != -1)
95+
prefix_ = index;
96+
else {
97+
bf_.writeBits(prefix_, numBits_);
98+
if (lzss_.AddCharString(prefix_, c) > limit_) {
99+
if (numBits_ == 12) {
100+
bf_.writeBits(clearCode_, numBits_);
101+
lzss_.ClearTable(codeSize_);
102+
numBits_ = codeSize_ + 1;
103+
} else
104+
++numBits_;
105+
106+
limit_ = (1 << numBits_) - 1;
107+
if (tiffFudge_)
108+
--limit_;
109+
}
110+
prefix_ = (short) ((short) c & 0xFF);
111+
}
112+
}
113+
}
114+
115+
/**
116+
* Indicate to compressor that no more data to go so write out
117+
* any remaining buffered data.
118+
*
119+
* @throws IOException if underlying output stream error
120+
**/
121+
public void flush() throws IOException {
122+
if (prefix_ != -1)
123+
bf_.writeBits(prefix_, numBits_);
124+
125+
bf_.writeBits(endOfInfo_, numBits_);
126+
bf_.flush();
127+
}
128+
}

0 commit comments

Comments
 (0)