diff options
author | Michael Niedermayer <michaelni@gmx.at> | 2013-04-28 19:28:42 +0200 |
---|---|---|
committer | Michael Niedermayer <michaelni@gmx.at> | 2013-04-28 19:30:01 +0200 |
commit | 0c47c9028be2cf4b1a557e653606fced5b959445 (patch) | |
tree | 5bdf78c411d5f3e7af35f674874afeeb5fa5c923 /libswscale/swscale.c | |
parent | 45f1cf88a85c3e17abe8244806d4161f062add88 (diff) | |
download | ffmpeg-0c47c9028be2cf4b1a557e653606fced5b959445.tar.gz |
sws: support xyz input
The implementation is heavily based on Matthias Buerchers and Nicolas Bertrands vf_xyz2rgb.c
Signed-off-by: Michael Niedermayer <michaelni@gmx.at>
Diffstat (limited to 'libswscale/swscale.c')
-rw-r--r-- | libswscale/swscale.c | 65 |
1 files changed, 65 insertions, 0 deletions
diff --git a/libswscale/swscale.c b/libswscale/swscale.c index 0c20a71f71..190a7b98f4 100644 --- a/libswscale/swscale.c +++ b/libswscale/swscale.c @@ -791,6 +791,62 @@ static int check_image_pointers(const uint8_t * const data[4], enum AVPixelForma return 1; } +static void xyz12Torgb48(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 & PIX_FMT_BE) { + x = AV_RB16(src + xp + 0); + y = AV_RB16(src + xp + 1); + z = AV_RB16(src + xp + 2); + } else { + x = AV_RL16(src + xp + 0); + y = AV_RL16(src + xp + 1); + z = AV_RL16(src + xp + 2); + } + + x = c->xyzgamma[x>>4]; + y = c->xyzgamma[y>>4]; + z = c->xyzgamma[z>>4]; + + // convert from XYZlinear to sRGBlinear + r = c->xyz2rgb_matrix[0][0] * x + + c->xyz2rgb_matrix[0][1] * y + + c->xyz2rgb_matrix[0][2] * z >> 12; + g = c->xyz2rgb_matrix[1][0] * x + + c->xyz2rgb_matrix[1][1] * y + + c->xyz2rgb_matrix[1][2] * z >> 12; + b = c->xyz2rgb_matrix[2][0] * x + + c->xyz2rgb_matrix[1][2] * y + + c->xyz2rgb_matrix[2][2] * z >> 12; + + // limit values to 12-bit depth + r = av_clip_c(r,0,4095); + g = av_clip_c(g,0,4095); + b = av_clip_c(b,0,4095); + + // convert from sRGBlinear to RGB and scale from 12bit to 16bit + if (desc->flags & PIX_FMT_BE) { + AV_WB16(dst + xp + 0, c->rgbgamma[r] << 4); + AV_WB16(dst + xp + 1, c->rgbgamma[g] << 4); + AV_WB16(dst + xp + 2, c->rgbgamma[b] << 4); + } else { + AV_WL16(dst + xp + 0, c->rgbgamma[r] << 4); + AV_WL16(dst + xp + 1, c->rgbgamma[g] << 4); + AV_WL16(dst + xp + 2, c->rgbgamma[b] << 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. @@ -922,6 +978,15 @@ int attribute_align_arg sws_scale(struct SwsContext *c, src2[0] = base; } + if (c->srcXYZ && !(c->dstXYZ && c->srcW==c->dstW && c->srcH==c->dstH)) { + uint8_t *base; + rgb0_tmp = av_malloc(FFABS(srcStride[0]) * srcSliceH + 32); + base = srcStride[0] < 0 ? rgb0_tmp - srcStride[0] * (srcSliceH-1) : rgb0_tmp; + + xyz12Torgb48(c, base, src2[0], srcStride[0]/2, srcSliceH); + src2[0] = base; + } + if (!srcSliceY && (c->flags & SWS_BITEXACT) && (c->flags & SWS_ERROR_DIFFUSION) && c->dither_error[0]) for (i = 0; i < 4; i++) memset(c->dither_error[i], 0, sizeof(c->dither_error[0][0]) * (c->dstW+2)); |