Skip to content

Commit cbce77f

Browse files
authored
Merge pull request #289 from simlu/develop
New Sliced Exporter
2 parents 50866d1 + faa8dfa commit cbce77f

File tree

2 files changed

+154
-1
lines changed

2 files changed

+154
-1
lines changed
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
package com.vitco.app.export;
2+
3+
import com.vitco.app.core.data.Data;
4+
import com.vitco.app.core.data.container.Voxel;
5+
import com.vitco.app.layout.content.console.ConsoleInterface;
6+
import com.vitco.app.util.components.progressbar.ProgressDialog;
7+
8+
import javax.imageio.ImageIO;
9+
import java.awt.image.BufferedImage;
10+
import java.io.File;
11+
import java.io.IOException;
12+
13+
/**
14+
* Export cross-section slices of the voxel into
15+
* series of bitmap files.
16+
*/
17+
public class SlicesExporter extends AbstractExporter {
18+
19+
public SlicesExporter(File exportTo, Data data, ProgressDialog dialog, ConsoleInterface console) throws IOException {
20+
super(exportTo, data, dialog, console);
21+
}
22+
23+
private int ax1 = -1;
24+
private int ax2 = -1;
25+
private int ax3 = -1;
26+
public void setSliceDirection(String sliceAxis) {
27+
ax1 = sliceAxis.charAt(0) - 120; // x = 0, y = 1, z = 2
28+
ax2 = sliceAxis.equals("x") ? 2 : 0;
29+
ax3 = sliceAxis.equals("y") ? 2 : 1;
30+
}
31+
32+
private String exportFormat = "png";
33+
public void setExportFormat(String format) {
34+
this.exportFormat = format;
35+
}
36+
37+
private boolean invertOrder = false;
38+
public void setInvertOrder(boolean invert) {
39+
this.invertOrder = invert;
40+
}
41+
42+
// allow explicit access since multiple files are generated
43+
public boolean generateImages() throws IOException {
44+
int[] size = getSize();
45+
int nSlices = size[ax1]; // number of slices
46+
int width = size[ax2]; // width of slice bitmaps
47+
int height = size[ax3]; // height of slice bitmaps
48+
49+
// create images
50+
BufferedImage[] slices = new BufferedImage[nSlices];
51+
for (int idx = 0; idx < nSlices; idx++) {
52+
slices[idx] = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
53+
}
54+
55+
// paint images
56+
int[] min = getMin();
57+
for (Voxel voxel : this.data.getVisibleLayerVoxel()) {
58+
int[] pos = voxel.getPosAsInt();
59+
slices[pos[ax1] - min[ax1]].setRGB(pos[ax2] - min[ax2], pos[ax3] - min[ax3], voxel.getColor().getRGB());
60+
}
61+
62+
// save images
63+
for (int idx = 0; idx < nSlices; idx++) {
64+
String fileName = String.format(
65+
"%s_%d.%s",
66+
exportTo.getAbsolutePath(),
67+
invertOrder ? slices.length - idx : idx + 1,
68+
exportFormat
69+
);
70+
System.out.println("Creating file: " + fileName);
71+
ImageIO.write(slices[idx], exportFormat, new File(fileName));
72+
}
73+
74+
return true; // success
75+
}
76+
77+
@Override
78+
protected boolean writeFile() {
79+
throw new UnsupportedOperationException("Not implemented yet");
80+
}
81+
}

src/main/java/com/vitco/app/layout/content/menu/MainMenuLogic.java

Lines changed: 73 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -631,9 +631,38 @@ protected Object doInBackground() throws Exception {
631631

632632
// ---------------
633633

634+
// add bitmap slices exporter
635+
FieldSet slicesExporter = new FieldSet("slices_format", "Sliced model (png/gif)");
636+
// add information for the exporter
637+
LabelModule slicesInfo = new LabelModule("Info: Generates series of bitmap images. Each image corresponds to "
638+
+ "cross-section of visible voxels at each coordinate of selected axis.\nImportant: Can generate a large "
639+
+ "number of files!");
640+
slicesExporter.addComponent(slicesInfo);
641+
slicesExporter.addComponent(new SeparatorModule("Slice Along"));
642+
slicesExporter.addComponent(new SeparatorModule("Slice Along"));
643+
ComboBoxModule sliceAxis = new ComboBoxModule("axis", new String[][]{
644+
new String[]{"x", "x-axis"},
645+
new String[]{"y", "y-axis"},
646+
new String[]{"z", "z-axis"}
647+
}, 0);
648+
slicesExporter.addComponent(sliceAxis);
649+
650+
slicesExporter.addComponent(new SeparatorModule("Output Format"));
651+
ComboBoxModule formatSelect = new ComboBoxModule("export_format", new String[][]{
652+
new String[]{"png", "*.png"},
653+
new String[]{"gif", "*.gif"},
654+
}, 0);
655+
slicesExporter.addComponent(formatSelect);
656+
slicesExporter.addComponent(new SeparatorModule("Misc"));
657+
slicesExporter.addComponent(new CheckBoxModule("invert", "Invert direction", false));
658+
LabelModule invertInfo = new LabelModule("This option effectively inverts order of the numbers in file names.");
659+
slicesExporter.addComponent(invertInfo);
660+
661+
// ---------------
662+
634663
// add all formats
635664
dialog.addComboBox("export_type", new FieldSet[] {
636-
collada, magicaVoxelExporter, voxVoxLapExporter, kv6Exporter, pnxExporter, qbExporter, imageRenderer
665+
collada, magicaVoxelExporter, voxVoxLapExporter, kv6Exporter, pnxExporter, qbExporter, slicesExporter, imageRenderer
637666
}, 0);
638667

639668
// ---------------
@@ -1112,6 +1141,49 @@ protected Object doInBackground() throws Exception {
11121141

11131142
// ===========
11141143
}
1144+
else if (dialog.is("export_type=slices_format")) {
1145+
1146+
// ===========
1147+
// -- handle sliced file format
1148+
1149+
// create progress dialog
1150+
final ProgressDialog progressDialog = new ProgressDialog(frame);
1151+
1152+
// do the exporting
1153+
progressDialog.start(new ProgressWorker() {
1154+
@Override
1155+
protected Object doInBackground() {
1156+
1157+
final File exportTo = new File(baseName);
1158+
1159+
// export sliced files format
1160+
boolean success;
1161+
long time = System.currentTimeMillis();
1162+
try {
1163+
SlicesExporter exporter = new SlicesExporter(exportTo, data, progressDialog, console);
1164+
exporter.setSliceDirection(dialog.getValue("slices_format.axis"));
1165+
exporter.setExportFormat(dialog.getValue("slices_format.export_format"));
1166+
exporter.setInvertOrder(dialog.is("slices_format.invert=true"));
1167+
1168+
success = exporter.generateImages();
1169+
} catch (IOException ignored) {
1170+
success = false;
1171+
}
1172+
if (success) {
1173+
console.addLine(
1174+
String.format(langSelector.getString("export_file_successful"),
1175+
System.currentTimeMillis() - time)
1176+
);
1177+
} else {
1178+
console.addLine(langSelector.getString("export_file_error"));
1179+
}
1180+
1181+
return null;
1182+
}
1183+
});
1184+
1185+
// ===========
1186+
}
11151187
// -----
11161188
// store serialization
11171189
preferences.storeObject("export_dialog_serialization", dialog.getSerialization());

0 commit comments

Comments
 (0)