Exemple #1
0
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;
}