From e117b8a3ba88bee85b42867d1b4d13bc8d3ab29b Mon Sep 17 00:00:00 2001 From: micio Date: Sun, 6 Sep 2009 21:42:37 +0000 Subject: [PATCH] Bazaar:Leptonica - Wrapped a page layout analysis function, with demo git-svn-id: svn://ultimatepp.org/upp/trunk@1557 f0d560ea-af0d-0410-9eb7-867de7ffcac7 --- bazaar/PixRaster/Lept-PageSeg.cpp | 32 +++ bazaar/PixRaster/Leptonica.upp~ | 183 +++++++++++++++ bazaar/PixRaster/PixRaster.h | 5 + bazaar/PixRaster/PixRaster.upp | 1 + bazaar/PixRaster/PixRaster.upp~ | 186 +++++++++++++++ bazaar/PixRaster/src.tpp/Blend$en-us.tpp | 20 ++ bazaar/PixRaster/src.tpp/Morph$en-us.tpp | 12 + bazaar/PixRaster/src.tpp/PageSeg$en-us.tpp | 24 ++ bazaar/PixRaster/src.tpp/PixRaster$en-us.tpp | 18 ++ bazaar/PixRaster/src.tpp/Rotate$en-us.tpp | 6 +- bazaar/PixRaster/src.tpp/Skew$en-us.tpp | 19 +- .../PixRaster/src.tpp/Thresholding$en-us.tpp | 212 +++++++++--------- bazaar/TestLeptonica/LineRemoval.cpp | 5 - bazaar/TestLeptonica/PageLayout.cpp | 45 ++++ bazaar/TestLeptonica/TestLeptonica.h | 1 + bazaar/TestLeptonica/TestLeptonica.lay | 3 +- bazaar/TestLeptonica/TestLeptonica.upp | 1 + bazaar/TestLeptonica/main.cpp | 1 + bazaar/TestLeptonica/pageseg1.tif | Bin 0 -> 133424 bytes bazaar/TestLeptonica/pageseg2.png | Bin 0 -> 255686 bytes bazaar/TestLeptonica/pageseg3.tif | Bin 0 -> 122176 bytes 21 files changed, 653 insertions(+), 121 deletions(-) create mode 100644 bazaar/PixRaster/Lept-PageSeg.cpp create mode 100644 bazaar/PixRaster/Leptonica.upp~ create mode 100644 bazaar/PixRaster/PixRaster.upp~ create mode 100644 bazaar/PixRaster/src.tpp/Blend$en-us.tpp create mode 100644 bazaar/PixRaster/src.tpp/PageSeg$en-us.tpp create mode 100644 bazaar/TestLeptonica/PageLayout.cpp create mode 100644 bazaar/TestLeptonica/pageseg1.tif create mode 100644 bazaar/TestLeptonica/pageseg2.png create mode 100644 bazaar/TestLeptonica/pageseg3.tif diff --git a/bazaar/PixRaster/Lept-PageSeg.cpp b/bazaar/PixRaster/Lept-PageSeg.cpp new file mode 100644 index 000000000..4f5b3174a --- /dev/null +++ b/bazaar/PixRaster/Lept-PageSeg.cpp @@ -0,0 +1,32 @@ +#include "PixRaster.h" + +NAMESPACE_UPP + +// top level page segmenting +bool PixRaster::GetRegionsBinary(int page) +{ + if(IsEmpty()) + return false; + page = getTruePage(page); + + PIX *ht, *tl, *tb; + PIX *pix = pixaGetPix(pixa, page, L_CLONE); + int res = pixGetRegionsBinary(pix, &ht, &tl, &tb, 0); + pixDestroy(&pix); + if(res) + return false; + AddPIX(ht); + AddPIX(tl); + AddPIX(tb); + pixDestroy(&ht); + pixDestroy(&tl); + pixDestroy(&tb); + + // seeks the ht page + SeekPage(-2); + + return true; + +} + +END_UPP_NAMESPACE diff --git a/bazaar/PixRaster/Leptonica.upp~ b/bazaar/PixRaster/Leptonica.upp~ new file mode 100644 index 000000000..9d264e2cc --- /dev/null +++ b/bazaar/PixRaster/Leptonica.upp~ @@ -0,0 +1,183 @@ +description "Leptonica image library\377"; + +noblitz; + +uses + plugin\tif, + plugin\png; + +include + lib; + +file + source readonly separator, + lib/adaptmap.c, + lib/affine.c, + lib/affinecompose.c, + lib/arithlow.c, + lib/arrayaccess.c, + lib/bardecode.c, + lib/baseline.c, + lib/bbuffer.c, + lib/bilinear.c, + lib/binarize.c, + lib/binexpand.c, + lib/binexpandlow.c, + lib/binreduce.c, + lib/binreducelow.c, + lib/blend.c, + lib/bmf.c, + lib/bmpio.c, + lib/bmpiostub.c, + lib/boxbasic.c, + lib/boxfunc1.c, + lib/boxfunc2.c, + lib/boxfunc3.c, + lib/ccbord.c, + lib/ccthin.c, + lib/classapp.c, + lib/colorcontent.c, + lib/colormap.c, + lib/colormorph.c, + lib/colorquant1.c, + lib/colorquant2.c, + lib/colorseg.c, + lib/compare.c, + lib/conncomp.c, + lib/convolve.c, + lib/convolvelow.c, + lib/correlscore.c, + lib/dwacomb.2.c, + lib/dwacomblow.2.c, + lib/edge.c, + lib/endiantest.c, + lib/enhance.c, + lib/fhmtauto.c, + lib/fhmtgen.1.c, + lib/fhmtgenlow.1.c, + lib/flipdetect.c, + lib/fliphmtgen.c, + lib/fmorphauto.c, + lib/fmorphgen.1.c, + lib/fmorphgenlow.1.c, + lib/fpix1.c, + lib/fpix2.c, + lib/gifio.c, + lib/gifiostub.c, + lib/gplot.c, + lib/graphics.c, + lib/graymorph.c, + lib/graymorphlow.c, + lib/grayquant.c, + lib/grayquantlow.c, + lib/heap.c, + lib/jbclass.c, + lib/jpegio.c, + lib/jpegiostub.c, + lib/kernel.c, + lib/list.c, + lib/maze.c, + lib/morphapp.c, + lib/morph.c, + lib/morphdwa.c, + lib/morphseq.c, + lib/numabasic.c, + lib/numafunc1.c, + lib/numafunc2.c, + lib/pageseg.c, + lib/paintcmap.c, + lib/parseprotos.c, + lib/partition.c, + lib/pix1.c, + lib/pix2.c, + lib/pix3.c, + lib/pix4.c, + lib/pixabasic.c, + lib/pixacc.c, + lib/pixafunc1.c, + lib/pixafunc2.c, + lib/pixalloc.c, + lib/pixarith.c, + lib/pixconv.c, + lib/pixtiling.c, + lib/pngio.c, + lib/pngiostub.c, + lib/pnmio.c, + lib/pnmiostub.c, + lib/projective.c, + lib/psio.c, + lib/psiostub.c, + lib/ptra.c, + lib/pts.c, + lib/queue.c, + lib/rank.c, + lib/readbarcode.c, + lib/readfile.c, + lib/rop.c, + lib/ropiplow.c, + lib/roplow.c, + lib/rotateam.c, + lib/rotateamlow.c, + lib/rotate.c, + lib/rotateorth.c, + lib/rotateorthlow.c, + lib/rotateshear.c, + lib/runlength.c, + lib/sarray.c, + lib/scale.c, + lib/scalelow.c, + lib/seedfill.c, + lib/seedfilllow.c, + lib/sel1.c, + lib/sel2.c, + lib/selgen.c, + lib/shear.c, + lib/skew.c, + lib/stack.c, + lib/textops.c, + lib/tiffio.c, + lib/tiffiostub.c, + lib/utils.c, + lib/viewfiles.c, + lib/warper.c, + lib/watershed.c, + lib/writefile.c, + lib/zlibmem.c, + lib/zlibmemstub.c, + header readonly separator, + lib/allheaders.h, + lib/alltypes.h, + lib/arrayaccess.h, + lib/array.h, + lib/bbuffer.h, + lib/bmf.h, + lib/bmp.h, + lib/ccbord.h, + lib/environ.h, + lib/gplot.h, + lib/heap.h, + lib/imageio.h, + lib/jbclass.h, + lib/jmorecfg.h, + lib/jpeglib.h, + lib/leptprotos.h, + lib/list.h, + lib/morph.h, + lib/pix.h, + lib/ptra.h, + lib/queue.h, + lib/readbarcode.h, + lib/stack.h, + lib/watershed.h, + main readonly separator, + PixRaster.h, + Leptonica.h, + PixRasterLoad.cpp, + PixRasterLept.cpp, + PixRaster.cpp, + TiffIo.cpp, + UppLept.cpp, + Lept-Skew.cpp, + Lept-Threshold.cpp, + src.tpp; + diff --git a/bazaar/PixRaster/PixRaster.h b/bazaar/PixRaster/PixRaster.h index bf653f111..adb902683 100644 --- a/bazaar/PixRaster/PixRaster.h +++ b/bazaar/PixRaster/PixRaster.h @@ -270,6 +270,11 @@ class PixRaster : public Raster bool CombineMasked(int destPage, int sourcePage, int maskPage); + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + // DOCUMENT PAGE SEGMENTING FUNCTIONS + + // top level page segmenting + bool GetRegionsBinary(int page = PIXRASTER_CURPAGE) ; }; // END class PixRaster diff --git a/bazaar/PixRaster/PixRaster.upp b/bazaar/PixRaster/PixRaster.upp index 704991710..4a2aae078 100644 --- a/bazaar/PixRaster/PixRaster.upp +++ b/bazaar/PixRaster/PixRaster.upp @@ -181,5 +181,6 @@ file Lept-Morph.cpp, Lept-Arith.cpp, Lept-Blend.cpp, + Lept-PageSeg.cpp, src.tpp; diff --git a/bazaar/PixRaster/PixRaster.upp~ b/bazaar/PixRaster/PixRaster.upp~ new file mode 100644 index 000000000..29eeafc69 --- /dev/null +++ b/bazaar/PixRaster/PixRaster.upp~ @@ -0,0 +1,186 @@ +description "Leptonica image library\377"; + +noblitz; + +uses + plugin\tif, + plugin\png; + +include + lib; + +file + source readonly separator, + lib/adaptmap.c, + lib/affine.c, + lib/affinecompose.c, + lib/arithlow.c, + lib/arrayaccess.c, + lib/bardecode.c, + lib/baseline.c, + lib/bbuffer.c, + lib/bilinear.c, + lib/binarize.c, + lib/binexpand.c, + lib/binexpandlow.c, + lib/binreduce.c, + lib/binreducelow.c, + lib/blend.c, + lib/bmf.c, + lib/bmpio.c, + lib/bmpiostub.c, + lib/boxbasic.c, + lib/boxfunc1.c, + lib/boxfunc2.c, + lib/boxfunc3.c, + lib/ccbord.c, + lib/ccthin.c, + lib/classapp.c, + lib/colorcontent.c, + lib/colormap.c, + lib/colormorph.c, + lib/colorquant1.c, + lib/colorquant2.c, + lib/colorseg.c, + lib/compare.c, + lib/conncomp.c, + lib/convolve.c, + lib/convolvelow.c, + lib/correlscore.c, + lib/dwacomb.2.c, + lib/dwacomblow.2.c, + lib/edge.c, + lib/endiantest.c, + lib/enhance.c, + lib/fhmtauto.c, + lib/fhmtgen.1.c, + lib/fhmtgenlow.1.c, + lib/flipdetect.c, + lib/fliphmtgen.c, + lib/fmorphauto.c, + lib/fmorphgen.1.c, + lib/fmorphgenlow.1.c, + lib/fpix1.c, + lib/fpix2.c, + lib/gifio.c, + lib/gifiostub.c, + lib/gplot.c, + lib/graphics.c, + lib/graymorph.c, + lib/graymorphlow.c, + lib/grayquant.c, + lib/grayquantlow.c, + lib/heap.c, + lib/jbclass.c, + lib/jpegio.c, + lib/jpegiostub.c, + lib/kernel.c, + lib/list.c, + lib/maze.c, + lib/morphapp.c, + lib/morph.c, + lib/morphdwa.c, + lib/morphseq.c, + lib/numabasic.c, + lib/numafunc1.c, + lib/numafunc2.c, + lib/pageseg.c, + lib/paintcmap.c, + lib/parseprotos.c, + lib/partition.c, + lib/pix1.c, + lib/pix2.c, + lib/pix3.c, + lib/pix4.c, + lib/pixabasic.c, + lib/pixacc.c, + lib/pixafunc1.c, + lib/pixafunc2.c, + lib/pixalloc.c, + lib/pixarith.c, + lib/pixconv.c, + lib/pixtiling.c, + lib/pngio.c, + lib/pngiostub.c, + lib/pnmio.c, + lib/pnmiostub.c, + lib/projective.c, + lib/psio.c, + lib/psiostub.c, + lib/ptra.c, + lib/pts.c, + lib/queue.c, + lib/rank.c, + lib/readbarcode.c, + lib/readfile.c, + lib/rop.c, + lib/ropiplow.c, + lib/roplow.c, + lib/rotateam.c, + lib/rotateamlow.c, + lib/rotate.c, + lib/rotateorth.c, + lib/rotateorthlow.c, + lib/rotateshear.c, + lib/runlength.c, + lib/sarray.c, + lib/scale.c, + lib/scalelow.c, + lib/seedfill.c, + lib/seedfilllow.c, + lib/sel1.c, + lib/sel2.c, + lib/selgen.c, + lib/shear.c, + lib/skew.c, + lib/stack.c, + lib/textops.c, + lib/tiffio.c, + lib/tiffiostub.c, + lib/utils.c, + lib/viewfiles.c, + lib/warper.c, + lib/watershed.c, + lib/writefile.c, + lib/zlibmem.c, + lib/zlibmemstub.c, + header readonly separator, + lib/allheaders.h, + lib/alltypes.h, + lib/arrayaccess.h, + lib/array.h, + lib/bbuffer.h, + lib/bmf.h, + lib/bmp.h, + lib/ccbord.h, + lib/environ.h, + lib/gplot.h, + lib/heap.h, + lib/imageio.h, + lib/jbclass.h, + lib/jmorecfg.h, + lib/jpeglib.h, + lib/leptprotos.h, + lib/list.h, + lib/morph.h, + lib/pix.h, + lib/ptra.h, + lib/queue.h, + lib/readbarcode.h, + lib/stack.h, + lib/watershed.h, + main readonly separator, + PixRaster.h, + Leptonica.h, + PixRasterLoad.cpp, + PixRaster.cpp, + TiffIo.cpp, + UppLept.cpp, + Lept-Skew.cpp, + Lept-Threshold.cpp, + Lept-Rotate.cpp, + Lept-Morph.cpp, + Lept-Arith.cpp, + Lept-Blend.cpp, + src.tpp; + diff --git a/bazaar/PixRaster/src.tpp/Blend$en-us.tpp b/bazaar/PixRaster/src.tpp/Blend$en-us.tpp new file mode 100644 index 000000000..22d02e1d3 --- /dev/null +++ b/bazaar/PixRaster/src.tpp/Blend$en-us.tpp @@ -0,0 +1,20 @@ +topic "Combining/blending functions"; +[ $$0,0#00000000000000000000000000000000:Default] +[H6;0 $$1,0#05600065144404261032431302351956:begin] +[i448;a25;kKO9;2 $$2,0#37138531426314131252341829483370:codeitem] +[l288;2 $$3,0#27521748481378242620020725143825:desc] +[0 $$4,0#96390100711032703541132217272105:end] +[{_}%EN-US +[s0;%- &] +[ {{10000F(128)G(128)@1 [s0; [* Combining/blending functions]]}}&] +[s1;%- &] +[s2;:PixRaster`:`:CombineMasked`(int`,int`,int`):%- [@(0.0.255) bool]_[* CombineMasked]([@(0.0.255) i +nt]_[*@3 destPage], [@(0.0.255) int]_[*@3 sourcePage], [@(0.0.255) int]_[*@3 maskPage])&] +[s3; Creates an image from [%-*@3 destPage] with pixels replaced by +[%-*@3 sourcePage]`'s ones if corresponding bits of [%-*@3 maskPage +]are set.&] +[s3; The combined image is appended at the end of PixRaster.&] +[s3; &] +[s3; Returns [%-@(0.0.255) true] on success, [%-@(0.0.255) false] otherwise.&] +[s4; &] +[s0; ] \ No newline at end of file diff --git a/bazaar/PixRaster/src.tpp/Morph$en-us.tpp b/bazaar/PixRaster/src.tpp/Morph$en-us.tpp index 7af8c024c..9b3310572 100644 --- a/bazaar/PixRaster/src.tpp/Morph$en-us.tpp +++ b/bazaar/PixRaster/src.tpp/Morph$en-us.tpp @@ -19,6 +19,9 @@ odd number if not) If both [%-*@3 hsize] and [%-*@3 vsize] are equal to 1, [* ErodeGray] just returns a cloned image.&] [s3; Erosion remove pixels on objects boundaries; the amount of eroded pixels depends on size of [* Sel]s&] +[s3; Eroded image is appended at the end of PixRaster&] +[s3; &] +[s3; Returns [%-@(0.0.255) true] on success, [%-@(0.0.255) false] otherwise.&] [s3; &] [s4; &] [s1;%- &] @@ -33,6 +36,9 @@ odd number if not) If both [%-*@3 hsize] and [%-*@3 vsize] are equal to 1, [* DilateGray] just returns a cloned image.&] [s3; Dilation adds pixels on objects boundaries; the amount of added pixels depends on size of [* Sel]s&] +[s3; Dilated image is appended at the end of PixRaster&] +[s3; &] +[s3; Returns [%-@(0.0.255) true] on success, [%-@(0.0.255) false] otherwise.&] [s3; &] [s4; &] [s1;%- &] @@ -47,6 +53,9 @@ odd number if not) If both [%-*@3 hsize] and [%-*@3 vsize] are equal to 1, [* OpenGray] just returns a cloned image.&] [s3; Opening combines an [* erosion] operation followed by a [* dilation] one; the amount of added/eroded pixels depends on size of [* Sel]s&] +[s3; Opened image is appended at the end of PixRaster&] +[s3; &] +[s3; Returns [%-@(0.0.255) true] on success, [%-@(0.0.255) false] otherwise.&] [s3; &] [s4; &] [s1;%- &] @@ -61,6 +70,9 @@ odd number if not) If both [%-*@3 hsize] and [%-*@3 vsize] are equal to 1, [* CloseGray] just returns a cloned image.&] [s3; Closing combines a [* dilation] operation followed by an [* erosion ]one; the amount of added/eroded pixels depends on size of [* Sel]s&] +[s3; Closed image is appended at the end of PixRaster&] +[s3; &] +[s3; Returns [%-@(0.0.255) true] on success, [%-@(0.0.255) false] otherwise.&] [s3; &] [s4; &] [s0; ] \ No newline at end of file diff --git a/bazaar/PixRaster/src.tpp/PageSeg$en-us.tpp b/bazaar/PixRaster/src.tpp/PageSeg$en-us.tpp new file mode 100644 index 000000000..057d4db81 --- /dev/null +++ b/bazaar/PixRaster/src.tpp/PageSeg$en-us.tpp @@ -0,0 +1,24 @@ +topic ""; +[ $$0,0#00000000000000000000000000000000:Default] +[H6;0 $$1,0#05600065144404261032431302351956:begin] +[i448;a25;kKO9;2 $$2,0#37138531426314131252341829483370:codeitem] +[l288;2 $$3,0#27521748481378242620020725143825:desc] +[0 $$4,0#96390100711032703541132217272105:end] +[{_}%EN-US +[s0;%- &] +[ {{10000F(128)G(128)@1 [s0; [* Page segmentation/layout analysis functions]]}}&] +[s1;%- &] +[s2;:PixRaster`:`:GetRegionsBinary`(int`):%- [@(0.0.255) bool]_[* GetRegionsBinary]([@(0.0.255) i +nt]_[*@3 page]_`=_PIXRASTER`_CURPAGE)&] +[s3; Gets layout masks for image at [%-*@3 page]. Masks are appended +at the end of PixRaster in this sequence :&] +[s3;i150;O0; Halftone mask-|-|1 bpp mask for halftone page parts&] +[s3;i150;O0; Textline mask-|-|1 bpp mask for text lines inside page&] +[s3;i150;O0; Textblock mask-|-|1 bpp mask for text blocks inside page&] +[s3; Active PixRaster page is set to first (Halftone) of the three +resulting masks.&] +[s3; &] +[s3; Returns [%-@(0.0.255) true] on success, [%-@(0.0.255) false] otherwise.&] +[s3; &] +[s4; &] +[s0; ] \ No newline at end of file diff --git a/bazaar/PixRaster/src.tpp/PixRaster$en-us.tpp b/bazaar/PixRaster/src.tpp/PixRaster$en-us.tpp index 07c91ad24..38b83c693 100644 --- a/bazaar/PixRaster/src.tpp/PixRaster$en-us.tpp +++ b/bazaar/PixRaster/src.tpp/PixRaster$en-us.tpp @@ -237,6 +237,24 @@ nt]_[@3 page])&] [s2;%% Returns the size of Raster in pixels for [%-*@3 page].&] [s3;%% &] [s4; &] +[s5;:PixRaster`:`:GetWidth`(`): [@(0.0.255) virtual] [@(0.0.255) int]_GetWidth()&] +[s2;%% Returns the width of Raster in pixels for active page.&] +[s3; &] +[s4; &] +[s5;:PixRaster`:`:GetWidth`(int`): [@(0.0.255) virtual] [@(0.0.255) int]_GetWidth([@(0.0.255) i +nt]_[@3 page])&] +[s2;%% Returns the width of Raster in pixels for [%-*@3 page].&] +[s3;%% &] +[s4; &] +[s5;:PixRaster`:`:GetHeight`(`): [@(0.0.255) virtual] [@(0.0.255) int]_GetHeight()&] +[s2;%% Returns the height of Raster in pixels for active page.&] +[s3; &] +[s4; &] +[s5;:PixRaster`:`:GetHeight`(int`): [@(0.0.255) virtual] [@(0.0.255) int]_GetHeight([@(0.0.255) i +nt]_[@3 page])&] +[s2;%% Returns the height of Raster in pixels for [%-*@3 page].&] +[s3;%% &] +[s4; &] [s5;:PixRaster`:`:GetInfo`(void`): [@(0.0.255) virtual] [_^Raster`:`:Info^ Info]_GetInfo( [@(0.0.255) void])&] [s2;%% Returns the information about Raster`'s active page.&] diff --git a/bazaar/PixRaster/src.tpp/Rotate$en-us.tpp b/bazaar/PixRaster/src.tpp/Rotate$en-us.tpp index 5280b098a..61b21018b 100644 --- a/bazaar/PixRaster/src.tpp/Rotate$en-us.tpp +++ b/bazaar/PixRaster/src.tpp/Rotate$en-us.tpp @@ -17,7 +17,7 @@ in black or white depending on [%-*@3 incolor] parameter.&] [s3; Image must be in 2, 4, 8 or 32 bpp format, either paletted or grayscale. The rotated image is appended to PixRaster and active page is set to it.&] -[s0; &] +[s3; &] [s3; Returns [%-@(0.0.255) true] on success, [%-@(0.0.255) false] otherwise.&] [s4; &] [s1;%- &] @@ -30,7 +30,7 @@ filled with [%-*@3 colorval].&] [s3; Image must be in 2, 4, 8 or 32 bpp format, either paletted or grayscale. The rotated image is appended to PixRaster and active page is set to it.&] -[s0; &] +[s3; &] [s3; Returns [%-@(0.0.255) true] on success, [%-@(0.0.255) false] otherwise.&] [s4; &] [s1;%- &] @@ -43,5 +43,7 @@ filled with [%-*@3 grayval].&] [s3; Image must be in 2, 4, 8 or 32 bpp format, either paletted or grayscale. The rotated image is appended to PixRaster and active page is set to it.&] +[s3; &] +[s3; Returns [%-@(0.0.255) true] on success, [%-@(0.0.255) false] otherwise.&] [s4; &] [s0; ] \ No newline at end of file diff --git a/bazaar/PixRaster/src.tpp/Skew$en-us.tpp b/bazaar/PixRaster/src.tpp/Skew$en-us.tpp index 72295bfeb..a0f131b47 100644 --- a/bazaar/PixRaster/src.tpp/Skew$en-us.tpp +++ b/bazaar/PixRaster/src.tpp/Skew$en-us.tpp @@ -17,7 +17,8 @@ the skew factor.&] [s3; [* WARNINGS ]: it operates [* ONLY ]on [* 1bpp monochromatic] images; if the skew factor is too low or not found, it just returns a clone of source image.&] -[s4; &] +[s3; Deskewed image is appended at the end of PixRaster&] +[s3; &] [s3; Returns [%-@(0.0.255) true] on success, [%-@(0.0.255) false] otherwise.&] [s4; &] [s1;%- &] @@ -31,15 +32,17 @@ It uses [%-*@3 ReductionFactor] value while binary`-searching for the skew factor. If [%-*@3 skewAngle] and [%-*@3 confidenceFactor] pointers are non`-NULL, it sets them to the skew angle and the confidence value found when de`-skewing&] -[s4; &] +[s3; Deskewed image is appended at the end of PixRaster&] +[s3; &] [s3; Returns [%-@(0.0.255) true] on success, [%-@(0.0.255) false] otherwise.&] +[s4; &] [s1;%- &] [s2;:PixRaster`:`:FindSkew`(double`*`,double`*`,int`):%- [@(0.0.255) bool]_[* FindSkew]([@(0.0.255) d ouble]_`*[*@3 pangle], [@(0.0.255) double]_`*[*@3 pconf]_`=_NULL, [@(0.0.255) int]_[*@3 pag e]_`=_PIXRASTER`_CURPAGE)&] [s3; Try to find skew of [%-*@3 page] and returns it`'s value in [%-*@3 pangle] ; confidence factor is returned in [%-*@3 pconf].&] -[s4; &] +[s3; &] [s3; Returns [%-@(0.0.255) true] on success, [%-@(0.0.255) false] otherwise.&] [s4; &] [s1;%- &] @@ -51,7 +54,7 @@ ol]_[* FindSkewSweep]([@(0.0.255) double]_`*[*@3 pangle], [@(0.0.255) int]_[*@3 of [%-*@3 page] and returns it`'s value in [%-*@3 pangle] ; Uses [%-*@3 reduction] factor in binary searching, a semi`-range of [%-*@3 sweeprange] skew angle and steps by [%-*@3 sweepdelta] value.&] -[s4; &] +[s3; &] [s3; Returns [%-@(0.0.255) true] on success, [%-@(0.0.255) false] otherwise.&] [s4; &] [s1;%- &] @@ -68,16 +71,16 @@ in [%-*@3 pconf].[%-*@3 redsweep] is the sweep reduction factor (1, is the half the full range, assumed about 0; in degrees , [%-*@3 sweepdelta] the angle increment of sweep; in degrees and [%-*@3 minbsdelta] the min binary search increment angle; in degrees.&] -[s4; &] +[s3; &] [s3; Returns [%-@(0.0.255) true] on success, [%-@(0.0.255) false] otherwise.&] -[s0; &] +[s3; &] [s3; [* Notes ]:&] -[s0; &] +[s3; &] [s3;i150;O1; This finds the skew angle, doing first a sweep through a set of equal angles, and then doing a binary search until convergence.&] [s3;i150;O1; Caller must check the return value for validity of the result.&] -[s0; &] +[s3; &] [s3;i150;O1; In computing the differential line sum variance score, we sum the result over scanlines, but we always skip:&] [s3;l448;i150;O0; at least one scanline&] diff --git a/bazaar/PixRaster/src.tpp/Thresholding$en-us.tpp b/bazaar/PixRaster/src.tpp/Thresholding$en-us.tpp index 4cb90c2ec..52af30c89 100644 --- a/bazaar/PixRaster/src.tpp/Thresholding$en-us.tpp +++ b/bazaar/PixRaster/src.tpp/Thresholding$en-us.tpp @@ -4,126 +4,128 @@ topic "Image thresholding functions"; [i448;a25;kKO9;2 $$2,0#37138531426314131252341829483370:codeitem] [l288;2 $$3,0#27521748481378242620020725143825:desc] [0 $$4,0#96390100711032703541132217272105:end] -[{_} -[s0; &] -[ {{10000F(128)G(128)@1 [s0;%% [* Image thresholding functions]]}}&] -[s1; &] -[s1; &] -[s2;:PixRaster`:`:DitherToBinary`(int`): [@(0.0.255) bool]_[* DitherToBinary]([@(0.0.255) i +[{_}%EN-US +[s0;%- &] +[ {{10000F(128)G(128)@1 [s0; [* Image thresholding functions]]}}&] +[s1;%- &] +[s1;%- &] +[s2;:PixRaster`:`:DitherToBinary`(int`):%- [@(0.0.255) bool]_[* DitherToBinary]([@(0.0.255) i nt]_[*@3 page]_`=_PIXRASTER`_CURPAGE)&] -[s3;%% [%-*@3 page].&] -[s4;%% &] -[s1; &] -[s2;:PixRaster`:`:DitherToBinarySpec`(int`,int`,int`): [@(0.0.255) bool]_[* DitherToBinar -ySpec]([@(0.0.255) int]_[*@3 lowerclip], [@(0.0.255) int]_[*@3 upperclip], +[s3; [%-*@3 page].&] +[s4; &] +[s1;%- &] +[s2;:PixRaster`:`:DitherToBinarySpec`(int`,int`,int`):%- [@(0.0.255) bool]_[* DitherToBin +arySpec]([@(0.0.255) int]_[*@3 lowerclip], [@(0.0.255) int]_[*@3 upperclip], [@(0.0.255) int]_[*@3 page]_`=_PIXRASTER`_CURPAGE)&] -[s3;%% [%-*@3 lowerclip] [%-*@3 upperclip] [%-*@3 page].&] -[s4;%% &] -[s1; &] -[s2;:PixRaster`:`:ThresholdToBinary`(int`,int`): [@(0.0.255) bool]_[* ThresholdToBinary]( -[@(0.0.255) int]_[*@3 threshold], [@(0.0.255) int]_[*@3 page]_`=_PIXRASTER`_CURPAGE)&] -[s3;%% Creates a new 1bpp black/white image from source`'s grayscale +[s3; [%-*@3 lowerclip] [%-*@3 upperclip] [%-*@3 page].&] +[s4; &] +[s1;%- &] +[s2;:PixRaster`:`:ThresholdToBinary`(int`,int`):%- [@(0.0.255) bool]_[* ThresholdToBinary +]([@(0.0.255) int]_[*@3 threshold], [@(0.0.255) int]_[*@3 page]_`=_PIXRASTER`_CURPAGE)&] +[s3; Creates a new 1bpp black/white image from source`'s grayscale [%-*@3 page] using [%-*@3 threshold] as limiting value. Newly created image is appended at the end of PixRaster, and currently active page is set to it.&] -[s3;%% [* WARNING], it operates [* ONLY ]on grayscale source images.&] -[s4;%% &] -[s3;%% Returns [%-@(0.0.255) true] on success, [%-@(0.0.255) false] otherwise.&] -[s1; &] -[s2;:PixRaster`:`:VarThresholdToBinary`(int`,int`): [@(0.0.255) bool]_[* VarThresholdToBi -nary]([@(0.0.255) int]_[*@3 thresholdPage], [@(0.0.255) int]_[*@3 page]_`=_PIXRASTER`_CUR -PAGE)&] -[s3;%% [%-*@3 thresholdPage] [%-*@3 page].&] -[s4;%% &] -[s1; &] -[s2;:PixRaster`:`:DitherToBinaryLUT`(int`,int`,int`): [@(0.0.255) bool]_[* DitherToBinary -LUT]([@(0.0.255) int]_[*@3 lowerclip], [@(0.0.255) int]_[*@3 upperclip], +[s3; [* WARNING], it operates [* ONLY ]on grayscale source images.&] +[s3; Thresholded image is appended at the end of PixRaster&] +[s3; &] +[s3; Returns [%-@(0.0.255) true] on success, [%-@(0.0.255) false] otherwise.&] +[s4; &] +[s1;%- &] +[s2;:PixRaster`:`:VarThresholdToBinary`(int`,int`):%- [@(0.0.255) bool]_[* VarThresholdTo +Binary]([@(0.0.255) int]_[*@3 thresholdPage], [@(0.0.255) int]_[*@3 page]_`=_PIXRASTER`_C +URPAGE)&] +[s3; [%-*@3 thresholdPage] [%-*@3 page].&] +[s4; &] +[s1;%- &] +[s2;:PixRaster`:`:DitherToBinaryLUT`(int`,int`,int`):%- [@(0.0.255) bool]_[* DitherToBina +ryLUT]([@(0.0.255) int]_[*@3 lowerclip], [@(0.0.255) int]_[*@3 upperclip], [@(0.0.255) int]_[*@3 page]_`=_PIXRASTER`_CURPAGE)&] -[s3;%% [%-*@3 lowerclip] [%-*@3 upperclip] [%-*@3 page].&] -[s4;%% &] -[s1; &] -[s2;:PixRaster`:`:GenerateMaskByValue`(int`,int`): [@(0.0.255) bool]_[* GenerateMaskByVal -ue]([@(0.0.255) int]_[*@3 val], [@(0.0.255) int]_[*@3 page]_`=_PIXRASTER`_CURPAGE)&] -[s3;%% [%-*@3 val] [%-*@3 page].&] -[s4;%% &] -[s1; &] -[s2;:PixRaster`:`:GenerateMaskByBand`(int`,int`,int`,int`): [@(0.0.255) bool]_[* Generate -MaskByBand]([@(0.0.255) int]_[*@3 lower], [@(0.0.255) int]_[*@3 upper], +[s3; [%-*@3 lowerclip] [%-*@3 upperclip] [%-*@3 page].&] +[s4; &] +[s1;%- &] +[s2;:PixRaster`:`:GenerateMaskByValue`(int`,int`):%- [@(0.0.255) bool]_[* GenerateMaskByV +alue]([@(0.0.255) int]_[*@3 val], [@(0.0.255) int]_[*@3 page]_`=_PIXRASTER`_CURPAGE)&] +[s3; [%-*@3 val] [%-*@3 page].&] +[s4; &] +[s1;%- &] +[s2;:PixRaster`:`:GenerateMaskByBand`(int`,int`,int`,int`):%- [@(0.0.255) bool]_[* Genera +teMaskByBand]([@(0.0.255) int]_[*@3 lower], [@(0.0.255) int]_[*@3 upper], [@(0.0.255) int]_[*@3 inband], [@(0.0.255) int]_[*@3 page]_`=_PIXRASTER`_CURPAGE)&] -[s3;%% [%-*@3 lower] [%-*@3 upper] [%-*@3 inband] [%-*@3 page].&] -[s4;%% &] -[s1; &] -[s2;:PixRaster`:`:DitherTo2bpp`(int`,int`): [@(0.0.255) bool]_[* DitherTo2bpp]([@(0.0.255) i +[s3; [%-*@3 lower] [%-*@3 upper] [%-*@3 inband] [%-*@3 page].&] +[s4; &] +[s1;%- &] +[s2;:PixRaster`:`:DitherTo2bpp`(int`,int`):%- [@(0.0.255) bool]_[* DitherTo2bpp]([@(0.0.255) i nt]_[*@3 cmapflag], [@(0.0.255) int]_[*@3 page]_`=_PIXRASTER`_CURPAGE)&] -[s3;%% [%-*@3 cmapflag] [%-*@3 page].&] -[s4;%% &] -[s1; &] -[s2;:PixRaster`:`:DitherTo2bppSpec`(int`,int`,int`,int`): [@(0.0.255) bool]_[* DitherTo2b -ppSpec]([@(0.0.255) int]_[*@3 lowerclip], [@(0.0.255) int]_[*@3 upperclip], +[s3; [%-*@3 cmapflag] [%-*@3 page].&] +[s4; &] +[s1;%- &] +[s2;:PixRaster`:`:DitherTo2bppSpec`(int`,int`,int`,int`):%- [@(0.0.255) bool]_[* DitherTo +2bppSpec]([@(0.0.255) int]_[*@3 lowerclip], [@(0.0.255) int]_[*@3 upperclip], [@(0.0.255) int]_[*@3 cmapflag], [@(0.0.255) int]_[*@3 page]_`=_PIXRASTER`_CURPAGE)&] -[s3;%% [%-*@3 lowerclip] [%-*@3 upperclip] [%-*@3 cmapflag] [%-*@3 page].&] -[s4;%% &] -[s1; &] -[s2;:PixRaster`:`:ThresholdTo2bpp`(int`,int`,int`): [@(0.0.255) bool]_[* ThresholdTo2bpp]( -[@(0.0.255) int]_[*@3 nlevels], [@(0.0.255) int]_[*@3 cmapflag], [@(0.0.255) int]_[*@3 page]_ -`=_PIXRASTER`_CURPAGE)&] -[s3;%% [%-*@3 nlevels] [%-*@3 cmapflag] [%-*@3 page].&] -[s4;%% &] -[s1; &] -[s2;:PixRaster`:`:ThresholdTo4bpp`(int`,int`,int`): [@(0.0.255) bool]_[* ThresholdTo4bpp]( -[@(0.0.255) int]_[*@3 nlevels], [@(0.0.255) int]_[*@3 cmapflag], [@(0.0.255) int]_[*@3 page]_ -`=_PIXRASTER`_CURPAGE)&] -[s3;%% [%-*@3 nlevels] [%-*@3 cmapflag] [%-*@3 page].&] -[s4;%% &] -[s1; &] -[s2;:PixRaster`:`:ThresholdOn8bpp`(int`,int`,int`): [@(0.0.255) bool]_[* ThresholdOn8bpp]( -[@(0.0.255) int]_[*@3 nlevels], [@(0.0.255) int]_[*@3 cmapflag], [@(0.0.255) int]_[*@3 page]_ -`=_PIXRASTER`_CURPAGE)&] -[s3;%% [%-*@3 nlevels] [%-*@3 cmapflag] [%-*@3 page].&] -[s4;%% &] -[s1; &] -[s2;:PixRaster`:`:ThresholdGrayArb`(const char`*`,int`,int`,int`,int`,int`): [@(0.0.255) b +[s3; [%-*@3 lowerclip] [%-*@3 upperclip] [%-*@3 cmapflag] [%-*@3 page].&] +[s4; &] +[s1;%- &] +[s2;:PixRaster`:`:ThresholdTo2bpp`(int`,int`,int`):%- [@(0.0.255) bool]_[* ThresholdTo2bp +p]([@(0.0.255) int]_[*@3 nlevels], [@(0.0.255) int]_[*@3 cmapflag], [@(0.0.255) int]_[*@3 pag +e]_`=_PIXRASTER`_CURPAGE)&] +[s3; [%-*@3 nlevels] [%-*@3 cmapflag] [%-*@3 page].&] +[s4; &] +[s1;%- &] +[s2;:PixRaster`:`:ThresholdTo4bpp`(int`,int`,int`):%- [@(0.0.255) bool]_[* ThresholdTo4bp +p]([@(0.0.255) int]_[*@3 nlevels], [@(0.0.255) int]_[*@3 cmapflag], [@(0.0.255) int]_[*@3 pag +e]_`=_PIXRASTER`_CURPAGE)&] +[s3; [%-*@3 nlevels] [%-*@3 cmapflag] [%-*@3 page].&] +[s4; &] +[s1;%- &] +[s2;:PixRaster`:`:ThresholdOn8bpp`(int`,int`,int`):%- [@(0.0.255) bool]_[* ThresholdOn8bp +p]([@(0.0.255) int]_[*@3 nlevels], [@(0.0.255) int]_[*@3 cmapflag], [@(0.0.255) int]_[*@3 pag +e]_`=_PIXRASTER`_CURPAGE)&] +[s3; [%-*@3 nlevels] [%-*@3 cmapflag] [%-*@3 page].&] +[s4; &] +[s1;%- &] +[s2;:PixRaster`:`:ThresholdGrayArb`(const char`*`,int`,int`,int`,int`,int`):%- [@(0.0.255) b ool]_[* ThresholdGrayArb]([@(0.0.255) const]_[@(0.0.255) char]_`*[*@3 edgevals], [@(0.0.255) int]_[*@3 outdepth], [@(0.0.255) int]_[*@3 use`_average], [@(0.0.255) int]_[*@3 setblack], [@(0.0.255) int]_[*@3 setwhite], [@(0.0.255) int]_[*@3 page]_ `=_PIXRASTER`_CURPAGE)&] -[s3;%% [%-*@3 edgevals] [%-*@3 outdepth] [%-*@3 use`_average] [%-*@3 setblack] +[s3; [%-*@3 edgevals] [%-*@3 outdepth] [%-*@3 use`_average] [%-*@3 setblack] [%-*@3 setwhite] [%-*@3 page].&] -[s4;%% &] -[s1; &] -[s2;:PixRaster`:`:MakeGrayQuantIndexTable`(int`): [_^Buffer^ Buffer]<[@(0.0.255) int]>_[* M -akeGrayQuantIndexTable]([@(0.0.255) int]_[*@3 nlevels])&] -[s3;%% [%-*@3 nlevels].&] -[s4;%% &] -[s1; &] -[s2;:PixRaster`:`:MakeGrayQuantTargetTable`(int`,int`): [_^Buffer^ Buffer]<[@(0.0.255) in -t]>_[* MakeGrayQuantTargetTable]([@(0.0.255) int]_[*@3 nlevels], [@(0.0.255) int]_[*@3 dept -h])&] -[s3;%% [%-*@3 nlevels] [%-*@3 depth].&] -[s4;%% &] -[s1; &] -[s2;:PixRaster`:`:GenerateMaskByBand32`(unsigned`,int`,int`,int`): [@(0.0.255) bool]_[* G -enerateMaskByBand32]([@(0.0.255) unsigned]_[*@3 refval], [@(0.0.255) int]_[*@3 delm], +[s4; &] +[s1;%- &] +[s2;:PixRaster`:`:MakeGrayQuantIndexTable`(int`):%- [_^Buffer^ Buffer]<[@(0.0.255) int]>_ +[* MakeGrayQuantIndexTable]([@(0.0.255) int]_[*@3 nlevels])&] +[s3; [%-*@3 nlevels].&] +[s4; &] +[s1;%- &] +[s2;:PixRaster`:`:MakeGrayQuantTargetTable`(int`,int`):%- [_^Buffer^ Buffer]<[@(0.0.255) i +nt]>_[* MakeGrayQuantTargetTable]([@(0.0.255) int]_[*@3 nlevels], [@(0.0.255) int]_[*@3 dep +th])&] +[s3; [%-*@3 nlevels] [%-*@3 depth].&] +[s4; &] +[s1;%- &] +[s2;:PixRaster`:`:GenerateMaskByBand32`(unsigned`,int`,int`,int`):%- [@(0.0.255) bool]_ +[* GenerateMaskByBand32]([@(0.0.255) unsigned]_[*@3 refval], [@(0.0.255) int]_[*@3 delm], [@(0.0.255) int]_[*@3 delp], [@(0.0.255) int]_[*@3 page]_`=_PIXRASTER`_CURPAGE)&] -[s3;%% [%-*@3 refval] [%-*@3 delm] [%-*@3 delp] [%-*@3 page].&] -[s4;%% &] -[s1; &] -[s2;:PixRaster`:`:GenerateMaskByDiscr32`(unsigned`,unsigned`,int`,int`): [@(0.0.255) bo -ol]_[* GenerateMaskByDiscr32]([@(0.0.255) unsigned]_[*@3 refval1], +[s3; [%-*@3 refval] [%-*@3 delm] [%-*@3 delp] [%-*@3 page].&] +[s4; &] +[s1;%- &] +[s2;:PixRaster`:`:GenerateMaskByDiscr32`(unsigned`,unsigned`,int`,int`):%- [@(0.0.255) b +ool]_[* GenerateMaskByDiscr32]([@(0.0.255) unsigned]_[*@3 refval1], [@(0.0.255) unsigned]_[*@3 refval2], [@(0.0.255) int]_[*@3 distflag], [@(0.0.255) int]_[*@3 page]_`=_PIXRASTER`_CURPAGE)&] -[s3;%% [%-*@3 refval1] [%-*@3 refval2] [%-*@3 distflag] [%-*@3 page].&] -[s4;%% &] -[s1; &] -[s2;:PixRaster`:`:GrayQuantFromHisto`(int`,double`,int`,int`): [@(0.0.255) bool]_[* GrayQ -uantFromHisto]([@(0.0.255) int]_[*@3 mPage], [@(0.0.255) double]_[*@3 minfract], +[s3; [%-*@3 refval1] [%-*@3 refval2] [%-*@3 distflag] [%-*@3 page].&] +[s4; &] +[s1;%- &] +[s2;:PixRaster`:`:GrayQuantFromHisto`(int`,double`,int`,int`):%- [@(0.0.255) bool]_[* Gra +yQuantFromHisto]([@(0.0.255) int]_[*@3 mPage], [@(0.0.255) double]_[*@3 minfract], [@(0.0.255) int]_[*@3 maxsize], [@(0.0.255) int]_[*@3 page]_`=_PIXRASTER`_CURPAGE)&] -[s3;%% [%-*@3 mPage] [%-*@3 minfract] [%-*@3 maxsize] [%-*@3 page].&] -[s4;%% &] -[s1; &] -[s2;:PixRaster`:`:ThresholdToValue`(int`,int`,int`): [@(0.0.255) bool]_[* ThresholdToValu -e]([@(0.0.255) int]_[*@3 threshval], [@(0.0.255) int]_[*@3 setval], [@(0.0.255) int]_[*@3 pag -e]_`=_PIXRASTER`_CURPAGE)&] -[s3;%% [%-*@3 threshval] [%-*@3 setval] [%-*@3 page].&] -[s4;%% &] -[s0; ] \ No newline at end of file +[s3; [%-*@3 mPage] [%-*@3 minfract] [%-*@3 maxsize] [%-*@3 page].&] +[s4; &] +[s1;%- &] +[s2;:PixRaster`:`:ThresholdToValue`(int`,int`,int`):%- [@(0.0.255) bool]_[* ThresholdToVa +lue]([@(0.0.255) int]_[*@3 threshval], [@(0.0.255) int]_[*@3 setval], +[@(0.0.255) int]_[*@3 page]_`=_PIXRASTER`_CURPAGE)&] +[s3; [%-*@3 threshval] [%-*@3 setval] [%-*@3 page].&] +[s4; &] +[s0;%- ] \ No newline at end of file diff --git a/bazaar/TestLeptonica/LineRemoval.cpp b/bazaar/TestLeptonica/LineRemoval.cpp index 63a962cf9..cf45d1cb1 100644 --- a/bazaar/TestLeptonica/LineRemoval.cpp +++ b/bazaar/TestLeptonica/LineRemoval.cpp @@ -1,7 +1,5 @@ #include "TestLeptonica.h" -#include - static void RemoveLines(PixRaster &pixRaster) { // gets source image page @@ -88,14 +86,11 @@ void TestLeptonica::onLineRemoval() s.Close(); return; } -// OnestreamRaster = StreamRaster::OpenAny(s); // Loads pixraster from source raster CHECKR(pixRaster.Load(s), "Error loading image"); s.Close(); - int ctc = pixRaster.GetPaletteCount(); - // apply line removal algothithm RemoveLines(pixRaster); diff --git a/bazaar/TestLeptonica/PageLayout.cpp b/bazaar/TestLeptonica/PageLayout.cpp new file mode 100644 index 000000000..fc2895a4f --- /dev/null +++ b/bazaar/TestLeptonica/PageLayout.cpp @@ -0,0 +1,45 @@ +#include "TestLeptonica.h" + +static void PageLayout(PixRaster &pixRaster) +{ + CHECKR(pixRaster.GetRegionsBinary(), "Error getting page layout"); +} + +void TestLeptonica::onPageLayout() +{ + String fileName; + FileSelector fs; + PIX *pix; + + if(!PromptYesNo( + "[= [* Page layout analysis demo]&&" + "Please select a scanned image with mixed text and graphics&" + "you can take one from TestLeptonica folder if you like&&" + "[* CONTINUE ??]]" + )) + return; + + fs.ReadOnlyOption(); + if(fs.ExecuteOpen("Please select image for page layout analysis:")) + { + FileIn s; + if(!s.Open(~fs)) + { + PromptOK("Error opening image"); + s.Close(); + return; + } + + // Loads pixraster from source raster + CHECKR(pixRaster.Load(s), "Error loading image"); + s.Close(); + + // apply line removal algothithm + PageLayout(pixRaster); + + // refresh the PixRasterCtrl control with the new image contents + pixRasterCtrl.Reload(); + pixRasterCtrl.SetPage(0); + + } +} diff --git a/bazaar/TestLeptonica/TestLeptonica.h b/bazaar/TestLeptonica/TestLeptonica.h index 5110da033..f50846858 100644 --- a/bazaar/TestLeptonica/TestLeptonica.h +++ b/bazaar/TestLeptonica/TestLeptonica.h @@ -27,6 +27,7 @@ class TestLeptonica : public WithTestLeptonicaLayout // button handlers void onLineRemoval(void); + void onPageLayout(void); void onQuit(void); // PIX raster diff --git a/bazaar/TestLeptonica/TestLeptonica.lay b/bazaar/TestLeptonica/TestLeptonica.lay index 7fb008709..0811f02b9 100644 --- a/bazaar/TestLeptonica/TestLeptonica.lay +++ b/bazaar/TestLeptonica/TestLeptonica.lay @@ -1,6 +1,7 @@ LAYOUT(TestLeptonicaLayout, 640, 400) - ITEM(Button, LineRemovalButton, SetLabel(t_("Line removal test")).LeftPosZ(8, 92).TopPosZ(8, 15)) + ITEM(Button, PageLayoutButton, SetLabel(t_("Page layout test")).LeftPosZ(8, 92).TopPosZ(32, 15)) ITEM(Button, QuitButton, SetLabel(t_("\aQuit")).LeftPosZ(8, 92).BottomPosZ(9, 15)) ITEM(PixRasterCtrl, pixRasterCtrl, SetFrame(InsetFrame()).HSizePosZ(108, 8).VSizePosZ(8, 8)) + ITEM(Button, LineRemovalButton, SetLabel(t_("Line removal test")).LeftPosZ(8, 92).TopPosZ(8, 15)) END_LAYOUT diff --git a/bazaar/TestLeptonica/TestLeptonica.upp b/bazaar/TestLeptonica/TestLeptonica.upp index fb0fe8b2d..16b296c75 100644 --- a/bazaar/TestLeptonica/TestLeptonica.upp +++ b/bazaar/TestLeptonica/TestLeptonica.upp @@ -7,6 +7,7 @@ file TestLeptonica.lay, TestLeptonica.h, LineRemoval.cpp, + PageLayout.cpp, main.cpp; mainconfig diff --git a/bazaar/TestLeptonica/main.cpp b/bazaar/TestLeptonica/main.cpp index aed12d75d..201eed3f2 100644 --- a/bazaar/TestLeptonica/main.cpp +++ b/bazaar/TestLeptonica/main.cpp @@ -15,6 +15,7 @@ TestLeptonica::TestLeptonica() // connects button handlers LineRemovalButton <<= THISBACK(onLineRemoval); + PageLayoutButton <<= THISBACK(onPageLayout); QuitButton <<= THISBACK(onQuit); } diff --git a/bazaar/TestLeptonica/pageseg1.tif b/bazaar/TestLeptonica/pageseg1.tif new file mode 100644 index 0000000000000000000000000000000000000000..2168f3d4d60c99a29f7caa0017f55d54647c395c GIT binary patch literal 133424 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

+c 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
QrcK!ZE7Bngky}IClv5;j= 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 z