Merge pull request #874 from minggo/iss931_refactor_ccimage_texture2d

Iss931 refactor ccimage texture2d
This commit is contained in:
minggo 2012-04-27 18:48:11 -07:00
commit 53733091d3
7 changed files with 157 additions and 248 deletions

View File

@ -1 +1 @@
7dc2eddab8c675364c06b0818030b2ed1792ca81
918b8b44c7b180874afc0599a0e1b2b4e13f1e2a

View File

@ -300,10 +300,33 @@ bool CCImage::_initWithPngData(void * pData, int nDatalen)
row_pointers[i] = (png_bytep)m_pData + q;
}
png_read_image(png_ptr, row_pointers);
if (m_bHasAlpha)
{
// premultiply alpha, or the effect will wrong when want to use other pixel format in CCTexture2D,
// such as RGB888, RGB5A1
#define CC_RGB_PREMULTIPLY_APLHA(vr, vg, vb, va) \
(unsigned)(((unsigned)((unsigned char)(vr) * ((unsigned char)(va) + 1)) >> 8) | \
((unsigned)((unsigned char)(vg) * ((unsigned char)(va) + 1) >> 8) << 8) | \
((unsigned)((unsigned char)(vb) * ((unsigned char)(va) + 1) >> 8) << 16) | \
((unsigned)(unsigned char)(va) << 24))
unsigned int *tmp = (unsigned int *)m_pData;
for(unsigned int i = 0; i < m_nHeight; i++)
{
for(int j = 0; j < m_nWidth * channels; j += 4)
{
*tmp++ = CC_RGB_PREMULTIPLY_APLHA( row_pointers[i][j], row_pointers[i][j + 1],
row_pointers[i][j + 2], row_pointers[i][j + 3] );
}
}
m_bPreMulti = true;
}
free(row_pointers);
bRet = true;
}
} while (0);
out:

View File

@ -42,217 +42,61 @@ typedef struct
unsigned char* data;
} tImageInfo;
static unsigned int nextPOT(unsigned int x)
static bool _initWithImage(CGImageRef cgImage, tImageInfo *pImageinfo)
{
x = x - 1;
x = x | (x >> 1);
x = x | (x >> 2);
x = x | (x >> 4);
x = x | (x >> 8);
x = x | (x >> 16);
return x + 1;
}
typedef enum {
kCCTexture2DPixelFormat_Automatic = 0,
//! 32-bit texture: RGBA8888
kCCTexture2DPixelFormat_RGBA8888,
//! 24-bit texture: RGBA888
kCCTexture2DPixelFormat_RGB888,
//! 16-bit texture without Alpha channel
kCCTexture2DPixelFormat_RGB565,
//! 8-bit textures used as masks
kCCTexture2DPixelFormat_A8,
//! 16-bit textures: RGBA4444
kCCTexture2DPixelFormat_RGBA4444,
//! 16-bit textures: RGB5A1
kCCTexture2DPixelFormat_RGB5A1,
//! Default texture format: RGBA8888
kCCTexture2DPixelFormat_Default = kCCTexture2DPixelFormat_RGBA8888,
// backward compatibility stuff
kTexture2DPixelFormat_Automatic = kCCTexture2DPixelFormat_Automatic,
kTexture2DPixelFormat_RGBA8888 = kCCTexture2DPixelFormat_RGBA8888,
kTexture2DPixelFormat_RGB888 = kCCTexture2DPixelFormat_RGB888,
kTexture2DPixelFormat_RGB565 = kCCTexture2DPixelFormat_RGB565,
kTexture2DPixelFormat_A8 = kCCTexture2DPixelFormat_A8,
kTexture2DPixelFormat_RGBA4444 = kCCTexture2DPixelFormat_RGBA4444,
kTexture2DPixelFormat_RGB5A1 = kCCTexture2DPixelFormat_RGB5A1,
kTexture2DPixelFormat_Default = kCCTexture2DPixelFormat_Default
} CCTexture2DPixelFormat;
static bool _initPremultipliedATextureWithImage(CGImageRef image, NSUInteger POTWide, NSUInteger POTHigh, tImageInfo *pImageInfo)
{
NSUInteger i;
CGContextRef context = nil;
unsigned char* data = nil;;
CGColorSpaceRef colorSpace;
unsigned char* tempData;
unsigned int* inPixel32;
unsigned short* outPixel16;
bool hasAlpha;
CGImageAlphaInfo info;
CGSize imageSize;
CCTexture2DPixelFormat pixelFormat;
info = CGImageGetAlphaInfo(image);
hasAlpha = ((info == kCGImageAlphaPremultipliedLast) || (info == kCGImageAlphaPremultipliedFirst) || (info == kCGImageAlphaLast) || (info == kCGImageAlphaFirst) ? YES : NO);
size_t bpp = CGImageGetBitsPerComponent(image);
colorSpace = CGImageGetColorSpace(image);
if(colorSpace)
if(cgImage == NULL)
{
if(hasAlpha || bpp >= 8)
{
pixelFormat = kCCTexture2DPixelFormat_Default;
}
else
{
pixelFormat = kCCTexture2DPixelFormat_RGB565;
}
}
else
{
// NOTE: No colorspace means a mask image
pixelFormat = kCCTexture2DPixelFormat_A8;
}
imageSize.width = CGImageGetWidth(image);
imageSize.height = CGImageGetHeight(image);
// Create the bitmap graphics context
switch(pixelFormat)
{
case kCCTexture2DPixelFormat_RGBA8888:
case kCCTexture2DPixelFormat_RGBA4444:
case kCCTexture2DPixelFormat_RGB5A1:
colorSpace = CGColorSpaceCreateDeviceRGB();
data = new unsigned char[POTHigh * POTWide * 4];
info = hasAlpha ? kCGImageAlphaPremultipliedLast : kCGImageAlphaNoneSkipLast;
context = CGBitmapContextCreate(data, POTWide, POTHigh, 8, 4 * POTWide, colorSpace, info | kCGBitmapByteOrder32Big);
CGColorSpaceRelease(colorSpace);
break;
case kCCTexture2DPixelFormat_RGB565:
colorSpace = CGColorSpaceCreateDeviceRGB();
data = new unsigned char[POTHigh * POTWide * 4];
info = kCGImageAlphaNoneSkipLast;
context = CGBitmapContextCreate(data, POTWide, POTHigh, 8, 4 * POTWide, colorSpace, info | kCGBitmapByteOrder32Big);
CGColorSpaceRelease(colorSpace);
break;
case kCCTexture2DPixelFormat_A8:
data = new unsigned char[POTHigh * POTWide];
info = kCGImageAlphaOnly;
context = CGBitmapContextCreate(data, POTWide, POTHigh, 8, POTWide, NULL, info);
break;
default:
return false;
}
CGRect rect;
rect.size.width = POTWide;
rect.size.height = POTHigh;
rect.origin.x = 0;
rect.origin.y = 0;
// get image info
CGContextClearRect(context, rect);
CGContextTranslateCTM(context, 0, POTHigh - imageSize.height);
rect.size.width = CGImageGetWidth(image);
rect.size.height = CGImageGetHeight(image);
rect.origin.x = 0;
rect.origin.y = 0;
CGContextDrawImage(context, rect, image);
pImageinfo->width = CGImageGetWidth(cgImage);
pImageinfo->height = CGImageGetHeight(cgImage);
// Repack the pixel data into the right format
CGImageAlphaInfo info = CGImageGetAlphaInfo(cgImage);
pImageinfo->hasAlpha = (info == kCGImageAlphaPremultipliedLast)
|| (info == kCGImageAlphaPremultipliedFirst)
|| (info == kCGImageAlphaLast)
|| (info == kCGImageAlphaFirst);
if(pixelFormat == kCCTexture2DPixelFormat_RGB565)
CGColorSpaceRef colorSpace = CGImageGetColorSpace(cgImage);
if (colorSpace)
{
//Convert "RRRRRRRRRGGGGGGGGBBBBBBBBAAAAAAAA" to "RRRRRGGGGGGBBBBB"
tempData = new unsigned char[POTHigh * POTWide * 2];
inPixel32 = (unsigned int*)data;
outPixel16 = (unsigned short*)tempData;
for(i = 0; i < POTWide * POTHigh; ++i, ++inPixel32)
if (pImageinfo->hasAlpha)
{
*outPixel16++ = ((((*inPixel32 >> 0) & 0xFF) >> 3) << 11) | ((((*inPixel32 >> 8) & 0xFF) >> 2) << 5) | ((((*inPixel32 >> 16) & 0xFF) >> 3) << 0);
info = kCGImageAlphaPremultipliedLast;
pImageinfo->isPremultipliedAlpha = true;
}
else
{
info = kCGImageAlphaNoneSkipLast;
pImageinfo->isPremultipliedAlpha = false;
}
}
else
{
return false;
}
delete[] data;
data = tempData;
// change to RGBA8888
pImageinfo->hasAlpha = true;
pImageinfo->bitsPerComponent = 8;
pImageinfo->data = new unsigned char[pImageinfo->width * pImageinfo->height * 4];
colorSpace = CGColorSpaceCreateDeviceRGB();
CGContextRef context = CGBitmapContextCreate(pImageinfo->data,
pImageinfo->width,
pImageinfo->height,
8,
4 * pImageinfo->width,
colorSpace,
info | kCGBitmapByteOrder32Big);
}
else if (pixelFormat == kCCTexture2DPixelFormat_RGBA4444)
{
//Convert "RRRRRRRRRGGGGGGGGBBBBBBBBAAAAAAAA" to "RRRRGGGGBBBBAAAA"
tempData = new unsigned char[POTHigh * POTWide * 2];
inPixel32 = (unsigned int*)data;
outPixel16 = (unsigned short*)tempData;
for(i = 0; i < POTWide * POTHigh; ++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
}
delete[] data;
data = tempData;
}
else if (pixelFormat == kCCTexture2DPixelFormat_RGB5A1)
{
//Convert "RRRRRRRRRGGGGGGGGBBBBBBBBAAAAAAAA" to "RRRRRGGGGGBBBBBA"
tempData = new unsigned char[POTHigh * POTWide * 2];
inPixel32 = (unsigned int*)data;
outPixel16 = (unsigned short*)tempData;
for(i = 0; i < POTWide * POTHigh; ++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
}
delete[] data;
data = tempData;
}
// should be after calling super init
pImageInfo->isPremultipliedAlpha = true;
pImageInfo->hasAlpha = true;
pImageInfo->bitsPerComponent = bpp;
pImageInfo->width = imageSize.width;
pImageInfo->height = imageSize.height;
if (pImageInfo->data)
{
delete [] pImageInfo->data;
}
pImageInfo->data = data;
CGContextClearRect(context, CGRectMake(0, 0, pImageinfo->width, pImageinfo->height));
//CGContextTranslateCTM(context, 0, 0);
CGContextDrawImage(context, CGRectMake(0, 0, pImageinfo->width, pImageinfo->height), cgImage);
CGContextRelease(context);
return true;
}
static bool _initWithImage(CGImageRef CGImage, tImageInfo *pImageinfo)
{
NSUInteger POTWide, POTHigh;
if(CGImage == NULL)
{
return false;
}
POTWide = CGImageGetWidth(CGImage);
POTHigh = CGImageGetHeight(CGImage);
// always load premultiplied images
_initPremultipliedATextureWithImage(CGImage, POTWide, POTHigh, pImageinfo);
return true;
}

View File

@ -304,6 +304,24 @@ bool CCTexture2D::initPremultipliedATextureWithImage(CCImage *image, unsigned in
unsigned int length = width * height;
if (pixelFormat == kCCTexture2DPixelFormat_RGB565)
{
if (hasAlpha)
{
// Convert "RRRRRRRRRGGGGGGGGBBBBBBBBAAAAAAAA" to "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
{
// Convert "RRRRRRRRRGGGGGGGGBBBBBBBB" to "RRRRRGGGGGGBBBBB"
@ -319,6 +337,7 @@ bool CCTexture2D::initPremultipliedATextureWithImage(CCImage *image, unsigned in
(((*inPixel8++ & 0xFF) >> 3) << 0); // B
}
}
}
else if (pixelFormat == kCCTexture2DPixelFormat_RGBA4444)
{
// Convert "RRRRRRRRRGGGGGGGGBBBBBBBBAAAAAAAA" to "RRRRGGGGBBBBAAAA"
@ -354,7 +373,30 @@ bool CCTexture2D::initPremultipliedATextureWithImage(CCImage *image, unsigned in
}
else if (pixelFormat == kCCTexture2DPixelFormat_A8)
{
// fixed me, how to convert?
// Convert "RRRRRRRRRGGGGGGGGBBBBBBBBAAAAAAAA" to "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)
{
// Convert "RRRRRRRRRGGGGGGGGBBBBBBBBAAAAAAAA" to "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);

View File

@ -1 +1 @@
941978c520f1726cf972dfa50fcfee7f72769685
0ffd9a2963117b5a53222965ff2d95f8178971f2

View File

@ -985,7 +985,7 @@ void TexturePixelFormat::onEnter()
// RGB565 image (16-bit)
CCTexture2D::setDefaultAlphaPixelFormat(kCCTexture2DPixelFormat_RGB565);
CCSprite *sprite5 = CCSprite::spriteWithFile("Images/test-rgba1.png");
sprite5->setPosition(ccp(4*s.width/7, s.height/2+32));
sprite5->setPosition(ccp(5*s.width/7, s.height/2+32));
addChild(sprite5, 0);
// remove texture from texture manager
@ -994,7 +994,7 @@ void TexturePixelFormat::onEnter()
// A8 image (8-bit)
CCTexture2D::setDefaultAlphaPixelFormat(kCCTexture2DPixelFormat_A8);
CCSprite *sprite6 = CCSprite::spriteWithFile("Images/test-rgba1.png");
sprite6->setPosition(ccp(5*s.width/7, s.height/2+32));
sprite6->setPosition(ccp(6*s.width/7, s.height/2-32));
addChild(sprite6, 0);
// remove texture from texture manager