Newer
Older
import cli.ParsedCliOptions;
import compression.data.ImageU16;
import compression.fileformat.QCMPFileHeader;
import compression.io.OutBitStream;
import compression.io.RawDataIO;
import compression.quantization.scalar.LloydMaxU16ScalarQuantization;
import compression.quantization.scalar.ScalarQuantizer;
import java.io.DataOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class ImageCompressor extends CompressorDecompressorBase {
private final int codebookSize;
public ImageCompressor(ParsedCliOptions options) {
super(options);
codebookSize = (int) Math.pow(2, options.getBitsPerPixel());
public void compress() throws Exception {
FileOutputStream fos = new FileOutputStream(options.getOutputFile(), false);
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
DataOutputStream dataOutputStream = new DataOutputStream(fos);
// Create and write header to output stream.
final QCMPFileHeader header = createHeader();
header.writeHeader(dataOutputStream);
boolean compressionResult = true;
switch (options.getQuantizationType()) {
case Scalar:
compressUsingScalarQuantization(dataOutputStream);
break;
case Vector1D:
break;
case Vector2D:
break;
case Vector3D:
case Invalid:
throw new Exception("Not supported quantization type");
}
dataOutputStream.flush();
dataOutputStream.close();
fos.flush();
fos.close();
}
private QCMPFileHeader createHeader() {
QCMPFileHeader header = new QCMPFileHeader();
header.setQuantizationType(options.getQuantizationType());
header.setBitsPerPixel((byte) options.getBitsPerPixel());
header.setCodebookPerPlane(!options.hasReferencePlaneIndex());
header.setImageDimension(options.getImageDimension());
header.setVectorDimension(options.getVectorDimension());
return header;
}
private void writeCodebookToOutputStream(final ScalarQuantizer quantizer,
DataOutputStream outputStream) throws IOException {
final int[] centroids = quantizer.getCentroids();
for (final int quantizationValue : centroids) {
// TODO(Moravec): Check this!
outputStream.writeShort(quantizationValue);
//outputStream.writeShort(TypeConverter.intToShort(quantizationValue));
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
private ScalarQuantizer getScalarQuantizerFromPlane(final ImageU16 plane) {
LloydMaxU16ScalarQuantization lloydMax = new LloydMaxU16ScalarQuantization(plane.getData(), codebookSize);
lloydMax.train(options.isVerbose());
return new ScalarQuantizer(U16.Min, U16.Max, lloydMax.getCentroids());
}
private void compressUsingScalarQuantization(DataOutputStream outputStream) throws Exception {
ScalarQuantizer quantizer = null;
if (options.hasReferencePlaneIndex()) {
final ImageU16 referencePlane = RawDataIO.loadImageU16(options.getInputFile(),
options.getImageDimension(),
options.getReferencePlaneIndex());
quantizer = getScalarQuantizerFromPlane(referencePlane);
writeCodebookToOutputStream(quantizer, outputStream);
}
final int[] planeIndices = getPlaneIndicesForCompression();
for (final int planeIndex : planeIndices) {
final ImageU16 plane = RawDataIO.loadImageU16(options.getInputFile(),
options.getImageDimension(),
planeIndex);
if (!options.hasReferencePlaneIndex()) {
quantizer = getScalarQuantizerFromPlane(plane);
writeCodebookToOutputStream(quantizer, outputStream);
}
assert (quantizer != null);
final int[] indices = quantizer.quantizeIntoIndices(plane.getData());
OutBitStream outBitStream = new OutBitStream(outputStream, options.getBitsPerPixel(), 2048);
outBitStream.write(indices);
outBitStream.flush();
}