[原][osg]分析JPEG插件的读取写入

本文为了分析osg插件的内部实现,举了一个ReaderWriterJPEG插件的例子进行分析,本文代码全为C++代码

osg通过插件的方式读取写入文件

用osg的jpeg插件举例

文件OSGsrcosgPluginsjpegReaderWriterJPEG.cpp 中定义了类:

class ReaderWriterJPEG : public osgDB::ReaderWriter

一、插件读取部分

在virtual ReadResult readImage(const std::string& file, const osgDB::ReaderWriter::Options* options) const函数中

1.首先将文件以二进制流的方式读取进来

osgDB::ifstream istream(fileName.c_str(), std::ios::in | std::ios::binary);

2.然后再将二进制流通过算法解析成读取结果:ReadResult

ReadResult rr = readJPGStream(istream);

那这个ReadResult是个什么东西,这个要怎么用,我们来分析一下这个类

osgDB/ReaderWriter 头文件中

声明并定义了osgDB::ReaderWriter类

在这个类中声明并定义了ReadResult类

 1 class OSGDB_EXPORT ReadResult
 2         {
 3             public:
 4 
 5                 enum ReadStatus
 6                 {
 7                     NOT_IMPLEMENTED, //!< read*() method not implemented in concrete ReaderWriter.
 8                     FILE_NOT_HANDLED, //!< File is not appropriate for this file reader, due to some incompatibility, but *not* a read error.
 9                     FILE_NOT_FOUND, //!< File could not be found or could not be read.
10                     ERROR_IN_READING_FILE, //!< File found, loaded, but an error was encountered during processing.
11                     FILE_LOADED, //!< File successfully found, loaded, and converted into osg.
12                     FILE_LOADED_FROM_CACHE, //!< File found in cache and returned.
13                     FILE_REQUESTED, //!< Asynchronous file read has been requested, but returning immediately, keep polling plugin until file read has been completed.
14                     INSUFFICIENT_MEMORY_TO_LOAD //!< File found but not loaded because estimated required memory surpasses available memory.
15                 };
16 
17                 ReadResult(ReadStatus status=FILE_NOT_HANDLED):_status(status) {}
18                 ReadResult(const std::string& m):_status(ERROR_IN_READING_FILE),_message(m) {}
19 
20                 ReadResult(osg::Object* obj, ReadStatus status=FILE_LOADED):_status(status),_object(obj) {}
21 
22                 template<class T>
23                 ReadResult(const osg::ref_ptr<T>& obj, ReadStatus status=FILE_LOADED):_status(status),_object(obj.get()) {}
24 
25                 ReadResult(const ReadResult& rr):_status(rr._status),_message(rr._message),_object(rr._object) {}
26                 ReadResult& operator = (const ReadResult& rr) { if (this==&rr) return *this; _status=rr._status; _message=rr._message;_object=rr._object; return *this; }
27 
28                 bool operator < (const ReadResult& rhs) const { return _status < rhs._status; }
29 
30                 osg::Object* getObject();
31                 osg::Image* getImage();
32                 osg::HeightField* getHeightField();
33                 osg::Node* getNode();
34                 osgDB::Archive* getArchive();
35                 osg::Shader* getShader();
36                 osg::Script* getScript();
37 
38                 bool validObject() { return _object.valid(); }
39                 bool validImage() { return getImage()!=0; }
40                 bool validHeightField() { return getHeightField()!=0; }
41                 bool validNode() { return getNode()!=0; }
42                 bool validArchive() { return getArchive()!=0; }
43                 bool validShader() { return getShader()!=0; }
44                 bool validScript() { return getScript()!=0; }
45 
46                 osg::Object* takeObject();
47                 osg::Image* takeImage();
48                 osg::HeightField* takeHeightField();
49                 osg::Node* takeNode();
50                 osgDB::Archive* takeArchive();
51                 osg::Shader* takeShader();
52                 osg::Script* takeScript();
53 
54                 std::string& message() { return _message; }
55                 const std::string& message() const { return _message; }
56 
57                 ReadStatus status() const { return _status; }
58                 bool success() const { return _status==FILE_LOADED || _status==FILE_LOADED_FROM_CACHE ; }
59                 bool loadedFromCache() const { return _status==FILE_LOADED_FROM_CACHE; }
60                 bool error() const { return _status==ERROR_IN_READING_FILE; }
61                 bool notHandled() const { return _status==FILE_NOT_HANDLED || _status==NOT_IMPLEMENTED; }
62                 bool notFound() const { return _status==FILE_NOT_FOUND; }
63                 bool notEnoughMemory() const { return _status==INSUFFICIENT_MEMORY_TO_LOAD; }
64 
65             protected:
66 
67                 ReadStatus                  _status;
68                 std::string                 _message;
69                 osg::ref_ptr<osg::Object>   _object;
70 
71         };

这个ReadResult支持osg读取多种类型的数据,有7种类型:目标物、图片、高度场、节点、文档、着色器、脚本。

1                 osg::Object* getObject();
2                 osg::Image* getImage();
3                 osg::HeightField* getHeightField();
4                 osg::Node* getNode();
5                 osgDB::Archive* getArchive();
6                 osg::Shader* getShader();
7                 osg::Script* getScript();

接口定义:

1 osg::Object* ReaderWriter::ReadResult::getObject() { return _object.get(); }
2 osg::Image* ReaderWriter::ReadResult::getImage() { return dynamic_cast<osg::Image*>(_object.get()); }
3 osg::HeightField* ReaderWriter::ReadResult::getHeightField() { return dynamic_cast<osg::HeightField*>(_object.get()); }
4 osg::Node* ReaderWriter::ReadResult::getNode() { return dynamic_cast<osg::Node*>(_object.get()); }
5 osgDB::Archive* ReaderWriter::ReadResult::getArchive() { return dynamic_cast<osgDB::Archive*>(_object.get()); }
6 osg::Shader* ReaderWriter::ReadResult::getShader() { return dynamic_cast<osg::Shader*>(_object.get()); }
7 osg::Script* ReaderWriter::ReadResult::getScript() { return dynamic_cast<osg::Script*>(_object.get()); }
View Code

通过接口定义可以看到这里所有类型都是由osg::Object指针强转过来的,所以ReadResult即可支持了需要读取的所有类型。

读取的函数readJPGStream需要实现的其实就是将数据流std::ifstream转成对应的osg::Image数据。

二、插件写入部分

 在 virtual WriteResult writeImage(const osg::Image &img,const std::string& fileName, const osgDB::ReaderWriter::Options *options) const

1.先将文件输出流打开

osgDB::ofstream fout(fileName.c_str(), std::ios::out | std::ios::binary);

2.将数据写入数据流

WriteResult::WriteStatus ws = write_JPEG_file(fout, *(tmp_img.get()), getQuality(options));

这个写入结果WriteResult就简单很多,它不关心写入的数据类型,只关注写入成功与否,这里不用去仔细分析。

这里的write_JPEG_file函数就完成了,从osg::Image到数据流std::ofstream的转换

备注:

osgDB下面的两个流就是调用std的fstream

class OSGDB_EXPORT ifstream : public std::ifstream

class OSGDB_EXPORT ofstream : public std::ofstream

readJPGStreamwrite_JPEG_file里面的实现除了osg::Image的转换,调用的都是jpeg的第三方库进行操作,这里不去分析。

原文地址:https://www.cnblogs.com/lyggqm/p/14272604.html