1 package nom.tam.image.compression.tile;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34 import java.nio.ByteBuffer;
35
36 import nom.tam.image.compression.tile.mask.ImageNullPixelMask;
37 import nom.tam.image.compression.tile.mask.NullPixelMaskPreserver;
38 import nom.tam.image.tile.operation.TileArea;
39 import nom.tam.util.type.ElementType;
40
41
42
43
44
45
46
47 public class TileCompressor extends TileCompressionOperation {
48
49 private boolean forceNoLoss = false;
50
51 private NullPixelMaskPreserver nullPixelMaskPerserver;
52
53
54
55
56
57
58
59
60 protected TileCompressor(TiledImageCompressionOperation array, int tileIndex, TileArea area) {
61 super(array, tileIndex, area);
62 }
63
64 @Override
65 public void run() {
66 compress();
67 }
68
69
70
71
72
73 private void compactCompressedData() {
74 synchronized (lock) {
75 if (getTileIndex() > 0) {
76
77 getPreviousTileOperation().waitForResult();
78 ByteBuffer compressedWholeArea = getCompressedWholeArea();
79 compressedOffset = compressedWholeArea.position();
80 ElementType.BYTE.appendBuffer(compressedWholeArea, compressedData);
81 replaceCompressedBufferWithTargetArea(compressedWholeArea);
82 } else {
83 compressedOffset = 0;
84 getCompressedWholeArea().position(compressedData.limit());
85 }
86 }
87 }
88
89 private void compress() {
90 synchronized (lock) {
91 initTileOptions();
92 getTiledImageOperation().ensureColumnParameters();
93
94 compressedData.limit(getTileBuffer().getPixelSize() * getBaseType().size());
95 compressionType = TileCompressionType.COMPRESSED;
96 boolean compressSuccess = false;
97 boolean tryNormalCompression = !(tileOptions.isLossyCompression() && forceNoLoss);
98
99 tileOptions.getCompressionParameters().setTileIndex(getTileIndex());
100
101 if (tryNormalCompression) {
102 compressSuccess = getCompressorControl().compress(getTileBuffer().getBuffer(), compressedData, tileOptions);
103 if (compressSuccess) {
104 if (nullPixelMaskPerserver != null) {
105 nullPixelMaskPerserver.preserveNull();
106 }
107 tileOptions.getCompressionParameters().setValuesInColumn(getTileIndex());
108 }
109 }
110
111 if (!compressSuccess) {
112 compressionType = TileCompressionType.GZIP_COMPRESSED;
113 compressedData.rewind();
114 getTileBuffer().getBuffer().rewind();
115 compressSuccess = getGzipCompressorControl().compress(getTileBuffer().getBuffer(), compressedData, null);
116 if (compressSuccess) {
117 tileOptions.getCompressionParameters().setValuesInColumn(getTileIndex());
118 }
119 }
120
121 if (!compressSuccess) {
122 compressionType = TileCompressionType.UNCOMPRESSED;
123 compressedData.rewind();
124 getTileBuffer().getBuffer().rewind();
125 getBaseType().appendToByteBuffer(compressedData, getTileBuffer().getBuffer());
126 }
127
128 compressedData.limit(compressedData.position());
129 compressedData.rewind();
130
131 compactCompressedData();
132 }
133 }
134
135 private void replaceCompressedBufferWithTargetArea(ByteBuffer compressedWholeArea) {
136 synchronized (lock) {
137 int compressedSize = compressedData.limit();
138 int latest = compressedWholeArea.position();
139 compressedWholeArea.position(compressedOffset);
140 compressedData = compressedWholeArea.slice();
141 compressedData.limit(compressedSize);
142 compressedWholeArea.position(latest);
143 }
144 }
145
146 @Override
147 protected NullPixelMaskPreserver createImageNullPixelMask(ImageNullPixelMask imageNullPixelMask) {
148 synchronized (lock) {
149 if (imageNullPixelMask != null) {
150 nullPixelMaskPerserver = imageNullPixelMask.createTilePreserver(getTileBuffer(), getTileIndex());
151 }
152 return nullPixelMaskPerserver;
153 }
154 }
155
156 @Override
157 protected void forceNoLoss(boolean value) {
158 synchronized (lock) {
159 forceNoLoss = value;
160 }
161 }
162 }