diff options
author | clook <build@localhost.localdomain> | 2013-07-14 03:30:38 +0000 |
---|---|---|
committer | Michael Niedermayer <michaelni@gmx.at> | 2013-07-23 01:02:41 +0200 |
commit | b9b1a2c3e47091eff07e4fc506e4f876a3209aed (patch) | |
tree | 2b23aa75966d02deeb0742d36544af1b0c16cc0e /libswscale | |
parent | 419a3d8a43d2047ae5339895943fb8926eaa6f8c (diff) |
libswscale: Adding RGB => XYZ support
Diffstat (limited to 'libswscale')
-rw-r--r-- | libswscale/swscale.c | 62 | ||||
-rw-r--r-- | libswscale/swscale_internal.h | 3 | ||||
-rw-r--r-- | libswscale/utils.c | 17 |
3 files changed, 79 insertions, 3 deletions
diff --git a/libswscale/swscale.c b/libswscale/swscale.c index cec428847b..6721dc3a2d 100644 --- a/libswscale/swscale.c +++ b/libswscale/swscale.c @@ -849,6 +849,62 @@ static void xyz12Torgb48(struct SwsContext *c, uint16_t *dst, } } +static void rgb48Toxyz12(struct SwsContext *c, uint16_t *dst, + const uint16_t *src, int stride, int h) +{ + int xp,yp; + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(c->srcFormat); + + for (yp=0; yp<h; yp++) { + for (xp=0; xp+2<stride; xp+=3) { + int x, y, z, r, g, b; + + if (desc->flags & AV_PIX_FMT_FLAG_BE) { + r = AV_RB16(src + xp + 0); + g = AV_RB16(src + xp + 1); + b = AV_RB16(src + xp + 2); + } else { + r = AV_RL16(src + xp + 0); + g = AV_RL16(src + xp + 1); + b = AV_RL16(src + xp + 2); + } + + r = c->rgbgammainv[r>>4]; + g = c->rgbgammainv[g>>4]; + b = c->rgbgammainv[b>>4]; + + // convert from sRGBlinear to XYZlinear + x = c->rgb2xyz_matrix[0][0] * r + + c->rgb2xyz_matrix[0][1] * g + + c->rgb2xyz_matrix[0][2] * b >> 12; + y = c->rgb2xyz_matrix[1][0] * r + + c->rgb2xyz_matrix[1][1] * g + + c->rgb2xyz_matrix[1][2] * b >> 12; + z = c->rgb2xyz_matrix[2][0] * r + + c->rgb2xyz_matrix[2][1] * g + + c->rgb2xyz_matrix[2][2] * b >> 12; + + // limit values to 12-bit depth + x = av_clip_c(x,0,4095); + y = av_clip_c(y,0,4095); + z = av_clip_c(z,0,4095); + + // convert from XYZlinear to X'Y'Z' and scale from 12bit to 16bit + if (desc->flags & AV_PIX_FMT_FLAG_BE) { + AV_WB16(dst + xp + 0, c->xyzgammainv[x] << 4); + AV_WB16(dst + xp + 1, c->xyzgammainv[y] << 4); + AV_WB16(dst + xp + 2, c->xyzgammainv[z] << 4); + } else { + AV_WL16(dst + xp + 0, c->xyzgammainv[x] << 4); + AV_WL16(dst + xp + 1, c->xyzgammainv[y] << 4); + AV_WL16(dst + xp + 2, c->xyzgammainv[z] << 4); + } + } + src += stride; + dst += stride; + } +} + /** * swscale wrapper, so we don't need to export the SwsContext. * Assumes planar YUV to be in YUV order instead of YVU. @@ -1045,6 +1101,12 @@ int attribute_align_arg sws_scale(struct SwsContext *c, srcSliceH, dst2, dstStride2); } + + if (c->dstXYZ && !(c->srcXYZ && c->srcW==c->dstW && c->srcH==c->dstH)) { + /* replace on the same data */ + rgb48Toxyz12(c, (uint16_t*)dst2[0], (const uint16_t*)dst2[0], dstStride[0]/2, ret); + } + av_free(rgb0_tmp); return ret; } diff --git a/libswscale/swscale_internal.h b/libswscale/swscale_internal.h index 02214f3473..e7cc26ea54 100644 --- a/libswscale/swscale_internal.h +++ b/libswscale/swscale_internal.h @@ -484,7 +484,10 @@ typedef struct SwsContext { #define RGB_GAMMA (2.2f) int16_t *xyzgamma; int16_t *rgbgamma; + int16_t *xyzgammainv; + int16_t *rgbgammainv; int16_t xyz2rgb_matrix[3][4]; + int16_t rgb2xyz_matrix[3][4]; /* function pointers for swScale() */ yuv2planar1_fn yuv2plane1; diff --git a/libswscale/utils.c b/libswscale/utils.c index 59bf49a0b2..00308e1553 100644 --- a/libswscale/utils.c +++ b/libswscale/utils.c @@ -201,8 +201,8 @@ static const FormatEntry format_entries[AV_PIX_FMT_NB] = { [AV_PIX_FMT_GBRP14BE] = { 1, 1 }, [AV_PIX_FMT_GBRP16LE] = { 1, 0 }, [AV_PIX_FMT_GBRP16BE] = { 1, 0 }, - [AV_PIX_FMT_XYZ12BE] = { 1, 0, 1 }, - [AV_PIX_FMT_XYZ12LE] = { 1, 0, 1 }, + [AV_PIX_FMT_XYZ12BE] = { 1, 1, 1 }, + [AV_PIX_FMT_XYZ12LE] = { 1, 1, 1 }, [AV_PIX_FMT_GBRAP] = { 1, 1 }, [AV_PIX_FMT_GBRAP16LE] = { 1, 0 }, [AV_PIX_FMT_GBRAP16BE] = { 1, 0 }, @@ -924,15 +924,24 @@ static void fill_xyztables(struct SwsContext *c) int i; double xyzgamma = XYZ_GAMMA; double rgbgamma = 1.0 / RGB_GAMMA; + double xyzgammainv = 1.0 / XYZ_GAMMA; + double rgbgammainv = RGB_GAMMA; static const int16_t xyz2rgb_matrix[3][4] = { {13270, -6295, -2041}, {-3969, 7682, 170}, { 228, -835, 4329} }; - static int16_t xyzgamma_tab[4096], rgbgamma_tab[4096]; + static const int16_t rgb2xyz_matrix[3][4] = { + {1689, 1464, 739}, + { 871, 2929, 296}, + { 79, 488, 3891} }; + static int16_t xyzgamma_tab[4096], rgbgamma_tab[4096], xyzgammainv_tab[4096], rgbgammainv_tab[4096]; memcpy(c->xyz2rgb_matrix, xyz2rgb_matrix, sizeof(c->xyz2rgb_matrix)); + memcpy(c->rgb2xyz_matrix, rgb2xyz_matrix, sizeof(c->rgb2xyz_matrix)); c->xyzgamma = xyzgamma_tab; c->rgbgamma = rgbgamma_tab; + c->xyzgammainv = xyzgammainv_tab; + c->rgbgammainv = rgbgammainv_tab; if (rgbgamma_tab[4095]) return; @@ -941,6 +950,8 @@ static void fill_xyztables(struct SwsContext *c) for (i = 0; i < 4096; i++) { xyzgamma_tab[i] = lrint(pow(i / 4095.0, xyzgamma) * 4095.0); rgbgamma_tab[i] = lrint(pow(i / 4095.0, rgbgamma) * 4095.0); + xyzgammainv_tab[i] = lrint(pow(i / 4095.0, xyzgammainv) * 4095.0); + rgbgammainv_tab[i] = lrint(pow(i / 4095.0, rgbgammainv) * 4095.0); } } |