CCTextureCache类源码分析(2)

CCTextureCache类源码分析(2):

在CCTextureCache类源码分析(1)中,我们分析了CCTextureCache如何实现
纹理缓存的,但是在分析的过程中,我们忽略了很多东西,比如CCImage类
如何加载纹理图片,这一篇我们分析一下CCImage:

源码分析:
    1、CCImage继承自CCObject
    2、成员变量,这些变量需要我们通过解析图片文件获得
	 unsigned char *m_pData; //图片数据
	 CC_SYNTHESIZE_READONLY(unsigned short,   m_nWidth,       Width); //宽高
	 CC_SYNTHESIZE_READONLY(unsigned short,   m_nHeight,      Height);
	 CC_SYNTHESIZE_READONLY(int,     m_nBitsPerComponent,   BitsPerComponent); //每个颜色分量的位数
	 bool m_bHasAlpha; //是否有alpha分量

    3、
    //对于.pvr 和 .pkm 图片格式文件需要特殊处理,后面分析
    if (std::string::npos != lowerCase.find(".pvr"))
    {
	texture = this->addPVRImage(fullpath.c_str());
    }
    else if (std::string::npos != lowerCase.find(".pkm"))
    {
	// ETC1 file format, only supportted on Android
	texture = this->addETCImage(fullpath.c_str());
    }
    else
    {
        //针对下面这些图片格式,我们需要使用CCImage类来读取
	//图片文件数据到内存中,并进行分析,因为每一种图片格式
	//文件对图片信息的存储方式是不同的,比如那几个字节存放图片的大小信息,
	//那些字节存放图片颜色信息,我们需要根据每种文件格式进行不同的分析处理,
	//从而得到我们需要的信息。
	//从这里也可以看出cocos2dx支持的图片格式:
	CCImage::EImageFormat eImageFormat = CCImage::kFmtUnKnown;
	if (std::string::npos != lowerCase.find(".png"))
	{
	    eImageFormat = CCImage::kFmtPng;
	}
	else if (std::string::npos != lowerCase.find(".jpg") || std::string::npos != lowerCase.find(".jpeg"))
	{
	    eImageFormat = CCImage::kFmtJpg;
	}
	else if (std::string::npos != lowerCase.find(".tif") || std::string::npos != lowerCase.find(".tiff"))
	{
	    eImageFormat = CCImage::kFmtTiff;
	}
	else if (std::string::npos != lowerCase.find(".webp"))
	{
	    eImageFormat = CCImage::kFmtWebp;
	}
	
	pImage = new CCImage();
	CC_BREAK_IF(NULL == pImage);

	bool bRet = pImage->initWithImageFile(fullpath.c_str(), eImageFormat);
	CC_BREAK_IF(!bRet);

----initWithImageFile---->>
strPath : 文件路径
eImgFmt :  图片格式
bool CCImage::initWithImageFile(const char * strPath, EImageFormat eImgFmt/* = eFmtPng*/)
{
    bool bRet = false;

#ifdef EMSCRIPTEN
    ....这部分就不管了
#else
    //读取图片的文件数据
    unsigned long nSize = 0;
    std::string fullPath = CCFileUtils::sharedFileUtils()->fullPathForFilename(strPath);
    unsigned char* pBuffer = CCFileUtils::sharedFileUtils()->getFileData(fullPath.c_str(), "rb", &nSize);
    if (pBuffer != NULL && nSize > 0)
    {
        bRet = initWithImageData(pBuffer, nSize, eImgFmt);
    }
    CC_SAFE_DELETE_ARRAY(pBuffer);
#endif // EMSCRIPTEN

    return bRet;
}

------initWithImageData------>>
bool CCImage::initWithImageData(void * pData, 
                                int nDataLen, 
                                EImageFormat eFmt/* = eSrcFmtPng*/, 
                                int nWidth/* = 0*/,
                                int nHeight/* = 0*/,
                                int nBitsPerComponent/* = 8*/)
{
    bool bRet = false;
    do 
    {
        CC_BREAK_IF(! pData || nDataLen <= 0);

	//根据图片文件格式,调用不同的解析函数
        if (kFmtPng == eFmt)
        {
            //对png图片进行解析,_initWithPngData函数里面调用png解析的库
	    //对png文件进行解析,然后得到我们所需的所有信息
            bRet = _initWithPngData(pData, nDataLen);
            break;
        }
        else if (kFmtJpg == eFmt)
        {
            bRet = _initWithJpgData(pData, nDataLen);
            break;
        }
        else if (kFmtTiff == eFmt)
        {
            bRet = _initWithTiffData(pData, nDataLen);
            break;
        }
#if (CC_TARGET_PLATFORM != CC_PLATFORM_WINRT) && (CC_TARGET_PLATFORM != CC_PLATFORM_WP8)
       else if (kFmtWebp == eFmt)
        {
            bRet = _initWithWebpData(pData, nDataLen);
            break;
        }
#endif
        else if (kFmtRawData == eFmt)
        {
            bRet = _initWithRawData(pData, nDataLen, nWidth, nHeight, nBitsPerComponent, false);
            break;
        }
        else
        {
            // if it is a png file buffer.
            if (nDataLen > 8)
            {
                unsigned char* pHead = (unsigned char*)pData;
                if (   pHead[0] == 0x89
                    && pHead[1] == 0x50
                    && pHead[2] == 0x4E
                    && pHead[3] == 0x47
                    && pHead[4] == 0x0D
                    && pHead[5] == 0x0A
                    && pHead[6] == 0x1A
                    && pHead[7] == 0x0A)
                {
                    bRet = _initWithPngData(pData, nDataLen);
                    break;
                }
            }

            // if it is a tiff file buffer.
            if (nDataLen > 2)
            {
                unsigned char* pHead = (unsigned char*)pData;
                if (  (pHead[0] == 0x49 && pHead[1] == 0x49)
                    || (pHead[0] == 0x4d && pHead[1] == 0x4d)
                    )
                {
                    bRet = _initWithTiffData(pData, nDataLen);
                    break;
                }
            }

            // if it is a jpeg file buffer.
            if (nDataLen > 2)
            {
                unsigned char* pHead = (unsigned char*)pData;
                if (   pHead[0] == 0xff
                    && pHead[1] == 0xd8)
                {
                    bRet = _initWithJpgData(pData, nDataLen);
                    break;
                }
            }
        }
    } while (0);
    return bRet;
}


总结:
CCImage所做的工作就是根据不同的图片格式调用不同的底层库,
如png,jpg解析库,通过这些库对图片文件进行分析,
从而得到我们所需要的所有信息,这里有个疑惑,就是通过底层库
解析图片文件之后得到的数据到底是什么格式存储的?
因为我在CCTextureCache类源码分析(1) 通过下面这行
// Convert "RRRRRRRRRGGGGGGGGBBBBBBBBAAAAAAAA" to "RRRRGGGGBBBBAAAA"  
猜测数据的存储都是每个颜色分量是8位,但是因为我对png这些图片的解析不熟悉,
所以在这里并没有很好的证据证明上面的猜测,所以把这个疑惑记录在此。

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。