Alien-FreeImage

 view release on metacpan or  search on metacpan

src/Source/FreeImage/PluginPNG.cpp  view on Meta::CPAN

			(depth == 8) ||
			(depth == 24) ||
			(depth == 32)
		);
}

static BOOL DLL_CALLCONV 
SupportsExportType(FREE_IMAGE_TYPE type) {
	return (
		(type == FIT_BITMAP) ||
		(type == FIT_UINT16) ||
		(type == FIT_RGB16) ||
		(type == FIT_RGBA16)
	);
}

static BOOL DLL_CALLCONV
SupportsICCProfiles() {
	return TRUE;
}

static BOOL DLL_CALLCONV
SupportsNoPixels() {
	return TRUE;
}

// --------------------------------------------------------------------------

/**
Configure the decoder so that decoded pixels are compatible with a FREE_IMAGE_TYPE format. 
Set conversion instructions as needed. 
@param png_ptr PNG handle
@param info_ptr PNG info handle
@param flags Decoder flags
@param output_image_type Returned FreeImage converted image type
@return Returns TRUE if successful, returns FALSE otherwise
@see png_read_update_info
*/
static BOOL 
ConfigureDecoder(png_structp png_ptr, png_infop info_ptr, int flags, FREE_IMAGE_TYPE *output_image_type) {
	// get original image info
	const int color_type = png_get_color_type(png_ptr, info_ptr);
	const int bit_depth = png_get_bit_depth(png_ptr, info_ptr);
	const int pixel_depth = bit_depth * png_get_channels(png_ptr, info_ptr);

	FREE_IMAGE_TYPE image_type = FIT_BITMAP;	// assume standard image type

	// check for transparency table or single transparent color
	BOOL bIsTransparent = png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS) == PNG_INFO_tRNS ? TRUE : FALSE;

	// check allowed combinations of colour type and bit depth
	// then get converted FreeImage type

	switch(color_type) {
		case PNG_COLOR_TYPE_GRAY:		// color type '0', bitdepth = 1, 2, 4, 8, 16
			switch(bit_depth) {
				case 1:
				case 2:
				case 4:
				case 8:
					// expand grayscale images to the full 8-bit from 2-bit/pixel
					if (pixel_depth == 2) {
						png_set_expand_gray_1_2_4_to_8(png_ptr);
					}

					// if a tRNS chunk is provided, we must also expand the grayscale data to 8-bits,
					// this allows us to make use of the transparency table with existing FreeImage methods
					if (bIsTransparent && (pixel_depth < 8)) {
						png_set_expand_gray_1_2_4_to_8(png_ptr);
					}
					break;

				case 16:
					image_type = (pixel_depth == 16) ? FIT_UINT16 : FIT_UNKNOWN;

					// 16-bit grayscale images can contain a transparent value (shade)
					// if found, expand the transparent value to a full alpha channel
					if (bIsTransparent && (image_type != FIT_UNKNOWN)) {
						// expand tRNS to a full alpha channel
						png_set_tRNS_to_alpha(png_ptr);
						
						// expand new 16-bit gray + 16-bit alpha to full 64-bit RGBA
						png_set_gray_to_rgb(png_ptr);

						image_type = FIT_RGBA16;
					}
					break;

				default:
					image_type = FIT_UNKNOWN;
					break;
			}
			break;

		case PNG_COLOR_TYPE_RGB:		// color type '2', bitdepth = 8, 16
			switch(bit_depth) {
				case 8:
					image_type = (pixel_depth == 24) ? FIT_BITMAP : FIT_UNKNOWN;
					break;
				case 16:
					image_type = (pixel_depth == 48) ? FIT_RGB16 : FIT_UNKNOWN;
					break;
				default:
					image_type = FIT_UNKNOWN;
					break;
			}
			// sometimes, 24- or 48-bit images may contain transparency information
			// check for this use case and convert to an alpha-compatible format
			if (bIsTransparent && (image_type != FIT_UNKNOWN)) {
				// if the image is 24-bit RGB, mark it as 32-bit; if it is 48-bit, mark it as 64-bit
				image_type = (pixel_depth == 24) ? FIT_BITMAP : (pixel_depth == 48) ? FIT_RGBA16 : FIT_UNKNOWN;
				// expand tRNS chunk to alpha channel
				png_set_tRNS_to_alpha(png_ptr);
			}
			break;

		case PNG_COLOR_TYPE_PALETTE:	// color type '3', bitdepth = 1, 2, 4, 8
			switch(bit_depth) {
				case 1:
				case 2:
				case 4:
				case 8:
					// expand palette images to the full 8 bits from 2 bits/pixel
					if (pixel_depth == 2) {
						png_set_packing(png_ptr);
					}

					// if a tRNS chunk is provided, we must also expand the palletized data to 8-bits,
					// this allows us to make use of the transparency table with existing FreeImage methods
					if (bIsTransparent && (pixel_depth < 8)) {
						png_set_packing(png_ptr);
					}
					break;

				default:
					image_type = FIT_UNKNOWN;
					break;
			}
			break;

		case PNG_COLOR_TYPE_GRAY_ALPHA:	// color type '4', bitdepth = 8, 16
			switch(bit_depth) {
				case 8:
					// 8-bit grayscale + 8-bit alpha => convert to 32-bit RGBA
					image_type = (pixel_depth == 16) ? FIT_BITMAP : FIT_UNKNOWN;
					break;
				case 16:
					// 16-bit grayscale + 16-bit alpha => convert to 64-bit RGBA
					image_type = (pixel_depth == 32) ? FIT_RGBA16 : FIT_UNKNOWN;
					break;
				default:
					image_type = FIT_UNKNOWN;
					break;
			}
			// expand 8-bit greyscale + 8-bit alpha to 32-bit
			// expand 16-bit greyscale + 16-bit alpha to 64-bit
			png_set_gray_to_rgb(png_ptr);
			break;

		case PNG_COLOR_TYPE_RGB_ALPHA:	// color type '6', bitdepth = 8, 16
			switch(bit_depth) {
				case 8:
					break;
				case 16:
					image_type = (pixel_depth == 64) ? FIT_RGBA16 : FIT_UNKNOWN;
					break;
				default:
					image_type = FIT_UNKNOWN;
					break;
			}
			break;
	}

	// check for unknown or invalid formats
	if(image_type == FIT_UNKNOWN) {
		*output_image_type = image_type;
		return FALSE;
	}

#ifndef FREEIMAGE_BIGENDIAN
	if((image_type == FIT_UINT16) || (image_type == FIT_RGB16) || (image_type == FIT_RGBA16)) {
		// turn on 16-bit byte swapping
		png_set_swap(png_ptr);
	}
#endif						

#if FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_BGR
	if((image_type == FIT_BITMAP) && ((color_type == PNG_COLOR_TYPE_RGB) || (color_type == PNG_COLOR_TYPE_RGB_ALPHA))) {
		// flip the RGB pixels to BGR (or RGBA to BGRA)
		png_set_bgr(png_ptr);
	}
#endif

	// gamma correction
	// unlike the example in the libpng documentation, we have *no* idea where
	// this file may have come from--so if it doesn't have a file gamma, don't
	// do any correction ("do no harm")

	if (png_get_valid(png_ptr, info_ptr, PNG_INFO_gAMA)) {
		double gamma = 0;
		double screen_gamma = 2.2;

		if (png_get_gAMA(png_ptr, info_ptr, &gamma) && ( flags & PNG_IGNOREGAMMA ) != PNG_IGNOREGAMMA) {
			png_set_gamma(png_ptr, screen_gamma, gamma);
		}
	}

	// all transformations have been registered; now update info_ptr data		
	png_read_update_info(png_ptr, info_ptr);

	// return the output image type
	*output_image_type = image_type;

	return TRUE;
}



( run in 1.423 second using v1.01-cache-2.11-cpan-5b529ec07f3 )