예제 #1
0
파일: CCImage.cpp 프로젝트: Avnerus/ichigo
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;
}
예제 #2
0
파일: Image.cpp 프로젝트: renbing/Giraffe
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);
}