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; } }