WIP: IMB: Allow BW images in byte to float conversion #118622

Draft
Omar Emara wants to merge 8 commits from OmarEmaraDev/blender:refactor-imbuf-byte-to-float into main

When changing the target branch, be careful to rebase the branch in your fork to match. See documentation.
3 changed files with 34 additions and 103 deletions

View File

@ -453,9 +453,7 @@ void IMB_buffer_byte_from_float_mask(unsigned char *rect_to,
*/
void IMB_buffer_float_from_byte(float *rect_to,
const unsigned char *rect_from,
int profile_to,
int profile_from,
bool predivide,
int channels,
int width,
int height,
int stride_to,

View File

@ -1651,15 +1651,8 @@ static void *do_display_buffer_apply_thread(void *handle_v)
}
if (display_buffer) {
IMB_buffer_float_from_byte(display_buffer,
handle->byte_buffer,
IB_PROFILE_SRGB,
IB_PROFILE_SRGB,
false,
width,
height,
width,
width);
IMB_buffer_float_from_byte(
display_buffer, handle->byte_buffer, channels, width, height, width, width);
}
OmarEmaraDev marked this conversation as resolved
Review

I think we should start removing this legacy profile. Will help simplifying this change as well, and I don't think we ever do color space conversion.

I think we should start removing this legacy profile. Will help simplifying this change as well, and I don't think we ever do color space conversion.
}
else {
@ -1903,15 +1896,7 @@ static void *do_processor_transform_thread(void *handle_v)
const bool float_from_byte = handle->float_from_byte;
if (float_from_byte) {
IMB_buffer_float_from_byte(float_buffer,
byte_buffer,
IB_PROFILE_SRGB,
IB_PROFILE_SRGB,
false,
width,
height,
width,
width);
IMB_buffer_float_from_byte(float_buffer, byte_buffer, channels, width, height, width, width);
IMB_colormanagement_processor_apply(
handle->cm_processor, float_buffer, width, height, channels, predivide);
IMB_premultiply_rect_float(float_buffer, 4, width, height);
@ -2063,15 +2048,7 @@ void IMB_colormanagement_transform_from_byte(float *float_buffer,
const char *from_colorspace,
const char *to_colorspace)
{
IMB_buffer_float_from_byte(float_buffer,
byte_buffer,
IB_PROFILE_SRGB,
IB_PROFILE_SRGB,
true,
width,
height,
width,
width);
IMB_buffer_float_from_byte(float_buffer, byte_buffer, channels, width, height, width, width);
IMB_colormanagement_transform(
float_buffer, width, height, channels, from_colorspace, to_colorspace, true);
}
@ -3618,15 +3595,8 @@ static void partial_buffer_update_rect(ImBuf *ibuf,
else {
if (display_buffer_float) {
/* huh, for dither we need float buffer first, no cheaper way. currently */
IMB_buffer_float_from_byte(display_buffer_float,
byte_buffer,
IB_PROFILE_SRGB,
IB_PROFILE_SRGB,
true,
width,
height,
width,
display_stride);
IMB_buffer_float_from_byte(
display_buffer_float, byte_buffer, channels, width, height, width, display_stride);
}
else {
int i;

View File

@ -349,58 +349,19 @@ void IMB_buffer_byte_from_float_mask(uchar *rect_to,
void IMB_buffer_float_from_byte(float *rect_to,
const uchar *rect_from,
int profile_to,
int profile_from,
bool predivide,
int channels,
int width,
int height,
int stride_to,
int stride_from)
{
float tmp[4];
int x, y;
/* we need valid profiles */
BLI_assert(profile_to != IB_PROFILE_NONE);
BLI_assert(profile_from != IB_PROFILE_NONE);
/* RGBA input */
for (y = 0; y < height; y++) {
const uchar *from = rect_from + size_t(stride_from) * y * 4;
float *to = rect_to + size_t(stride_to) * y * 4;
if (profile_to == profile_from) {
/* no color space conversion */
for (x = 0; x < width; x++, from += 4, to += 4) {
rgba_uchar_to_float(to, from);
}
}
else if (profile_to == IB_PROFILE_LINEAR_RGB) {
/* convert sRGB to linear */
if (predivide) {
for (x = 0; x < width; x++, from += 4, to += 4) {
srgb_to_linearrgb_uchar4_predivide(to, from);
}
}
else {
for (x = 0; x < width; x++, from += 4, to += 4) {
srgb_to_linearrgb_uchar4(to, from);
}
}
}
else if (profile_to == IB_PROFILE_SRGB) {
/* convert linear to sRGB */
if (predivide) {
for (x = 0; x < width; x++, from += 4, to += 4) {
rgba_uchar_to_float(tmp, from);
linearrgb_to_srgb_predivide_v4(to, tmp);
}
}
else {
for (x = 0; x < width; x++, from += 4, to += 4) {
rgba_uchar_to_float(tmp, from);
linearrgb_to_srgb_v4(to, tmp);
}
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
for (int i = 0; i < channels; i++) {
/* Bytes buffers are always 4 channel in image buffers. */
const size_t from_index = (y * stride_from + x) * 4 + i;
const size_t to_index = (y * stride_to + x) * channels + i;
rect_to[to_index] = float(rect_from[from_index]) / 255.0f;
}
}
}
@ -755,7 +716,7 @@ void IMB_float_from_rect_ex(ImBuf *dst, const ImBuf *src, const rcti *region_to_
"Source buffer should have a byte buffer assigned.");
BLI_assert_msg(dst->x == src->x, "Source and destination buffer should have the same dimension");
BLI_assert_msg(dst->y == src->y, "Source and destination buffer should have the same dimension");
BLI_assert_msg(dst->channels = 4, "Destination buffer should have 4 channels.");
BLI_assert_msg(dst->channels > 0, "Destination buffer should have at least one channel.");
BLI_assert_msg(region_to_update->xmin >= 0,
"Region to update should be clipped to the given buffers.");
BLI_assert_msg(region_to_update->ymin >= 0,
@ -766,29 +727,22 @@ void IMB_float_from_rect_ex(ImBuf *dst, const ImBuf *src, const rcti *region_to_
"Region to update should be clipped to the given buffers.");
float *rect_float = dst->float_buffer.data;
rect_float += (region_to_update->xmin + region_to_update->ymin * dst->x) * 4;
rect_float += (region_to_update->xmin + region_to_update->ymin * dst->x) * dst->channels;
uchar *rect = src->byte_buffer.data;
rect += (region_to_update->xmin + region_to_update->ymin * dst->x) * 4;
rect += (region_to_update->xmin + region_to_update->ymin * dst->x) * dst->channels;
const int region_width = BLI_rcti_size_x(region_to_update);
const int region_height = BLI_rcti_size_y(region_to_update);
/* Convert byte buffer to float buffer without color or alpha conversion. */
IMB_buffer_float_from_byte(rect_float,
rect,
IB_PROFILE_SRGB,
IB_PROFILE_SRGB,
false,
region_width,
region_height,
src->x,
dst->x);
IMB_buffer_float_from_byte(
rect_float, rect, dst->channels, region_width, region_height, src->x, dst->x);
/* Perform color space conversion from rect color space to linear. */
float *float_ptr = rect_float;
for (int i = 0; i < region_height; i++) {
IMB_colormanagement_colorspace_to_scene_linear(
float_ptr, region_width, 1, dst->channels, src->byte_buffer.colorspace, false);
float_ptr += 4 * dst->x;
float_ptr += dst->channels * dst->x;
}
/* Perform alpha conversion. */
@ -796,7 +750,7 @@ void IMB_float_from_rect_ex(ImBuf *dst, const ImBuf *src, const rcti *region_to_
float_ptr = rect_float;
for (int i = 0; i < region_height; i++) {
IMB_premultiply_rect_float(float_ptr, dst->channels, region_width, 1);
float_ptr += 4 * dst->x;
float_ptr += dst->channels * dst->x;
}
}
}
@ -814,15 +768,24 @@ void IMB_float_from_rect(ImBuf *ibuf)
*/
float *rect_float = ibuf->float_buffer.data;
if (rect_float == nullptr) {
const size_t size = IMB_get_rect_len(ibuf) * sizeof(float[4]);
/* For color spaces other than sRGB and linear, we force full RGBA channels since color space
* conversion might introduce color shifts even for greyscale images. */
if (!(IMB_colormanagement_space_is_srgb(ibuf->byte_buffer.colorspace) ||
IMB_colormanagement_space_is_scene_linear(ibuf->byte_buffer.colorspace)))
{
ibuf->channels = 4;
}
else {
ibuf->channels = ibuf->planes / 8;
}
const size_t size = IMB_get_rect_len(ibuf) * ibuf->channels * sizeof(float);
rect_float = static_cast<float *>(MEM_callocN(size, "IMB_float_from_rect"));
if (rect_float == nullptr) {
return;
}
ibuf->channels = 4;
IMB_assign_float_buffer(ibuf, rect_float, IB_TAKE_OWNERSHIP);
}