void Image::premultipliedAlpha() { #if CC_ENABLE_PREMULTIPLIED_ALPHA == 0 _hasPremultipliedAlpha = false; return; #else CCASSERT(_renderFormat == Texture2D::PixelFormat::RGBA8888, "The pixel format should be RGBA8888!"); unsigned int* fourBytes = (unsigned int*)_data; for (int i = 0; i < _width * _height; i++) { unsigned char* p = _data + i * 4; fourBytes[i] = CC_RGB_PREMULTIPLY_ALPHA(p[0], p[1], p[2], p[3]); } _hasPremultipliedAlpha = true; #endif }
bool Image::initWithImageFile(const char * strPath) { bool bRet = false; std::string fullPath = FileUtils::getInstance()->fullPathForFilename(strPath); #ifdef EMSCRIPTEN // Emscripten includes a re-implementation of SDL that uses HTML5 canvas // operations underneath. Consequently, loading images via IMG_Load (an SDL // API) will be a lot faster than running libpng et al as compiled with // Emscripten. SDL_Surface *iSurf = IMG_Load(fullPath.c_str()); int size = 4 * (iSurf->w * iSurf->h); bRet = initWithRawData((const unsigned char*)iSurf->pixels, size, iSurf->w, iSurf->h, 8, true); unsigned int *tmp = (unsigned int *)m_pData; int nrPixels = iSurf->w * iSurf->h; for (int i = 0; i < nrPixels; i++) { unsigned char *p = m_pData + i * 4; tmp[i] = CC_RGB_PREMULTIPLY_ALPHA(p[0], p[1], p[2], p[3]); } SDL_FreeSurface(iSurf); #else KDint32 bufferLen = 0; unsigned char* buffer = FileUtils::getInstance()->getFileData(fullPath.c_str(), "rb", &bufferLen); if (buffer != nullptr && bufferLen > 0) { bRet = initWithImageData(buffer, bufferLen); } kdFree(buffer); #endif // EMSCRIPTEN return bRet; }
bool Cc3dImage::_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[PNGSIGSIZE] = {0}; png_structp png_ptr = 0; png_infop info_ptr = 0; do { // png header len is 8 bytes if(nDatalen < PNGSIGSIZE) break; // check the data is png or not memcpy(header, pData, PNGSIGSIZE); if(png_sig_cmp(header, 0, PNGSIGSIZE)) break; // init png_struct png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0); if(! png_ptr) break; // init png_info info_ptr = png_create_info_struct(png_ptr); if(!info_ptr) break; // 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 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 color_type = png_get_color_type(png_ptr, info_ptr); //CCLOG("color type %u", color_type); // force palette images to be expanded to 24-bit RGB // it may include alpha channel if (color_type == PNG_COLOR_TYPE_PALETTE) { png_set_palette_to_rgb(png_ptr); } // low-bit-depth grayscale images are to be expanded to 8 bits if (color_type == PNG_COLOR_TYPE_GRAY && m_nBitsPerComponent < 8) { png_set_expand_gray_1_2_4_to_8(png_ptr); } // expand any tRNS chunk data into a full alpha channel if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) { png_set_tRNS_to_alpha(png_ptr); } // reduce images with 16-bit samples to 8 bits if (m_nBitsPerComponent == 16) { png_set_strip_16(png_ptr); } // expand grayscale images to RGB if (color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA) { png_set_gray_to_rgb(png_ptr); } // read png data // m_nBitsPerComponent will always be 8 m_nBitsPerComponent = 8; png_uint_32 rowbytes; png_bytep* row_pointers = (png_bytep*)malloc( sizeof(png_bytep) * m_nHeight ); png_read_update_info(png_ptr, info_ptr); rowbytes = png_get_rowbytes(png_ptr, info_ptr); m_pData = new unsigned char[rowbytes * m_nHeight]; if(!m_pData) break; for (unsigned short i = 0; i < m_nHeight; ++i) { row_pointers[i] = m_pData + i*rowbytes; } png_read_image(png_ptr, row_pointers); png_read_end(png_ptr, NULL); png_uint_32 channel = rowbytes/m_nWidth; if (channel == 4) { m_bHasAlpha = true; unsigned int *tmp = (unsigned int *)m_pData; for(unsigned short i = 0; i < m_nHeight; i++) { for(unsigned int j = 0; j < rowbytes; j += 4) { *tmp++ = CC_RGB_PREMULTIPLY_ALPHA( row_pointers[i][j], row_pointers[i][j + 1], row_pointers[i][j + 2], row_pointers[i][j + 3] ); } } m_bPreMulti = true; } do { if(row_pointers) { free(row_pointers); (row_pointers) = 0; } } while(0); bRet = true; } while (0); if (png_ptr) { png_destroy_read_struct(&png_ptr, (info_ptr) ? &info_ptr : 0, 0); } return bRet; }
Texture2D* openImage(const char* jpgFile, const char* maskFile) { if (nullptr == jpgFile || '\0' == *jpgFile || nullptr == maskFile || '\0' == *maskFile) return nullptr; Texture2D* ret = Director::getInstance()->getTextureCache()->getTextureForKey(jpgFile); if (ret) return ret; Image* img = new Image(); Image* jpgImg = new Image(); Image* pngImg = new Image(); do { if (!jpgImg->initWithImageFile(jpgFile)) break; if (!pngImg->initWithImageFile(maskFile)) break; unsigned char* jpgData = jpgImg->getData(); unsigned char* pngData = pngImg->getData(); int jpgStep = jpgImg->getBitPerPixel() / 8; int pngStep = pngImg->getBitPerPixel() / 8; int width = jpgImg->getWidth(); int height = jpgImg->getHeight(); ssize_t outDataLen = width*height*4; unsigned char * outData = new unsigned char[outDataLen]; if (!outData) break; int pngIndex = 0; int jpgIndex = 0; unsigned int *tmpData = (unsigned int *)outData; for (int i = 0; i < width*height; i++) { *tmpData++ = CC_RGB_PREMULTIPLY_ALPHA( jpgData[jpgIndex], // R jpgData[jpgIndex + 1], // G jpgData[jpgIndex + 2], // B pngData[pngIndex]); //A jpgIndex += jpgStep; pngIndex += pngStep; } img->initWithRawData(outData, outDataLen, width, height, 4, true); ret = Director::getInstance()->getTextureCache()->addImage(img, jpgFile); delete []outData; break; } while (1); CC_SAFE_DELETE(img); CC_SAFE_DELETE(jpgImg); CC_SAFE_DELETE(pngImg); return ret; }