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