[英]Save PApplet frame as image on disk not working
我正在制作一張使用 processing.core.PApplet展開的地圖。 我使用的是純 Java 而不是處理(Java 8)。
我的目標是將地圖另存為硬盤上的圖像,但是當我嘗試將其另存為 PNG 時,它是黑色圖像。 嘗試將其保存為 TIF 或 JPG 時會出現相同的空白結果。
地圖本身沒有事件調度程序。 你不能與之交互,不能點擊、縮放或滾動。 保存為圖像應該沒有問題。
我的主要代碼很簡單:
import processing.core.PApplet;
public class Main {
public static void main(String args[]) {
PApplet sketch = new ChoroplethMap();
sketch.init();
sketch.save("test.jpg");
}
}
我也試過saveFrame()
方法也無濟於事。 從其他論壇來看,這些方法似乎在處理中沒有問題,但我在純 Java 8 中沒有找到關於它們的信息。
我也嘗試過使用 BufferedImages 和流,但它產生了相同的結果:沒有地圖的黑色圖像。
這是我的地圖代碼,它幾乎是從展開庫 Choropleth 地圖示例中復制而來的:
import java.util.HashMap;
import java.util.List;
import processing.core.PApplet;
import de.fhpotsdam.unfolding.UnfoldingMap;
import de.fhpotsdam.unfolding.data.Feature;
import de.fhpotsdam.unfolding.data.GeoJSONReader;
import de.fhpotsdam.unfolding.examples.SimpleMapApp;
import de.fhpotsdam.unfolding.examples.interaction.snapshot.MapSnapshot;
import de.fhpotsdam.unfolding.marker.Marker;
import de.fhpotsdam.unfolding.utils.MapUtils;
/**
* Visualizes population density of the world as a choropleth map. Countries are shaded in proportion to the population
* density.
*
* It loads the country shapes from a GeoJSON file via a data reader, and loads the population density values from
* another CSV file (provided by the World Bank). The data value is encoded to transparency via a simplistic linear
* mapping.
*/
public class ChoroplethMap extends PApplet {
UnfoldingMap map;
HashMap<String, DataEntry> dataEntriesMap;
List<Marker> countryMarkers;
public void setup() {
size(800, 600, OPENGL);
smooth();
map = new UnfoldingMap(this, 50, 50, 700, 500);
map.zoomToLevel(2);
map.setBackgroundColor(240);
//MapUtils.createDefaultEventDispatcher(this, map);
// Load country polygons and adds them as markers
List<Feature> countries = GeoJSONReader.loadData(this, "data/countries.geo.json");
countryMarkers = MapUtils.createSimpleMarkers(countries);
map.addMarkers(countryMarkers);
// Load population data
dataEntriesMap = loadPopulationDensityFromCSV("data/countries-population-density.csv");
println("Loaded " + dataEntriesMap.size() + " data entries");
// Country markers are shaded according to its population density (only once)
shadeCountries();
}
public void draw() {
background(255);
// Draw map tiles and country markers
map.draw();
}
public void shadeCountries() {
for (Marker marker : countryMarkers) {
// Find data for country of the current marker
String countryId = marker.getId();
DataEntry dataEntry = dataEntriesMap.get(countryId);
if (dataEntry != null && dataEntry.value != null) {
// Encode value as brightness (values range: 0-1000)
float transparency = map(dataEntry.value, 0, 700, 10, 255);
marker.setColor(color(255, 0, 0, transparency));
} else {
// No value available
marker.setColor(color(100, 120));
}
}
}
public HashMap<String, DataEntry> loadPopulationDensityFromCSV(String fileName) {
HashMap<String, DataEntry> dataEntriesMap = new HashMap<String, DataEntry>();
String[] rows = loadStrings(fileName);
for (String row : rows) {
// Reads country name and population density value from CSV row
String[] columns = row.split(";");
if (columns.length >= 3) {
DataEntry dataEntry = new DataEntry();
dataEntry.countryName = columns[0];
dataEntry.id = columns[1];
dataEntry.value = Float.parseFloat(columns[2]);
dataEntriesMap.put(dataEntry.id, dataEntry);
}
}
return dataEntriesMap;
}
class DataEntry {
String countryName;
String id;
Integer year;
Float value;
}
}
我覺得我沒有以正確的方式在我的主類中初始化 PApplet。 除了調用init()
方法外,我還需要做什么嗎?
除了嘗試修復save()
或saveFrame()
之外,我還願意接受建議,例如使用 BufferedImages 或流寫入文件。
感謝,並有一個愉快的一天。
PApplet 是否啟動? 如果是這樣,您可以通過從 PApplet 中調用save()
/ saveFrame()
來逃脫嗎?
例如
public void draw() {
background(255);
// Draw map tiles and country markers
map.draw();
save("test.jpg");
noLoop();// alternatively just exit(); if you don't need the PApplet window anymore.
}
如果你調用sketch.loadPixels();
什么不同嗎? 在sketch.save()
之前?
我還想知道您是否有任何保證,當您調用 save 時,草圖完成了初始化和渲染至少一幀。 (AFAIK 渲染發生在單獨的線程(動畫線程)上)。
要測試這個想法,您可以使用registerMethod("draw",this);
注冊一個內置事件,以便可以為庫等觸發它。支持的事件包括: ...draw - 在 draw() 方法的末尾(可安全繪制)
例如(未經測試,但希望能說明這個想法):
public class Main {
PApplet sketch;
public Main(){
sketch = new ChoroplethMap();
sketch.init();
// add a callback triggered after draw() in a sketch completed
// (as soon as a frame is ready)
// sketch will search for method named "draw" in "this" instance
sketch.registerMethod("draw", this);
//stop rendering after the first frame
sketch.noLoop();
}
// called after sketch's draw() completes
public void draw(){
sketch.save("test.jpg");
}
public static void main(String args[]) {
new Main();
}
}
可能是題外話,但在過去我記得用PApplet.main()
啟動草圖:
import processing.core.PApplet;
public class Main {
public static void main(String args[]) {
PApplet.main(ChoroplethMap.class.getCanonicalName());
}
}
僅當sketch.init()
尚未啟動草圖時,這可能才有意義。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.