目前网络带宽比起以前是快了很多,但对于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的动态库等内容。