Example #1
0
    void set_user_transform_info(void* info, int bit_depth, int channels)
    {
        TRACE_IO_TRANSFORM("png_set_user_transform_info: bit_depth=%d,"
                           " channels=%d\n", bit_depth, channels);

        png_set_user_transform_info(m_png, info, bit_depth, channels);
    }
Example #2
0
HGLOBAL CPng::PNGToDIB(png_structp png_ptr, png_infop info_ptr)
{
	//Read the image
	png_read_info(png_ptr, info_ptr);

	int nBitDepth = 0;
	int nColorType = 0;
	png_uint_32 width = 0;
	png_uint_32 height = 0;
	png_get_IHDR(png_ptr, info_ptr, &width, &height, &nBitDepth, &nColorType, NULL, NULL, NULL);

	IMAGE img;
	img.width = (LONG)width;
	img.height = (LONG)height;

	//Determine the type of format
	if (nColorType==PNG_COLOR_TYPE_RGB || nColorType==PNG_COLOR_TYPE_RGB_ALPHA)
	{
		img.pixdepth = 24;		// nBitDepth 8, 16
		img.palnum   = 0;
	}
	else
	{
		switch(nBitDepth) // bit depths 1, 2, 4, 8, 16
		{	
			case 2:  
				img.pixdepth = 4;		
				break;
			case 16: 
				img.pixdepth = 8;		
				break;
			default: 
				img.pixdepth = nBitDepth;
		}

		img.palnum = 1 << img.pixdepth;
	}

	//Allocate the image struct that will be used to transport file info
	if (!AllocImageStruct(&img))
	{
		longjmp(png_ptr->jmpbuf, 1);
	}

	//Not sure if we can take advantage of this info in a BMP, thus remove it.
	if (nColorType & PNG_COLOR_MASK_ALPHA)
		png_set_strip_alpha(png_ptr);

	//Set user transform function to deal with a Bitdepth of 2
	if (nBitDepth == 2)
	{
		png_set_user_transform_info(png_ptr, NULL, 4, 1);
		png_set_read_user_transform_fn(png_ptr, ConvertTo4BitsPerPix);
	}

	//Tell libpng to strip 16 bit/color files down to 8 bits/color
	if (nBitDepth == 16) 
		png_set_strip_16(png_ptr);

	if (nColorType==PNG_COLOR_TYPE_RGB || nColorType==PNG_COLOR_TYPE_RGB_ALPHA)
	{
		png_set_bgr(png_ptr);
	}

	png_read_update_info(png_ptr, info_ptr);

	//If palette, get it and fill our img struct
	if (img.palnum > 0)
	{
		if (nColorType == PNG_COLOR_TYPE_PALETTE)
		{
			png_colorp palette;
			int num_palette;
			png_get_PLTE(png_ptr, info_ptr, &palette, &num_palette);
			if (num_palette > (int)img.palnum) 
				num_palette = img.palnum;

			memset(img.palette, 0, img.palnum * sizeof(png_color));
			memcpy(img.palette, palette, num_palette * sizeof(png_color));
		}
		else
		{
			int depth = (nBitDepth == 16)? 8 : nBitDepth ;
			png_build_grayscale_palette(depth, img.palette);
		}
	}

	png_read_image(png_ptr, img.rowptr);

	png_infop end_info = NULL;
	png_read_end(png_ptr, end_info);

	// Alloc the buffer to be big enough to hold all the bits
	DWORD dwLen = (DWORD)sizeof(BITMAPINFOHEADER) + (img.palnum * sizeof(RGBQUAD)) + img.imgbytes;

	// Allocate enough memory to hold the entire DIB
	HGLOBAL hMemory = ::GlobalAlloc(GMEM_FIXED | GMEM_ZEROINIT, dwLen);
	if (!hMemory)
		return NULL;

	//Begin filling out DIB info
	BITMAPINFOHEADER* pDib = (BITMAPINFOHEADER*)::GlobalLock(hMemory);
	if (!pDib)
	{
		::GlobalFree(hMemory);
		return NULL;
	}

	::ZeroMemory(pDib, dwLen);
	pDib->biSize			= sizeof(BITMAPINFOHEADER);
	pDib->biWidth			= (DWORD)img.width; 
	pDib->biHeight			= (DWORD)img.height; 
	pDib->biPlanes			= 1;
	pDib->biCompression		= BI_RGB;
	pDib->biXPelsPerMeter	= 3937; // 100 pixels/inch
	pDib->biYPelsPerMeter	= 3937;
	pDib->biSizeImage		= img.imgbytes;
	pDib->biBitCount		= img.pixdepth; 
	pDib->biClrUsed			= img.palnum;

	if (pDib->biBitCount >= 16)
		pDib->biBitCount = 24;	

	if (pDib->biClrUsed)
	{
		RGBQUAD* pRgb = DibColors(pDib);
		BYTE rgbq[RGBQUAD_SIZE];
		PALETTE* pal;
		UINT nIndex;
		memset(rgbq, 0, sizeof(rgbq));
		for (pal = img.palette, nIndex = img.palnum ; nIndex > 0 ; nIndex--, pal++)
		{
			rgbq[RGBQ_RED]			= pal->red;
			rgbq[RGBQ_GREEN]		= pal->green;
			rgbq[RGBQ_BLUE]			= pal->blue;
			rgbq[RGBQ_RESERVED]		= 0;
			memcpy((LPVOID)pRgb, rgbq, sizeof(RGBQUAD));
			pRgb++;
		}
	}

	memcpy(DibPtr(pDib), img.bmpbits, DibSizeImage(pDib));

	FreeImageStruct(&img);

	::GlobalUnlock(hMemory);
	return hMemory;
}
Example #3
0
static uint8_t png_write( png_structp writePtr, png_image * image, uint32_t flags )
{
	const uint32_t  h = image->height;
	const uint32_t  w = image->width;
	const uint8_t * p = image->data;
	const uint32_t  bitDepth = 8;
	const uint32_t  channels = 4;
	
	png_infop infoPtr = png_create_info_struct( writePtr );
	if (!infoPtr) 
	{
		pngio_error( "Couldn't initialize PNG info struct" );
		png_destroy_write_struct( & writePtr, NULL );
		return 0;
	}
	
	if (setjmp( png_jmpbuf( writePtr ) )) 
	{
		png_destroy_write_struct( & writePtr, & infoPtr );
		pngio_error( "An error occured while writing the PNG file." );
		return 0;
	}

	png_set_filter( writePtr, 0, PNG_FILTER_NONE );
	
	#ifdef PNG_APPLE_MODE_SUPPORTED
	if (png_get_apple_mode())
	{
		png_write_sig( writePtr );
		png_set_sig_bytes( writePtr, 8 );
		png_set_compression_window_bits( writePtr, -15 );
		png_set_write_user_transform_fn( writePtr, png_write_swap_and_premultiply_transform );
		png_set_user_transform_info( writePtr, NULL, bitDepth, channels );
	}
	#endif
	
	png_set_IHDR( writePtr, infoPtr, w, h, bitDepth, PNG_COLOR_TYPE_RGBA, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT );
	png_set_gAMA( writePtr, infoPtr, 0.45455 );
	png_set_cHRM( writePtr, infoPtr, 0.312700, 0.329, 0.64, 0.33, 0.3, 0.6, 0.15, 0.06 );
	png_set_sRGB( writePtr, infoPtr, 0);
	
	#ifdef PNG_APPLE_MODE_SUPPORTED
	if (png_get_apple_mode())
	{
		png_byte cname[] = { 'C', 'g', 'B', 'I', '\0' };
		png_byte cdata[] = { 0x50, 0x00, 0x20, 0x02 };
		png_write_chunk( writePtr, cname, cdata, 4 );
	}
	#endif

	png_write_info( writePtr, infoPtr );	

	const size_t bytesPerRow = w * 4;
	if (flags & PNG_IMAGE_FLIP_VERTICAL)
	{
		for (size_t i = 0; i < h; i++) 
		{
			png_write_row( writePtr, p + (bytesPerRow * (h - i - 1)) );
		}
	}
	else
	{
		for (size_t i = 0; i < h; i++) 
		{
			png_write_row( writePtr, p + (bytesPerRow * i) );
		}
	}
	
	png_write_end( writePtr, infoPtr );
	png_destroy_write_struct( & writePtr, & infoPtr );
	
	return 1;
}
Example #4
0
static uint8_t png_read( png_structp readPtr, png_image * image, uint32_t flags )
{
//	png_set_error_fn( readPtr, NULL, png_user_error, NULL );

	png_infop infoPtr = png_create_info_struct( readPtr );
	if (!infoPtr) 
	{
		pngio_error( "Couldn't initialize PNG info struct." );
		png_destroy_read_struct( & readPtr, NULL, NULL );
		return 0;
	}
	
	if (setjmp( png_jmpbuf( readPtr ) ))
	{
		pngio_error( "An error occured while reading the PNG file." );
		png_destroy_read_struct( & readPtr, & infoPtr, NULL );
		png_image_free( image );
		return 0;
	}

	png_set_sig_bytes( readPtr, 8 );
	
	#ifdef PNG_APPLE_MODE_SUPPORTED 
	if (png_get_apple_mode())
	{
		png_set_keep_unknown_chunks( readPtr, PNG_HANDLE_CHUNK_ALWAYS, NULL, 0 );
		png_set_read_user_chunk_fn( readPtr, NULL, png_read_user_chunk );
	}
	#endif
	
	png_read_info( readPtr, infoPtr );
	
	png_uint_32 w = png_get_image_width( readPtr, infoPtr );
	png_uint_32 h = png_get_image_height( readPtr, infoPtr );
	png_uint_32 bitDepth = png_get_bit_depth( readPtr, infoPtr );
	png_uint_32 channels = png_get_channels( readPtr, infoPtr );
	png_uint_32 interlaceType = png_get_interlace_type( readPtr, infoPtr );
	png_uint_32 colorType = png_get_color_type( readPtr, infoPtr );
	
	switch (colorType) 
	{
		case PNG_COLOR_TYPE_PALETTE:
			png_set_palette_to_rgb( readPtr );
			channels = 3;           
			break;
		case PNG_COLOR_TYPE_GRAY:
			if (bitDepth < 8)
			{
				png_set_expand_gray_1_2_4_to_8( readPtr );
				bitDepth = 8;
			}
			png_set_gray_to_rgb( readPtr );
			break;
	}
	
	if (png_get_valid( readPtr, infoPtr, PNG_INFO_tRNS )) 
	{
		png_set_tRNS_to_alpha( readPtr );
		channels += 1;
	}
	else if (!(colorType & PNG_COLOR_MASK_ALPHA)) 
	{
		png_set_add_alpha( readPtr, 0xff, PNG_FILLER_AFTER );
	}
	
	if (bitDepth == 16)
	{
		png_set_strip_16( readPtr );
	}

	#ifdef PNG_APPLE_MODE_SUPPORTED
	if (png_get_apple_mode())
	{
		if (flags & PNG_IMAGE_PREMULTIPLY_ALPHA)
		{
			png_set_read_user_transform_fn( readPtr, png_read_swap_transform );
		}
		else
		{
			png_set_read_user_transform_fn( readPtr, png_read_swap_and_unpremultiply_transform );
		}
		png_set_user_transform_info( readPtr, NULL, bitDepth, channels );
		png_read_update_info( readPtr, infoPtr );
	}
	else
	#endif
	{
		if (flags & PNG_IMAGE_PREMULTIPLY_ALPHA)
		{
			png_set_read_user_transform_fn( readPtr, png_read_premultiply_transform );
		}
	}

	png_image_alloc( image, w, h );
	png_bytep p = image->data;
	
	const size_t passCount = interlaceType == PNG_INTERLACE_NONE ? 1 : png_set_interlace_handling( readPtr );
	const size_t bytesPerRow = w * 4;
	if (flags & PNG_IMAGE_FLIP_VERTICAL)
	{
		for (size_t pass = 0; pass < passCount; pass++)
		{
			for (size_t i = 0; i < h; i++) 
			{
				png_read_row( readPtr, p + (bytesPerRow * (h - i - 1)), NULL );
			}
		}
	}
	else
	{
//		png_bytep rp[h];
//		for (size_t i = 0; i < h; i++) 
//		{
//			rp[i] = p + (bytesPerRow * i);
//		}
//		png_read_image( readPtr, rp );
		for (size_t pass = 0; pass < passCount; pass++)
		{
			for (size_t i = 0; i < h; i++) 
			{
				png_read_row( readPtr, p + (bytesPerRow * i), NULL );
			}
		}
	}
	
	png_destroy_read_struct( & readPtr, & infoPtr, NULL );
	
	return 1;
}