mirror of https://github.com/axmolengine/axmol.git
Merge pull request #874 from minggo/iss931_refactor_ccimage_texture2d
Iss931 refactor ccimage texture2d
This commit is contained in:
commit
53733091d3
|
@ -1 +1 @@
|
|||
7dc2eddab8c675364c06b0818030b2ed1792ca81
|
||||
918b8b44c7b180874afc0599a0e1b2b4e13f1e2a
|
|
@ -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:
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -1 +1 @@
|
|||
941978c520f1726cf972dfa50fcfee7f72769685
|
||||
0ffd9a2963117b5a53222965ff2d95f8178971f2
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue