Leptonica 1.68
C Image Processing Library

smallpix_reg.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  *  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 
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines