From 7ecbd8ea6cd6ea841f29a800edba68abc6a0a119 Mon Sep 17 00:00:00 2001 From: minggo Date: Thu, 26 Apr 2012 17:36:32 +0800 Subject: [PATCH 1/2] issue #931: refactor CCImage and CCTexture2D --- .../gen/org/cocos2dx/application/R.java | 52 ++--- .../proj.android/jni/helloworld/main.cpp | 1 + cocos2dx/platform/CCImage.cpp | 131 ++++++------ cocos2dx/textures/CCTexture2D.cpp | 187 +++++------------- 4 files changed, 142 insertions(+), 229 deletions(-) diff --git a/HelloWorld/proj.android/gen/org/cocos2dx/application/R.java b/HelloWorld/proj.android/gen/org/cocos2dx/application/R.java index 979d1ae7fc..056c00f791 100644 --- a/HelloWorld/proj.android/gen/org/cocos2dx/application/R.java +++ b/HelloWorld/proj.android/gen/org/cocos2dx/application/R.java @@ -1,26 +1,26 @@ -/* AUTO-GENERATED FILE. DO NOT MODIFY. - * - * This class was automatically generated by the - * aapt tool from the resource data it found. It - * should not be modified by hand. - */ - -package org.cocos2dx.application; - -public final class R { - public static final class attr { - } - public static final class drawable { - public static final int icon=0x7f020000; - } - public static final class id { - public static final int helloworld_gl_surfaceview=0x7f050001; - public static final int textField=0x7f050000; - } - public static final class layout { - public static final int helloworld_demo=0x7f030000; - } - public static final class string { - public static final int app_name=0x7f040000; - } -} +/* AUTO-GENERATED FILE. DO NOT MODIFY. + * + * This class was automatically generated by the + * aapt tool from the resource data it found. It + * should not be modified by hand. + */ + +package org.cocos2dx.application; + +public final class R { + public static final class attr { + } + public static final class drawable { + public static final int icon=0x7f020000; + } + public static final class id { + public static final int helloworld_gl_surfaceview=0x7f050001; + public static final int textField=0x7f050000; + } + public static final class layout { + public static final int helloworld_demo=0x7f030000; + } + public static final class string { + public static final int app_name=0x7f040000; + } +} diff --git a/HelloWorld/proj.android/jni/helloworld/main.cpp b/HelloWorld/proj.android/jni/helloworld/main.cpp index 3f954d0376..12de1ac94c 100644 --- a/HelloWorld/proj.android/jni/helloworld/main.cpp +++ b/HelloWorld/proj.android/jni/helloworld/main.cpp @@ -1,6 +1,7 @@ #include "AppDelegate.h" #include "cocos2d.h" #include "platform/android/jni/JniHelper.h" +#include "CCEventType.h" #include #include diff --git a/cocos2dx/platform/CCImage.cpp b/cocos2dx/platform/CCImage.cpp index 454688f4e5..daa720e9b5 100644 --- a/cocos2dx/platform/CCImage.cpp +++ b/cocos2dx/platform/CCImage.cpp @@ -28,22 +28,13 @@ THE SOFTWARE. #include "CCStdC.h" #include "CCFileUtils.h" #include "png.h" +#include "jpeglib.h" #include #include #if (CC_TARGET_PLATFORM != CC_PLATFORM_IOS) // on ios, we should use platform/ios/CCImage_ios.mm instead -#define QGLOBAL_H // defined for wophone -#include "jpeglib.h" -#undef QGLOBAL_H - -#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)) - typedef struct { unsigned char* data; @@ -206,20 +197,21 @@ bool CCImage::_initWithJpgData(void * data, int nSize) bool CCImage::_initWithPngData(void * pData, int nDatalen) { +// length of bytes to check if it is a valid png file +#define PNGSIGSIZE 8 bool bRet = false; - png_byte header[8] = {0}; + png_byte header[PNGSIGSIZE] = {0}; png_structp png_ptr = 0; png_infop info_ptr = 0; - unsigned char * pImateData = 0; do { // png header len is 8 bytes - CC_BREAK_IF(nDatalen < 8); + CC_BREAK_IF(nDatalen < PNGSIGSIZE); // check the data is png or not - memcpy(header, pData, 8); - CC_BREAK_IF(png_sig_cmp(header, 0, 8)); + memcpy(header, pData, PNGSIGSIZE); + CC_BREAK_IF(png_sig_cmp(header, 0, PNGSIGSIZE)); // init png_struct png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0); @@ -228,9 +220,11 @@ bool CCImage::_initWithPngData(void * pData, int nDatalen) // init png_info info_ptr = png_create_info_struct(png_ptr); CC_BREAK_IF(!info_ptr); + #if (CC_TARGET_PLATFORM != CC_PLATFORM_BADA) CC_BREAK_IF(setjmp(png_jmpbuf(png_ptr))); #endif + // set the read call back function tImageSource imageSource; imageSource.data = (unsigned char*)pData; @@ -238,67 +232,74 @@ bool CCImage::_initWithPngData(void * pData, int nDatalen) imageSource.offset = 0; png_set_read_fn(png_ptr, &imageSource, pngReadCallback); - // read png - // PNG_TRANSFORM_EXPAND: perform set_expand() - // PNG_TRANSFORM_PACKING: expand 1, 2 and 4-bit samples to bytes - // PNG_TRANSFORM_STRIP_16: strip 16-bit samples to 8 bits - // PNG_TRANSFORM_GRAY_TO_RGB: expand grayscale samples to RGB (or GA to RGBA) - png_read_png(png_ptr, info_ptr, PNG_TRANSFORM_EXPAND | PNG_TRANSFORM_PACKING - | PNG_TRANSFORM_STRIP_16 | PNG_TRANSFORM_GRAY_TO_RGB, 0); + // read png header info + + // read png file info + png_read_info(png_ptr, info_ptr); + + m_nWidth = png_get_image_width(png_ptr, info_ptr); + m_nHeight = png_get_image_height(png_ptr, info_ptr); + m_nBitsPerComponent = png_get_bit_depth(png_ptr, info_ptr); + png_uint_32 channels = png_get_channels(png_ptr, info_ptr); + png_uint_32 color_type = png_get_color_type(png_ptr, info_ptr); - int color_type = 0; - png_uint_32 nWidth = 0; - png_uint_32 nHeight = 0; - int nBitsPerComponent = 0; - png_get_IHDR(png_ptr, info_ptr, &nWidth, &nHeight, &nBitsPerComponent, &color_type, 0, 0, 0); - - // init image info - m_bPreMulti = true; - m_bHasAlpha = ( info_ptr->color_type & PNG_COLOR_MASK_ALPHA ) ? true : false; - - // allocate memory and read data - int bytesPerComponent = 3; + CCLOG("color type %u", color_type); + // only support color type: PNG_COLOR_TYPE_RGB, PNG_COLOR_TYPE_RGB_ALPHA PNG_COLOR_TYPE_PALETTE + // and expand bit depth to 8 + switch (color_type) { + case PNG_COLOR_TYPE_RGB: + case PNG_COLOR_TYPE_RGB_ALPHA: + // do nothing + + break; + case PNG_COLOR_TYPE_PALETTE: + png_set_palette_to_rgb(png_ptr); + channels = 3; + + break; + case PNG_COLOR_TYPE_GRAY: + case PNG_COLOR_TYPE_GRAY_ALPHA: + if (m_nBitsPerComponent < 8) + { + png_set_expand_gray_1_2_4_to_8(png_ptr); + } + png_set_gray_to_rgb(png_ptr); + channels = 3; + + break; + + default: + CCLog("unsopprted color type %u", color_type); + goto out; + } + if (m_nBitsPerComponent == 16) + { + png_set_strip_16(png_ptr); + m_nBitsPerComponent = 8; + } + + m_bHasAlpha = (color_type & PNG_COLOR_MASK_ALPHA) ? true : false; if (m_bHasAlpha) { - bytesPerComponent = 4; + channels = 4; } - pImateData = new unsigned char[nHeight * nWidth * bytesPerComponent]; - CC_BREAK_IF(! pImateData); - png_bytep * rowPointers = png_get_rows(png_ptr, info_ptr); - - // copy data to image info - int bytesPerRow = nWidth * bytesPerComponent; - if(m_bHasAlpha) + // read png data + // m_nBitsPerComponent will always be 8 + m_pData = new unsigned char[m_nWidth * m_nHeight * channels]; + png_bytep row_pointers[m_nHeight]; + const unsigned int stride = m_nWidth * channels; + for (size_t i = 0; i < m_nHeight; ++i) { - unsigned int *tmp = (unsigned int *)pImateData; - for(unsigned int i = 0; i < nHeight; i++) - { - for(int j = 0; j < bytesPerRow; j += 4) - { - *tmp++ = CC_RGB_PREMULTIPLY_APLHA( rowPointers[i][j], rowPointers[i][j + 1], - rowPointers[i][j + 2], rowPointers[i][j + 3] ); - } - } - } - else - { - for (unsigned int j = 0; j < nHeight; ++j) - { - memcpy(pImateData + j * bytesPerRow, rowPointers[j], bytesPerRow); - } + png_uint_32 q = i * stride; + row_pointers[i] = (png_bytep)m_pData + q; } + png_read_image(png_ptr, row_pointers); - m_nBitsPerComponent = nBitsPerComponent; - m_nHeight = (short)nHeight; - m_nWidth = (short)nWidth; - m_pData = pImateData; - pImateData = 0; bRet = true; } while (0); - CC_SAFE_DELETE_ARRAY(pImateData); - +out: if (png_ptr) { png_destroy_read_struct(&png_ptr, (info_ptr) ? &info_ptr : 0, 0); diff --git a/cocos2dx/textures/CCTexture2D.cpp b/cocos2dx/textures/CCTexture2D.cpp index 8010b45650..9568a62966 100644 --- a/cocos2dx/textures/CCTexture2D.cpp +++ b/cocos2dx/textures/CCTexture2D.cpp @@ -271,19 +271,16 @@ bool CCTexture2D::initWithImage(CCImage * uiImage, ccResolutionType resolution) // always load premultiplied images return initPremultipliedATextureWithImage(uiImage, imageWidth, imageHeight); } -bool CCTexture2D::initPremultipliedATextureWithImage(CCImage *image, unsigned int POTWide, unsigned int POTHigh) +bool CCTexture2D::initPremultipliedATextureWithImage(CCImage *image, unsigned int width, unsigned int height) { - unsigned char* data = NULL; - unsigned char* tempData =NULL; - unsigned int* inPixel32 = NULL; - unsigned short* outPixel16 = NULL; - bool hasAlpha; - CCSize imageSize; + unsigned char* tempData = image->getData(); + unsigned int* inPixel32 = NULL; + unsigned char* inPixel8 = NULL; + unsigned short* outPixel16 = NULL; + bool hasAlpha = image->hasAlpha(); + CCSize imageSize = CCSizeMake((float)(image->getWidth()), (float)(image->getHeight())); CCTexture2DPixelFormat pixelFormat; - - hasAlpha = image->hasAlpha(); - - size_t bpp = image->getBitsPerComponent(); + size_t bpp = image->getBitsPerComponent(); // compute pixel format if(hasAlpha) @@ -296,164 +293,78 @@ bool CCTexture2D::initPremultipliedATextureWithImage(CCImage *image, unsigned in { pixelFormat = kCCTexture2DPixelFormat_RGB888; } - else + else { - CCLOG("cocos2d: CCTexture2D: Using RGB565 texture since image has no alpha"); pixelFormat = kCCTexture2DPixelFormat_RGB565; } + } - - - imageSize = CCSizeMake((float)(image->getWidth()), (float)(image->getHeight())); - - switch(pixelFormat) { - case kCCTexture2DPixelFormat_RGBA8888: - case kCCTexture2DPixelFormat_RGBA4444: - case kCCTexture2DPixelFormat_RGB5A1: - case kCCTexture2DPixelFormat_RGB565: - case kCCTexture2DPixelFormat_A8: - tempData = (unsigned char*)(image->getData()); - CCAssert(tempData != NULL, "NULL image data."); - - if(image->getWidth() == (short)POTWide && image->getHeight() == (short)POTHigh) - { - data = new unsigned char[POTHigh * POTWide * 4]; - memcpy(data, tempData, POTHigh * POTWide * 4); - } - else - { - data = new unsigned char[POTHigh * POTWide * 4]; - memset(data, 0, POTHigh * POTWide * 4); - - unsigned char* pPixelData = (unsigned char*) tempData; - unsigned char* pTargetData = (unsigned char*) data; - - int imageHeight = image->getHeight(); - for(int y = 0; y < imageHeight; ++y) - { - memcpy(pTargetData+POTWide*4*y, pPixelData+(image->getWidth())*4*y, (image->getWidth())*4); - } - } - - break; - case kCCTexture2DPixelFormat_RGB888: - tempData = (unsigned char*)(image->getData()); - CCAssert(tempData != NULL, "NULL image data."); - if(image->getWidth() == (short)POTWide && image->getHeight() == (short)POTHigh) - { - data = new unsigned char[POTHigh * POTWide * 3]; - memcpy(data, tempData, POTHigh * POTWide * 3); - } - else - { - data = new unsigned char[POTHigh * POTWide * 3]; - memset(data, 0, POTHigh * POTWide * 3); - - unsigned char* pPixelData = (unsigned char*) tempData; - unsigned char* pTargetData = (unsigned char*) data; - - int imageHeight = image->getHeight(); - for(int y = 0; y < imageHeight; ++y) - { - memcpy(pTargetData+POTWide*3*y, pPixelData+(image->getWidth())*3*y, (image->getWidth())*3); - } - } - break; - default: - CCAssert(0, "Invalid pixel format"); - } - + // Repack the pixel data into the right format - - if(pixelFormat == kCCTexture2DPixelFormat_RGB565) { - //Convert "RRRRRRRRRGGGGGGGGBBBBBBBBAAAAAAAA" to "RRRRRGGGGGGBBBBB" - tempData = new unsigned char[POTHigh * POTWide * 2]; - inPixel32 = (unsigned int*)data; + unsigned int length = width * height; + + if (pixelFormat == kCCTexture2DPixelFormat_RGB565) + { + // Convert "RRRRRRRRRGGGGGGGGBBBBBBBB" to "RRRRRGGGGGGBBBBB" + + tempData = new unsigned char[width * height * 2]; outPixel16 = (unsigned short*)tempData; - - unsigned int length = POTWide * POTHigh; - for(unsigned int i = 0; i < length; ++i, ++inPixel32) + inPixel8 = (unsigned char*)image->getData(); + + for(unsigned int i = 0; i < length; ++i) { *outPixel16++ = - ((((*inPixel32 >> 0) & 0xFF) >> 3) << 11) | // R - ((((*inPixel32 >> 8) & 0xFF) >> 2) << 5) | // G - ((((*inPixel32 >> 16) & 0xFF) >> 3) << 0); // B + (((*inPixel8++ & 0xFF) >> 3) << 11) | // R + (((*inPixel8++ & 0xFF) >> 2) << 5) | // G + (((*inPixel8++ & 0xFF) >> 3) << 0); // B } - - delete [] data; - data = tempData; } - else if (pixelFormat == kCCTexture2DPixelFormat_RGBA4444) { - //Convert "RRRRRRRRRGGGGGGGGBBBBBBBBAAAAAAAA" to "RRRRGGGGBBBBAAAA" - tempData = new unsigned char[POTHigh * POTWide * 2]; - inPixel32 = (unsigned int*)data; + else if (pixelFormat == kCCTexture2DPixelFormat_RGBA4444) + { + // Convert "RRRRRRRRRGGGGGGGGBBBBBBBBAAAAAAAA" to "RRRRGGGGBBBBAAAA" + + inPixel32 = (unsigned int*)image->getData(); + tempData = new unsigned char[width * height * 2]; outPixel16 = (unsigned short*)tempData; - - unsigned int length = POTWide * POTHigh; + for(unsigned int i = 0; i < length; ++i, ++inPixel32) { *outPixel16++ = ((((*inPixel32 >> 0) & 0xFF) >> 4) << 12) | // R - ((((*inPixel32 >> 8) & 0xFF) >> 4) << 8) | // G + ((((*inPixel32 >> 8) & 0xFF) >> 4) << 8) | // G ((((*inPixel32 >> 16) & 0xFF) >> 4) << 4) | // B - ((((*inPixel32 >> 24) & 0xFF) >> 4) << 0); // A + ((((*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; + else if (pixelFormat == kCCTexture2DPixelFormat_RGB5A1) + { + // Convert "RRRRRRRRRGGGGGGGGBBBBBBBBAAAAAAAA" to "RRRRRGGGGGBBBBBA" + inPixel32 = (unsigned int*)image->getData(); + tempData = new unsigned char[width * height * 2]; outPixel16 = (unsigned short*)tempData; - - unsigned int length = POTWide * POTHigh; + for(unsigned int i = 0; i < length; ++i, ++inPixel32) { *outPixel16++ = ((((*inPixel32 >> 0) & 0xFF) >> 3) << 11) | // R - ((((*inPixel32 >> 8) & 0xFF) >> 3) << 6) | // G + ((((*inPixel32 >> 8) & 0xFF) >> 3) << 6) | // G ((((*inPixel32 >> 16) & 0xFF) >> 3) << 1) | // B - ((((*inPixel32 >> 24) & 0xFF) >> 7) << 0); // A + ((((*inPixel32 >> 24) & 0xFF) >> 7) << 0); // A } - - delete []data; - data = tempData; } else if (pixelFormat == kCCTexture2DPixelFormat_A8) { - // fix me, how to convert to A8 - pixelFormat = kCCTexture2DPixelFormat_RGBA8888; - - /* - * The code can not work, how to convert to A8? - * - tempData = new unsigned char[POTHigh * POTWide]; - inPixel32 = (unsigned int*)data; - outPixel8 = tempData; - - unsigned int length = POTWide * POTHigh; - for(unsigned int i = 0; i < length; ++i, ++inPixel32) - { - *outPixel8++ = (*inPixel32 >> 24) & 0xFF; - } - - delete []data; - data = tempData; - */ + // fixed me, how to convert? } - - if (data) + + initWithData(tempData, pixelFormat, width, height, imageSize); + + if (tempData != image->getData()) { - this->initWithData(data, pixelFormat, POTWide, POTHigh, imageSize); - - // should be after calling super init - m_bHasPremultipliedAlpha = image->isPremultipliedAlpha(); - - //CGContextRelease(context); - delete [] data; + delete [] tempData; } + + m_bHasPremultipliedAlpha = image->isPremultipliedAlpha(); return true; } From 2bffd3a565ba0dab1e211bddbdafa9892406549d Mon Sep 17 00:00:00 2001 From: James Chen Date: Thu, 26 Apr 2012 18:17:57 +0800 Subject: [PATCH 2/2] issue #931: dynamically allocate array(row_pointers) in CCImage::_initWithPngData. --- cocos2dx/platform/CCImageCommon_cpp.h | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/cocos2dx/platform/CCImageCommon_cpp.h b/cocos2dx/platform/CCImageCommon_cpp.h index cbefe3e4ee..7a759b7511 100644 --- a/cocos2dx/platform/CCImageCommon_cpp.h +++ b/cocos2dx/platform/CCImageCommon_cpp.h @@ -290,16 +290,20 @@ bool CCImage::_initWithPngData(void * pData, int nDatalen) // read png data // m_nBitsPerComponent will always be 8 m_pData = new unsigned char[m_nWidth * m_nHeight * channels]; - png_bytep row_pointers[m_nHeight]; - const unsigned int stride = m_nWidth * channels; - for (size_t i = 0; i < m_nHeight; ++i) + png_bytep* row_pointers = (png_bytep*)malloc(sizeof(png_bytep)*m_nHeight); + if (row_pointers) { - png_uint_32 q = i * stride; - row_pointers[i] = (png_bytep)m_pData + q; + const unsigned int stride = m_nWidth * channels; + for (size_t i = 0; i < m_nHeight; ++i) + { + png_uint_32 q = i * stride; + row_pointers[i] = (png_bytep)m_pData + q; + } + png_read_image(png_ptr, row_pointers); + free(row_pointers); + bRet = true; } - png_read_image(png_ptr, row_pointers); - bRet = true; } while (0); out: