third-party/leptonica/prog/croptest.c
/*====================================================================*
- Copyright (C) 2001 Leptonica. All rights reserved.
-
- Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions
- are met:
- 1. Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
- 2. Redistributions in binary form must reproduce the above
- copyright notice, this list of conditions and the following
- disclaimer in the documentation and/or other materials
- provided with the distribution.
-
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ANY
- CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*====================================================================*/
/*
* croptest.c
*/
#ifndef _WIN32
#include <unistd.h>
#else
#include <windows.h> /* for Sleep() */
#endif /* _WIN32 */
#include "allheaders.h"
static const l_int32 mindif = 60;
l_int32 GetLeftCut(NUMA *narl, NUMA *nart, NUMA *nait,
l_int32 h, l_int32 *pleft);
l_int32 GetRightCut(NUMA *narl, NUMA *nart, NUMA *nait,
l_int32 h, l_int32 *pright);
const char *fnames[] = {"lyra.005.jpg", "lyra.036.jpg"};
int main(int argc,
char **argv)
{
#if 1
l_int32 i, pageno, w, h, left, right;
NUMA *nar, *naro, *narl, *nart, *nai, *naio, *nait;
PIX *pixs, *pixr, *pixg, *pixgi, *pixd, *pix1, *pix2;
PIXA *pixa1, *pixa2;
static char mainName[] = "croptest";
if (argc != 1)
return ERROR_INT("syntax: croptest", mainName, 1);
pixa1 = pixaCreate(2);
for (i = 0; i < 2; i++) {
pageno = extractNumberFromFilename(fnames[i], 5, 0);
fprintf(stderr, "Page %d\n", pageno);
pixs = pixRead(fnames[i]);
pixr = pixRotate90(pixs, (pageno % 2) ? 1 : -1);
pixg = pixConvertTo8(pixr, 0);
pixGetDimensions(pixg, &w, &h, NULL);
/* Get info on vertical reversal profile */
nar = pixReversalProfile(pixg, 0.8, L_VERTICAL_LINE,
0, h - 1, mindif, 1, 1);
naro = numaOpen(nar, 11);
gplotSimple1(naro, GPLOT_PNG, "/tmp/root1", "Reversals Opened");
narl = numaLowPassIntervals(naro, 0.1, 0.0);
fprintf(stderr, "narl:");
numaWriteStream(stderr, narl);
nart = numaThresholdEdges(naro, 0.1, 0.5, 0.0);
fprintf(stderr, "nart:");
numaWriteStream(stderr, nart);
numaDestroy(&nar);
numaDestroy(&naro);
/* Get info on vertical intensity profile */
pixgi = pixInvert(NULL, pixg);
nai = pixAverageIntensityProfile(pixgi, 0.8, L_VERTICAL_LINE,
0, h - 1, 1, 1);
naio = numaOpen(nai, 11);
gplotSimple1(naio, GPLOT_PNG, "/tmp/root2", "Intensities Opened");
nait = numaThresholdEdges(naio, 0.4, 0.6, 0.0);
fprintf(stderr, "nait:");
numaWriteStream(stderr, nait);
numaDestroy(&nai);
numaDestroy(&naio);
/* Analyze profiles for left/right edges */
GetLeftCut(narl, nart, nait, w, &left);
GetRightCut(narl, nart, nait, w, &right);
fprintf(stderr, "left = %d, right = %d\n", left, right);
/* Output visuals */
#ifndef _WIN32
sleep(1);
#else
Sleep(1000);
#endif /* _WIN32 */
pixa2 = pixaCreate(3);
pixSaveTiled(pixr, pixa2, 1.0, 1, 25, 32);
pix1 = pixRead("/tmp/root1.png");
pix2 = pixRead("/tmp/root2.png");
pixSaveTiled(pix1, pixa2, 1.0, 1, 25, 32);
pixSaveTiled(pix2, pixa2, 1.0, 0, 25, 32);
pixd = pixaDisplay(pixa2, 0, 0);
pixaDestroy(&pixa2);
pixaAddPix(pixa1, pixd, L_INSERT);
pixDisplay(pixd, 100, 100);
pixDestroy(&pixs);
pixDestroy(&pixr);
pixDestroy(&pixg);
pixDestroy(&pixgi);
pixDestroy(&pix1);
pixDestroy(&pix2);
numaDestroy(&narl);
numaDestroy(&nart);
numaDestroy(&nait);
}
pixaConvertToPdf(pixa1, 75, 1.0, L_JPEG_ENCODE, 0, "Profiles",
"/tmp/croptest.pdf");
pixaDestroy(&pixa1);
return 0;
}
#endif
#if 0
/* pixs = pixRead("lucasta-cropped.jpg"); */
Pix *pixs = pixRead("1555-7.jpg");
/* pixs = pixRead("feyn.tif"); */
int w, h, d, minrev;
pixGetDimensions(pixs, &w, &h, &d);
if (d == 1)
minrev = 1;
else
minrev = 40;
Numa *na = pixReversalProfile(pixs, 0.98, L_HORIZONTAL_LINE,
0, h - 1, minrev, 3, 3);
gplotSimple1(na, GPLOT_X11, "/tmp/junkroot1", "Reversals");
numaDestroy(&na);
na = pixAverageIntensityProfile(pixs, 0.98, L_HORIZONTAL_LINE,
0, h - 1, 1, 1);
gplotSimple1(na, GPLOT_X11, "/tmp/junkroot2", "Intensities");
numaDestroy(&na);
pixDestroy(&pixs);
}
#endif
/*
* Use these variable abbreviations:
*
* pap1: distance from left edge to the page
* txt1: distance from left edge to the text
* Identify pap1 by (a) 1st downward transition in intensity (nait).
* (b) start of 1st lowpass interval (nail)
* Identify txt1 by (a) end of 1st lowpass interval (nail)
* (b) first upward transition in reversals (nart)
*
* pap2: distance from right edge to beginning of last upward transition,
* plus some extra for safety.
* txt1: distance from right edge to the text
* Identify pap2 by 1st downward transition in intensity.
* Identify txt2 by (a) beginning of 1st lowpass interval from bottom
* (b) last downward transition in reversals from bottom
*/
l_int32
GetLeftCut(NUMA *narl,
NUMA *nart,
NUMA *nait,
l_int32 w,
l_int32 *pleft) {
l_int32 nrl, nrt, nit, start, end, sign, pap1, txt1, del;
nrl = numaGetCount(narl);
nrt = numaGetCount(nart);
nit = numaGetCount(nait);
/* Check for small max number of reversals or no edge */
numaGetSpanValues(narl, 0, NULL, &end);
if (end < 20 || nrl <= 1) {
*pleft = 0;
return 0;
}
/* Where is text and page, scanning from the left? */
pap1 = 0;
txt1 = 0;
if (nrt >= 4) { /* beginning of first upward transition */
numaGetEdgeValues(nart, 0, &start, NULL, NULL);
txt1 = start;
}
if (nit >= 4) { /* end of first downward trans in (inverse) intensity */
numaGetEdgeValues(nait, 0, NULL, &end, &sign);
if (end < txt1 && sign == -1)
pap1 = end;
else
pap1 = 0.5 * txt1;
}
del = txt1 - pap1;
if (del > 20) {
txt1 -= L_MIN(20, 0.5 * del);
pap1 += L_MIN(20, 0.5 * del);
}
fprintf(stderr, "txt1 = %d, pap1 = %d\n", txt1, pap1);
*pleft = pap1;
return 0;
}
l_int32
GetRightCut(NUMA *narl,
NUMA *nart,
NUMA *nait,
l_int32 w,
l_int32 *pright) {
l_int32 nrt, ntrans, start, end, sign, txt2, pap2, found, trans;
nrt = numaGetCount(nart);
/* Check for small max number of reversals or no edge */
/* Where is text and page, scanning from the right? */
ntrans = nrt / 3;
if (ntrans > 1) {
found = FALSE;
for (trans = ntrans - 1; trans > 0; --trans) {
numaGetEdgeValues(nart, trans, &start, &end, &sign);
if (sign == -1) { /* end of textblock */
txt2 = end;
found = TRUE;
}
}
if (!found) {
txt2 = w - 1; /* take the whole thing! */
pap2 = w - 1;
} else { /* found textblock; now find right side of page */
found = FALSE;
for (trans = ntrans - 1; trans > 0; --trans) {
numaGetEdgeValues(nart, trans, &start, &end, &sign);
if (sign == 1 && start > txt2) {
pap2 = start; /* start of textblock on other page */
found = TRUE;
}
}
if (!found) { /* no text from other page */
pap2 = w - 1; /* refine later */
}
}
} else {
txt2 = w - 1;
pap2 = w - 1;
}
fprintf(stderr, "txt2 = %d, pap2 = %d\n", txt2, pap2);
*pright = pap2;
return 0;
}