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 * smallpix_reg.c 00018 * 00019 * This is a regression test for scaling and rotation. 00020 * 00021 * The question to be answered is: in the quantization, where, if 00022 * anywhere, do we add 0.5? 00023 * 00024 * The answer is that it should usually, but not always, be omitted. 00025 * To see this, we operate on a very small pix and for visualization, 00026 * scale up with replication to avoid aliasing and shifting. 00027 * 00028 * To determine that the current implementations in scalelow.c, 00029 * rotate.c and rotateamlow.c are better, change the specific 00030 * implementations and re-run. 00031 * 00032 * In all cases here, the pix to be operated on is of odd size 00033 * so that the center pixel is symmetrically located, and there 00034 * are a couple of black pixels outside the pattern so that edge 00035 * effects (e.g., in pixScaleSmooth()) do not affect the results. 00036 */ 00037 00038 #include <stdio.h> 00039 #include <stdlib.h> 00040 #include "allheaders.h" 00041 00042 00043 void DisplayPix(PIXA **ppixa, l_int32 x, l_int32 y, char *fname) 00044 { 00045 PIX *pixt; 00046 00047 pixt = pixaDisplay(*ppixa, 0, 0); 00048 if (fname) 00049 pixWrite(fname, pixt, IFF_PNG); 00050 pixDisplay(pixt, x, y); 00051 pixDestroy(&pixt); 00052 pixaDestroy(ppixa); 00053 } 00054 00055 00056 main(int argc, 00057 char **argv) 00058 { 00059 l_int32 i; 00060 l_float32 pi, scale, angle; 00061 PIX *pixc, *pixm, *pix1, *pix2, *pix3; 00062 PIXA *pixa; 00063 PTA *pta1, *pta2, *pta3, *pta4; 00064 static char mainName[] = "smallpix_reg"; 00065 00066 /* Make a small test image, the hard way! */ 00067 pi = 3.1415926535; 00068 pixc = pixCreate(9, 9, 32); 00069 pixm = pixCreate(9, 9, 1); 00070 pta1 = generatePtaLineFromPt(4, 4, 3.1, 0.0); 00071 pta2 = generatePtaLineFromPt(4, 4, 3.1, 0.5 * pi); 00072 pta3 = generatePtaLineFromPt(4, 4, 3.1, pi); 00073 pta4 = generatePtaLineFromPt(4, 4, 3.1, 1.5 * pi); 00074 ptaJoin(pta1, pta2, 0, 0); 00075 ptaJoin(pta1, pta3, 0, 0); 00076 ptaJoin(pta1, pta4, 0, 0); 00077 pixRenderPta(pixm, pta1, L_SET_PIXELS); 00078 pixPaintThroughMask(pixc, pixm, 0, 0, 0x00ff0000); 00079 ptaDestroy(&pta1); 00080 ptaDestroy(&pta2); 00081 ptaDestroy(&pta3); 00082 ptaDestroy(&pta4); 00083 pixDestroy(&pixm); 00084 00085 /* Results differ for scaleSmoothLow() w/ and w/out + 0.5. 00086 * Neither is properly symmetric (with symm pattern on odd-sized 00087 * pix, because the smoothing is destroying the symmetry. */ 00088 pixa = pixaCreate(11); 00089 pix1 = pixExpandReplicate(pixc, 2); 00090 for (i = 0; i < 11; i++) { 00091 scale = 0.30 + 0.035 * (l_float32)i; 00092 pix2 = pixScaleSmooth(pix1, scale, scale); 00093 pix3 = pixExpandReplicate(pix2, 6); 00094 pixSaveTiled(pix3, pixa, 1, (i == 0), 20, 32); 00095 pixDestroy(&pix2); 00096 pixDestroy(&pix3); 00097 } 00098 pixDestroy(&pix1); 00099 DisplayPix(&pixa, 100, 100, NULL); 00100 00101 /* Results same for pixScaleAreaMap w/ and w/out + 0.5 */ 00102 pixa = pixaCreate(11); 00103 pix1 = pixExpandReplicate(pixc, 2); 00104 for (i = 0; i < 11; i++) { 00105 scale = 0.30 + 0.035 * (l_float32)i; 00106 pix2 = pixScaleAreaMap(pix1, scale, scale); 00107 pix3 = pixExpandReplicate(pix2, 6); 00108 pixSaveTiled(pix3, pixa, 1, (i == 0), 20, 32); 00109 pixDestroy(&pix2); 00110 pixDestroy(&pix3); 00111 } 00112 pixDestroy(&pix1); 00113 DisplayPix(&pixa, 100, 200, NULL); 00114 00115 /* Results better for pixScaleBySampling with + 0.5, for small, 00116 * odd-dimension pix. */ 00117 pixa = pixaCreate(11); 00118 pix1 = pixExpandReplicate(pixc, 2); 00119 for (i = 0; i < 11; i++) { 00120 scale = 0.30 + 0.035 * (l_float32)i; 00121 pix2 = pixScaleBySampling(pix1, scale, scale); 00122 pix3 = pixExpandReplicate(pix2, 6); 00123 pixSaveTiled(pix3, pixa, 1, (i == 0), 20, 32); 00124 pixDestroy(&pix2); 00125 pixDestroy(&pix3); 00126 } 00127 pixDestroy(&pix1); 00128 DisplayPix(&pixa, 100, 300, NULL); 00129 00130 /* Results same for pixRotateAM w/ and w/out + 0.5 */ 00131 pixa = pixaCreate(11); 00132 pix1 = pixExpandReplicate(pixc, 1); 00133 for (i = 0; i < 11; i++) { 00134 angle = 0.10 + 0.05 * (l_float32)i; 00135 pix2 = pixRotateAM(pix1, angle, L_BRING_IN_BLACK); 00136 pix3 = pixExpandReplicate(pix2, 8); 00137 pixSaveTiled(pix3, pixa, 1, (i == 0), 20, 32); 00138 pixDestroy(&pix2); 00139 pixDestroy(&pix3); 00140 } 00141 pixDestroy(&pix1); 00142 DisplayPix(&pixa, 100, 400, NULL); 00143 00144 /* If the size is odd, we express the center exactly, and the 00145 * results are better for pixRotateBySampling() w/out 0.5 00146 * However, if the size is even, the center value is not 00147 * exact, and if we choose it 0.5 smaller than the actual 00148 * center, we get symmetrical results with +0.5. 00149 * So we choose not to include + 0.5. */ 00150 pixa = pixaCreate(11); 00151 pix1 = pixExpandReplicate(pixc, 1); 00152 for (i = 0; i < 11; i++) { 00153 angle = 0.10 + 0.05 * (l_float32)i; 00154 pix2 = pixRotateBySampling(pix1, 4, 4, angle, L_BRING_IN_BLACK); 00155 pix3 = pixExpandReplicate(pix2, 8); 00156 pixSaveTiled(pix3, pixa, 1, (i == 0), 20, 32); 00157 pixDestroy(&pix2); 00158 pixDestroy(&pix3); 00159 } 00160 pixDestroy(&pix1); 00161 DisplayPix(&pixa, 100, 500, NULL); 00162 00163 /* Results same for pixRotateAMCorner w/ and w/out + 0.5 */ 00164 pixa = pixaCreate(11); 00165 pix1 = pixExpandReplicate(pixc, 1); 00166 for (i = 0; i < 11; i++) { 00167 angle = 0.10 + 0.05 * (l_float32)i; 00168 pix2 = pixRotateAMCorner(pix1, angle, L_BRING_IN_BLACK); 00169 pix3 = pixExpandReplicate(pix2, 8); 00170 pixSaveTiled(pix3, pixa, 1, (i == 0), 20, 32); 00171 pixDestroy(&pix2); 00172 pixDestroy(&pix3); 00173 } 00174 pixDestroy(&pix1); 00175 DisplayPix(&pixa, 100, 600, NULL); 00176 00177 /* Results better for pixRotateAMColorFast without + 0.5 */ 00178 pixa = pixaCreate(11); 00179 pix1 = pixExpandReplicate(pixc, 1); 00180 for (i = 0; i < 11; i++) { 00181 angle = 0.10 + 0.05 * (l_float32)i; 00182 pix2 = pixRotateAMColorFast(pix1, angle, 0); 00183 pix3 = pixExpandReplicate(pix2, 8); 00184 pixSaveTiled(pix3, pixa, 1, (i == 0), 20, 32); 00185 pixDestroy(&pix2); 00186 pixDestroy(&pix3); 00187 } 00188 pixDestroy(&pix1); 00189 DisplayPix(&pixa, 100, 700, NULL); 00190 00191 /* Results slightly better for pixScaleColorLI() w/out + 0.5 */ 00192 pixa = pixaCreate(11); 00193 pix1 = pixExpandReplicate(pixc, 1); 00194 for (i = 0; i < 11; i++) { 00195 scale = 1.0 + 0.2 * (l_float32)i; 00196 pix2 = pixScaleColorLI(pix1, scale, scale); 00197 pix3 = pixExpandReplicate(pix2, 4); 00198 pixSaveTiled(pix3, pixa, 1, (i == 0), 20, 32); 00199 pixDestroy(&pix2); 00200 pixDestroy(&pix3); 00201 } 00202 pixDestroy(&pix1); 00203 DisplayPix(&pixa, 100, 800, NULL); 00204 00205 /* Results slightly better for pixScaleColorLI() w/out + 0.5 */ 00206 pixa = pixaCreate(11); 00207 pix1 = pixExpandReplicate(pixc, 1); 00208 for (i = 0; i < 11; i++) { 00209 scale = 1.0 + 0.2 * (l_float32)i; 00210 pix2 = pixScaleLI(pix1, scale, scale); 00211 pix3 = pixExpandReplicate(pix2, 4); 00212 pixSaveTiled(pix3, pixa, 1, (i == 0), 20, 32); 00213 pixDestroy(&pix2); 00214 pixDestroy(&pix3); 00215 } 00216 pixDestroy(&pix1); 00217 DisplayPix(&pixa, 100, 940, NULL); 00218 00219 pixDestroy(&pixc); 00220 return 0; 00221 } 00222 00223