summaryrefslogtreecommitdiff
path: root/libswscale
diff options
context:
space:
mode:
authorclook <build@localhost.localdomain>2013-07-14 03:30:38 +0000
committerMichael Niedermayer <michaelni@gmx.at>2013-07-23 01:02:41 +0200
commitb9b1a2c3e47091eff07e4fc506e4f876a3209aed (patch)
tree2b23aa75966d02deeb0742d36544af1b0c16cc0e /libswscale
parent419a3d8a43d2047ae5339895943fb8926eaa6f8c (diff)
libswscale: Adding RGB => XYZ support
Diffstat (limited to 'libswscale')
-rw-r--r--libswscale/swscale.c62
-rw-r--r--libswscale/swscale_internal.h3
-rw-r--r--libswscale/utils.c17
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);
}
}