package com.vitco.export;
import com.vitco.core.data.Data;
import com.vitco.core.data.container.Voxel;
import com.vitco.layout.content.console.ConsoleInterface;
import com.vitco.util.components.progressbar.ProgressDialog;
import com.vitco.util.file.FileOut;
import com.vitco.util.graphic.GraphicTools;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
/**
* Exporter for *.pnx voxel format
*/
public class PnxExporter extends AbstractExporter {
// constructor
public PnxExporter(File exportTo, Data data, ProgressDialog dialog, ConsoleInterface console) throws IOException {
super(exportTo, data, dialog, console);
}
// write the file
@Override
protected boolean writeFile() throws IOException {
// for progress display
setActivity("Exporting to file...", false);
// write dimension information
int[] overallSize = getSize();
fileOut.writeIntRev(overallSize[0]);
fileOut.writeIntRev(overallSize[1]);
fileOut.writeIntRev(overallSize[2]);
Integer[] layers = data.getLayers();
// write amount of layers
fileOut.writeIntRev(layers.length);
// data cache
ByteArrayOutputStream baos = new ByteArrayOutputStream();
FileOut fileOutBuffer = new FileOut(baos);
// holds unique images
HashMap<String, BufferedImage> images = new HashMap<String, BufferedImage>();
ArrayList<String> imageOrder = new ArrayList<String>();
for (int layerId : layers) {
// write layer name
String layerName = data.getLayerName(layerId);
fileOutBuffer.writeIntRev(layerName.length());
fileOutBuffer.writeUTF8String(layerName);
// write visible flag
fileOutBuffer.writeByte((byte) (data.getLayerVisible(layerId)?1:0));
// write locked flag (not implemented yet)
fileOutBuffer.writeByte((byte) 1);
// get min and max of layer
int[] min = new int[] {Integer.MAX_VALUE, Integer.MAX_VALUE, Integer.MAX_VALUE};
int[] max = new int[] {Integer.MIN_VALUE, Integer.MIN_VALUE, Integer.MIN_VALUE};
int[] size = new int[] {0, 0, 0};
boolean hasVoxel = false;
for (Voxel voxel : data.getLayerVoxels(layerId)) {
min[0] = Math.min(voxel.x, min[0]);
min[1] = Math.min(voxel.y, min[1]);
min[2] = Math.min(voxel.z, min[2]);
max[0] = Math.max(voxel.x, max[0]);
max[1] = Math.max(voxel.y, max[1]);
max[2] = Math.max(voxel.z, max[2]);
hasVoxel = true;
}
if (hasVoxel) {
size = new int[]{max[0] - min[0] + 1, max[1] - min[1] + 1, max[2] - min[2] + 1};
}
// write size
fileOutBuffer.writeIntRev(size[0]);
fileOutBuffer.writeIntRev(size[1]);
fileOutBuffer.writeIntRev(size[2]);
// write minimum
fileOutBuffer.writeIntRev(min[0]);
fileOutBuffer.writeIntRev(min[1]);
fileOutBuffer.writeIntRev(min[2]);
// write image for layer
for (int x = max[0]; x > min[0] - 1; x--) {
BufferedImage img = new BufferedImage(size[1], size[2], BufferedImage.TYPE_INT_ARGB);
for (Voxel voxel : data.getVoxelsYZ(x, layerId)) {
Color color = voxel.getColor();
img.setRGB(voxel.y - min[1], voxel.z - min[2], color.getRGB());
}
// hash and store if necessary
String md5 = GraphicTools.getHash(img);
if (!images.containsKey(md5)) {
images.put(md5, img);
imageOrder.add(md5);
}
fileOutBuffer.writeIntRev(imageOrder.indexOf(md5));
}
}
// write images
int count = imageOrder.size();
int currentCount = 0;
fileOut.writeIntRev(count);
for (String md5 : imageOrder) {
setProgress((currentCount / (float) count) * 100);
fileOut.writeImageCompressed(images.get(md5));
currentCount++;
}
// write data cache
fileOut.writeBytes(baos.toByteArray());
// success
return true;
}
}