List of usage examples for com.badlogic.gdx.utils ByteArray ByteArray
public ByteArray(byte[] array)
From source file:com.crashinvaders.texturepackergui.utils.PNG8.java
License:Open Source License
/** * Attempts to write the given Pixmap exactly as a PNG-8 image to output; this attempt will only succeed if there * are no more than 256 colors in the Pixmap (treating all partially transparent colors as fully transparent). * If the attempt fails, this falls back to calling {@link #write(OutputStream, Pixmap, boolean, boolean)}, which * can dither the image to use no more than 255 colors (plus fully transparent) based on ditherFallback and will * always analyze the Pixmap to get an accurate-enough palette, using the given threshold for analysis (which is * typically between 1 and 1000, and most often near 200-400). All other write() methods in this class will * reduce the color depth somewhat, but as long as the color count stays at 256 or less, this will keep the * non-alpha components of colors exactly. * @param output an OutputStream that will not be closed * @param pixmap a Pixmap to write to the given output stream * @param ditherFallback if the Pixmap contains too many colors, this determines whether it will dither the output * @param threshold the analysis threshold to use if there are too many colors (min 0, practical max is over 100000) * @throws IOException if OutputStream things fail for any reason *//*w w w . j a v a 2s. c om*/ public void writePrecisely(OutputStream output, Pixmap pixmap, boolean ditherFallback, int threshold) throws IOException { IntIntMap colorToIndex = new IntIntMap(256); colorToIndex.put(0, 0); int color; int hasTransparent = 0; final int w = pixmap.getWidth(), h = pixmap.getHeight(); for (int y = 0; y < h; y++) { int py = flipY ? (h - y - 1) : y; for (int px = 0; px < w; px++) { color = pixmap.getPixel(px, py); if ((color & 0xFE) != 0xFE) { if (hasTransparent == 0 && colorToIndex.size >= 256) { write(output, pixmap, true, ditherFallback, threshold); return; } hasTransparent = 1; } else if (!colorToIndex.containsKey(color)) { colorToIndex.put(color, colorToIndex.size & 255); if (colorToIndex.size == 257 && hasTransparent == 0) { colorToIndex.remove(0, 0); } if (colorToIndex.size > 256) { write(output, pixmap, true, ditherFallback, threshold); return; } } } } int[] paletteArray = new int[colorToIndex.size]; for (IntIntMap.Entry ent : colorToIndex) { paletteArray[ent.value] = ent.key; } DeflaterOutputStream deflaterOutput = new DeflaterOutputStream(buffer, deflater); DataOutputStream dataOutput = new DataOutputStream(output); dataOutput.write(SIGNATURE); buffer.writeInt(IHDR); buffer.writeInt(pixmap.getWidth()); buffer.writeInt(pixmap.getHeight()); buffer.writeByte(8); // 8 bits per component. buffer.writeByte(COLOR_INDEXED); buffer.writeByte(COMPRESSION_DEFLATE); buffer.writeByte(FILTER_NONE); buffer.writeByte(INTERLACE_NONE); buffer.endChunk(dataOutput); buffer.writeInt(PLTE); for (int i = 0; i < paletteArray.length; i++) { int p = paletteArray[i]; buffer.write(p >>> 24); buffer.write(p >>> 16); buffer.write(p >>> 8); } buffer.endChunk(dataOutput); if (hasTransparent == 1) { buffer.writeInt(TRNS); buffer.write(0); buffer.endChunk(dataOutput); } buffer.writeInt(IDAT); deflater.reset(); int lineLen = pixmap.getWidth(); byte[] lineOut, curLine, prevLine; if (lineOutBytes == null) { lineOut = (lineOutBytes = new ByteArray(lineLen)).items; curLine = (curLineBytes = new ByteArray(lineLen)).items; prevLine = (prevLineBytes = new ByteArray(lineLen)).items; } else { lineOut = lineOutBytes.ensureCapacity(lineLen); curLine = curLineBytes.ensureCapacity(lineLen); prevLine = prevLineBytes.ensureCapacity(lineLen); for (int i = 0, n = lastLineLen; i < n; i++) { prevLine[i] = 0; } } lastLineLen = lineLen; for (int y = 0; y < h; y++) { int py = flipY ? (h - y - 1) : y; for (int px = 0; px < w; px++) { color = pixmap.getPixel(px, py); curLine[px] = (byte) colorToIndex.get(color, 0); } lineOut[0] = (byte) (curLine[0] - prevLine[0]); //Paeth for (int x = 1; x < lineLen; x++) { int a = curLine[x - 1] & 0xff; int b = prevLine[x] & 0xff; int c = prevLine[x - 1] & 0xff; int p = a + b - c; int pa = p - a; if (pa < 0) pa = -pa; int pb = p - b; if (pb < 0) pb = -pb; int pc = p - c; if (pc < 0) pc = -pc; if (pa <= pb && pa <= pc) c = a; else if (pb <= pc) c = b; lineOut[x] = (byte) (curLine[x] - c); } deflaterOutput.write(PAETH); deflaterOutput.write(lineOut, 0, lineLen); byte[] temp = curLine; curLine = prevLine; prevLine = temp; } deflaterOutput.finish(); buffer.endChunk(dataOutput); buffer.writeInt(IEND); buffer.endChunk(dataOutput); output.flush(); }
From source file:com.crashinvaders.texturepackergui.utils.PNG8.java
License:Open Source License
private void writeSolid(OutputStream output, Pixmap pixmap) throws IOException { final int[] paletteArray = palette.paletteArray; final byte[] paletteMapping = palette.paletteMapping; DeflaterOutputStream deflaterOutput = new DeflaterOutputStream(buffer, deflater); DataOutputStream dataOutput = new DataOutputStream(output); dataOutput.write(SIGNATURE);//w ww .ja va2s . c om buffer.writeInt(IHDR); buffer.writeInt(pixmap.getWidth()); buffer.writeInt(pixmap.getHeight()); buffer.writeByte(8); // 8 bits per component. buffer.writeByte(COLOR_INDEXED); buffer.writeByte(COMPRESSION_DEFLATE); buffer.writeByte(FILTER_NONE); buffer.writeByte(INTERLACE_NONE); buffer.endChunk(dataOutput); buffer.writeInt(PLTE); for (int i = 0; i < paletteArray.length; i++) { int p = paletteArray[i]; buffer.write(p >>> 24); buffer.write(p >>> 16); buffer.write(p >>> 8); } buffer.endChunk(dataOutput); boolean hasTransparent = false; if (paletteArray[0] == 0) { hasTransparent = true; buffer.writeInt(TRNS); buffer.write(0); buffer.endChunk(dataOutput); } buffer.writeInt(IDAT); deflater.reset(); int lineLen = pixmap.getWidth(); byte[] lineOut, curLine, prevLine; if (lineOutBytes == null) { lineOut = (lineOutBytes = new ByteArray(lineLen)).items; curLine = (curLineBytes = new ByteArray(lineLen)).items; prevLine = (prevLineBytes = new ByteArray(lineLen)).items; } else { lineOut = lineOutBytes.ensureCapacity(lineLen); curLine = curLineBytes.ensureCapacity(lineLen); prevLine = prevLineBytes.ensureCapacity(lineLen); for (int i = 0, n = lastLineLen; i < n; i++) { prevLine[i] = 0; } } lastLineLen = lineLen; int color; final int w = pixmap.getWidth(), h = pixmap.getHeight(); for (int y = 0; y < h; y++) { int py = flipY ? (h - y - 1) : y; for (int px = 0; px < w; px++) { color = pixmap.getPixel(px, py); if ((color & 0x80) == 0 && hasTransparent) curLine[px] = 0; else { int rr = ((color >>> 24)); int gg = ((color >>> 16) & 0xFF); int bb = ((color >>> 8) & 0xFF); curLine[px] = paletteMapping[((rr << 7) & 0x7C00) | ((gg << 2) & 0x3E0) | ((bb >>> 3))]; } } lineOut[0] = (byte) (curLine[0] - prevLine[0]); //Paeth for (int x = 1; x < lineLen; x++) { int a = curLine[x - 1] & 0xff; int b = prevLine[x] & 0xff; int c = prevLine[x - 1] & 0xff; int p = a + b - c; int pa = p - a; if (pa < 0) pa = -pa; int pb = p - b; if (pb < 0) pb = -pb; int pc = p - c; if (pc < 0) pc = -pc; if (pa <= pb && pa <= pc) c = a; else if (pb <= pc) c = b; lineOut[x] = (byte) (curLine[x] - c); } deflaterOutput.write(PAETH); deflaterOutput.write(lineOut, 0, lineLen); byte[] temp = curLine; curLine = prevLine; prevLine = temp; } deflaterOutput.finish(); buffer.endChunk(dataOutput); buffer.writeInt(IEND); buffer.endChunk(dataOutput); output.flush(); }
From source file:com.crashinvaders.texturepackergui.utils.PNG8.java
License:Open Source License
private void writeDithered(OutputStream output, Pixmap pixmap) throws IOException { DeflaterOutputStream deflaterOutput = new DeflaterOutputStream(buffer, deflater); final int[] paletteArray = palette.paletteArray; final byte[] paletteMapping = palette.paletteMapping; DataOutputStream dataOutput = new DataOutputStream(output); dataOutput.write(SIGNATURE);/* w ww . ja v a 2s .com*/ buffer.writeInt(IHDR); buffer.writeInt(pixmap.getWidth()); buffer.writeInt(pixmap.getHeight()); buffer.writeByte(8); // 8 bits per component. buffer.writeByte(COLOR_INDEXED); buffer.writeByte(COMPRESSION_DEFLATE); buffer.writeByte(FILTER_NONE); buffer.writeByte(INTERLACE_NONE); buffer.endChunk(dataOutput); buffer.writeInt(PLTE); for (int i = 0; i < paletteArray.length; i++) { int p = paletteArray[i]; buffer.write(p >>> 24); buffer.write(p >>> 16); buffer.write(p >>> 8); } buffer.endChunk(dataOutput); boolean hasTransparent = false; if (paletteArray[0] == 0) { hasTransparent = true; buffer.writeInt(TRNS); buffer.write(0); buffer.endChunk(dataOutput); } buffer.writeInt(IDAT); deflater.reset(); final int w = pixmap.getWidth(), h = pixmap.getHeight(); byte[] lineOut, curLine, prevLine; byte[] curErrorRed, nextErrorRed, curErrorGreen, nextErrorGreen, curErrorBlue, nextErrorBlue; if (lineOutBytes == null) { lineOut = (lineOutBytes = new ByteArray(w)).items; curLine = (curLineBytes = new ByteArray(w)).items; prevLine = (prevLineBytes = new ByteArray(w)).items; } else { lineOut = lineOutBytes.ensureCapacity(w); curLine = curLineBytes.ensureCapacity(w); prevLine = prevLineBytes.ensureCapacity(w); for (int i = 0, n = lastLineLen; i < n; i++) { prevLine[i] = 0; } } if (palette.curErrorRedBytes == null) { curErrorRed = (palette.curErrorRedBytes = new ByteArray(w)).items; nextErrorRed = (palette.nextErrorRedBytes = new ByteArray(w)).items; curErrorGreen = (palette.curErrorGreenBytes = new ByteArray(w)).items; nextErrorGreen = (palette.nextErrorGreenBytes = new ByteArray(w)).items; curErrorBlue = (palette.curErrorBlueBytes = new ByteArray(w)).items; nextErrorBlue = (palette.nextErrorBlueBytes = new ByteArray(w)).items; } else { curErrorRed = palette.curErrorRedBytes.ensureCapacity(w); nextErrorRed = palette.nextErrorRedBytes.ensureCapacity(w); curErrorGreen = palette.curErrorGreenBytes.ensureCapacity(w); nextErrorGreen = palette.nextErrorGreenBytes.ensureCapacity(w); curErrorBlue = palette.curErrorBlueBytes.ensureCapacity(w); nextErrorBlue = palette.nextErrorBlueBytes.ensureCapacity(w); for (int i = 0; i < w; i++) { nextErrorRed[i] = 0; nextErrorGreen[i] = 0; nextErrorBlue[i] = 0; } } lastLineLen = w; int color, used, rdiff, gdiff, bdiff, state = 0xFEEDBEEF; byte er, eg, eb, paletteIndex; float xi1, xi2, w1 = palette.ditherStrength * 0.125f, w3 = w1 * 3f, w5 = w1 * 5f, w7 = w1 * 7f; for (int y = 0; y < h; y++) { int py = flipY ? (h - y - 1) : y; int ny = flipY ? (h - y - 2) : y + 1; for (int i = 0; i < w; i++) { curErrorRed[i] = nextErrorRed[i]; curErrorGreen[i] = nextErrorGreen[i]; curErrorBlue[i] = nextErrorBlue[i]; nextErrorRed[i] = 0; nextErrorGreen[i] = 0; nextErrorBlue[i] = 0; } for (int px = 0; px < w; px++) { color = pixmap.getPixel(px, py) & 0xF8F8F880; if ((color & 0x80) == 0 && hasTransparent) curLine[px] = 0; else { er = curErrorRed[px]; eg = curErrorGreen[px]; eb = curErrorBlue[px]; color |= (color >>> 5 & 0x07070700) | 0xFE; int rr = MathUtils.clamp(((color >>> 24)) + (er), 0, 0xFF); int gg = MathUtils.clamp(((color >>> 16) & 0xFF) + (eg), 0, 0xFF); int bb = MathUtils.clamp(((color >>> 8) & 0xFF) + (eb), 0, 0xFF); curLine[px] = paletteIndex = paletteMapping[((rr << 7) & 0x7C00) | ((gg << 2) & 0x3E0) | ((bb >>> 3))]; used = paletteArray[paletteIndex & 0xFF]; rdiff = (color >>> 24) - (used >>> 24); gdiff = (color >>> 16 & 255) - (used >>> 16 & 255); bdiff = (color >>> 8 & 255) - (used >>> 8 & 255); state += (color + 0x41C64E6D) ^ color >>> 7; state = (state << 21 | state >>> 11); xi1 = randomXi(state); state = (state << 15 | state >>> 17) ^ 0x9E3779B9; xi2 = randomXi(state); if (px < w - 1) { curErrorRed[px + 1] += rdiff * w7 * (1f + xi1); curErrorGreen[px + 1] += gdiff * w7 * (1f + xi1); curErrorBlue[px + 1] += bdiff * w7 * (1f + xi1); } if (ny < h) { if (px > 0) { nextErrorRed[px - 1] += rdiff * w3 * (1f + xi2); nextErrorGreen[px - 1] += gdiff * w3 * (1f + xi2); nextErrorBlue[px - 1] += bdiff * w3 * (1f + xi2); } if (px < w - 1) { nextErrorRed[px + 1] += rdiff * w1 * (1f - xi2); nextErrorGreen[px + 1] += gdiff * w1 * (1f - xi2); nextErrorBlue[px + 1] += bdiff * w1 * (1f - xi2); } nextErrorRed[px] += rdiff * w5 * (1f - xi1); nextErrorGreen[px] += gdiff * w5 * (1f - xi1); nextErrorBlue[px] += bdiff * w5 * (1f - xi1); } } } lineOut[0] = (byte) (curLine[0] - prevLine[0]); //Paeth for (int x = 1; x < w; x++) { int a = curLine[x - 1] & 0xff; int b = prevLine[x] & 0xff; int c = prevLine[x - 1] & 0xff; int p = a + b - c; int pa = p - a; if (pa < 0) pa = -pa; int pb = p - b; if (pb < 0) pb = -pb; int pc = p - c; if (pc < 0) pc = -pc; if (pa <= pb && pa <= pc) c = a; else if (pb <= pc) c = b; lineOut[x] = (byte) (curLine[x] - c); } deflaterOutput.write(PAETH); deflaterOutput.write(lineOut, 0, w); byte[] temp = curLine; curLine = prevLine; prevLine = temp; } deflaterOutput.finish(); buffer.endChunk(dataOutput); buffer.writeInt(IEND); buffer.endChunk(dataOutput); output.flush(); }