complete rewrite of opj_convert.c with correct values (from winfried)
This commit is contained in:
parent
005b1b1a4b
commit
2b7f6f82be
3
CHANGES
3
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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
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;
|
||||
|
||||
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;
|
||||
|
||||
b = y + (int)(1.772 * (float)cb);
|
||||
if(b < 0) b = 0; else if(b > upb) b = upb; *out_b = b;
|
||||
}
|
||||
|
||||
static void opj_convert_sycc444(opj_image_t *img)
|
||||
{
|
||||
int *d0, *d1, *d2, *r, *g, *b;
|
||||
const int *y, *cb, *cr;
|
||||
int maxw, maxh, max, i, offset, upb;
|
||||
|
||||
i = img->comps[0].prec;
|
||||
offset = 1<<(i - 1); upb = (1<<i)-1;
|
||||
|
||||
maxw = img->comps[0].w; maxh = img->comps[0].h;
|
||||
max = maxw * maxh;
|
||||
|
||||
sY = img->comps[0].data;
|
||||
sCb = img->comps[1].data;
|
||||
sCr = img->comps[2].data;
|
||||
y = img->comps[0].data;
|
||||
cb = img->comps[1].data;
|
||||
cr = img->comps[2].data;
|
||||
|
||||
if(img->comps[0].prec > 8)
|
||||
shiftR = img->comps[0].prec - 8;
|
||||
else
|
||||
shiftR = 0;
|
||||
|
||||
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);
|
||||
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 < 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;
|
||||
sycc_to_rgb(offset, upb, *y, *cb, *cr, r, g, b);
|
||||
|
||||
++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;
|
||||
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[0].prec = 8; img->comps[1].prec = 8; img->comps[2].prec = 8;
|
||||
}/* opj_convert_yuv444() */
|
||||
}/* opj_convert_sycc444() */
|
||||
|
||||
static void yuv422rgb(int *src_y, int *src_cb, int *src_cr, int *red,
|
||||
int *green, int *blue, int width, int height)
|
||||
static void opj_convert_sycc422(opj_image_t *img)
|
||||
{
|
||||
int i, j, tmp;
|
||||
int y, crR, crG, cbG, cbB;
|
||||
int *d0, *d1, *d2, *r, *g, *b;
|
||||
const int *y, *cb, *cr;
|
||||
int maxw, maxh, max, offset, upb;
|
||||
int i, j;
|
||||
|
||||
for(i=0; i<height; i++)
|
||||
{
|
||||
for(j=0; j<width; j+=2)
|
||||
{
|
||||
crR=(*src_cr - 128)*KcrR;
|
||||
crG=(*src_cr - 128)*KcrG; ++src_cr;
|
||||
cbG=(*src_cb - 128)*KcbG;
|
||||
cbB=(*src_cb - 128)*KcbB; ++src_cb;
|
||||
|
||||
y=(src_y[j]-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;
|
||||
|
||||
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)
|
||||
{
|
||||
int *red_e, *green_e, *blue_e, *red_o, *green_o, *blue_o;
|
||||
int y, crR, crG, cbG, cbB, i, j, tmp;
|
||||
int yskip;
|
||||
|
||||
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<<i)-1;
|
||||
|
||||
maxw = img->comps[0].w; maxh = img->comps[0].h;
|
||||
maxy = maxw * maxh;
|
||||
max = maxw * maxh;
|
||||
|
||||
y = img->comps[0].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 < maxh; ++i)
|
||||
{
|
||||
for(j=0; j < maxw; j += 2)
|
||||
{
|
||||
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; ++r; ++g; ++b;
|
||||
|
||||
img->comps[1].w = maxw; img->comps[2].h = maxh;
|
||||
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[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<<i)-1;
|
||||
|
||||
maxw = img->comps[0].w; maxh = img->comps[0].h;
|
||||
maxy = maxw * maxh;
|
||||
max = maxw * maxh;
|
||||
|
||||
y = img->comps[0].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;
|
||||
++y; ++r; ++g; ++b;
|
||||
|
||||
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;
|
||||
|
||||
img->comps[0].prec = 8; img->comps[1].prec = 8; img->comps[2].prec = 8;
|
||||
}
|
||||
}/* opj_convert_sycc420() */
|
||||
|
||||
void opj_convert_sycc_to_rgb(opj_image_t *img)
|
||||
{
|
||||
|
@ -276,14 +175,15 @@ 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
|
||||
&& (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)
|
||||
|
@ -291,9 +191,9 @@ void opj_convert_sycc_to_rgb(opj_image_t *img)
|
|||
&& (img->comps[2].dx == 2)
|
||||
&& (img->comps[0].dy == 1)
|
||||
&& (img->comps[1].dy == 1)
|
||||
&& (img->comps[2].dy == 1))// horizontal only
|
||||
&& (img->comps[2].dy == 1))/* horizontal sub-sample only */
|
||||
{
|
||||
opj_convert_yuv422(img);
|
||||
opj_convert_sycc422(img);
|
||||
}
|
||||
else
|
||||
if((img->comps[0].dx == 1)
|
||||
|
@ -301,9 +201,9 @@ void opj_convert_sycc_to_rgb(opj_image_t *img)
|
|||
&& (img->comps[2].dx == 1)
|
||||
&& (img->comps[0].dy == 1)
|
||||
&& (img->comps[1].dy == 1)
|
||||
&& (img->comps[2].dy == 1))
|
||||
&& (img->comps[2].dy == 1))/* no sub-sample */
|
||||
{
|
||||
opj_convert_yuv444(img);
|
||||
opj_convert_sycc444(img);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -312,4 +212,5 @@ __FILE__,__LINE__);
|
|||
return;
|
||||
}
|
||||
img->color_space = CLRSPC_SRGB;
|
||||
|
||||
}/* opj_convert_sycc_to_rgb() */
|
||||
|
|
Loading…
Reference in New Issue