Search in sources :

Example 1 with BitOutputStream

use of com.bergerkiller.bukkit.common.io.BitOutputStream in project BKCommonLib by bergerhealer.

the class MCSDWebbingCodec method calculateCompressedSize.

public int calculateCompressedSize() {
    ByteArrayOutputStream bs = new ByteArrayOutputStream();
    try {
        BitOutputStream s = new BitOutputStream(CommonUtil.setCompressionLevel(new GZIPOutputStream(bs), Deflater.BEST_COMPRESSION));
        for (int i = 0; i < this.packets_count; i++) {
            s.writePacket(this.packets[i]);
        }
        s.close();
        return bs.size();
    } catch (IOException ex) {
        ex.printStackTrace();
    }
    return 0;
}
Also used : BitOutputStream(com.bergerkiller.bukkit.common.io.BitOutputStream) GZIPOutputStream(java.util.zip.GZIPOutputStream) ByteArrayOutputStream(java.io.ByteArrayOutputStream) IOException(java.io.IOException)

Example 2 with BitOutputStream

use of com.bergerkiller.bukkit.common.io.BitOutputStream in project BKCommonLib by bergerhealer.

the class MCSDBubbleFormat method writeTo.

public void writeTo(OutputStream stream) throws IOException {
    try (BitOutputStream bitStream = new BitOutputStream(StreamUtil.createDeflaterOutputStreamWithCompressionLevel(stream, Deflater.BEST_COMPRESSION))) {
        // Input colors will be used to correct errors in the color model
        // These are never written to and serve as a backup while writing
        this.input_colors = new MapColorSpaceData();
        this.input_colors.readFrom(this);
        // Load in all bubble boundary information
        Logging.LOGGER_MAPDISPLAY.info("Loading bubble boundaries...");
        for (int z = 0; z < 256; z++) {
            boolean[] strands = this.strands[z];
            final int index_end = ((z + 1) << 16);
            for (int index = (z << 16); index < index_end; index++) {
                int x = (index & 0xFF);
                int y = ((index >> 8) & 0xFF);
                byte color = get(index);
                strands[index & (strands.length - 1)] = (x < 255 && color != get(index + 1)) || (y < 255 && color != get(index + 256));
            }
        }
        // Find connected blobs of color (restore colors after all bubbles are found)
        Logging.LOGGER_MAPDISPLAY.info("Generating bubble spatial information...");
        for (int z = 0; z < 256; z++) {
            boolean[] strands = this.strands[z];
            int index_offset = (z << 16);
            for (int index = 0; index < (1 << 16); index++) {
                if (strands[index]) {
                    continue;
                }
                byte color = this.get(index_offset + index);
                if (color == 0) {
                    continue;
                }
                this.set(index_offset + index, (byte) 0);
                Bubble bubble = new Bubble();
                bubble.x = (index & 0xFF);
                bubble.y = ((index >> 8) & 0xFF);
                bubble.z_min = z;
                bubble.z_max = z;
                bubble.color = color;
                bubble.pixels.add(new IntVector2(bubble.x, bubble.y));
                spread(bubble);
                this.bubbles.add(bubble);
            }
        }
        this.readFrom(this.input_colors);
        // Merge the blobs with same colors sharing points
        Logging.LOGGER_MAPDISPLAY.info("Connecting bubbles in the z-axis...");
        for (int bubbleidx = 0; bubbleidx < this.bubbles.size(); bubbleidx++) {
            Bubble bubble = this.bubbles.get(bubbleidx);
            Iterator<Bubble> iter = this.bubbles.iterator();
            while (iter.hasNext()) {
                Bubble otherBubble = iter.next();
                // Mergable?
                if (bubble == otherBubble || bubble.color != otherBubble.color) {
                    continue;
                }
                // Sharing a Z-border?
                if (bubble.z_min != (otherBubble.z_max + 1) && bubble.z_max != (otherBubble.z_min - 1)) {
                    continue;
                }
                // Sharing any pixel at all?
                boolean sharesPixels = false;
                for (IntVector2 p : otherBubble.pixels) {
                    if (bubble.pixels.contains(p)) {
                        sharesPixels = true;
                        break;
                    }
                }
                if (!sharesPixels) {
                    continue;
                }
                // Remove all pixels of the other cell and update z-bounds to merge the two
                bubble.pixels.retainAll(otherBubble.pixels);
                if (otherBubble.z_min < bubble.z_min) {
                    bubble.z_min = otherBubble.z_min;
                }
                if (otherBubble.z_max > bubble.z_max) {
                    bubble.z_max = otherBubble.z_max;
                }
                iter.remove();
            }
        }
        // Calculate bubble x/y
        Logging.LOGGER_MAPDISPLAY.info("Calculating bubble positions...");
        for (Bubble bubble : this.bubbles) {
            // Adjust x/y to be in the middle of all pixels found
            int avg_x = 0;
            int avg_y = 0;
            for (IntVector2 pixel : bubble.pixels) {
                avg_x += pixel.x;
                avg_y += pixel.z;
            }
            avg_x /= bubble.pixels.size();
            avg_y /= bubble.pixels.size();
            IntVector2 closest = null;
            int minDistSq = Integer.MAX_VALUE;
            for (IntVector2 pixel : bubble.pixels) {
                int dx = (pixel.x - avg_x);
                int dy = (pixel.z - avg_y);
                int distSq = (dx * dx) + (dy * dy);
                if (distSq < minDistSq) {
                    minDistSq = distSq;
                    closest = pixel;
                }
            }
            bubble.x = closest.x;
            bubble.y = closest.z;
        }
        // Write out all color RGB values
        for (int i = 0; i < 256; i++) {
            Color color = this.getColor((byte) i);
            bitStream.write(color.getRed());
            bitStream.write(color.getGreen());
            bitStream.write(color.getBlue());
            bitStream.write(color.getAlpha());
        }
        // Write out all bubble information
        for (Bubble bubble : bubbles) {
            bitStream.write(bubble.color & 0xFF);
            bitStream.write(bubble.x);
            bitStream.write(bubble.y);
            bitStream.write(bubble.z_min);
            bitStream.write(bubble.z_max - bubble.z_min);
        }
        bitStream.write(0);
        // Initialize the colors based on the known cell colors
        Logging.LOGGER_MAPDISPLAY.info("Initializing color information for " + bubbles.size() + " bubbles...");
        this.initColors();
        // Write cell information
        Logging.LOGGER_MAPDISPLAY.info("Writing bubble boundary information...");
        IntStream.range(0, 256).mapToObj(z -> generateSlice(z)).parallel().forEachOrdered(codec -> {
            try {
                codec.writePackets(bitStream);
            } catch (IOException ex) {
                // Oh well.
                ex.printStackTrace();
            }
        });
        // Write missing color information using bit encoding
        Logging.LOGGER_MAPDISPLAY.info("Correcting missing color information...");
        List<BitPacket> colorCodes = new ArrayList<BitPacket>();
        for (int i = 0; i < (1 << 24); i++) {
            if (this.get(i) == 0) {
                int x = (i & 0xFF);
                int y = (i >> 8) & 0xFF;
                BitPacket code = new BitPacket();
                byte color = this.input_colors.get(i);
                if (x > 0 && this.get(i - 1) == color) {
                    code.write(0, 1);
                } else {
                    code.write(1, 1);
                    if (y > 0 && this.get(i - 256) == color) {
                        code.write(0, 2);
                    } else if (x < 255 && this.get(i + 1) == color) {
                        code.write(1, 2);
                    } else if (y < 255 && this.get(i + 256) == color) {
                        code.write(2, 2);
                    } else {
                        code.write(3, 2);
                        code.write(color & 0xFF, 8);
                    }
                }
                colorCodes.add(code);
                this.set(i, color);
            }
        }
        for (BitPacket code : colorCodes) {
            bitStream.writeBits(code.data, code.bits);
        }
    }
}
Also used : BitOutputStream(com.bergerkiller.bukkit.common.io.BitOutputStream) Color(java.awt.Color) ArrayList(java.util.ArrayList) BitPacket(com.bergerkiller.bukkit.common.io.BitPacket) IOException(java.io.IOException) IntVector2(com.bergerkiller.bukkit.common.bases.IntVector2)

Aggregations

BitOutputStream (com.bergerkiller.bukkit.common.io.BitOutputStream)2 IOException (java.io.IOException)2 IntVector2 (com.bergerkiller.bukkit.common.bases.IntVector2)1 BitPacket (com.bergerkiller.bukkit.common.io.BitPacket)1 Color (java.awt.Color)1 ByteArrayOutputStream (java.io.ByteArrayOutputStream)1 ArrayList (java.util.ArrayList)1 GZIPOutputStream (java.util.zip.GZIPOutputStream)1