mirror of
https://git.ffmpeg.org/ffmpeg.git
synced 2025-01-18 05:11:09 +00:00
sws: rgb/bgr 4/8 error diffusion dither
Signed-off-by: Michael Niedermayer <michaelni@gmx.at>
This commit is contained in:
parent
d7a46ca179
commit
ca447592b1
@ -1227,6 +1227,8 @@ yuv2rgb_full_X_c_template(SwsContext *c, const int16_t *lumFilter,
|
|||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
int step = (target == AV_PIX_FMT_RGB24 || target == AV_PIX_FMT_BGR24) ? 3 : 4;
|
int step = (target == AV_PIX_FMT_RGB24 || target == AV_PIX_FMT_BGR24) ? 3 : 4;
|
||||||
|
int err[4] = {0};
|
||||||
|
int isrgb8 = target == AV_PIX_FMT_BGR8 || target == AV_PIX_FMT_RGB8;
|
||||||
|
|
||||||
for (i = 0; i < dstW; i++) {
|
for (i = 0; i < dstW; i++) {
|
||||||
int j;
|
int j;
|
||||||
@ -1301,9 +1303,48 @@ yuv2rgb_full_X_c_template(SwsContext *c, const int16_t *lumFilter,
|
|||||||
dest[2] = R >> 22;
|
dest[2] = R >> 22;
|
||||||
dest[3] = hasAlpha ? A : 255;
|
dest[3] = hasAlpha ? A : 255;
|
||||||
break;
|
break;
|
||||||
|
case AV_PIX_FMT_BGR4_BYTE:
|
||||||
|
case AV_PIX_FMT_RGB4_BYTE:
|
||||||
|
case AV_PIX_FMT_BGR8:
|
||||||
|
case AV_PIX_FMT_RGB8:
|
||||||
|
{
|
||||||
|
int r,g,b;
|
||||||
|
R >>= 22;
|
||||||
|
G >>= 22;
|
||||||
|
B >>= 22;
|
||||||
|
R += (7*err[0] + 1*c->dither_error[0][i] + 5*c->dither_error[0][i+1] + 3*c->dither_error[0][i+2])>>4;
|
||||||
|
G += (7*err[1] + 1*c->dither_error[1][i] + 5*c->dither_error[1][i+1] + 3*c->dither_error[1][i+2])>>4;
|
||||||
|
B += (7*err[2] + 1*c->dither_error[2][i] + 5*c->dither_error[2][i+1] + 3*c->dither_error[2][i+2])>>4;
|
||||||
|
c->dither_error[0][i] = err[0];
|
||||||
|
c->dither_error[1][i] = err[1];
|
||||||
|
c->dither_error[2][i] = err[2];
|
||||||
|
r = R >> (isrgb8 ? 5 : 7);
|
||||||
|
g = G >> (isrgb8 ? 5 : 6);
|
||||||
|
b = B >> (isrgb8 ? 6 : 7);
|
||||||
|
r = av_clip(r, 0, isrgb8 ? 7 : 1);
|
||||||
|
g = av_clip(g, 0, isrgb8 ? 7 : 3);
|
||||||
|
b = av_clip(b, 0, isrgb8 ? 3 : 1);
|
||||||
|
err[0] = R - r*(isrgb8 ? 36 : 255);
|
||||||
|
err[1] = G - g*(isrgb8 ? 36 : 85);
|
||||||
|
err[2] = B - b*(isrgb8 ? 85 : 255);
|
||||||
|
if(target == AV_PIX_FMT_BGR4_BYTE) {
|
||||||
|
dest[0] = r + 2*g + 8*b;
|
||||||
|
} else if(target == AV_PIX_FMT_RGB4_BYTE) {
|
||||||
|
dest[0] = b + 2*g + 8*r;
|
||||||
|
} else if(target == AV_PIX_FMT_BGR8) {
|
||||||
|
dest[0] = r + 8*g + 64*b;
|
||||||
|
} else if(target == AV_PIX_FMT_RGB8) {
|
||||||
|
dest[0] = b + 4*g + 32*r;
|
||||||
|
} else
|
||||||
|
av_assert2(0);
|
||||||
|
step = 1;
|
||||||
|
break;}
|
||||||
}
|
}
|
||||||
dest += step;
|
dest += step;
|
||||||
}
|
}
|
||||||
|
c->dither_error[0][i] = err[0];
|
||||||
|
c->dither_error[1][i] = err[1];
|
||||||
|
c->dither_error[2][i] = err[2];
|
||||||
}
|
}
|
||||||
|
|
||||||
#if CONFIG_SMALL
|
#if CONFIG_SMALL
|
||||||
@ -1326,6 +1367,11 @@ YUV2RGBWRAPPERX(yuv2, rgb_full, xrgb32_full, AV_PIX_FMT_ARGB, 0)
|
|||||||
YUV2RGBWRAPPERX(yuv2, rgb_full, bgr24_full, AV_PIX_FMT_BGR24, 0)
|
YUV2RGBWRAPPERX(yuv2, rgb_full, bgr24_full, AV_PIX_FMT_BGR24, 0)
|
||||||
YUV2RGBWRAPPERX(yuv2, rgb_full, rgb24_full, AV_PIX_FMT_RGB24, 0)
|
YUV2RGBWRAPPERX(yuv2, rgb_full, rgb24_full, AV_PIX_FMT_RGB24, 0)
|
||||||
|
|
||||||
|
YUV2RGBWRAPPERX(yuv2, rgb_full, bgr4_byte_full, AV_PIX_FMT_BGR4_BYTE, 0)
|
||||||
|
YUV2RGBWRAPPERX(yuv2, rgb_full, rgb4_byte_full, AV_PIX_FMT_RGB4_BYTE, 0)
|
||||||
|
YUV2RGBWRAPPERX(yuv2, rgb_full, bgr8_full, AV_PIX_FMT_BGR8, 0)
|
||||||
|
YUV2RGBWRAPPERX(yuv2, rgb_full, rgb8_full, AV_PIX_FMT_RGB8, 0)
|
||||||
|
|
||||||
av_cold void ff_sws_init_output_funcs(SwsContext *c,
|
av_cold void ff_sws_init_output_funcs(SwsContext *c,
|
||||||
yuv2planar1_fn *yuv2plane1,
|
yuv2planar1_fn *yuv2plane1,
|
||||||
yuv2planarX_fn *yuv2planeX,
|
yuv2planarX_fn *yuv2planeX,
|
||||||
@ -1426,6 +1472,18 @@ av_cold void ff_sws_init_output_funcs(SwsContext *c,
|
|||||||
case AV_PIX_FMT_BGR24:
|
case AV_PIX_FMT_BGR24:
|
||||||
*yuv2packedX = yuv2bgr24_full_X_c;
|
*yuv2packedX = yuv2bgr24_full_X_c;
|
||||||
break;
|
break;
|
||||||
|
case AV_PIX_FMT_BGR4_BYTE:
|
||||||
|
*yuv2packedX = yuv2bgr4_byte_full_X_c;
|
||||||
|
break;
|
||||||
|
case AV_PIX_FMT_RGB4_BYTE:
|
||||||
|
*yuv2packedX = yuv2rgb4_byte_full_X_c;
|
||||||
|
break;
|
||||||
|
case AV_PIX_FMT_BGR8:
|
||||||
|
*yuv2packedX = yuv2bgr8_full_X_c;
|
||||||
|
break;
|
||||||
|
case AV_PIX_FMT_RGB8:
|
||||||
|
*yuv2packedX = yuv2rgb8_full_X_c;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
if(!*yuv2packedX)
|
if(!*yuv2packedX)
|
||||||
goto YUV_PACKED;
|
goto YUV_PACKED;
|
||||||
|
@ -1008,7 +1008,12 @@ av_cold int sws_init_context(SwsContext *c, SwsFilter *srcFilter,
|
|||||||
dstFormat != AV_PIX_FMT_BGRA &&
|
dstFormat != AV_PIX_FMT_BGRA &&
|
||||||
dstFormat != AV_PIX_FMT_ABGR &&
|
dstFormat != AV_PIX_FMT_ABGR &&
|
||||||
dstFormat != AV_PIX_FMT_RGB24 &&
|
dstFormat != AV_PIX_FMT_RGB24 &&
|
||||||
dstFormat != AV_PIX_FMT_BGR24) {
|
dstFormat != AV_PIX_FMT_BGR24 &&
|
||||||
|
dstFormat != AV_PIX_FMT_BGR4_BYTE &&
|
||||||
|
dstFormat != AV_PIX_FMT_RGB4_BYTE &&
|
||||||
|
dstFormat != AV_PIX_FMT_BGR8 &&
|
||||||
|
dstFormat != AV_PIX_FMT_RGB8
|
||||||
|
) {
|
||||||
av_log(c, AV_LOG_WARNING,
|
av_log(c, AV_LOG_WARNING,
|
||||||
"full chroma interpolation for destination format '%s' not yet implemented\n",
|
"full chroma interpolation for destination format '%s' not yet implemented\n",
|
||||||
av_get_pix_fmt_name(dstFormat));
|
av_get_pix_fmt_name(dstFormat));
|
||||||
|
Loading…
Reference in New Issue
Block a user