complete rewrite of opj_convert.c with correct values (from winfried)
authorAntonin Descampe <antonin@gmail.com>
Mon, 15 Nov 2010 11:06:46 +0000 (11:06 +0000)
committerAntonin Descampe <antonin@gmail.com>
Mon, 15 Nov 2010 11:06:46 +0000 (11:06 +0000)
CHANGES
libopenjpeg/opj_convert.c

diff --git a/CHANGES b/CHANGES
index c3541d49aabb45082c19fd9704c43fd3af77af50..4165a6d52030deaef2af6d9662cc8711cffa6ca4 100644 (file)
--- 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;
 
index 332166553507d623ea52c99422a33c382fd37875..0355e502cc6e3d05ccdfc1c0a1426b221e7b73cb 100644 (file)
 #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)
-{
-    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;
-
-    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;
-
-    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);
-
-    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<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;
+/*--------------------------------------------------------
+Matrix f�r sYCC, Amendment 1 to IEC 61966-2-1
 
-       tmp=(y+crR)>>16;
-       if(tmp < 0) tmp = 0; else if(tmp > 255) tmp = 255;
-       *red++ = tmp;
+Y :   0.299   0.587    0.114   :R
+Cb:  -0.1687 -0.3312   0.5     :G
+Cr:   0.5    -0.4187  -0.0812  :B
 
-       tmp=(y-crG-cbG)>>16;
-       if(tmp < 0) tmp = 0; else if(tmp > 255) tmp = 255;
-       *green++ = tmp;
+Inverse:
 
-       tmp=(y+cbB)>>16;
-       if(tmp < 0) tmp = 0; else if(tmp > 255) tmp = 255;
-       *blue = tmp;
+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)
 
-       y=(src_y[j+1]-16)*Ky;
+-----------------------------------------------------------*/
+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 r, g, b;
 
-       tmp=(y+crR)>>16;
-       if(tmp < 0) tmp = 0; else if(tmp > 255) tmp = 255;
-       *red++ = tmp;
+       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;
 
-       tmp=(y-crG-cbG)>>16;
-       if(tmp < 0) tmp = 0; else if(tmp > 255) tmp = 255;
-       *green++ = tmp;
+       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;
 
-       tmp=(y+cbB)>>16;
-       if(tmp < 0) tmp = 0; else if(tmp > 255) tmp = 255;
-       *blue++ = tmp;
-  }
-       src_y += width;
-   }
-}/* yuv422rgb() */
+       b = y + (int)(1.772 * (float)cb);
+       if(b < 0) b = 0; else if(b > upb) b = upb; *out_b = b;
+}
 
-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;
-
-       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;
+       int *d0, *d1, *d2, *r, *g, *b;
+       const int *y, *cb, *cr;
+       int maxw, maxh, max, i, offset, upb;
 
-       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);
+       i = img->comps[0].prec;
+       offset = 1<<(i - 1); upb = (1<<i)-1;
 
-       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);
+       maxw = img->comps[0].w; maxh = img->comps[0].h;
+       max = maxw * maxh;
 
-       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 = img->comps[0].data;
+       cb = img->comps[1].data;
+       cr = img->comps[2].data;
 
-       y=(src_y[j+1]-16)*Ky;
+       d0 = r = (int*)opj_malloc(sizeof(int) * max);
+       d1 = g = (int*)opj_malloc(sizeof(int) * max);
+       d2 = b = (int*)opj_malloc(sizeof(int) * max);
 
-       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);
+       for(i = 0; i < max; ++i)
+   {
+       sycc_to_rgb(offset, upb, *y, *cb, *cr, r, g, b);        
 
-       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);
+       ++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;
 
-       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);
+}/* opj_convert_sycc444() */
 
-       y=(src_y[j+yskip]-16)*Ky;
+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;
 
-       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);
+       i = img->comps[0].prec;
+       offset = 1<<(i - 1); upb = (1<<i)-1;
 
-       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);
+       maxw = img->comps[0].w; maxh = img->comps[0].h;
+       max = maxw * maxh;
 
-       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 = img->comps[0].data;
+       cb = img->comps[1].data;
+       cr = img->comps[2].data;
 
-       y=(src_y[j+1+yskip]-16)*Ky;
+       d0 = r = (int*)opj_malloc(sizeof(int) * max);
+       d1 = g = (int*)opj_malloc(sizeof(int) * max);
+       d2 = b = (int*)opj_malloc(sizeof(int) * max);
 
-       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);
+       for(i=0; i < maxh; ++i)
+   {
+       for(j=0; j < maxw; j += 2)
+  {
+       sycc_to_rgb(offset, upb, *y, *cb, *cr, r, g, b);
 
-       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);
+       ++y; ++r; ++g; ++b;
 
-       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);
+       sycc_to_rgb(offset, upb, *y, *cb, *cr, r, g, b);
 
+       ++y; ++r; ++g; ++b; ++cb; ++cr;
   }
-       red_e += width; green_e += width; blue_e += width;
-       red_o += width; green_o += width; blue_o += width;
-       src_y += width<<1;
    }
-}/* yuv420rgb() */
+       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;
 
-static void opj_convert_yuv422(opj_image_t *img)
+}/* opj_convert_sycc422() */
+
+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; 
+       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 += 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);
 
-static void opj_convert_yuv420(opj_image_t *img)
-{
-       int *y, *cb, *cr, *red, *green, *blue;
-       int maxy, maxw, maxh;
+       ++y; ++r; ++g; ++b;
 
-       maxw = img->comps[0].w; maxh = img->comps[0].h;
-       maxy = maxw * maxh;
+       sycc_to_rgb(offset, upb, *ny, *cb, *cr, nr, ng, nb);
 
-       y = img->comps[0].data;
-       cb = img->comps[1].data; 
-       cr = img->comps[2].data;
+       ++ny; ++nr; ++ng; ++nb;
 
-//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);
+       sycc_to_rgb(offset, upb, *ny, *cb, *cr, nr, ng, nb);
 
-       yuv420rgb(y, cb, cr, red, green, blue, maxw, maxh);
-
-       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;
+       ++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[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[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,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() */