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
93 compressedData.limit(getTileBuffer().getPixelSize() * getBaseType().size());
94 compressionType = TileCompressionType.COMPRESSED;
95 boolean compressSuccess = false;
96 boolean tryNormalCompression = !(tileOptions.isLossyCompression() && forceNoLoss);
97
98 tileOptions.getCompressionParameters().setTileIndex(getTileIndex());
99
100 if (tryNormalCompression) {
101 compressSuccess = getCompressorControl().compress(getTileBuffer().getBuffer(), compressedData, tileOptions);
102 if (compressSuccess) {
103 if (nullPixelMaskPerserver != null) {
104 nullPixelMaskPerserver.preserveNull();
105 }
106 tileOptions.getCompressionParameters().setValuesInColumn(getTileIndex());
107 }
108 }
109
110 if (!compressSuccess) {
111 compressionType = TileCompressionType.GZIP_COMPRESSED;
112 compressedData.rewind();
113 getTileBuffer().getBuffer().rewind();
114 compressSuccess = getGzipCompressorControl().compress(getTileBuffer().getBuffer(), compressedData, null);
115 if (compressSuccess) {
116 tileOptions.getCompressionParameters().setValuesInColumn(getTileIndex());
117 }
118 }
119
120 if (!compressSuccess) {
121 compressionType = TileCompressionType.UNCOMPRESSED;
122 compressedData.rewind();
123 getTileBuffer().getBuffer().rewind();
124 getBaseType().appendToByteBuffer(compressedData, getTileBuffer().getBuffer());
125 }
126
127 compressedData.limit(compressedData.position());
128 compressedData.rewind();
129
130 compactCompressedData();
131 }
132 }
133
134 private void replaceCompressedBufferWithTargetArea(ByteBuffer compressedWholeArea) {
135 synchronized (lock) {
136 int compressedSize = compressedData.limit();
137 int latest = compressedWholeArea.position();
138 compressedWholeArea.position(compressedOffset);
139 compressedData = compressedWholeArea.slice();
140 compressedData.limit(compressedSize);
141 compressedWholeArea.position(latest);
142 }
143 }
144
145 @Override
146 protected NullPixelMaskPreserver createImageNullPixelMask(ImageNullPixelMask imageNullPixelMask) {
147 synchronized (lock) {
148 if (imageNullPixelMask != null) {
149 nullPixelMaskPerserver = imageNullPixelMask.createTilePreserver(getTileBuffer(), getTileIndex());
150 }
151 return nullPixelMaskPerserver;
152 }
153 }
154
155 @Override
156 protected void forceNoLoss(boolean value) {
157 synchronized (lock) {
158 forceNoLoss = value;
159 }
160 }
161 }