summaryrefslogtreecommitdiff
path: root/libavcodec/imgconvert.c
diff options
context:
space:
mode:
authorFabrice Bellard <fabrice@bellard.org>2003-02-02 19:53:01 +0000
committerFabrice Bellard <fabrice@bellard.org>2003-02-02 19:53:01 +0000
commit4c7e86192937f9477532cd593b6a27f1f2fe9566 (patch)
treec0eacd6204a67e807a8430d09887d865d335d467 /libavcodec/imgconvert.c
parentfe2a4ca37913331b8d740cd0a43462df6d16944d (diff)
handle odd image sizes when using subsampled chroma (useful for JPEG images)
Originally committed as revision 1536 to svn://svn.ffmpeg.org/ffmpeg/trunk
Diffstat (limited to 'libavcodec/imgconvert.c')
-rw-r--r--libavcodec/imgconvert.c147
1 files changed, 101 insertions, 46 deletions
diff --git a/libavcodec/imgconvert.c b/libavcodec/imgconvert.c
index 2304092fd2..4019631932 100644
--- a/libavcodec/imgconvert.c
+++ b/libavcodec/imgconvert.c
@@ -133,18 +133,27 @@ const char *avcodec_get_pix_fmt_name(int pix_fmt)
int avpicture_fill(AVPicture *picture, UINT8 *ptr,
int pix_fmt, int width, int height)
{
- int size;
-
+ int size, w2, h2, size2;
+ PixFmtInfo *pinfo;
+
+ pinfo = &pix_fmt_info[pix_fmt];
size = width * height;
switch(pix_fmt) {
case PIX_FMT_YUV420P:
+ case PIX_FMT_YUV422P:
+ case PIX_FMT_YUV444P:
+ case PIX_FMT_YUV410P:
+ case PIX_FMT_YUV411P:
+ w2 = (width + (1 << pinfo->x_chroma_shift) - 1) >> pinfo->x_chroma_shift;
+ h2 = (height + (1 << pinfo->y_chroma_shift) - 1) >> pinfo->y_chroma_shift;
+ size2 = w2 * h2;
picture->data[0] = ptr;
picture->data[1] = picture->data[0] + size;
- picture->data[2] = picture->data[1] + size / 4;
+ picture->data[2] = picture->data[1] + size2;
picture->linesize[0] = width;
- picture->linesize[1] = width / 2;
- picture->linesize[2] = width / 2;
- return (size * 3) / 2;
+ picture->linesize[1] = w2;
+ picture->linesize[2] = w2;
+ return size + 2 * size2;
case PIX_FMT_RGB24:
case PIX_FMT_BGR24:
picture->data[0] = ptr;
@@ -152,44 +161,12 @@ int avpicture_fill(AVPicture *picture, UINT8 *ptr,
picture->data[2] = NULL;
picture->linesize[0] = width * 3;
return size * 3;
- case PIX_FMT_YUV422P:
- picture->data[0] = ptr;
- picture->data[1] = picture->data[0] + size;
- picture->data[2] = picture->data[1] + size / 2;
- picture->linesize[0] = width;
- picture->linesize[1] = width / 2;
- picture->linesize[2] = width / 2;
- return (size * 2);
- case PIX_FMT_YUV444P:
- picture->data[0] = ptr;
- picture->data[1] = picture->data[0] + size;
- picture->data[2] = picture->data[1] + size;
- picture->linesize[0] = width;
- picture->linesize[1] = width;
- picture->linesize[2] = width;
- return size * 3;
case PIX_FMT_RGBA32:
picture->data[0] = ptr;
picture->data[1] = NULL;
picture->data[2] = NULL;
picture->linesize[0] = width * 4;
return size * 4;
- case PIX_FMT_YUV410P:
- picture->data[0] = ptr;
- picture->data[1] = picture->data[0] + size;
- picture->data[2] = picture->data[1] + size / 16;
- picture->linesize[0] = width;
- picture->linesize[1] = width / 4;
- picture->linesize[2] = width / 4;
- return size + (size / 8);
- case PIX_FMT_YUV411P:
- picture->data[0] = ptr;
- picture->data[1] = picture->data[0] + size;
- picture->data[2] = picture->data[1] + size / 4;
- picture->linesize[0] = width;
- picture->linesize[1] = width / 4;
- picture->linesize[2] = width / 4;
- return size + (size / 2);
case PIX_FMT_RGB555:
case PIX_FMT_RGB565:
case PIX_FMT_YUV422:
@@ -424,12 +401,12 @@ static void yuv420p_to_ ## rgb_name (AVPicture *dst, AVPicture *src, \
y1_ptr = src->data[0]; \
cb_ptr = src->data[1]; \
cr_ptr = src->data[2]; \
- width2 = width >> 1; \
- for(;height > 0; height -= 2) { \
+ width2 = (width + 1) >> 1; \
+ for(;height >= 2; height -= 2) { \
d1 = d; \
d2 = d + dst->linesize[0]; \
y2_ptr = y1_ptr + src->linesize[0]; \
- for(w = width2; w > 0; w --) { \
+ for(w = width; w >= 2; w -= 2) { \
cb = cb_ptr[0] - 128; \
cr = cr_ptr[0] - 128; \
r_add = C_RV * cr + (1 << (SCALE_BITS - 1)); \
@@ -457,11 +434,72 @@ static void yuv420p_to_ ## rgb_name (AVPicture *dst, AVPicture *src, \
cb_ptr++; \
cr_ptr++; \
} \
+ /* handle odd width */ \
+ if (w) { \
+ cb = cb_ptr[0] - 128; \
+ cr = cr_ptr[0] - 128; \
+ r_add = C_RV * cr + (1 << (SCALE_BITS - 1)); \
+ g_add = - C_GU * cb - C_GV * cr + (1 << (SCALE_BITS - 1)); \
+ b_add = C_BU * cb + (1 << (SCALE_BITS - 1)); \
+ \
+ YUV_TO_RGB2(r, g, b, y1_ptr[0]); \
+ RGB_OUT(d1, r, g, b); \
+ \
+ YUV_TO_RGB2(r, g, b, y2_ptr[0]); \
+ RGB_OUT(d2, r, g, b); \
+ d1 += BPP; \
+ d2 += BPP; \
+ y1_ptr++; \
+ y2_ptr++; \
+ cb_ptr++; \
+ cr_ptr++; \
+ } \
d += 2 * dst->linesize[0]; \
y1_ptr += 2 * src->linesize[0] - width; \
cb_ptr += src->linesize[1] - width2; \
cr_ptr += src->linesize[2] - width2; \
} \
+ /* handle odd height */ \
+ if (height) { \
+ d1 = d; \
+ for(w = width; w >= 2; w -= 2) { \
+ cb = cb_ptr[0] - 128; \
+ cr = cr_ptr[0] - 128; \
+ r_add = C_RV * cr + (1 << (SCALE_BITS - 1)); \
+ g_add = - C_GU * cb - C_GV * cr + (1 << (SCALE_BITS - 1)); \
+ b_add = C_BU * cb + (1 << (SCALE_BITS - 1)); \
+ \
+ /* output 2 pixels */ \
+ YUV_TO_RGB2(r, g, b, y1_ptr[0]); \
+ RGB_OUT(d1, r, g, b); \
+ \
+ YUV_TO_RGB2(r, g, b, y1_ptr[1]); \
+ RGB_OUT(d1 + BPP, r, g, b); \
+ \
+ d1 += 2 * BPP; \
+ \
+ y1_ptr += 2; \
+ cb_ptr++; \
+ cr_ptr++; \
+ } \
+ /* handle width */ \
+ if (w) { \
+ cb = cb_ptr[0] - 128; \
+ cr = cr_ptr[0] - 128; \
+ r_add = C_RV * cr + (1 << (SCALE_BITS - 1)); \
+ g_add = - C_GU * cb - C_GV * cr + (1 << (SCALE_BITS - 1)); \
+ b_add = C_BU * cb + (1 << (SCALE_BITS - 1)); \
+ \
+ /* output 2 pixels */ \
+ YUV_TO_RGB2(r, g, b, y1_ptr[0]); \
+ RGB_OUT(d1, r, g, b); \
+ d1 += BPP; \
+ \
+ y1_ptr++; \
+ cb_ptr++; \
+ cr_ptr++; \
+ } \
+ } \
} \
\
/* XXX: no chroma interpolating is done */ \
@@ -477,10 +515,10 @@ static void yuv422p_to_ ## rgb_name (AVPicture *dst, AVPicture *src, \
y1_ptr = src->data[0]; \
cb_ptr = src->data[1]; \
cr_ptr = src->data[2]; \
- width2 = width >> 1; \
+ width2 = (width + 1) >> 1; \
for(;height > 0; height --) { \
d1 = d; \
- for(w = width2; w > 0; w --) { \
+ for(w = width; w >= 2; w -= 2) { \
cb = cb_ptr[0] - 128; \
cr = cr_ptr[0] - 128; \
r_add = C_RV * cr + (1 << (SCALE_BITS - 1)); \
@@ -489,17 +527,34 @@ static void yuv422p_to_ ## rgb_name (AVPicture *dst, AVPicture *src, \
\
/* output 2 pixels */ \
YUV_TO_RGB2(r, g, b, y1_ptr[0]); \
- RGB_OUT(d, r, g, b); \
+ RGB_OUT(d1, r, g, b); \
\
YUV_TO_RGB2(r, g, b, y1_ptr[1]); \
- RGB_OUT(d + BPP, r, g, b); \
+ RGB_OUT(d1 + BPP, r, g, b); \
\
- d += 2 * BPP; \
+ d1 += 2 * BPP; \
\
y1_ptr += 2; \
cb_ptr++; \
cr_ptr++; \
} \
+ /* handle width */ \
+ if (w) { \
+ cb = cb_ptr[0] - 128; \
+ cr = cr_ptr[0] - 128; \
+ r_add = C_RV * cr + (1 << (SCALE_BITS - 1)); \
+ g_add = - C_GU * cb - C_GV * cr + (1 << (SCALE_BITS - 1)); \
+ b_add = C_BU * cb + (1 << (SCALE_BITS - 1)); \
+ \
+ /* output 2 pixels */ \
+ YUV_TO_RGB2(r, g, b, y1_ptr[0]); \
+ RGB_OUT(d1, r, g, b); \
+ d1 += BPP; \
+ \
+ y1_ptr++; \
+ cb_ptr++; \
+ cr_ptr++; \
+ } \
d += dst->linesize[0]; \
y1_ptr += src->linesize[0] - width; \
cb_ptr += src->linesize[1] - width2; \