ImageSurface.getData() Method Fails to Retrieve Data
Closed this issue · 2 comments
Hello,
I am experiencing a problem with specifically with the ImageSurface.getData()
method. The issue is that the function does not seem to work as expected.
The getData()
function, which is supposed to return a pointer to the image data of a surface, is not functioning correctly in my example. When I call getData()
, the returned MemorySegment shows a byteSize()
of 0 which is incorrect.
public class CairoPngExample {
public static void main(String[] args) throws IOException {
int width = 400;
int height = 300;
try (var surface = ImageSurface.create(Format.RGB24, width, height)) {
var cr = Context.create(surface);
cr.setSourceRGB(1, 0, 0);
cr.rectangle(0, 0, width, height);
cr.fill();
cr.setSourceRGB(1, 1, 0);
cr.moveTo(100, 200);
cr.setFontSize(100);
cr.selectFontFace("Segoe UI", FontSlant.NORMAL, FontWeight.BOLD);
cr.showText("Hello");
surface.flush();
System.out.println(surface.getData().byteSize()); // prints 0
surface.writeToPNG("example.png");
}
}
}
As a workaround, I provided my custom allocated buffer and was able to read the data. However, the problem still exists when using getData()
. It continues to return 0, which is incorrect.
public class CairoPngExampleCustomSurface {
public static void main(String[] args) throws IOException {
int width = 400;
int height = 300;
int stride = ImageSurface.formatStrideForWidth(Format.RGB24, width);
MemorySegment data = Arena.ofAuto().allocate(stride * height);
try (var surface = ImageSurface.create(data, Format.RGB24, width, height, stride)) {
var cr = Context.create(surface);
cr.setSourceRGB(1, 0, 0);
cr.rectangle(0, 0, width, height);
cr.fill();
cr.setSourceRGB(1, 1, 0);
cr.moveTo(100, 200);
cr.setFontSize(100);
cr.selectFontFace("Segoe UI", FontSlant.NORMAL, FontWeight.BOLD);
cr.showText("Hello");
surface.flush();
System.out.println(surface.getData().byteSize()); // prints 0
System.out.println(data.byteSize()); // prints 480000
surface.writeToPNG("example.png");
}
}
}
Hi,
ImageSurface.getData() returns a zero-length memory segment, which is basically a pointer with unknown size. You can resize it with: surface.getData().reinterpret(stride * height);
In the next release of the bindings, I will change ImageSurface.getData() to do this automatically.
Thank you for your guidance regarding the zero-length memory segment. I wasn't familiar with this reinterpret
method, and your suggestion worked perfectly.