Search in sources :

Example 1 with BitPacket

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

the class MCSDWebbingCodec method writePackets.

public void writePackets(BitOutputStream stream) throws IOException {
    for (int i = 0; i < this.packets_count; i++) {
        stream.writePacket(this.packets[i]);
    }
    // Closing BitPacket tells the reader this is end of this slice
    BitPacket closingCode = new BitPacket();
    closingCode.write(0b11, 2);
    closingCode.write(0b0, 1);
    closingCode.write(0b1, 1);
    stream.writePacket(closingCode);
}
Also used : BitPacket(com.bergerkiller.bukkit.common.io.BitPacket)

Example 2 with BitPacket

use of com.bergerkiller.bukkit.common.io.BitPacket 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)

Example 3 with BitPacket

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

the class MCSDWebbingCodec method reset.

public void reset(MCSDWebbingCodec codec) {
    this.written_cells = codec.written_cells;
    this.last_x = codec.last_x;
    this.last_y = codec.last_y;
    this.last_dx = codec.last_dx;
    this.last_dy = codec.last_dy;
    System.arraycopy(codec.strands, 0, this.strands, 0, strands.length);
    this.packets_count = 0;
    for (BitPacket packet2 : codec.packets) {
        BitPacket packet = this.addPacket();
        packet.bits = packet2.bits;
        packet.data = packet2.data;
    }
    this.packets_count = codec.packets_count;
}
Also used : BitPacket(com.bergerkiller.bukkit.common.io.BitPacket)

Example 4 with BitPacket

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

the class MCSDWebbingCodec method addPacket.

private BitPacket addPacket() {
    if (this.packets_count >= packets.length) {
        BitPacket[] new_packets = new BitPacket[packets.length * 2];
        System.arraycopy(this.packets, 0, new_packets, 0, this.packets.length);
        for (int i = this.packets.length; i < new_packets.length; i++) {
            new_packets[i] = new BitPacket();
        }
        this.packets = new_packets;
    }
    BitPacket result = this.packets[this.packets_count++];
    result.bits = 0;
    result.data = 0;
    return result;
}
Also used : BitPacket(com.bergerkiller.bukkit.common.io.BitPacket)

Example 5 with BitPacket

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

the class MCSDWebbingCodec method writeNext.

public boolean writeNext(int x, int y) {
    if (x < 0 || y < 0 || x >= 256 || y >= 256) {
        return false;
    }
    int index = x | (y << 8);
    if (!strands[index]) {
        return false;
    }
    strands[index] = false;
    written_cells++;
    int dx = x - last_x;
    int dy = y - last_y;
    last_x = x;
    last_y = y;
    if (dx == 0 && dy == 0) {
        return false;
    }
    if (dx > 1 || dx < -1 || dy > 1 || dy < -1) {
        // Reset coordinates when difference is too big
        BitPacket code = addPacket();
        code.write(0b11, 2);
        code.write(0b0, 1);
        code.write(0b0, 1);
        code.write(x, 8);
        code.write(y, 8);
    } else {
        // Update directions when changed
        if ((dx > 0 && last_dx < 0) || (dx < 0 && last_dx > 0)) {
            BitPacket code = addPacket();
            code.write(0b11, 2);
            code.write(0b1, 1);
            code.write(dx > 0 ? 0b01 : 0b00, 2);
            last_dx = dx;
        }
        if ((dy > 0 && last_dy < 0) || (dy < 0 && last_dy > 0)) {
            BitPacket code = addPacket();
            code.write(0b11, 2);
            code.write(0b1, 1);
            code.write(dy > 0 ? 0b11 : 0b10, 2);
            last_dy = dy;
        }
        // Push pixels
        BitPacket code = addPacket();
        if (dy == 0) {
            // DX
            code.write(0b00, 2);
        } else if (dx == 0) {
            // DY
            code.write(0b01, 2);
        } else {
            // DX AND DY
            code.write(0b10, 2);
        }
    }
    return true;
}
Also used : BitPacket(com.bergerkiller.bukkit.common.io.BitPacket)

Aggregations

BitPacket (com.bergerkiller.bukkit.common.io.BitPacket)5 IntVector2 (com.bergerkiller.bukkit.common.bases.IntVector2)1 BitOutputStream (com.bergerkiller.bukkit.common.io.BitOutputStream)1 Color (java.awt.Color)1 IOException (java.io.IOException)1 ArrayList (java.util.ArrayList)1