簡體   English   中英

將 PApplet 框架保存為磁盤上的圖像不起作用

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM