From 2b7f6f82bece95a79adeffa1c731fdf6383e60cf Mon Sep 17 00:00:00 2001 From: Antonin Descampe Date: Mon, 15 Nov 2010 11:06:46 +0000 Subject: [PATCH] complete rewrite of opj_convert.c with correct values (from winfried) --- CHANGES | 3 + libopenjpeg/opj_convert.c | 425 +++++++++++++++----------------------- 2 files changed, 166 insertions(+), 262 deletions(-) diff --git a/CHANGES b/CHANGES index c3541d49..4165a6d5 100644 --- a/CHANGES +++ b/CHANGES @@ -5,6 +5,9 @@ What's New for OpenJPEG ! : changed + : added +November 15, 2010 +* [antonin] complete rewrite of opj_convert.c with correct values (from winfried) + November 11, 2010 - [antonin] removed call to dirent.h in jp3d; diff --git a/libopenjpeg/opj_convert.c b/libopenjpeg/opj_convert.c index 33216655..0355e502 100644 --- a/libopenjpeg/opj_convert.c +++ b/libopenjpeg/opj_convert.c @@ -1,273 +1,172 @@ #include "opj_includes.h" -#include "opj_convert.h" -/* - * The yuv code is based on cinelerra-VERSION/quicktime/rtjpeg_core.c -*/ -#define KcrR 76284 -#define KcrG 53281 -#define KcbG 25625 -#define KcbB 132252 -#define Ky 76284 -static void opj_convert_yuv444(opj_image_t *img) +/*-------------------------------------------------------- +Matrix für sYCC, Amendment 1 to IEC 61966-2-1 + +Y : 0.299 0.587 0.114 :R +Cb: -0.1687 -0.3312 0.5 :G +Cr: 0.5 -0.4187 -0.0812 :B + +Inverse: + +R: 1 -3.68213e-05 1.40199 :Y +G: 1.00003 -0.344125 -0.714128 :Cb - 2^(prec - 1) +B: 0.999823 1.77204 -8.04142e-06 :Cr - 2^(prec - 1) + +-----------------------------------------------------------*/ +static void sycc_to_rgb(int offset, int upb, int y, int cb, int cr, + int *out_r, int *out_g, int *out_b) { - int *d0, *d1, *d2, *red, *green, *blue; - const int *sY, *sCb, *sCr; - int maxw, maxh, max, i; - int R, G, B, C, D, E; - int shiftR, shiftG, shiftB; - int addR, addG, addB; + int r, g, b; - maxw = img->comps[0].w; maxh = img->comps[0].h; - max = maxw * maxh; + cb -= offset; cr -= offset; + r = y + (int)(1.402 * (float)cr); + if(r < 0) r = 0; else if(r > upb) r = upb; *out_r = r; - sY = img->comps[0].data; - sCb = img->comps[1].data; - sCr = img->comps[2].data; + g = y - (int)(0.344 * (float)cb + 0.714 * (float)cr); + if(g < 0) g = 0; else if(g > upb) g = upb; *out_g = g; - if(img->comps[0].prec > 8) - shiftR = img->comps[0].prec - 8; - else - shiftR = 0; + b = y + (int)(1.772 * (float)cb); + if(b < 0) b = 0; else if(b > upb) b = upb; *out_b = b; +} - if(img->comps[1].prec > 8) - shiftG = img->comps[1].prec - 8; - else - shiftG = 0; - - if(img->comps[2].prec > 8) - shiftB = img->comps[2].prec - 8; - else - shiftB = 0; - - addR = (img->comps[0].sgnd ? 1 << (img->comps[0].prec - 1) : 0); - addG = (img->comps[1].sgnd ? 1 << (img->comps[1].prec - 1) : 0); - addB = (img->comps[2].sgnd ? 1 << (img->comps[2].prec - 1) : 0); - - d0 = red = (int*)opj_malloc(sizeof(int) * max); - d1 = green = (int*)opj_malloc(sizeof(int) * max); - d2 = blue = (int*)opj_malloc(sizeof(int) * max); - - for(i = 0; i < max; ++i) - { - C = ((*sY++ + addR) >> shiftR) - 16; - D = ((*sCb++ + addG) >> shiftG) - 128; - E = ((*sCr++ + addB) >> shiftB) - 128; - - - R = (298 * C + 409 * E + 128)>>8; - if(R < 0) R = 0; else if(R > 255) R = 255; - - G = (298 * C - 100 * D - 208 * E + 128)>>8; - if(G < 0) G = 0; else if(G > 255) G = 255; - - B = (298 * C + 516 * D + 128)>>8; - if(B < 0) B = 0; else if(B > 255) B = 255; - - *d0++ = R; *d1++ = G; *d2++ = B; - - } - opj_free(img->comps[0].data); img->comps[0].data = red; - opj_free(img->comps[1].data); img->comps[1].data = green; - opj_free(img->comps[2].data); img->comps[2].data = blue; - - img->comps[0].prec = 8; img->comps[1].prec = 8; img->comps[2].prec = 8; -}/* opj_convert_yuv444() */ - -static void yuv422rgb(int *src_y, int *src_cb, int *src_cr, int *red, - int *green, int *blue, int width, int height) -{ - int i, j, tmp; - int y, crR, crG, cbG, cbB; - - for(i=0; i>16; - if(tmp < 0) tmp = 0; else if(tmp > 255) tmp = 255; - *red++ = tmp; - - tmp=(y-crG-cbG)>>16; - if(tmp < 0) tmp = 0; else if(tmp > 255) tmp = 255; - *green++ = tmp; - - tmp=(y+cbB)>>16; - if(tmp < 0) tmp = 0; else if(tmp > 255) tmp = 255; - *blue = tmp; - - y=(src_y[j+1]-16)*Ky; - - tmp=(y+crR)>>16; - if(tmp < 0) tmp = 0; else if(tmp > 255) tmp = 255; - *red++ = tmp; - - tmp=(y-crG-cbG)>>16; - if(tmp < 0) tmp = 0; else if(tmp > 255) tmp = 255; - *green++ = tmp; - - tmp=(y+cbB)>>16; - if(tmp < 0) tmp = 0; else if(tmp > 255) tmp = 255; - *blue++ = tmp; - } - src_y += width; - } -}/* yuv422rgb() */ - -static void yuv420rgb(const int *src_y, const int *src_cb, - const int *src_cr, int *red, int *green, int *blue, - int width, int height) +static void opj_convert_sycc444(opj_image_t *img) { - int *red_e, *green_e, *blue_e, *red_o, *green_o, *blue_o; - int y, crR, crG, cbG, cbB, i, j, tmp; - int yskip; + int *d0, *d1, *d2, *r, *g, *b; + const int *y, *cb, *cr; + int maxw, maxh, max, i, offset, upb; - yskip = width; - red_e = red; green_e = green; blue_e = blue; - red_o = red + width; green_o = green + width; blue_o = blue + width; - - for(i=0; i < (height>>1); i++) - { - for(j=0; j < width; j+=2) - { - crR=(*src_cr-128)*KcrR; - crG=(*(src_cr++)-128)*KcrG; - cbG=(*src_cb-128)*KcbG; - cbB=(*(src_cb++)-128)*KcbB; - - y=(src_y[j]-16)*Ky; - - tmp=(y+crR)>>16; - if(tmp < 0) tmp = 0; else if(tmp > 255) tmp = 255; - *red_e++ = tmp;//*(bufoute++)=(tmp>255)?255:((tmp<0)?0:tmp); - - tmp=(y-crG-cbG)>>16; - if(tmp < 0) tmp = 0; else if(tmp > 255) tmp = 255; - *green_e++ = tmp;//*(bufoute++)=(tmp>255)?255:((tmp<0)?0:tmp); - - tmp=(y+cbB)>>16; - if(tmp < 0) tmp = 0; else if(tmp > 255) tmp = 255; - *blue_e++ = tmp;//*(bufoute++)=(tmp>255)?255:((tmp<0)?0:tmp); - - y=(src_y[j+1]-16)*Ky; - - tmp=(y+crR)>>16; - if(tmp < 0) tmp = 0; else if(tmp > 255) tmp = 255; - *red_e++ = tmp;//*(bufoute++)=(tmp>255)?255:((tmp<0)?0:tmp); - - tmp=(y-crG-cbG)>>16; - if(tmp < 0) tmp = 0; else if(tmp > 255) tmp = 255; - *green_e++ = tmp;//*(bufoute++)=(tmp>255)?255:((tmp<0)?0:tmp); - - tmp=(y+cbB)>>16; - if(tmp < 0) tmp = 0; else if(tmp > 255) tmp = 255; - *blue_e++ = tmp;//*(bufoute++)=(tmp>255)?255:((tmp<0)?0:tmp); - - y=(src_y[j+yskip]-16)*Ky; - - tmp=(y+crR)>>16; - if(tmp < 0) tmp = 0; else if(tmp > 255) tmp = 255; - *red_o++ = tmp;//*(bufouto++)=(tmp>255)?255:((tmp<0)?0:tmp); - - tmp=(y-crG-cbG)>>16; - if(tmp < 0) tmp = 0; else if(tmp > 255) tmp = 255; - *green_o++ = tmp;//*(bufouto++)=(tmp>255)?255:((tmp<0)?0:tmp); - - tmp=(y+cbB)>>16; - if(tmp < 0) tmp = 0; else if(tmp > 255) tmp = 255; - *blue_o++ = tmp;//*(bufouto++)=(tmp>255)?255:((tmp<0)?0:tmp); - - y=(src_y[j+1+yskip]-16)*Ky; - - tmp=(y+crR)>>16; - if(tmp < 0) tmp = 0; else if(tmp > 255) tmp = 255; - *red_o++ = tmp;//*(bufouto++)=(tmp>255)?255:((tmp<0)?0:tmp); - - tmp=(y-crG-cbG)>>16; - if(tmp < 0) tmp = 0; else if(tmp > 255) tmp = 255; - *green_o++ = tmp;//*(bufouto++)=(tmp>255)?255:((tmp<0)?0:tmp); - - tmp=(y+cbB)>>16; - if(tmp < 0) tmp = 0; else if(tmp > 255) tmp = 255; - *blue_o++ = tmp;//*(bufouto++)=(tmp>255)?255:((tmp<0)?0:tmp); - - } - red_e += width; green_e += width; blue_e += width; - red_o += width; green_o += width; blue_o += width; - src_y += width<<1; - } -}/* yuv420rgb() */ - -static void opj_convert_yuv422(opj_image_t *img) -{ - int *y, *cb, *cr, *red, *green, *blue; - int maxy, maxw, maxh; + i = img->comps[0].prec; + offset = 1<<(i - 1); upb = (1<comps[0].w; maxh = img->comps[0].h; - maxy = maxw * maxh; + max = maxw * maxh; y = img->comps[0].data; - cb = img->comps[1].data; + cb = img->comps[1].data; cr = img->comps[2].data; -//YUV422 -> YUV444 -> RGB - red = (int*)opj_calloc(sizeof(int), maxy); - green = (int*)opj_calloc(sizeof(int), maxy); - blue = (int*)opj_calloc(sizeof(int), maxy); + d0 = r = (int*)opj_malloc(sizeof(int) * max); + d1 = g = (int*)opj_malloc(sizeof(int) * max); + d2 = b = (int*)opj_malloc(sizeof(int) * max); - yuv422rgb(y, cb, cr, red, green, blue, maxw, maxh); + for(i = 0; i < max; ++i) + { + sycc_to_rgb(offset, upb, *y, *cb, *cr, r, g, b); - opj_free(img->comps[0].data); img->comps[0].data = red; - opj_free(img->comps[1].data); img->comps[1].data = green; - opj_free(img->comps[2].data); img->comps[2].data = blue; + ++y; ++cb; ++cr; ++r; ++g; ++b; + } + opj_free(img->comps[0].data); img->comps[0].data = d0; + opj_free(img->comps[1].data); img->comps[1].data = d1; + opj_free(img->comps[2].data); img->comps[2].data = d2; - img->comps[1].w = maxw; img->comps[2].h = maxh; - img->comps[1].dx = img->comps[0].dx; +}/* opj_convert_sycc444() */ + +static void opj_convert_sycc422(opj_image_t *img) +{ + int *d0, *d1, *d2, *r, *g, *b; + const int *y, *cb, *cr; + int maxw, maxh, max, offset, upb; + int i, j; + + i = img->comps[0].prec; + offset = 1<<(i - 1); upb = (1<comps[0].w; maxh = img->comps[0].h; + max = maxw * maxh; + + y = img->comps[0].data; + cb = img->comps[1].data; + cr = img->comps[2].data; + + d0 = r = (int*)opj_malloc(sizeof(int) * max); + d1 = g = (int*)opj_malloc(sizeof(int) * max); + d2 = b = (int*)opj_malloc(sizeof(int) * max); + + for(i=0; i < maxh; ++i) + { + for(j=0; j < maxw; j += 2) + { + sycc_to_rgb(offset, upb, *y, *cb, *cr, r, g, b); + + ++y; ++r; ++g; ++b; + + sycc_to_rgb(offset, upb, *y, *cb, *cr, r, g, b); + + ++y; ++r; ++g; ++b; ++cb; ++cr; + } + } + opj_free(img->comps[0].data); img->comps[0].data = d0; + opj_free(img->comps[1].data); img->comps[1].data = d1; + opj_free(img->comps[2].data); img->comps[2].data = d2; + + img->comps[1].w = maxw; img->comps[1].h = maxh; + img->comps[2].w = maxw; img->comps[2].h = maxh; + img->comps[1].dx = img->comps[0].dx; img->comps[2].dx = img->comps[0].dx; - img->comps[1].dy = img->comps[0].dy; + img->comps[1].dy = img->comps[0].dy; img->comps[2].dy = img->comps[0].dy; - img->comps[0].prec = 8; img->comps[1].prec = 8; img->comps[2].prec = 8; -} +}/* opj_convert_sycc422() */ -static void opj_convert_yuv420(opj_image_t *img) +static void opj_convert_sycc420(opj_image_t *img) { - int *y, *cb, *cr, *red, *green, *blue; - int maxy, maxw, maxh; + int *d0, *d1, *d2, *r, *g, *b, *nr, *ng, *nb; + const int *y, *cb, *cr, *ny; + int maxw, maxh, max, offset, upb; + int i, j; + + i = img->comps[0].prec; + offset = 1<<(i - 1); upb = (1<comps[0].w; maxh = img->comps[0].h; - maxy = maxw * maxh; + max = maxw * maxh; y = img->comps[0].data; - cb = img->comps[1].data; + cb = img->comps[1].data; cr = img->comps[2].data; -//YUV420 -> YUV422 -> YUV444 -> RGB - red = (int*)opj_calloc(sizeof(int), maxy); - green = (int*)opj_calloc(sizeof(int), maxy); - blue = (int*)opj_calloc(sizeof(int), maxy); + d0 = r = (int*)opj_malloc(sizeof(int) * max); + d1 = g = (int*)opj_malloc(sizeof(int) * max); + d2 = b = (int*)opj_malloc(sizeof(int) * max); - yuv420rgb(y, cb, cr, red, green, blue, maxw, maxh); + for(i=0; i < maxh; i += 2) + { + ny = y + maxw; + nr = r + maxw; ng = g + maxw; nb = b + maxw; - opj_free(img->comps[0].data); img->comps[0].data = red; - opj_free(img->comps[1].data); img->comps[1].data = green; - opj_free(img->comps[2].data); img->comps[2].data = blue; + for(j=0; j < maxw; j += 2) + { + sycc_to_rgb(offset, upb, *y, *cb, *cr, r, g, b); - img->comps[1].w = maxw; img->comps[2].h = maxh; - img->comps[1].dx = img->comps[0].dx; - img->comps[2].dx = img->comps[0].dx; - img->comps[1].dy = img->comps[0].dy; - img->comps[2].dy = img->comps[0].dy; + ++y; ++r; ++g; ++b; - img->comps[0].prec = 8; img->comps[1].prec = 8; img->comps[2].prec = 8; -} + sycc_to_rgb(offset, upb, *y, *cb, *cr, r, g, b); + + ++y; ++r; ++g; ++b; + + sycc_to_rgb(offset, upb, *ny, *cb, *cr, nr, ng, nb); + + ++ny; ++nr; ++ng; ++nb; + + sycc_to_rgb(offset, upb, *ny, *cb, *cr, nr, ng, nb); + + ++ny; ++nr; ++ng; ++nb; ++cb; ++cr; + } + y += maxw; r += maxw; g += maxw; b += maxw; + } + opj_free(img->comps[0].data); img->comps[0].data = d0; + opj_free(img->comps[1].data); img->comps[1].data = d1; + opj_free(img->comps[2].data); img->comps[2].data = d2; + + img->comps[1].w = maxw; img->comps[1].h = maxh; + img->comps[2].w = maxw; img->comps[2].h = maxh; + img->comps[1].dx = img->comps[0].dx; + img->comps[2].dx = img->comps[0].dx; + img->comps[1].dy = img->comps[0].dy; + img->comps[2].dy = img->comps[0].dy; + +}/* opj_convert_sycc420() */ void opj_convert_sycc_to_rgb(opj_image_t *img) { @@ -276,40 +175,42 @@ void opj_convert_sycc_to_rgb(opj_image_t *img) img->color_space = CLRSPC_GRAY; return; } - if((img->comps[0].dx == 1) - && (img->comps[1].dx == 2) - && (img->comps[2].dx == 2) - && (img->comps[0].dy == 1) - && (img->comps[1].dy == 2) - && (img->comps[2].dy == 2))// horizontal and vertical + + if((img->comps[0].dx == 1) + && (img->comps[1].dx == 2) + && (img->comps[2].dx == 2) + && (img->comps[0].dy == 1) + && (img->comps[1].dy == 2) + && (img->comps[2].dy == 2))/* horizontal and vertical sub-sample */ { - opj_convert_yuv420(img); + opj_convert_sycc420(img); } - else - if((img->comps[0].dx == 1) - && (img->comps[1].dx == 2) - && (img->comps[2].dx == 2) - && (img->comps[0].dy == 1) - && (img->comps[1].dy == 1) - && (img->comps[2].dy == 1))// horizontal only + else + if((img->comps[0].dx == 1) + && (img->comps[1].dx == 2) + && (img->comps[2].dx == 2) + && (img->comps[0].dy == 1) + && (img->comps[1].dy == 1) + && (img->comps[2].dy == 1))/* horizontal sub-sample only */ { - opj_convert_yuv422(img); + opj_convert_sycc422(img); } - else - if((img->comps[0].dx == 1) - && (img->comps[1].dx == 1) - && (img->comps[2].dx == 1) - && (img->comps[0].dy == 1) - && (img->comps[1].dy == 1) - && (img->comps[2].dy == 1)) + else + if((img->comps[0].dx == 1) + && (img->comps[1].dx == 1) + && (img->comps[2].dx == 1) + && (img->comps[0].dy == 1) + && (img->comps[1].dy == 1) + && (img->comps[2].dy == 1))/* no sub-sample */ { - opj_convert_yuv444(img); + opj_convert_sycc444(img); } else { -fprintf(stderr,"%s:%d:opj_convert_sycc_to_rgb\n\tCAN NOT CONVERT\n", -__FILE__,__LINE__); + fprintf(stderr,"%s:%d:opj_convert_sycc_to_rgb\n\tCAN NOT CONVERT\n", + __FILE__,__LINE__); return; } img->color_space = CLRSPC_SRGB; + }/* opj_convert_sycc_to_rgb() */