ebiten: NewImageFromImage problems: erasing source image, crashing when calling GL functions if source image variable is set to nil after NewImageFromImage call
NewImageFromImage seems to have some issues.
This test code, run inside either a Game’s Update or its Draw method, crashes reliably:
testPngFile, err = os.Open("testdata/testPNG2.png")
r := bufio.NewReader(testPngFile)
var pngImg image.Image
pngImg, err = png.Decode(r)
eImg := ebiten.NewImageFromImage(pngImg)
pngImg = nil
time.Sleep(time.Second)
eImg.At(0, 0)
The test image is a 32-bit 1x1 pixel PNG whose single pixel is RGBA FF FF FF FF, but this also happens with larger images and seems to happen with 24-bit PNGs as well. I created both the 32-bit and 24-bit 1x1 test PNGs with Paint.NET, but it was happening with images from other sources as well.
One of the crashes:
Exception 0xc0000005 0x0 0x6c8 0x7ffa13657630
PC=0x7ffa13657630
syscall.Syscall(0x7ffa13657600, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
C:/Program Files/Go/src/runtime/syscall_windows.go:330 +0xe9
github.com/hajimehoshi/ebiten/v2/internal/graphicsdriver/opengl/gl.Flush(...)
C:/Users/Amani/Documents/Go/pkg/mod/github.com/hajimehoshi/ebiten/v2@v2.1.1/internal/graphicsdriver/opengl/gl/package_windows.go:184
[etc]
It looks like the pointer to the image it’s passing no longer points to anything valid.
It isn’t always the same GL function, and if there’s no Sleep call, it sometimes crashes and sometimes doesn’t, and all of this makes me suspect the garbage collector is involved. I actually added the Sleep call to the test code above so that it would crash every time instead of only sometimes. Also, when it didn’t crash, At(0,0) sometimes returned RGBA 0 0 0 0 instead of the pixel’s actual RGBA value, which is FF FF FF FF.
Also, if I don’t set pngImage to nil, it doesn’t crash, but the pngImg’s pixel data appears to have been erased, replaced with all RGBA 0 0 0 0 pixels, which doesn’t seem like something that should be happening.
Doing this instead of calling NewImageFromImage avoids all of these problems, so I figure something must be going very wrong with whatever NewImageFromImage is doing:
w, h := pngImg.Bounds().Dx(), pngImg.Bounds().Dy()
eImg := ebiten.NewImage(w, h)
for y := 0; y < h; y++ {
for x := 0; x < w; x++ {
eImg.Set(x, y, pngImg.At(x, y))
}
}
Ebiten version: 2.1.1 OS: Windows 10 Pro, version 20H2
If you have any questions, I’d be happy to answer them.
About this issue
- Original URL
- State: closed
- Created 3 years ago
- Comments: 18 (10 by maintainers)
I came up a solution: if a given image is a
*ebiten.Image
,NewImageFromImage
can useDrawImage
instead ofAt
.Yes, this is a known issue and there is no way to fix this so far.