Load Texture from PNG in Memory

Jzone

22-06-2009 22:06:09

I have a PNG file which is created at runtime, and saved to memory using StringIO. The problem I am having is actually getting ogre to load this file as a texture. I've scoured the Image and Texture documentation in the ogre API trying to find something to help, but have had no luck. The closest I could get was the loadRawData() functions, which require the data in a datastream format, and I can't find a way to get my data into this format.

If anyone has any ideas on how to do this, I'd really appreciate it. Thanks in advance.

P.S. I don't want to write the file to the hard drive because of performance issues.

SirGolan

25-06-2009 04:03:08

Have a look at this code:

http://www.mv3d.com/trac/browser/trunk/ ... ge.py#L103

I think it basically does what you want. It takes an image from PIL and makes it into an Ogre texture. self.image is the PIL image. Hope that helps!

Mike

Jzone

25-06-2009 20:59:24

It looks promising, but I keep running into errors. (Likely due to my relative inexperience with ogre)

(On converting PIL to Ogre)
mTexture.loadRawData(nam, grp, ms, sz[0], sz[1], pf, ogre.TextureType.TEX_TYPE_2D, - 1, 1.0)

Traceback (most recent call last):
File "<pyshell#154>", line 1, in <module>
mTexture.loadRawData(nam, grp, ms, sz[0], sz[1], pf, ogre.TextureType.TEX_TYPE_2D, - 1, 1.0)
ArgumentError: Python argument types in
TextureManager.loadRawData(TextureManager, str, str, MemoryDataStream, int, int, PixelFormat, TextureType, int, float)
did not match C++ signature:
loadRawData(struct TextureManager_wrapper {lvalue}, class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > name, class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > group, class Ogre::SharedPtr<class Ogre::DataStream> {lvalue} stream, unsigned short uWidth, unsigned short uHeight, enum Ogre::PixelFormat format, enum Ogre::TextureType texType=ogre.renderer.OGRE._ogre_.TextureType.TEX_TYPE_2D, int iNumMipmaps=-1, float gamma=1.0, bool hwGammaCorrection=False)
loadRawData(class Ogre::TextureManager {lvalue}, class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > name, class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > group, class Ogre::SharedPtr<class Ogre::DataStream> {lvalue} stream, unsigned short uWidth, unsigned short uHeight, enum Ogre::PixelFormat format, enum Ogre::TextureType texType=ogre.renderer.OGRE._ogre_.TextureType.TEX_TYPE_2D, int iNumMipmaps=-1, float gamma=1.0, bool hwGammaCorrection=False)


I also tried converting from Ogre to PIL, just to see if I could get that working, however I first ran into this error:
buff.lock(buff.HBL_READ_ONLY)

Traceback (most recent call last):
File "<pyshell#100>", line 1, in <module>
buff.lock(buff.HBL_READ_ONLY)
ArgumentError: Python argument types in
HardwarePixelBuffer.lock(HardwarePixelBuffer, LockOptions)
did not match C++ signature:
lock(struct HardwarePixelBuffer_wrapper {lvalue}, unsigned int offset, unsigned int length, enum Ogre::HardwareBuffer::LockOptions options)
lock(class Ogre::HardwarePixelBuffer {lvalue}, unsigned int offset, unsigned int length, enum Ogre::HardwareBuffer::LockOptions options)
lock(class Ogre::HardwarePixelBuffer {lvalue}, struct Ogre::Box lockBox, enum Ogre::HardwareBuffer::LockOptions options)


But I was able to get around this by using buff.lock(0, im.getSize(), buff.HBL_READ_ONLY)
Unfortunately, immediately after that I ran into...
image = Image.frombuffer('RGB', size, pbuff.data)

Warning (from warnings module):
File "__main__", line 1
RuntimeWarning: the frombuffer defaults may change in a future release; for portability, change the call to read:
frombuffer(mode, size, data, 'raw', mode, 0, 1)

Traceback (most recent call last):
File "<pyshell#106>", line 1, in <module>
image = Image.frombuffer('RGB', size, pbuff.data)
File "C:\Python25\Lib\site-packages\PIL\Image.py", line 1858, in frombuffer
return fromstring(mode, size, data, decoder_name, args)
File "C:\Python25\Lib\site-packages\PIL\Image.py", line 1797, in fromstring
im.fromstring(data, decoder_name, args)
File "C:\Python25\Lib\site-packages\PIL\Image.py", line 591, in fromstring
s = d.decode(data)
TypeError: argument 1 must be string or read-only buffer, not int

I found that the contents of pbuff.data was the integer 59639592, but I don't know why it is an integer instead of the expected string, so I didn't know how to proceed.

I can tell this has got me on the right track, and that I'm probably quite close to getting things working, but I just don't have enough experience to understand the problems. If you have any more suggestions, I'd really appreciate it.

Thanks!

P.S. I'm using Python 2.5 and Python-Ogre 1.6.1

SirGolan

26-06-2009 02:24:01

The first issue seems like a problem which I think happened in vanilla 1.6.1 installs. Have you installed the update for 1.6.1?

viewtopic.php?f=3&t=9376

As for the warning from PIL, I'd just do what it says. You probably have a newer version than I do.

Thanks,
Mike

Jzone

26-06-2009 14:29:20

I actually tried installing the update for 1.6.1 already, I still get the same error.

As for changing the Image.frombuffer() call, I still get a TypeError complaining that I'm passing and int instead of a string or buffer, after making the change to the call that it suggests.

Edit: I've now tried every alternate solution I can find on the internet for loading in an image with loadRawData, and have had 0 luck. Maybe I should try nuking python/ogre and reinstalling...

Edit2:
mTexture.loadRawData(nam, grp, ms, sz[0], sz[1], pf, ogre.TextureType.TEX_TYPE_2D, -1, 1.0)
<ogre.renderer.OGRE._ogre_.Texture object at 0x03AB7AE0>

Seems that did the trick! Now to just implement it in my application, with fingers crossed. :D

Edit3: Well, I'm not getting any errors, but I'm also only getting pure black textures showing on the meshes. Perhaps I'm not applying the textures properly...

Edit4: Turns out there was some issue with the way the images were saved. Some kind of pixel format conflict I think, though I'll have to test more (at some point) to be sure. Got everything working great now though. BIG BIG BIG Thanks, SirGolan! :mrgreen:

geetika

18-09-2009 05:35:05

Hi

Could you post more details of how you got it going? I am attempting a similar thing - displaying a PIL image as a texture in the scene and am getting the same error

Boost.Python.ArgumentError: Python argument types in
TextureManager.loadRawData(TextureManager, str, str, MemoryDataStream, int,
int, PixelFormat, TextureType, int, float)
did not match C++ signature:
loadRawData(struct TextureManager_wrapper {lvalue}, class std::basic_string<
char,struct std::char_traits<char>,class std::allocator<char> > name, class std:
:basic_string<char,struct std::char_traits<char>,class std::allocator<char> > gr
oup, class Ogre::SharedPtr<class Ogre::DataStream> {lvalue} stream, unsigned sho
rt uWidth, unsigned short uHeight, enum Ogre::PixelFormat format, enum Ogre::Tex
tureType texType=ogre.renderer.OGRE._ogre_.TextureType.TEX_TYPE_2D, int iNumMipm
aps=-1, float gamma=1.0, bool hwGammaCorrection=False)
loadRawData(class Ogre::TextureManager {lvalue}, class std::basic_string<cha
r,struct std::char_traits<char>,class std::allocator<char> > name, class std::ba
sic_string<char,struct std::char_traits<char>,class std::allocator<char> > group
, class Ogre::SharedPtr<class Ogre::DataStream> {lvalue} stream, unsigned short
uWidth, unsigned short uHeight, enum Ogre::PixelFormat format, enum Ogre::Textur
eType texType=ogre.renderer.OGRE._ogre_.TextureType.TEX_TYPE_2D, int iNumMipmaps
=-1, float gamma=1.0, bool hwGammaCorrection=False)

Thanks
Geetika

Jzone

05-11-2009 22:43:18

Ah, sorry for the slow response I haven't checked these boards lately.

In order to get around that error I had to remove my python & ogre installs, then reinstall both and reapply the patch. But if you haven't installed the update yet, you should do that as I found with some experimenting it definitely does not work without the update installed - it's linked a couple posts above this one.