You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
77 lines
2.4 KiB
77 lines
2.4 KiB
package com.jotuntech.sketcher.common;
|
|
|
|
import java.util.zip.DataFormatException;
|
|
import java.util.zip.Inflater;
|
|
|
|
|
|
public class PixelUnpacker {
|
|
Inflater inflater;
|
|
private byte[] encodedPixels;
|
|
|
|
public PixelUnpacker() {
|
|
inflater = new Inflater(true);
|
|
}
|
|
|
|
public void unpack(byte[] input, int ofs, int len, int[] output) {
|
|
if(encodedPixels == null || encodedPixels.length < input.length * 6) {
|
|
encodedPixels = new byte[output.length * 6];
|
|
}
|
|
|
|
inflater.reset();
|
|
inflater.setInput(input, ofs, len);
|
|
//Log.debug("Inflating from offset " + ofs + " length " + len);
|
|
|
|
int encodedLength = 0;
|
|
try {
|
|
while(!inflater.finished() && encodedLength < encodedPixels.length) {
|
|
encodedLength += inflater.inflate(encodedPixels, encodedLength, encodedPixels.length - encodedLength);
|
|
}
|
|
} catch(DataFormatException e) {
|
|
throw new RuntimeException(e);
|
|
}
|
|
|
|
if(encodedLength < output.length * 6) {
|
|
Log.error("needsInput = " + inflater.needsInput());
|
|
throw new RuntimeException("Encoded length " + encodedLength + " is shorter than output length " + output.length * 6 + ".");
|
|
}
|
|
|
|
int lastAlpha = 0, lastY = 0, lastCb = 256, lastCr = 256;
|
|
for(int outputOffset = 0, YOffset = output.length, CbOffset = output.length * 2, CrOffset = output.length * 4; outputOffset < output.length; outputOffset++, YOffset++, CbOffset++, CrOffset++) {
|
|
/* Extract alpha channel delta */
|
|
int deltaAlpha = encodedPixels[outputOffset] & 0xFF;
|
|
|
|
/* Differential transform with overflow wrapping */
|
|
int alpha = (lastAlpha + deltaAlpha) & 0xFF;
|
|
lastAlpha = alpha;
|
|
|
|
/* Color channel deltas are always zero when alpha is zero */
|
|
if(alpha == 0) {
|
|
output[outputOffset] = 0;
|
|
++CbOffset;
|
|
++CrOffset;
|
|
} else {
|
|
/* Extract color channel deltas */
|
|
int deltaY = encodedPixels[YOffset] & 0xFF;
|
|
int deltaCb = ((encodedPixels[CbOffset++] & 0xFF) << 8) | (encodedPixels[CbOffset] & 0xFF);
|
|
int deltaCr = ((encodedPixels[CrOffset++] & 0xFF) << 8) | (encodedPixels[CrOffset] & 0xFF);
|
|
|
|
/* Differental transform with overflow wrapping */
|
|
int Y = (lastY + deltaY) & 0xFF;
|
|
int Cb = (lastCb + deltaCb) & 0x1FF;
|
|
int Cr = (lastCr + deltaCr) & 0x1FF;
|
|
lastY = Y;
|
|
lastCb = Cb;
|
|
lastCr = Cr;
|
|
|
|
/* Inverse color transform */
|
|
Cb -= 256;
|
|
Cr -= 256;
|
|
int green = Y - ((Cb + Cr) >> 2);
|
|
int red = Cr + green;
|
|
int blue = Cb + green;
|
|
|
|
output[outputOffset] = Pixels.pack(alpha, red, green, blue);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|