Leptonica 1.68
C Image Processing Library
|
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