第二人生的源码分析(五十三) 纹理图片的格式之LLImageJ2C类

来源:互联网 发布:使命召唤9剧情分支知乎 编辑:程序博客网 时间:2024/05/22 13:51
目前网络带宽比起以前是快了很多,但对于3D这样大型程序来说,还是远远不够的。特别像第二人生这样逼真的画面,需要实时传送更多真实细节的图片,既然网络的带宽不够,又需要显示这么逼真的画面,那么只有采用更加先进的技术了。在这里就介绍一下第二人生采用比较新的JPEG2000图片格式。
它的类声明如下:
#001 class LLImageJ2C : public LLImageFormatted
#002 {
#003 protected:
#004      virtual ~LLImageJ2C();
#005 
#006 public:
#007      LLImageJ2C();
#008 
#009      // Base class overrides
 
更新图像的数据。
#010      /*virtual*/ BOOL updateData();
 
下面进行数据解码,也就是变换为RAW的格式。
#011      /*virtual*/ BOOL decode(LLImageRaw *raw_imagep, F32 decode_time=0.0);
#012      /*virtual*/ BOOL decode(LLImageRaw *raw_imagep, F32 decode_time, S32 first_channel, S32 max_channel_count);
 
下面从RAW的格式变换为JPEG2000的格式,也就是压缩数据。
#013      /*virtual*/ BOOL encode(const LLImageRaw *raw_imagep, F32 encode_time=0.0);
 
计算需要内存空间。
#014      /*virtual*/ S32 calcHeaderSize();
#015      /*virtual*/ S32 calcDataSize(S32 discard_level = 0);
#016      /*virtual*/ S32 calcDiscardLevelBytes(S32 bytes);
#017      /*virtual*/ S8 getRawDiscardLevel();
#018     
 
下面添加注释的压缩方式。
#019      // Encode with comment text
#020      BOOL encode(const LLImageRaw *raw_imagep, const char* comment_text, F32 encode_time=0.0);
#021 
 
下面检查数据是否有效。
#022      BOOL validate(U8 *data, U32 file_size);
 
下面是加载JPEG2000的文件。
#023      BOOL loadAndValidate(const LLString &filename);
#024 
#025      // Encode accessors
#026      void setReversible(const BOOL reversible); // Use non-lossy?
#027      void setRate(F32 rate);
#028      void setMaxBytes(S32 max_bytes);
#029      S32 getMaxBytes() const { return mMaxBytes; }
#030 
#031      static S32 calcHeaderSizeJ2C();
#032      static S32 calcDataSizeJ2C(S32 w, S32 h, S32 comp, S32 discard_level, F32 rate = 0.f);
#033 
 
下面使用DSO库来实现JPEG2000的数据压缩。
#034      static void openDSO();
#035      static void closeDSO();
#036      static std::string getEngineInfo();
#037     
#038 protected:
#039      friend class LLImageJ2CImpl;
#040      friend class LLImageJ2COJ;
#041      friend class LLImageJ2CKDU;
#042      void decodeFailed();
#043      void updateRawDiscardLevel();
#044 
#045      S32 mMaxBytes; // Maximum number of bytes of data to use...
#046      S8 mRawDiscardLevel;
#047       F32 mRate;
#048      BOOL mReversible;
 
下面保存JPEG2000实现压缩的对象。
#049      LLImageJ2CImpl *mImpl;
#050 };
#051 
 
通过这个类可以看到,实现JPEG2000的压缩并不是在这个类里,而是在LLImageJ2Cimpl实现类,这个类也是一个实现组合类,只是一个间接访问的模式。所有的数据压缩和解压,其实都是DSO的库里面,而这个DSO的接口是怎么样的呢?它是通过C++纯虚函数的二进制接口来实现的,现在就去看LLImageJ2Cimpl的声明,就可以知道这个接口是什么样了,它的声明如下:
#001 class LLImageJ2CImpl
#002 {
#003 public:
#004      virtual ~LLImageJ2CImpl();
#005 protected:
#006      // Find out the image size and number of channels.
#007      // Return value:
#008      // true: image size and number of channels was determined
#009      // false: error on decode
#010      virtual BOOL getMetadata(LLImageJ2C &base) = 0;
#011      // Decode the raw image optionally aborting (to continue later) after
#012      // decode_time seconds. Decode at most max_channel_count and start
#013      // decoding channel first_channel.
#014      // Return value:
#015      // true: decoding complete (even if it failed)
#016      // false: time expired while decoding
#017      virtual BOOL decodeImpl(LLImageJ2C &base, LLImageRaw &raw_image, F32 decode_time, S32 first_channel, S32 max_channel_count) = 0;
#018      virtual BOOL encodeImpl(LLImageJ2C &base, const LLImageRaw &raw_image, const char* comment_text, F32 encode_time=0.0,
#019                                                BOOL reversible=FALSE) = 0;
#020 
#021      friend class LLImageJ2C;
#022 };
 
在这个类声明只有三个接口函数getMetadata、decodeImpl和encodeImpl。getMetadata函数是获取图片数据的大小和多少个通道。
decodeImpl函数是把多个通道数据解码为RAW的格式。
encodeImpl函数是把RAW的格式数据压缩为JPEG2000的格式。
下一节再介绍怎么样加载JPEG2000的动态库等内容。
原创粉丝点击