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.
99 lines
2.7 KiB
99 lines
2.7 KiB
package com.jotuntech.sketcher.common;
|
|
|
|
import java.util.zip.Deflater;
|
|
|
|
public class PixelPacker {
|
|
private Deflater deflater;
|
|
private byte[] encodedPixels = null;
|
|
|
|
public PixelPacker() {
|
|
deflater = new Deflater(Deflater.BEST_COMPRESSION, true);
|
|
}
|
|
|
|
public int pack(int[] pixels, byte[] output) {
|
|
return pack(pixels, output, 0, output.length);
|
|
}
|
|
|
|
public int pack(int[] pixels, byte[] output, int ofs, int len) {
|
|
/* Create buffers, or enlarge them if they are too small */
|
|
if(encodedPixels == null || encodedPixels.length < pixels.length * 6) {
|
|
encodedPixels = new byte[pixels.length * 6];
|
|
}
|
|
|
|
int lastAlpha = 0, lastY = 0, lastCb = 256, lastCr = 256;
|
|
for(int pixelOffset = 0, YOffset = pixels.length, CbOffset = pixels.length * 2, CrOffset = pixels.length * 4; pixelOffset < pixels.length; pixelOffset++, YOffset++, CbOffset++, CrOffset++) {
|
|
int pixel = pixels[pixelOffset];
|
|
|
|
/* Extract alpha channel */
|
|
int alpha = (pixel >> 24) & 0xFF;
|
|
|
|
/* Differential transform */
|
|
int deltaAlpha = alpha - lastAlpha;
|
|
lastAlpha = alpha;
|
|
|
|
/* Convert negative deltas to equivalent positive deltas */
|
|
if(deltaAlpha < 0) {
|
|
deltaAlpha = 256 + deltaAlpha;
|
|
}
|
|
|
|
/* Luma and chroma deltas */
|
|
int deltaY, deltaCb, deltaCr;
|
|
|
|
/* Color deltas are zero if alpha is zero, for better compression */
|
|
if(alpha == 0) {
|
|
deltaY = 0;
|
|
deltaCb = 0;
|
|
deltaCr = 0;
|
|
} else {
|
|
/* Extract color channels */
|
|
int red = (pixel >> 16) & 0xFF;
|
|
int green = (pixel >> 8) & 0xFF;
|
|
int blue = pixel & 0xFF;
|
|
|
|
/* Forward color transform */
|
|
int Y = (red + (green << 1) + blue) >> 2;
|
|
int Cb = 256 + blue - green;
|
|
int Cr = 256 + red - green;
|
|
|
|
/* Differential transform */
|
|
deltaY = Y - lastY;
|
|
deltaCb = Cb - lastCb;
|
|
deltaCr = Cr - lastCr;
|
|
lastY = Y;
|
|
lastCb = Cb;
|
|
lastCr = Cr;
|
|
|
|
/* Convert negative deltas to equivalent positive deltas */
|
|
if(deltaY < 0) {
|
|
deltaY = 256 + deltaY;
|
|
}
|
|
|
|
if(deltaCb < 0) {
|
|
deltaCb = 512 + deltaCb;
|
|
}
|
|
|
|
if(deltaCr < 0) {
|
|
deltaCr = 512 + deltaCr;
|
|
}
|
|
}
|
|
|
|
/* Store image channels */
|
|
encodedPixels[pixelOffset] = (byte) deltaAlpha;
|
|
encodedPixels[YOffset] = (byte) deltaY;
|
|
encodedPixels[CbOffset++] = (byte) (deltaCb >>> 8);
|
|
encodedPixels[CbOffset] = (byte) deltaCb;
|
|
encodedPixels[CrOffset++] = (byte) (deltaCr >>> 8);
|
|
encodedPixels[CrOffset] = (byte) deltaCr;
|
|
}
|
|
|
|
/* Deflate encoded pixels */
|
|
deflater.reset();
|
|
deflater.setInput(encodedPixels, 0, pixels.length * 6);
|
|
deflater.finish();
|
|
int compressedLength = 0;
|
|
while(!deflater.finished() && compressedLength < len) {
|
|
compressedLength += deflater.deflate(output, ofs + compressedLength, len - compressedLength);
|
|
}
|
|
return compressedLength;
|
|
}
|
|
}
|
|
|