This commit is contained in:
Ming 2010-09-18 06:14:51 +00:00
parent 5af16c3282
commit b87fb419fb
3 changed files with 158 additions and 326 deletions

View File

@ -32,6 +32,24 @@ THE SOFTWARE.
using namespace std;
namespace cocos2d {
#ifdef _TRANZDA_VM_
#define CCX_RGB(vr,vg,vb) \
(ColorRefType)(((UInt32)(UInt8)(vb) << 16) | ((UInt32)(UInt8)(vg) << 8) | (UInt32)(UInt8)(vr) | ((UInt32)0xffL << 24))
#define CCX_RGB_APLHA(vr, vg, vb, va) \
(ColorRefType)(((UInt32)((UInt8)(vr) * ((UInt8)(va) + 1)) >> 8) | \
((UInt32)((UInt8)(vg) * ((UInt8)(va) + 1) >> 8) << 8) | \
((UInt32)((UInt8)(vb) * ((UInt8)(va) + 1) >> 8) << 16) | \
((UInt32)(UInt8)(va) << 24))
#define CCX_RGBA(vr,vg,vb,va) \
(((va) == 0xff)?CCX_RGB((vr), (vg), (vb)):CCX_RGB_APLHA((vr), (vg), (vb), (va)))
#else
#define CCX_RGB RGB
#define CCX_RGBA RGBA
#endif //_TRANZDA_VM_
typedef struct
{
unsigned char* data;
@ -56,13 +74,70 @@ static void pngReadCallback(png_structp png_ptr, png_bytep data, png_size_t leng
}
}
static void copyImageData(tImageInfo &imageInfo, png_bytep* rowPointers)
{
// allocate memory
imageInfo.data = new unsigned char[imageInfo.height * imageInfo.width * 4];
if (! imageInfo.data)
{
return;
}
// copy data
if(imageInfo.hasAlpha) {
unsigned int bytesPerRow = imageInfo.width * 4;
unsigned int *tmp = (unsigned int *)imageInfo.data;
for(unsigned int i = 0; i < imageInfo.height; i++)
{
for(unsigned int j = 0; j < bytesPerRow; j += 4)
{
*tmp++ = CCX_RGBA( rowPointers[i][j], rowPointers[i][j + 1],
rowPointers[i][j + 2], rowPointers[i][j + 3] );
}
}
}
else
{
unsigned int bytesPerRow = imageInfo.width * 3;
unsigned int *tmp = (unsigned int *)imageInfo.data;
for(unsigned int i = 0; i < imageInfo.height; i++)
{
for(unsigned int j = 0; j < bytesPerRow; j += 3)
{
*tmp++ = CCX_RGB( rowPointers[i][j], rowPointers[i][j + 1],
rowPointers[i][j + 2] );
}
}
}
}
UIImage::UIImage(void)
{
m_pBitmap = NULL;
m_imageInfo.hasAlpha = false;
m_imageInfo.isPremultipliedAlpha = false;
m_imageInfo.height = 0;
m_imageInfo.width = 0;
m_imageInfo.data = NULL;
m_imageInfo.bitsPerComponent = 0;
}
UIImage::UIImage(TBitmap *bitmap)
{
m_pBitmap = bitmap->Clone();
if (bitmap)
{
m_pBitmap = bitmap->DupBitmapTo32();
// init imageinfo
m_imageInfo.data = m_pBitmap->GetDataPtr();
m_imageInfo.height = m_pBitmap->GetHeight();
m_imageInfo.width = m_pBitmap->GetWidth();
m_imageInfo.hasAlpha = m_pBitmap->HasAlphaData();
// uphone only support predefined
m_imageInfo.isPremultipliedAlpha = true;
m_imageInfo.bitsPerComponent = m_pBitmap->GetDepth();
}
}
UIImage::UIImage(int nX, int nY, void *buffer)
@ -74,100 +149,38 @@ UIImage::~UIImage(void)
{
if (m_pBitmap)
{
// the m_imageInfo's data points to m_pBitmap,
// so we don't release m_imageInfo's data
m_pBitmap->Destroy();
}
else
{
if (m_imageInfo.data)
{
delete []m_imageInfo.data;
}
}
}
bool UIImage::initWithContentsOfFile(const string &strPath)
{
if (m_pBitmap)
{
return false;
}
bool bRet = false;
do
{
// load the image
/************************************************************************/
/* Use ImageToolKit load image */
// ImageLoader obImgLoader;
// Image obImg;
// TUChar *pszPath = new TUChar[strPath.size() + 1];
// TUString::StrGBToUnicode(pszPath, (const Char *) strPath.c_str());
// if (! obImgLoader.loadImage(obImg, pszPath, IT_LOAD_FMT_UNKNOWN))
// {
// bRet = false;
// break;
// }
//
// // init bitmap
// m_pBitmap = (TBitmap *) obImg.GetTBitmap();
// m_pBitmap = m_pBitmap->DupBitmapTo32();
// delete[] pszPath;
/************************************************************************/
// use libpng load image
bRet = loadPng(strPath.c_str());
// check if the loading action is successful
if (! bRet)
{
break;
}
// the hight is 0??
if (m_pBitmap->GetHeight() == 0)
{
m_pBitmap->Destroy();
m_pBitmap = NULL;
bRet = false;
break;
}
} while(0);
return bRet;
// use libpng load image
return loadPng(strPath.c_str());
}
unsigned int UIImage::width(void)
{
if (! m_pBitmap)
{
return 0;
}
return m_pBitmap->GetWidth();
return m_imageInfo.width;
}
unsigned int UIImage::height(void)
{
if (! m_pBitmap)
{
return 0;
}
return m_pBitmap->GetHeight();
return m_imageInfo.height;
}
bool UIImage::isAlphaPixelFormat(void)
{
if (! m_pBitmap)
{
return false;
}
bool bRet;
if (m_pBitmap->HasAlphaData())
{
bRet = true;
}
else
{
bRet = false;
}
return bRet;
return m_imageInfo.hasAlpha;
}
// now, uphone only support premultiplied data
@ -180,27 +193,7 @@ bool UIImage::isPremultipliedAlpha(void)
// compute how many bits every color component
int UIImage::CGImageGetBitsPerComponent(void)
{
if (! m_pBitmap)
{
return 0;
}
int nRet = 0;
int nRowBytes = m_pBitmap->GetRowBytes();
if (m_pBitmap->HasAlphaData())
{
// it has alpha data, so
// nRawBytes / 4 -> the bytes of per component
nRet = nRowBytes / 4 * 8;
}
else
{
// have not alpha data
// nRawBytes / 3 -> the bytes of per component
nRet = nRowBytes / 3 * 8;
}
return nRet;
return m_imageInfo.bitsPerComponent;
}
// 0 -> it is a mask
@ -209,7 +202,7 @@ int UIImage::CGImageGetColorSpace(void)
{
int nRet = 1;
if (m_pBitmap->GetRowBytes() == 1)
if (m_imageInfo.bitsPerComponent == 8)
{
nRet = 0;
}
@ -219,181 +212,53 @@ int UIImage::CGImageGetColorSpace(void)
unsigned char* UIImage::getRGBA8888Data(void)
{
unsigned char *pBufferRet = NULL;
do {
/*TBitmap *pBitmap;*/
int nW;
int nH;
unsigned char uR;
unsigned char uB;
if (m_pBitmap == NULL)
{
break;
}
// convert to RGBA8888 format
// pBitmap = m_pBitmap->DupBitmapTo32();
// if (pBitmap == NULL)
// {
// break;
// }
// compute width and height
nW = m_pBitmap->GetWidth();
nH = m_pBitmap->GetHeight();
// alloc memory and store the bitmap data
pBufferRet = new unsigned char[nW * nH * 4];
memcpy(pBufferRet, m_pBitmap->GetDataPtr(), nW * nH * 4);
#ifdef _TRANZDA_VM_
// translate BGRA to RGBA
for (int i = 0; i < nW; ++i)
{
for (int j = 0; j < nH; ++j)
{
int baseAddr = (j * nW + i) * 4;
uB = pBufferRet[baseAddr];
uR = pBufferRet[baseAddr + 2];
pBufferRet[baseAddr] = uR;
pBufferRet[baseAddr + 2] = uB;
}
}
#endif // _TRANZDA_VM_
/*pBitmap->Destroy();*/
} while(0);
return pBufferRet;
return m_imageInfo.data;
}
bool UIImage::loadPng(const char* strFileName)
{
char header[8];
FILE *fp;
png_structp png_ptr;
png_infop info_ptr;
UInt32 * pBmpData;
Int32 bitDepth;
png_uint_32 width;
png_uint_32 height;
Int32 interlaceType;
png_bytep * rowPointers;
Int32 colorType;
FILE *fp;
unsigned char *buffer = NULL;
bool bRet = true;
fp = NULL;
pBmpData = NULL;
// open file
fp = fopen(strFileName, "rb");
if (!fp)
return false;
do
{
// open file
fp = fopen(strFileName, "rb");
if (!fp)
{
bRet = false;
break;
}
// read 8 bytes from the beginning of the file
fread(header, 1, 8, fp);
// compute the length of file
fseek(fp,0,SEEK_END);
int size = ftell(fp);
fseek(fp,0,SEEK_SET);
// close the file if it's not a png
if (png_sig_cmp((png_bytep)header, 0, 8))
{
fclose(fp);
return false;
}
// allocate enough memory to save the data of file
buffer = new unsigned char[size];
if (! buffer)
{
bRet = false;
break;
}
// init png_struct
png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
if (!png_ptr)
{
fclose(fp);
return false;
}
// read data
fread(buffer, sizeof(unsigned char), size, fp);
// init png_info
info_ptr = png_create_info_struct(png_ptr);
if (!info_ptr)
{
png_destroy_read_struct(&png_ptr, NULL, NULL);
fclose(fp);
return false;
}
bRet = loadPngFromStream(buffer, size);
delete[] buffer;
} while (0);
if (fp)
{
fclose(fp);
}
// if something wrong,close file and return
if (setjmp(png_jmpbuf(png_ptr)))
{
png_destroy_read_struct(&png_ptr, NULL, NULL);
png_destroy_info_struct(png_ptr, &info_ptr);
fclose(fp);
return false;
}
// conect the file pointer to libpng
png_init_io(png_ptr, fp);
png_set_sig_bytes(png_ptr, 8);
// read the data of the file
png_read_png(png_ptr, info_ptr, PNG_TRANSFORM_EXPAND | PNG_TRANSFORM_GRAY_TO_RGB, 0);
png_get_IHDR(png_ptr, info_ptr, &width, &height, &bitDepth, &colorType,
&interlaceType, NULL, NULL);
if (setjmp(png_jmpbuf(png_ptr)))
{
png_destroy_read_struct(&png_ptr, NULL, NULL);
png_destroy_info_struct(png_ptr, &info_ptr);
fclose(fp);
return false;
}
// get the image file data
rowPointers = png_get_rows(png_ptr, info_ptr);
// Create a bitmap of 32bits depth
if(!m_pBitmap)
{
m_pBitmap = TBitmap::Create(width, height, 32);
}
if(!m_pBitmap)
{
png_destroy_read_struct(&png_ptr, NULL, NULL);
png_destroy_info_struct(png_ptr, &info_ptr);
fclose(fp);
return false;
}
// Alpha data
pBmpData = (UInt32* )( m_pBitmap->GetDataPtr() );
if( info_ptr->color_type & PNG_COLOR_MASK_ALPHA ) {
for(unsigned int i = 0; i < height; i++)
{
for(unsigned int j = 0; j < (4 * width); j += 4)
{
*pBmpData++ = RGBA( rowPointers[i][j], rowPointers[i][j + 1],
rowPointers[i][j + 2], rowPointers[i][j + 3] );
}
}
}
else
{
for(unsigned int i = 0; i < height; i++)
{
for(unsigned int j = 0; j < (3 * width); j += 3)
{
*pBmpData++ = RGB( rowPointers[i][j], rowPointers[i][j + 1],
rowPointers[i][j + 2] );
}
}
}
// release
png_destroy_read_struct(&png_ptr, NULL, NULL);
png_destroy_info_struct(png_ptr, &info_ptr);
fclose(fp);
return true;
return bRet;
}
bool UIImage::loadPngFromStream(unsigned char *data, int nLength)
@ -401,7 +266,6 @@ bool UIImage::loadPngFromStream(unsigned char *data, int nLength)
char header[8];
png_structp png_ptr;
png_infop info_ptr;
UInt32 * pBmpData;
Int32 pos;
Int32 bitDepth;
png_uint_32 width;
@ -412,7 +276,6 @@ bool UIImage::loadPngFromStream(unsigned char *data, int nLength)
tImageSource imageSource;
pos = 0;
pBmpData = NULL;
// read 8 bytes from the beginning of stream
unsigned char *tmp = data;
@ -453,6 +316,7 @@ bool UIImage::loadPngFromStream(unsigned char *data, int nLength)
imageSource.offset = 0;
png_set_read_fn(png_ptr, &imageSource, pngReadCallback);
// read the data of the file
png_read_png(png_ptr, info_ptr, PNG_TRANSFORM_EXPAND | PNG_TRANSFORM_GRAY_TO_RGB, 0);
@ -469,42 +333,17 @@ bool UIImage::loadPngFromStream(unsigned char *data, int nLength)
// get the image file data
rowPointers = png_get_rows(png_ptr, info_ptr);
// Create a bitmap of 32bits depth
if(!m_pBitmap)
{
m_pBitmap = TBitmap::Create(width, height, 32);
}
if(!m_pBitmap)
{
png_destroy_read_struct(&png_ptr, NULL, NULL);
png_destroy_info_struct(png_ptr, &info_ptr);
return false;
}
// Alpha data
pBmpData = reinterpret_cast< UInt32* >( m_pBitmap->GetDataPtr() );
if( info_ptr->color_type & PNG_COLOR_MASK_ALPHA ) {
for(unsigned int i = 0; i < height; i++)
{
for(unsigned int j = 0; j < (4 * width); j += 4)
{
*pBmpData++ = RGBA( rowPointers[i][j], rowPointers[i][j + 1],
rowPointers[i][j + 2], rowPointers[i][j + 3] );
}
}
}
else
{
for(unsigned int i = 0; i < height; i++)
{
for(unsigned int j = 0; j < (3 * width); j += 3)
{
*pBmpData++ = RGB( rowPointers[i][j], rowPointers[i][j + 1],
rowPointers[i][j + 2] );
}
}
}
// init image info
m_imageInfo.height = height;
m_imageInfo.width = width;
m_imageInfo.hasAlpha = info_ptr->color_type & PNG_COLOR_MASK_ALPHA;
m_imageInfo.isPremultipliedAlpha = true;
copyImageData(m_imageInfo, rowPointers);
// we use CCX_RGA or CCX_RGB to save data
// so the bitsPerComponet is 32, and it also
// has the alpha data
m_imageInfo.bitsPerComponent = 32;
m_imageInfo.hasAlpha = true;
// release
png_destroy_read_struct(&png_ptr, NULL, NULL);
@ -520,29 +359,7 @@ bool UIImage::save(const std::string &strFileName, int nFormat)
}
bool UIImage::initWithData(unsigned char *pBuffer, int nLength)
{
bool bRet = true;
do
{
bRet = loadPngFromStream(pBuffer, nLength);
// if load failed, break
if (! bRet)
{
break;
}
// the hight is 0??
if (m_pBitmap->GetHeight() == 0)
{
m_pBitmap->Destroy();
m_pBitmap = NULL;
bRet = false;
break;
}
} while(0);
return bRet;
return loadPngFromStream(pBuffer, nLength);
}
bool UIImage::initWithBuffer(int tx, int ty, unsigned char *pBuffer)

View File

@ -31,6 +31,16 @@ THE SOFTWARE.
class TBitmap;
namespace cocos2d {
typedef struct
{
unsigned int height;
unsigned int width;
int bitsPerComponent;
bool hasAlpha;
bool isPremultipliedAlpha;
unsigned char *data;
} tImageInfo;
class CCX_DLL UIImage
{
public:
@ -65,6 +75,7 @@ private:
private:
TBitmap *m_pBitmap;
tImageInfo m_imageInfo;
};
}//namespace cocos2d

View File

@ -283,7 +283,8 @@ bool CCTexture2D::initPremultipliedATextureWithImage(UIImage *image, unsigned in
NSAssert(tempData != NULL, "NULL image data.");
if(image->width() == POTWide && image->height() == POTHigh)
{
data = tempData;
data = new UINT8[POTHigh * POTWide * 4];
memcpy(data, tempData, POTHigh * POTWide * 4);
}
else
{
@ -297,7 +298,6 @@ bool CCTexture2D::initPremultipliedATextureWithImage(UIImage *image, unsigned in
{
memcpy(pTargetData+POTWide*4*y, pPixelData+(image->width())*4*y, (image->width())*4);
}
delete []tempData;
}
break;
default:
@ -317,8 +317,10 @@ bool CCTexture2D::initPremultipliedATextureWithImage(UIImage *image, unsigned in
tempData = new UINT8[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) | ((((*inPixel32 >> 8) & 0xFF) >> 2) << 5) | ((((*inPixel32 >> 16) & 0xFF) >> 3) << 0);
delete [] data;
data = tempData;
}
@ -327,6 +329,7 @@ bool CCTexture2D::initPremultipliedATextureWithImage(UIImage *image, unsigned in
tempData = new UINT8[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
@ -342,6 +345,7 @@ bool CCTexture2D::initPremultipliedATextureWithImage(UIImage *image, unsigned in
tempData = new UINT8[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