Exemplo n.º 1
0
FloatPixMapRef FPMCreateWithPNGCustom(png_voidp ioPtr, png_rw_ptr readDataFn, FPMGammaFactor desiredGamma, FPMPNGErrorHandler errorHandler)
{
    png_structp			png = NULL;
    png_infop			pngInfo = NULL;
    png_infop			pngEndInfo = NULL;
    FloatPixMapRef		result = NULL;
    png_uint_32			i, width, height, rowBytes;
    int					depth, colorType;
    png_bytepp			rows = NULL;
    void				*data = NULL;

    png = png_create_read_struct(PNG_LIBPNG_VER_STRING, errorHandler, PNGError, PNGWarning);
    if (png == NULL)  goto FAIL;

    pngInfo = png_create_info_struct(png);
    if (pngInfo == NULL)  goto FAIL;

    pngEndInfo = png_create_info_struct(png);
    if (pngEndInfo == NULL)  goto FAIL;

    if (setjmp(png_jmpbuf(png)))
    {
        // libpng will jump here on error.
        goto FAIL;
    }

    png_set_read_fn(png, ioPtr, readDataFn);

    png_read_info(png, pngInfo);
    if (!png_get_IHDR(png, pngInfo, &width, &height, &depth, &colorType, NULL, NULL, NULL))  goto FAIL;

#if __LITTLE_ENDIAN__
    if (depth == 16)  png_set_swap(png);
#endif
    if (depth <= 8 && !(colorType & PNG_COLOR_MASK_ALPHA))
    {
        png_set_filler(png, 0xFF, PNG_FILLER_AFTER);
    }
    png_set_gray_to_rgb(png);
    if (depth < 8)
    {
        png_set_packing(png);
        png_set_expand(png);
    }

    png_read_update_info(png, pngInfo);
    rowBytes = png_get_rowbytes(png, pngInfo);

    rows = malloc(sizeof *rows * height);
    data = malloc(rowBytes * height);
    if (rows == NULL || data == NULL)  goto FAIL;

    // Set up row pointers.
    for (i = 0; i < height; i++)
    {
        rows[i] = (png_bytep)data + i * rowBytes;
    }

    png_read_image(png, rows);
    png_read_end(png, pngEndInfo);

    free(rows);

    result = ConvertPNGData(data, width, height, rowBytes, png_get_bit_depth(png, pngInfo), png_get_color_type(png, pngInfo));

    if (result != NULL)
    {
        double invGamma = 1.0/kFPMGammaSRGB;
        png_get_gAMA(png, pngInfo, &invGamma);
        FPMApplyGamma(result, 1.0/invGamma, desiredGamma, png_get_bit_depth(png, pngInfo) == 16 ? 65536 : 256);
    }

    png_destroy_read_struct(&png, &pngInfo, &pngEndInfo);
    free(data);

    return result;

FAIL:
    FPMRelease(&result);
    if (png != NULL)  png_destroy_read_struct(&png, &pngInfo, &pngEndInfo);
    free(rows);
    free(data);

    return NULL;
}
Exemplo n.º 2
0
FloatPixMapRef FPMCreateWithPNGCustom(png_voidp ioPtr, png_rw_ptr readDataFn, FPMGammaFactor desiredGamma, FPMPNGErrorHandler errorHandler, FPMPNGProgressHandler progressHandler, void *callbackContext)
{
	png_structp			png = NULL;
	png_infop			pngInfo = NULL;
	png_infop			pngEndInfo = NULL;
	FloatPixMapRef		result = NULL;
	png_uint_32			i, width, height, rowBytes;
	int					depth, colorType;
	void				*data = NULL;
	ErrorInfo			errInfo = { errorHandler, callbackContext };
	
	png = png_create_read_struct(PNG_LIBPNG_VER_STRING, &errInfo, PNGError, PNGWarning);
	if (png == NULL)  goto FAIL;
	
	pngInfo = png_create_info_struct(png);
	if (pngInfo == NULL)  goto FAIL;
	
	pngEndInfo = png_create_info_struct(png);
	if (pngEndInfo == NULL)  goto FAIL;
	
	if (setjmp(png_jmpbuf(png)))
	{
		// libpng will jump here on error.
		goto FAIL;
	}
	
	png_set_read_fn(png, ioPtr, readDataFn);
	
	png_read_info(png, pngInfo);
	if (!png_get_IHDR(png, pngInfo, &width, &height, &depth, &colorType, NULL, NULL, NULL))  goto FAIL;
	
#if FPM_LITTLE_ENDIAN
	if (depth == 16)  png_set_swap(png);
#endif
	if (depth <= 8 && !(colorType & PNG_COLOR_MASK_ALPHA))
	{
		png_set_filler(png, 0xFF, PNG_FILLER_AFTER);
	}
	png_set_gray_to_rgb(png);
	if (depth < 8)
	{
		png_set_packing(png);
		png_set_expand(png);
	}
	
	if (colorType & PNG_COLOR_MASK_PALETTE)
	{
		png_set_palette_to_rgb(png);
	}
	
	png_read_update_info(png, pngInfo);
	rowBytes = png_get_rowbytes(png, pngInfo);
	
	data = malloc(rowBytes * height);
	if (data == NULL)  goto FAIL;
	
	// Set up row pointers.
	for (i = 0; i < height; i++)
	{
		png_read_row(png, (png_bytep)data + i * rowBytes, NULL);
		if (progressHandler)  progressHandler((float)(i + 1) / (float)height, callbackContext);
	}
	
	png_read_end(png, pngEndInfo);
	
	result = ConvertPNGData(data, width, height, rowBytes, png_get_bit_depth(png, pngInfo), png_get_color_type(png, pngInfo));
	
	if (result != NULL)
	{
		double invGamma = 1.0/kFPMGammaSRGB;
		png_get_gAMA(png, pngInfo, &invGamma);
		FPMApplyGamma(result, 1.0/invGamma, desiredGamma, png_get_bit_depth(png, pngInfo) == 16 ? 65536 : 256);
	}
	else
	{
		if (errorHandler != NULL)  errorHandler("Could not convert PNG data to native representation.", true, callbackContext);
	}

	
	png_destroy_read_struct(&png, &pngInfo, &pngEndInfo);
	free(data);
	
	return result;
	
FAIL:
	FPMRelease(&result);
	if (png != NULL)  png_destroy_read_struct(&png, &pngInfo, &pngEndInfo);
	free(data);
	
	return NULL;
}