Image loader type issue

aeolian

25-03-2009 12:52:14

Hi guys,

I'm writting some code to load a custom texture image streamed over a network from a central server than added to ogres resource pool at the client display side. On the server the file is read and transmitted as a list in the form 'name' | 'data'

data = file("Dirt.jpg").read()
startup = {'name':'splash', 'data':data}


This is then parsed on the client:

if material['name'] in self.available_material_list:
#Material already loaded
print "Material already exists, skipping"
return True
else:
print "Attempting to load material ", material['name']
img = ogre.Image()
img.load((material['data']),'')
textureManager = ogre.TextureManager.getSingleton ()
textureManager.loadImage(material['name'], 'General', img)
self.available_material_list.append(material['name'])
return True


The problem i am having is there are two available Image.load interfaces

Load(
class Ogre::Image {lvalue},
class Ogre::SharedPtr<class Ogre::DataStream> {lvalue} stream,
class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > type='')

load(
class Ogre::Image {lvalue},
class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > strFileName,
class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > groupName)


And because file.read() returns a string, python interprets the data as being a filename, not the contents of the file itself.

So, my question is, how can i get python to recognise the data stream as data and not as a filename.

Thanks in advance :)

andy

26-03-2009 01:50:28

You can do something like:width = 240
height = 240
depth = 8
format = ogre.PixelFormat.PF_BYTE_BGR
requiredSize = ogre.PixelUtil.getMemorySize(width, height, depth, format )
mDs = ogre.MemoryDataStream ( requiredSize )
pointer = mDs.getPtr ()
for i in range ( requiredSize):
pointer[i] = random.randint ( 0, 255 )
img=ogre.Image()
img.loadRawData(mDs, width, height, depth, ogre.PixelFormat.PF_BYTE_BGR)

Obviously filling the MemoryDataStream as needed...
or another way to get data into the MemoryDataStream using a helper function: f= file("test.material", 'r')
MatString = f.read()
f.close()
memDataStream = ogre.MemoryDataStream ( "MyBuffer", len (MatString) )
memDataStream.setData ( MatString )


Regards
Andy

aeolian

26-03-2009 17:08:39

Hi,
Thank you for reply! I am trying to stay away from using loadRawData as i do not want to lock the images down to be a specific file size, type dimension, etc. This information should be in the header hence the convenience of load(DataStream, type)

I have taken your direction towards MemoryDataStream, however this still returns:

ArgumentError: Python argument types in
Image.load(Image, MemoryDataStream, str)
did not match C++ signature:
load(class Ogre::Image {lvalue}, class Ogre::SharedPtr<class Ogre::DataStream> {lvalue} stream, class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > type='')
load(class Ogre::Image {lvalue}, class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > strFileName, class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > groupName)


So the question is, given (Image, str, str) works fine then:
(Image, <what should this be>, str) to access the first signature

andy

27-03-2009 00:13:42

can you send the example code you are using... Examples that might help are:f= file('../../media/materials/textures/smoke.png', 'rb')
MatString = f.read()
f.close()
memDataStream = ogre.MemoryDataStream ( "MyBuffer", len (MatString) )
memDataStream.setData ( MatString )
img2=ogre.Image()
img2.load (memDataStream)

or of course you can configure the image files as part of your media area (resources.cfg) and do
img.load('smoke.png', 'General)

Andy

aeolian

27-03-2009 13:57:18

Hi Andy,

What i am trying to is essentially as you have written in the first block of code. Editing the cfg is not an option as the texture images are never stored locally.


data = file("smoke.png").read()

stream = ogre.MemoryDataStream("MyBuffer", len(data))
stream.setData(data)

img = ogre.Image()
img.load(stream)


which gives the run time error

Image.load(Image, MemoryDataStream)
did not match C++ signature:
load(class Ogre::Image {lvalue}, class Ogre::SharedPtr<class Ogre::DataStream> {lvalue} stream, class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > type='')
load(class Ogre::Image {lvalue}, class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > strFileName, class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > groupName)


Your code also reacts the same :(

andy

27-03-2009 14:06:52

Can you make sure you are running the latest version of Python-Ogre.. ie the 1.6.1 release plus the update mentioned here

The code I sent you works on my system so clearly there is something different -- also make sure you are reading the image file in a binary fashion ('b') otherwise you'll get strange results..

Andy

aeolian

27-03-2009 14:21:23

Can you make sure you are running the latest version of Python-Ogre.. ie the 1.6.1 release plus the update mentioned here

The code I sent you works on my system so clearly there is something different -- also make sure you are reading the image file in a binary fashion ('b') otherwise you'll get strange results..

Andy


Somewhere inbetween refreshing installations of python, python-ogre and installing the update the issue got fixed. Thanks for the binary read tip as well :) Thank you

edit: Actually i have just walked into my next problem. I then need to use this image to texture a simple quad which worked fine under resources loaded by the cfg files. I am struggling to find any documentation on how to actually use said image file. I thought this might work:

textureManager = ogre.TextureManager.getSingleton ()
textureManager.loadImage(material['name'], 'General', img)
....
self.MaterialName = material['name']
....
self.currentMaterial = ogre.MaterialManager.getSingleton().getByName(self.MaterialName)


however, getByName() returns a noneobject, indicating the material doesnt exist. I have the suspicion i have missed a step, and i am unsure what the difference between a material and a texture is

edit2:
http://www.ogre3d.org/docs/manual/manual_11.html states
Materials can either be set up programmatically, by calling SceneManager::createMaterial

but scenemanager does not seem to have a create material method