将papplet框架保存为磁盘上不起作用的图像

发布于 2025-02-08 17:56:44 字数 4329 浏览 2 评论 0原文

我正在用

我的目标是将地图保存为我的硬盘驱动器上的图像,但是当我尝试将其保存为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和流,但会产生相同的结果:一个没有地图的黑色图像。

这是我的地图代码,它几乎是从展开的图书馆唱片地图示例中复制的:

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()之外,除了尝试修复save()之外,我开放的是,我开放了。

谢谢,祝你有美好的一天。

I am making a map with unfolding with processing.core.PApplet. I'm using pure Java instead of Processing (Java 8).

My goal is to save the map as an image on my hard drive, but when I try to save it as a PNG, it is a black image. Same blank result happens when trying to save it as a TIF or JPG.

The map itself has no event dispatcher. You cannot interact with it, no clicking, zooming nor scrolling. It should have no problem saving as an image.

My Main code is quite simple:

import processing.core.PApplet;


public class Main {
    public static void main(String args[]) {
        PApplet sketch = new ChoroplethMap();
        sketch.init();
        sketch.save("test.jpg");
    }
}

I've also tried the saveFrame() method as well to no avail. From other forums, it seems like these methods have no issues in Processing but I've found no information on them in pure Java 8.

I've also tried using BufferedImages and streams but it yields the same result: a black image with no map.

Here's my map code, it is pretty much copied from the unfolding library Choropleth map example:

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

}

I feel like I'm not initializing the PApplet in my main class the right way. Is there anything else I need to do besides calling the init() method?

I'm open to over suggestions besides trying to fix save() or saveFrame(), something like using BufferedImages or streams to write to a file.

Thanks, and have a nice day.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

幸福%小乖 2025-02-15 17:56:44

Papplet推出了吗?如果确实如此,您可以通过调用save()/saveframe()从papplet中逃脱?

例如,

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

}

可能是偏离的,但是过去,我记得用

import processing.core.PApplet;


public class Main {
    public static void main(String args[]) {
        PApplet.main(ChoroplethMap.class.getCanonicalName());
    }
}

仅当Sketch.Init()还没有启动草图时,这可能是相关的。

Does the PApplet launch ? If it does, could you get away by calling save()/saveFrame() from within the PApplet ?

E.g.

 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.
    }

Does it make a difference if you call sketch.loadPixels(); before sketch.save() ?

I also wonder if you've got any guarantees that the sketch finished initialising and rendering at least a frame when you call save. (AFAIK rendering happens on a separate thread (the animation thread)).

To test this idea you can use registerMethod("draw",this);

Register a built-in event so that it can be fired for libraries, etc. Supported events include:
...draw – at the end of the draw() method (safe to draw)

e.g. (not tested, but hopefully illustrates the idea):

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

}

Might be offtopic, but in the past I remember launching the sketch with PApplet.main():

import processing.core.PApplet;


public class Main {
    public static void main(String args[]) {
        PApplet.main(ChoroplethMap.class.getCanonicalName());
    }
}

This is probably relevant only if sketch.init() doesn't launch the sketch already.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文