📄 readerwritergif.cpp
字号:
cmentry = colormap ? &colormap->Colors[col] : NULL; if (cmentry) { *ptr++ = cmentry->Red; *ptr++ = cmentry->Green; *ptr++ = cmentry->Blue; } else { *ptr++ = col; *ptr++ = col; *ptr++ = col; } } *ptr++ = (col == transparent ? 0x00 : 0xff); }}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(std::istream& fin,int *width_ret,int *height_ret,int *numComponents_ret,GifImageStream** obj){ int i, j, n, row, col, width, height, extcode; unsigned char * rowdata; unsigned char * buffer, * ptr; unsigned char bg; int transparent, delaytime; GifRecordType recordtype; GifByteType * extension; GifFileType * giffile; GifColorType * bgcol; /* The way an interlaced image should be read - offsets and jumps */ int interlacedoffset[] = { 0, 4, 2, 1 }; int interlacedjumps[] = { 8, 8, 4, 2 }; giffile = DGifOpen(&fin,gif_read_stream); if (!giffile) { giferror = ERR_OPEN; return NULL; } transparent = -1; /* no transparent color by default */ delaytime = 8; /* delay time of a frame */ n = giffile->SHeight * giffile->SWidth; buffer = new unsigned char [n * 4]; if (!buffer) { giferror = ERR_MEM; return NULL; } rowdata = new unsigned char [giffile->SWidth]; if (!rowdata) { giferror = ERR_MEM; delete [] buffer; return NULL; } bg = giffile->SBackGroundColor; if (giffile->SColorMap && bg < giffile->SColorMap->ColorCount) { bgcol = &giffile->SColorMap->Colors[bg]; } else bgcol = NULL; ptr = buffer; for (i = 0; i < n; i++) { if (bgcol) { *ptr++ = bgcol->Red; *ptr++ = bgcol->Green; *ptr++ = bgcol->Blue; *ptr++ = 0xff; } else { *ptr++ = 0x00; *ptr++ = 0x00; *ptr++ = 0x00; *ptr++ = 0xff; } } /* Scan the content of the GIF file and load the image(s) in: */ int gif_num=0; do { if (DGifGetRecordType(giffile, &recordtype) == GIF_ERROR) { giferror = ERR_READ; delete [] buffer; delete [] rowdata; return NULL; } switch (recordtype) { case IMAGE_DESC_RECORD_TYPE: /* start recording image stream if more than one image found */ gif_num++; if ( gif_num==2 ) { *obj = new GifImageStream; (*obj)->addToImageStream( giffile->SWidth, giffile->SHeight, 1, 4, delaytime, buffer ); unsigned char* destbuffer = new unsigned char [n * 4]; buffer = (unsigned char*)memcpy( destbuffer, buffer, n*4 ); } if (DGifGetImageDesc(giffile) == GIF_ERROR) { giferror = ERR_READ; delete [] buffer; delete [] rowdata; return NULL; } /* subimage position in composite image */ row = giffile->Image.Top; col = giffile->Image.Left; width = giffile->Image.Width; height = giffile->Image.Height; if (giffile->Image.Left + giffile->Image.Width > giffile->SWidth || giffile->Image.Top + giffile->Image.Height > giffile->SHeight) { /* image is not confined to screen dimension */ giferror = ERR_READ; delete [] buffer; delete [] rowdata; return NULL; } if (giffile->Image.Interlace) { //fprintf(stderr,"interlace\n"); /* Need to perform 4 passes on the images: */ for (i = 0; i < 4; i++) { for (j = row + interlacedoffset[i]; j < row + height; j += interlacedjumps[i]) { if (DGifGetLine(giffile, rowdata, width) == GIF_ERROR) { giferror = ERR_READ; delete [] buffer; delete [] rowdata; return NULL; } else decode_row(giffile, buffer, rowdata, col, j, width, transparent); } } } else { for (i = 0; i < height; i++, row++) { if (DGifGetLine(giffile, rowdata, width) == GIF_ERROR) { giferror = ERR_READ; delete [] buffer; delete [] rowdata; return NULL; } else decode_row(giffile, buffer, rowdata, col, row, width, transparent); } } // Record gif image stream if ( *obj && obj ) { (*obj)->addToImageStream( giffile->SWidth, giffile->SHeight, 1, 4, delaytime, buffer ); unsigned char* destbuffer = new unsigned char [n * 4]; buffer = (unsigned char*)memcpy( destbuffer, buffer, n*4 ); } break; case EXTENSION_RECORD_TYPE: /* Skip any extension blocks in file: */ if (DGifGetExtension(giffile, &extcode, &extension) == GIF_ERROR) { giferror = ERR_READ; delete [] buffer; delete [] rowdata; return NULL; } /* transparent test from the gimp gif-plugin. Open Source rulez! */ else if (extcode == 0xf9) { if (extension[0] >= 4 && extension[1] & 0x1) transparent = extension[4]; else transparent = -1; delaytime = (extension[3]<<8)+extension[2]; // minimum unit 1/100s, so 8 here means 8/100s } while (extension != NULL) { if (DGifGetExtensionNext(giffile, &extension) == GIF_ERROR) { giferror = ERR_READ; delete [] buffer; delete [] rowdata; return NULL; } } break; case TERMINATE_RECORD_TYPE: break; default: /* Should be trapped by DGifGetRecordType. */ break; } } while (recordtype != TERMINATE_RECORD_TYPE); delete [] rowdata; *width_ret = giffile->SWidth; *height_ret = giffile->SHeight; *numComponents_ret = 4; DGifCloseFile(giffile); return buffer;}class ReaderWriterGIF : public osgDB::ReaderWriter{ public: ReaderWriterGIF() { supportsExtension("gif","GIF Image format"); } virtual const char* className() const { return "GIF Image Reader"; } ReadResult readGIFStream(std::istream& fin) const { unsigned char *imageData = NULL; int width_ret; int height_ret; int numComponents_ret; GifImageStream* gifStream = NULL; imageData = simage_gif_load( fin,&width_ret,&height_ret,&numComponents_ret, &gifStream ); switch (giferror) { case ERR_OPEN: return ReadResult("GIF loader: Error opening file"); case ERR_READ: return ReadResult("GIF loader: Error reading file"); case ERR_MEM: return ReadResult("GIF loader: Out of memory error"); } // Use GifImageStream to display animate GIFs if ( gifStream ) { osg::notify(osg::DEBUG_INFO)<<"Using GifImageStream ..."<<std::endl; return gifStream; } if (imageData==NULL) return ReadResult::FILE_NOT_HANDLED; int s = width_ret; int t = height_ret; int r = 1; int internalFormat = numComponents_ret; unsigned int pixelFormat = numComponents_ret == 1 ? GL_LUMINANCE : numComponents_ret == 2 ? GL_LUMINANCE_ALPHA : numComponents_ret == 3 ? GL_RGB : numComponents_ret == 4 ? GL_RGBA : (GLenum)-1; unsigned int dataType = GL_UNSIGNED_BYTE; osg::Image* pOsgImage = new osg::Image; pOsgImage->setImage(s,t,r, internalFormat, pixelFormat, dataType, imageData, osg::Image::USE_NEW_DELETE); return pOsgImage; } virtual ReadResult readObject(std::istream& fin,const osgDB::ReaderWriter::Options* options =NULL) const { return readImage(fin, options); } virtual ReadResult readObject(const std::string& file, const osgDB::ReaderWriter::Options* options =NULL) const { return readImage(file, options); } 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; }};// now register with Registry to instantiate the above// reader/writer.REGISTER_OSGPLUGIN(gif, ReaderWriterGIF)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -