bool CCImage::_initWithPngData(void * pData, int nDatalen) { bool bRet = false; png_byte header[8] = {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); // check the data is png or not memcpy(header, pData, 8); CC_BREAK_IF(png_sig_cmp(header, 0, 8)); // init png_struct png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0); CC_BREAK_IF(! png_ptr); // 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; imageSource.size = 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); 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; if (m_bHasAlpha) { bytesPerComponent = 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) { 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); } } 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); if (png_ptr) { png_destroy_read_struct(&png_ptr, (info_ptr) ? &info_ptr : 0, 0); } return bRet; }
void Image::createTexture(const void *input, unsigned int size) { const char *filename = m_src.c_str(); do{ const void *raws = input; png_byte header[8]; memcpy(header, raws, 8); // 读取图片头,判断是否PNG文件 if( png_sig_cmp(header, 0, 8) ) { LOG("Not a png file : %s", filename); break; } // 创建PNG读取结构 png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if( !png_ptr ) { LOG("Unable to create png struct : %s", filename); break; } // 创建PNG信息结构 png_infop info_ptr = png_create_info_struct(png_ptr); if( !info_ptr ) { png_destroy_read_struct(&png_ptr, (png_infopp) NULL, (png_infopp) NULL); LOG("Unable to create png info : %s", filename); break; } if( setjmp(png_jmpbuf(png_ptr)) ) { LOG("Error during setjmp : %s", filename); png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp) NULL); break; } // 设置数据读取函数 void *inputCopy = (void *)input; png_set_read_fn(png_ptr, &inputCopy, png_raw_read); // 设置PNG数据宽度处理 RGB/RGBA 24/32bit //png_read_png(png_ptr, info_ptr, PNG_TRANSFORM_EXPAND | PNG_TRANSFORM_PACKING // | PNG_TRANSFORM_STRIP_16 | PNG_TRANSFORM_GRAY_TO_RGB, 0); png_read_info(png_ptr, info_ptr); // 读取图片信息 int bit_depth, color_type; png_uint_32 twidth, theight; png_get_IHDR(png_ptr, info_ptr, &twidth, &theight, &bit_depth, &color_type, NULL, NULL, NULL); hasAlpha = ( color_type & PNG_COLOR_MASK_ALPHA ) ? true:false; LOG("PNG width=%u height=%u bit_depth=%d alpha=%d", twidth, theight, bit_depth, hasAlpha); // Update the png info struct. //png_read_update_info(png_ptr, info_ptr); int rowbytes = png_get_rowbytes(png_ptr, info_ptr); LOG("PNG rowbytes:%d", rowbytes); int bytes_per_component = hasAlpha ? 4:3; width = twidth; height = theight; POTWidth = computePOT(width); POTHeight = computePOT(height); png_byte *image_data = new png_byte[POTWidth * POTHeight * bytes_per_component]; if( !image_data ) { png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp) NULL); LOG("Unable to allocate image_data while loading %s ", filename); break; } // 创建并设置行指针 png_bytep *row_pointers = new png_bytep[theight]; if( !row_pointers ) { png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp) NULL); delete[] image_data; LOG("Unable to allocate row_pointer while loading %s ", filename); break; } for( int i = 0; i < theight; i++ ) { row_pointers[i] = image_data + i * POTWidth * bytes_per_component; } png_read_image(png_ptr, row_pointers); png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp) NULL); delete[] row_pointers; // 如果有alpha值,开始预乘 if( hasAlpha ) { for( int i=0; i<theight; i++ ) { for( int j=0; j<twidth; j++ ) { unsigned char *pixel = (unsigned char *)(image_data + (i * POTWidth + j) * bytes_per_component); *((unsigned int *)pixel) = CC_RGB_PREMULTIPLY_APLHA( pixel[0], pixel[1], pixel[2], pixel[3] ); } } } setupTexture(image_data); delete[] image_data; JSCContext::getInstance()->callJSFunction(onload); TRACE("load Texture finished:%s", m_src.c_str()); TRACE("texture %d", m_texture); }while(false); }