1 package nom.tam.fits.compression.algorithm.gzip2;
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.io.IOException;
35 import java.nio.Buffer;
36 import java.nio.ByteBuffer;
37 import java.nio.DoubleBuffer;
38 import java.nio.FloatBuffer;
39 import java.nio.IntBuffer;
40 import java.nio.LongBuffer;
41 import java.nio.ShortBuffer;
42 import java.util.zip.GZIPInputStream;
43 import java.util.zip.GZIPOutputStream;
44
45 import nom.tam.fits.compression.algorithm.gzip.GZipCompressor;
46 import nom.tam.util.type.ElementType;
47
48
49
50
51
52
53 @SuppressWarnings("javadoc")
54 public abstract class GZip2Compressor<T extends Buffer> extends GZipCompressor<T> {
55
56 public static class ByteGZip2Compressor extends ByteGZipCompressor {
57 }
58
59 public static class IntGZip2Compressor extends GZip2Compressor<IntBuffer> {
60
61 public IntGZip2Compressor() {
62 super(ElementType.INT.size());
63 }
64
65 @Override
66 protected void getPixel(IntBuffer pixelData, byte[] pixelBytes) {
67 IntBuffer pixelBuffer = ByteBuffer.wrap(pixelBytes).asIntBuffer();
68 pixelBuffer.put(pixelData);
69 }
70
71 @Override
72 protected void setPixel(IntBuffer pixelData, byte[] pixelBytes) {
73 pixelData.put(ByteBuffer.wrap(pixelBytes).asIntBuffer());
74 }
75 }
76
77 public static class FloatGZip2Compressor extends GZip2Compressor<FloatBuffer> {
78
79 public FloatGZip2Compressor() {
80 super(ElementType.FLOAT.size());
81 }
82
83 @Override
84 protected void getPixel(FloatBuffer pixelData, byte[] pixelBytes) {
85 FloatBuffer pixelBuffer = ByteBuffer.wrap(pixelBytes).asFloatBuffer();
86 pixelBuffer.put(pixelData);
87 }
88
89 @Override
90 protected void setPixel(FloatBuffer pixelData, byte[] pixelBytes) {
91 pixelData.put(ByteBuffer.wrap(pixelBytes).asFloatBuffer());
92 }
93 }
94
95 public static class LongGZip2Compressor extends GZip2Compressor<LongBuffer> {
96
97 public LongGZip2Compressor() {
98 super(ElementType.LONG.size());
99 }
100
101 @Override
102 protected void getPixel(LongBuffer pixelData, byte[] pixelBytes) {
103 LongBuffer pixelBuffer = ByteBuffer.wrap(pixelBytes).asLongBuffer();
104 pixelBuffer.put(pixelData);
105 }
106
107 @Override
108 protected void setPixel(LongBuffer pixelData, byte[] pixelBytes) {
109 pixelData.put(ByteBuffer.wrap(pixelBytes).asLongBuffer());
110 }
111 }
112
113 public static class DoubleGZip2Compressor extends GZip2Compressor<DoubleBuffer> {
114
115 public DoubleGZip2Compressor() {
116 super(ElementType.DOUBLE.size());
117 }
118
119 @Override
120 protected void getPixel(DoubleBuffer pixelData, byte[] pixelBytes) {
121 DoubleBuffer pixelBuffer = ByteBuffer.wrap(pixelBytes).asDoubleBuffer();
122 pixelBuffer.put(pixelData);
123 }
124
125 @Override
126 protected void setPixel(DoubleBuffer pixelData, byte[] pixelBytes) {
127 pixelData.put(ByteBuffer.wrap(pixelBytes).asDoubleBuffer());
128 }
129 }
130
131 public static class ShortGZip2Compressor extends GZip2Compressor<ShortBuffer> {
132
133 public ShortGZip2Compressor() {
134 super(ElementType.SHORT.size());
135 }
136
137 @Override
138 protected void getPixel(ShortBuffer pixelData, byte[] pixelBytes) {
139 ShortBuffer shortBuffer = ByteBuffer.wrap(pixelBytes).asShortBuffer();
140 shortBuffer.put(pixelData);
141 }
142
143 @Override
144 protected void setPixel(ShortBuffer pixelData, byte[] pixelBytes) {
145 pixelData.put(ByteBuffer.wrap(pixelBytes).asShortBuffer());
146 }
147 }
148
149 public GZip2Compressor(int primitiveSize) {
150 super(primitiveSize);
151 }
152
153 private int[] calculateOffsets(byte[] byteArray) {
154 int[] offset = new int[primitiveSize];
155 offset[0] = 0;
156 for (int primitivIndex = 1; primitivIndex < primitiveSize; primitivIndex++) {
157 offset[primitivIndex] = offset[primitivIndex - 1] + byteArray.length / primitiveSize;
158 }
159 return offset;
160 }
161
162 @Override
163 public boolean compress(T pixelData, ByteBuffer compressed) {
164 int pixelDataLimit = pixelData.limit();
165 byte[] pixelBytes = new byte[pixelDataLimit * primitiveSize];
166 getPixel(pixelData, pixelBytes);
167 pixelBytes = shuffle(pixelBytes);
168 try (GZIPOutputStream zip = createGZipOutputStream(pixelDataLimit, compressed)) {
169
170 zip.write(pixelBytes, 0, pixelBytes.length);
171 } catch (IOException e) {
172 throw new IllegalStateException("could not gzip data", e);
173 }
174 return true;
175 }
176
177 @Override
178 public void decompress(ByteBuffer compressed, T pixelData) {
179 int pixelDataLimit = pixelData.limit();
180 byte[] pixelBytes = new byte[pixelDataLimit * primitiveSize];
181 try (GZIPInputStream zip = createGZipInputStream(compressed)) {
182 int count = 0;
183 int offset = 0;
184 while (offset < pixelBytes.length && count >= 0) {
185 count = zip.read(pixelBytes, offset, pixelBytes.length - offset);
186 if (count >= 0) {
187 offset = offset + count;
188 }
189 }
190 } catch (IOException e) {
191 throw new IllegalStateException("could not gunzip data", e);
192 }
193 pixelBytes = unshuffle(pixelBytes);
194 setPixel(pixelData, pixelBytes);
195 }
196
197 public byte[] shuffle(byte[] byteArray) {
198 byte[] result = new byte[byteArray.length];
199 int resultIndex = 0;
200 int[] offset = calculateOffsets(byteArray);
201 for (int index = 0; index < byteArray.length; index += primitiveSize) {
202 for (int primitiveIndex = 0; primitiveIndex < primitiveSize; primitiveIndex++) {
203 result[resultIndex + offset[primitiveIndex]] = byteArray[index + primitiveIndex];
204 }
205 resultIndex++;
206 }
207 return result;
208 }
209
210 public byte[] unshuffle(byte[] byteArray) {
211 byte[] result = new byte[byteArray.length];
212 int resultIndex = 0;
213 int[] offset = calculateOffsets(byteArray);
214 for (int index = 0; index < byteArray.length; index += primitiveSize) {
215 for (int primitiveIndex = 0; primitiveIndex < primitiveSize; primitiveIndex++) {
216 result[index + primitiveIndex] = byteArray[resultIndex + offset[primitiveIndex]];
217 }
218 resultIndex++;
219 }
220 return result;
221 }
222 }