📄 readerwritergif.cpp
字号:
#include <osg/Image>#include <osg/ImageStream>#include <osg/Notify>#include <osg/Geode>#include <osg/GL>#include <osgDB/FileNameUtils>#include <osgDB/FileUtils>#include <osgDB/Registry>#include <OpenThreads/Thread>/**************************************************************************** * * Follows is code extracted from the simage library. Original Authors: * * Systems in Motion, * <URL:http://www.sim.no> * * Peder Blekken <pederb@sim.no> * Morten Eriksen <mortene@sim.no> * Marius Bugge Monsen <mariusbu@sim.no> * * The original COPYING notice * * All files in this library are public domain, except simage_rgb.cpp which is * Copyright (c) Mark J Kilgard <mjk@nvidia.com>. I will contact Mark * very soon to hear if this source also can become public domain. * * Please send patches for bugs and new features to: <pederb@sim.no>. * * Peder Blekken * * * Ported into the OSG as a plugin, Robert Osfield Decemeber 2000. * Note, reference above to license of simage_rgb is not relevent to the OSG * as the OSG does not use it. Also for patches, bugs and new features * please send them direct to the OSG dev team rather than address above. * **********************************************************************//*! GIF loader, using libungif Based, in part, on source code found in libungif, gif2rgb.c*/#include <stdlib.h>#include <string.h>#include <stdio.h>extern "C"{ #include <gif_lib.h>}#define ERR_NO_ERROR 0#define ERR_OPEN 1#define ERR_READ 2#define ERR_MEM 3#define MY_GIF_DEBUG 1// GifImageStream class class GifImageStream : public osg::ImageStream, public OpenThreads::Thread{public: GifImageStream() : _length(0), _dataNum(0), _frameNum(0), _done(false), _currentLength(0), _multiplier(1.0), osg::ImageStream() { _status=PAUSED; } virtual Object* clone() const { return new GifImageStream; } virtual bool isSameKindAs( const Object* obj ) const { return dynamic_cast<const GifImageStream*>(obj) != NULL; } virtual const char* className() const { return "GifImageStream"; } virtual void play() { if (!isRunning()) start(); _status=PLAYING; } virtual void pause() { _status=PAUSED; } virtual void rewind() { setReferenceTime( 0.0 ); } virtual void quit( bool waitForThreadToExit=true ) { _done = true; if ( waitForThreadToExit ) { while( isRunning() ) OpenThreads::Thread::YieldCurrentThread(); osg::notify(osg::DEBUG_INFO)<<"GifImageStream thread quitted"<<std::endl; } } StreamStatus getStatus() { return _status; } virtual double getLength() const { return _length*0.01*_multiplier; } // Go to a specific position of stream virtual void setReferenceTime( double time ) { OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_mutex); int i=1; int framePos = static_cast<int>(time*100.0/_multiplier); if ( framePos>=(int)_length ) framePos = _length; std::vector<FrameData*>::iterator it; for ( it=_dataList.begin(); it!=_dataList.end(); it++,i++ ) { framePos -= (*it)->delay; if ( framePos<0 ) break; } _dataNum = i-1; _frameNum = (*it)->delay+framePos; setNewImage(); } virtual double getReferenceTime() const { return _currentLength*0.01*_multiplier; } // Speed up, slow down or back to normal (1.0) virtual void setTimeMultiplier( double m ) { OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_mutex); if ( m>0 ) _multiplier = m; } virtual double getTimeMultiplier() const { return _multiplier; } // Not used in GIF animation virtual void setVolume(float) {} virtual float getVolume() const { return 0.0f; } virtual void run() { _dataIter = _dataList.begin(); while ( !_done ) { if ( _status==PLAYING && (*_dataIter) ) { if ( _frameNum>=(*_dataIter)->delay ) { _frameNum = 0; if ( _dataNum>=_dataList.size()-1 ) { if ( getLoopingMode()==LOOPING ) { _dataNum = 0; _currentLength = 0; } } else _dataNum++; setNewImage(); } else { _frameNum++; _currentLength++; } OpenThreads::Thread::microSleep(static_cast<int>(10000.0f*_multiplier)); } else OpenThreads::Thread::microSleep(150000L); } } void addToImageStream( int ss, int tt, int rr, int numComponents, int delayTime, unsigned char* imgData ) { if ( isRunning() ) { osg::notify(osg::WARN)<<"GifImageStream::addToImageStream: thread is running!"<<std::endl; return; } _s = ss; _t = tt; _r = rr; _internalFormat = numComponents; _dataType = GL_UNSIGNED_BYTE; _pixelFormat = numComponents == 1 ? GL_LUMINANCE : numComponents == 2 ? GL_LUMINANCE_ALPHA : numComponents == 3 ? GL_RGB : numComponents == 4 ? GL_RGBA : (GLenum)-1; if ( _dataList.empty() ) { // Set image texture for the first time setImage(_s,_t,_r,_internalFormat,_pixelFormat,_dataType, imgData,osg::Image::NO_DELETE,1); } FrameData* newData = new FrameData; newData->delay = delayTime; newData->data = imgData; _dataList.push_back( newData ); _length += delayTime; }protected: typedef struct { unsigned int delay; unsigned char* data; } FrameData; void setNewImage() { _dataIter = _dataList.begin()+_dataNum; if ( *_dataIter ) { unsigned char* image = (*_dataIter)->data; setImage(_s,_t,_r,_internalFormat,_pixelFormat,_dataType, image,osg::Image::NO_DELETE,1); dirty(); } } virtual ~GifImageStream() { if( isRunning() ) quit( true ); std::vector<FrameData*>::iterator it; for ( it=_dataList.begin(); it!=_dataList.end(); it++ ) { delete (*it)->data; delete (*it); } } double _multiplier; unsigned int _currentLength; unsigned int _length; unsigned int _frameNum; unsigned int _dataNum; std::vector<FrameData*> _dataList; std::vector<FrameData*>::iterator _dataIter; int _s; int _t; int _r; int _internalFormat; unsigned int _pixelFormat; unsigned int _dataType; bool _done; OpenThreads::Mutex _mutex;};static int giferror = ERR_NO_ERROR;intsimage_gif_error(char * buffer, int buflen){ switch (giferror) { case ERR_OPEN: strncpy(buffer, "GIF loader: Error opening file", buflen); break; case ERR_READ: strncpy(buffer, "GIF loader: Error reading file", buflen); break; case ERR_MEM: strncpy(buffer, "GIF loader: Out of memory error", buflen); break; } return giferror;}intsimage_gif_identify(const char *,const unsigned char *header,int headerlen){ static unsigned char gifcmp[] = {'G', 'I', 'F'}; if (headerlen < 3) return 0; if (memcmp((const void*)header, (const void*)gifcmp, 3) == 0) return 1; return 0;}static voiddecode_row(GifFileType * giffile,unsigned char * buffer,unsigned char * rowdata,int x, int y, int len,int transparent){ GifColorType * cmentry; ColorMapObject * colormap; int colormapsize; unsigned char col; unsigned char * ptr; y = giffile->SHeight - (y+1); ptr = buffer + (giffile->SWidth * y + x) * 4; colormap = (giffile->Image.ColorMap ? giffile->Image.ColorMap : giffile->SColorMap); colormapsize = colormap ? colormap->ColorCount : 255; while (len--) { col = *rowdata++; /* just in case */ if (col >= colormapsize) col = 0; if ( col == transparent ) { // keep pixels of last image if transparent mode is on // this is necessary for GIF animating ptr += 3; } else {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -