cocos2d的资源压缩

2015年01月21日 09:25 0 点赞 0 评论 更新于 2017-05-09 13:07

本文主要介绍Cocos2d中图片的压缩算法。最近笔者刚好在研究这方面内容,因此贴出源代码供大家学习参考。

以下是CCTexture2D类中initPremultipliedATextureWithImage函数的实现代码,该函数用于根据传入的图片数据,将其转换为合适的像素格式并初始化纹理:

bool CCTexture2D::initPremultipliedATextureWithImage(CCImage *image, unsigned int width, unsigned int height)
{
// 获取图片数据
unsigned char* tempData = image->getData();
unsigned int* inPixel32 = NULL;
unsigned char* inPixel8 = NULL;
unsigned short* outPixel16 = NULL;

// 检查图片是否有Alpha通道
bool hasAlpha = image->hasAlpha();
// 获取图片的尺寸
CCSize imageSize = CCSizeMake((float)(image->getWidth()), (float)(image->getHeight()));
// 纹理的像素格式
CCTexture2DPixelFormat pixelFormat;
// 获取每个颜色分量的位数
size_t bpp = image->getBitsPerComponent();

// 计算像素格式
if (hasAlpha) {
// 如果有Alpha通道,使用默认的Alpha像素格式
pixelFormat = g_defaultAlphaPixelFormat;
} else {
if (bpp >= 8) {
// 如果每个颜色分量的位数大于等于8,使用RGB888格式
pixelFormat = kCCTexture2DPixelFormat_RGB888;
} else {
// 否则使用RGB565格式
pixelFormat = kCCTexture2DPixelFormat_RGB565;
}
}

// 重新打包像素数据到正确的格式
unsigned int length = width * height;

if (pixelFormat == kCCTexture2DPixelFormat_RGB565) {
if (hasAlpha) {
// 将 "RRRRRRRRRGGGGGGGGBBBBBBBBAAAAAAAA" 转换为 "RRRRRGGGGGGBBBBB"
tempData = new unsigned char[width * height * 2];
outPixel16 = (unsigned short*)tempData;
inPixel32 = (unsigned int*)image->getData();

for (unsigned int i = 0; i < length; ++i, ++inPixel32) {
*outPixel16++ =
(((*inPixel32 >>  0) & 0xFF) >> 3) << 11 |  // R
(((*inPixel32 >>  8) & 0xFF) >> 2) << 5  |  // G
(((*inPixel32 >> 16) & 0xFF) >> 3) << 0;    // B
}
} else {
// 将 "RRRRRRRRRGGGGGGGGBBBBBBBB" 转换为 "RRRRRGGGGGGBBBBB"
tempData = new unsigned char[width * height * 2];
outPixel16 = (unsigned short*)tempData;
inPixel8 = (unsigned char*)image->getData();

for (unsigned int i = 0; i < length; ++i) {
*outPixel16++ =
((*inPixel8++ & 0xFF) >> 3) << 11 |  // R
((*inPixel8++ & 0xFF) >> 2) << 5  |  // G
((*inPixel8++ & 0xFF) >> 3) << 0;    // B
}
}
} else if (pixelFormat == kCCTexture2DPixelFormat_RGBA4444) {
// 将 "RRRRRRRRRGGGGGGGGBBBBBBBBAAAAAAAA" 转换为 "RRRRGGGGBBBBAAAA"
inPixel32 = (unsigned int*)image->getData();
tempData = new unsigned char[width * height * 2];
outPixel16 = (unsigned short*)tempData;

for (unsigned int i = 0; i < length; ++i, ++inPixel32) {
*outPixel16++ =
(((*inPixel32 >> 0) & 0xFF) >> 4) << 12 | // R
(((*inPixel32 >> 8) & 0xFF) >> 4) <<  8 | // G
(((*inPixel32 >> 16) & 0xFF) >> 4) << 4 | // B
(((*inPixel32 >> 24) & 0xFF) >> 4) << 0;  // A
}
} else if (pixelFormat == kCCTexture2DPixelFormat_RGB5A1) {
// 将 "RRRRRRRRRGGGGGGGGBBBBBBBBAAAAAAAA" 转换为 "RRRRRGGGGGBBBBBA"
inPixel32 = (unsigned int*)image->getData();
tempData = new unsigned char[width * height * 2];
outPixel16 = (unsigned short*)tempData;

for (unsigned int i = 0; i < length; ++i, ++inPixel32) {
*outPixel16++ =
(((*inPixel32 >> 0) & 0xFF) >> 3) << 11 | // R
(((*inPixel32 >> 8) & 0xFF) >> 3) <<  6 | // G
(((*inPixel32 >> 16) & 0xFF) >> 3) << 1 | // B
(((*inPixel32 >> 24) & 0xFF) >> 7) << 0;  // A
}
} else if (pixelFormat == kCCTexture2DPixelFormat_A8) {
// 将 "RRRRRRRRRGGGGGGGGBBBBBBBBAAAAAAAA" 转换为 "AAAAAAAA"
inPixel32 = (unsigned int*)image->getData();
tempData = new unsigned char[width * height];
unsigned char *outPixel8 = tempData;

for (unsigned int i = 0; i < length; ++i, ++inPixel32) {
*outPixel8++ = (*inPixel32 >> 24) & 0xFF;  // A
}
}

if (hasAlpha && pixelFormat == kCCTexture2DPixelFormat_RGB888) {
// 将 "RRRRRRRRRGGGGGGGGBBBBBBBBAAAAAAAA" 转换为 "RRRRRRRRGGGGGGGGBBBBBBBB"
inPixel32 = (unsigned int*)image->getData();
tempData = new unsigned char[width * height * 3];
unsigned char *outPixel8 = tempData;

for (unsigned int i = 0; i < length; ++i, ++inPixel32) {
*outPixel8++ = (*inPixel32 >> 0) & 0xFF; // R
*outPixel8++ = (*inPixel32 >> 8) & 0xFF; // G
*outPixel8++ = (*inPixel32 >> 16) & 0xFF; // B
}
}

// 使用转换后的数据初始化纹理
initWithData(tempData, pixelFormat, width, height, imageSize);

// 如果临时数据不是原始图片数据,释放临时数据
if (tempData != image->getData()) {
delete [] tempData;
}

// 标记纹理是否有预乘Alpha通道
m_bHasPremultipliedAlpha = image->isPremultipliedAlpha();

return true;
}

代码解释

  1. 像素格式计算:根据图片是否有Alpha通道以及每个颜色分量的位数,选择合适的像素格式。
  2. 数据转换:根据选择的像素格式,将原始图片数据转换为目标格式。
  3. 纹理初始化:使用转换后的数据初始化纹理。
  4. 内存管理:如果临时数据不是原始图片数据,释放临时数据以避免内存泄漏。

通过上述代码,我们可以看到Cocos2d如何对图片资源进行压缩和格式转换,以适应不同的需求。希望这段代码能帮助大家更好地理解Cocos2d的资源压缩机制。

作者信息

boke

boke

共发布了 1025 篇文章