您的位置:首页 > 其它

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

2008-05-03 20:37 519 查看
这次来讨论一下图片的基类LLImageBase,从前一篇里已经看到它的继承关系,仅在引用类LLThreadSafeRefCount之后,而在JPEG2000和TGA类之前。那么为什么需要设计有这个基类LLImageBase呢?这个得从面向对象来说起,由于JPEG2000和TGA都有共同的图像属性,那么就需要一个公共的基类,这样达到代码复用,减少代码编写和维护。下面仔细查看这个类的声明:
#001 class LLImageBase : public LLThreadSafeRefCount
#002 {
#003 protected:
#004 virtual ~LLImageBase();
#005
#006 public:
#007 LLImageBase();
#008

图片的类型。
#009 enum
#010 {
#011 TYPE_NORMAL = 0,
#012 TYPE_***ATAR_BAKE = 1,
#013 };
#014

删除不用的数据和分配内存空间。
#015 virtual void deleteData();
#016 virtual U8* allocateData(S32 size = -1);
#017 virtual U8* reallocateData(S32 size = -1);
#018
#019 virtual void dump();
#020 virtual void sanityCheck();
#021

获取图片的宽度和高度。
#022 U16 getWidth() const { return mWidth; }
#023 U16 getHeight() const { return mHeight; }

获取每个图像元素有几个字节组成。
#024 S8 getComponents() const { return mComponents; }

获取图片数据区的大小。
#025 S32 getDataSize() const { return mDataSize; }
#026

获取图片数据。
#027 const U8 *getData() const { return mData; } // read only
#028 U8 *getData() { return mData; }
#029

设置图片结构属性。
#030 void setSize(S32 width, S32 height, S32 ncomponents);
#031 U8* allocateDataSize(S32 width, S32 height, S32 ncomponents, S32 size = -1); // setSize() + allocateData()
#032
#033 protected:
#034 // special accessor to allow direct setting of mData and mDataSize by LLImageFormatted
#035 void setDataAndSize(U8 *data, S32 size) { mData = data; mDataSize = size; };
#036
#037 public:
#038 static const LLString& getLastError() {return sLastErrorMessage;};
#039 static void resetLastError() {sLastErrorMessage = LLString("No Error"); };
#040 static BOOL setLastError(const LLString& message, const LLString& filename = LLString()); // returns FALSE
#041

生成不同分辨率的MIP纹理图片。
#042 static void generateMip(const U8 *indata, U8* mipdata, int width, int height, S32 nchannels);
#043
#044 // Function for calculating the download priority for textures
#045 // <= 0 priority means that there's no need for more data.
#046 static F32 calc_download_priority(F32 virtual_size, F32 visible_area, S32 bytes_sent);
#047
#048 static void setSizeOverride(BOOL enabled) { sSizeOverride = enabled; }
#049

下面就是公共的成员数据。
#050 private:
#051 U8 *mData;
#052 S32 mDataSize;
#053
#054 U16 mWidth;
#055 U16 mHeight;
#056
#057 S8 mComponents;
#058
#059 public:
#060 S16 mMemType; // debug
#061
#062 static LLString sLastErrorMessage;
#063
#064 static BOOL sSizeOverride;
#065 };

从上面的类声明可以看到都是图片公共的属性,比保存图片数据的内存空间,图片的高度和宽度,还有每个图像元素的大小等等。最重要的一个函数是generateMip函数,它主要用来从一个图片生成不同的MIP图片,这样让纹理在不同大小的情况下不会让贴图失真。它的实现代码如下:
#001 //static
#002 void LLImageBase::generateMip(const U8* indata, U8* mipdata, S32 width, S32 height, S32 nchannels)
#003 {
#004 llassert(width > 0 && height > 0);
#005 U8* data = mipdata;
#006 S32 in_width = width*2;
#007 for (S32 h=0; h<height; h++)
#008 {
#009 for (S32 w=0; w<width; w++)
#010 {
#011 switch(nchannels)
#012 {
#013 case 4:
#014 avg4_colors4(indata, indata+4, indata+4*in_width, indata+4*in_width+4, data);
#015 break;
#016 case 3:
#017 avg4_colors3(indata, indata+3, indata+3*in_width, indata+3*in_width+3, data);
#018 break;
#019 case 2:
#020 avg4_colors2(indata, indata+2, indata+2*in_width, indata+2*in_width+2, data);
#021 break;
#022 case 1:
#023 *(U8*)data = (U8)(((U32)(indata[0]) + indata[1] + indata[in_width] + indata[in_width+1])>>2);
#024 break;
#025 default:
#026 llerrs << "generateMmip called with bad num channels" << llendl;
#027 }
#028 indata += nchannels*2;
#029 data += nchannels;
#030 }
#031 indata += nchannels*in_width; // skip odd lines
#032 }
#033 }

avg4_colors4函数实现从16个数据组合成4个数据,avg4_colors3函数实现从9个数据组合成3个数据、avg4_colors2函数实现从4个数据组合成2个数据,还有当是两个数据时变成一个数据,这样就是进行数据重采样的操作,让失真变化得最小。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐