Hi
On 8/28/07, 赵明伟 <[EMAIL PROTECTED]> wrote:
>
> I find the ReadWriter's virtual function read/write Object/Image/Node from
> file and also from the memory by istream. I think That's what I want. But It
> seems to only the osg plugin implement the function completely.
>
I think we kinda float the same boat :)
First, my situation: I have stuffed images in a database by loading the
files into memory buffers, and saving them in my DB. The table has a row
that contains the image name, extension (essential!) and the binary data
(stored as a PostgreSQL 'bytea' data type). Until today, I was loading the
row, saving it to a file and reloading it with osgDB::readImageFile(). This
worked but was ugly.
Now the solution I ended up with: of course, we want to load the images
directly from memory. Idea: osg::ReaderWriter provides a virtual method
readImage(std::istream& fin) that can read from streams. If we can create an
ad-hoc stream from our memory buffer, we're done (provided that the specific
plugins you are interested in, i.e. 3ds and OpenFlight, do implement this
method). Now, the C++ does not have a built-in way to create a stream from a
buffer. So, after googling for a couple of hours, I have written (ahem ...
copy-pasted :) a custom std::streambuf that can read from our memory buffer.
It goes like this:
template <class cT, class traits = std::char_traits<cT> >
class basic_membuf : public std::basic_streambuf<cT, traits> {
public:
basic_membuf(cT * mem, std::streamsize sz) {
setg(mem, mem, mem + sz);
}
};
typedef basic_membuf<char, std::char_traits<char> > membuf;
[ Credits go to Dietmar Kühl. See the thread that comes first while
searching 'memory mapped istream' in google groups for '
comp.lang.c++.moderated'. ]
Let's assume your image data is:
char* memory_mapped_file = read_the_data_from_the_database();
size_t length = ... // you have to know the size, but that should not be
tricky
const char* extension = "png"; // for instance
Now, we can create a stream for our memory-mapped file:
membuf my_buf(memory_mapped_file, length);
std::istream stream(&my_buf);
If we add the OSG stuff, we have the following function:
osg::Image* getImageFromBuffer(char* buffer, size_t length, const char*
extension)
{
osgDB::ReaderWriter* rw =
osgDB::Registry::instance()->getReaderWriterForExtension(extension);
if (rw)
{
membuf sb(buffer, length);
std::istream stream(&sb);
osgDB::ReaderWriter::ReadResult rr = rw->readImage(stream);
return rr.takeImage();
}
}
And you are done.
Thibault
_______________________________________________
osg-users mailing list
[email protected]
http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org