FreeImage icon indicating copy to clipboard operation
FreeImage copied to clipboard

`.exr` File Saved with 16-bit Depth Instead of 32-bit Float When Using `EXR_FLOAT`

Open karel-tomanec opened this issue 11 months ago • 0 comments

Description

When saving a .exr file using FreeImage with a FIBITMAP of type FIT_RGBF and the EXR_FLOAT flag, the resulting file is saved with a 16-bit depth per channel instead of the expected 32-bit float depth. This behavior persists even though the EXR_FLOAT flag is explicitly passed to the FreeImage_Save function.

My code:

Click to expand code
#include <FreeImage.h>
#include <iostream>
#include <string>

FIBITMAP* CreateTestImage(unsigned width, unsigned height)
{
	FIBITMAP* bitmap = FreeImage_AllocateT(FIT_RGBF, width, height);
	if (!bitmap)
	{
		std::cerr << "Failed to allocate image." << std::endl;
		return nullptr;
	}

	// Fill the image with a gradient
	float* bits = reinterpret_cast<float*>(FreeImage_GetBits(bitmap));
	for (unsigned y = 0; y < height; ++y)
	{
		for (unsigned x = 0; x < width; ++x)
		{
			unsigned index = (y * width + x) * 3;
			bits[index + 0] = static_cast<float>(x) / width;
			bits[index + 1] = static_cast<float>(y) / height;
			bits[index + 2] = 0.5f;
		}
	}

	return bitmap;
}

void SaveTestImage(const std::string& filename, FIBITMAP* bitmap, int flags)
{
	if (!bitmap)
	{
		std::cerr << "Invalid bitmap, cannot save." << std::endl;
		return;
	}

	unsigned width = FreeImage_GetWidth(bitmap);
	unsigned height = FreeImage_GetHeight(bitmap);
	unsigned bpp = FreeImage_GetBPP(bitmap);
	FREE_IMAGE_TYPE type = FreeImage_GetImageType(bitmap);

	std::cout << "Image properties:" << std::endl;
	std::cout << "  Width: " << width << std::endl;
	std::cout << "  Height: " << height << std::endl;
	std::cout << "  Bits per pixel: " << bpp << std::endl;
	std::cout << "  Image type: " << type << std::endl;

	std::cout << "Saving image to " << filename << "..." << std::endl;
	if (FreeImage_Save(FIF_EXR, bitmap, filename.c_str(), flags))
	{
		std::cout << "Image saved successfully: " << filename << std::endl;
	}
	else
	{
		std::cerr << "Failed to save image: " << filename << std::endl;
	}
}

int main()
{
	FreeImage_Initialise();

	const unsigned width = 512;
	const unsigned height = 512;
	const std::string filename = "test_image.exr";

	FIBITMAP* bitmap = CreateTestImage(width, height);
	if (!bitmap)
	{
		FreeImage_DeInitialise();
		return 1;
	}

	int flags = EXR_FLOAT;
	SaveTestImage(filename, bitmap, flags);

	FreeImage_Unload(bitmap);
	FreeImage_DeInitialise();

	return 0;
}

magick output:

Click to expand loge
 magick identify -verbose test_image.exr
Image:
  Filename: test_image.exr
  Permissions: rw-rw-rw-
  Format: EXR (High Dynamic-range (HDR))
  Class: DirectClass
  Geometry: 512x512+0+0
  Units: Undefined
  Colorspace: sRGB
  Type: TrueColor
  Base type: Undefined
  Endianness: Undefined
  Depth: 16-bit
  Channels: 3.0
  Channel depth:
    Red: 16-bit
    Green: 16-bit
    Blue: 16-bit
  Channel statistics:
    Pixels: 262144
    Red:
      min: 0  (0)
      max: 65407 (0.998047)
      mean: 32703.5 (0.499023)
      median: 32639.5 (0.498047)
      standard deviation: 18918.3 (0.288675)
      kurtosis: -1.20002
      skewness: -9.10919e-10
      entropy: 1
    Green:
      min: 0  (0)
      max: 65407 (0.998047)
      mean: 32703.5 (0.499023)
      median: 32639.5 (0.498047)
      standard deviation: 18918.3 (0.288675)
      kurtosis: -1.20002
      skewness: -9.10884e-10
      entropy: 1
    Blue:
      min: 32767.5  (0.5)
      max: 32767.5 (0.5)
      mean: 32767.5 (0.5)
      median: 32767.5 (0.5)
      standard deviation: 0 (0)
      kurtosis: 0
      skewness: 0
      entropy: 0
  Image statistics:
    Overall:
      min: 0  (0)
      max: 65407 (0.998047)
      mean: 32724.8 (0.499349)
      median: 32682.2 (0.498698)
      standard deviation: 12612.2 (0.19245)
      kurtosis: -0.800015
      skewness: -6.07268e-10
      entropy: 0.666667
  Rendering intent: Perceptual
  Gamma: 1
  Chromaticity:
    red primary: (0.64,0.33,0.03)
    green primary: (0.3,0.6,0.1)
    blue primary: (0.15,0.06,0.79)
    white point: (0.3127,0.329,0.3583)
  Matte color: grey74
  Background color: white
  Border color: srgb(223,223,223)
  Transparent color: black
  Interlace: None
  Intensity: Undefined
  Compose: Over
  Page geometry: 512x512+0+0
  Dispose: Undefined
  Iterations: 0
  Compression: Piz
  Orientation: Undefined
  Properties:
    date:create: 2025-01-28T10:44:56+00:00
    date:modify: 2025-01-28T11:12:23+00:00
    date:timestamp: 2025-01-28T11:18:29+00:00
    signature: e3e00cda1b1142bd3ac1a130f916bddddfdde7e6f4442f15fa24bef51628bfe3
  Artifacts:
    verbose: true
  Tainted: False
  Filesize: 203153B
  Number pixels: 262144
  Pixel cache type: Memory
  Pixels per second: 48.2761MP
  User time: 0.005u
  Elapsed time: 0:01.005
  Version: ImageMagick 7.1.1-36 Q16-HDRI x64 852a4e9:20240727 https://imagemagick.org

Expected Behaviour

The .exr file should be saved with 32-bit float depth per channel.

karel-tomanec avatar Jan 28 '25 11:01 karel-tomanec