1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.commons.imaging.formats.psd.datareaders;
18
19 import java.awt.image.BufferedImage;
20 import java.io.ByteArrayInputStream;
21 import java.io.IOException;
22 import java.io.InputStream;
23 import java.nio.ByteOrder;
24
25 import org.apache.commons.imaging.ImagingException;
26 import org.apache.commons.imaging.common.Allocator;
27 import org.apache.commons.imaging.common.BinaryFileParser;
28 import org.apache.commons.imaging.common.BinaryFunctions;
29 import org.apache.commons.imaging.common.PackBits;
30 import org.apache.commons.imaging.formats.psd.PsdHeaderInfo;
31 import org.apache.commons.imaging.formats.psd.PsdImageContents;
32 import org.apache.commons.imaging.formats.psd.dataparsers.DataParser;
33 import org.apache.commons.imaging.mylzw.BitsToByteInputStream;
34 import org.apache.commons.imaging.mylzw.MyBitInputStream;
35
36 public class CompressedDataReader implements DataReader {
37
38 private final DataParser dataParser;
39
40 public CompressedDataReader(final DataParser dataParser) {
41 this.dataParser = dataParser;
42 }
43
44 @Override
45 public void readData(final InputStream is, final BufferedImage bi, final PsdImageContents imageContents, final BinaryFileParser bfp)
46 throws ImagingException, IOException {
47 final PsdHeaderInfo header = imageContents.header;
48 final int width = header.columns;
49 final int height = header.rows;
50
51
52 final int scanlineCount = height * header.channels;
53 final int[] scanlineByteCounts = Allocator.intArray(scanlineCount);
54 for (int i = 0; i < scanlineCount; i++) {
55 scanlineByteCounts[i] = BinaryFunctions.read2Bytes("scanlineByteCounts[" + i + "]", is, "PSD: bad Image Data", bfp.getByteOrder());
56 }
57
58
59
60 final int depth = header.depth;
61
62 final int channelCount = dataParser.getBasicChannelsCount();
63 final int[][][] data = new int[Allocator.check(channelCount)][Allocator.check(height)][];
64
65 for (int channel = 0; channel < channelCount; channel++) {
66 for (int y = 0; y < height; y++) {
67 final int index = channel * height + y;
68 final byte[] packed = BinaryFunctions.readBytes("scanline", is, scanlineByteCounts[index], "PSD: Missing Image Data");
69
70 final byte[] unpacked = PackBits.decompress(packed, width);
71 try (InputStream bais = new ByteArrayInputStream(unpacked);
72 MyBitInputStream mbis = new MyBitInputStream(bais, ByteOrder.BIG_ENDIAN, false)) {
73
74 try (BitsToByteInputStream bbis = new BitsToByteInputStream(mbis, 8)) {
75 final int[] scanline = bbis.readBitsArray(depth, width);
76 data[channel][y] = scanline;
77 }
78 }
79 }
80 }
81 dataParser.parseData(data, bi, imageContents);
82 }
83
84 }