Skip to content

Commit

Permalink
use resize filter during applyGainMap process
Browse files Browse the repository at this point in the history
If the aspect ratio of the gainmap image differs from the primary image,
the library throws an error. Try resizing the gainmap image to primary
image dimensions before returning with error.

Test: ./ultrahdr_unit_test
  • Loading branch information
ram-mohan committed Nov 4, 2024
1 parent 25e4c8e commit 73e1356
Show file tree
Hide file tree
Showing 5 changed files with 108 additions and 34 deletions.
2 changes: 2 additions & 0 deletions lib/include/ultrahdr/editorhelper.h
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,8 @@ template <typename T>
extern void resize_buffer(T* src_buffer, T* dst_buffer, int src_w, int src_h, int dst_w, int dst_h,
int src_stride, int dst_stride);

std::unique_ptr<uhdr_raw_image_ext_t> resize_image(uhdr_raw_image_t* src, int dst_w, int dst_h);

#if (defined(UHDR_ENABLE_INTRINSICS) && (defined(__ARM_NEON__) || defined(__ARM_NEON)))
template <typename T>
extern void mirror_buffer_neon(T* src_buffer, T* dst_buffer, int src_w, int src_h, int src_stride,
Expand Down
4 changes: 4 additions & 0 deletions lib/include/ultrahdr/gainmapmath.h
Original file line number Diff line number Diff line change
Expand Up @@ -369,8 +369,10 @@ class LookUpTable {
Color getYuv444Pixel(uhdr_raw_image_t* image, size_t x, size_t y);
Color getYuv422Pixel(uhdr_raw_image_t* image, size_t x, size_t y);
Color getYuv420Pixel(uhdr_raw_image_t* image, size_t x, size_t y);
Color getYuv400Pixel(uhdr_raw_image_t* image, size_t x, size_t y);
Color getP010Pixel(uhdr_raw_image_t* image, size_t x, size_t y);
Color getYuv444Pixel10bit(uhdr_raw_image_t* image, size_t x, size_t y);
Color getRgb888Pixel(uhdr_raw_image_t* image, size_t x, size_t y);
Color getRgba8888Pixel(uhdr_raw_image_t* image, size_t x, size_t y);
Color getRgba1010102Pixel(uhdr_raw_image_t* image, size_t x, size_t y);
Color getRgbaF16Pixel(uhdr_raw_image_t* image, size_t x, size_t y);
Expand All @@ -388,6 +390,8 @@ Color sampleRgbaF16(uhdr_raw_image_t* image, size_t map_scale_factor, size_t x,

// Put pixel in the image at the provided location.
void putRgba8888Pixel(uhdr_raw_image_t* image, size_t x, size_t y, Color& pixel);
void putRgb888Pixel(uhdr_raw_image_t* image, size_t x, size_t y, Color& pixel);
void putYuv400Pixel(uhdr_raw_image_t* image, size_t x, size_t y, Color& pixel);
void putYuv444Pixel(uhdr_raw_image_t* image, size_t x, size_t y, Color& pixel);

////////////////////////////////////////////////////////////////////////////////
Expand Down
61 changes: 36 additions & 25 deletions lib/src/editorhelper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#include <cmath>

#include "ultrahdr/editorhelper.h"
#include "ultrahdr/gainmapmath.h"

namespace ultrahdr {

Expand Down Expand Up @@ -102,42 +103,52 @@ double bicubic_interpolate(double p0, double p1, double p2, double p3, double x)
return w0 * p0 + w1 * p1 + w2 * p2 + w3 * p3;
}

template <typename T>
void resize_buffer(T* src_buffer, T* dst_buffer, int src_w, int src_h, int dst_w, int dst_h,
int src_stride, int dst_stride, uhdr_img_fmt_t img_fmt, size_t plane) {
std::unique_ptr<uhdr_raw_image_ext_t> resize_image(uhdr_raw_image_t* src, int dst_w, int dst_h) {
GetPixelFn get_pixel_fn = getPixelFn(src->fmt);
if (get_pixel_fn == nullptr) {
return nullptr;
}

PutPixelFn put_pixel_fn = putPixelFn(src->fmt);
if (put_pixel_fn == nullptr) {
return nullptr;
}

std::unique_ptr<uhdr_raw_image_ext_t> dst = std::make_unique<uhdr_raw_image_ext_t>(
src->fmt, src->cg, src->ct, src->range, dst_w, dst_h, 64);

int src_w = src->w;
int src_h = src->h;
double scale_x = (double)src_w / dst_w;
double scale_y = (double)src_h / dst_h;
for (int y = 0; y < dst_h; y++) {
for (int x = 0; x < dst_w; x++) {
double ori_x = x * scale_x;
double ori_y = y * scale_y;
int p0_x = (int)floor(ori_x);
int p0_y = (int)floor(ori_y);
int p1_x = p0_x + 1;
int p0_x = CLIP3((int)floor(ori_x), 0, src_w - 1);
int p0_y = CLIP3((int)floor(ori_y), 0, src_h - 1);
int p1_x = CLIP3((p0_x + 1), 0, src_w - 1);
int p1_y = p0_y;
int p2_x = p0_x;
int p2_y = p0_y + 1;
int p3_x = p0_x + 1;
int p3_y = p0_y + 1;

if ((img_fmt == UHDR_IMG_FMT_8bppYCbCr400) ||
(img_fmt == UHDR_IMG_FMT_12bppYCbCr420 && plane == UHDR_PLANE_Y) ||
(img_fmt == UHDR_IMG_FMT_12bppYCbCr420 && plane == UHDR_PLANE_U) ||
(img_fmt == UHDR_IMG_FMT_12bppYCbCr420 && plane == UHDR_PLANE_V)) {
double p0 = (double)src_buffer[p0_y * src_stride + p0_x];
double p1 = (double)src_buffer[p1_y * src_stride + p1_x];
double p2 = (double)src_buffer[p2_y * src_stride + p2_x];
double p3 = (double)src_buffer[p3_y * src_stride + p3_x];

double new_pix_val = bicubic_interpolate(p0, p1, p2, p3, ori_x - p0_x);

dst_buffer[y * dst_stride + x] = (uint8_t)floor(new_pix_val + 0.5);
} else {
// Unsupported feature.
return;
int p2_y = CLIP3((p0_y + 1), 0, src_h - 1);
int p3_x = CLIP3((p0_x + 1), 0, src_w - 1);
int p3_y = CLIP3((p0_y + 1), 0, src_h - 1);

Color p0 = get_pixel_fn(src, p0_x, p0_y);
Color p1 = get_pixel_fn(src, p1_x, p1_y);
Color p2 = get_pixel_fn(src, p2_x, p2_y);
Color p3 = get_pixel_fn(src, p3_x, p3_y);

Color interp;
interp.r = (float)bicubic_interpolate(p0.r, p1.r, p2.r, p3.r, ori_x - p0_x);
if (src->fmt != UHDR_IMG_FMT_8bppYCbCr400) {
interp.g = (float)bicubic_interpolate(p0.g, p1.g, p2.g, p3.g, ori_x - p0_x);
interp.b = (float)bicubic_interpolate(p0.b, p1.b, p2.b, p3.b, ori_x - p0_x);
}
put_pixel_fn(dst.get(), x, y, interp);
}
}
return dst;
}

template void mirror_buffer<uint8_t>(uint8_t*, uint8_t*, int, int, int, int,
Expand Down
53 changes: 53 additions & 0 deletions lib/src/gainmapmath.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -389,6 +389,15 @@ Color getYuv420Pixel(uhdr_raw_image_t* image, size_t x, size_t y) {
return getYuv4abPixel(image, x, y, 2, 2);
}

Color getYuv400Pixel(uhdr_raw_image_t* image, size_t x, size_t y) {
uint8_t* luma_data = reinterpret_cast<uint8_t*>(image->planes[UHDR_PLANE_Y]);
size_t luma_stride = image->stride[UHDR_PLANE_Y];
size_t pixel_y_idx = x + y * luma_stride;
uint8_t y_uint = luma_data[pixel_y_idx];

return {{{static_cast<float>(y_uint) * (1 / 255.0f), 0.f, 0.f}}};
}

Color getYuv444Pixel10bit(uhdr_raw_image_t* image, size_t x, size_t y) {
uint16_t* luma_data = reinterpret_cast<uint16_t*>(image->planes[UHDR_PLANE_Y]);
size_t luma_stride = image->stride[UHDR_PLANE_Y];
Expand Down Expand Up @@ -441,6 +450,17 @@ Color getP010Pixel(uhdr_raw_image_t* image, size_t x, size_t y) {
static_cast<float>(v_uint - 64) * (1 / 896.0f) - 0.5f}}};
}

Color getRgb888Pixel(uhdr_raw_image_t* image, size_t x, size_t y) {
uint8_t* rgbData = static_cast<uint8_t*>(image->planes[UHDR_PLANE_PACKED]);
unsigned int srcStride = image->stride[UHDR_PLANE_PACKED];
size_t offset = x * 3 + y * srcStride * 3;
Color pixel;
pixel.r = float(rgbData[offset]);
pixel.g = float(rgbData[offset + 1]);
pixel.b = float(rgbData[offset + 2]);
return pixel / 255.0f;
}

Color getRgba8888Pixel(uhdr_raw_image_t* image, size_t x, size_t y) {
uint32_t* rgbData = static_cast<uint32_t*>(image->planes[UHDR_PLANE_PACKED]);
unsigned int srcStride = image->stride[UHDR_PLANE_PACKED];
Expand Down Expand Up @@ -534,6 +554,31 @@ void putRgba8888Pixel(uhdr_raw_image_t* image, size_t x, size_t y, Color& pixel)
rgbData[x + y * srcStride] = r0 | (g0 << 8) | (b0 << 16) | (255 << 24); // Set alpha to 1.0
}

void putRgb888Pixel(uhdr_raw_image_t* image, size_t x, size_t y, Color& pixel) {
uint8_t* rgbData = static_cast<uint8_t*>(image->planes[UHDR_PLANE_PACKED]);
unsigned int srcStride = image->stride[UHDR_PLANE_PACKED];
size_t offset = x * 3 + y * srcStride * 3;
pixel *= 255.0f;
pixel += 0.5f;
pixel.r = CLIP3(pixel.r, 0.0f, 255.0f);
pixel.g = CLIP3(pixel.g, 0.0f, 255.0f);
pixel.b = CLIP3(pixel.b, 0.0f, 255.0f);
rgbData[offset] = uint8_t(pixel.r);
rgbData[offset + 1] = uint8_t(pixel.r);
rgbData[offset + 2] = uint8_t(pixel.b);
}

void putYuv400Pixel(uhdr_raw_image_t* image, size_t x, size_t y, Color& pixel) {
uint8_t* luma_data = reinterpret_cast<uint8_t*>(image->planes[UHDR_PLANE_Y]);
size_t luma_stride = image->stride[UHDR_PLANE_Y];

pixel *= 255.0f;
pixel += 0.5f;
pixel.y = CLIP3(pixel.y, 0.0f, 255.0f);

luma_data[x + y * luma_stride] = uint8_t(pixel.y);
}

void putYuv444Pixel(uhdr_raw_image_t* image, size_t x, size_t y, Color& pixel) {
uint8_t* luma_data = reinterpret_cast<uint8_t*>(image->planes[UHDR_PLANE_Y]);
uint8_t* cb_data = reinterpret_cast<uint8_t*>(image->planes[UHDR_PLANE_U]);
Expand Down Expand Up @@ -1180,6 +1225,10 @@ GetPixelFn getPixelFn(uhdr_img_fmt_t format) {
return getRgba1010102Pixel;
case UHDR_IMG_FMT_64bppRGBAHalfFloat:
return getRgbaF16Pixel;
case UHDR_IMG_FMT_8bppYCbCr400:
return getYuv400Pixel;
case UHDR_IMG_FMT_24bppRGB888:
return getRgb888Pixel;
default:
return nullptr;
}
Expand All @@ -1192,6 +1241,10 @@ PutPixelFn putPixelFn(uhdr_img_fmt_t format) {
return putYuv444Pixel;
case UHDR_IMG_FMT_32bppRGBA8888:
return putRgba8888Pixel;
case UHDR_IMG_FMT_8bppYCbCr400:
return putYuv400Pixel;
case UHDR_IMG_FMT_24bppRGB888:
return putRgb888Pixel;
default:
return nullptr;
}
Expand Down
22 changes: 13 additions & 9 deletions lib/src/jpegr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
#include <mutex>
#include <thread>

#include "ultrahdr/editorhelper.h"
#include "ultrahdr/gainmapmetadata.h"
#include "ultrahdr/ultrahdrcommon.h"
#include "ultrahdr/jpegr.h"
Expand Down Expand Up @@ -1426,22 +1427,25 @@ uhdr_error_info_t JpegR::applyGainMap(uhdr_raw_image_t* sdr_intent, uhdr_raw_ima
}
#endif

std::unique_ptr<uhdr_raw_image_ext_t> resized_gainmap = nullptr;
{
float primary_aspect_ratio = (float)sdr_intent->w / sdr_intent->h;
float gainmap_aspect_ratio = (float)gainmap_img->w / gainmap_img->h;
float delta_aspect_ratio = fabs(primary_aspect_ratio - gainmap_aspect_ratio);
// Allow 1% delta
const float delta_tolerance = 0.01;
if (delta_aspect_ratio / primary_aspect_ratio > delta_tolerance) {
uhdr_error_info_t status;
status.error_code = UHDR_CODEC_UNSUPPORTED_FEATURE;
status.has_detail = 1;
snprintf(
status.detail, sizeof status.detail,
"gain map dimensions scale factor values for height and width are different, \n primary "
"image resolution is %ux%u, received gain map resolution is %ux%u",
sdr_intent->w, sdr_intent->h, gainmap_img->w, gainmap_img->h);
return status;
resized_gainmap = resize_image(gainmap_img, sdr_intent->w, sdr_intent->h);
if (resized_gainmap == nullptr) {
uhdr_error_info_t status;
status.error_code = UHDR_CODEC_UNSUPPORTED_FEATURE;
status.has_detail = 1;
snprintf(status.detail, sizeof status.detail,
"encountered error while resizing the gainmap image from %ux%u to %ux%u",
gainmap_img->w, gainmap_img->h, sdr_intent->w, sdr_intent->h);
return status;
}
gainmap_img = resized_gainmap.get();
}
}

Expand Down

0 comments on commit 73e1356

Please sign in to comment.