OpenEXR: Preserve compression and depth settings when re-saving file
Set the flags on the image buffer when loading an EXR file, so they can be used when saving. This also removes IB_halffloat and replaces it by the file options flag. Pull Request: https://projects.blender.org/blender/blender/pulls/135656
This commit is contained in:
committed by
Brecht Van Lommel
parent
202db40afb
commit
afee81753e
@@ -818,12 +818,51 @@ void BKE_image_format_to_imbuf(ImBuf *ibuf, const ImageFormatData *imf)
|
||||
}
|
||||
}
|
||||
|
||||
static char imtype_best_depth(const ImBuf *ibuf, const char imtype)
|
||||
{
|
||||
const char depth_ok = BKE_imtype_valid_depths(imtype);
|
||||
|
||||
if (ibuf->float_buffer.data) {
|
||||
if (depth_ok & R_IMF_CHAN_DEPTH_32) {
|
||||
return R_IMF_CHAN_DEPTH_32;
|
||||
}
|
||||
if (depth_ok & R_IMF_CHAN_DEPTH_24) {
|
||||
return R_IMF_CHAN_DEPTH_24;
|
||||
}
|
||||
if (depth_ok & R_IMF_CHAN_DEPTH_16) {
|
||||
return R_IMF_CHAN_DEPTH_16;
|
||||
}
|
||||
if (depth_ok & R_IMF_CHAN_DEPTH_12) {
|
||||
return R_IMF_CHAN_DEPTH_12;
|
||||
}
|
||||
return R_IMF_CHAN_DEPTH_8;
|
||||
}
|
||||
|
||||
if (depth_ok & R_IMF_CHAN_DEPTH_8) {
|
||||
return R_IMF_CHAN_DEPTH_8;
|
||||
}
|
||||
if (depth_ok & R_IMF_CHAN_DEPTH_12) {
|
||||
return R_IMF_CHAN_DEPTH_12;
|
||||
}
|
||||
if (depth_ok & R_IMF_CHAN_DEPTH_16) {
|
||||
return R_IMF_CHAN_DEPTH_16;
|
||||
}
|
||||
if (depth_ok & R_IMF_CHAN_DEPTH_24) {
|
||||
return R_IMF_CHAN_DEPTH_24;
|
||||
}
|
||||
if (depth_ok & R_IMF_CHAN_DEPTH_32) {
|
||||
return R_IMF_CHAN_DEPTH_32;
|
||||
}
|
||||
return R_IMF_CHAN_DEPTH_8; /* fallback, should not get here */
|
||||
}
|
||||
|
||||
void BKE_image_format_from_imbuf(ImageFormatData *im_format, const ImBuf *imbuf)
|
||||
{
|
||||
/* Read from ImBuf after file read. */
|
||||
int ftype = imbuf->ftype;
|
||||
int custom_flags = imbuf->foptions.flag;
|
||||
char quality = imbuf->foptions.quality;
|
||||
bool is_depth_set = false;
|
||||
|
||||
BKE_image_format_init(im_format, false);
|
||||
|
||||
@@ -839,6 +878,7 @@ void BKE_image_format_from_imbuf(ImageFormatData *im_format, const ImBuf *imbuf)
|
||||
|
||||
if (custom_flags & PNG_16BIT) {
|
||||
im_format->depth = R_IMF_CHAN_DEPTH_16;
|
||||
is_depth_set = true;
|
||||
}
|
||||
|
||||
im_format->compress = quality;
|
||||
@@ -853,6 +893,7 @@ void BKE_image_format_from_imbuf(ImageFormatData *im_format, const ImBuf *imbuf)
|
||||
im_format->imtype = R_IMF_IMTYPE_TIFF;
|
||||
if (custom_flags & TIF_16BIT) {
|
||||
im_format->depth = R_IMF_CHAN_DEPTH_16;
|
||||
is_depth_set = true;
|
||||
}
|
||||
if (custom_flags & TIF_COMPRESS_NONE) {
|
||||
im_format->tiff_codec = R_IMF_TIFF_CODEC_NONE;
|
||||
@@ -871,11 +912,17 @@ void BKE_image_format_from_imbuf(ImageFormatData *im_format, const ImBuf *imbuf)
|
||||
#ifdef WITH_OPENEXR
|
||||
else if (ftype == IMB_FTYPE_OPENEXR) {
|
||||
im_format->imtype = R_IMF_IMTYPE_OPENEXR;
|
||||
char exr_codec = custom_flags & OPENEXR_CODEC_MASK;
|
||||
if (custom_flags & OPENEXR_HALF) {
|
||||
im_format->depth = R_IMF_CHAN_DEPTH_16;
|
||||
is_depth_set = true;
|
||||
}
|
||||
if (custom_flags & OPENEXR_CODEC_MASK) {
|
||||
im_format->exr_codec = R_IMF_EXR_CODEC_ZIP; /* Can't determine compression */
|
||||
else if (exr_codec == R_IMF_EXR_CODEC_B44 || exr_codec == R_IMF_EXR_CODEC_B44A) {
|
||||
/* B44 and B44A are only selectable for half precision images, default to ZIP compression */
|
||||
exr_codec = R_IMF_EXR_CODEC_ZIP;
|
||||
}
|
||||
if (exr_codec < R_IMF_EXR_CODEC_MAX) {
|
||||
im_format->exr_codec = exr_codec;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -903,9 +950,11 @@ void BKE_image_format_from_imbuf(ImageFormatData *im_format, const ImBuf *imbuf)
|
||||
|
||||
if (custom_flags & JP2_16BIT) {
|
||||
im_format->depth = R_IMF_CHAN_DEPTH_16;
|
||||
is_depth_set = true;
|
||||
}
|
||||
else if (custom_flags & JP2_12BIT) {
|
||||
im_format->depth = R_IMF_CHAN_DEPTH_12;
|
||||
is_depth_set = true;
|
||||
}
|
||||
|
||||
if (custom_flags & JP2_YCC) {
|
||||
@@ -942,6 +991,11 @@ void BKE_image_format_from_imbuf(ImageFormatData *im_format, const ImBuf *imbuf)
|
||||
im_format->quality = quality;
|
||||
}
|
||||
|
||||
/* Default depth, accounting for float buffer and format support */
|
||||
if (!is_depth_set) {
|
||||
im_format->depth = imtype_best_depth(imbuf, im_format->imtype);
|
||||
}
|
||||
|
||||
/* planes */
|
||||
im_format->planes = imbuf->planes;
|
||||
}
|
||||
|
||||
@@ -42,44 +42,6 @@
|
||||
|
||||
using blender::Vector;
|
||||
|
||||
static char imtype_best_depth(ImBuf *ibuf, const char imtype)
|
||||
{
|
||||
const char depth_ok = BKE_imtype_valid_depths(imtype);
|
||||
|
||||
if (ibuf->float_buffer.data) {
|
||||
if (depth_ok & R_IMF_CHAN_DEPTH_32) {
|
||||
return R_IMF_CHAN_DEPTH_32;
|
||||
}
|
||||
if (depth_ok & R_IMF_CHAN_DEPTH_24) {
|
||||
return R_IMF_CHAN_DEPTH_24;
|
||||
}
|
||||
if (depth_ok & R_IMF_CHAN_DEPTH_16) {
|
||||
return R_IMF_CHAN_DEPTH_16;
|
||||
}
|
||||
if (depth_ok & R_IMF_CHAN_DEPTH_12) {
|
||||
return R_IMF_CHAN_DEPTH_12;
|
||||
}
|
||||
return R_IMF_CHAN_DEPTH_8;
|
||||
}
|
||||
|
||||
if (depth_ok & R_IMF_CHAN_DEPTH_8) {
|
||||
return R_IMF_CHAN_DEPTH_8;
|
||||
}
|
||||
if (depth_ok & R_IMF_CHAN_DEPTH_12) {
|
||||
return R_IMF_CHAN_DEPTH_12;
|
||||
}
|
||||
if (depth_ok & R_IMF_CHAN_DEPTH_16) {
|
||||
return R_IMF_CHAN_DEPTH_16;
|
||||
}
|
||||
if (depth_ok & R_IMF_CHAN_DEPTH_24) {
|
||||
return R_IMF_CHAN_DEPTH_24;
|
||||
}
|
||||
if (depth_ok & R_IMF_CHAN_DEPTH_32) {
|
||||
return R_IMF_CHAN_DEPTH_32;
|
||||
}
|
||||
return R_IMF_CHAN_DEPTH_8; /* fallback, should not get here */
|
||||
}
|
||||
|
||||
bool BKE_image_save_options_init(ImageSaveOptions *opts,
|
||||
Main *bmain,
|
||||
Scene *scene,
|
||||
@@ -108,13 +70,11 @@ bool BKE_image_save_options_init(ImageSaveOptions *opts,
|
||||
ImBuf *ibuf = BKE_image_acquire_ibuf(ima, iuser, &lock);
|
||||
|
||||
if (ibuf) {
|
||||
bool is_depth_set = false;
|
||||
const char *ima_colorspace = ima->colorspace_settings.name;
|
||||
|
||||
if (opts->save_as_render) {
|
||||
/* Render/compositor output or user chose to save with render settings. */
|
||||
BKE_image_format_init_for_write(&opts->im_format, scene, nullptr);
|
||||
is_depth_set = true;
|
||||
if (!BKE_image_is_multiview(ima)) {
|
||||
/* In case multiview is disabled,
|
||||
* render settings would be invalid for render result in this area. */
|
||||
@@ -156,11 +116,6 @@ bool BKE_image_save_options_init(ImageSaveOptions *opts,
|
||||
opts->im_format.planes = R_IMF_PLANES_RGBA;
|
||||
}
|
||||
|
||||
/* depth, account for float buffer and format support */
|
||||
if (is_depth_set == false) {
|
||||
opts->im_format.depth = imtype_best_depth(ibuf, opts->im_format.imtype);
|
||||
}
|
||||
|
||||
/* some formats don't use quality so fallback to scenes quality */
|
||||
if (opts->im_format.quality == 0) {
|
||||
opts->im_format.quality = scene->r.im_format.quality;
|
||||
|
||||
@@ -283,7 +283,7 @@ CachedImage::CachedImage(Context &context,
|
||||
ImBuf *image_buffer = BKE_image_acquire_ibuf(image, &image_user_for_pass, nullptr);
|
||||
ImBuf *linear_image_buffer = compute_linear_buffer(image_buffer);
|
||||
|
||||
const bool use_half_float = linear_image_buffer->flags & IB_halffloat;
|
||||
const bool use_half_float = linear_image_buffer->foptions.flag & OPENEXR_HALF;
|
||||
this->result.set_precision(use_half_float ? ResultPrecision::Half : ResultPrecision::Full);
|
||||
|
||||
this->result.set_type(get_result_type(render_result, image_user_for_pass, linear_image_buffer));
|
||||
|
||||
@@ -943,7 +943,7 @@ void uiTemplateImage(uiLayout *layout,
|
||||
void *lock;
|
||||
ImBuf *ibuf = BKE_image_acquire_ibuf(ima, iuser, &lock);
|
||||
|
||||
if (ibuf && ibuf->float_buffer.data && (ibuf->flags & IB_halffloat) == 0) {
|
||||
if (ibuf && ibuf->float_buffer.data && (ibuf->foptions.flag & OPENEXR_HALF) == 0) {
|
||||
uiItemR(col, &imaptr, "use_half_precision", UI_ITEM_NONE, std::nullopt, ICON_NONE);
|
||||
}
|
||||
BKE_image_release_ibuf(ima, ibuf, lock);
|
||||
|
||||
@@ -102,7 +102,6 @@ enum eImBufFlags {
|
||||
/** ignore alpha on load and substitute it with 1.0f */
|
||||
IB_alphamode_ignore = 1 << 15,
|
||||
IB_thumbnail = 1 << 16,
|
||||
IB_halffloat = 1 << 18,
|
||||
};
|
||||
|
||||
/** \} */
|
||||
|
||||
@@ -203,7 +203,7 @@ static ImBuf *get_oiio_ibuf(ImageInput *in, const ReadContext &ctx, char colorsp
|
||||
/* Fill in common ibuf properties. */
|
||||
if (ibuf) {
|
||||
ibuf->ftype = ctx.file_type;
|
||||
ibuf->flags |= (spec.format == TypeDesc::HALF) ? IB_halffloat : 0;
|
||||
ibuf->foptions.flag |= (spec.format == TypeDesc::HALF) ? OPENEXR_HALF : 0;
|
||||
|
||||
set_colorspace_name(colorspace, ctx, spec, is_float);
|
||||
|
||||
|
||||
@@ -466,6 +466,35 @@ static void openexr_header_compression(Header *header, int compression, int qual
|
||||
}
|
||||
}
|
||||
|
||||
static int openexr_header_get_compression(const Header &header)
|
||||
{
|
||||
switch (header.compression()) {
|
||||
case NO_COMPRESSION:
|
||||
return R_IMF_EXR_CODEC_NONE;
|
||||
case RLE_COMPRESSION:
|
||||
return R_IMF_EXR_CODEC_RLE;
|
||||
case ZIPS_COMPRESSION:
|
||||
return R_IMF_EXR_CODEC_ZIPS;
|
||||
case ZIP_COMPRESSION:
|
||||
return R_IMF_EXR_CODEC_ZIP;
|
||||
case PIZ_COMPRESSION:
|
||||
return R_IMF_EXR_CODEC_PIZ;
|
||||
case PXR24_COMPRESSION:
|
||||
return R_IMF_EXR_CODEC_PXR24;
|
||||
case B44_COMPRESSION:
|
||||
return R_IMF_EXR_CODEC_B44;
|
||||
case B44A_COMPRESSION:
|
||||
return R_IMF_EXR_CODEC_B44A;
|
||||
case DWAA_COMPRESSION:
|
||||
return R_IMF_EXR_CODEC_DWAA;
|
||||
case DWAB_COMPRESSION:
|
||||
return R_IMF_EXR_CODEC_DWAB;
|
||||
case NUM_COMPRESSION_METHODS:
|
||||
return R_IMF_EXR_CODEC_NONE;
|
||||
}
|
||||
return R_IMF_EXR_CODEC_NONE;
|
||||
}
|
||||
|
||||
static void openexr_header_metadata(Header *header, ImBuf *ibuf)
|
||||
{
|
||||
if (ibuf->metadata) {
|
||||
@@ -2220,7 +2249,8 @@ ImBuf *imb_load_openexr(const uchar *mem, size_t size, int flags, char colorspac
|
||||
const bool is_alpha = exr_has_alpha(*file);
|
||||
|
||||
ibuf = IMB_allocImBuf(width, height, is_alpha ? 32 : 24, 0);
|
||||
ibuf->flags |= exr_is_half_float(*file) ? IB_halffloat : 0;
|
||||
ibuf->foptions.flag |= exr_is_half_float(*file) ? OPENEXR_HALF : 0;
|
||||
ibuf->foptions.flag |= openexr_header_get_compression(file_header);
|
||||
|
||||
if (hasXDensity(file_header)) {
|
||||
/* Convert inches to meters. */
|
||||
|
||||
@@ -59,7 +59,7 @@ static void imb_gpu_get_format(const ImBuf *ibuf,
|
||||
|
||||
if (float_rect) {
|
||||
/* Float. */
|
||||
const bool use_high_bitdepth = (!(ibuf->flags & IB_halffloat) && high_bitdepth);
|
||||
const bool use_high_bitdepth = (!(ibuf->foptions.flag & OPENEXR_HALF) && high_bitdepth);
|
||||
*r_texture_format = is_grayscale ? (use_high_bitdepth ? GPU_R32F : GPU_R16F) :
|
||||
(use_high_bitdepth ? GPU_RGBA32F : GPU_RGBA16F);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user