From Farshid Lashari, added support for reading from std::istream's to the BMP, GIF, PNG and TGA image plugins

This commit is contained in:
Robert Osfield
2005-08-24 10:48:24 +00:00
parent 3ac94784fc
commit e7c6a03bb2
4 changed files with 158 additions and 93 deletions

View File

@@ -135,7 +135,7 @@ void swapbyte(short *i)
vv[1]=tmp;
}
unsigned char *bmp_load(const char *filename,
unsigned char *bmp_load(std::istream& fin,
int *width_ret,
int *height_ret,
int *numComponents_ret)
@@ -150,12 +150,10 @@ int *numComponents_ret)
long filelen;
bmperror = ERROR_NO_FILE;
FILE *fp = fopen(filename, "rb");
if (!fp) return NULL;
fseek(fp, 0, SEEK_END);
filelen = ftell(fp); // determine file size so we can fill it in later if FileSize == 0
fseek(fp, 0, SEEK_SET);
fin.seekg(0, std::ios::end);
filelen = fin.tellg(); // determine file size so we can fill it in later if FileSize == 0
fin.seekg(0, std::ios::beg);
int ncolours;
int ncomp=0;
@@ -165,7 +163,7 @@ int *numComponents_ret)
struct bmpheader hd;
struct BMPInfo inf;
bmperror = ERROR_NO_ERROR;
fread((char *)&hd, sizeof(bmpheader), 1, fp);
fin.read((char*)&hd,sizeof(bmpheader));
if (hd.FileType != MB) {
swapbyte(&(hd.FileType));
swap=true;
@@ -177,15 +175,15 @@ int *numComponents_ret)
int32 infsize; //size of BMPinfo in bytes
unsigned char *cols=NULL; // dynamic colour palette
unsigned char *imbuff; // returned to sender & as read from the disk
fread((char *)&infsize, sizeof(int32), 1, fp); // insert inside 'the file is bmp' clause
fin.read((char*)&infsize,sizeof(int32)); // insert inside 'the file is bmp' clause
if (swap) swapbyte(&infsize);
unsigned char *hdr=new unsigned char[infsize]; // to hold the new header
fread((char *)hdr, 1,infsize-sizeof(int32), fp);
fin.read((char*)hdr,infsize-sizeof(int32));
int32 hsiz=sizeof(inf); // minimum of structure size &
if(infsize<=hsiz) hsiz=infsize;
memcpy(&inf,hdr, hsiz/*-sizeof(long)*/); // copy only the bytes I can cope with
delete [] hdr;
osg::notify(osg::INFO) << "loading "<<filename <<" "<<swap<<" "<<infsize<< " "<<sizeof(inf) << " "<<sizeof(bmpheader) << std::endl;
osg::notify(osg::INFO) << "loading bmp file "<<swap<<" "<<infsize<< " "<<sizeof(inf) << " "<<sizeof(bmpheader) << std::endl;
if (swap) { // inverse the field of the header which need swapping
swapbyte(&hd.siz[0]);
swapbyte(&hd.siz[1]);
@@ -224,7 +222,7 @@ int *numComponents_ret)
size -= sizeof(bmpheader)+infsize;
if (inf.ImageSize<size) inf.ImageSize=size;
imbuff = new unsigned char [ inf.ImageSize]; // read from disk
fread((char *)imbuff, sizeof(unsigned char),inf.ImageSize, fp);
fin.read((char*)imbuff,sizeof(unsigned char)*inf.ImageSize);
ncolours=inf.Colorbits/8;
switch (ncolours) {
case 1:
@@ -287,13 +285,10 @@ int *numComponents_ret)
}
}
delete [] imbuff; // free the on-disk storage
fclose(fp);
}
else // else error in header
{
fclose(fp);
return NULL;
}
*width_ret = inf.width;
@@ -322,20 +317,14 @@ class ReaderWriterBMP : public osgDB::ReaderWriter
virtual const char* className() const { return "BMP Image Reader"; }
virtual bool acceptsExtension(const std::string& extension) const { return osgDB::equalCaseInsensitive(extension,"bmp"); }
virtual ReadResult readImage(const std::string& file, const osgDB::ReaderWriter::Options* options) const
ReadResult readBMPStream(std::istream& fin) const
{
std::string ext = osgDB::getLowerCaseFileExtension(file);
if (!acceptsExtension(ext)) return ReadResult::FILE_NOT_HANDLED;
std::string fileName = osgDB::findDataFile( file, options );
if (fileName.empty()) return ReadResult::FILE_NOT_FOUND;
unsigned char *imageData = NULL;
int width_ret;
int height_ret;
int numComponents_ret;
imageData = bmp_load(fileName.c_str(),&width_ret,&height_ret,&numComponents_ret);
imageData = bmp_load(fin,&width_ret,&height_ret,&numComponents_ret);
if (imageData==NULL) return ReadResult::FILE_NOT_HANDLED;
@@ -354,7 +343,6 @@ class ReaderWriterBMP : public osgDB::ReaderWriter
unsigned int dataType = GL_UNSIGNED_BYTE;
osg::Image* pOsgImage = new osg::Image;
pOsgImage->setFileName(fileName.c_str());
pOsgImage->setImage(s,t,r,
internalFormat,
pixelFormat,
@@ -363,15 +351,30 @@ class ReaderWriterBMP : public osgDB::ReaderWriter
osg::Image::USE_NEW_DELETE);
return pOsgImage;
}
virtual WriteResult writeImage(const osg::Image &img,const std::string& fileName, const osgDB::ReaderWriter::Options*) const
{
std::string ext = osgDB::getFileExtension(fileName);
if (!acceptsExtension(ext)) return WriteResult::FILE_NOT_HANDLED;
FILE *fp = fopen(fileName.c_str(), "wb");
if (!fp) return WriteResult::ERROR_IN_WRITING_FILE;
virtual ReadResult readImage(std::istream& fin,const Options* =NULL) const
{
return readBMPStream(fin);
}
virtual ReadResult readImage(const std::string& file, const osgDB::ReaderWriter::Options* options) const
{
std::string ext = osgDB::getLowerCaseFileExtension(file);
if (!acceptsExtension(ext)) return ReadResult::FILE_NOT_HANDLED;
std::string fileName = osgDB::findDataFile( file, options );
if (fileName.empty()) return ReadResult::FILE_NOT_FOUND;
std::ifstream istream(fileName.c_str(), std::ios::in | std::ios::binary);
if(!istream) return ReadResult::FILE_NOT_HANDLED;
ReadResult rr = readBMPStream(istream);
if(rr.validImage()) rr.getImage()->setFileName(file);
return rr;
}
bool WriteBMPStream(const osg::Image &img, std::ostream& fout, const std::string &fileName) const
{
// its easier for me to write a binary write using stdio than streams
struct bmpheader hd;
uint32 nx=img.s(),ny=img.t(); // unsigned long ndep=img.r();
@@ -392,7 +395,7 @@ class ReaderWriterBMP : public osgDB::ReaderWriter
hd.siz[0]=(size&0xffff); // low word
hd.siz[1]=(size&0xffff0000)>>16; // high word
fwrite(&hd, sizeof(hd), 1, fp);
fout.write((const char*)&hd, sizeof(hd));
struct BMPInfo inf;
osg::notify(osg::INFO) << "sizes "<<size << " "<<sizeof(inf)<< std::endl;
inf.width=nx; //width of the image in pixels
@@ -407,8 +410,8 @@ class ReaderWriterBMP : public osgDB::ReaderWriter
inf.Important=0; //number of "important" colors
// inf.os2stuff[6]; // allows os2.1 with 64 bytes to be read. Dont know what these are yet.
infsize=sizeof(BMPInfo)+sizeof(int32);
fwrite(&infsize, sizeof(int32), 1, fp);
fwrite(&inf, sizeof(inf), 1, fp); // one dword shorter than the structure defined by MS
fout.write((const char*)&infsize,sizeof(int32));
fout.write((const char*)&inf,sizeof(inf)); // one dword shorter than the structure defined by MS
// the infsize value (above) completes the structure.
osg::notify(osg::INFO) << "save screen "<<fileName <<inf.width<< " "<<inf.height << std::endl;
osg::notify(osg::INFO) << "sizes "<<size << " "<<infsize <<" "<<sizeof(inf)<< std::endl;
@@ -453,11 +456,36 @@ class ReaderWriterBMP : public osgDB::ReaderWriter
osg::notify(osg::WARN) << "Cannot write images with other number of components than 3 or 4" << std::endl;
break;
}
fwrite(dta, sizeof(unsigned char), size, fp);
fout.write((const char*)dta,sizeof(unsigned char)*size);
delete [] dta;
fclose(fp);
return WriteResult::FILE_SAVED;
return true;
}
virtual WriteResult writeImage(const osg::Image& image,std::ostream& fout,const Options*) const
{
bool success = WriteBMPStream(image, fout, "<output stream>");
if(success)
return WriteResult::FILE_SAVED;
else
return WriteResult::ERROR_IN_WRITING_FILE;
}
virtual WriteResult writeImage(const osg::Image &img,const std::string& fileName, const osgDB::ReaderWriter::Options*) const
{
std::string ext = osgDB::getFileExtension(fileName);
if (!acceptsExtension(ext)) return WriteResult::FILE_NOT_HANDLED;
std::ofstream fout(fileName.c_str(), std::ios::out | std::ios::binary);
if(!fout) return WriteResult::ERROR_IN_WRITING_FILE;
bool success = WriteBMPStream(img, fout, fileName);
if(success)
return WriteResult::FILE_SAVED;
else
return WriteResult::ERROR_IN_WRITING_FILE;
}
};

View File

@@ -133,9 +133,15 @@ int transparent)
}
}
int gif_read_stream(GifFileType *gfile, GifByteType *gdata, int glength)
{
std::istream *stream = (std::istream*)gfile->UserData; //Get pointer to istream
stream->read((char*)gdata,glength); //Read requested amount of data
return stream->gcount();
}
unsigned char *
simage_gif_load(const char *filename,
simage_gif_load(std::istream& fin,
int *width_ret,
int *height_ret,
int *numComponents_ret)
@@ -154,7 +160,7 @@ int *numComponents_ret)
int interlacedoffset[] = { 0, 4, 2, 1 };
int interlacedjumps[] = { 8, 8, 4, 2 };
giffile = DGifOpenFileName(filename);
giffile = DGifOpen(&fin,gif_read_stream);
if (!giffile)
{
giferror = ERR_OPEN;
@@ -314,7 +320,6 @@ int *numComponents_ret)
return buffer;
}
class ReaderWriterGIF : public osgDB::ReaderWriter
{
public:
@@ -324,20 +329,14 @@ class ReaderWriterGIF : public osgDB::ReaderWriter
return osgDB::equalCaseInsensitive(extension,"gif");
}
virtual ReadResult readImage(const std::string& file, const osgDB::ReaderWriter::Options* options) const
ReadResult readGIFStream(std::istream& fin) const
{
std::string ext = osgDB::getLowerCaseFileExtension(file);
if (!acceptsExtension(ext)) return ReadResult::FILE_NOT_HANDLED;
std::string fileName = osgDB::findDataFile( file, options );
if (fileName.empty()) return ReadResult::FILE_NOT_FOUND;
unsigned char *imageData = NULL;
int width_ret;
int height_ret;
int numComponents_ret;
imageData = simage_gif_load(fileName.c_str(),&width_ret,&height_ret,&numComponents_ret);
imageData = simage_gif_load(fin,&width_ret,&height_ret,&numComponents_ret);
switch (giferror)
{
@@ -366,7 +365,6 @@ class ReaderWriterGIF : public osgDB::ReaderWriter
unsigned int dataType = GL_UNSIGNED_BYTE;
osg::Image* pOsgImage = new osg::Image;
pOsgImage->setFileName(fileName.c_str());
pOsgImage->setImage(s,t,r,
internalFormat,
pixelFormat,
@@ -375,7 +373,26 @@ class ReaderWriterGIF : public osgDB::ReaderWriter
osg::Image::USE_NEW_DELETE);
return pOsgImage;
}
virtual ReadResult readImage(std::istream& fin,const osgDB::ReaderWriter::Options* =NULL) const
{
return readGIFStream(fin);
}
virtual ReadResult readImage(const std::string& file, const osgDB::ReaderWriter::Options* options) const
{
std::string ext = osgDB::getLowerCaseFileExtension(file);
if (!acceptsExtension(ext)) return ReadResult::FILE_NOT_HANDLED;
std::string fileName = osgDB::findDataFile( file, options );
if (fileName.empty()) return ReadResult::FILE_NOT_FOUND;
std::ifstream istream(fileName.c_str(), std::ios::in | std::ios::binary);
if(!istream) return ReadResult::FILE_NOT_HANDLED;
ReadResult rr = readGIFStream(istream);
if(rr.validImage()) rr.getImage()->setFileName(file);
return rr;
}
};

View File

@@ -30,22 +30,21 @@ typedef struct
unsigned int Alpha;
} pngInfo;
void png_read_istream(png_structp png_ptr, png_bytep data, png_size_t length)
{
std::istream *stream = (std::istream*)png_get_io_ptr(png_ptr); //Get pointer to istream
stream->read((char*)data,length); //Read requested amount of data
}
class ReaderWriterPNG : public osgDB::ReaderWriter
{
public:
virtual const char* className() const { return "PNG Image Reader/Writer"; }
virtual bool acceptsExtension(const std::string& extension) const { return osgDB::equalCaseInsensitive(extension,"png"); }
virtual ReadResult readImage(const std::string& file, const osgDB::ReaderWriter::Options* options) const
ReadResult readPNGStream(std::istream& fin) const
{
std::string ext = osgDB::getLowerCaseFileExtension(file);
if (!acceptsExtension(ext)) return ReadResult::FILE_NOT_HANDLED;
std::string fileName = osgDB::findDataFile( file, options );
if (fileName.empty()) return ReadResult::FILE_NOT_FOUND;
int trans = PNG_ALPHA;
FILE *fp = NULL;
pngInfo pInfo;
pngInfo *pinfo = &pInfo;
@@ -65,9 +64,9 @@ class ReaderWriterPNG : public osgDB::ReaderWriter
info = png_create_info_struct(png);
endinfo = png_create_info_struct(png);
fp = fopen(fileName.c_str(), "rb");
if (fp && fread(header, 1, 8, fp) && png_check_sig(header, 8))
png_init_io(png, fp);
fin.read((char*)header,8);
if (fin.gcount() == 8 && png_check_sig(header, 8))
png_set_read_fn(png,&fin,png_read_istream); //Use custom read function that will get data from istream
else
{
png_destroy_read_struct(&png, &info, &endinfo);
@@ -180,15 +179,11 @@ class ReaderWriterPNG : public osgDB::ReaderWriter
// delete [] data;
if (fp)
fclose(fp);
if (pixelFormat==0)
return ReadResult::FILE_NOT_HANDLED;
osg::Image* pOsgImage = new osg::Image();
pOsgImage->setFileName(fileName.c_str());
pOsgImage->setImage(width, height, 1,
internalFormat,
pixelFormat,
@@ -198,6 +193,26 @@ class ReaderWriterPNG : public osgDB::ReaderWriter
return pOsgImage;
}
virtual ReadResult readImage(std::istream& fin,const Options* =NULL) const
{
return readPNGStream(fin);
}
virtual ReadResult readImage(const std::string& file, const osgDB::ReaderWriter::Options* options) const
{
std::string ext = osgDB::getLowerCaseFileExtension(file);
if (!acceptsExtension(ext)) return ReadResult::FILE_NOT_HANDLED;
std::string fileName = osgDB::findDataFile( file, options );
if (fileName.empty()) return ReadResult::FILE_NOT_FOUND;
std::ifstream istream(fileName.c_str(), std::ios::in | std::ios::binary);
if(!istream) return ReadResult::FILE_NOT_HANDLED;
ReadResult rr = readPNGStream(istream);
if(rr.validImage()) rr.getImage()->setFileName(file);
return rr;
}
};
// now register with Registry to instantiate the above

View File

@@ -243,12 +243,11 @@ const int rleEntrySize)
unsigned char *
simage_tga_load(const char *filename,
simage_tga_load(std::istream& fin,
int *width_ret,
int *height_ret,
int *numComponents_ret)
{
FILE * fp;
unsigned char header[18];
int type;
int width;
@@ -269,17 +268,10 @@ int *numComponents_ret)
tgaerror = ERR_NO_ERROR; /* clear error */
fp = fopen(filename, "rb");
if (!fp)
{
tgaerror = ERR_OPEN;
return NULL;
}
if (fread(header, 1, 18, fp) != 18)
fin.read((char*)header,18);
if (fin.gcount() != 18)
{
tgaerror = ERR_READ;
fclose(fp);
return NULL;
}
@@ -296,12 +288,11 @@ int *numComponents_ret)
(depth < 2 || depth > 4))
{
tgaerror = ERR_UNSUPPORTED;
fclose(fp);
return NULL;
}
if (header[0]) /* skip identification field */
fseek(fp, header[0], SEEK_CUR);
fin.seekg(header[0],std::ios::cur);
colormap = NULL;
if (header[1] == 1) /* there is a colormap */
@@ -309,7 +300,7 @@ int *numComponents_ret)
int len = getInt16(&header[5]);
indexsize = header[7]>>3;
colormap = new unsigned char [len*indexsize];
fread(colormap, 1, len*indexsize, fp);
fin.read((char*)colormap,len*indexsize);
}
if (depth == 2) /* 16 bits */
@@ -353,7 +344,8 @@ int *numComponents_ret)
int x, y;
for (y = 0; y < height; y++)
{
if (fread(linebuf, 1, width*depth, fp) != (unsigned int)width*depth)
fin.read((char*)linebuf,width*depth);
if (fin.gcount() != (unsigned int)width*depth)
{
tgaerror = ERR_READ;
break;
@@ -380,10 +372,10 @@ int *numComponents_ret)
int size, x, y;
unsigned char *buf;
unsigned char *src;
int pos = ftell(fp);
fseek(fp, 0, SEEK_END);
size = ftell(fp) - pos;
fseek(fp, pos, SEEK_SET);
int pos = fin.tellg();
fin.seekg(0,std::ios::end);
size = (int)fin.tellg() - pos;
fin.seekg(pos,std::ios::beg);
buf = new unsigned char [size];
if (buf == NULL)
{
@@ -391,7 +383,8 @@ int *numComponents_ret)
break;
}
src = buf;
if (fread(buf, 1, size, fp) != (unsigned int) size)
fin.read((char*)buf,size);
if (fin.gcount() != (unsigned int) size)
{
tgaerror = ERR_READ;
break;
@@ -415,7 +408,6 @@ int *numComponents_ret)
}
if (linebuf) delete [] linebuf;
fclose(fp);
if (tgaerror)
{
@@ -478,20 +470,14 @@ class ReaderWriterTGA : public osgDB::ReaderWriter
virtual const char* className() const { return "TGA Image Reader"; }
virtual bool acceptsExtension(const std::string& extension) const { return osgDB::equalCaseInsensitive(extension,"tga"); }
virtual ReadResult readImage(const std::string& file, const osgDB::ReaderWriter::Options* options) const
ReadResult readTGAStream(std::istream& fin) const
{
std::string ext = osgDB::getLowerCaseFileExtension(file);
if (!acceptsExtension(ext)) return ReadResult::FILE_NOT_HANDLED;
std::string fileName = osgDB::findDataFile( file, options );
if (fileName.empty()) return ReadResult::FILE_NOT_FOUND;
unsigned char *imageData = NULL;
int width_ret;
int height_ret;
int numComponents_ret;
imageData = simage_tga_load(fileName.c_str(),&width_ret,&height_ret,&numComponents_ret);
imageData = simage_tga_load(fin,&width_ret,&height_ret,&numComponents_ret);
if (imageData==NULL) return ReadResult::FILE_NOT_HANDLED;
@@ -510,7 +496,6 @@ class ReaderWriterTGA : public osgDB::ReaderWriter
unsigned int dataType = GL_UNSIGNED_BYTE;
osg::Image* pOsgImage = new osg::Image;
pOsgImage->setFileName(fileName.c_str());
pOsgImage->setImage(s,t,r,
internalFormat,
pixelFormat,
@@ -521,6 +506,26 @@ class ReaderWriterTGA : public osgDB::ReaderWriter
return pOsgImage;
}
virtual ReadResult readImage(std::istream& fin,const Options* =NULL) const
{
return readTGAStream(fin);
}
virtual ReadResult readImage(const std::string& file, const osgDB::ReaderWriter::Options* options) const
{
std::string ext = osgDB::getLowerCaseFileExtension(file);
if (!acceptsExtension(ext)) return ReadResult::FILE_NOT_HANDLED;
std::string fileName = osgDB::findDataFile( file, options );
if (fileName.empty()) return ReadResult::FILE_NOT_FOUND;
std::ifstream istream(fileName.c_str(), std::ios::in | std::ios::binary);
if(!istream) return ReadResult::FILE_NOT_HANDLED;
ReadResult rr = readTGAStream(istream);
if(rr.validImage()) rr.getImage()->setFileName(file);
return rr;
}
};
// now register with Registry to instantiate the above