Leptonica 1.68
C Image Processing Library

yuvtest.c

Go to the documentation of this file.
00001 /*====================================================================*
00002  -  Copyright (C) 2001 Leptonica.  All rights reserved.
00003  -  This software is distributed in the hope that it will be
00004  -  useful, but with NO WARRANTY OF ANY KIND.
00005  -  No author or distributor accepts responsibility to anyone for the
00006  -  consequences of using this software, or for whether it serves any
00007  -  particular purpose or works at all, unless he or she says so in
00008  -  writing.  Everyone is granted permission to copy, modify and
00009  -  redistribute this source code, for commercial or non-commercial
00010  -  purposes, with the following restrictions: (1) the origin of this
00011  -  source code must not be misrepresented; (2) modified versions must
00012  -  be plainly marked as such; and (3) this notice may not be removed
00013  -  or altered from any source or modified source distribution.
00014  *====================================================================*/
00015 
00016 /*
00017  *  yuvtest.c
00018  *
00019  *    Test the yuv to rgb conversion.
00020  *
00021  *    Note that the yuv gamut is greater than rgb, so although any
00022  *    rgb image can be converted to yuv (and back), any possible
00023  *    yuv value does not necessarily represent a valid rgb value.
00024  */
00025 
00026 #include "allheaders.h"
00027 
00028 void AddTransformsRGB(PIXA *pixa, L_BMF *bmf, l_int32 gval);
00029 void AddTransformsYUV(PIXA *pixa, L_BMF *bmf, l_int32 yval);
00030 
00031 
00032 l_int32 main(int    argc,
00033              char **argv)
00034 {
00035 l_int32     size, i, rval, gval, bval, yval, uval, vval;
00036 l_float32  *a[3], b[3];
00037 L_BMF      *bmf;
00038 PIX        *pixd;
00039 PIXA       *pixa;
00040 
00041         /* Explore the range of rgb --> yuv transforms.  All rgb
00042          * values transform to a valid value of yuv, so when transforming
00043          * back we get the same rgb values that we started with. */
00044     pixa = pixaCreate(0);
00045     bmf = bmfCreate("fonts", 6);
00046     for (gval = 0; gval <= 255; gval += 20)
00047         AddTransformsRGB(pixa, bmf, gval);
00048 
00049     pixd = pixaDisplayTiledAndScaled(pixa, 32, 755, 1, 0, 20, 2);
00050     pixDisplay(pixd, 100, 0);
00051     pixWrite("/tmp/yuv1.png", pixd, IFF_PNG);
00052     pixDestroy(&pixd);
00053     pixaDestroy(&pixa);
00054 
00055         /* Now start with all "valid" yuv values, not all of which are
00056          * related to a valid rgb value.  Our yuv --> rgb transform
00057          * clips the rgb components to [0 ... 255], so when transforming
00058          * back we get different values whenever the initial yuv
00059          * value is out of the rgb gamut. */
00060     pixa = pixaCreate(0);
00061     for (yval = 16; yval <= 235; yval += 16)
00062         AddTransformsYUV(pixa, bmf, yval);
00063 
00064     pixd = pixaDisplayTiledAndScaled(pixa, 32, 755, 1, 0, 20, 2);
00065     pixDisplay(pixd, 600, 0);
00066     pixWrite("/tmp/yuv2.png", pixd, IFF_PNG);
00067     pixDestroy(&pixd);
00068     pixaDestroy(&pixa);
00069     bmfDestroy(&bmf);
00070 
00071 
00072     /* --------- Try out a special case by hand, and show that --------- *
00073      * ------- the transform matrices we are using are inverses ---------*/
00074 
00075         /* First, use our functions for the transform */
00076     fprintf(stderr, "Start with: yval = 143, uval = 79, vval = 103\n");
00077     convertYUVToRGB(143, 79, 103, &rval, &gval, &bval);
00078     fprintf(stderr, " ==> rval = %d, gval = %d, bval = %d\n", rval, gval, bval);
00079     convertRGBToYUV(rval, gval, bval, &yval, &uval, &vval);
00080     fprintf(stderr, " ==> yval = %d, uval = %d, vval = %d\n", yval, uval, vval);
00081 
00082         /* Next, convert yuv --> rbg by solving for rgb --> yuv transform.
00083          *      [ a00   a01   a02 ]    r   =   b0           (y - 16)
00084          *      [ a10   a11   a12 ] *  g   =   b1           (u - 128)
00085          *      [ a20   a21   a22 ]    b   =   b2           (v - 128)
00086          */
00087     b[0] = 143.0 - 16.0;    /* y - 16 */
00088     b[1] = 79.0 - 128.0;   /* u - 128 */
00089     b[2] = 103.0 - 128.0;    /* v - 128 */
00090     for (i = 0; i < 3; i++)
00091         a[i] = (l_float32 *)lept_calloc(3, sizeof(l_float32));
00092     a[0][0] = 65.738 / 256.0;
00093     a[0][1] = 129.057 / 256.0;
00094     a[0][2] = 25.064 / 256.0;
00095     a[1][0] = -37.945 / 256.0;
00096     a[1][1] = -74.494 / 256.0;
00097     a[1][2] = 112.439 / 256.0;
00098     a[2][0] = 112.439 / 256.0;
00099     a[2][1] = -94.154 / 256.0;
00100     a[2][2] = -18.285 / 256.0;
00101     fprintf(stderr, "Here's the original matrix: yuv --> rgb:\n");
00102     for (i = 0; i < 3; i++)
00103         fprintf(stderr, "    %7.3f  %7.3f  %7.3f\n", 256.0 * a[i][0],
00104                 256.0 * a[i][1], 256.0 * a[i][2]);
00105     gaussjordan(a, b, 3);
00106     fprintf(stderr, "\nInput (yuv) = (143,79,103); solve for rgb:\n"
00107             "rval = %7.3f, gval = %7.3f, bval = %7.3f\n",
00108             b[0], b[1], b[2]);
00109     fprintf(stderr, "Here's the inverse matrix: rgb --> yuv:\n");
00110     for (i = 0; i < 3; i++)
00111         fprintf(stderr, "    %7.3f  %7.3f  %7.3f\n", 256.0 * a[i][0],
00112                 256.0 * a[i][1], 256.0 * a[i][2]);
00113 
00114         /* Now, convert back: rgb --> yuv;
00115          * Do this by solving for yuv --> rgb transform.
00116          * Use the b[] found previously (the rgb values), and
00117          * the a[][] which now holds the rgb --> yuv transform.  */
00118     gaussjordan(a, b, 3);
00119     fprintf(stderr, "\nInput rgb; solve for yuv:\n"
00120             "yval = %7.3f, uval = %7.3f, vval = %7.3f\n",
00121             b[0] + 16.0, b[1] + 128.0, b[2] + 128.0);
00122     fprintf(stderr, "Inverting the matrix again: yuv --> rgb:\n");
00123     for (i = 0; i < 3; i++)
00124         fprintf(stderr, "    %7.3f  %7.3f  %7.3f\n", 256.0 * a[i][0],
00125                 256.0 * a[i][1], 256.0 * a[i][2]);
00126 
00127     for (i = 0; i < 3; i++) lept_free(a[i]);
00128     return 0;
00129 }
00130 
00131 
00132 void
00133 AddTransformsRGB(PIXA    *pixa,
00134                  L_BMF   *bmf,
00135                  l_int32  gval)
00136 {
00137 char       textbuf[256];
00138 l_int32    i, j, wpls;
00139 l_uint32  *datas, *lines;
00140 PIX       *pixs, *pixt1, *pixt2, *pixt3, *pixt4;
00141 PIXA      *pixat;
00142 
00143     pixs = pixCreate(255, 255, 32);
00144     wpls = pixGetWpl(pixs);
00145     datas = pixGetData(pixs);
00146     for (i = 0; i < 255; i++) {   /* r */
00147         lines = datas + i * wpls;
00148         for (j = 0; j < 255; j++)  /* b */
00149             composeRGBPixel(i, gval, j, lines + j);
00150     }
00151 
00152     pixat = pixaCreate(3);
00153     pixaAddPix(pixat, pixs, L_INSERT);
00154     pixt1 = pixConvertRGBToYUV(NULL, pixs);
00155     pixaAddPix(pixat, pixt1, L_INSERT);
00156     pixt2 = pixConvertYUVToRGB(NULL, pixt1);
00157     pixaAddPix(pixat, pixt2, L_INSERT);
00158     pixt3 = pixaDisplayTiledAndScaled(pixat, 32, 255, 3, 0, 20, 2);
00159     snprintf(textbuf, sizeof(textbuf), "gval = %d", gval);
00160     pixt4 = pixAddSingleTextblock(pixt3, bmf, textbuf, 0xff000000,
00161                                   L_ADD_BELOW, NULL);
00162     pixaAddPix(pixa, pixt4, L_INSERT);
00163     pixDestroy(&pixt3);
00164     pixaDestroy(&pixat);
00165     return;
00166 }
00167 
00168 
00169 void
00170 AddTransformsYUV(PIXA    *pixa,
00171                  L_BMF   *bmf,
00172                  l_int32  yval)
00173 {
00174 char       textbuf[256];
00175 l_int32    i, j, wpls;
00176 l_uint32  *datas, *lines;
00177 PIX       *pixs, *pixt1, *pixt2, *pixt3, *pixt4;
00178 PIXA      *pixat;
00179 
00180     pixs = pixCreate(225, 225, 32);
00181     wpls = pixGetWpl(pixs);
00182     datas = pixGetData(pixs);
00183     for (i = 0; i < 225; i++) {   /* v */
00184         lines = datas + i * wpls;
00185         for (j = 0; j < 225; j++)  /* u */
00186             composeRGBPixel(yval + 16, j + 16, i + 16, lines + j);
00187     }
00188 
00189     pixat = pixaCreate(3);
00190     pixaAddPix(pixat, pixs, L_INSERT);
00191     pixt1 = pixConvertYUVToRGB(NULL, pixs);
00192     pixaAddPix(pixat, pixt1, L_INSERT);
00193     pixt2 = pixConvertRGBToYUV(NULL, pixt1);
00194     pixaAddPix(pixat, pixt2, L_INSERT);
00195     pixt3 = pixaDisplayTiledAndScaled(pixat, 32, 225, 3, 0, 20, 2);
00196     snprintf(textbuf, sizeof(textbuf), "yval = %d", yval);
00197     pixt4 = pixAddSingleTextblock(pixt3, bmf, textbuf, 0xff000000,
00198                                   L_ADD_BELOW, NULL);
00199     pixaAddPix(pixa, pixt4, L_INSERT);
00200     pixDestroy(&pixt3);
00201     pixaDestroy(&pixat);
00202     return;
00203 }
00204 
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines