There is a quick way to get a string from a texture, which is texture.getRamImageAs(“RGB”). You could store it into a Texture object first and try that.
Traceback (most recent call last):
File "captchagenerator.py", line 67, in <module>
captcha.renderCaptcha('solmasks', 'solmasks')
File "captchagenerator.py", line 36, in renderCaptcha
t = Image.fromstring('RGB', (imgMask.getReadXSize(), imgMask.getReadYSize())
, tex.getRamImageAs("RGB"), 'raw')
File "C:\Panda3D-1.8.0\python\lib\site-packages\PIL\Image.py", line 1797, in f
romstring
im.fromstring(data, decoder_name, args)
File "C:\Panda3D-1.8.0\python\lib\site-packages\PIL\Image.py", line 591, in fr
omstring
s = d.decode(data)
TypeError: must be string or read-only buffer, not libpandaexpress.CPTA_uchar
Also I would like to clarify that when I say “the fastest way”, I mean the cheapest on CPU and memory.
getRamImageAs() returns a CPTA_uchar; use getData() on this value to return a string, e.g. tex.getRamImageAs(“RGB”).getData().
Or, for your earlier approach, you should use the “img” type (instead of “raw”), and you be aware that the “img” data type by default writes the size of the buffer in the first four bytes, so you can skip over this value. But I suspect that the byte order might trip you up.
The cheapest CPU way to get an image into PIL, though, is to load it into PIL in the first place.
I would very much like to do that, but I did not find any way to do so, because I am not loading just any image into PNMImage, I’m loading a rendered image directly from Panda3D renderer, and it seems noone knows of a better way to save a rendered image than storing it into a PNMImage first.
According to the docs if you call getScreenshot with no arguments it will return a Texture object, so you can skip the PNMImage step if all you are using it for is to retrieve the Texture.
Right, the Texture is the fundamental unit of retrieving data from the framebuffer. The getScreenshot() call that fills a PNMImage does this by first copying the framebuffer data to a Texture, then storing the Texture data in a PNMImage.
The fastest way to get the framebuffer data to CPU is to copy it to a texture using win.setupRenderTexture() or win.addRenderTexture().