From 2a7128f4ed00dbc9209d6f24501bb76a0c14b490 Mon Sep 17 00:00:00 2001 From: Pedro Arthur Date: Fri, 17 Apr 2015 17:08:42 -0300 Subject: Add gamma encodign/decoding before/after scaling in libswscale Signed-off-by: Michael Niedermayer --- libswscale/utils.c | 76 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 76 insertions(+) (limited to 'libswscale/utils.c') diff --git a/libswscale/utils.c b/libswscale/utils.c index 781071946c..d1cdf00f6a 100644 --- a/libswscale/utils.c +++ b/libswscale/utils.c @@ -960,6 +960,20 @@ SwsContext *sws_alloc_context(void) return c; } +static uint16_t * alloc_gamma_tbl(double e) +{ + int i = 0; + uint16_t * tbl; + tbl = (uint16_t*)av_malloc(sizeof(uint16_t) * 1 << 16); + if (!tbl) + return NULL; + + for (i = 0; i < 65536; ++i) { + tbl[i] = pow(i / 65535.0, e) * 65535.0; + } + return tbl; +} + av_cold int sws_init_context(SwsContext *c, SwsFilter *srcFilter, SwsFilter *dstFilter) { @@ -978,6 +992,7 @@ av_cold int sws_init_context(SwsContext *c, SwsFilter *srcFilter, const AVPixFmtDescriptor *desc_src; const AVPixFmtDescriptor *desc_dst; int ret = 0; + enum AVPixelFormat tmpFmt; cpu_flags = av_get_cpu_flags(); flags = c->flags; @@ -1235,6 +1250,61 @@ av_cold int sws_init_context(SwsContext *c, SwsFilter *srcFilter, } } + // hardcoded for now + c->gamma_value = 2.2; + tmpFmt = AV_PIX_FMT_RGBA64LE; + + + if (!unscaled && c->gamma_flag && (srcFormat != tmpFmt || dstFormat != tmpFmt)) { + c->cascaded_context[0] = NULL; + + ret = av_image_alloc(c->cascaded_tmp, c->cascaded_tmpStride, + srcW, srcH, tmpFmt, 64); + if (ret < 0) + return ret; + + c->cascaded_context[0] = sws_getContext(srcW, srcH, srcFormat, + srcW, srcH, tmpFmt, + flags, NULL, NULL, c->param); + if (!c->cascaded_context[0]) { + return -1; + } + + c->cascaded_context[1] = sws_getContext(srcW, srcH, tmpFmt, + dstW, dstH, tmpFmt, + flags | SWS_GAMMA_CORRECT, srcFilter, dstFilter, c->param); + + if (!c->cascaded_context[1]) + return -1; + + c->cascaded_context[2] = NULL; + if (dstFormat != tmpFmt) { + ret = av_image_alloc(c->cascaded1_tmp, c->cascaded1_tmpStride, + dstW, dstH, tmpFmt, 64); + if (ret < 0) + return ret; + + c->cascaded_context[2] = sws_getContext(dstW, dstH, tmpFmt, + dstW, dstH, dstFormat, + flags, NULL, NULL, c->param); + if (!c->cascaded_context[2]) + return -1; + } + return 0; + } + + c->gamma = NULL; + c->inv_gamma = NULL; + if (c->flags & SWS_GAMMA_CORRECT) { + c->gamma = alloc_gamma_tbl(c->gamma_value); + if (!c->gamma) + return AVERROR(ENOMEM); + c->inv_gamma = alloc_gamma_tbl(1.f/c->gamma_value); + if (!c->inv_gamma) { + return AVERROR(ENOMEM); + } + } + if (isBayer(srcFormat)) { if (!unscaled || (dstFormat != AV_PIX_FMT_RGB24 && dstFormat != AV_PIX_FMT_YUV420P)) { @@ -1977,8 +2047,14 @@ void sws_freeContext(SwsContext *c) sws_freeContext(c->cascaded_context[0]); sws_freeContext(c->cascaded_context[1]); + sws_freeContext(c->cascaded_context[2]); memset(c->cascaded_context, 0, sizeof(c->cascaded_context)); av_freep(&c->cascaded_tmp[0]); + av_freep(&c->cascaded1_tmp[0]); + + av_freep(&c->gamma); + av_freep(&c->inv_gamma); + av_free(c); } -- cgit v1.2.3