diff options
Diffstat (limited to 'leptonica/prog')
701 files changed, 80567 insertions, 0 deletions
diff --git a/leptonica/prog/1555.003.jpg b/leptonica/prog/1555.003.jpg Binary files differnew file mode 100644 index 00000000..e35fa013 --- /dev/null +++ b/leptonica/prog/1555.003.jpg diff --git a/leptonica/prog/1555.007.jpg b/leptonica/prog/1555.007.jpg Binary files differnew file mode 100644 index 00000000..c00c18b8 --- /dev/null +++ b/leptonica/prog/1555.007.jpg diff --git a/leptonica/prog/19-colors.png b/leptonica/prog/19-colors.png Binary files differnew file mode 100644 index 00000000..5555d569 --- /dev/null +++ b/leptonica/prog/19-colors.png diff --git a/leptonica/prog/CMakeLists.txt b/leptonica/prog/CMakeLists.txt new file mode 100644 index 00000000..eb533816 --- /dev/null +++ b/leptonica/prog/CMakeLists.txt @@ -0,0 +1,322 @@ +######################################## +# FUNCTION add_prog_target +######################################## +function(add_prog_target target) + set (${target}_src "${ARGN}") + if (WIN32) + set_source_files_properties (${${target}_src} PROPERTIES LANGUAGE CXX) + endif() + add_executable (${target} ${${target}_src}) + if (BUILD_SHARED_LIBS) + target_compile_definitions (${target} PRIVATE -DLIBLEPT_IMPORTS) + endif() + target_link_libraries (${target} leptonica) + set_target_properties (${target} PROPERTIES FOLDER prog) +endfunction(add_prog_target) +######################################## + +add_prog_target(adaptmap_reg adaptmap_reg.c) +add_prog_target(adaptnorm_reg adaptnorm_reg.c) +add_prog_target(affine_reg affine_reg.c) +add_prog_target(alltests_reg alltests_reg.c) +add_prog_target(alphaops_reg alphaops_reg.c) +add_prog_target(alphaxform_reg alphaxform_reg.c) +add_prog_target(baseline_reg baseline_reg.c) +add_prog_target(bilateral1_reg bilateral1_reg.c) +add_prog_target(bilateral2_reg bilateral2_reg.c) +add_prog_target(bilinear_reg bilinear_reg.c) +add_prog_target(binarize_reg binarize_reg.c) +add_prog_target(binmorph1_reg binmorph1_reg.c) +add_prog_target(binmorph2_reg binmorph2_reg.c) +add_prog_target(binmorph3_reg binmorph3_reg.c) +add_prog_target(binmorph4_reg binmorph4_reg.c) +add_prog_target(binmorph5_reg binmorph5_reg.c) +add_prog_target(binmorph6_reg binmorph6_reg.c) +add_prog_target(blackwhite_reg blackwhite_reg.c) +add_prog_target(blend1_reg blend1_reg.c) +add_prog_target(blend2_reg blend2_reg.c) +add_prog_target(blend3_reg blend3_reg.c) +add_prog_target(blend4_reg blend4_reg.c) +add_prog_target(blend5_reg blend5_reg.c) +add_prog_target(boxa1_reg boxa1_reg.c) +add_prog_target(boxa2_reg boxa2_reg.c) +add_prog_target(boxa3_reg boxa3_reg.c) +add_prog_target(boxa4_reg boxa4_reg.c) +add_prog_target(bytea_reg bytea_reg.c) +add_prog_target(ccbord_reg ccbord_reg.c) +add_prog_target(ccthin1_reg ccthin1_reg.c) +add_prog_target(ccthin2_reg ccthin2_reg.c) +add_prog_target(checkerboard_reg checkerboard_reg.c) +add_prog_target(circle_reg circle_reg.c) +add_prog_target(cmapquant_reg cmapquant_reg.c) +add_prog_target(colorcontent_reg colorcontent_reg.c) +add_prog_target(colorfill_reg colorfill_reg.c) +add_prog_target(coloring_reg coloring_reg.c) +add_prog_target(colorize_reg colorize_reg.c) +add_prog_target(colormask_reg colormask_reg.c) +add_prog_target(colormorph_reg colormorph_reg.c) +add_prog_target(colorquant_reg colorquant_reg.c) +add_prog_target(colorseg_reg colorseg_reg.c) +add_prog_target(colorspace_reg colorspace_reg.c) +add_prog_target(compare_reg compare_reg.c) +add_prog_target(compfilter_reg compfilter_reg.c) +add_prog_target(conncomp_reg conncomp_reg.c) +add_prog_target(conversion_reg conversion_reg.c) +add_prog_target(convolve_reg convolve_reg.c) +add_prog_target(crop_reg crop_reg.c) +add_prog_target(dewarp_reg dewarp_reg.c) +add_prog_target(distance_reg distance_reg.c) +add_prog_target(dither_reg dither_reg.c) +add_prog_target(dna_reg dna_reg.c) +add_prog_target(dwamorph1_reg dwamorph1_reg.c dwalinear.3.c dwalinearlow.3.c) +add_prog_target(dwamorph2_reg dwamorph2_reg.c dwalinear.3.c dwalinearlow.3.c) +add_prog_target(edge_reg edge_reg.c) +add_prog_target(encoding_reg encoding_reg.c) +add_prog_target(enhance_reg enhance_reg.c) +add_prog_target(equal_reg equal_reg.c) +add_prog_target(expand_reg expand_reg.c) +add_prog_target(extrema_reg extrema_reg.c) +add_prog_target(falsecolor_reg falsecolor_reg.c) +add_prog_target(fhmtauto_reg fhmtauto_reg.c) +add_prog_target(files_reg files_reg.c) +add_prog_target(findcorners_reg findcorners_reg.c) +add_prog_target(findpattern_reg findpattern_reg.c) +add_prog_target(flipdetect_reg flipdetect_reg.c) +add_prog_target(fmorphauto_reg fmorphauto_reg.c) +add_prog_target(fpix1_reg fpix1_reg.c) +add_prog_target(fpix2_reg fpix2_reg.c) +add_prog_target(genfonts_reg genfonts_reg.c) +add_prog_target(gifio_reg gifio_reg.c) +add_prog_target(grayfill_reg grayfill_reg.c) +add_prog_target(graymorph1_reg graymorph1_reg.c) +add_prog_target(graymorph2_reg graymorph2_reg.c) +add_prog_target(grayquant_reg grayquant_reg.c) +add_prog_target(hardlight_reg hardlight_reg.c) +add_prog_target(hash_reg hash_reg.c) +add_prog_target(heap_reg heap_reg.c) +add_prog_target(insert_reg insert_reg.c) +add_prog_target(ioformats_reg ioformats_reg.c) +add_prog_target(iomisc_reg iomisc_reg.c) +add_prog_target(italic_reg italic_reg.c) +add_prog_target(jbclass_reg jbclass_reg.c) +add_prog_target(jp2kio_reg jp2kio_reg.c) +add_prog_target(jpegio_reg jpegio_reg.c) +add_prog_target(kernel_reg kernel_reg.c) +add_prog_target(label_reg label_reg.c) +add_prog_target(lineremoval_reg lineremoval_reg.c) +add_prog_target(locminmax_reg locminmax_reg.c) +add_prog_target(logicops_reg logicops_reg.c) +add_prog_target(lowaccess_reg lowaccess_reg.c) +add_prog_target(lowsat_reg lowsat_reg.c) +add_prog_target(maze_reg maze_reg.c) +add_prog_target(mtiff_reg mtiff_reg.c) +add_prog_target(multitype_reg multitype_reg.c) +add_prog_target(nearline_reg nearline_reg.c) +add_prog_target(newspaper_reg newspaper_reg.c) +add_prog_target(numa1_reg numa1_reg.c) +add_prog_target(numa2_reg numa2_reg.c) +add_prog_target(numa3_reg numa3_reg.c) +add_prog_target(overlap_reg overlap_reg.c) +add_prog_target(pageseg_reg pageseg_reg.c) +add_prog_target(paintmask_reg paintmask_reg.c) +add_prog_target(paint_reg paint_reg.c) +add_prog_target(pdfio1_reg pdfio1_reg.c) +add_prog_target(pdfio2_reg pdfio2_reg.c) +add_prog_target(pdfseg_reg pdfseg_reg.c) +add_prog_target(pixa1_reg pixa1_reg.c) +add_prog_target(pixa2_reg pixa2_reg.c) +add_prog_target(pixadisp_reg pixadisp_reg.c) +add_prog_target(pixalloc_reg pixalloc_reg.c) +add_prog_target(pixcomp_reg pixcomp_reg.c) +add_prog_target(pixmem_reg pixmem_reg.c) +add_prog_target(pixserial_reg pixserial_reg.c) +add_prog_target(pixtile_reg pixtile_reg.c) +add_prog_target(pngio_reg pngio_reg.c) +add_prog_target(pnmio_reg pnmio_reg.c) +add_prog_target(projection_reg projection_reg.c) +add_prog_target(projective_reg projective_reg.c) +add_prog_target(psioseg_reg psioseg_reg.c) +add_prog_target(psio_reg psio_reg.c) +add_prog_target(pta_reg pta_reg.c) +add_prog_target(ptra1_reg ptra1_reg.c) +add_prog_target(ptra2_reg ptra2_reg.c) +add_prog_target(quadtree_reg quadtree_reg.c) +add_prog_target(rankbin_reg rankbin_reg.c) +add_prog_target(rankhisto_reg rankhisto_reg.c) +add_prog_target(rank_reg rank_reg.c) +add_prog_target(rasteropip_reg rasteropip_reg.c) +add_prog_target(rasterop_reg rasterop_reg.c) +add_prog_target(rectangle_reg rectangle_reg.c) +add_prog_target(rotate1_reg rotate1_reg.c) +add_prog_target(rotate2_reg rotate2_reg.c) +add_prog_target(scale_reg scale_reg.c) +add_prog_target(selio_reg selio_reg.c) +add_prog_target(shear1_reg shear1_reg.c) +add_prog_target(shear2_reg shear2_reg.c) +add_prog_target(skew_reg skew_reg.c) +add_prog_target(smallpix_reg smallpix_reg.c) +add_prog_target(smoothedge_reg smoothedge_reg.c) +add_prog_target(speckle_reg speckle_reg.c) +add_prog_target(splitcomp_reg splitcomp_reg.c) +add_prog_target(string_reg string_reg.c) +add_prog_target(subpixel_reg subpixel_reg.c) +add_prog_target(texturefill_reg texturefill_reg.c) +add_prog_target(threshnorm_reg threshnorm_reg.c) +add_prog_target(translate_reg translate_reg.c) +add_prog_target(warper_reg warper_reg.c) +add_prog_target(watershed_reg watershed_reg.c) +add_prog_target(webpio_reg webpio_reg.c) +add_prog_target(webpanimio_reg webpanimio_reg.c) +add_prog_target(wordboxes_reg wordboxes_reg.c) +add_prog_target(writetext_reg writetext_reg.c) +add_prog_target(xformbox_reg xformbox_reg.c) +add_prog_target(adaptmap_dark adaptmap_dark.c) +add_prog_target(arabic_lines arabic_lines.c) +add_prog_target(arithtest arithtest.c) +add_prog_target(autogentest1 autogentest1.c) +add_prog_target(autogentest2 autogentest2.c autogen.137.c) +add_prog_target(barcodetest barcodetest.c) +add_prog_target(binarize_set binarize_set.c) +add_prog_target(binarizefiles binarizefiles.c) +add_prog_target(bincompare bincompare.c) +add_prog_target(blendcmaptest blendcmaptest.c) +add_prog_target(buffertest buffertest.c) +add_prog_target(ccbordtest ccbordtest.c) +add_prog_target(cctest1 cctest1.c) +add_prog_target(cleanpdf cleanpdf.c) +add_prog_target(colorsegtest colorsegtest.c) +add_prog_target(comparepages comparepages.c) +add_prog_target(comparepixa comparepixa.c) +add_prog_target(comparetest comparetest.c) +add_prog_target(concatpdf concatpdf.c) +add_prog_target(contrasttest contrasttest.c) +add_prog_target(convertfilestopdf convertfilestopdf.c) +add_prog_target(convertfilestops convertfilestops.c) +add_prog_target(convertformat convertformat.c) +add_prog_target(convertsegfilestopdf convertsegfilestopdf.c) +add_prog_target(convertsegfilestops convertsegfilestops.c) +add_prog_target(converttogray converttogray.c) +add_prog_target(converttopdf converttopdf.c) +add_prog_target(converttops converttops.c) +add_prog_target(cornertest cornertest.c) +add_prog_target(corrupttest corrupttest.c) +add_prog_target(croptext croptext.c) +add_prog_target(deskew_it deskew_it.c) +add_prog_target(dewarprules dewarprules.c) +add_prog_target(dewarptest1 dewarptest1.c) +add_prog_target(dewarptest2 dewarptest2.c) +add_prog_target(dewarptest3 dewarptest3.c) +add_prog_target(dewarptest4 dewarptest4.c) +add_prog_target(dewarptest5 dewarptest5.c) +add_prog_target(digitprep1 digitprep1.c) +add_prog_target(displayboxa displayboxa.c) +add_prog_target(displayboxes_on_pixa displayboxes_on_pixa.c) +add_prog_target(displaypix displaypix.c) +add_prog_target(displaypixa displaypixa.c) +add_prog_target(dwalineargen dwalineargen.c) +add_prog_target(fcombautogen fcombautogen.c) +add_prog_target(fhmtautogen fhmtautogen.c) +add_prog_target(fileinfo fileinfo.c) +add_prog_target(findbinding findbinding.c) +add_prog_target(find_colorregions find_colorregions.c) +add_prog_target(findpattern1 findpattern1.c) +add_prog_target(findpattern2 findpattern2.c) +add_prog_target(findpattern3 findpattern3.c) +add_prog_target(fmorphautogen fmorphautogen.c) +add_prog_target(fpixcontours fpixcontours.c) +add_prog_target(gammatest gammatest.c) +add_prog_target(graphicstest graphicstest.c) +add_prog_target(graymorphtest graymorphtest.c) +add_prog_target(histotest histotest.c) +add_prog_target(histoduptest histoduptest.c) +add_prog_target(htmlviewer htmlviewer.c) +add_prog_target(imagetops imagetops.c) +add_prog_target(jbcorrelation jbcorrelation.c) +add_prog_target(jbrankhaus jbrankhaus.c) +add_prog_target(jbwords jbwords.c) +add_prog_target(lightcolortest lightcolortest.c) +add_prog_target(listtest listtest.c) +add_prog_target(livre_adapt livre_adapt.c) +add_prog_target(livre_hmt livre_hmt.c) +add_prog_target(livre_makefigs livre_makefigs.c) +add_prog_target(livre_orient livre_orient.c) +add_prog_target(livre_pageseg livre_pageseg.c) +add_prog_target(livre_seedgen livre_seedgen.c) +add_prog_target(livre_tophat livre_tophat.c) +add_prog_target(maketile maketile.c) +add_prog_target(maptest maptest.c) +add_prog_target(messagetest messagetest.c) +add_prog_target(misctest1 misctest1.c) +add_prog_target(modifyhuesat modifyhuesat.c) +add_prog_target(morphseq_reg morphseq_reg.c) +add_prog_target(morphtest1 morphtest1.c) +add_prog_target(numaranktest numaranktest.c) +add_prog_target(otsutest1 otsutest1.c) +add_prog_target(otsutest2 otsutest2.c) +add_prog_target(pagesegtest1 pagesegtest1.c) +add_prog_target(pagesegtest2 pagesegtest2.c) +add_prog_target(partifytest partifytest.c) +add_prog_target(partitiontest partitiontest.c) +add_prog_target(percolatetest percolatetest.c) +add_prog_target(pixaatest pixaatest.c) +add_prog_target(pixafileinfo pixafileinfo.c) +add_prog_target(plottest plottest.c) +add_prog_target(printimage printimage.c) +add_prog_target(printsplitimage printsplitimage.c) +add_prog_target(printtiff printtiff.c) +add_prog_target(rasteroptest rasteroptest.c) +add_prog_target(rbtreetest rbtreetest.c) +add_prog_target(recog_bootnum1 recog_bootnum1.c) +add_prog_target(recog_bootnum2 recog_bootnum2.c) +add_prog_target(recog_bootnum3 recog_bootnum3.c) +add_prog_target(recogsort recogsort.c) +add_prog_target(recogtest1 recogtest1.c) +add_prog_target(recogtest2 recogtest2.c) +add_prog_target(recogtest3 recogtest3.c) +add_prog_target(recogtest4 recogtest4.c) +add_prog_target(recogtest5 recogtest5.c) +add_prog_target(recogtest6 recogtest6.c) +add_prog_target(recogtest7 recogtest7.c) +add_prog_target(reducetest reducetest.c) +add_prog_target(removecmap removecmap.c) +add_prog_target(renderfonts renderfonts.c) +add_prog_target(replacebytes replacebytes.c) +add_prog_target(rotatefastalt rotatefastalt.c) +add_prog_target(rotate_it rotate_it.c) +add_prog_target(rotateorthtest1 rotateorthtest1.c) +add_prog_target(rotateorth_reg rotateorth_reg.c) +add_prog_target(rotatetest1 rotatetest1.c) +add_prog_target(runlengthtest runlengthtest.c) +add_prog_target(scaleandtile scaleandtile.c) +add_prog_target(scale_it scale_it.c) +add_prog_target(scaletest1 scaletest1.c) +add_prog_target(scaletest2 scaletest2.c) +add_prog_target(seedfilltest seedfilltest.c) +add_prog_target(seedspread_reg seedspread_reg.c) +add_prog_target(settest settest.c) +add_prog_target(sharptest sharptest.c) +add_prog_target(sheartest sheartest.c) +add_prog_target(showedges showedges.c) +add_prog_target(skewtest skewtest.c) +add_prog_target(sorttest sorttest.c) +add_prog_target(splitimage2pdf splitimage2pdf.c) +add_prog_target(sudokutest sudokutest.c) +add_prog_target(textorient textorient.c) +add_prog_target(tiffpdftest tiffpdftest.c) +add_prog_target(trctest trctest.c) +add_prog_target(underlinetest underlinetest.c) +add_prog_target(warpertest warpertest.c) +add_prog_target(wordsinorder wordsinorder.c) +add_prog_target(writemtiff writemtiff.c) +add_prog_target(xtractprotos xtractprotos.c) +add_prog_target(yuvtest yuvtest.c) + +set (INSTALL_PROGS + convertfilestopdf convertfilestops + convertformat convertsegfilestopdf convertsegfilestops + converttopdf converttops fileinfo xtractprotos +) + +foreach(make_install ${INSTALL_PROGS}) + install(TARGETS ${make_install} RUNTIME DESTINATION bin LIBRARY DESTINATION lib ARCHIVE DESTINATION lib) +endforeach() diff --git a/leptonica/prog/Leptonica.jpg b/leptonica/prog/Leptonica.jpg Binary files differnew file mode 100644 index 00000000..676f46f1 --- /dev/null +++ b/leptonica/prog/Leptonica.jpg diff --git a/leptonica/prog/Makefile.am b/leptonica/prog/Makefile.am new file mode 100644 index 00000000..ecdf3d2f --- /dev/null +++ b/leptonica/prog/Makefile.am @@ -0,0 +1,138 @@ +AUTOMAKE_OPTIONS = parallel-tests +AM_CPPFLAGS = -I$(top_srcdir)/src -I$(top_builddir)/src +LDADD = $(top_builddir)/src/liblept.la $(LIBM) + +INSTALL_PROGS = convertfilestopdf convertfilestops \ + convertformat convertsegfilestopdf convertsegfilestops \ + converttopdf converttops fileinfo imagetops xtractprotos + +AUTO_REG_PROGS = adaptmap_reg adaptnorm_reg affine_reg alphaops_reg \ + alphaxform_reg baseline_reg bilateral2_reg \ + bilinear_reg binarize_reg \ + binmorph1_reg binmorph3_reg binmorph6_reg blackwhite_reg \ + blend1_reg blend2_reg blend3_reg blend4_reg blend5_reg \ + boxa1_reg boxa2_reg boxa3_reg boxa4_reg bytea_reg \ + ccbord_reg ccthin1_reg ccthin2_reg \ + checkerboard_reg circle_reg cmapquant_reg \ + colorcontent_reg colorfill_reg \ + coloring_reg colorize_reg \ + colormask_reg colormorph_reg colorquant_reg \ + colorseg_reg colorspace_reg compare_reg \ + compfilter_reg conncomp_reg conversion_reg \ + convolve_reg crop_reg dewarp_reg distance_reg \ + dither_reg dna_reg dwamorph1_reg edge_reg encoding_reg \ + enhance_reg equal_reg expand_reg extrema_reg \ + falsecolor_reg fhmtauto_reg \ + findcorners_reg findpattern_reg flipdetect_reg \ + fpix1_reg fpix2_reg genfonts_reg \ + grayfill_reg graymorph1_reg graymorph2_reg \ + grayquant_reg hardlight_reg hash_reg heap_reg \ + insert_reg ioformats_reg iomisc_reg italic_reg \ + jbclass_reg jpegio_reg \ + kernel_reg label_reg lineremoval_reg \ + locminmax_reg logicops_reg lowaccess_reg lowsat_reg \ + maze_reg mtiff_reg multitype_reg \ + nearline_reg newspaper_reg numa1_reg numa2_reg numa3_reg \ + overlap_reg pageseg_reg paint_reg paintmask_reg \ + pdfio1_reg pdfio2_reg pdfseg_reg \ + pixa1_reg pixa2_reg pixadisp_reg pixcomp_reg \ + pixmem_reg pixserial_reg pngio_reg pnmio_reg \ + projection_reg projective_reg \ + psio_reg psioseg_reg pta_reg \ + ptra1_reg ptra2_reg \ + quadtree_reg rankbin_reg rankhisto_reg \ + rank_reg rasteropip_reg rasterop_reg rectangle_reg \ + rotate1_reg rotate2_reg rotateorth_reg \ + scale_reg seedspread_reg selio_reg \ + shear1_reg shear2_reg skew_reg \ + smallpix_reg speckle_reg splitcomp_reg \ + string_reg subpixel_reg \ + texturefill_reg threshnorm_reg \ + translate_reg warper_reg \ + watershed_reg wordboxes_reg \ + writetext_reg xformbox_reg + +if HAVE_LIBGIF +AUTO_REG_PROGS += gifio_reg +endif + +if HAVE_LIBWEBP +AUTO_REG_PROGS += webpio_reg +endif + +if HAVE_LIBWEBP_ANIM +AUTO_REG_PROGS += webpanimio_reg +endif + +if HAVE_LIBJP2K +AUTO_REG_PROGS += jp2kio_reg +endif + +MANUAL_REG_PROGS = alltests_reg bilateral1_reg \ + binmorph2_reg binmorph4_reg binmorph5_reg \ + dwamorph2_reg \ + files_reg fmorphauto_reg \ + morphseq_reg pixalloc_reg pixtile_reg \ + smoothedge_reg + +OTHER_PROGS = adaptmap_dark \ + arabic_lines arithtest \ + autogentest1 autogentest2 barcodetest \ + binarizefiles binarize_set bincompare \ + blendcmaptest buffertest \ + ccbordtest cctest1 cleanpdf \ + colorsegtest comparepages comparepixa \ + comparetest concatpdf \ + contrasttest converttogray \ + cornertest corrupttest croptext deskew_it \ + dewarprules dewarptest1 dewarptest2 \ + dewarptest3 dewarptest4 dewarptest5 \ + digitprep1 displayboxa displayboxes_on_pixa \ + displaypix displaypixa dwalineargen \ + fcombautogen fhmtautogen findbinding find_colorregions \ + findpattern1 findpattern2 findpattern3 \ + fmorphautogen fpixcontours \ + gammatest graphicstest graymorphtest \ + histotest histoduptest htmlviewer \ + jbcorrelation jbrankhaus jbwords \ + listtest lightcolortest livre_adapt livre_hmt \ + livre_makefigs livre_orient \ + livre_pageseg livre_seedgen livre_tophat \ + maketile maptest messagetest misctest1 \ + modifyhuesat morphtest1 \ + numaranktest otsutest1 otsutest2 \ + pagesegtest1 pagesegtest2 \ + partifytest partitiontest percolatetest \ + pixaatest pixafileinfo plottest \ + printimage printsplitimage printtiff \ + rasteroptest rbtreetest \ + recog_bootnum1 recog_bootnum2 recog_bootnum3 \ + recogsort recogtest1 recogtest2 recogtest3 \ + recogtest4 recogtest5 recogtest6 recogtest7 \ + reducetest removecmap \ + renderfonts replacebytes \ + rotatefastalt rotate_it \ + rotateorthtest1 rotatetest1 \ + runlengthtest scaleandtile \ + scale_it scaletest1 scaletest2 \ + seedfilltest settest sharptest \ + sheartest showedges skewtest \ + sorttest splitimage2pdf sudokutest \ + textorient tiffpdftest trctest \ + underlinetest warpertest wordsinorder \ + writemtiff yuvtest + +if ENABLE_PROGRAMS +bin_PROGRAMS = $(INSTALL_PROGS) +noinst_PROGRAMS = $(AUTO_REG_PROGS) $(MANUAL_REG_PROGS) $(OTHER_PROGS) +endif + +check_PROGRAMS = $(AUTO_REG_PROGS) +TESTS = $(AUTO_REG_PROGS) +TESTS_ENVIRONMENT = $(srcdir)/reg_wrapper.sh +EXTRA_DIST = reg_wrapper.sh + +dwamorph1_reg_SOURCES = dwamorph1_reg.c dwalinear.3.c dwalinearlow.3.c +dwamorph2_reg_SOURCES = dwamorph2_reg.c dwalinear.3.c dwalinearlow.3.c + +autogentest2_SOURCES = autogentest2.c autogen.137.c diff --git a/leptonica/prog/adaptmap_dark.c b/leptonica/prog/adaptmap_dark.c new file mode 100644 index 00000000..d8c22133 --- /dev/null +++ b/leptonica/prog/adaptmap_dark.c @@ -0,0 +1,198 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * adaptmap_dark.c + * + * Demonstrates the effect of the fg threshold on adaptive mapping + * and cleaning for images with dark and variable background. + * + * The example pages are text and image. For both, because the + * background is both dark and variable, using a lower threshold + * gives much better results. + * + * For text, cleaning the background to white after adaptively + * remapping to make the background uniform is preferable. + * The final cleaning step uses pixGammaTRC() where the white value + * (here, 180) is set below the remapped gray value (here, 200). + * + * For the image, however, it is best to stop after remapping + * the background. Going further and moving pixels near the + * background color to white removes the details in the lighter + * regions of the image. In practice, parts of a scanned page + * that are image (as opposed to text) don't necessarily have + * background pixels that should be white. These regions can be + * protected by masks from operations, such as pixGammaTRC(), + * where the white value is less than 255. + * + * This also tests some code useful for rendering: + * * NUp display from pixa to pixa + * * Interleaving of both pixa and pixacomp + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "string.h" +#include "allheaders.h" + +void GenCleans(const char *fname, l_int32 *pindex, l_int32 thresh, L_BMF *bmf); + +l_int32 main(int argc, + char **argv) +{ +l_int32 index; +L_BMF *bmf; +PIXA *pixa1, *pixa2, *pixa3, *pixa4; +PIXAC *pixac1, *pixac2, *pixac3; + + PROCNAME("adaptmap_dark"); + + setLeptDebugOK(1); + bmf = bmfCreate(NULL, 10); + index = 0; + lept_mkdir("lept/adapt"); + + /* Using a variety of different thresholds */ + GenCleans("cavalerie.29.jpg", &index, 80, bmf); + GenCleans("cavalerie.29.jpg", &index, 60, bmf); + GenCleans("cavalerie.29.jpg", &index, 40, bmf); + GenCleans("cavalerie.11.jpg", &index, 80, bmf); + GenCleans("cavalerie.11.jpg", &index, 60, bmf); + GenCleans("cavalerie.11.jpg", &index, 40, bmf); + + /* Read the images and convert to a 4-up pixa */ + pixa1 = convertToNUpPixa("/tmp/lept/adapt", "adapt_", 2, 2, 500, + 6, 2, 0); + + /* Convert to pdf */ + L_INFO("Writing to /tmp/lept/adapt/cleaning.pdf\n", procName); + pixaConvertToPdf(pixa1, 100, 1.0, L_JPEG_ENCODE, + 75, "Adaptive cleaning", + "/tmp/lept/adapt/cleaning.pdf"); + pixaDestroy(&pixa1); + + /* Test the pixac interleaving. Make two copies, + * and interleave them: + * (1) convert NUp 2 x 1 + * (2) convert twice to pixac + * (3) interleave the two copies + * (4) convert back to pixa + * (5) convert NUp 1 x 2 (result now is 2 x 2) + * (6) output as pdf */ + pixa1 = convertToNUpPixa("/tmp/lept/adapt", "adapt_", 2, 1, 500, + 6, 2, 0); + startTimer(); + pixac1 = pixacompCreateFromPixa(pixa1, IFF_DEFAULT, L_CLONE); + pixac2 = pixacompCreateFromPixa(pixa1, IFF_DEFAULT, L_CLONE); + pixac3 = pixacompInterleave(pixac1, pixac2); + pixa2 = pixaCreateFromPixacomp(pixac3, L_CLONE); + pixa3 = pixaConvertToNUpPixa(pixa2, NULL, 1, 2, 1000, 6, 2, 0); + lept_stderr("Time with pixac interleaving = %7.3f sec\n", stopTimer()); + L_INFO("Writing to /tmp/lept/adapt/cleaning2.pdf\n", procName); + pixaConvertToPdf(pixa3, 100, 1.0, L_JPEG_ENCODE, + 75, "Adaptive cleaning", "/tmp/lept/adapt/cleaning2.pdf"); + pixaDestroy(&pixa1); + pixaDestroy(&pixa2); + pixaDestroy(&pixa3); + pixacompDestroy(&pixac1); + pixacompDestroy(&pixac2); + pixacompDestroy(&pixac3); + + /* Test the pixa interleaving. Make two copies, + * and interleave them: + * (1) convert NUp 2 x 1 + * (2) copy and interleave + * (3) convert NUp 1 x 2 (result now is 2 x 2) + * (4) output as pdf */ + pixa1 = convertToNUpPixa("/tmp/lept/adapt", "adapt_", 2, 1, 500, + 6, 2, 0); + startTimer(); + pixa2 = pixaCopy(pixa1, L_COPY_CLONE); + pixa3 = pixaInterleave(pixa1, pixa2, L_CLONE); + pixa4 = pixaConvertToNUpPixa(pixa3, NULL, 1, 2, 1000, 6, 2, 0); + lept_stderr("Time with pixa interleaving = %7.3f sec\n", stopTimer()); + L_INFO("Writing to /tmp/lept/adapt/cleaning3.pdf\n", procName); + pixaConvertToPdf(pixa4, 100, 1.0, L_JPEG_ENCODE, + 75, "Adaptive cleaning", "/tmp/lept/adapt/cleaning3.pdf"); + pixaDestroy(&pixa1); + pixaDestroy(&pixa2); + pixaDestroy(&pixa3); + pixaDestroy(&pixa4); + bmfDestroy(&bmf); + return 0; +} + +void +GenCleans(const char *fname, + l_int32 *pindex, + l_int32 thresh, + L_BMF *bmf) +{ +l_int32 index, blackval, whiteval; +char buf[256]; +PIX *pix1, *pix2, *pix3, *pix4, *pix5; + + blackval = 70; + whiteval = 180; + index = *pindex; + pix1 = pixRead(fname); + snprintf(buf, sizeof(buf), "/tmp/lept/adapt/adapt_%03d.jpg", index++); + pixWrite(buf, pix1, IFF_JFIF_JPEG); + + pix2 = pixBackgroundNorm(pix1, NULL, NULL, 10, 15, thresh, 25, 200, 2, 1); + snprintf(buf, sizeof(buf), "Norm color: fg thresh = %d", thresh); + lept_stderr("%s\n", buf); + pix3 = pixAddTextlines(pix2, bmf, buf, 0x00ff0000, L_ADD_BELOW); + snprintf(buf, sizeof(buf), "/tmp/lept/adapt/adapt_%03d.jpg", index++); + pixWrite(buf, pix3, IFF_JFIF_JPEG); + pixDestroy(&pix3); + pix3 = pixGammaTRC(NULL, pix2, 1.0, blackval, whiteval); + snprintf(buf, sizeof(buf), "Clean color: fg thresh = %d", thresh); + pix4 = pixAddSingleTextblock(pix3, bmf, buf, 0x00ff0000, L_ADD_BELOW, NULL); + snprintf(buf, sizeof(buf), "/tmp/lept/adapt/adapt_%03d.jpg", index++); + pixWrite(buf, pix4, IFF_JFIF_JPEG); + pixDestroy(&pix2); + pixDestroy(&pix3); + pixDestroy(&pix4); + + pix2 = pixConvertRGBToGray(pix1, 0.33, 0.34, 0.33); + pix3 = pixBackgroundNorm(pix2, NULL, NULL, 10, 15, thresh, 25, 200, 2, 1); + pix4 = pixGammaTRC(NULL, pix3, 1.0, blackval, whiteval); + snprintf(buf, sizeof(buf), "Clean gray: fg thresh = %d", thresh); + pix5 = pixAddSingleTextblock(pix4, bmf, buf, 0x00ff0000, L_ADD_BELOW, NULL); + snprintf(buf, sizeof(buf), "/tmp/lept/adapt/adapt_%03d.jpg", index++); + pixWrite(buf, pix5, IFF_JFIF_JPEG); + pixDestroy(&pix2); + pixDestroy(&pix3); + pixDestroy(&pix4); + pixDestroy(&pix5); + + pixDestroy(&pix1); + *pindex = index; + return; +} diff --git a/leptonica/prog/adaptmap_reg.c b/leptonica/prog/adaptmap_reg.c new file mode 100644 index 00000000..ea8f18de --- /dev/null +++ b/leptonica/prog/adaptmap_reg.c @@ -0,0 +1,208 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * adaptmap_reg.c + * + * Regression test demonstrating adaptive mappings in both gray and color + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + + /* Location of image region in wet-day.jpg */ +static const l_int32 XS = 151; +static const l_int32 YS = 225; +static const l_int32 WS = 913; +static const l_int32 HS = 1285; + +static const l_int32 SIZE_X = 10; +static const l_int32 SIZE_Y = 30; +static const l_int32 BINTHRESH = 50; +static const l_int32 MINCOUNT = 30; + +static const l_int32 BGVAL = 200; +static const l_int32 SMOOTH_X = 2; +static const l_int32 SMOOTH_Y = 1; + +int main(int argc, + char **argv) +{ +l_int32 w, h; +PIX *pixs, *pixg, *pixim, *pixgm, *pixmi, *pix1, *pix2; +PIX *pixmr, *pixmg, *pixmb, *pixmri, *pixmgi, *pixmbi; +PIXA *pixa; +L_REGPARAMS *rp; + + if (regTestSetup(argc, argv, &rp)) + return 1; + + lept_mkdir("lept/adapt"); // REMOVE? + + pixs = pixRead("wet-day.jpg"); + pixa = pixaCreate(0); + pixg = pixConvertRGBToGray(pixs, 0.33, 0.34, 0.33); + pixaAddPix(pixa, pixs, L_INSERT); + pixaAddPix(pixa, pixg, L_INSERT); + pixGetDimensions(pixs, &w, &h, NULL); + + /* Process in grayscale */ + startTimer(); + pixim = pixCreate(w, h, 1); + pixRasterop(pixim, XS, YS, WS, HS, PIX_SET, NULL, 0, 0); + pixGetBackgroundGrayMap(pixg, pixim, SIZE_X, SIZE_Y, + BINTHRESH, MINCOUNT, &pixgm); + lept_stderr("Time for gray adaptmap gen: %7.3f\n", stopTimer()); + regTestWritePixAndCheck(rp, pixgm, IFF_PNG); /* 0 */ + pixaAddPix(pixa, pixgm, L_INSERT); + + startTimer(); + pixmi = pixGetInvBackgroundMap(pixgm, BGVAL, SMOOTH_X, SMOOTH_Y); + lept_stderr("Time for gray inv map generation: %7.3f\n", stopTimer()); + regTestWritePixAndCheck(rp, pixmi, IFF_PNG); /* 1 */ + pixaAddPix(pixa, pixmi, L_INSERT); + + startTimer(); + pix1 = pixApplyInvBackgroundGrayMap(pixg, pixmi, SIZE_X, SIZE_Y); + lept_stderr("Time to apply gray inv map: %7.3f\n", stopTimer()); + regTestWritePixAndCheck(rp, pix1, IFF_JFIF_JPEG); /* 2 */ + pixaAddPix(pixa, pix1, L_INSERT); + + pix2 = pixGammaTRCMasked(NULL, pix1, pixim, 1.0, 0, 190); + pixInvert(pixim, pixim); + pixGammaTRCMasked(pix2, pix2, pixim, 1.0, 60, 190); + regTestWritePixAndCheck(rp, pix2, IFF_JFIF_JPEG); /* 3 */ + pixaAddPix(pixa, pix2, L_INSERT); + pixDestroy(&pixim); + + /* Process in color */ + startTimer(); + pixim = pixCreate(w, h, 1); + pixRasterop(pixim, XS, YS, WS, HS, PIX_SET, NULL, 0, 0); + pixGetBackgroundRGBMap(pixs, pixim, NULL, SIZE_X, SIZE_Y, + BINTHRESH, MINCOUNT, + &pixmr, &pixmg, &pixmb); + lept_stderr("Time for color adaptmap gen: %7.3f\n", stopTimer()); + regTestWritePixAndCheck(rp, pixmr, IFF_PNG); /* 4 */ + regTestWritePixAndCheck(rp, pixmg, IFF_PNG); /* 5 */ + regTestWritePixAndCheck(rp, pixmb, IFF_PNG); /* 6 */ + pixaAddPix(pixa, pixmr, L_INSERT); + pixaAddPix(pixa, pixmg, L_INSERT); + pixaAddPix(pixa, pixmb, L_INSERT); + + startTimer(); + pixmri = pixGetInvBackgroundMap(pixmr, BGVAL, SMOOTH_X, SMOOTH_Y); + pixmgi = pixGetInvBackgroundMap(pixmg, BGVAL, SMOOTH_X, SMOOTH_Y); + pixmbi = pixGetInvBackgroundMap(pixmb, BGVAL, SMOOTH_X, SMOOTH_Y); + lept_stderr("Time for color inv map generation: %7.3f\n", stopTimer()); + regTestWritePixAndCheck(rp, pixmri, IFF_PNG); /* 7 */ + regTestWritePixAndCheck(rp, pixmgi, IFF_PNG); /* 8 */ + regTestWritePixAndCheck(rp, pixmbi, IFF_PNG); /* 9 */ + pixaAddPix(pixa, pixmri, L_INSERT); + pixaAddPix(pixa, pixmgi, L_INSERT); + pixaAddPix(pixa, pixmbi, L_INSERT); + + startTimer(); + pix1 = pixApplyInvBackgroundRGBMap(pixs, pixmri, pixmgi, pixmbi, + SIZE_X, SIZE_Y); + lept_stderr("Time to apply color inv maps: %7.3f\n", stopTimer()); + regTestWritePixAndCheck(rp, pix1, IFF_JFIF_JPEG); /* 10 */ + pixaAddPix(pixa, pix1, L_INSERT); + + pix2 = pixGammaTRCMasked(NULL, pix1, pixim, 1.0, 0, 190); + pixInvert(pixim, pixim); + pixGammaTRCMasked(pix2, pix2, pixim, 1.0, 60, 190); + regTestWritePixAndCheck(rp, pix2, IFF_JFIF_JPEG); /* 11 */ + pixaAddPix(pixa, pix2, L_INSERT); + pixDestroy(&pixim); + + /* Process at higher level in color */ + startTimer(); + pixim = pixCreate(w, h, 1); + pixRasterop(pixim, XS, YS, WS, HS, PIX_SET, NULL, 0, 0); + pix1 = pixBackgroundNorm(pixs, pixim, NULL, 5, 10, BINTHRESH, 20, + BGVAL, SMOOTH_X, SMOOTH_Y); + lept_stderr("Time for bg normalization: %7.3f\n", stopTimer()); + regTestWritePixAndCheck(rp, pix1, IFF_JFIF_JPEG); /* 12 */ + pixaAddPix(pixa, pix1, L_INSERT); + + pix2 = pixGammaTRCMasked(NULL, pix1, pixim, 1.0, 0, 190); + pixInvert(pixim, pixim); + pixGammaTRCMasked(pix2, pix2, pixim, 1.0, 60, 190); + regTestWritePixAndCheck(rp, pix2, IFF_JFIF_JPEG); /* 13 */ + pixaAddPix(pixa, pix2, L_INSERT); + pixDestroy(&pixim); + + /* Display results */ + pix1 = pixaDisplayTiledAndScaled(pixa, 32, 400, 4, 0, 20, 2); + pixWrite("/tmp/lept/adapt/results.jpg", pix1, IFF_JFIF_JPEG); + pixDisplayWithTitle(pix1, 50, 0, NULL, rp->display); + pixDestroy(&pix1); + pixaDestroy(&pixa); + + /* Check pixFillMapHoles() */ + pixa = pixaCreate(3); + pix1 = pixRead("weasel8.png"); /* use this as the map */ + pixGammaTRC(pix1, pix1, 1.0, 0, 270); /* darken white pixels */ + pixaAddPix(pixa, pix1, L_COPY); + pixGetDimensions(pix1, &w, &h, NULL); + pixRasterop(pix1, 0, 0, 5, h, PIX_SET, NULL, 0, 0); /* add white holes */ + pixRasterop(pix1, 20, 0, 2, h, PIX_SET, NULL, 0, 0); + pixRasterop(pix1, 40, 0, 3, h, PIX_SET, NULL, 0, 0); + pixRasterop(pix1, 0, 0, w, 3, PIX_SET, NULL, 0, 0); + pixRasterop(pix1, 0, 15, w, 3, PIX_SET, NULL, 0, 0); + pixRasterop(pix1, 0, 35, w, 2, PIX_SET, NULL, 0, 0); + pixaAddPix(pixa, pix1, L_COPY); + pixFillMapHoles(pix1, w, h, L_FILL_WHITE); + pixaAddPix(pixa, pix1, L_INSERT); + pix2 = pixaDisplayTiledInColumns(pixa, 3, 1.0, 20, 1); + regTestWritePixAndCheck(rp, pix2, IFF_PNG); /* 14 */ + pixDisplayWithTitle(pix2, 50, 850, NULL, rp->display); + pixaDestroy(&pixa); + pixDestroy(&pix2); + + /* An even simpler check of pixFillMapHoles() */ + pixa = pixaCreate(2); + pix1 = pixCreate(3, 3, 8); + pixSetPixel(pix1, 1, 0, 128); + pix2 = pixExpandReplicate(pix1, 25); + pixaAddPix(pixa, pix2, L_INSERT); + pixFillMapHoles(pix1, 3, 3, L_FILL_BLACK); + pix2 = pixExpandReplicate(pix1, 25); + pixaAddPix(pixa, pix2, L_INSERT); + pixDestroy(&pix1); + pix1 = pixaDisplayTiledInColumns(pixa, 2, 1.0, 20, 0); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 15 */ + pixDisplayWithTitle(pix1, 50, 1000, NULL, rp->display); + pixaDestroy(&pixa); + pixDestroy(&pix1); + + return regTestCleanup(rp); +} + diff --git a/leptonica/prog/adaptnorm_reg.c b/leptonica/prog/adaptnorm_reg.c new file mode 100644 index 00000000..842330d3 --- /dev/null +++ b/leptonica/prog/adaptnorm_reg.c @@ -0,0 +1,154 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * adaptnorm_reg.c + * + * Image normalization for two extreme cases: + * * variable and low contrast + * * good contrast but fast varying background + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + +int main(int argc, + char **argv) +{ +l_int32 w, h; +l_float32 mps; +PIX *pixs, *pixmin, *pix1, *pix2, *pix3, *pix4, *pix5; +PIX *pix6, *pix7, *pix8, *pix9, *pix10, *pix11; +PIXA *pixa1; +L_REGPARAMS *rp; + + if (regTestSetup(argc, argv, &rp)) + return 1; + + /* ---------------------------------------------------------- * + * Normalize by adaptively expanding the dynamic range * + * ---------------------------------------------------------- */ + pixa1 = pixaCreate(0); + pixs = pixRead("lighttext.jpg"); + pixGetDimensions(pixs, &w, &h, NULL); + regTestWritePixAndCheck(rp, pixs, IFF_JFIF_JPEG); /* 0 */ + pixaAddPix(pixa1, pixs, L_INSERT); + startTimer(); + pix1 = pixContrastNorm(NULL, pixs, 10, 10, 40, 2, 2); + mps = 0.000001 * w * h / stopTimer(); + lept_stderr("Time: Contrast norm: %7.3f Mpix/sec\n", mps); + pixaAddPix(pixa1, pix1, L_INSERT); + regTestWritePixAndCheck(rp, pix1, IFF_JFIF_JPEG); /* 1 */ + + /* Apply a gamma to clean up the remaining background */ + pix2 = pixGammaTRC(NULL, pix1, 1.5, 50, 235); + pixaAddPix(pixa1, pix2, L_INSERT); + regTestWritePixAndCheck(rp, pix2, IFF_JFIF_JPEG); /* 2 */ + + /* Here are two possible output display images; a dithered + * 2 bpp image and a 7 level thresholded 4 bpp image */ + pix3 = pixDitherTo2bpp(pix2, 1); + pixaAddPix(pixa1, pix3, L_INSERT); + regTestWritePixAndCheck(rp, pix3, IFF_PNG); /* 3 */ + pix4 = pixThresholdTo4bpp(pix2, 7, 1); + pixaAddPix(pixa1, pix4, L_INSERT); + regTestWritePixAndCheck(rp, pix4, IFF_PNG); /* 4 */ + + /* Binary image produced from 8 bpp normalized ones, + * before and after the gamma correction. */ + pix5 = pixThresholdToBinary(pix1, 180); + pixaAddPix(pixa1, pix5, L_INSERT); + regTestWritePixAndCheck(rp, pix5, IFF_PNG); /* 5 */ + pix6 = pixThresholdToBinary(pix2, 200); + pixaAddPix(pixa1, pix6, L_INSERT); + regTestWritePixAndCheck(rp, pix6, IFF_PNG); /* 6 */ + + pix7 = pixaDisplayTiledInColumns(pixa1, 3, 1.0, 30, 2); + pixDisplayWithTitle(pix7, 0, 0, NULL, rp->display); + regTestWritePixAndCheck(rp, pix7, IFF_JFIF_JPEG); /* 7 */ + pixDestroy(&pix7); + pixaDestroy(&pixa1); + + /* ---------------------------------------------------------- * + * Normalize for rapidly varying background * + * ---------------------------------------------------------- */ + pixa1 = pixaCreate(0); + pixs = pixRead("w91frag.jpg"); + pixGetDimensions(pixs, &w, &h, NULL); + pixaAddPix(pixa1, pixs, L_INSERT); + regTestWritePixAndCheck(rp, pixs, IFF_JFIF_JPEG); /* 8 */ + startTimer(); + pix1 = pixBackgroundNormFlex(pixs, 7, 7, 1, 1, 10); + mps = 0.000001 * w * h / stopTimer(); + lept_stderr("Time: Flexible bg norm: %7.3f Mpix/sec\n", mps); + pixaAddPix(pixa1, pix1, L_INSERT); + regTestWritePixAndCheck(rp, pix1, IFF_JFIF_JPEG); /* 9 */ + + /* Now do it again in several steps */ + pix2 = pixScaleSmooth(pixs, 1./7., 1./7.); + pix3 = pixScale(pix2, 7.0, 7.0); + pixaAddPix(pixa1, pix3, L_INSERT); + regTestWritePixAndCheck(rp, pix3, IFF_JFIF_JPEG); /* 10 */ + pixLocalExtrema(pix2, 0, 0, &pixmin, NULL); /* 1's at minima */ + pix4 = pixExpandBinaryReplicate(pixmin, 7, 7); + pixaAddPix(pixa1, pix4, L_INSERT); + regTestWritePixAndCheck(rp, pix4, IFF_JFIF_JPEG); /* 11 */ + pix5 = pixSeedfillGrayBasin(pixmin, pix2, 10, 4); + pix6 = pixExtendByReplication(pix5, 1, 1); + regTestWritePixAndCheck(rp, pix6, IFF_JFIF_JPEG); /* 12 */ + pixDestroy(&pixmin); + pixDestroy(&pix5); + pixDestroy(&pix2); + pix7 = pixGetInvBackgroundMap(pix6, 200, 1, 1); /* smoothing incl. */ + pix8 = pixApplyInvBackgroundGrayMap(pixs, pix7, 7, 7); + pixaAddPix(pixa1, pix8, L_INSERT); + regTestWritePixAndCheck(rp, pix8, IFF_JFIF_JPEG); /* 13 */ + pixDestroy(&pix6); + pixDestroy(&pix7); + + /* Process the result for gray and binary output */ + pix9 = pixGammaTRCMasked(NULL, pix1, NULL, 1.0, 100, 175); + pixaAddPix(pixa1, pix9, L_INSERT); + regTestWritePixAndCheck(rp, pix9, IFF_JFIF_JPEG); /* 14 */ + pix10 = pixThresholdTo4bpp(pix9, 10, 1); + pixaAddPix(pixa1, pix10, L_INSERT); + regTestWritePixAndCheck(rp, pix10, IFF_JFIF_JPEG); /* 15 */ + pix11 = pixThresholdToBinary(pix9, 190); + pixaAddPix(pixa1, pix11, L_INSERT); + regTestWritePixAndCheck(rp, pix11, IFF_JFIF_JPEG); /* 16 */ + + pix2 = pixaDisplayTiledInColumns(pixa1, 3, 1.0, 30, 2); + pixDisplayWithTitle(pix2, 0, 700, NULL, rp->display); + regTestWritePixAndCheck(rp, pix2, IFF_JFIF_JPEG); /* 17 */ + pixDestroy(&pix2); + pixaDestroy(&pixa1); + return regTestCleanup(rp); +} + + diff --git a/leptonica/prog/affine_reg.c b/leptonica/prog/affine_reg.c new file mode 100644 index 00000000..a789d1c9 --- /dev/null +++ b/leptonica/prog/affine_reg.c @@ -0,0 +1,425 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * affine_reg.c + * + * Tests affine transforms, including invertability and large distortions. + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + +static void MakePtas(l_int32 i, PTA **pptas, PTA **pptad); +static l_int32 RenderHashedBoxa(PIX *pixt, BOXA *boxa, l_int32 i); + + + /* Sample values. + * 1-3: invertability tests + * 4: comparison between sampling and sequential + * 5: test with large distortion + */ +static const l_int32 x1[] = { 300, 300, 300, 95, 32}; +static const l_int32 y1[] = {1200, 1200, 1250, 2821, 934}; +static const l_int32 x2[] = {1200, 1200, 1125, 1432, 487}; +static const l_int32 y2[] = {1100, 1100, 1100, 2682, 934}; +static const l_int32 x3[] = { 200, 200, 200, 232, 32}; +static const l_int32 y3[] = { 200, 200, 200, 657, 67}; + +static const l_int32 xp1[] = { 500, 300, 350, 117, 32}; +static const l_int32 yp1[] = {1700, 1400, 1400, 2629, 934}; +static const l_int32 xp2[] = {850, 1400, 1400, 1464, 487}; +static const l_int32 yp2[] = {850, 1500, 1500, 2432, 804}; +static const l_int32 xp3[] = { 450, 200, 400, 183, 61}; +static const l_int32 yp3[] = { 300, 300, 400, 490, 83}; + +static const l_int32 SHIFTX = 44; +static const l_int32 SHIFTY = 39; +static const l_float32 SCALEX = 0.83; +static const l_float32 SCALEY = 0.78; +static const l_float32 ROTATION = 0.11; /* radian */ + +#define ADDED_BORDER_PIXELS 1000 +#define ALL 1 + + +int main(int argc, + char **argv) +{ +l_int32 i, w, h; +l_float32 *mat1, *mat2, *mat3, *mat1i, *mat2i, *mat3i, *matdinv; +l_float32 matd[9], matdi[9]; +BOXA *boxa, *boxa2; +PIX *pix, *pixs, *pixb, *pixg, *pixc, *pixcs; +PIX *pixd, *pix1, *pix2, *pix3; +PIXA *pixa; +PTA *ptas, *ptad; +L_REGPARAMS *rp; + + if (regTestSetup(argc, argv, &rp)) + return 1; + + pix = pixRead("feyn.tif"); + pixs = pixScale(pix, 0.22, 0.22); + pixDestroy(&pix); + +#if ALL + /* Test invertability of sequential. */ + lept_stderr("Test invertability of sequential\n"); + pixa = pixaCreate(0); + for (i = 0; i < 3; i++) { + pixb = pixAddBorder(pixs, ADDED_BORDER_PIXELS, 0); + MakePtas(i, &ptas, &ptad); + pix1 = pixAffineSequential(pixb, ptad, ptas, 0, 0); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 0,3,6 */ + pixaAddPix(pixa, pix1, L_INSERT); + pix2 = pixAffineSequential(pix1, ptas, ptad, 0, 0); + regTestWritePixAndCheck(rp, pix2, IFF_PNG); /* 1,4,7 */ + pixaAddPix(pixa, pix2, L_INSERT); + pixd = pixRemoveBorder(pix2, ADDED_BORDER_PIXELS); + pixXor(pixd, pixd, pixs); + regTestWritePixAndCheck(rp, pixd, IFF_PNG); /* 2,5,8 */ + pixaAddPix(pixa, pixd, L_INSERT); + pixDestroy(&pixb); + ptaDestroy(&ptas); + ptaDestroy(&ptad); + } + + pix1 = pixaDisplayTiledInColumns(pixa, 3, 1.0, 20, 3); + pix2 = pixScaleToGray(pix1, 0.2); + regTestWritePixAndCheck(rp, pix2, IFF_PNG); /* 9 */ + pixDisplayWithTitle(pix2, 0, 100, NULL, rp->display); + pixDestroy(&pix1); + pixDestroy(&pix2); + pixaDestroy(&pixa); +#endif + +#if ALL + /* Test invertability of sampling */ + lept_stderr("Test invertability of sampling\n"); + pixa = pixaCreate(0); + for (i = 0; i < 3; i++) { + pixb = pixAddBorder(pixs, ADDED_BORDER_PIXELS, 0); + MakePtas(i, &ptas, &ptad); + pix1 = pixAffineSampledPta(pixb, ptad, ptas, L_BRING_IN_WHITE); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 10,13,16 */ + pixaAddPix(pixa, pix1, L_INSERT); + pix2 = pixAffineSampledPta(pix1, ptas, ptad, L_BRING_IN_WHITE); + regTestWritePixAndCheck(rp, pix2, IFF_PNG); /* 11,14,17 */ + pixaAddPix(pixa, pix2, L_INSERT); + pixd = pixRemoveBorder(pix2, ADDED_BORDER_PIXELS); + pixXor(pixd, pixd, pixs); + regTestWritePixAndCheck(rp, pixd, IFF_PNG); /* 12,15,18 */ + pixaAddPix(pixa, pixd, L_INSERT); + pixDestroy(&pixb); + ptaDestroy(&ptas); + ptaDestroy(&ptad); + } + + pix1 = pixaDisplayTiledInColumns(pixa, 3, 1.0, 20, 3); + pix2 = pixScaleToGray(pix1, 0.2); + regTestWritePixAndCheck(rp, pix2, IFF_PNG); /* 19 */ + pixDisplayWithTitle(pix2, 200, 100, NULL, rp->display); + pixDestroy(&pix1); + pixDestroy(&pix2); + pixDestroy(&pixs); + pixaDestroy(&pixa); +#endif + +#if ALL + /* Test invertability of interpolation on grayscale */ + lept_stderr("Test invertability of grayscale interpolation\n"); + pix = pixRead("feyn.tif"); + pixg = pixScaleToGray3(pix); + pixDestroy(&pix); + pixa = pixaCreate(0); + for (i = 0; i < 3; i++) { + pixb = pixAddBorder(pixg, ADDED_BORDER_PIXELS / 3, 255); + MakePtas(i, &ptas, &ptad); + pix1 = pixAffinePta(pixb, ptad, ptas, L_BRING_IN_WHITE); + regTestWritePixAndCheck(rp, pix1, IFF_JFIF_JPEG); /* 20,23,26 */ + pixaAddPix(pixa, pix1, L_INSERT); + pix2 = pixAffinePta(pix1, ptas, ptad, L_BRING_IN_WHITE); + regTestWritePixAndCheck(rp, pix2, IFF_JFIF_JPEG); /* 21,24,27 */ + pixaAddPix(pixa, pix2, L_INSERT); + pixd = pixRemoveBorder(pix2, ADDED_BORDER_PIXELS / 3); + pixXor(pixd, pixd, pixg); + pixInvert(pixd, pixd); + regTestWritePixAndCheck(rp, pixd, IFF_JFIF_JPEG); /* 22,25,28 */ + pixaAddPix(pixa, pixd, L_INSERT); + pixDestroy(&pixb); + ptaDestroy(&ptas); + ptaDestroy(&ptad); + } + + pix1 = pixaDisplayTiledInColumns(pixa, 3, 1.0, 20, 3); + pix2 = pixScale(pix1, 0.2, 0.2); + regTestWritePixAndCheck(rp, pix2, IFF_JFIF_JPEG); /* 29 */ + pixDisplayWithTitle(pix2, 400, 100, NULL, rp->display); + pixDestroy(&pix1); + pixDestroy(&pix2); + pixDestroy(&pixg); + pixaDestroy(&pixa); +#endif + +#if ALL + /* Test invertability of interpolation on color */ + lept_stderr("Test invertability of color interpolation\n"); + pixa = pixaCreate(0); + pixc = pixRead("test24.jpg"); + pixcs = pixScale(pixc, 0.3, 0.3); + for (i = 0; i < 3; i++) { + pixb = pixAddBorder(pixcs, ADDED_BORDER_PIXELS / 4, 0xffffff00); + MakePtas(i, &ptas, &ptad); + pix1 = pixAffinePta(pixb, ptad, ptas, L_BRING_IN_WHITE); + regTestWritePixAndCheck(rp, pix1, IFF_JFIF_JPEG); /* 30,33,36 */ + pixaAddPix(pixa, pix1, L_INSERT); + pix2 = pixAffinePta(pix1, ptas, ptad, L_BRING_IN_WHITE); + regTestWritePixAndCheck(rp, pix2, IFF_JFIF_JPEG); /* 31,34,37 */ + pixaAddPix(pixa, pix2, L_INSERT); + pixd = pixRemoveBorder(pix2, ADDED_BORDER_PIXELS / 4); + pixXor(pixd, pixd, pixcs); + pixInvert(pixd, pixd); + regTestWritePixAndCheck(rp, pixd, IFF_JFIF_JPEG); /* 32,35,38 */ + pixaAddPix(pixa, pixd, L_INSERT); + pixDestroy(&pixb); + ptaDestroy(&ptas); + ptaDestroy(&ptad); + } + pixDestroy(&pixcs); + + pix1 = pixaDisplayTiledInColumns(pixa, 3, 1.0, 20, 3); + pix2 = pixScale(pix1, 0.25, 0.25); + regTestWritePixAndCheck(rp, pix2, IFF_JFIF_JPEG); /* 39 */ + pixDisplayWithTitle(pix2, 600, 100, NULL, rp->display); + pixDestroy(&pix1); + pixDestroy(&pix2); + pixDestroy(&pixc); + pixaDestroy(&pixa); +#endif + +#if ALL + /* Comparison between sequential and sampling */ + lept_stderr("Compare sequential with sampling\n"); + pix = pixRead("feyn.tif"); + pixs = pixScale(pix, 0.22, 0.22); + pixDestroy(&pix); + + MakePtas(3, &ptas, &ptad); + pixa = pixaCreate(0); + + /* Use sequential transforms */ + pix1 = pixAffineSequential(pixs, ptas, ptad, + ADDED_BORDER_PIXELS, ADDED_BORDER_PIXELS); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 40 */ + pixaAddPix(pixa, pix1, L_INSERT); + + /* Use sampled transform */ + pix2 = pixAffineSampledPta(pixs, ptas, ptad, L_BRING_IN_WHITE); + regTestWritePixAndCheck(rp, pix2, IFF_PNG); /* 41 */ + pixaAddPix(pixa, pix2, L_COPY); + + /* Compare the results */ + pixXor(pix2, pix2, pix1); + regTestWritePixAndCheck(rp, pix2, IFF_PNG); /* 42 */ + pixaAddPix(pixa, pix2, L_INSERT); + + pix1 = pixaDisplayTiledInColumns(pixa, 3, 1.0, 20, 3); + pix2 = pixScale(pix1, 0.5, 0.5); + regTestWritePixAndCheck(rp, pix2, IFF_PNG); /* 43 */ + pixDisplayWithTitle(pix2, 800, 100, NULL, rp->display); + pixDestroy(&pix1); + pixDestroy(&pix2); + pixDestroy(&pixs); + pixaDestroy(&pixa); + ptaDestroy(&ptas); + ptaDestroy(&ptad); +#endif + + +#if ALL + /* Test with large distortion */ + lept_stderr("Test with large distortion\n"); + MakePtas(4, &ptas, &ptad); + pixa = pixaCreate(0); + pix = pixRead("feyn.tif"); + pixg = pixScaleToGray6(pix); + pixDestroy(&pix); + + pix1 = pixAffineSequential(pixg, ptas, ptad, 0, 0); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 44 */ + pixaAddPix(pixa, pix1, L_COPY); + + pix2 = pixAffineSampledPta(pixg, ptas, ptad, L_BRING_IN_WHITE); + regTestWritePixAndCheck(rp, pix2, IFF_PNG); /* 45 */ + pixaAddPix(pixa, pix2, L_COPY); + + pix3 = pixAffinePta(pixg, ptas, ptad, L_BRING_IN_WHITE); + regTestWritePixAndCheck(rp, pix3, IFF_PNG); /* 46 */ + pixaAddPix(pixa, pix3, L_INSERT); + + pixXor(pix1, pix1, pix2); + pixInvert(pix1, pix1); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 47 */ + pixaAddPix(pixa, pix1, L_INSERT); + pixXor(pix2, pix2, pix3); + pixInvert(pix2, pix2); + regTestWritePixAndCheck(rp, pix2, IFF_PNG); /* 48 */ + pixaAddPix(pixa, pix2, L_INSERT); + + pix1 = pixaDisplayTiledInColumns(pixa, 5, 1.0, 20, 3); + pix2 = pixScale(pix1, 0.8, 0.8); + regTestWritePixAndCheck(rp, pix2, IFF_PNG); /* 49 */ + pixDisplayWithTitle(pix2, 1000, 100, NULL, rp->display); + pixDestroy(&pix1); + pixDestroy(&pix2); + pixDestroy(&pixg); + pixaDestroy(&pixa); + ptaDestroy(&ptas); + ptaDestroy(&ptad); +#endif + +#if ALL + /* Set up pix and boxa */ + lept_stderr("Test affine transforms and inverses on pix and boxa\n"); + pixa = pixaCreate(0); + pix = pixRead("lucasta.1.300.tif"); + pixTranslate(pix, pix, 70, 0, L_BRING_IN_WHITE); + pix1 = pixCloseBrick(NULL, pix, 14, 5); + pixOpenBrick(pix1, pix1, 1, 2); + boxa = pixConnComp(pix1, NULL, 8); + pixs = pixConvertTo32(pix); + pixGetDimensions(pixs, &w, &h, NULL); + pixc = pixCopy(NULL, pixs); + RenderHashedBoxa(pixc, boxa, 113); + regTestWritePixAndCheck(rp, pixc, IFF_PNG); /* 50 */ + pixaAddPix(pixa, pixc, L_INSERT); + pixDestroy(&pix); + pixDestroy(&pix1); + + /* Set up an affine transform in matd, and apply it to boxa */ + mat1 = createMatrix2dTranslate(SHIFTX, SHIFTY); + mat2 = createMatrix2dScale(SCALEX, SCALEY); + mat3 = createMatrix2dRotate(w / 2, h / 2, ROTATION); + l_productMat3(mat3, mat2, mat1, matd, 3); + boxa2 = boxaAffineTransform(boxa, matd); + + /* Set up the inverse transform --> matdi */ + mat1i = createMatrix2dTranslate(-SHIFTX, -SHIFTY); + mat2i = createMatrix2dScale(1.0/ SCALEX, 1.0 / SCALEY); + mat3i = createMatrix2dRotate(w / 2, h / 2, -ROTATION); + l_productMat3(mat1i, mat2i, mat3i, matdi, 3); + + /* Invert the original affine transform --> matdinv */ + affineInvertXform(matd, &matdinv); + if (rp->display) { + lept_stderr(" Affine transform, applied to boxa\n"); + for (i = 0; i < 9; i++) { + if (i && (i % 3 == 0)) lept_stderr("\n"); + lept_stderr(" %7.3f ", matd[i]); + } + lept_stderr("\n Inverse transform, by composing inverse parts"); + for (i = 0; i < 9; i++) { + if (i % 3 == 0) lept_stderr("\n"); + lept_stderr(" %7.3f ", matdi[i]); + } + lept_stderr("\n Inverse transform, by inverting affine xform"); + for (i = 0; i < 6; i++) { + if (i % 3 == 0) lept_stderr("\n"); + lept_stderr(" %7.3f ", matdinv[i]); + } + lept_stderr("\n"); + } + + /* Apply the inverted affine transform --> pixs */ + pixd = pixAffine(pixs, matdinv, L_BRING_IN_WHITE); + RenderHashedBoxa(pixd, boxa2, 513); + regTestWritePixAndCheck(rp, pixd, IFF_PNG); /* 51 */ + pixaAddPix(pixa, pixd, L_INSERT); + + pix1 = pixaDisplayTiledInColumns(pixa, 2, 1.0, 30, 2); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 52 */ + pixDisplayWithTitle(pix1, 1200, 100, NULL, rp->display); + pixDestroy(&pix1); + pixaDestroy(&pixa); + + pixDestroy(&pixs); + boxaDestroy(&boxa); + boxaDestroy(&boxa2); + lept_free(mat1); + lept_free(mat2); + lept_free(mat3); + lept_free(mat1i); + lept_free(mat2i); + lept_free(mat3i); + lept_free(matdinv); +#endif + + return regTestCleanup(rp); +} + +static void +MakePtas(l_int32 i, + PTA **pptas, + PTA **pptad) +{ + + *pptas = ptaCreate(3); + ptaAddPt(*pptas, x1[i], y1[i]); + ptaAddPt(*pptas, x2[i], y2[i]); + ptaAddPt(*pptas, x3[i], y3[i]); + *pptad = ptaCreate(3); + ptaAddPt(*pptad, xp1[i], yp1[i]); + ptaAddPt(*pptad, xp2[i], yp2[i]); + ptaAddPt(*pptad, xp3[i], yp3[i]); + return; +} + + +static l_int32 +RenderHashedBoxa(PIX *pixt, + BOXA *boxa, + l_int32 i) +{ +l_int32 j, n, rval, gval, bval; +BOX *box; + + n = boxaGetCount(boxa); + rval = (1413 * i) % 256; + gval = (4917 * i) % 256; + bval = (7341 * i) % 256; + for (j = 0; j < n; j++) { + box = boxaGetBox(boxa, j, L_CLONE); + pixRenderHashBoxArb(pixt, box, 10, 3, i % 4, 1, rval, gval, bval); + boxDestroy(&box); + } + return 0; +} + + diff --git a/leptonica/prog/alltests_reg.c b/leptonica/prog/alltests_reg.c new file mode 100644 index 00000000..6d651424 --- /dev/null +++ b/leptonica/prog/alltests_reg.c @@ -0,0 +1,282 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * alltests_reg.c + * + * Tests all the reg tests: + * + * alltests_reg command + * + * where + * <command> == "generate" to make the golden files in /tmp/golden + * <command> == "compare" to make local files and compare with + * the golden files + * <command> == "display" to make local files and display + * + * You can also run each test individually with any one of these + * arguments. Warning: if you run this with "display", a very + * large number of images will be displayed on the screen. + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include <string.h> +#include "allheaders.h" + +static const char *tests[] = { + "adaptmap_reg", + "adaptnorm_reg", + "affine_reg", + "alphaops_reg", + "alphaxform_reg", + "baseline_reg", + "bilateral2_reg", + "bilinear_reg", + "binarize_reg", + "binmorph1_reg", + "binmorph3_reg", + "binmorph6_reg", + "blackwhite_reg", + "blend1_reg", + "blend2_reg", + "blend3_reg", + "blend4_reg", + "blend5_reg", + "boxa1_reg", + "boxa2_reg", + "boxa3_reg", + "boxa4_reg", + "bytea_reg", + "ccbord_reg", + "ccthin1_reg", + "ccthin2_reg", + "checkerboard_reg", + "circle_reg", + "cmapquant_reg", + "colorcontent_reg", + "colorfill_reg", + "coloring_reg", + "colorize_reg", + "colormask_reg", + "colormorph_reg", + "colorquant_reg", + "colorseg_reg", + "colorspace_reg", + "compare_reg", + "compfilter_reg", + "conncomp_reg", + "conversion_reg", + "convolve_reg", + "crop_reg", + "dewarp_reg", + "distance_reg", + "dither_reg", + "dna_reg", + "dwamorph1_reg", + "edge_reg", + "encoding_reg", + "enhance_reg", + "equal_reg", + "expand_reg", + "extrema_reg", + "falsecolor_reg", + "fhmtauto_reg", + /* "files_reg", */ + "findcorners_reg", + "findpattern_reg", + "flipdetect_reg", + "fpix1_reg", + "fpix2_reg", + "genfonts_reg", +#if HAVE_LIBGIF + "gifio_reg", +#endif /* HAVE_LIBGIF */ + "grayfill_reg", + "graymorph1_reg", + "graymorph2_reg", + "grayquant_reg", + "hardlight_reg", + "hash_reg", + "heap_reg", + "insert_reg", + "ioformats_reg", + "iomisc_reg", + "italic_reg", + "jbclass_reg", +#if HAVE_LIBJP2K + "jp2kio_reg", +#endif /* HAVE_LIBJP2K */ + "jpegio_reg", + "kernel_reg", + "label_reg", + "lineremoval_reg", + "locminmax_reg", + "logicops_reg", + "lowaccess_reg", + "lowsat_reg", + "maze_reg", + "mtiff_reg", + "multitype_reg", + "numa1_reg", + "numa2_reg", + "nearline_reg", + "newspaper_reg", + "overlap_reg", + "pageseg_reg", + "paint_reg", + "paintmask_reg", + "pdfio1_reg", + "pdfio2_reg", + "pdfseg_reg", + "pixa1_reg", + "pixa2_reg", + "pixadisp_reg", + "pixcomp_reg", + "pixmem_reg", + "pixserial_reg", + "pngio_reg", + "pnmio_reg", + "projection_reg", + "projective_reg", + "psio_reg", + "psioseg_reg", + "pta_reg", + "ptra1_reg", + "ptra2_reg", + "quadtree_reg", + "rank_reg", + "rankbin_reg", + "rankhisto_reg", + "rasterop_reg", + "rasteropip_reg", + "rectangle_reg", + "rotate1_reg", + "rotate2_reg", + "rotateorth_reg", + "scale_reg", + "seedspread_reg", + "selio_reg", + "shear1_reg", + "shear2_reg", + "skew_reg", + "smallpix_reg", + "speckle_reg", + "splitcomp_reg", + "string_reg", + "subpixel_reg", + "texturefill_reg", + "threshnorm_reg", + "translate_reg", + "warper_reg", + "watershed_reg", +#if HAVE_LIBWEBP_ANIM + "webpanimio_reg", +#endif /* HAVE_LIBWEBP_ANIM */ +#if HAVE_LIBWEBP + "webpio_reg", +#endif /* HAVE_LIBWEBP */ + "wordboxes_reg", + "writetext_reg", + "xformbox_reg", + }; + +static const char *header = {"\n=======================\n" + "Regression Test Results\n" + "======================="}; + +int main(int argc, + char **argv) +{ +char *str, *results_file; +char command[256], buf[256]; +l_int32 i, ntests, dotest, nfail, ret, start, stop; +SARRAY *sa; +static char mainName[] = "alltests_reg"; + + if (argc != 2) + return ERROR_INT(" Syntax alltests_reg [generate | compare | display]", + mainName, 1); + + setLeptDebugOK(1); /* required for testing */ + l_getCurrentTime(&start, NULL); + ntests = sizeof(tests) / sizeof(char *); + lept_stderr("Running alltests_reg:\n" + "This currently tests %d regression test\n" + "programs in the /prog directory.\n", ntests); + + /* Clear the output file if we're doing the set of reg tests */ + dotest = strcmp(argv[1], "compare") ? 0 : 1; + if (dotest) { + results_file = genPathname("/tmp/lept", "reg_results.txt"); + sa = sarrayCreate(3); + sarrayAddString(sa, header, L_COPY); + sarrayAddString(sa, getLeptonicaVersion(), L_INSERT); + sarrayAddString(sa, getImagelibVersions(), L_INSERT); + str = sarrayToString(sa, 1); + sarrayDestroy(&sa); + l_binaryWrite("/tmp/lept/reg_results.txt", "w", str, strlen(str)); + lept_free(str); + } + + nfail = 0; + for (i = 0; i < ntests; i++) { +#ifndef _WIN32 + snprintf(command, sizeof(command) - 2, "./%s %s", tests[i], argv[1]); +#else /* windows interprets '/' as a commandline flag */ + snprintf(command, sizeof(command) - 2, "%s %s", tests[i], argv[1]); +#endif /* ! _WIN32 */ + ret = system(command); + if (ret) { + snprintf(buf, sizeof(buf), "Failed to complete %s\n", tests[i]); + if (dotest) { + l_binaryWrite("/tmp/lept/reg_results.txt", "a", + buf, strlen(buf)); + nfail++; + } + else + lept_stderr("%s", buf); + } + } + + if (dotest) { +#ifndef _WIN32 + snprintf(command, sizeof(command) - 2, "cat %s", results_file); +#else + snprintf(command, sizeof(command) - 2, "type \"%s\"", results_file); +#endif /* !_WIN32 */ + lept_free(results_file); + ret = system(command); + lept_stderr("Success in %d of %d *_reg programs (output matches" + " the \"golden\" files)\n", ntests - nfail, ntests); + } + + l_getCurrentTime(&stop, NULL); + lept_stderr("Time for all regression tests: %d sec\n", stop - start); + return 0; +} diff --git a/leptonica/prog/alphaops_reg.c b/leptonica/prog/alphaops_reg.c new file mode 100644 index 00000000..e373db5f --- /dev/null +++ b/leptonica/prog/alphaops_reg.c @@ -0,0 +1,337 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * alphaops_reg.c + * + * Tests various functions that use the alpha layer: + * + * (1) Remove and add alpha layers. + * Removing is done by blending with a uniform image. + * Adding is done by setting all white pixels to transparent, + * and grading the alpha layer to opaque depending on + * the distance from the nearest transparent pixel. + * + * (2) Tests transparency and cleaning under alpha. + * + * (3) Blending with a uniform color. Also tests an alternative + * way to "blend" to a color: component-wise multiplication by + * the color. + * + * (4) Testing RGB and colormapped images with alpha, including + * binary and ascii colormap serialization. + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + +static PIX *DoBlendTest(PIX *pix, BOX *box, l_uint32 val, l_float32 gamma, + l_int32 minval, l_int32 maxval, l_int32 which); + +int main(int argc, + char **argv) +{ +l_uint8 *data; +l_int32 w, h, n1, n2, n, i, minval, maxval; +l_int32 ncolors, rval, gval, bval, equal; +l_int32 *rmap, *gmap, *bmap; +l_uint32 color; +l_float32 gamma; +BOX *box; +FILE *fp; +PIX *pix1, *pix2, *pix3, *pix4, *pix5, *pix6; +PIX *pixs, *pixb, *pixg, *pixc, *pixd; +PIX *pixg2, *pixcs1, *pixcs2, *pixd1, *pixd2; +PIXA *pixa, *pixa2, *pixa3; +PIXCMAP *cmap, *cmap2; +RGBA_QUAD *cta; +L_REGPARAMS *rp; + + if (regTestSetup(argc, argv, &rp)) + return 1; + + /* ------------------------ (1) ----------------------------*/ + /* Blend with a white background */ + pix1 = pixRead("books_logo.png"); + pixDisplayWithTitle(pix1, 100, 0, NULL, rp->display); + pix2 = pixAlphaBlendUniform(pix1, 0xffffff00); + pixDisplayWithTitle(pix2, 100, 150, NULL, rp->display); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 0 */ + regTestWritePixAndCheck(rp, pix2, IFF_PNG); /* 1 */ + + /* Generate an alpha layer based on the white background */ + pix3 = pixSetAlphaOverWhite(pix2); + pixSetSpp(pix3, 3); + /* without alpha */ + pixWrite("/tmp/lept/regout/alphaops.2.png", pix3, IFF_PNG); + regTestCheckFile(rp, "/tmp/lept/regout/alphaops.2.png"); /* 2 */ + pixSetSpp(pix3, 4); + regTestWritePixAndCheck(rp, pix3, IFF_PNG); /* 3, with alpha */ + pixDisplayWithTitle(pix3, 100, 300, NULL, rp->display); + + /* Render on a light yellow background */ + pix4 = pixAlphaBlendUniform(pix3, 0xffffe000); + regTestWritePixAndCheck(rp, pix4, IFF_PNG); /* 4 */ + pixDisplayWithTitle(pix4, 100, 450, NULL, rp->display); + pixDestroy(&pix1); + pixDestroy(&pix2); + pixDestroy(&pix3); + pixDestroy(&pix4); + + /* ------------------------ (2) ----------------------------*/ + lept_mkdir("lept/alpha"); + /* Make the transparency (alpha) layer. + * pixs is the mask. We turn it into a transparency (alpha) + * layer by converting to 8 bpp. A small convolution fuzzes + * the mask edges so that you don't see the pixels. */ + pixs = pixRead("feyn-fract.tif"); + pixGetDimensions(pixs, &w, &h, NULL); + pixg = pixConvert1To8(NULL, pixs, 0, 255); + pixg2 = pixBlockconvGray(pixg, NULL, 1, 1); + regTestWritePixAndCheck(rp, pixg2, IFF_JFIF_JPEG); /* 5 */ + pixDisplayWithTitle(pixg2, 0, 0, "alpha", rp->display); + + /* Make the viewable image. + * pixc is the image that we see where the alpha layer is + * opaque -- i.e., greater than 0. Scale it to the same + * size as the mask. To visualize what this will look like + * when displayed over a black background, create the black + * background image, pixb, and do the blending with pixcs1 + * explicitly using the alpha layer pixg2. */ + pixc = pixRead("tetons.jpg"); + pixcs1 = pixScaleToSize(pixc, w, h); + regTestWritePixAndCheck(rp, pixcs1, IFF_JFIF_JPEG); /* 6 */ + pixDisplayWithTitle(pixcs1, 300, 0, "viewable", rp->display); + pixb = pixCreateTemplate(pixcs1); /* black */ + pixd1 = pixBlendWithGrayMask(pixb, pixcs1, pixg2, 0, 0); + regTestWritePixAndCheck(rp, pixd1, IFF_JFIF_JPEG); /* 7 */ + pixDisplayWithTitle(pixd1, 600, 0, "alpha-blended 1", rp->display); + + /* Embed the alpha layer pixg2 into the color image pixc. + * Write it out as is. Then clean pixcs1 (to 0) under the fully + * transparent part of the alpha layer, and write that result + * out as well. */ + pixSetRGBComponent(pixcs1, pixg2, L_ALPHA_CHANNEL); + pixWrite("/tmp/lept/alpha/cs1.png", pixcs1, IFF_PNG); + pixcs2 = pixSetUnderTransparency(pixcs1, 0, 0); + pixWrite("/tmp/lept/alpha/cs2.png", pixcs2, IFF_PNG); + + /* What will this look like over a black background? + * Do the blending explicitly and display. It should + * look identical to the blended result pixd1 before cleaning. */ + pixd2 = pixBlendWithGrayMask(pixb, pixcs2, pixg2, 0, 0); + regTestWritePixAndCheck(rp, pixd2, IFF_JFIF_JPEG); /* 8 */ + pixDisplayWithTitle(pixd2, 0, 400, "alpha blended 2", rp->display); + + /* Read the two images back, ignoring the transparency layer. + * The uncleaned image will come back identical to pixcs1. + * However, the cleaned image will be black wherever + * the alpha layer was fully transparent. It will + * look the same when viewed through the alpha layer, + * but have much better compression. */ + pix1 = pixRead("/tmp/lept/alpha/cs1.png"); /* just pixcs1 */ + pix2 = pixRead("/tmp/lept/alpha/cs2.png"); /* cleaned under transparent */ + n1 = nbytesInFile("/tmp/lept/alpha/cs1.png"); + n2 = nbytesInFile("/tmp/lept/alpha/cs2.png"); + lept_stderr(" Original: %d bytes\n Cleaned: %d bytes\n", n1, n2); + regTestWritePixAndCheck(rp, pix1, IFF_JFIF_JPEG); /* 9 */ + regTestWritePixAndCheck(rp, pix2, IFF_JFIF_JPEG); /* 10 */ + pixDisplayWithTitle(pix1, 300, 400, "without alpha", rp->display); + pixDisplayWithTitle(pix2, 600, 400, "cleaned under transparent", + rp->display); + + pixa = pixaCreate(0); + pixaAddPix(pixa, pixg2, L_INSERT); + pixaAddPix(pixa, pixcs1, L_INSERT); + pixaAddPix(pixa, pix1, L_INSERT); + pixaAddPix(pixa, pixd1, L_INSERT); + pixaAddPix(pixa, pixd2, L_INSERT); + pixaAddPix(pixa, pix2, L_INSERT); + pixd = pixaDisplayTiledInColumns(pixa, 1, 1.0, 20, 2); + regTestWritePixAndCheck(rp, pixd, IFF_JFIF_JPEG); /* 11 */ + pixDisplayWithTitle(pixd, 200, 200, "composite", rp->display); + pixWrite("/tmp/lept/alpha/composite.png", pixd, IFF_JFIF_JPEG); + pixDestroy(&pixd); + pixaDestroy(&pixa); + pixDestroy(&pixs); + pixDestroy(&pixb); + pixDestroy(&pixg); + pixDestroy(&pixc); + pixDestroy(&pixcs2); + pixDestroy(&pixd); + + /* ------------------------ (3) ----------------------------*/ + color = 0xffffa000; + gamma = 1.0; + minval = 0; + maxval = 200; + box = boxCreate(0, 85, 600, 100); + pixa = pixaCreate(6); + pix1 = pixRead("blend-green1.jpg"); + pixaAddPix(pixa, pix1, L_INSERT); + pix1 = pixRead("blend-green2.png"); + pixaAddPix(pixa, pix1, L_INSERT); + pix1 = pixRead("blend-green3.png"); + pixaAddPix(pixa, pix1, L_INSERT); + pix1 = pixRead("blend-orange.jpg"); + pixaAddPix(pixa, pix1, L_INSERT); + pix1 = pixRead("blend-yellow.jpg"); + pixaAddPix(pixa, pix1, L_INSERT); + pix1 = pixRead("blend-red.png"); + pixaAddPix(pixa, pix1, L_INSERT); + n = pixaGetCount(pixa); + pixa2 = pixaCreate(n); + pixa3 = pixaCreate(n); + for (i = 0; i < n; i++) { + pix1 = pixaGetPix(pixa, i, L_CLONE); + pix2 = DoBlendTest(pix1, box, color, gamma, minval, maxval, 1); + regTestWritePixAndCheck(rp, pix2, IFF_JFIF_JPEG); /* 12, 14, ... 22 */ + pixDisplayWithTitle(pix2, 150 * i, 0, NULL, rp->display); + pixaAddPix(pixa2, pix2, L_INSERT); + pix2 = DoBlendTest(pix1, box, color, gamma, minval, maxval, 2); + regTestWritePixAndCheck(rp, pix2, IFF_JFIF_JPEG); /* 13, 15, ... 23 */ + pixDisplayWithTitle(pix2, 150 * i, 200, NULL, rp->display); + pixaAddPix(pixa3, pix2, L_INSERT); + pixDestroy(&pix1); + } + if (rp->display) { + pixaConvertToPdf(pixa2, 0, 0.75, L_FLATE_ENCODE, 0, "blend 1 test", + "/tmp/lept/alpha/blend1.pdf"); + pixaConvertToPdf(pixa3, 0, 0.75, L_FLATE_ENCODE, 0, "blend 2 test", + "/tmp/lept/alpha/blend2.pdf"); + } + pixaDestroy(&pixa); + pixaDestroy(&pixa2); + pixaDestroy(&pixa3); + boxDestroy(&box); + + /* ------------------------ (4) ----------------------------*/ + /* Use one image as the alpha component for a second image */ + pix1 = pixRead("test24.jpg"); + pix2 = pixRead("marge.jpg"); + pix3 = pixScale(pix2, 1.9, 2.2); + pix4 = pixConvertTo8(pix3, 0); + pixSetRGBComponent(pix1, pix4, L_ALPHA_CHANNEL); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 24 */ + pixDisplayWithTitle(pix1, 600, 0, NULL, rp->display); + + /* Set the alpha value in a colormap to bval */ + pix5 = pixOctreeColorQuant(pix1, 128, 0); + cmap = pixGetColormap(pix5); + pixcmapToArrays(cmap, &rmap, &gmap, &bmap, NULL); + n = pixcmapGetCount(cmap); + for (i = 0; i < n; i++) { + pixcmapGetColor(cmap, i, &rval, &gval, &bval); + cta = (RGBA_QUAD *)cmap->array; + cta[i].alpha = bval; + } + + /* Test binary serialization/deserialization of colormap with alpha */ + pixcmapSerializeToMemory(cmap, 4, &ncolors, &data); + cmap2 = pixcmapDeserializeFromMemory(data, 4, ncolors); + cmapEqual(cmap, cmap2, 4, &equal); + regTestCompareValues(rp, TRUE, equal, 0.0); /* 25 */ + pixcmapDestroy(&cmap2); + lept_free(data); + + /* Test ascii serialization/deserialization of colormap with alpha */ + fp = fopenWriteStream("/tmp/lept/alpha/cmap.4", "w"); + pixcmapWriteStream(fp, cmap); + fclose(fp); + fp = fopenReadStream("/tmp/lept/alpha/cmap.4"); + cmap2 = pixcmapReadStream(fp); + fclose(fp); + cmapEqual(cmap, cmap2, 4, &equal); + regTestCompareValues(rp, TRUE, equal, 0.0); /* 26 */ + pixcmapDestroy(&cmap2); + + /* Test r/w for cmapped pix with non-opaque alpha */ + pixDisplayWithTitle(pix5, 900, 0, NULL, rp->display); + regTestWritePixAndCheck(rp, pix5, IFF_PNG); /* 27 */ + pixWrite("/tmp/lept/alpha/fourcomp.png", pix5, IFF_PNG); + pix6 = pixRead("/tmp/lept/alpha/fourcomp.png"); + regTestComparePix(rp, pix5, pix6); /* 28 */ + pixDestroy(&pix1); + pixDestroy(&pix2); + pixDestroy(&pix3); + pixDestroy(&pix4); + pixDestroy(&pix5); + pixDestroy(&pix6); + lept_free(rmap); + lept_free(gmap); + lept_free(bmap); + return regTestCleanup(rp); +} + + + /* Use which == 1 to test alpha blending; which == 2 to test "blending" + * by pixel multiplication. This generates a composite of 5 images: + * the original, blending over a box at the bottom (2 ways), and + * multiplying over a box at the bottom (2 ways). */ +static PIX * +DoBlendTest(PIX *pix, BOX *box, l_uint32 color, l_float32 gamma, + l_int32 minval, l_int32 maxval, l_int32 which) +{ +PIX *pix1, *pix2, *pix3, *pixd; +PIXA *pixa; + pixa = pixaCreate(5); + pix1 = pixRemoveColormap(pix, REMOVE_CMAP_TO_FULL_COLOR); + pix2 = pixCopy(NULL, pix1); + pixaAddPix(pixa, pix2, L_COPY); + if (which == 1) + pix3 = pixBlendBackgroundToColor(NULL, pix2, box, color, + gamma, minval, maxval); + else + pix3 = pixMultiplyByColor(NULL, pix2, box, color); + pixaAddPix(pixa, pix3, L_INSERT); + if (which == 1) + pixBlendBackgroundToColor(pix2, pix2, box, color, + gamma, minval, maxval); + else + pixMultiplyByColor(pix2, pix2, box, color); + pixaAddPix(pixa, pix2, L_INSERT); + pix2 = pixCopy(NULL, pix1); + if (which == 1) + pix3 = pixBlendBackgroundToColor(NULL, pix2, NULL, color, + gamma, minval, maxval); + else + pix3 = pixMultiplyByColor(NULL, pix2, NULL, color); + pixaAddPix(pixa, pix3, L_INSERT); + if (which == 1) + pixBlendBackgroundToColor(pix2, pix2, NULL, color, + gamma, minval, maxval); + else + pixMultiplyByColor(pix2, pix2, NULL, color); + pixaAddPix(pixa, pix2, L_INSERT); + + pixd = pixaDisplayTiledInRows(pixa, 32, 800, 1.0, 0, 30, 2); + pixDestroy(&pix1); + pixaDestroy(&pixa); + return pixd; +} diff --git a/leptonica/prog/alphaxform_reg.c b/leptonica/prog/alphaxform_reg.c new file mode 100644 index 00000000..7d30c47b --- /dev/null +++ b/leptonica/prog/alphaxform_reg.c @@ -0,0 +1,230 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * alphaxform_reg.c + * + * This tests the alpha blending functions when used with various + * transforms (scaling, rotation, affine, projective, bilinear). + * + * It also tests the version that are wrapped in a gamma transform, + * which is a technique for getting a truer color on transforming, + * because it undoes the gamma that has been applied to an image + * before transforming and then re-applying the gamma transform. + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + +static void MakePtas(l_int32 i, l_int32 npts, PTA **pptas, PTA **pptad); + +static const l_int32 x1[] = { 300, 300, 300, 95, 32 }; +static const l_int32 y1[] = { 1200, 1200, 1250, 2821, 934 }; +static const l_int32 x2[] = { 1200, 1200, 1125, 1432, 487 }; +static const l_int32 y2[] = { 1100, 1100, 1100, 2682, 934 }; +static const l_int32 x3[] = { 200, 200, 200, 232, 32 }; +static const l_int32 y3[] = { 200, 200, 200, 657, 67 }; +static const l_int32 x4[] = { 1200, 1200, 1125, 1432, 487 }; +static const l_int32 y4[] = { 200, 200, 200, 242, 84 }; + +static const l_int32 xp1[] = { 500, 300, 350, 117, 32 }; +static const l_int32 yp1[] = { 1700, 1400, 1100, 2629, 934 }; +static const l_int32 xp2[] = { 850, 400, 1100, 1664, 487 }; +static const l_int32 yp2[] = { 850, 500, 1300, 2432, 804 }; +static const l_int32 xp3[] = { 450, 200, 400, 183, 61 }; +static const l_int32 yp3[] = { 300, 300, 400, 490, 83 }; +static const l_int32 xp4[] = { 850, 1000, 1100, 1664, 487 }; +static const l_int32 yp4[] = { 350, 350, 400, 532, 114 }; + +int main(int argc, + char **argv) +{ +PIX *pixs2, *pixs3, *pixb1, *pixb2, *pixb3; +PIX *pixr2, *pixr3; +PIX *pixc1, *pixc2, *pixc3, *pixcs1, *pixcs2, *pixcs3; +PIX *pixd, *pixt1, *pixt2, *pixt3; +PTA *ptas1, *ptas2, *ptas3, *ptad1, *ptad2, *ptad3; +L_REGPARAMS *rp; + + if (regTestSetup(argc, argv, &rp)) + return 1; + + pixc1 = pixRead("test24.jpg"); + pixc2 = pixRead("wyom.jpg"); + pixc3 = pixRead("marge.jpg"); + + /* Test alpha blend scaling */ + pixd = pixCreate(900, 400, 32); + pixSetAll(pixd); + pixs2 = pixScaleWithAlpha(pixc2, 0.5, 0.5, NULL, 0.3); + pixs3 = pixScaleWithAlpha(pixc3, 0.4, 0.4, NULL, 0.7); + pixb1 = pixBlendWithGrayMask(pixd, pixs3, NULL, 100, 100); + pixb2 = pixBlendWithGrayMask(pixb1, pixs2, NULL, 300, 130); + pixb3 = pixBlendWithGrayMask(pixb2, pixs3, NULL, 600, 160); + regTestWritePixAndCheck(rp, pixb3, IFF_PNG); /* 0 */ + pixDisplayWithTitle(pixb3, 900, 100, NULL, rp->display); + pixDestroy(&pixd); + pixDestroy(&pixs2); + pixDestroy(&pixs3); + pixDestroy(&pixb1); + pixDestroy(&pixb2); + pixDestroy(&pixb3); + + /* Test alpha blend rotation */ + pixd = pixCreate(1200, 800, 32); + pixSetAll(pixd); + pixr3 = pixRotateWithAlpha(pixc3, -0.3, NULL, 1.0); + pixr2 = pixRotateWithAlpha(pixc2, +0.3, NULL, 1.0); + pixb3 = pixBlendWithGrayMask(pixd, pixr3, NULL, 100, 100); + pixb2 = pixBlendWithGrayMask(pixb3, pixr2, NULL, 400, 100); + regTestWritePixAndCheck(rp, pixb2, IFF_PNG); /* 1 */ + pixDisplayWithTitle(pixb2, 500, 100, NULL, rp->display); + pixDestroy(&pixd); + pixDestroy(&pixr3); + pixDestroy(&pixr2); + pixDestroy(&pixb3); + pixDestroy(&pixb2); + + pixcs1 = pixScale(pixc1, 0.35, 0.35); + pixcs2 = pixScale(pixc2, 0.55, 0.55); + pixcs3 = pixScale(pixc3, 0.65, 0.65); + + /* Test alpha blend affine */ + pixd = pixCreate(800, 900, 32); + pixSetAll(pixd); + MakePtas(2, 3, &ptas1, &ptad1); + MakePtas(4, 3, &ptas2, &ptad2); + MakePtas(3, 3, &ptas3, &ptad3); + pixt1 = pixAffinePtaWithAlpha(pixcs1, ptad1, ptas1, NULL, 1.0, 300); + pixt2 = pixAffinePtaWithAlpha(pixcs2, ptad2, ptas2, NULL, 0.8, 400); + pixt3 = pixAffinePtaWithAlpha(pixcs3, ptad3, ptas3, NULL, 0.7, 300); + pixb1 = pixBlendWithGrayMask(pixd, pixt1, NULL, -250, 20); + pixb2 = pixBlendWithGrayMask(pixb1, pixt2, NULL, -150, -250); + pixb3 = pixBlendWithGrayMask(pixb2, pixt3, NULL, -100, 220); + regTestWritePixAndCheck(rp, pixb3, IFF_PNG); /* 2 */ + pixDisplayWithTitle(pixb3, 100, 100, NULL, rp->display); + pixDestroy(&pixd); + pixDestroy(&pixb1); + pixDestroy(&pixb2); + pixDestroy(&pixb3); + pixDestroy(&pixt1); + pixDestroy(&pixt2); + pixDestroy(&pixt3); + ptaDestroy(&ptas1); + ptaDestroy(&ptas2); + ptaDestroy(&ptas3); + ptaDestroy(&ptad1); + ptaDestroy(&ptad2); + ptaDestroy(&ptad3); + + /* Test alpha blend projective */ + pixd = pixCreate(900, 900, 32); + pixSetAll(pixd); + MakePtas(2, 4, &ptas1, &ptad1); + MakePtas(4, 4, &ptas2, &ptad2); + MakePtas(3, 4, &ptas3, &ptad3); + pixt1 = pixProjectivePtaWithAlpha(pixcs1, ptad1, ptas1, NULL, 1.0, 300); + pixt2 = pixProjectivePtaWithAlpha(pixcs2, ptad2, ptas2, NULL, 0.8, 400); + pixt3 = pixProjectivePtaWithAlpha(pixcs3, ptad3, ptas3, NULL, 0.7, 400); + pixb1 = pixBlendWithGrayMask(pixd, pixt1, NULL, -150, 20); + pixb2 = pixBlendWithGrayMask(pixb1, pixt2, NULL, -50, -250); + pixb3 = pixBlendWithGrayMask(pixb2, pixt3, NULL, -100, 220); + regTestWritePixAndCheck(rp, pixb3, IFF_PNG); /* 3 */ + pixDisplayWithTitle(pixb3, 300, 100, NULL, rp->display); + pixDestroy(&pixd); + pixDestroy(&pixb1); + pixDestroy(&pixb2); + pixDestroy(&pixb3); + pixDestroy(&pixt1); + pixDestroy(&pixt2); + pixDestroy(&pixt3); + ptaDestroy(&ptas1); + ptaDestroy(&ptas2); + ptaDestroy(&ptas3); + ptaDestroy(&ptad1); + ptaDestroy(&ptad2); + ptaDestroy(&ptad3); + + /* Test alpha blend bilinear */ + pixd = pixCreate(900, 900, 32); + pixSetAll(pixd); + MakePtas(2, 4, &ptas1, &ptad1); + MakePtas(4, 4, &ptas2, &ptad2); + MakePtas(3, 4, &ptas3, &ptad3); + pixt1 = pixBilinearPtaWithAlpha(pixcs1, ptad1, ptas1, NULL, 1.0, 300); + pixt2 = pixBilinearPtaWithAlpha(pixcs2, ptad2, ptas2, NULL, 0.8, 400); + pixt3 = pixBilinearPtaWithAlpha(pixcs3, ptad3, ptas3, NULL, 0.7, 400); + pixb1 = pixBlendWithGrayMask(pixd, pixt1, NULL, -150, 20); + pixb2 = pixBlendWithGrayMask(pixb1, pixt2, NULL, -50, -250); + pixb3 = pixBlendWithGrayMask(pixb2, pixt3, NULL, -100, 220); + regTestWritePixAndCheck(rp, pixb3, IFF_PNG); /* 4 */ + pixDisplayWithTitle(pixb3, 500, 100, NULL, rp->display); + pixDestroy(&pixd); + pixDestroy(&pixb1); + pixDestroy(&pixb2); + pixDestroy(&pixb3); + pixDestroy(&pixt1); + pixDestroy(&pixt2); + pixDestroy(&pixt3); + ptaDestroy(&ptas1); + ptaDestroy(&ptas2); + ptaDestroy(&ptas3); + ptaDestroy(&ptad1); + ptaDestroy(&ptad2); + ptaDestroy(&ptad3); + + pixDestroy(&pixc1); + pixDestroy(&pixc2); + pixDestroy(&pixc3); + pixDestroy(&pixcs1); + pixDestroy(&pixcs2); + pixDestroy(&pixcs3); + return regTestCleanup(rp); +} + + +static void +MakePtas(l_int32 i, + l_int32 npts, /* 3 or 4 */ + PTA **pptas, + PTA **pptad) +{ + + *pptas = ptaCreate(npts); + ptaAddPt(*pptas, x1[i], y1[i]); + ptaAddPt(*pptas, x2[i], y2[i]); + ptaAddPt(*pptas, x3[i], y3[i]); + if (npts == 4) ptaAddPt(*pptas, x4[i], y4[i]); + *pptad = ptaCreate(npts); + ptaAddPt(*pptad, xp1[i], yp1[i]); + ptaAddPt(*pptad, xp2[i], yp2[i]); + ptaAddPt(*pptad, xp3[i], yp3[i]); + if (npts == 4) ptaAddPt(*pptad, xp4[i], yp4[i]); + return; +} diff --git a/leptonica/prog/amoris.2.150.jpg b/leptonica/prog/amoris.2.150.jpg Binary files differnew file mode 100644 index 00000000..0e251068 --- /dev/null +++ b/leptonica/prog/amoris.2.150.jpg diff --git a/leptonica/prog/aneurisms8.jpg b/leptonica/prog/aneurisms8.jpg Binary files differnew file mode 100644 index 00000000..97432588 --- /dev/null +++ b/leptonica/prog/aneurisms8.jpg diff --git a/leptonica/prog/arabic.png b/leptonica/prog/arabic.png Binary files differnew file mode 100644 index 00000000..2cd43f35 --- /dev/null +++ b/leptonica/prog/arabic.png diff --git a/leptonica/prog/arabic2.png b/leptonica/prog/arabic2.png Binary files differnew file mode 100644 index 00000000..80180539 --- /dev/null +++ b/leptonica/prog/arabic2.png diff --git a/leptonica/prog/arabic_lines.c b/leptonica/prog/arabic_lines.c new file mode 100644 index 00000000..d4a95db8 --- /dev/null +++ b/leptonica/prog/arabic_lines.c @@ -0,0 +1,166 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * arabic_lines.c + * + * Demonstrates some segmentation techniques and display options. + * To see the results in one image: /tmp/lept/lineseg/result.png. + * + * This demonstration shows many different operations. However, + * better results may be obtained from pixExtractLines() + * which is a much simpler function. See testmisc1.c for examples. + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + + +/* Hit-miss transform that splits lightly touching lines */ +static const char *seltext = "xxxxxxx" + " x " + " x " + " x " + " x " + " x " + " x " + " x " + "o X o" + " x " + " x " + " x " + " x " + " x " + " x " + " x " + "xxxxxxx"; + +int main(int argc, + char **argv) +{ +l_int32 w, h, d, w2, h2, i, ncols, same; +l_float32 angle, conf; +BOX *box; +BOXA *boxa1, *boxa2; +PIX *pix, *pixs, *pixb, *pixb2; +PIX *pix1, *pix2, *pix3, *pix4; +PIXA *pixam; /* mask with a single component over each column */ +PIXA *pixa, *pixa1, *pixa2; +PIXAA *pixaa, *pixaa2; +SEL *selsplit; +static char mainName[] = "arabic_lines"; + + if (argc != 1) + return ERROR_INT(" Syntax: arabic_lines", mainName, 1); + + setLeptDebugOK(1); + lept_mkdir("lept/lineseg"); + pixa = pixaCreate(0); + + /* Binarize input */ + pixs = pixRead("arabic.png"); + pixGetDimensions(pixs, &w, &h, &d); + pix = pixConvertTo1(pixs, 128); + pixDestroy(&pixs); + + /* Deskew */ + pixb = pixFindSkewAndDeskew(pix, 1, &angle, &conf); + pixDestroy(&pix); + lept_stderr("Skew angle: %7.2f degrees; %6.2f conf\n", angle, conf); + pixaAddPix(pixa, pixb, L_INSERT); + + /* Use full image morphology to find columns, at 2x reduction. + This only works for very simple layouts where each column + of text extends the full height of the input image. */ + pixb2 = pixReduceRankBinary2(pixb, 2, NULL); + pix1 = pixMorphCompSequence(pixb2, "c5.500 + o20.20", 0); + boxa1 = pixConnComp(pix1, &pixam, 8); + ncols = boxaGetCount(boxa1); + lept_stderr("Num columns: %d\n", ncols); + pixaAddPix(pixa, pix1, L_INSERT); + boxaDestroy(&boxa1); + + /* Use selective region-based morphology to get the textline mask. */ + pixa2 = pixaMorphSequenceByRegion(pixb2, pixam, "c100.3 + o30.1", 0, 0); + pixGetDimensions(pixb2, &w2, &h2, NULL); + pix2 = pixaDisplay(pixa2, w2, h2); + pixaAddPix(pixa, pix2, L_INSERT); + pixaDestroy(&pixam); + pixDestroy(&pixb2); + + /* Some of the lines may be touching, so use a HMT to split the + lines in each column, and use a pixaa to save the results. */ + selsplit = selCreateFromString(seltext, 17, 7, "selsplit"); + pixaa = pixaaCreate(ncols); + for (i = 0; i < ncols; i++) { + pix2 = pixaGetPix(pixa2, i, L_CLONE); + box = pixaGetBox(pixa2, i, L_COPY); + pix3 = pixHMT(NULL, pix2, selsplit); + pixXor(pix3, pix3, pix2); + boxa2 = pixConnComp(pix3, &pixa1, 8); + pixaaAddPixa(pixaa, pixa1, L_INSERT); + pixaaAddBox(pixaa, box, L_INSERT); + pix4 = pixaDisplayRandomCmap(pixa1, 0, 0); + pixaAddPix(pixa, pix4, L_INSERT); + lept_stderr("Num textlines in col %d: %d\n", i, boxaGetCount(boxa2)); + pixDestroy(&pix2); + pixDestroy(&pix3); + boxaDestroy(&boxa2); + } + pixaDestroy(&pixa2); + + /* Visual output */ + pix2 = selDisplayInPix(selsplit, 31, 2); + pixaAddPix(pixa, pix2, L_INSERT); + pix3 = pixaDisplayTiledAndScaled(pixa, 32, 400, 3, 0, 35, 3); + pixWrite("/tmp/lept/lineseg/result.png", pix3, IFF_PNG); + pixDisplay(pix3, 100, 100); + pixaDestroy(&pixa); + pixDestroy(&pix3); + selDestroy(&selsplit); + + /* Test pixaa I/O */ + pixaaWrite("/tmp/lept/lineseg/pixaa", pixaa); + pixaa2 = pixaaRead("/tmp/lept/lineseg/pixaa"); + pixaaWrite("/tmp/lept/lineseg/pixaa2", pixaa2); + filesAreIdentical("/tmp/lept/lineseg/pixaa", "/tmp/lept/lineseg/pixaa2", + &same); + if (!same) + L_ERROR("pixaa I/O failure\n", mainName); + pixaaDestroy(&pixaa2); + + /* Test pixaa display */ + pix2 = pixaaDisplay(pixaa, w2, h2); + pixWrite("/tmp/lept/lineseg/textlines.png", pix2, IFF_PNG); + pixaaDestroy(&pixaa); + pixDestroy(&pix2); + + return 0; +} + diff --git a/leptonica/prog/arithtest.c b/leptonica/prog/arithtest.c new file mode 100644 index 00000000..75fac589 --- /dev/null +++ b/leptonica/prog/arithtest.c @@ -0,0 +1,83 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * arithtest.c + * + * Test the pixacc functions, using an 8 bpp image and converting + * back and forth between 8 and 16 bpp. + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + +int main(int argc, + char **argv) +{ +char *filein; +l_int32 w, h; +PIX *pixs, *pix1, *pix2, *pix3, *pix4, *pix5; +static char mainName[] = "arithtest"; + + if (argc != 2) + return ERROR_INT(" Syntax: arithtest filein", mainName, 1); + filein = argv[1]; + + setLeptDebugOK(1); + lept_mkdir("lept/arith"); + + if ((pixs = pixRead(filein)) == NULL) + return ERROR_INT("pix not made", mainName, 1); + + /* Input a grayscale image and convert it to 16 bpp */ + pixGetDimensions(pixs, &w, &h, NULL); + pix1 = pixInitAccumulate(w, h, 0); + pixAccumulate(pix1, pixs, L_ARITH_ADD); + pixMultConstAccumulate(pix1, 255., 0); + pix2 = pixFinalAccumulate(pix1, 0, 16); + l_pngSetReadStrip16To8(0); + pixWrite("/tmp/lept/arith/pix1.png", pix2, IFF_PNG); + + /* Convert it back to 8 bpp, linear mapped */ + pix3 = pixMaxDynamicRange(pix2, L_LINEAR_SCALE); + pixWrite("/tmp/lept/arith/pix2.png", pix3, IFF_PNG); + + /* Convert it back to 8 bpp using the MSB */ + pix4 = pixRead("/tmp/pix1.png"); + pix5 = pixConvert16To8(pix4, 1); + pixWrite("/tmp/lept/arith/pix3.png", pix5, IFF_PNG); + + pixDestroy(&pixs); + pixDestroy(&pix1); + pixDestroy(&pix2); + pixDestroy(&pix3); + pixDestroy(&pix4); + pixDestroy(&pix5); + return 0; +} diff --git a/leptonica/prog/autogen.137.c b/leptonica/prog/autogen.137.c new file mode 100644 index 00000000..f414eee9 --- /dev/null +++ b/leptonica/prog/autogen.137.c @@ -0,0 +1,98 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * autogen.137.c + * + * Automatically generated code for deserializing data from + * compiled strings. + * + * Index Type Deserializer Filename + * ----- ---- ------------ -------- + * 0 PIXA pixaRead chars-6.pa + * 1 PIXA pixaRead chars-10.pa + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include <string.h> +#include "allheaders.h" +#include "autogen.137.h" + +/*---------------------------------------------------------------------*/ +/* Auto-generated deserializers */ +/*---------------------------------------------------------------------*/ +/*! + * \brief l_autodecode_137() + * + * \param[in] index into array of functions + * \return data struct e.g., pixa, in memory + */ +void * +l_autodecode_137(l_int32 index) +{ +l_uint8 *data1, *data2; +l_int32 size1; +size_t size2; +void *result = NULL; +l_int32 nfunc = 2; + + PROCNAME("l_autodecode_137"); + + if (index < 0 || index >= nfunc) { + L_ERROR("invalid index = %d; must be less than %d\n", procName, + index, nfunc); + return NULL; + } + + lept_mkdir("lept/auto"); + + /* Unencode the selected string, uncompress it, and read it */ + switch (index) { + case 0: + data1 = decodeBase64(l_strdata_0, strlen(l_strdata_0), &size1); + data2 = zlibUncompress(data1, size1, &size2); + result = (void *)pixaReadMem(data2, size2); + lept_free(data1); + lept_free(data2); + break; + case 1: + data1 = decodeBase64(l_strdata_1, strlen(l_strdata_1), &size1); + data2 = zlibUncompress(data1, size1, &size2); + result = (void *)pixaReadMem(data2, size2); + lept_free(data1); + lept_free(data2); + break; + default: + L_ERROR("invalid index", procName); + } + + return result; +} + + diff --git a/leptonica/prog/autogen.137.h b/leptonica/prog/autogen.137.h new file mode 100644 index 00000000..81d4e487 --- /dev/null +++ b/leptonica/prog/autogen.137.h @@ -0,0 +1,306 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * autogen.137.h + * + * Automatically generated function prototype and associated + * encoded serialized strings. + */ + +#ifndef LEPTONICA_AUTOGEN_137_H +#define LEPTONICA_AUTOGEN_137_H + +/*---------------------------------------------------------------------*/ +/* Function prototype */ +/*---------------------------------------------------------------------*/ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +void *l_autodecode_137(l_int32 index); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +/*---------------------------------------------------------------------*/ +/* Serialized strings */ +/*---------------------------------------------------------------------*/ +static const char *l_strdata_0 = + "eJy1mgtUE1cax+9kQh4wIREQBhAyQCoPFYd3UEjCQ0RtC1prbbUyaBWsVvDRFRRIAjSgSwta" + "16q1Ilq7PrpdtN3W1q1OHCtUEcTXqu0KwSpY2yWIj4Ah2aA1xJ3NIeM5cg6gnJwzv9x78/99" + "97vXOXNxQTY2a+GKlYvzlmGRzi+/+878hSuwvEVY/uICLBGLj3F2Ts6z85L5eQULV1pehDsP" + "vnoO/uYErGDF47+MxQr/+JfzusyXJwucfZwBAIIp6akzLL85lm8UsvwAPUsOulp+8fPTX18J" + "nnx9Mn905KNXpybN5G1dYKAUbmwQ97JX3Sulc28MvmDKpJdTv0gmSh89NmLosRGR+NCTB//z" + "/x4OWx/ulbxm6tDDD1cNfkNN94+Mt/zR+4+HF5B6FeQ3VpVcs501+xcIYQFK76xehk69RgOJ" + "ZAjCtYL477uKDwdiaNBXJ5VqWbzVQBeuURoCwHc/elR3HQicSAOJYggisILw/zy1zx5I8BMQ" + "cxlUKWtR1fkhbeNQHxTdMQcTwVzqW+dV7FZeCtjFCriRcYa4TcOKZojlYsVi/2XCUXtYyY+x" + "/E5HCEjMA7ROC9t9+oHau2iVlruoZsXFs3WU+A2s8Lrf3xN2Ve3kLtzvEX+jZlZEeuPXc8+7" + "1sxZcaztDnwp14+tN95g04hjGBK7W4nx3x7uskecYR1IMwTz5KYBVfbNTi4S26Y2xIuOcTt6" + "FQcfClHXFu7+K8ITnnzE/OeRqGlPHG4svEbqvSqVrJ7uFmekVinBiyq2vVcOFX0Qz+1eA++g" + "4ccyxHez4reF12y3h//iED6Aeea9clL/owlQK0NKOL/IwXo5u6OBi6KurJ6qFi66VHHYAMo+" + "6Yc4hSXYMhl5tpkk83eSap1ZXvl6OgpSODiVMcadvobjGLI7Wdl95joL7LGPesKu1at0gOJr" + "XDXeyEQ0DC1prwDtx0ZGnM96J4vGImXIYi/enmYJssabXq3jU96aichKVaZGy3Fh//gztL/w" + "uN4JyFyQf//eXhJDQ4p/LkijrUiZFEHhFTpEJIOOcxUGiC8Dfy59qxP/LXsvBH444v5CWOoX" + "8+lRjDPE4lmxunepv7eHhT3BatHX6qLKIsqkFIS9xT0kiyrKMVS7sMCBLPfzGzKcd9GBmMrB" + "sSj0tIlCwcAPCoUqtHK/C5ijHudzJaNYRsdgqgbHpsuqBkollhFSVnkOehPUCSgxCO4fuRBe" + "HJBMJ2HqBsdmyM06Qyq/WByf784Ffi2eS9E4VyUdgakHHBO2u1XYKnEYjoOI7UJwJcutTtLe" + "N4POwDTZHXNRonVdqHRKmDI7IeaRiq4sFm+gECQrxbixiNQ/hKgcfI1rWqe2ywRr+oTofTlR" + "z32bGwD+dDH4/Q19aafotEyD3DHacUO0UKV/AiH9iMSz1NkyuCxRFEMk3VF8Cmac/4jMB5+7" + "8CFQwfflb/xMcIZOxzSqna10t1+brrJHJ35Cp7TQycSEtEiVhDZhnBgcV0QfF4FVW0ZfjS/v" + "uETnYRrXiJXn5pSABns8MutoqS2j5YFHo3iTO3FZmOqOmlJqIMrM0ijFqKmEMPSpdb1cTacY" + "bVYSuQSAKtNQFmjeF9TShGN/o+MyjXLHJjf+fye3hsQz1NlydOA1wvARqe+EKC72sdqyTD0u" + "xuGXx+BN04hccDs5GRS3BXiVfbMtnUYayTTdHRvYCY9JY05r+Spc5NQaWhg2NXRzjduM0rH+" + "kspUr81F13qEWTWb/xl5Y8O0ZfF7TteMrrhwZxYr7OeST7UB8/SrwrfTUZnmvmODGm47qK64" + "6uwAl7cqQK1TsahEjsasuKBS3HdGet1QH/K7GhH4+6XABF59Kd3ekUx94BhetC2eSfIobowQ" + "VYhvE6ax+EiRM3IHQe4LeNFZ6rrxah2Y7eXGAu9eERfwswwv0iGZqsKx6Y63/RxZzFlXAqd8" + "D6UUQ5Qc67esS5jKwPuRtBY5PspM5pvgFDOXU1gfLmGDvxe9ENgv95pMJ30+O4vY//kIdU0j" + "6l9TBX7L1nzNRbjqDr6lXpvL4azF3gZBTppCPsJ9NOvrq3xli3/722k6JlPpOBaUf3x+Jp3W" + "ChQKwCb3pY75grydFHppmt/b+o2VEyWBW7tzl/+0y/OViH7BTE+f1wq3Lz/hv6Qpz7jqrcW+" + "/zq69hROR2VqnMG9k9fjEW08f3M4RxtIlXPwoKNdZaBe4BYRcGd+NZ3hWbYAjxluOx++bI9h" + "aAugchYCHSwxwfWN/EfbgLGg86L7vgIZSpdKJFOpCKwwhn8bxg6v4DLIL5EwtJH6jFLdZCeK" + "EiO/y9FftJIagQe0Hl6Y9LboDTB3TnBsVm3hv+l0TB3iGJ27DZ2Qxfp86Uw22D4mNJWddq6T" + "xhDF1A6OMeC2pfYVM9Fu1uYbuFSFGFGORU0rcaNl+3kMPmECnp3cA0nnWCDOfbR/R8woFh2Q" + "qRP4VsCe2NmzhgndSacO8gGGOLX6/jT16Pn49Xv28OZXHRTNW5m/JX9SuqSxPvvWtvmVo9cU" + "/DVHcN/vgr+/aGl14nk6JFMzjLBC/pCx1W5xnGkdxWNqqFypj8OLin62pGsOTBmVAuThBRQd" + "e9Ubda6OwiVl+niO5q5MtIzI7H6HuCz5kcSvi2CqTy5AhHLWvS9TmpKOA8HZkKmJBzI/pr8B" + "ptZws76B8ILAKfbewLTHbyCx6YhAkQkUrR+HVGV7BPlow7555eiIdI+pG17Td4iTl1+lCk/t" + "3nT9lcZZp+dNcT4U68bduvZWpPeuqg/LJb8H3hvX3X5snteeabGLl7gs+j9LmKlHHFvCEbaN" + "M1SCNq/Gt8uhFMXXbAraiXGpPhjpFGN17tg+jgunMg1ngZdaA955ee6Ii3RCpgoRWQnD3r+z" + "anjT1VpqbRxPMFrWxniqCOtvwcy1Wn/+j2UjMv9pllM9ZkRYghuJt1S57CDw5edBrZn7rjTT" + "MZnqw7FVHPXUKva+7Is2yzkdtQojt9wbbTZT6qQVWIxcZQgSiZcRue0VW8rKoTFnwrdMjtyI" + "0BmZ6sXVyuj+a8p4e4zjrYwVUKWqvY+L9x/XG4VUbxx214BQsH+Ir4SXKt+5V62Gdo2oAkG3" + "gr0nHtlaTOd7PsYJsV2Mg3xov1ZvdOIlyrR6FXyKww8M4NSHWzYsAd7B0w+cn/F/ustMZePY" + "5E58anLNeDReZDxP5huzYKoY2yH0+LKh9IYYxxvN4BR88X7ZBbgHxkxaEMHlw2DRG+ODj6yQ" + "5NFYo5lKaaSVtenTeLs9eWufzGzmwrwo0Npr9pzdA3NcNA3m+tNaPF3eNDaEA1q2RS69B2We" + "oGMxVRHPiuV/NyrXHpanTZ9MrdbFz2sk9WIW9F2se7lr1heb6BhMZeOYEa1tqTYSpAoQpNa3" + "ManNFzX4gpeaxR+nbt8ZTid5PtaY/FSrOspIEAWmPkD1diqK/Cs74YMDkCbnHhfdAW6IVbmY" + "+dsE0QO4ZzlWgpwQqw3cTLOYw9nyeiYCFvnEhCxYsLSXzs3UGEIrtzEkZIQ9bj8rd7XFGKaI" + "hGDOgGoX/CIiep9ggz3rwni/v5XhS6dhagdPK03wh6VR9mheGhpFIcz70pxHSE1ZnCqh+cPs" + "w8Y8V+oH+Up0mekTKh+u7DayO36NRx6sV18ucqWK38VucjtKsB3yCvWAPww/+lC4yyPvXnZn" + "0euzaKbScLfSa7+bstoe/aSnTlt6zdkWerlah4uy2B2+mUV/lal1O4pZVHEh9h9ux58wmeuJ" + "arXFIGYVcV/OV6x0Q4mbUATY/A+8Tyj8pZxOzVQjjq1cxdOHLISlytXrIE2v3BVvMl8ncbMY" + "LkvkmSf/cAczCiXd5FlzN6B6jimKawP6sxclRQD+xfBFGYVLwujATL3imPfG2nrPpwDdIc4u" + "MKl0Fr+ssfgPoaK8NZ3KeuyxW1LiQ7wSXTado8MxdQuj6vHVpoMCFSZK0300W8rZ3aj5gAxT" + "5txCTjiFBGgnfnuu48C8O/ledd27Zi1fPX3RZ+gorXlGfdfW8yfurc+p/Jo/7XQ/QvqKu5pC" + "7ybzUDGNPYapaxyrzaS2tZmPwXuHeFGBaYuuLwdd06yvqtWtS6SiCjWdigsteqP0xTOTORrx" + "45i4tlDSxv9n2FY6KFP7IFZQL/GHbsMLfLBBysPvZhCX5Wqtf6VMJTJzORqWBmYhShQ1xVk2" + "bSD5niJandSsUkOfu2jAT/5+v87O2sajszJVlGMBGzQUsDqTnIPV78uuP5C998ACw2R2P9kA" + "LvBSwAh2gMumL6EOOhNTWTkWVKFPBdVjWcnVBUZhqdhcSOp1nbBG3CRaWYODD+LjRk1qNV+g" + "kzHVkWOlmeLpuluJ46PM58HJajOrp4WjaTnmi8pKNO3iNrWhEKZqHyh+ayP14/0rbwQYjiV6" + "mCdrAWKOGPjTgT56nzaGqbFQK3D8G4dU9oBtjqjllqFUmix1ZG+G5rol2XV5mk6uPCpBxj8R" + "pyo4uVrTsvac1rD7TRnVMKFYI3zXiMhNZfUJqNkor4UWeXrAwHN53KVtIe+J6PBMheXYBz71" + "ST/8UVgpWtsiOLulu4J+lm5CkrLXeTljO4MjAgp/p6qWHk4Ky50UNe5ceaHe9FnniP4p/Avk" + "XyrX//z54WKhcHRuzrekPx2aqa8cgx7q6tbqjErO/WNIgxlPMJ3R90VRDZ2I/FqUUdqiD96h" + "q02g5Gs1ZrSLOxHODEIgcPtBkCmoMzWOTspUVI6RJg0dN5CYB7v1lmTPp9HT6vcoXDf38Ge1" + "j9v5235uxWq/pd8VYD7T13l5be957z/vSErONwXvDwkUzlqSMPp+5QvJOD+/m07M1F6OdSyf" + "tOEIwOJjX2Eg6W0UvLoM1s0x3HyHxhDL1EKO9cIThnrhWhNEmbhIr7YrAU3k7u4WojI5YRhQ" + "6YLRAWi3ko/dFVd6oKbxg91MEK0zw2DjleD3R/+aSC9YY5maaPBc3PsR7IS4+QeGHbBsS4Ym" + "S9j7BmDQGuN2McQHe53OwNQwAivD8X9tnWuPYYztPrtE1fpXZ02LJ9IyDr3WQkjlZdkmvuiQ" + "kgTTU3gQCPUZc6shbtIYOtuz3OQanm3EEJvajc3GY4H/8vGhmYlx9IyLZWoUJytBK7iy1x6B" + "zT2cUh30xz0cN8QTkfOSQO/0kcud+sZ8SId5llP7xzAtP97ytQdjew7unlhE4p0QdZStURJ3" + "scFzMq1r1VI3VOKGXkXxdyGwhZLkYdNuvEGnY6oDxybLpnuoFlc1B9VFeSLBUvSD1fgoOZlv" + "gtwmaPNNnJQjTikpTpZEDWOB4orgyR8LUr+iEzLNfr6V8HRC/Gh7hMFD+33VOlk0vn0BsUWY" + "dl/Ak7SR+DF13SdqHQR/Fg7m4H4j/P82ir77j32WVhejkdMdY1NyvsYcJepqQDQr3ZDeHFVN" + "ottGbiBfc9Qb4fqgCp/pIqB9IaAtMOW2gE74LIf0w6+8MNuVV5xOFHxB5u9QZ5fAPEhthEW/" + "cndfFyBCj8Flt6xB8tO6T/voZz9xz3Ln6jGaxDQDtYcmHuollelgaq2mN/NyI8nLobAoSslm" + "g/90eTi7JX+0jc7zLFeuhp9MqU2euicatPkadbY/t+x7J4+eV/FoIyG1TLJJqOHwRRPatJiy" + "VOtfugi/O8ey9+OJg7tiN0XTQZkGv6sVNLQ9MMse6FCDtaLOLITNYk3v3q5yhNL5a67noM0L" + "Upq4qMpn+ghwlRMakXKqposOxjT1HbOiNXMp/eDFvmvZqvoCMmFmI9hclgwMWo/pr865sIwO" + "83wE4DskgDIdhJbOFqM+OxN+07MpAQg5O7L16JwtA3QWpvnv2NIaOv0oqxvgwg+Fms7GLkD1" + "cjSdFmOHoTuMRIEBTmVdUWzojFIcOiN8PH8P5oZeWztmDf1kIY6pCLhWzIv3+H+xh2nt7jac" + "PUme1CPjlxKGChV4uGFkYXt6/kw6BtO0H2nFuP/FbMWwaT/Y+w4v8q+MR8aiH3w5Dd/eXavN" + "L5EtazpxTXV6FPimY2Kq+na/kM71LA2o4T93ATYNKPfvzRQZQOUfrtAZvDW9l0W90ItvgskL" + "ww4euaKU0omYpjtiJRo38s784dNdbYmsEEKaQ+JZKu1RqMpVscEIafrc0asChTO+ypLu1ZKD" + "3Ia0cTQ0KdN0d2ywwp8arA+z23XZ0qJynQHW9IprzrprevNQ15ZsKUHlm4Q+LBC1M/Qfv4Zl" + "0MNe+nzC3vaQyn2gkiho0eYrOZTRG7mfnu5f1S9BXZsIQ/UHoLwjiB958usHdLBnOdoYvtTB" + "bEud5mg8H8dHLSGk18h8f9/5J3e5gJ8TA6CZGyPpOSplGuqOAY2zBXKNxZsWE/VLiPo8oiaP" + "IJYSubmEgSQzuWmxxAjkTTCzddRH+x9ceoFOxzTlHYusQGtkgdJutDniLtQTr+FwOPj7qgrU" + "P8KYogA9GR4fR/Qlv0RHej5hj9kurU/kWrIFCjy401WzYJSlChwstEK+CiXXRT+6tvw/QM+n" + "vh9vCxQRpzrb54405OEJtVp9AZfKcdG0jETEY9ASI6iTz7ZEBfZy2D8iN4XQ7zRLmea9h5XP" + "e2lUiT0++VDew3B4U1GtWt03Cqb6THyk4WEcnpATRxTsmEfqQwSV4mLCoL8FUw1ChbEXplpq" + "pWcgcPU92cLaoHZ66kqf5Z7u8KmL26buvTi8PoMoWEbqD6t0FFcjJu7WqXRzIGqiJelYyB3B" + "lu9A38qQNL/GYPqGTspUC45lr8w2e2O+wfE4y06Oyje6Ur3xSPUDvOhrqK46BpGruoRUrRxR" + "mnEje3ebEpWZs3PNMMCPh8VdO6faTcONf5brucOPZ7TtePqJiK4cYkseibeodBkQVS1E5HK8" + "yETqDTDVAyMDltoWpHiBK28E33pdtG4SHZKpMBwrJ32s5WR+aTaH8xVIfrHVHRGillVdHCFU" + "izek0e8XxjNVBGRFuXy78Jw9FOEfKLkExonGMBB2CFZPeHU5/RgmnqkR2Nbny44f2mzv+dbT" + "d5IgcQj2twzFdFjD0ghB7nLX6TcbX6EfG8Q/y72n4ZPN1ybZ5BMMquyTfM5EPuuUyQzAJWP4" + "xunS9L22LP8FbV4rjQ=="; + +static const char *l_strdata_1 = + "eJy1nAdUE1n7hyckJICBhCIEKQlFQEVJRCmCJEBoNooNG4YioqKCCuKKKQRCF0SKWAARFEUE" + "xFXswQRBRQHLisoqAdsqSmLBKIH546qB7z9fzsfsOetRgzk5Z55n5s79vfedG9X81sUFk5as" + "2bJ13eZNpOlqC2I2hqzZQtocTopaF0eaTXKcqabmtlnBR0I2x63ZOvwhstr3T68gr5pFitvy" + "4x1r0o6fP6ml+i3wUleboAYAgLqPNz1g+PX7z5aI4b8A453PpcMvqlHey7YCv34dCrGYPvyi" + "4UN3XaRSGCplsTnvVYC8R/QJoVeEEd8/4eOxgH7KjZHw93EpI8elTCePHPr7P/7b0ZXlR++L" + "uhozcvT6jO9/EC39F22G37T4dfQGMVeEcEciUTP4wRg1ZwTPnsBkB2MW7cLk4pIBxjiCxHnX" + "xUwI1XSYVOPkVJLzWdcVUZF+UYHs4CtKSCoSSUSmoEq/Rp0BEtlqFZnAutNOhel+4X0QHluY" + "POPlPM1PXQ4p4qH94Nl4+7A6YIL3aLCsLlu4ckWK9qc5yqiPjWjvJYBqSrt737VdNlN7Td9l" + "dVhwbLXvGjmf0jFaP97R5uMVAx/tFdUt7CM2EN4ZMHm15byN/AWPFfEG/+D1uF2rzibpJIps" + "dfMzALMIL9eoPPu0Q+VTHp2/PnclH+Fd5IXQWR3zdWvNqvbcZRJXiWfDXtRa3ZXPJ7+/7WZr" + "tCDa96abH54xhZH6oeuAjneX2UDmxsEPPRfr3mPK9R3/ipg5NxIiNBOmEFEu9Ex2apEiobU/" + "hJLu/C2EaqNyzJotLhTm5mfw7QJOJ7QnLHFf4+aAMz1jV33h4kGgWanM+iLztINHRirxZtLu" + "vsDTj7UKUyduumsYqKI1wXdC82XV7h0601yj1J/V5mkVTokMO+QZUD0oUXrbzJkk3fB8IkTL" + "DqaWkVzriSpznSKt+B9aMXdMNK7RdDzaCxYtYqa/tYtapZROYyxzO5C2qRKFuEVgIO/dv2Sx" + "t3BILwfNdXyTlh6gJnkx7TfL1YfMmw8tbgnR1IsOeJhydhtjHMnuzpMgX+dIi+vtta6ddKmD" + "pLfG4k3YgljeSs1dbkIdS9IiEbB8VverPpwBX7L9FWp2+SuIqz1MVxW564TdMxoVuZr/uqdb" + "xQUihMCdFN8StU/kgO+3bVlbs7ZirdR3FgqYamtWfuyb7ScIk8O/Ms+4jswzIlCJB6phQS3C" + "kDNDKmGLzAiz0UcEOMJuKiMi2YTZmWKU0TUZx20P3beO2mAB+gCPPqxGADdT7PqRemmmEGDH" + "fwXYbdTECCLRXzHYV0SyIYsvliIEXuRvCFdVLIvtjeARCEMiGm1S4mlUtmeKKv4e+7oL5gDu" + "zJohJLDzuV0O5URxKDRgyDCRNeTIetn0BEXIDnLkZETiesLQDXJnXfDrumBGZXDEiWBpG1/M" + "5YhckSnqOoVrBeJWdBm6QutEUjwK6EmibnUGU59BQeFG4dgmeYIcFMQgXeOLHLBI4QlLhg2w" + "8MC61q5jhwAoCNz0G9udYiK/U2izZA1itsgE7xLu0BJ18DBR5YV+r+t0oLnCLOJ312ONUCK4" + "+YeVE2mvyb2qiEhbfmo4HGeUslLYa2UApHhUPZx8ejyUAW6mja1SGS+vVGizDjbwGwAlo9fT" + "gW0SU33TI4OlUAq4QaQlp5isNPG5Ioo5P5NV0KDKJ+FR/HfCgDN1uQzVdY3FSdLmFTJC9kXr" + "Tjc0epPyJnax1vb0hXo4Zv2GB2XnGz6tjN4Zv+ND9+FVlU8POtSB1BybINvHXP0FUHS4YTO2" + "omDOyPhGILFgMJMv7hEhea1UY7IzuIcfJctScnci2JI/ISlUFdDMuE7wmUtuvoTiCWh1RDCe" + "LxZR2lyYiX8GkoHOqLmiW/bBflB0uNmBl6NP+/L5kSJ0azl6MSLxpa1s71opqTWKVsSZXxRc" + "7JwyV/Vbw50oNgex3mGWElD5ZHo9HftgMxQObojoyOEsDRcfUQQX8jPEh4stmh9BKLk6Z0Pu" + "OU7eU3QkA1V5iX54hlIqfTCVR3dObjv/fOlTI8qEgtkzrSnoDIu45R+3VV78fPFIvlQi/Fx6" + "6ob1kTMBPlPPR+s8ftBvkT4vDFXy/MbAYA/KdOryc7r3vg1AleDGzNhGOeOXEkWNTQaQ/BTu" + "Ed/1rKNdXa+1v+kgB1MObGgsTwi4l8blCub7qASYnu7AH7bITxObH2WITkdQ5k6+/2dYQV69" + "57v71Hx7zN2vD8brWoQn3mOK6c/e3HJ+Rt3kEr6ommzU9AAiNB1uCI3tGvmOjH0kkgAC3Tia" + "DJ+CU4o2w9ugQjxIC2R8MS6Rs4XFllriQXR3K01mlFKMlOywKsIJ1bFkEkDBGdnrkGWIm9fe" + "Xd+NuPcn42PkeJIDlB9uNo3t3l0iH2OqbBqe3o5D54tiQ6Y8LKxS0WWMM7MkrK+IijuVQipt" + "mMvj+N7pPsN4bfLNbtck4WucJiFsXiXFsvnc4O2Kve1lXfSrqdPSzn4Kj/mdZXjFZ/GZUxJn" + "OlQDbrKNTWP1r3XUz3XJs7Sc8Z3CxR3Ca3RMXVTm2kDASc3UmHdd2H1rfEGnf6VkcgjngtXl" + "aF/PwsyT73MW9m/agA5tZPOzPVeil/LtvxTsrcrQcjAPN/N4d3FosA9Rd9ff9XYUzx/qAzcX" + "x+azdPSUqmI75M9gA8rks2ABnwFiEonkDjCO7wdqV7y3xVPR3a9o8YYprchoKv6Wu5i6k3Rq" + "uG7DpLBkyV3fR2Mazj3aCV/n/q6Ri+DkLPc81+v4F9Tj31kvrvl1XS6rssl45S5L3Xz9hox8" + "o4M0a+u6nFV/1GcrBxRFEYqTUA3dPV3Mp4dnNtzydL2dUJpQhrgY84Q7+FnHMJ1m8T5H46SK" + "VbLXCWN/TgQ/fpdjT4Z++77bGSvj3n7rI9q/0Q74VvLxpRfU6t/J6tBfN42JBtcPjxZFzzQP" + "NHxIu3JAM6GiN4+pc3opm4/gV5H+fD/FIUDySL/TIzY3ZLXwdHq78N5d3x1hnc699ze3VZUo" + "HZ0cPP/a1PRNZ+I12j9TLgmP6f6RZlLU93awSc9C1deVm73ivzjBDfHvVZDF307m1pFtipwM" + "5VUQ2yiWHEUmA9EY3fP6DEf0NkcgoctonW6Ezm0ozD9Z0v2Aab/7iqEIxkpeqLKNmGFxAI9Y" + "2zwIpFFR15qwyfq7bT8hDztzZwtYQGSJifhjydGNUDC4kTxeDoZMeOegCCzgZ7vg+zxDxiNp" + "cye5FWgGcttf+wlD9Ceaxf9lmlaLmjnp1I5HTG/h8kBbWii3mz2Bot3g9im94s6aKbFvL0dv" + "t7i4uqoY/+ch6dnuvlfI5TEh47xa++2gCnAjeGwKOqNXI+cJ6Oa8Ji5ifH1YVYVZvi4EwhZu" + "bI4Nwm80hMlKnPADrUVDmEmT8YcwAhyzxNAWTxzOUl0sCEYBD6YD0UgByKJ9S0b5nVI6+RLn" + "9w5TUoSkXW6hteCE/dJ3KGBP62pzin9oNlQAbm7i5AK2GjL9/y2QhUgx7qAYdoVGMEL3tQoZ" + "LCDxDZEsSy5xx4JZFFlfqNSmSdy6W+RrJMhiYYkgJZ53uBgkMLnqCNOS+8mzrL4htOkeQBvR" + "5e6Q60Z7qADcxDSSC+AXV7UoEkj5IbDmR4coUeQzObt1Gvra1CUzRNadpWnqx60S2B7ZUXl5" + "b39Lmo//vavoTc2uKfh9vndkpOMVYZNK/FsqK9pKjFwOzg4qE9CLKDmq5+JT4vovJnzSP5AU" + "uwGrz1ydKg72VvaJcn0f5SWJO3NXdOGK1fWXOm8rbl8tMLt4ZuutCterV1hXIs+u+fp6ILka" + "Kg43Wkly8czAMroi8c0/xHfdOTx8C+ug2ubivT1fWxlVKXHCUEs4ZGAKDd+hNc9nP3ge58pw" + "kNx/scUPPblBbPNol/d4x8zL5sm1dmGVmXvmcWuzYy0OiUwlFBrbAKd6wyx5nkNmWXfUiUUd" + "izfP+TRZuVIz7tRgNGLjh7iyhfhBaIfbFm7k6sn9MNtnKyvymzdyaxGHSwdyB4JCFCRTI7HE" + "IXtXiYl5PDZlgB1njH9Cia+RNok5rho+s71vI0hMtrKgJQJ54lVoHHCmkoMIsdHAAmUhKzYc" + "M5/SDoWHm6wGcnijuX+mK4IP+XVxhstR8vCo1E7P3c2wuzF5UylDNGF3aX3zVm5HefbBPmVN" + "6zNfT82SugbwA6cgZ7WpRvGwZUXGmLw/OzaFz+u3cjjytfGyPvEPDCWkK+G+VvPiD20PSLUn" + "7n5pUJ7Vuc0qwzkhCaoEN1iN5UoDIbqtipQCR64HSESTG6TsQRwSiewh8nCgwXq2EGdAknih" + "vWU9CC1wGY0+7mAEWxsj1lKveMxHdTjX3CB145pLcaQpBkNkQwZjSNDGJ+FixgcpAVMe78pq" + "qoxLhorADeWxDSzn/zewyJQZgCQZTGZLtbWG0EIwW+yMCs/mdv3muCha5zO1TWzJQ9J20vob" + "eq8nIDqdVjFyhX+8g8L+O0FtNzpgVLg0JJ4lfQYIcdnicaQhTuJaEpmLQj2cW5J2pKJJiOnl" + "9Evcexs5iLOVQbwbOZz5UEy4YTy2wSGfjEw0Er+Pd5OU/RY7Ey+r+FR7JvB7y1WUBJr4+fiO" + "HNJk7+QdKp0hLvZ7iea+5MWlHtzunCb9NC8LVscN/UrKBO3zJecaM21dqh02JafgZz1oOWLL" + "S44oI31Ymjt5J3598MnFMV8GRUrP66IHik99PAbxmwE3503kfiH7W39T5Cfv0eJQ6lh8Dmd4" + "kYx058qIPPTw6AfruDdiT/ug0bEOPqmO3s8RA6wM8nbTi4Y2qkBJYcaa+j2Fk6CgcPMcKwft" + "cPSaoAjUeKQRiUhhl7iyRQLMicNINMnWhHfEFAiSujYrP354EooDN5015DidLQWWinAmjupt" + "p0wgEIxryLLaw4gTiCNUbB6LQADJZBABlNfY3DdZSBdAqeBG59hqhvW/nipN1aL5EZJEtmZt" + "mx5EutdNVZ9SMzEnYlx4ZNf61fU934I8Aopimblb7S5bBZbX1i6neG1d0MHgXT/vZKm+e4dp" + "UNQ1DdtcP74aRmjv6qp2JvfTeHKDklfrpsryjwZqPt9ODUoAi93MWcTY3ntQNbipSZCr9ceH" + "pyhSmzIyX1CHJzcxuDYiG2wVi6i/S4ikodQEIpk8fQZAadlkTQDuukXoLXB/vhbKBjcULeVs" + "mxOvzlbExvw1SVDUlCgEusg1/d1KIbJ3pg7dRtevI8Qg2KZrDX1uHwOFy54+zqRHppqWVy19" + "gzmRMVljHt//Dr4/w0m4vkkcvf6vdJtHYgvM0zWtey99sLZptDx3V8/91Kx7he0Tt248Oj96" + "3cvF0ZtOf63NKwpdCfz5+vCrpi+y6s2qKWmhl4MeJkB14QamqVw3tWrbDkW6G+Q1wI9eTkGg" + "X4AD4D782xGwsEZHa2rpkWobEsXPjSjLdzRuf+fbqRfRkZViZxl+a21JSIlu9eEEY899DONZ" + "tYG1E2r/WrqkTaByr+lS2hrNt9Zn/8q7mProywKB0/6sY7KHBspFhYFTN1OgfZ0ZcDOUKHfT" + "Kdkl+R/zfcywG5cM0NvTTUXTItn2wTOytSZtK7zBzj0pClOao5dPtYue+/GC0y6ET9ze9omT" + "zm7yI7hXZ3b8Nc6+qu01cvv8vPKu+0tkjkc/TLEG3yGfvvh0XD/oQ9s6g4XVjJ6SiPh158MP" + "3jbcZdl7KTom4MJ9AhrqBzd2x1YjuP+/GqGZQu6QUOKlz9DC4ToBwFP5Ca5bmtj1WSIB1ZGH" + "w7whuHSCmOfaWbgO5Lue5I50JBIwOB86J+pQvBWUGW4Gj+2axP7sUQ1fk2tkgrIIWVZvZmB+" + "IOwMytW1aZ6J95mTXWTOXL381TLuOLX9vhfeZ+fu2a4cW3j/jll0GtL1eGjebuey6w5bq6yv" + "z1shYUVfvZSZNPfFjVUXdkkCvPZ9oPXe895Sedmw94QN3Sw+59pbVECH3pY6RBBzU8VUMAk6" + "9GbCjeKxldarRoYem4xF8fusZivNc/N0T0n4XWuN5lpkwST89d30u7Stt+eCuMVrZrAfBVry" + "XovCLB1fcDsdjaaHkGMrtWLLavUfcG+9eXFUz8j9uCCDEIaoUOp5TMRpbdw5cPzrq1SoDdy8" + "1pHb9NJ4aEU2QaMavmQsvT3LymqveqCJQVh5Bq1pubd1t+bKADrFghRhFbTjC2Xh4wpDHbr2" + "zvknY8fZvDva1JVfEmnl9mGjEHXywsvevRe9N+05/3Xp1IzSrvmSrEqwBzXtotdf5OL2E1Ad" + "uHk/tvix/I/4EbB3fSSiBwQVUlAE3m+kSbkNRYhwe10sQJoV9CK40fQUlOvfWSx7jNRvWEYC" + "Z3jlIkAMUTOwxDdg8Vqp69bSYlHyIPiV5FYkypJRd/KoLcQ3+kMUMmAk5KuYG9e4H+IND8iK" + "hu3dT984MaHUcMN8bFX1xl9D/e+uM09UjbeuY2d7JFpb0GuisMm1NduUG6/ZhWy9tuejzCc4" + "+GOujQ09MRqpzX4cwPMpo9VLauNJxCnZPWq9+xryg0pn69Sta+ydw2yfpld5FzuHavFyGmXZ" + "xHrcc2rU8oEeVBtuZ9YJ3EwZ1A5uOTBJbhc9P2u3Irvs73aEvKRWEw0lV6xymxbKtSopLOe8" + "yqPz+hvxt+p/V9E6dbqBdP6aFir/9gSU6N4CH7zK5KG9YAHDMrcnZR49mn3Uyu1+T4K/2tLD" + "Tr8dE1Tx0dvjtX6Lio39K7J33KSyPwIbuW11pw59Tp48mVNp/knNyrqNMHfGyZZaf3JD+771" + "h4/cI9+jrD67IF2kB/ZRN3uzDy5U/tC4FHoC4BYIY5vJYn4VCJdVBWRCoujtovWoddqZR9lP" + "aHbeS6KZ/A3xFuPi3y9SWb2AcW5d0cukHtpdWn9GoVH9/XzRA/WqSF7RFd7sqaZq1w+o4Cjj" + "JRNaFhN8LxV1VBQ3zEzdqePTOzHi/AJMpq/A0/Yk1362WRtneIZjvkiOuZKhe3I61BJuqWAo" + "twQLrn9QZPnzIcOhH30qj/ZX2e/QqzjqF7QMZlhdZ+gm0GKTZvVa7tPa78JU1uU4fniZUNZl" + "MdVzCXBSN7U8OXE6acDaaiig06Ti/aKWaSWPcifZha+JudmdpxOUeNW7KmHBug3FzvQgDu5W" + "3kMdqBPc8gBWeyfmzsXvTu7+23P1TSJzFnegyublzzcev/Gmjn8Gkegfnb5wOdpHkOSaqu/0" + "NoMboxle6pz9qFCoUtpUkE9flfT16XsdS6e9hIbUUqep0e6rkiRoK0M+71zfY6Llbua2yOCK" + "6F6oEtzqQVWu5ILPCFKkpPtzhmSwEf1oNHO5aSw5hAEAX9S0Xq0MnmgJwbCDm+5jeyTl/QNj" + "pqBWnU/Comibr1nVLPNkoJYcDsWn3U/heat8zKdaHtKp0iJv7bmjjWHWx1GH6NV2US+v28Qe" + "dIiTLBgK1Fy8AtTLZAXZOpzeth8KDjfIv5+/yX+D+9ydN1ERuL78/HFwzRWcEyo3wvARDCnO" + "AzhLpzytzo73hJLAzeDxcpJttKnuikjcRreMCF+QFCcUGIoOeUHEstRMpE04/CmGVIpJAZeR" + "ndEiUAvbxKkfZGHcqfhbIJUP2Kd/IwDbZ2yeEXOwBRrPdv9k+/D/RtYehSxg8Mlsd2PAOi42" + "urxA6z6UAW7YqsgZjuItDRQxyFsV37dfYgRevFZslr6GreHaCIxbLJrJ+40HPncDHr2c2KJq" + "d2EvlApuSGrLqXYErUIpovIc/QB9khQzgORhWnCExwZE8ifq910a0YRNwE1b4AWnt4fWqSGU" + "kWVAwiNLZ0aEXRw/qoTNEZlI+pUA6e/rdI/trVGBYsONNl05dvH2fJoi7Lkj2DgBhhQOdKOt" + "DCyH/ARiERsrSEYb83AfAwku95ESEG3lwkaeo0Xj8MjPfzwhO2d/FYgTJTjBzpdULGkglQ/U" + "+m3AHptWS4Cy/5O9VD/Yc9a9xChinz2yl4pD+tb09/bLHgyviUXYDQZHgIK24feJ42u5/gMs" + "3ksQiwEpzhUMKb9ZnKx/9QawodWDLx7Yfw1K+09Wqj9oo34fZCqiDRi1UhWAYDwWZNEkLOf6" + "wiwREUkUZOHiscWgmOIMNjVFGVo91RAO0lqylOvco538Ntr6tTYUx2NxaY8IzBpbsmwP5tF8" + "HTRwbf3CuxsKHFygCv9kM9UPhfyDdrPGMMaB4TGO+4jg4XA4svNQNFskxWF4saT3oIDPxzWS" + "+LhFGEGv3/A4v02LFxcjBVy1Ev0MWl1H6lk9oPrQ6oqGb9aDEGx7uFGlLsemOfauVoQ9Q47N" + "FbGQAhaax8JiWS5kmaxBrJlhXFqKNMRiDV8nxLVxiFisFpYkkJgAjm+9d1ZbnITu37aHG0tj" + "uxF/Vl95LbWqSWQdT5EZKhKlF6XjVbewebnLaW/zcahIU1nc5UNnq6U3t5K1QT/L9bwA5PGp" + "Qjvtz8t/r7HbM21PesSR+ktOq6Kp52z36Fegbhql6BI2DhBebzR9anuD5fUA6aC36g8HXAy0" + "orT/J4vMH06cK0c/KnKijVpkCrxI4ahuTxIzBUetWBsXRysSBSOpAnd9Jg/zuReLG6pDvnjs" + "cw0zZG9LbrYns3sttJBAaU1El+tiJS4UGG68jZMDz7c8SFAEPHVkUzoixZjKcFBxz2owjfr0" + "BSEQYLAZjE/ZEdu6EEi8jMUmIoBsba+mrKCq/3I64Qbf2CqXab/onvEBOnUCwYVMa8fVqChx" + "lA0IBA2g3IpOWzH8bkJ7D5rXjwYqH0+LdaoBD0Dx4Cbg2EZw4OgocSeFJ3YnJ4qpurxkVhjB" + "eKgiOE6q2czCCps4cS7DFUxwHCDEfeXUG6XgkBJ30pAYU2pc1kfECTggFovtV8eCYF8w8MgX" + "hQYev9gw84qhihQqAjcTxzYKjEZ9l0KERHuSf/Oe/fdlB9Sb0gH7Pq9oe1oEC0oDN+UmymkM" + "66p3KqJxHemIUAlWJuCuirVgg1jEMerB8XjI6VjaFo0mZIn37I/JaoSvVwcxM5sxMS1UawLB" + "nJ3v9zycrApor6559IIXBH0GZw836cZ22zuM7i3VSvu4v/GSMc/1CQZS/QlrpPrG9+tsnaWt" + "d8RilpOPlA+Go9Ff0aXvlEMAXt96gvJ5P+gDZnu4eaYjBz2Q4LlLEajHCChyOM+IHzE8ItFl" + "OM/8v+8hR7gPUBGkcEYXRgTu22eUocx/sx/UJxuiu5NZagSXRUyGVDDvzGXA7QqjvbeGDN1I" + "4wA3zsZWSMwZ3fKulbZinHgY3PPhGUBMmdESGir1eyYUi0CEuQxQpyp1u9PisWkD7N96CS7N" + "DyjxDGmT+LB+Cqh9Xb0fBGZu3Gh4zsPsKhQdbsiNDf0/toq01381FlDRLjwqVUpwGdoTGjfk" + "u1vkgD/3fV/px9CGXj9swD3s/a3iZEMB12sLlih9TmB23KDIQC/UUAMKwHUu/oBZZYuFwsNN" + "M5wcnt7iHKIInjxqBxb120CKSIRAX0ejPdE8jDIWx6Q4D5/abPwsvyY+yYv/fLhEWlg35wJC" + "tP8CFBBueo2tHvb8j3qYf0csJQu+tmIH8Z+KDw9S3d1nCxDDYduCpRL0h4aLSBa/BkQSdoV1" + "gNmuQxTkTqoAsVNmgQSSTnrq334xngTFhhtrWDl29UBysCLska9EcBD6g4N8Md5gFh9QCiwn" + "t3ORWByK4EIgy6wYNFvieATwLtXHIP2KeTkUDm6ojW0us//PuewZ2DdcqpwbPnvBayO+r+rs" + "JISKISL+yRlbGSMyXCro5IuzDkVcRICZkf4FbeNOQznhZtbY7izP0XfWpH0NPI6oC3ThJTOc" + "s0RIwhNKfMW5UKn/Usx1Vu8QRVaLCClkYUFzzj7tigKDlMLhGFYlWj4OArZ3RIa927aIDMWG" + "G26mcuyhzWeUFGGvGwk3zHC4GfR+IUYxGDUFmxkMB+nqIQGClwy+oCrdYMloHwTUoVbaB5zT" + "vkgWky3yUt930jneeIEuFZXDyiDeweTcZAQMCoaQWLCD2oH0Yap8PWIcYZaYC3JJN7Y7Apkx" + "x8t316+sgJr9k+/S/O9sWf7DLPP79xzIBLrIUjc/Gjl3xfYtHDbXITdpg5XuWYydqszccyWp" + "sWmDxu6DHlUXIxb6hhbdE2om6WqGB4eK6BNu9m/4UjdfuNA5ud68v2uZINH2BCtdb+f6DeLc" + "1T2dUBW4MTm2sfXzuw55f6voeLRjluwmOcxJOTAxrWSVZ9viXutVND/7mjPZ4K52a0b0zVtJ" + "J7pwBMZdjWR076yu+GUriwyXJTtNV5p0nKH3Itd/7uzbZ8wNMn0+a9oEHn9Z578DEFWtRcce" + "OzcV4uMIN0DH1qpZ+MuHoskm4+ntz/xNOVsTxh/kz1MLQ02iI3Q1MJMWhjn84Zb2UBZSoLJW" + "mCmZYfZw/kHZCT2fLTd749PvlVeddpqp4TxtDsHn6KaSQ5xnRGdS+KvGnkNGUAe4STq2Jtio" + "7yBzRWaCUGexg2AHegePScr0feDFK8aCJnjgc7f5qcUdpXOgUHATUkkOVTv93F1FUL/+AwhG" + "iYohH41YoaPiKgaM9kEPDzf/xrY+sh5ZH7U940dd4ogo7a+DkYImNI+KxVL52O6Zxpgni5/x" + "xcQ0gMhwtK3GZqlD4eCm3Ng6p5NGN3vLpQIQg8U9x5ENQ98zXm/OZmSzGA0MX+Wte8jA0qYY" + "7NlEpu9osv8DuJwRWA=="; + +#endif /* LEPTONICA_AUTOGEN_137_H */ diff --git a/leptonica/prog/autogentest1.c b/leptonica/prog/autogentest1.c new file mode 100644 index 00000000..f7c687d7 --- /dev/null +++ b/leptonica/prog/autogentest1.c @@ -0,0 +1,80 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * autogentest1.c + * + * This makes /tmp/lept/auto/autogen.137.c and /tmp/lept/auto/autogen.137.h. + * It shows how to use the stringcode facility. + * + * In general use, you compile and run the code generator before + * compiling and running the generated code, in autogentest2.c. + * + * But here, because we compile both autogentest1.c and autogentest2.c + * at the same time, it is necessary to put the generated code + * in this directory. Running autogentest1 will simply regenerate + * this code, but in the /tmp/lept/auto/ directory. + * + * As part of the test, this makes /tmp/lept/auto/autogen.138.c and + * /tmp/lept/auto/autogen.138.h, which contain the same data, using + * the function strcodeCreateFromFile(). With this method, you do not + * need to specify the file type (e.g., "PIXA") + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" +#include <string.h> + +static const char *files[2] = { "fonts/chars-6.pa", "fonts/chars-10.pa" }; + +static const char *filetext = "# testnames\n" + "fonts/chars-6.pa\n" + "fonts/chars-10.pa"; + +l_int32 main(int argc, + char **argv) +{ +l_int32 i; +L_STRCODE *strc; + + setLeptDebugOK(1); + + /* Method 1: generate autogen.137.c and autogen.137.h */ + strc = strcodeCreate(137); + for (i = 0; i < 2; i++) + strcodeGenerate(strc, files[i], "PIXA"); + strcodeFinalize(&strc, NULL); + + /* Method 2: generate autogen.138.c and autogen.138.c */ + l_binaryWrite("/tmp/lept/auto/fontnames.txt", "w", filetext, + strlen(filetext)); + strcodeCreateFromFile("/tmp/lept/auto/fontnames.txt", 138, NULL); + return 0; +} + diff --git a/leptonica/prog/autogentest2.c b/leptonica/prog/autogentest2.c new file mode 100644 index 00000000..432694d4 --- /dev/null +++ b/leptonica/prog/autogentest2.c @@ -0,0 +1,69 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * autogentest2.c + * + * This is a test of the stringcode utility. + * + * It uses the files compiled from autogen.137.c and autogen.137.h + * to regenerate each of the 2 pixa from the strings in autogen.137.h. + * It then writes them to file and compares with the original. + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" +#include "autogen.137.h" /* this must be included */ + + /* Original serialized pixa, that were used by autogentest1.c */ +static const char *files[2] = { "fonts/chars-6.pa", "fonts/chars-10.pa" }; + +l_int32 main(int argc, + char **argv) +{ +l_int32 i, same; +PIXA *pixa; + + setLeptDebugOK(1); + lept_mkdir("lept/auto"); + + for (i = 0; i < 2; i++) { + pixa = (PIXA *)l_autodecode_137(i); /* this is the dispatcher */ + pixaWrite("/tmp/lept/auto/junkpa.pa", pixa); + filesAreIdentical("/tmp/lept/auto/junkpa.pa", files[i], &same); + if (same) + lept_stderr("Files are the same for %s\n", files[i]); + else + lept_stderr("Error: files are different for %s\n", files[i]); + pixaDestroy(&pixa); + } + + return 0; +} + diff --git a/leptonica/prog/barcode-128-300.png b/leptonica/prog/barcode-128-300.png Binary files differnew file mode 100644 index 00000000..a3548236 --- /dev/null +++ b/leptonica/prog/barcode-128-300.png diff --git a/leptonica/prog/barcode-2of5-300.png b/leptonica/prog/barcode-2of5-300.png Binary files differnew file mode 100644 index 00000000..6e52537c --- /dev/null +++ b/leptonica/prog/barcode-2of5-300.png diff --git a/leptonica/prog/barcode-39-300.png b/leptonica/prog/barcode-39-300.png Binary files differnew file mode 100644 index 00000000..dcdb841f --- /dev/null +++ b/leptonica/prog/barcode-39-300.png diff --git a/leptonica/prog/barcode-93-300.png b/leptonica/prog/barcode-93-300.png Binary files differnew file mode 100644 index 00000000..f202be10 --- /dev/null +++ b/leptonica/prog/barcode-93-300.png diff --git a/leptonica/prog/barcode-codabar-300.png b/leptonica/prog/barcode-codabar-300.png Binary files differnew file mode 100644 index 00000000..8f599cae --- /dev/null +++ b/leptonica/prog/barcode-codabar-300.png diff --git a/leptonica/prog/barcode-digits.png b/leptonica/prog/barcode-digits.png Binary files differnew file mode 100644 index 00000000..bb3af672 --- /dev/null +++ b/leptonica/prog/barcode-digits.png diff --git a/leptonica/prog/barcode-i2of5-300.png b/leptonica/prog/barcode-i2of5-300.png Binary files differnew file mode 100644 index 00000000..79ccd4cd --- /dev/null +++ b/leptonica/prog/barcode-i2of5-300.png diff --git a/leptonica/prog/barcode-upc-300.png b/leptonica/prog/barcode-upc-300.png Binary files differnew file mode 100644 index 00000000..02e2a94e --- /dev/null +++ b/leptonica/prog/barcode-upc-300.png diff --git a/leptonica/prog/barcodetest.c b/leptonica/prog/barcodetest.c new file mode 100644 index 00000000..626e4e01 --- /dev/null +++ b/leptonica/prog/barcodetest.c @@ -0,0 +1,90 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * barcodetest.c + * + * barcodetest filein + * + * For each barcode in the image, if the barcode format is supported, + * this deskews and crops it, and then decodes it twice: + * (1) as is (deskewed) + * (2) after 180 degree rotation + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" +#include "readbarcode.h" + +int main(int argc, + char **argv) +{ +char *filein; +PIX *pixs; +SARRAY *saw1, *saw2, *sad1, *sad2; +static char mainName[] = "barcodetest"; + + if (argc != 2) + return ERROR_INT(" Syntax: barcodetest filein", mainName, 1); + filein = argv[1]; + + setLeptDebugOK(1); + lept_mkdir("lept/barc"); + + if ((pixs = pixRead(filein)) == NULL) + return ERROR_INT("pixs not made", mainName, 1); + + sad1 = pixProcessBarcodes(pixs, L_BF_ANY, L_USE_WIDTHS, &saw1, 0); + sarrayWrite("/tmp/lept/barc/saw1", saw1); + sarrayWrite("/tmp/lept/barc/sad1", sad1); + sarrayDestroy(&saw1); + sarrayDestroy(&sad1); + + pixRotate180(pixs, pixs); + sad2 = pixProcessBarcodes(pixs, L_BF_ANY, L_USE_WIDTHS, &saw2, 0); + sarrayWrite("/tmp/lept/barc/saw2", saw2); + sarrayWrite("/tmp/lept/barc/sad2", sad2); + sarrayDestroy(&saw2); + sarrayDestroy(&sad2); + +/* +{ + SARRAY *saw3, *sad3; + sad3 = pixProcessBarcodes(pixs, L_BF_ANY, L_USE_WINDOW, &saw3, 1); + sarrayWrite("/tmp/lept/barc/saw3", saw3); + sarrayWrite("/tmp/lept/barc/sad3", sad3); + sarrayDestroy(&saw3); + sarrayDestroy(&sad3); +} +*/ + + pixDestroy(&pixs); + return 0; +} + diff --git a/leptonica/prog/barcodetest1.jpg b/leptonica/prog/barcodetest1.jpg Binary files differnew file mode 100644 index 00000000..2a813734 --- /dev/null +++ b/leptonica/prog/barcodetest1.jpg diff --git a/leptonica/prog/barcodetest2.jpg b/leptonica/prog/barcodetest2.jpg Binary files differnew file mode 100644 index 00000000..fe361690 --- /dev/null +++ b/leptonica/prog/barcodetest2.jpg diff --git a/leptonica/prog/baseline_reg.c b/leptonica/prog/baseline_reg.c new file mode 100644 index 00000000..a02de42e --- /dev/null +++ b/leptonica/prog/baseline_reg.c @@ -0,0 +1,135 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * baselinetest.c + * + * This tests two things: + * (1) The ability to find a projective transform that will deskew + * textlines in an image with keystoning. + * (2) The ability to find baselines in a text image. + * (3) The ability to clean background to white in a dark and + * mottled text image. + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + +int main(int argc, + char **argv) +{ +NUMA *na; +PIX *pixs, *pix1, *pix2, *pix3, *pix4, *pix5; +PIXA *pixadb; +PTA *pta; +L_REGPARAMS *rp; + +#if !defined(HAVE_LIBPNG) + L_ERROR("This test requires libpng to run.\n", "baseline_reg"); + exit(77); +#endif + + if (regTestSetup(argc, argv, &rp)) + return 1; + + pixs = pixRead("keystone.png"); + + /* Test function for deskewing using projective transform + * on linear approximation for local skew angle */ + pix1 = pixDeskewLocal(pixs, 10, 0, 0, 0.0, 0.0, 0.0); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 0 */ + + /* Test function for finding local skew angles */ + na = pixGetLocalSkewAngles(pixs, 10, 0, 0, 0.0, 0.0, 0.0, NULL, NULL, 1); + gplotSimple1(na, GPLOT_PNG, "/tmp/lept/baseline/ang", "Angles in degrees"); + pix2 = pixRead("/tmp/lept/baseline/ang.png"); + pix3 = pixRead("/tmp/lept/baseline/skew.png"); + regTestWritePixAndCheck(rp, pix2, IFF_PNG); /* 1 */ + regTestWritePixAndCheck(rp, pix3, IFF_PNG); /* 2 */ + pixDisplayWithTitle(pix2, 0, 550, NULL, rp->display); + pixDisplayWithTitle(pix3, 700, 550, NULL, rp->display); + numaDestroy(&na); + pixDestroy(&pix2); + pixDestroy(&pix3); + pixDestroy(&pixs); + + /* Test baseline finder */ + pixadb = pixaCreate(6); + na = pixFindBaselines(pix1, &pta, pixadb); + pix2 = pixRead("/tmp/lept/baseline/diff.png"); + pix3 = pixRead("/tmp/lept/baseline/loc.png"); + pix4 = pixRead("/tmp/lept/baseline/baselines.png"); + regTestWritePixAndCheck(rp, pix2, IFF_PNG); /* 3 */ + regTestWritePixAndCheck(rp, pix3, IFF_PNG); /* 4 */ + regTestWritePixAndCheck(rp, pix4, IFF_PNG); /* 5 */ + pixDisplayWithTitle(pix2, 0, 0, NULL, rp->display); + pixDisplayWithTitle(pix3, 700, 0, NULL, rp->display); + pixDisplayWithTitle(pix4, 1350, 0, NULL, rp->display); + pix5 = pixaDisplayTiledInRows(pixadb, 32, 1500, 1.0, 0, 30, 2); + pixDisplayWithTitle(pix5, 0, 500, NULL, rp->display); + regTestWritePixAndCheck(rp, pix5, IFF_PNG); /* 6 */ + pixDestroy(&pix1); + pixDestroy(&pix2); + pixDestroy(&pix3); + pixDestroy(&pix4); + pixDestroy(&pix5); + pixaDestroy(&pixadb); + numaDestroy(&na); + ptaDestroy(&pta); + + /* Another test for baselines, with dark image */ + pixadb = pixaCreate(6); + pixs = pixRead("pedante.079.jpg"); /* 75 ppi */ + pix1 = pixRemoveBorder(pixs, 30); + pixaAddPix(pixadb, pix1, L_COPY); + pix2 = pixConvertRGBToGray(pix1, 0.33, 0.34, 0.33); + pix3 = pixScale(pix2, 4.0, 4.0); /* scale up to 300 ppi */ + pix4 = pixCleanBackgroundToWhite(pix3, NULL, NULL, 1.0, 70, 170); + pix5 = pixThresholdToBinary(pix4, 170); + regTestWritePixAndCheck(rp, pix5, IFF_PNG); /* 7 */ + pixaAddPix(pixadb, pixScale(pix5, 0.25, 0.25), L_INSERT); + pixDestroy(&pix1); + pixDestroy(&pix2); + pixDestroy(&pix3); + pixDestroy(&pix4); + pix1 = pixDeskew(pix5, 2); + na = pixFindBaselines(pix1, &pta, pixadb); + pix2 = pixaDisplayTiledInRows(pixadb, 32, 1500, 1.0, 0, 30, 2); + regTestWritePixAndCheck(rp, pix2, IFF_PNG); /* 8 */ + pixDisplayWithTitle(pix2, 800, 500, NULL, rp->display); + pixaDestroy(&pixadb); + pixDestroy(&pixs); + pixDestroy(&pix1); + pixDestroy(&pix2); + pixDestroy(&pix5); + numaDestroy(&na); + ptaDestroy(&pta); + + return regTestCleanup(rp); +} diff --git a/leptonica/prog/bigweasel2.4c.png b/leptonica/prog/bigweasel2.4c.png Binary files differnew file mode 100644 index 00000000..ce2e27e1 --- /dev/null +++ b/leptonica/prog/bigweasel2.4c.png diff --git a/leptonica/prog/bilateral1_reg.c b/leptonica/prog/bilateral1_reg.c new file mode 100644 index 00000000..5f76a225 --- /dev/null +++ b/leptonica/prog/bilateral1_reg.c @@ -0,0 +1,136 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * bilateral1_reg.c + * + * Regression test for bilateral (nonlinear) filtering, with both: + * (1) Separable results with full res intermediate images + * (2) Exact results + * This test takes about 30 seconds, so it is not included + * in the alltests_reg set. + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + +static void DoTestsOnImage(PIX *pixs, L_REGPARAMS *rp, l_int32 width); + +static const l_int32 ncomps = 10; + +int main(int argc, + char **argv) +{ +PIX *pixs; +L_REGPARAMS *rp; + + if (regTestSetup(argc, argv, &rp)) + return 1; + + pixs = pixRead("rock.png"); + DoTestsOnImage(pixs, rp, 2000); /* 0 - 16 */ + pixDestroy(&pixs); + + pixs = pixRead("church.png"); + DoTestsOnImage(pixs, rp, 1500); /* 17 - 33 */ + pixDestroy(&pixs); + + pixs = pixRead("color-wheel-hue.jpg"); + DoTestsOnImage(pixs, rp, 1000); /* 34 - 50 */ + pixDestroy(&pixs); + + return regTestCleanup(rp); +} + + +static void +DoTestsOnImage(PIX *pixs, + L_REGPARAMS *rp, + l_int32 width) +{ +PIX *pix, *pixd; +PIXA *pixa; + + pixa = pixaCreate(0); + pix = pixBilateral(pixs, 5.0, 10.0, ncomps, 1); + regTestWritePixAndCheck(rp, pix, IFF_JFIF_JPEG); + pixaAddPix(pixa, pix, L_INSERT); + pix = pixBilateral(pixs, 5.0, 20.0, ncomps, 1); + regTestWritePixAndCheck(rp, pix, IFF_JFIF_JPEG); + pixaAddPix(pixa, pix, L_INSERT); + pix = pixBilateral(pixs, 5.0, 40.0, ncomps, 1); + regTestWritePixAndCheck(rp, pix, IFF_JFIF_JPEG); + pixaAddPix(pixa, pix, L_INSERT); + pix = pixBilateral(pixs, 5.0, 60.0, ncomps, 1); + regTestWritePixAndCheck(rp, pix, IFF_JFIF_JPEG); + pixaAddPix(pixa, pix, L_INSERT); + pix = pixBilateral(pixs, 10.0, 10.0, ncomps, 1); + regTestWritePixAndCheck(rp, pix, IFF_JFIF_JPEG); + pixaAddPix(pixa, pix, L_INSERT); + pix = pixBilateral(pixs, 10.0, 20.0, ncomps, 1); + regTestWritePixAndCheck(rp, pix, IFF_JFIF_JPEG); + pixaAddPix(pixa, pix, L_INSERT); + pix = pixBilateral(pixs, 10.0, 40.0, ncomps, 1); + regTestWritePixAndCheck(rp, pix, IFF_JFIF_JPEG); + pixaAddPix(pixa, pix, L_INSERT); + pix = pixBilateral(pixs, 10.0, 60.0, ncomps, 1); + regTestWritePixAndCheck(rp, pix, IFF_JFIF_JPEG); + pixaAddPix(pixa, pix, L_INSERT); + pix = pixBilateral(pixs, 10.0, 10.0, ncomps, 2); + regTestWritePixAndCheck(rp, pix, IFF_JFIF_JPEG); + pixaAddPix(pixa, pix, L_INSERT); + pix = pixBilateral(pixs, 10.0, 20.0, ncomps, 2); + regTestWritePixAndCheck(rp, pix, IFF_JFIF_JPEG); + pixaAddPix(pixa, pix, L_INSERT); + pix = pixBilateral(pixs, 10.0, 40.0, ncomps, 2); + regTestWritePixAndCheck(rp, pix, IFF_JFIF_JPEG); + pixaAddPix(pixa, pix, L_INSERT); + pix = pixBilateral(pixs, 10.0, 60.0, ncomps, 2); + regTestWritePixAndCheck(rp, pix, IFF_JFIF_JPEG); + pixaAddPix(pixa, pix, L_INSERT); + pix = pixBlockBilateralExact(pixs, 10.0, 10.0); + regTestWritePixAndCheck(rp, pix, IFF_JFIF_JPEG); + pixaAddPix(pixa, pix, L_INSERT); + pix = pixBlockBilateralExact(pixs, 10.0, 20.0); + regTestWritePixAndCheck(rp, pix, IFF_JFIF_JPEG); + pixaAddPix(pixa, pix, L_INSERT); + pix = pixBlockBilateralExact(pixs, 10.0, 40.0); + regTestWritePixAndCheck(rp, pix, IFF_JFIF_JPEG); + pixaAddPix(pixa, pix, L_INSERT); + pix = pixBlockBilateralExact(pixs, 10.0, 60.0); + regTestWritePixAndCheck(rp, pix, IFF_JFIF_JPEG); + pixaAddPix(pixa, pix, L_INSERT); + pixd = pixaDisplayTiledInRows(pixa, 32, width, 1.0, 0, 30, 2); + regTestWritePixAndCheck(rp, pixd, IFF_JFIF_JPEG); + pixDisplayWithTitle(pixd, 100, 100, NULL, rp->display); + pixDestroy(&pixd); + pixaDestroy(&pixa); + return; +} + diff --git a/leptonica/prog/bilateral2_reg.c b/leptonica/prog/bilateral2_reg.c new file mode 100644 index 00000000..b02dc7d1 --- /dev/null +++ b/leptonica/prog/bilateral2_reg.c @@ -0,0 +1,105 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * bilateral2_reg.c + * + * Regression test for bilateral (nonlinear) filtering. + * + * Separable operation with intermediate images at 4x reduction. + * This speeds the filtering up by about 30x compared to + * separable operation with full resolution intermediate images. + * Using 4x reduction on intermediates, this runs at about + * 3 MPix/sec, with very good quality. + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + +static void DoTestsOnImage(PIX *pixs, L_REGPARAMS *rp); + +static const l_int32 ncomps = 10; + +int main(int argc, + char **argv) +{ +PIX *pixs; +L_REGPARAMS *rp; + + if (regTestSetup(argc, argv, &rp)) + return 1; + + pixs = pixRead("test24.jpg"); + DoTestsOnImage(pixs, rp); /* 0 - 7 */ + pixDestroy(&pixs); + + return regTestCleanup(rp); +} + + +static void +DoTestsOnImage(PIX *pixs, + L_REGPARAMS *rp) +{ +PIX *pix, *pixd; +PIXA *pixa; + + pixa = pixaCreate(0); + pix = pixBilateral(pixs, 5.0, 10.0, ncomps, 4); /* 0 */ + regTestWritePixAndCheck(rp, pix, IFF_JFIF_JPEG); + pixaAddPix(pixa, pix, L_INSERT); + pix = pixBilateral(pixs, 5.0, 20.0, ncomps, 4); /* 1 */ + regTestWritePixAndCheck(rp, pix, IFF_JFIF_JPEG); + pixaAddPix(pixa, pix, L_INSERT); + pix = pixBilateral(pixs, 5.0, 40.0, ncomps, 4); /* 2 */ + regTestWritePixAndCheck(rp, pix, IFF_JFIF_JPEG); + pixaAddPix(pixa, pix, L_INSERT); + pix = pixBilateral(pixs, 5.0, 60.0, ncomps, 4); /* 3 */ + regTestWritePixAndCheck(rp, pix, IFF_JFIF_JPEG); + pixaAddPix(pixa, pix, L_INSERT); + pix = pixBilateral(pixs, 10.0, 10.0, ncomps, 4); /* 4 */ + regTestWritePixAndCheck(rp, pix, IFF_JFIF_JPEG); + pixaAddPix(pixa, pix, L_INSERT); + pix = pixBilateral(pixs, 10.0, 20.0, ncomps, 4); /* 5 */ + regTestWritePixAndCheck(rp, pix, IFF_JFIF_JPEG); + pixaAddPix(pixa, pix, L_INSERT); + pix = pixBilateral(pixs, 10.0, 40.0, ncomps, 4); /* 6 */ + regTestWritePixAndCheck(rp, pix, IFF_JFIF_JPEG); + pixaAddPix(pixa, pix, L_INSERT); + pix = pixBilateral(pixs, 10.0, 60.0, ncomps, 4); /* 7 */ + regTestWritePixAndCheck(rp, pix, IFF_JFIF_JPEG); + pixaAddPix(pixa, pix, L_INSERT); + pixd = pixaDisplayTiledInRows(pixa, 32, 2500, 1.0, 0, 30, 2); + pixDisplayWithTitle(pixd, 100, 100, NULL, rp->display); + pixDestroy(&pixd); + pixaDestroy(&pixa); + return; +} + + diff --git a/leptonica/prog/bilinear_reg.c b/leptonica/prog/bilinear_reg.c new file mode 100644 index 00000000..01aa7ad8 --- /dev/null +++ b/leptonica/prog/bilinear_reg.c @@ -0,0 +1,263 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * bilinear_reg.c + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + +static void MakePtas(l_int32 i, PTA **pptas, PTA **pptad); + + /* Sample values. + * 1: test with relatively large distortion + * 2-3: invertability tests + */ +static const l_int32 x1[] = { 32, 32, 32}; +static const l_int32 y1[] = { 150, 150, 150}; +static const l_int32 x2[] = { 520, 520, 520}; +static const l_int32 y2[] = { 150, 150, 150}; +static const l_int32 x3[] = { 32, 32, 32}; +static const l_int32 y3[] = { 612, 612, 612}; +static const l_int32 x4[] = { 520, 520, 520}; +static const l_int32 y4[] = { 612, 612, 612}; + +static const l_int32 xp1[] = { 32, 32, 32}; +static const l_int32 yp1[] = { 150, 150, 150}; +static const l_int32 xp2[] = { 520, 520, 520}; +static const l_int32 yp2[] = { 44, 124, 140}; +static const l_int32 xp3[] = { 32, 32, 32}; +static const l_int32 yp3[] = { 612, 612, 612}; +static const l_int32 xp4[] = { 520, 520, 520}; +static const l_int32 yp4[] = { 694, 624, 622}; + +#define ALL 1 +#define ADDED_BORDER_PIXELS 250 + +int main(int argc, + char **argv) +{ +l_int32 i; +PIX *pixs, *pix1, *pix2, *pix3, *pix4, *pixd; +PIX *pixb, *pixg, *pixc, *pixcs; +PIXA *pixa; +PTA *ptas, *ptad; +L_REGPARAMS *rp; + + if (regTestSetup(argc, argv, &rp)) + return 1; + + pixs = pixRead("feyn.tif"); + pixg = pixScaleToGray(pixs, 0.2); + pixDestroy(&pixs); + +#if ALL + /* Test non-invertability of sampling */ + lept_stderr("Test invertability of sampling\n"); + pixa = pixaCreate(0); + for (i = 1; i < 3; i++) { + pixb = pixAddBorder(pixg, ADDED_BORDER_PIXELS, 255); + MakePtas(i, &ptas, &ptad); + pix1 = pixBilinearSampledPta(pixb, ptad, ptas, L_BRING_IN_WHITE); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 0,3,6 */ + pixaAddPix(pixa, pix1, L_INSERT); + pix2 = pixBilinearSampledPta(pix1, ptas, ptad, L_BRING_IN_WHITE); + regTestWritePixAndCheck(rp, pix2, IFF_PNG); /* 1,4,7 */ + pixaAddPix(pixa, pix2, L_INSERT); + pixd = pixRemoveBorder(pix2, ADDED_BORDER_PIXELS); + pixInvert(pixd, pixd); + pixXor(pixd, pixd, pixg); + regTestWritePixAndCheck(rp, pixd, IFF_PNG); /* 2,5,8 */ + pixaAddPix(pixa, pixd, L_INSERT); + pixDestroy(&pixb); + ptaDestroy(&ptas); + ptaDestroy(&ptad); + } + + pix1 = pixaDisplayTiledInColumns(pixa, 3, 0.5, 20, 3); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 9 */ + pixDisplayWithTitle(pix1, 0, 100, NULL, rp->display); + pixDestroy(&pix1); + pixaDestroy(&pixa); +#endif + +#if ALL + /* Test invertability of grayscale interpolation */ + lept_stderr("Test invertability of grayscale interpolation\n"); + pixa = pixaCreate(0); + for (i = 1; i < 3; i++) { + pixb = pixAddBorder(pixg, ADDED_BORDER_PIXELS, 255); + MakePtas(i, &ptas, &ptad); + pix1 = pixBilinearPta(pixb, ptad, ptas, L_BRING_IN_WHITE); + regTestWritePixAndCheck(rp, pix1, IFF_JFIF_JPEG); /* 10,13 */ + pixaAddPix(pixa, pix1, L_INSERT); + pix2 = pixBilinearPta(pix1, ptas, ptad, L_BRING_IN_WHITE); + regTestWritePixAndCheck(rp, pix2, IFF_JFIF_JPEG); /* 11,14 */ + pixaAddPix(pixa, pix2, L_INSERT); + pixd = pixRemoveBorder(pix2, ADDED_BORDER_PIXELS); + pixInvert(pixd, pixd); + pixXor(pixd, pixd, pixg); + regTestWritePixAndCheck(rp, pixd, IFF_JFIF_JPEG); /* 12,15 */ + pixaAddPix(pixa, pixd, L_INSERT); + pixDestroy(&pixb); + ptaDestroy(&ptas); + ptaDestroy(&ptad); + } + + pix1 = pixaDisplayTiledInColumns(pixa, 3, 0.5, 20, 3); + regTestWritePixAndCheck(rp, pix1, IFF_JFIF_JPEG); /* 16 */ + pixDisplayWithTitle(pix1, 200, 100, NULL, rp->display); + pixDestroy(&pix1); + pixaDestroy(&pixa); +#endif + +#if ALL + /* Test invertability of color interpolation */ + lept_stderr("Test invertability of color interpolation\n"); + pixa = pixaCreate(0); + pixc = pixRead("test24.jpg"); + pixcs = pixScale(pixc, 0.3, 0.3); + for (i = 1; i < 3; i++) { + pixb = pixAddBorder(pixcs, ADDED_BORDER_PIXELS / 2, 0xffffff00); + MakePtas(i, &ptas, &ptad); + pix1 = pixBilinearPta(pixb, ptad, ptas, L_BRING_IN_WHITE); + regTestWritePixAndCheck(rp, pix1, IFF_JFIF_JPEG); /* 17,20 */ + pixaAddPix(pixa, pix1, L_INSERT); + pix2 = pixBilinearPta(pix1, ptas, ptad, L_BRING_IN_WHITE); + regTestWritePixAndCheck(rp, pix2, IFF_JFIF_JPEG); /* 18,21 */ + pixaAddPix(pixa, pix2, L_INSERT); + pixd = pixRemoveBorder(pix2, ADDED_BORDER_PIXELS / 2); + pixXor(pixd, pixd, pixc); + pixInvert(pixd, pixd); + regTestWritePixAndCheck(rp, pixd, IFF_JFIF_JPEG); /* 19,22 */ + pixaAddPix(pixa, pixd, L_INSERT); + pixDestroy(&pixb); + ptaDestroy(&ptas); + ptaDestroy(&ptad); + } + + pix1 = pixaDisplayTiledInColumns(pixa, 3, 0.5, 20, 3); + regTestWritePixAndCheck(rp, pix1, IFF_JFIF_JPEG); /* 23 */ + pixDisplayWithTitle(pix1, 400, 100, NULL, rp->display); + pixDestroy(&pix1); + pixDestroy(&pixc); + pixDestroy(&pixcs); + pixaDestroy(&pixa); +#endif + +#if ALL + /* Comparison between sampling and interpolated */ + lept_stderr("Compare sampling with interpolated\n"); + MakePtas(2, &ptas, &ptad); + pixa = pixaCreate(0); + + /* Use sampled transform */ + pix1 = pixBilinearSampledPta(pixg, ptas, ptad, L_BRING_IN_WHITE); + regTestWritePixAndCheck(rp, pix1, IFF_JFIF_JPEG); /* 24 */ + pixaAddPix(pixa, pix1, L_INSERT); + + /* Use interpolated transforms */ + pix2 = pixBilinearPta(pixg, ptas, ptad, L_BRING_IN_WHITE); + regTestWritePixAndCheck(rp, pix2, IFF_JFIF_JPEG); /* 25 */ + pixaAddPix(pixa, pix2, L_COPY); + + /* Compare the results */ + pixXor(pix2, pix2, pix1); + pixInvert(pix2, pix2); + regTestWritePixAndCheck(rp, pix2, IFF_JFIF_JPEG); /* 26 */ + pixaAddPix(pixa, pix2, L_INSERT); + + pix1 = pixaDisplayTiledInColumns(pixa, 3, 0.5, 20, 3); + regTestWritePixAndCheck(rp, pix1, IFF_JFIF_JPEG); /* 27 */ + pixDisplayWithTitle(pix1, 600, 100, NULL, rp->display); + pixDestroy(&pix1); + pixDestroy(&pixg); + pixaDestroy(&pixa); + ptaDestroy(&ptas); + ptaDestroy(&ptad); +#endif + +#if ALL + /* Large distortion with inversion */ + lept_stderr("Large bilinear distortion with inversion\n"); + MakePtas(0, &ptas, &ptad); + pixa = pixaCreate(0); + pixs = pixRead("marge.jpg"); + pixg = pixConvertTo8(pixs, 0); + + pix1 = pixBilinearSampledPta(pixg, ptas, ptad, L_BRING_IN_WHITE); + regTestWritePixAndCheck(rp, pix1, IFF_JFIF_JPEG); /* 28 */ + pixaAddPix(pixa, pix1, L_INSERT); + + pix2 = pixBilinearPta(pixg, ptas, ptad, L_BRING_IN_WHITE); + regTestWritePixAndCheck(rp, pix2, IFF_JFIF_JPEG); /* 29 */ + pixaAddPix(pixa, pix2, L_INSERT); + + pix3 = pixBilinearSampledPta(pix1, ptad, ptas, L_BRING_IN_WHITE); + regTestWritePixAndCheck(rp, pix3, IFF_JFIF_JPEG); /* 30 */ + pixaAddPix(pixa, pix3, L_INSERT); + + pix4 = pixBilinearPta(pix2, ptad, ptas, L_BRING_IN_WHITE); + regTestWritePixAndCheck(rp, pix4, IFF_JFIF_JPEG); /* 31 */ + pixaAddPix(pixa, pix4, L_INSERT); + + pix1 = pixaDisplayTiledInColumns(pixa, 4, 1.0, 20, 0); + regTestWritePixAndCheck(rp, pix1, IFF_JFIF_JPEG); /* 32 */ + pixDisplayWithTitle(pix1, 800, 100, NULL, rp->display); + pixDestroy(&pix1); + pixaDestroy(&pixa); + + pixDestroy(&pixs); + pixDestroy(&pixg); + ptaDestroy(&ptas); + ptaDestroy(&ptad); +#endif + + return regTestCleanup(rp); +} + + +static void +MakePtas(l_int32 i, + PTA **pptas, + PTA **pptad) +{ + *pptas = ptaCreate(4); + ptaAddPt(*pptas, x1[i], y1[i]); + ptaAddPt(*pptas, x2[i], y2[i]); + ptaAddPt(*pptas, x3[i], y3[i]); + ptaAddPt(*pptas, x4[i], y4[i]); + *pptad = ptaCreate(4); + ptaAddPt(*pptad, xp1[i], yp1[i]); + ptaAddPt(*pptad, xp2[i], yp2[i]); + ptaAddPt(*pptad, xp3[i], yp3[i]); + ptaAddPt(*pptad, xp4[i], yp4[i]); + return; +} diff --git a/leptonica/prog/binarize_reg.c b/leptonica/prog/binarize_reg.c new file mode 100644 index 00000000..1bec31ba --- /dev/null +++ b/leptonica/prog/binarize_reg.c @@ -0,0 +1,180 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * binarize_reg.c + * + * Tests Sauvola local binarization and variants + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + +PIX *PixTest1(PIX *pixs, l_int32 size, l_float32 factor, L_REGPARAMS *rp); +PIX *PixTest2(PIX *pixs, l_int32 size, l_float32 factor, l_int32 nx, + l_int32 ny, L_REGPARAMS *rp); +void PixTest3(PIX *pixs, l_int32 size, l_float32 factor, + l_int32 nx, l_int32 ny, l_int32 paircount, L_REGPARAMS *rp); + +int main(int argc, + char **argv) +{ +PIX *pixs, *pixt1, *pixt2; +L_REGPARAMS *rp; + + if (regTestSetup(argc, argv, &rp)) + return 1; + + pixs = pixRead("w91frag.jpg"); + + PixTest3(pixs, 3, 0.20, 2, 3, 0, rp); + PixTest3(pixs, 6, 0.20, 100, 100, 1, rp); + PixTest3(pixs, 10, 0.40, 10, 10, 2, rp); + PixTest3(pixs, 10, 0.40, 20, 20, 3, rp); + PixTest3(pixs, 20, 0.34, 30, 30, 4, rp); + + pixt1 = PixTest1(pixs, 7, 0.34, rp); + pixt2 = PixTest2(pixs, 7, 0.34, 4, 4, rp); + regTestComparePix(rp, pixt1, pixt2); + pixDestroy(&pixt1); + pixDestroy(&pixt2); + + /* Do combination of contrast norm and sauvola */ + pixt1 = pixContrastNorm(NULL, pixs, 100, 100, 55, 1, 1); + pixSauvolaBinarizeTiled(pixt1, 8, 0.34, 1, 1, NULL, &pixt2); + regTestWritePixAndCheck(rp, pixt1, IFF_PNG); + regTestWritePixAndCheck(rp, pixt2, IFF_PNG); + pixDisplayWithTitle(pixt1, 100, 500, NULL, rp->display); + pixDisplayWithTitle(pixt2, 700, 500, NULL, rp->display); + pixDestroy(&pixt1); + pixDestroy(&pixt2); + + pixDestroy(&pixs); + return regTestCleanup(rp); +} + + +PIX * +PixTest1(PIX *pixs, + l_int32 size, + l_float32 factor, + L_REGPARAMS *rp) +{ +l_int32 w, h; +PIX *pixm, *pixsd, *pixth, *pixd, *pixt; +PIXA *pixa; + + pixm = pixsd = pixth = pixd = NULL; + pixGetDimensions(pixs, &w, &h, NULL); + + /* Get speed */ + startTimer(); + pixSauvolaBinarize(pixs, size, factor, 1, NULL, NULL, NULL, &pixd); + lept_stderr("\nSpeed: 1 tile, %7.3f Mpix/sec\n", + (w * h / 1000000.) / stopTimer()); + pixDestroy(&pixd); + + /* Get results */ + pixSauvolaBinarize(pixs, size, factor, 1, &pixm, &pixsd, &pixth, &pixd); + pixa = pixaCreate(0); + pixaAddPix(pixa, pixm, L_INSERT); + pixaAddPix(pixa, pixsd, L_INSERT); + pixaAddPix(pixa, pixth, L_INSERT); + pixaAddPix(pixa, pixd, L_COPY); + pixt = pixaDisplayTiledInColumns(pixa, 2, 1.0, 30, 2); + regTestWritePixAndCheck(rp, pixt, IFF_JFIF_JPEG); + if (rp->index < 5) + pixDisplayWithTitle(pixt, 100, 100, NULL, rp->display); + regTestWritePixAndCheck(rp, pixd, IFF_PNG); + + pixaDestroy(&pixa); + pixDestroy(&pixt); + return pixd; +} + + +PIX * +PixTest2(PIX *pixs, + l_int32 size, + l_float32 factor, + l_int32 nx, + l_int32 ny, + L_REGPARAMS *rp) +{ +l_int32 w, h; +PIX *pixth, *pixd, *pixt; +PIXA *pixa; + + pixth = pixd = NULL; + pixGetDimensions(pixs, &w, &h, NULL); + + /* Get speed */ + startTimer(); + pixSauvolaBinarizeTiled(pixs, size, factor, nx, ny, NULL, &pixd); + lept_stderr("Speed: %d x %d tiles, %7.3f Mpix/sec\n", + nx, ny, (w * h / 1000000.) / stopTimer()); + pixDestroy(&pixd); + + /* Get results */ + pixSauvolaBinarizeTiled(pixs, size, factor, nx, ny, &pixth, &pixd); + regTestWritePixAndCheck(rp, pixth, IFF_JFIF_JPEG); + regTestWritePixAndCheck(rp, pixd, IFF_PNG); + if (rp->index < 5 && rp->display) { + pixa = pixaCreate(0); + pixaAddPix(pixa, pixth, L_COPY); + pixaAddPix(pixa, pixd, L_COPY); + pixt = pixaDisplayTiledInColumns(pixa, 2, 1.0, 30, 2); + pixDisplayWithTitle(pixt, 100, 400, NULL, rp->display); + pixDestroy(&pixt); + pixaDestroy(&pixa); + } + + pixDestroy(&pixth); + return pixd; +} + + +void +PixTest3(PIX *pixs, + l_int32 size, + l_float32 factor, + l_int32 nx, + l_int32 ny, + l_int32 paircount, + L_REGPARAMS *rp) +{ +PIX *pixt1, *pixt2; + + pixt1 = PixTest1(pixs, size, factor, rp); + pixt2 = PixTest2(pixs, size, factor, nx, ny, rp); + regTestComparePix(rp, pixt1, pixt2); + pixDestroy(&pixt1); + pixDestroy(&pixt2); + return; +} diff --git a/leptonica/prog/binarize_set.c b/leptonica/prog/binarize_set.c new file mode 100644 index 00000000..874c541b --- /dev/null +++ b/leptonica/prog/binarize_set.c @@ -0,0 +1,177 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * binarize_set.c + * + * Does 5 different types of binarization for the contest. + * + * Method 1. Using local background normalization, followed by + * a global threshold. + * Method 2. Using local background normalization, followed by + * Otsu on the result to get a global threshold that + * can be applied to the normalized image. + * Method 3. Using local background normalization with two different + * thresholds. For the part of the image near the text, + * a high threshold can be chosen, to render the text + * fully in black. For the rest of the image, + * much of which is background, use a threshold based on + * the Otsu global value of the original image. + * Method 4. Background normalization followed by Sauvola binarization. + * Method 5. Contrast normalization followed by background normalization + * and thresholding. + * + * The first 3 were submitted to a binarization contest associated + * with ICDAR in 2009. The 4th and 5th work better for difficult + * images, such as w91frag.jpg. + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + +#define ALL 1 + + +int main(int argc, + char **argv) +{ +char *infile; +l_int32 w, d, threshval, ival, newval; +l_uint32 val; +PIX *pixs, *pixg, *pixg2; +PIX *pix1, *pix2; +PIXA *pixa; +static char mainName[] = "binarize_set"; + + if (argc != 2) + return ERROR_INT(" Syntax: binarize_set infile", mainName, 1); + infile = argv[1]; + + setLeptDebugOK(1); + lept_mkdir("lept/binar"); + + pixa = pixaCreate(5); + pixs = pixRead(infile); + pixGetDimensions(pixs, &w, NULL, &d); + pixaAddPix(pixa, pixs, L_INSERT); + pixDisplay(pixs, 100, 0); + +#if ALL + /* 1. Standard background normalization with a global threshold. */ + pixg = pixConvertTo8(pixs, 0); + pix1 = pixBackgroundNorm(pixg, NULL, NULL, 10, 15, 100, 50, 255, 2, 2); + pix2 = pixThresholdToBinary(pix1, 160); + pixWrite("/tmp/lept/binar/binar1.png", pix2, IFF_PNG); + pixDisplay(pix2, 100, 0); + pixaAddPix(pixa, pix2, L_INSERT); + pixDestroy(&pixg); + pixDestroy(&pix1); +#endif + +#if ALL + /* 2. Background normalization followed by Otsu thresholding. Otsu + * binarization attempts to split the image into two roughly equal + * sets of pixels, and it does a very poor job when there are large + * amounts of dark background. By doing a background normalization + * first (to get the background near 255), we remove this problem. + * Then we use a modified Otsu to estimate the best global + * threshold on the normalized image. */ + pixg = pixConvertTo8(pixs, 0); + pix1 = pixOtsuThreshOnBackgroundNorm(pixg, NULL, 10, 15, 100, + 50, 255, 2, 2, 0.10, &threshval); + lept_stderr("thresh val = %d\n", threshval); + pixaAddPix(pixa, pix1, L_INSERT); + pixWrite("/tmp/lept/binar/binar2.png", pix1, IFF_PNG); + pixDisplay(pix1, 100, 200); + pixDestroy(&pixg); +#endif + +#if ALL + /* 3. Background normalization with Otsu threshold estimation and + * masking for threshold selection. */ + pixg = pixConvertTo8(pixs, 0); + pix1 = pixMaskedThreshOnBackgroundNorm(pixg, NULL, 10, 15, 100, + 50, 2, 2, 0.10, &threshval); + lept_stderr("thresh val = %d\n", threshval); + pixaAddPix(pixa, pix1, L_INSERT); + pixWrite("/tmp/lept/binar/binar3.png", pix1, IFF_PNG); + pixDisplay(pix1, 100, 400); + pixDestroy(&pixg); +#endif + +#if ALL + /* 4. Background normalization followed by Sauvola binarization */ + if (d == 32) + pixg = pixConvertRGBToGray(pixs, 0.2, 0.7, 0.1); + else + pixg = pixConvertTo8(pixs, 0); + pixg2 = pixContrastNorm(NULL, pixg, 20, 20, 130, 2, 2); + pixSauvolaBinarizeTiled(pixg2, 25, 0.40, 1, 1, NULL, &pix1); + pixaAddPix(pixa, pix1, L_INSERT); + pixWrite("/tmp/lept/binar/binar4.png", pix1, IFF_PNG); + pixDisplay(pix1, 100, 600); + pixDestroy(&pixg); + pixDestroy(&pixg2); +#endif + +#if ALL + /* 5. Contrast normalization followed by background normalization, and + * thresholding. */ + if (d == 32) + pixg = pixConvertRGBToGray(pixs, 0.2, 0.7, 0.1); + else + pixg = pixConvertTo8(pixs, 0); + + pixOtsuAdaptiveThreshold(pixg, 5000, 5000, 0, 0, 0.1, &pix1, NULL); + pixGetPixel(pix1, 0, 0, &val); + ival = (l_int32)val; + newval = ival + (l_int32)(0.6 * (110 - ival)); + lept_stderr("th1 = %d, th2 = %d\n", ival, newval); + pixDestroy(&pix1); + + pixContrastNorm(pixg, pixg, 50, 50, 130, 2, 2); + pixg2 = pixBackgroundNorm(pixg, NULL, NULL, 20, 20, 70, 40, 200, 2, 2); + + ival = L_MIN(ival, 110); + pix1 = pixThresholdToBinary(pixg2, ival); + pixaAddPix(pixa, pix1, L_INSERT); + pixWrite("/tmp/lept/binar/binar5.png", pix1, IFF_PNG); + pixDisplay(pix1, 100, 800); + pixDestroy(&pixg); + pixDestroy(&pixg2); +#endif + + pix1 = pixaDisplayTiledInColumns(pixa, 2, 1.0, 30, 2); + pixWrite("/tmp/lept/binar/binar6.png", pix1, IFF_PNG); + pixDisplay(pix1, 1000, 0); + pixDestroy(&pix1); + pixaDestroy(&pixa); + + return 0; +} diff --git a/leptonica/prog/binarizefiles.c b/leptonica/prog/binarizefiles.c new file mode 100644 index 00000000..5285aa94 --- /dev/null +++ b/leptonica/prog/binarizefiles.c @@ -0,0 +1,120 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * binarizefiles.c + * + * Program that optionally scales and then binarizes a set of files, + * writing them to the specified directory in tiff-g4 format. + * The resolution is preserved. + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "string.h" +#include <sys/stat.h> +#include <sys/types.h> +#include "allheaders.h" + +l_int32 main(int argc, + char **argv) +{ +char buf[512], dirname[256]; +char *dirin, *pattern, *subdirout, *fname, *tail, *basename; +l_int32 thresh, i, n; +l_float32 scalefactor; +PIX *pix1, *pix2, *pix3, *pix4; +SARRAY *sa; +static char mainName[] = "binarizefiles.c"; + + if (argc != 6) { + lept_stderr( + "Syntax: binarizefiles dirin pattern thresh scalefact dirout\n" + " dirin: input directory for image files\n" + " pattern: use 'allfiles' to convert all files\n" + " in the directory\n" + " thresh: 0 for adaptive; > 0 for global thresh (e.g., 128)\n" + " scalefactor: in (0.0 ... 4.0]; use 1.0 to prevent scaling\n" + " subdirout: subdirectory of /tmp for output files\n"); + return 1; + } + dirin = argv[1]; + pattern = argv[2]; + thresh = atoi(argv[3]); + scalefactor = atof(argv[4]); + subdirout = argv[5]; + if (!strcmp(pattern, "allfiles")) + pattern = NULL; + if (scalefactor <= 0.0 || scalefactor > 4.0) { + L_WARNING("invalid scalefactor: setting to 1.0\n", mainName); + scalefactor = 1.0; + } + + setLeptDebugOK(1); + + /* Get the input filenames */ + sa = getSortedPathnamesInDirectory(dirin, pattern, 0, 0); + sarrayWriteStream(stderr, sa); + n = sarrayGetCount(sa); + + /* Write the output files */ + makeTempDirname(dirname, 256, subdirout); + lept_stderr("dirname: %s\n", dirname); + lept_mkdir(subdirout); + for (i = 0; i < n; i++) { + fname = sarrayGetString(sa, i, L_NOCOPY); + if ((pix1 = pixRead(fname)) == NULL) { + L_ERROR("file %s not read as image", mainName, fname); + continue; + } + splitPathAtDirectory(fname, NULL, &tail); + splitPathAtExtension(tail, &basename, NULL); + snprintf(buf, sizeof(buf), "%s/%s.tif", dirname, basename); + lept_free(tail); + lept_free(basename); + lept_stderr("fileout: %s\n", buf); + if (scalefactor != 1.0) + pix2 = pixScale(pix1, scalefactor, scalefactor); + else + pix2 = pixClone(pix1); + if (thresh == 0) { + pix4 = pixConvertTo8(pix2, 0); + pix3 = pixAdaptThresholdToBinary(pix4, NULL, 1.0); + pixDestroy(&pix4); + } else { + pix3 = pixConvertTo1(pix2, thresh); + } + pixWrite(buf, pix3, IFF_TIFF_G4); + pixDestroy(&pix1); + pixDestroy(&pix2); + pixDestroy(&pix3); + } + sarrayDestroy(&sa); + return 0; +} + diff --git a/leptonica/prog/bincompare.c b/leptonica/prog/bincompare.c new file mode 100644 index 00000000..2f9c72c5 --- /dev/null +++ b/leptonica/prog/bincompare.c @@ -0,0 +1,98 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * bincompare.c + * + * Bitwise comparison of two binary images + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + + /* set one of these to 1 */ +#define XOR 1 +#define SUBTRACT_1_FROM_2 0 +#define SUBTRACT_2_FROM_1 0 + +int main(int argc, + char **argv) +{ +l_int32 w, h, d, n; +char *filein1, *filein2, *fileout; +PIX *pixs1, *pixs2; +static char mainName[] = "bincompare"; + + if (argc != 4) + return ERROR_INT(" Syntax: bincompare filein1 filein2 fileout", + mainName, 1); + filein1 = argv[1]; + filein2 = argv[2]; + fileout = argv[3]; + setLeptDebugOK(1); + + if ((pixs1 = pixRead(filein1)) == NULL) + return ERROR_INT("pixs1 not made", mainName, 1); + if ((pixs2 = pixRead(filein2)) == NULL) + return ERROR_INT("pixs2 not made", mainName, 1); + + pixGetDimensions(pixs1, &w, &h, &d); + if (d != 1) + return ERROR_INT("pixs1 not binary", mainName, 1); + + pixCountPixels(pixs1, &n, NULL); + lept_stderr("Number of fg pixels in file1 = %d\n", n); + pixCountPixels(pixs2, &n, NULL); + lept_stderr("Number of fg pixels in file2 = %d\n", n); + +#if XOR + lept_stderr("xor: 1 ^ 2\n"); + pixRasterop(pixs1, 0, 0, w, h, PIX_SRC ^ PIX_DST, pixs2, 0, 0); + pixCountPixels(pixs1, &n, NULL); + lept_stderr("Number of fg pixels in XOR = %d\n", n); + pixWrite(fileout, pixs1, IFF_PNG); +#elif SUBTRACT_1_FROM_2 + lept_stderr("subtract: 2 - 1\n"); + pixRasterop(pixs1, 0, 0, w, h, PIX_SRC & PIX_NOT(PIX_DST), pixs2, 0, 0); + pixCountPixels(pixs1, &n, NULL); + lept_stderr("Number of fg pixels in 2 - 1 = %d\n", n); + pixWrite(fileout, pixs1, IFF_PNG); +#elif SUBTRACT_2_FROM_1 + lept_stderr("subtract: 1 - 2\n"); + pixRasterop(pixs1, 0, 0, w, h, PIX_DST & PIX_NOT(PIX_SRC), pixs2, 0, 0); + pixCountPixels(pixs1, &n, NULL); + lept_stderr("Number of fg pixels in 1 - 2 = %d\n", n); + pixWrite(fileout, pixs1, IFF_PNG); +#else + lept_stderr("no comparison selected\n"); +#endif + + return 0; +} + diff --git a/leptonica/prog/binding-example.45.jpg b/leptonica/prog/binding-example.45.jpg Binary files differnew file mode 100644 index 00000000..c6f3b68c --- /dev/null +++ b/leptonica/prog/binding-example.45.jpg diff --git a/leptonica/prog/binmorph1_reg.c b/leptonica/prog/binmorph1_reg.c new file mode 100644 index 00000000..1df62f3a --- /dev/null +++ b/leptonica/prog/binmorph1_reg.c @@ -0,0 +1,578 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * binmorph1_reg.c + * + * This is a thorough regression test of different methods for + * doing binary morphology. It should always be run if changes + * are made to the low-level morphology code. + * + * Some things to note: + * + * (1) We add a white border to guarantee safe closing; i.e., that + * closing is extensive for ASYMMETRIC_MORPH_BC. The separable + * sequence for closing is not safe, so if we didn't add the border + * ab initio, we would get different results for the atomic sequence + * closing (which is safe) and the separable one. + * + * (2) There are no differences in any of the operations: + * rasterop general + * rasterop brick + * morph sequence rasterop brick + * dwa brick + * morph sequence dwa brick + * morph sequence dwa composite brick + * when using ASYMMETRIC_MORPH_BC. + * However, when using SYMMETRIC_MORPH_BC, there are differences + * in two of the safe closing operations. These differences + * are in pix numbers 4 and 5. These differences are + * all due to the fact that for SYMMETRIC_MORPH_BC, we don't need + * to add any borders to get the correct answer. When we do + * add a border of 0 pixels, we naturally get a different result. + * + * (3) The 2-way Sel decomposition functions, implemented with the + * separable brick interface, are tested separately against + * the rasterop brick. See binmorph2_reg.c. + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + + /* set these ad lib. */ +#define WIDTH 21 /* brick sel width */ +#define HEIGHT 15 /* brick sel height */ + +void TestAll(L_REGPARAMS *rp, PIX *pix, l_int32 symmetric); + +int main(int argc, + char **argv) +{ +PIX *pixs; +L_REGPARAMS *rp; + + if (regTestSetup(argc, argv, &rp)) + return 1; + + pixs = pixRead("feyn-fract.tif"); + + TestAll(rp, pixs, FALSE); + TestAll(rp, pixs, TRUE); + pixDestroy(&pixs); + return regTestCleanup(rp); +} + + +void +TestAll(L_REGPARAMS *rp, + PIX *pixs, + l_int32 symmetric) +{ +l_int32 ok, same; +char sequence[512]; +PIX *pixref; +PIX *pix1, *pix2, *pix3, *pix4, *pix5, *pix6; +PIX *pix7, *pix8, *pix9, *pix10, *pix11; +PIX *pix12, *pix13, *pix14; +SEL *sel; + + if (symmetric) { + /* This works properly if there is an added border */ + resetMorphBoundaryCondition(SYMMETRIC_MORPH_BC); +#if 1 + pix1 = pixAddBorder(pixs, 32, 0); + pixTransferAllData(pixs, &pix1, 0, 0); +#endif + lept_stderr("Testing with symmetric boundary conditions\n"); + } else { + resetMorphBoundaryCondition(ASYMMETRIC_MORPH_BC); + lept_stderr("Testing with asymmetric boundary conditions\n"); + } + + /* This is our test sel */ + sel = selCreateBrick(HEIGHT, WIDTH, HEIGHT / 2, WIDTH / 2, SEL_HIT); + + /* Dilation */ + lept_stderr(" Testing dilation\n"); + ok = TRUE; + pixref = pixDilate(NULL, pixs, sel); /* new one */ + pix1 = pixCreateTemplate(pixs); + pixDilate(pix1, pixs, sel); /* existing one */ + pixEqual(pixref, pix1, &same); + if (!same) { + lept_stderr("pixref != pix1 !\n"); ok = FALSE; + } + pix2 = pixCopy(NULL, pixs); + pixDilate(pix2, pix2, sel); /* in-place */ + pixEqual(pixref, pix2, &same); + if (!same) { + lept_stderr("pixref != pix2 !\n"); ok = FALSE; + } + snprintf(sequence, sizeof(sequence), "d%d.%d", WIDTH, HEIGHT); + pix3 = pixMorphSequence(pixs, sequence, 0); /* sequence, atomic */ + pixEqual(pixref, pix3, &same); + if (!same) { + lept_stderr("pixref != pix3 !\n"); ok = FALSE; + } + snprintf(sequence, sizeof(sequence), "d%d.1 + d1.%d", WIDTH, HEIGHT); + pix4 = pixMorphSequence(pixs, sequence, 0); /* sequence, separable */ + pixEqual(pixref, pix4, &same); + if (!same) { + lept_stderr("pixref != pix4 !\n"); ok = FALSE; + } + pix5 = pixDilateBrick(NULL, pixs, WIDTH, HEIGHT); /* new one */ + pixEqual(pixref, pix5, &same); + if (!same) { + lept_stderr("pixref != pix5 !\n"); ok = FALSE; + } + pix6 = pixCreateTemplate(pixs); + pixDilateBrick(pix6, pixs, WIDTH, HEIGHT); /* existing one */ + pixEqual(pixref, pix6, &same); + if (!same) { + lept_stderr("pixref != pix6 !\n"); ok = FALSE; + } + pix7 = pixCopy(NULL, pixs); + pixDilateBrick(pix7, pix7, WIDTH, HEIGHT); /* in-place */ + pixEqual(pixref, pix7, &same); + if (!same) { + lept_stderr("pixref != pix7 !\n"); ok = FALSE; + } + pix8 = pixDilateBrickDwa(NULL, pixs, WIDTH, HEIGHT); /* new one */ + pixEqual(pixref, pix8, &same); + if (!same) { + lept_stderr("pixref != pix8 !\n"); ok = FALSE; + } + pix9 = pixCreateTemplate(pixs); + pixDilateBrickDwa(pix9, pixs, WIDTH, HEIGHT); /* existing one */ + pixEqual(pixref, pix9, &same); + if (!same) { + lept_stderr("pixref != pix9 !\n"); ok = FALSE; + } + pix10 = pixCopy(NULL, pixs); + pixDilateBrickDwa(pix10, pix10, WIDTH, HEIGHT); /* in-place */ + pixEqual(pixref, pix10, &same); + if (!same) { + lept_stderr("pixref != pix10 !\n"); ok = FALSE; + } + pix11 = pixCreateTemplate(pixs); + pixDilateCompBrickDwa(pix11, pixs, WIDTH, HEIGHT); /* existing one */ + pixEqual(pixref, pix11, &same); + if (!same) { + lept_stderr("pixref != pix11 !\n"); ok = FALSE; + } + snprintf(sequence, sizeof(sequence), "d%d.%d", WIDTH, HEIGHT); + pix12 = pixMorphCompSequence(pixs, sequence, 0); /* comp sequence */ + pixEqual(pixref, pix12, &same); + if (!same) { + lept_stderr("pixref != pix12!\n"); ok = FALSE; + } + pix13 = pixMorphSequenceDwa(pixs, sequence, 0); /* dwa sequence */ + pixEqual(pixref, pix13, &same); + if (!same) { + lept_stderr("pixref != pix13!\n"); ok = FALSE; + } + pixDestroy(&pixref); + pixDestroy(&pix1); + pixDestroy(&pix2); + pixDestroy(&pix3); + pixDestroy(&pix4); + pixDestroy(&pix5); + pixDestroy(&pix6); + pixDestroy(&pix7); + pixDestroy(&pix8); + pixDestroy(&pix9); + pixDestroy(&pix10); + pixDestroy(&pix11); + pixDestroy(&pix12); + pixDestroy(&pix13); + + /* Erosion */ + lept_stderr(" Testing erosion\n"); + pixref = pixErode(NULL, pixs, sel); /* new one */ + pix1 = pixCreateTemplate(pixs); + pixErode(pix1, pixs, sel); /* existing one */ + pixEqual(pixref, pix1, &same); + if (!same) { + lept_stderr("pixref != pix1 !\n"); ok = FALSE; + } + pix2 = pixCopy(NULL, pixs); + pixErode(pix2, pix2, sel); /* in-place */ + pixEqual(pixref, pix2, &same); + if (!same) { + lept_stderr("pixref != pix2 !\n"); ok = FALSE; + } + snprintf(sequence, sizeof(sequence), "e%d.%d", WIDTH, HEIGHT); + pix3 = pixMorphSequence(pixs, sequence, 0); /* sequence, atomic */ + pixEqual(pixref, pix3, &same); + if (!same) { + lept_stderr("pixref != pix3 !\n"); ok = FALSE; + } + snprintf(sequence, sizeof(sequence), "e%d.1 + e1.%d", WIDTH, HEIGHT); + pix4 = pixMorphSequence(pixs, sequence, 0); /* sequence, separable */ + pixEqual(pixref, pix4, &same); + if (!same) { + lept_stderr("pixref != pix4 !\n"); ok = FALSE; + } + pix5 = pixErodeBrick(NULL, pixs, WIDTH, HEIGHT); /* new one */ + pixEqual(pixref, pix5, &same); + if (!same) { + lept_stderr("pixref != pix5 !\n"); ok = FALSE; + } + pix6 = pixCreateTemplate(pixs); + pixErodeBrick(pix6, pixs, WIDTH, HEIGHT); /* existing one */ + pixEqual(pixref, pix6, &same); + if (!same) { + lept_stderr("pixref != pix6 !\n"); ok = FALSE; + } + pix7 = pixCopy(NULL, pixs); + pixErodeBrick(pix7, pix7, WIDTH, HEIGHT); /* in-place */ + pixEqual(pixref, pix7, &same); + if (!same) { + lept_stderr("pixref != pix7 !\n"); ok = FALSE; + } + pix8 = pixErodeBrickDwa(NULL, pixs, WIDTH, HEIGHT); /* new one */ + pixEqual(pixref, pix8, &same); + if (!same) { + lept_stderr("pixref != pix8 !\n"); ok = FALSE; + } + pix9 = pixCreateTemplate(pixs); + pixErodeBrickDwa(pix9, pixs, WIDTH, HEIGHT); /* existing one */ + pixEqual(pixref, pix9, &same); + if (!same) { + lept_stderr("pixref != pix9 !\n"); ok = FALSE; + } + pix10 = pixCopy(NULL, pixs); + pixErodeBrickDwa(pix10, pix10, WIDTH, HEIGHT); /* in-place */ + pixEqual(pixref, pix10, &same); + if (!same) { + lept_stderr("pixref != pix10 !\n"); ok = FALSE; + } + pix11 = pixCreateTemplate(pixs); + pixErodeCompBrickDwa(pix11, pixs, WIDTH, HEIGHT); /* existing one */ + pixEqual(pixref, pix11, &same); + if (!same) { + lept_stderr("pixref != pix11 !\n"); ok = FALSE; + } + + snprintf(sequence, sizeof(sequence), "e%d.%d", WIDTH, HEIGHT); + pix12 = pixMorphCompSequence(pixs, sequence, 0); /* comp sequence */ + pixEqual(pixref, pix12, &same); + if (!same) { + lept_stderr("pixref != pix12!\n"); ok = FALSE; + } + pix13 = pixMorphSequenceDwa(pixs, sequence, 0); /* dwa sequence */ + pixEqual(pixref, pix13, &same); + if (!same) { + lept_stderr("pixref != pix13!\n"); ok = FALSE; + } + pixDestroy(&pixref); + pixDestroy(&pix1); + pixDestroy(&pix2); + pixDestroy(&pix3); + pixDestroy(&pix4); + pixDestroy(&pix5); + pixDestroy(&pix6); + pixDestroy(&pix7); + pixDestroy(&pix8); + pixDestroy(&pix9); + pixDestroy(&pix10); + pixDestroy(&pix11); + pixDestroy(&pix12); + pixDestroy(&pix13); + + /* Opening */ + lept_stderr(" Testing opening\n"); + pixref = pixOpen(NULL, pixs, sel); /* new one */ + pix1 = pixCreateTemplate(pixs); + pixOpen(pix1, pixs, sel); /* existing one */ + pixEqual(pixref, pix1, &same); + if (!same) { + lept_stderr("pixref != pix1 !\n"); ok = FALSE; + } + pix2 = pixCopy(NULL, pixs); + pixOpen(pix2, pix2, sel); /* in-place */ + pixEqual(pixref, pix2, &same); + if (!same) { + lept_stderr("pixref != pix2 !\n"); ok = FALSE; + } + snprintf(sequence, sizeof(sequence), "o%d.%d", WIDTH, HEIGHT); + pix3 = pixMorphSequence(pixs, sequence, 0); /* sequence, atomic */ + pixEqual(pixref, pix3, &same); + if (!same) { + lept_stderr("pixref != pix3 !\n"); ok = FALSE; + } + snprintf(sequence, sizeof(sequence), "e%d.%d + d%d.%d", + WIDTH, HEIGHT, WIDTH, HEIGHT); + pix4 = pixMorphSequence(pixs, sequence, 0); /* sequence, separable */ + pixEqual(pixref, pix4, &same); + if (!same) { + lept_stderr("pixref != pix4 !\n"); ok = FALSE; + } + snprintf(sequence, sizeof(sequence), "e%d.1 + e1.%d + d%d.1 + d1.%d", + WIDTH, HEIGHT, WIDTH, HEIGHT); + pix5 = pixMorphSequence(pixs, sequence, 0); /* sequence, separable^2 */ + pixEqual(pixref, pix5, &same); + if (!same) { + lept_stderr("pixref != pix5 !\n"); ok = FALSE; + } + pix6 = pixOpenBrick(NULL, pixs, WIDTH, HEIGHT); /* new one */ + pixEqual(pixref, pix6, &same); + if (!same) { + lept_stderr("pixref != pix6 !\n"); ok = FALSE; + } + pix7 = pixCreateTemplate(pixs); + pixOpenBrick(pix7, pixs, WIDTH, HEIGHT); /* existing one */ + pixEqual(pixref, pix7, &same); + if (!same) { + lept_stderr("pixref != pix7 !\n"); ok = FALSE; + } + pix8 = pixCopy(NULL, pixs); /* in-place */ + pixOpenBrick(pix8, pix8, WIDTH, HEIGHT); /* existing one */ + pixEqual(pixref, pix8, &same); + if (!same) { + lept_stderr("pixref != pix8 !\n"); ok = FALSE; + } + pix9 = pixOpenBrickDwa(NULL, pixs, WIDTH, HEIGHT); /* new one */ + pixEqual(pixref, pix9, &same); + if (!same) { + lept_stderr("pixref != pix9 !\n"); ok = FALSE; + } + pix10 = pixCreateTemplate(pixs); + pixOpenBrickDwa(pix10, pixs, WIDTH, HEIGHT); /* existing one */ + pixEqual(pixref, pix10, &same); + if (!same) { + lept_stderr("pixref != pix10 !\n"); ok = FALSE; + } + pix11 = pixCopy(NULL, pixs); + pixOpenBrickDwa(pix11, pix11, WIDTH, HEIGHT); /* in-place */ + pixEqual(pixref, pix11, &same); + if (!same) { + lept_stderr("pixref != pix11 !\n"); ok = FALSE; + } + snprintf(sequence, sizeof(sequence), "o%d.%d", WIDTH, HEIGHT); + pix12 = pixMorphCompSequence(pixs, sequence, 0); /* comp sequence */ + pixEqual(pixref, pix12, &same); + if (!same) { + lept_stderr("pixref != pix12!\n"); ok = FALSE; + } + + pix13 = pixMorphSequenceDwa(pixs, sequence, 0); /* dwa sequence */ + pixEqual(pixref, pix13, &same); + if (!same) { + lept_stderr("pixref != pix13!\n"); ok = FALSE; + } + pix14 = pixCreateTemplate(pixs); + pixOpenCompBrickDwa(pix14, pixs, WIDTH, HEIGHT); /* existing one */ + pixEqual(pixref, pix14, &same); + if (!same) { + lept_stderr("pixref != pix14 !\n"); ok = FALSE; + } + + pixDestroy(&pixref); + pixDestroy(&pix1); + pixDestroy(&pix2); + pixDestroy(&pix3); + pixDestroy(&pix4); + pixDestroy(&pix5); + pixDestroy(&pix6); + pixDestroy(&pix7); + pixDestroy(&pix8); + pixDestroy(&pix9); + pixDestroy(&pix10); + pixDestroy(&pix11); + pixDestroy(&pix12); + pixDestroy(&pix13); + pixDestroy(&pix14); + + /* Closing */ + lept_stderr(" Testing closing\n"); + pixref = pixClose(NULL, pixs, sel); /* new one */ + pix1 = pixCreateTemplate(pixs); + pixClose(pix1, pixs, sel); /* existing one */ + pixEqual(pixref, pix1, &same); + if (!same) { + lept_stderr("pixref != pix1 !\n"); ok = FALSE; + } + pix2 = pixCopy(NULL, pixs); + pixClose(pix2, pix2, sel); /* in-place */ + pixEqual(pixref, pix2, &same); + if (!same) { + lept_stderr("pixref != pix2 !\n"); ok = FALSE; + } + snprintf(sequence, sizeof(sequence), "d%d.%d + e%d.%d", + WIDTH, HEIGHT, WIDTH, HEIGHT); + pix3 = pixMorphSequence(pixs, sequence, 0); /* sequence, separable */ + pixEqual(pixref, pix3, &same); + if (!same) { + lept_stderr("pixref != pix3 !\n"); ok = FALSE; + } + snprintf(sequence, sizeof(sequence), "d%d.1 + d1.%d + e%d.1 + e1.%d", + WIDTH, HEIGHT, WIDTH, HEIGHT); + pix4 = pixMorphSequence(pixs, sequence, 0); /* sequence, separable^2 */ + pixEqual(pixref, pix4, &same); + if (!same) { + lept_stderr("pixref != pix4 !\n"); ok = FALSE; + } + pix5 = pixCloseBrick(NULL, pixs, WIDTH, HEIGHT); /* new one */ + pixEqual(pixref, pix5, &same); + if (!same) { + lept_stderr("pixref != pix5 !\n"); ok = FALSE; + } + pix6 = pixCreateTemplate(pixs); + pixCloseBrick(pix6, pixs, WIDTH, HEIGHT); /* existing one */ + pixEqual(pixref, pix6, &same); + if (!same) { + lept_stderr("pixref != pix6 !\n"); ok = FALSE; + } + pix7 = pixCopy(NULL, pixs); /* in-place */ + pixCloseBrick(pix7, pix7, WIDTH, HEIGHT); /* existing one */ + pixEqual(pixref, pix7, &same); + if (!same) { + lept_stderr("pixref != pix7 !\n"); ok = FALSE; + } + pixDestroy(&pixref); + pixDestroy(&pix1); + pixDestroy(&pix2); + pixDestroy(&pix3); + pixDestroy(&pix4); + pixDestroy(&pix5); + pixDestroy(&pix6); + pixDestroy(&pix7); + + /* Safe closing (using pix, not pixs) */ + lept_stderr(" Testing safe closing\n"); + pixref = pixCloseSafe(NULL, pixs, sel); /* new one */ + pix1 = pixCreateTemplate(pixs); + pixCloseSafe(pix1, pixs, sel); /* existing one */ + pixEqual(pixref, pix1, &same); + if (!same) { + lept_stderr("pixref != pix1 !\n"); ok = FALSE; + } + pix2 = pixCopy(NULL, pixs); + pixCloseSafe(pix2, pix2, sel); /* in-place */ + pixEqual(pixref, pix2, &same); + if (!same) { + lept_stderr("pixref != pix2 !\n"); ok = FALSE; + } + snprintf(sequence, sizeof(sequence), "c%d.%d", WIDTH, HEIGHT); + pix3 = pixMorphSequence(pixs, sequence, 0); /* sequence, atomic */ + pixEqual(pixref, pix3, &same); + if (!same) { + lept_stderr("pixref != pix3 !\n"); ok = FALSE; + } + snprintf(sequence, sizeof(sequence), "b32 + d%d.%d + e%d.%d", + WIDTH, HEIGHT, WIDTH, HEIGHT); + pix4 = pixMorphSequence(pixs, sequence, 0); /* sequence, separable */ + pixEqual(pixref, pix4, &same); + if (!same) { + lept_stderr("pixref != pix4 !\n"); ok = FALSE; + } + snprintf(sequence, sizeof(sequence), "b32 + d%d.1 + d1.%d + e%d.1 + e1.%d", + WIDTH, HEIGHT, WIDTH, HEIGHT); + pix5 = pixMorphSequence(pixs, sequence, 0); /* sequence, separable^2 */ + pixEqual(pixref, pix5, &same); + if (!same) { + lept_stderr("pixref != pix5 !\n"); ok = FALSE; + } + pix6 = pixCloseSafeBrick(NULL, pixs, WIDTH, HEIGHT); /* new one */ + pixEqual(pixref, pix6, &same); + if (!same) { + lept_stderr("pixref != pix6 !\n"); ok = FALSE; + } + pix7 = pixCreateTemplate(pixs); + pixCloseSafeBrick(pix7, pixs, WIDTH, HEIGHT); /* existing one */ + pixEqual(pixref, pix7, &same); + if (!same) { + lept_stderr("pixref != pix7 !\n"); ok = FALSE; + } + pix8 = pixCopy(NULL, pixs); /* in-place */ + pixCloseSafeBrick(pix8, pix8, WIDTH, HEIGHT); /* existing one */ + pixEqual(pixref, pix8, &same); + if (!same) { + lept_stderr("pixref != pix8 !\n"); ok = FALSE; + } + pix9 = pixCloseBrickDwa(NULL, pixs, WIDTH, HEIGHT); /* new one */ + pixEqual(pixref, pix9, &same); + if (!same) { + lept_stderr("pixref != pix9 !\n"); ok = FALSE; + } + pix10 = pixCreateTemplate(pixs); + pixCloseBrickDwa(pix10, pixs, WIDTH, HEIGHT); /* existing one */ + pixEqual(pixref, pix10, &same); + if (!same) { + lept_stderr("pixref != pix10 !\n"); ok = FALSE; + } + pix11 = pixCopy(NULL, pixs); + pixCloseBrickDwa(pix11, pix11, WIDTH, HEIGHT); /* in-place */ + pixEqual(pixref, pix11, &same); + if (!same) { + lept_stderr("pixref != pix11 !\n"); ok = FALSE; + } + snprintf(sequence, sizeof(sequence), "c%d.%d", WIDTH, HEIGHT); + pix12 = pixMorphCompSequence(pixs, sequence, 0); /* comp sequence */ + pixEqual(pixref, pix12, &same); + if (!same) { + lept_stderr("pixref != pix12!\n"); ok = FALSE; + } + pix13 = pixMorphSequenceDwa(pixs, sequence, 0); /* dwa sequence */ + pixEqual(pixref, pix13, &same); + if (!same) { + lept_stderr("pixref != pix13!\n"); ok = FALSE; + } + pix14 = pixCreateTemplate(pixs); + pixCloseCompBrickDwa(pix14, pixs, WIDTH, HEIGHT); /* existing one */ + pixEqual(pixref, pix14, &same); + if (!same) { + lept_stderr("pixref != pix14 !\n"); ok = FALSE; + } + + pixDestroy(&pixref); + pixDestroy(&pix1); + pixDestroy(&pix2); + pixDestroy(&pix3); + pixDestroy(&pix4); + pixDestroy(&pix5); + pixDestroy(&pix6); + pixDestroy(&pix7); + pixDestroy(&pix8); + pixDestroy(&pix9); + pixDestroy(&pix10); + pixDestroy(&pix11); + pixDestroy(&pix12); + pixDestroy(&pix13); + pixDestroy(&pix14); + + regTestCompareValues(rp, TRUE, ok, 0); + if (ok) + lept_stderr(" All morph tests OK!\n"); + else + lept_stderr(" Some morph tests failed!\n"); + selDestroy(&sel); +} + diff --git a/leptonica/prog/binmorph2_reg.c b/leptonica/prog/binmorph2_reg.c new file mode 100644 index 00000000..7b34794f --- /dev/null +++ b/leptonica/prog/binmorph2_reg.c @@ -0,0 +1,227 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * binmorph2_reg.c + * + * Thorough regression test for binary separable rasterops, + * using the sequence interpreters. This compares the + * results for 2-way composite Sels with unitary Sels, + * all invoked on the separable block morph ops. + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + +static const l_int32 MAX_SEL_SIZE = 120; + +static void writeResult(const char *sequence, l_int32 same); + + +int main(int argc, + char **argv) +{ +char buffer1[256]; +char buffer2[256]; +l_int32 i, same, same2, factor1, factor2, diff, success; +PIX *pixs, *pixsd, *pixt1, *pixt2, *pixt3; +static char mainName[] = "binmorph2_reg"; + + if (argc != 1) + return ERROR_INT(" Syntax: binmorph2_reg", mainName, 1); + + setLeptDebugOK(1); + pixs = pixRead("feyn-fract.tif"); + pixsd = pixMorphCompSequence(pixs, "d5.5", 0); + success = TRUE; + for (i = 1; i < MAX_SEL_SIZE; i++) { + + /* Check if the size is exactly decomposable */ + selectComposableSizes(i, &factor1, &factor2); + diff = factor1 * factor2 - i; + lept_stderr("%d: (%d, %d): %d\n", i, factor1, factor2, diff); + + /* Carry out operations on identical sized Sels: dilation */ + snprintf(buffer1, sizeof(buffer1), "d%d.%d", i + diff, i + diff); + snprintf(buffer2, sizeof(buffer2), "d%d.%d", i, i); + pixt1 = pixMorphSequence(pixsd, buffer1, 0); + pixt2 = pixMorphCompSequence(pixsd, buffer2, 0); + pixEqual(pixt1, pixt2, &same); + if (i < 64) { + pixt3 = pixMorphCompSequenceDwa(pixsd, buffer2, 0); + pixEqual(pixt1, pixt3, &same2); + } else { + pixt3 = NULL; + same2 = TRUE; + } + if (same && same2) + writeResult(buffer1, 1); + else { + writeResult(buffer1, 0); + success = FALSE; + } + pixDestroy(&pixt1); + pixDestroy(&pixt2); + pixDestroy(&pixt3); + + /* ... erosion */ + snprintf(buffer1, sizeof(buffer1), "e%d.%d", i + diff, i + diff); + snprintf(buffer2, sizeof(buffer2), "e%d.%d", i, i); + pixt1 = pixMorphSequence(pixsd, buffer1, 0); + pixt2 = pixMorphCompSequence(pixsd, buffer2, 0); + pixEqual(pixt1, pixt2, &same); + if (i < 64) { + pixt3 = pixMorphCompSequenceDwa(pixsd, buffer2, 0); + pixEqual(pixt1, pixt3, &same2); + } else { + pixt3 = NULL; + same2 = TRUE; + } + if (same && same2) + writeResult(buffer1, 1); + else { + writeResult(buffer1, 0); + success = FALSE; + } + pixDestroy(&pixt1); + pixDestroy(&pixt2); + pixDestroy(&pixt3); + + /* ... opening */ + snprintf(buffer1, sizeof(buffer1), "o%d.%d", i + diff, i + diff); + snprintf(buffer2, sizeof(buffer2), "o%d.%d", i, i); + pixt1 = pixMorphSequence(pixsd, buffer1, 0); + pixt2 = pixMorphCompSequence(pixsd, buffer2, 0); + pixEqual(pixt1, pixt2, &same); + if (i < 64) { + pixt3 = pixMorphCompSequenceDwa(pixsd, buffer2, 0); + pixEqual(pixt1, pixt3, &same2); + } else { + pixt3 = NULL; + same2 = TRUE; + } + if (same && same2) + writeResult(buffer1, 1); + else { + writeResult(buffer1, 0); + success = FALSE; + } + pixDestroy(&pixt1); + pixDestroy(&pixt2); + pixDestroy(&pixt3); + + /* ... closing */ + snprintf(buffer1, sizeof(buffer1), "c%d.%d", i + diff, i + diff); + snprintf(buffer2, sizeof(buffer2), "c%d.%d", i, i); + pixt1 = pixMorphSequence(pixsd, buffer1, 0); + pixt2 = pixMorphCompSequence(pixsd, buffer2, 0); + pixEqual(pixt1, pixt2, &same); + if (i < 64) { + pixt3 = pixMorphCompSequenceDwa(pixsd, buffer2, 0); + pixEqual(pixt1, pixt3, &same2); + } else { + pixt3 = NULL; + same2 = TRUE; + } + if (same && same2) + writeResult(buffer1, 1); + else { + writeResult(buffer1, 0); + success = FALSE; + } + pixDestroy(&pixt1); + pixDestroy(&pixt2); + pixDestroy(&pixt3); + + } + pixDestroy(&pixs); + pixDestroy(&pixsd); + + if (success) + lept_stderr("\n---------- Success: no errors ----------\n"); + else + lept_stderr("\n---------- Failure: error(s) found -----------\n"); + return 0; +} + + +static void writeResult(const char *sequence, + l_int32 same) +{ + if (same) + lept_stderr("Sequence %s: SUCCESS\n", sequence); + else + lept_stderr("Sequence %s: FAILURE\n", sequence); +} + + +#if 0 + for (i = 1; i < 400; i++) { + selectComposableSizes(i, &factor1, &factor2); + diff = factor1 * factor2 - i; + lept_stderr("%d: (%d, %d): %d\n", + i, factor1, factor2, diff); + selectComposableSels(i, L_HORIZ, &sel1, &sel2); + selDestroy(&sel1); + selDestroy(&sel2); + } +#endif + +#if 0 + selectComposableSels(68, L_HORIZ, &sel1, &sel2); /* 17, 4 */ + str = selPrintToString(sel2); + lept_stderr(str); + selDestroy(&sel1); + selDestroy(&sel2); + lept_free(str); + selectComposableSels(70, L_HORIZ, &sel1, &sel2); /* 10, 7 */ + str = selPrintToString(sel2); + selDestroy(&sel1); + selDestroy(&sel2); + lept_stderr(str); + lept_free(str); + selectComposableSels(85, L_HORIZ, &sel1, &sel2); /* 17, 5 */ + str = selPrintToString(sel2); + selDestroy(&sel1); + selDestroy(&sel2); + lept_stderr(str); + lept_free(str); + selectComposableSels(96, L_HORIZ, &sel1, &sel2); /* 12, 8 */ + str = selPrintToString(sel2); + selDestroy(&sel1); + selDestroy(&sel2); + lept_stderr(str); + lept_free(str); + + { SELA *sela; + sela = selaAddBasic(NULL); + selaWrite("/tmp/junksela.sela", sela); + selaDestroy(&sela); + } +#endif diff --git a/leptonica/prog/binmorph3_reg.c b/leptonica/prog/binmorph3_reg.c new file mode 100644 index 00000000..36a1ebac --- /dev/null +++ b/leptonica/prog/binmorph3_reg.c @@ -0,0 +1,404 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * binmorph3_reg.c + * + * This is a regression test of dwa functions. It should always + * be run if changes are made to the low-level morphology code. + * + * Some things to note: + * + * (1) This compares results for these operations: + * - rasterop brick (non-separable, separable) + * - dwa brick (separable), as implemented in morphdwa.c + * - dwa brick separable, but using lower-level non-separable + * autogen'd code. + * + * (2) See in-line comments for ordinary closing and safe closing. + * The complication is due to the fact that the results differ + * for symmetric and asymmetric b.c., so we must do some + * fine adjustments of the border when implementing using + * the lower-level code directly. + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + +l_int32 TestAll(L_REGPARAMS *rp, PIX *pixs, l_int32 symmetric); + +int main(int argc, + char **argv) +{ +PIX *pixs; +L_REGPARAMS *rp; + + if (regTestSetup(argc, argv, &rp)) + return 1; + + pixs = pixRead("feyn-fract.tif"); + + TestAll(rp, pixs, FALSE); + TestAll(rp, pixs, TRUE); + pixDestroy(&pixs); + return regTestCleanup(rp); +} + +l_int32 +TestAll(L_REGPARAMS *rp, + PIX *pixs, + l_int32 symmetric) +{ +char *selnameh, *selnamev; +l_int32 ok, same, w, h, i, bordercolor, extraborder; +l_int32 width[3] = {21, 1, 21}; +l_int32 height[3] = {1, 7, 7}; +PIX *pixref, *pix0, *pix1, *pix2, *pix3, *pix4; +SEL *sel; +SELA *sela; + + + if (symmetric) { + resetMorphBoundaryCondition(SYMMETRIC_MORPH_BC); + lept_stderr("Testing with symmetric boundary conditions\n" + "==========================================\n"); + } else { + resetMorphBoundaryCondition(ASYMMETRIC_MORPH_BC); + lept_stderr("Testing with asymmetric boundary conditions\n" + "==========================================\n"); + } + + for (i = 0; i < 3; i++) { + w = width[i]; + h = height[i]; + sel = selCreateBrick(h, w, h / 2, w / 2, SEL_HIT); + selnameh = NULL; + selnamev = NULL; + + + /* Get the selnames for horiz and vert */ + sela = selaAddBasic(NULL); + if (w > 1) { + if ((selnameh = selaGetBrickName(sela, w, 1)) == NULL) { + selaDestroy(&sela); + selDestroy(&sel); + return ERROR_INT("dwa hor sel not defined", rp->testname, 1); + } + } + if (h > 1) { + if ((selnamev = selaGetBrickName(sela, 1, h)) == NULL) { + selaDestroy(&sela); + selDestroy(&sel); + return ERROR_INT("dwa vert sel not defined", rp->testname, 1); + } + } + lept_stderr("w = %d, h = %d, selh = %s, selv = %s\n", + w, h, selnameh, selnamev); + ok = TRUE; + selaDestroy(&sela); + + /* ----------------- Dilation ----------------- */ + lept_stderr("Testing dilation\n"); + pixref = pixDilate(NULL, pixs, sel); + pix1 = pixDilateBrickDwa(NULL, pixs, w, h); + pixEqual(pixref, pix1, &same); + if (!same) { + lept_stderr("pixref != pix1 !\n"); ok = FALSE; + } + pixDestroy(&pix1); + + if (w > 1) + pix1 = pixMorphDwa_1(NULL, pixs, L_MORPH_DILATE, selnameh); + else + pix1 = pixClone(pixs); + if (h > 1) + pix2 = pixMorphDwa_1(NULL, pix1, L_MORPH_DILATE, selnamev); + else + pix2 = pixClone(pix1); + pixEqual(pixref, pix2, &same); + if (!same) { + lept_stderr("pixref != pix2 !\n"); ok = FALSE; + } + pixDestroy(&pix1); + pixDestroy(&pix2); + + pix1 = pixAddBorder(pixs, 32, 0); + if (w > 1) + pix2 = pixFMorphopGen_1(NULL, pix1, L_MORPH_DILATE, selnameh); + else + pix2 = pixClone(pix1); + if (h > 1) + pix3 = pixFMorphopGen_1(NULL, pix2, L_MORPH_DILATE, selnamev); + else + pix3 = pixClone(pix2); + pix4 = pixRemoveBorder(pix3, 32); + pixEqual(pixref, pix4, &same); + if (!same) { + lept_stderr("pixref != pix4 !\n"); ok = FALSE; + } + pixDestroy(&pixref); + pixDestroy(&pix1); + pixDestroy(&pix2); + pixDestroy(&pix3); + pixDestroy(&pix4); + + /* ----------------- Erosion ----------------- */ + lept_stderr("Testing erosion\n"); + pixref = pixErode(NULL, pixs, sel); + pix1 = pixErodeBrickDwa(NULL, pixs, w, h); + pixEqual(pixref, pix1, &same); + if (!same) { + lept_stderr("pixref != pix1 !\n"); ok = FALSE; + } + pixDestroy(&pix1); + + if (w > 1) + pix1 = pixMorphDwa_1(NULL, pixs, L_MORPH_ERODE, selnameh); + else + pix1 = pixClone(pixs); + if (h > 1) + pix2 = pixMorphDwa_1(NULL, pix1, L_MORPH_ERODE, selnamev); + else + pix2 = pixClone(pix1); + pixEqual(pixref, pix2, &same); + if (!same) { + lept_stderr("pixref != pix2 !\n"); ok = FALSE; + } + pixDestroy(&pix1); + pixDestroy(&pix2); + + pix1 = pixAddBorder(pixs, 32, 0); + if (w > 1) + pix2 = pixFMorphopGen_1(NULL, pix1, L_MORPH_ERODE, selnameh); + else + pix2 = pixClone(pix1); + if (h > 1) + pix3 = pixFMorphopGen_1(NULL, pix2, L_MORPH_ERODE, selnamev); + else + pix3 = pixClone(pix2); + pix4 = pixRemoveBorder(pix3, 32); + pixEqual(pixref, pix4, &same); + if (!same) { + lept_stderr("pixref != pix4 !\n"); ok = FALSE; + } + pixDestroy(&pixref); + pixDestroy(&pix1); + pixDestroy(&pix2); + pixDestroy(&pix3); + pixDestroy(&pix4); + + /* ----------------- Opening ----------------- */ + lept_stderr("Testing opening\n"); + pixref = pixOpen(NULL, pixs, sel); + pix1 = pixOpenBrickDwa(NULL, pixs, w, h); + pixEqual(pixref, pix1, &same); + if (!same) { + lept_stderr("pixref != pix1 !\n"); ok = FALSE; + } + pixDestroy(&pix1); + + if (h == 1) + pix2 = pixMorphDwa_1(NULL, pixs, L_MORPH_OPEN, selnameh); + else if (w == 1) + pix2 = pixMorphDwa_1(NULL, pixs, L_MORPH_OPEN, selnamev); + else { + pix1 = pixMorphDwa_1(NULL, pixs, L_MORPH_ERODE, selnameh); + pix2 = pixMorphDwa_1(NULL, pix1, L_MORPH_ERODE, selnamev); + pixMorphDwa_1(pix1, pix2, L_MORPH_DILATE, selnameh); + pixMorphDwa_1(pix2, pix1, L_MORPH_DILATE, selnamev); + pixDestroy(&pix1); + } + pixEqual(pixref, pix2, &same); + if (!same) { + lept_stderr("pixref != pix2 !\n"); ok = FALSE; + } + pixDestroy(&pix2); + + pix1 = pixAddBorder(pixs, 32, 0); + if (h == 1) + pix3 = pixFMorphopGen_1(NULL, pix1, L_MORPH_OPEN, selnameh); + else if (w == 1) + pix3 = pixFMorphopGen_1(NULL, pix1, L_MORPH_OPEN, selnamev); + else { + pix2 = pixFMorphopGen_1(NULL, pix1, L_MORPH_ERODE, selnameh); + pix3 = pixFMorphopGen_1(NULL, pix2, L_MORPH_ERODE, selnamev); + pixFMorphopGen_1(pix2, pix3, L_MORPH_DILATE, selnameh); + pixFMorphopGen_1(pix3, pix2, L_MORPH_DILATE, selnamev); + pixDestroy(&pix2); + } + pix4 = pixRemoveBorder(pix3, 32); + pixEqual(pixref, pix4, &same); + if (!same) { + lept_stderr("pixref != pix4 !\n"); ok = FALSE; + } + pixDestroy(&pixref); + pixDestroy(&pix1); + pixDestroy(&pix3); + pixDestroy(&pix4); + + /* ----------------- Closing ----------------- */ + lept_stderr("Testing closing\n"); + pixref = pixClose(NULL, pixs, sel); + + /* Note: L_MORPH_CLOSE for h==1 or w==1 gives safe closing, + * so we can't use it here. */ + if (h == 1) { + pix1 = pixMorphDwa_1(NULL, pixs, L_MORPH_DILATE, selnameh); + pix2 = pixMorphDwa_1(NULL, pix1, L_MORPH_ERODE, selnameh); + } + else if (w == 1) { + pix1 = pixMorphDwa_1(NULL, pixs, L_MORPH_DILATE, selnamev); + pix2 = pixMorphDwa_1(NULL, pix1, L_MORPH_ERODE, selnamev); + } + else { + pix1 = pixMorphDwa_1(NULL, pixs, L_MORPH_DILATE, selnameh); + pix2 = pixMorphDwa_1(NULL, pix1, L_MORPH_DILATE, selnamev); + pixMorphDwa_1(pix1, pix2, L_MORPH_ERODE, selnameh); + pixMorphDwa_1(pix2, pix1, L_MORPH_ERODE, selnamev); + } + pixDestroy(&pix1); + pixEqual(pixref, pix2, &same); + if (!same) { + lept_stderr("pixref != pix2 !\n"); ok = FALSE; + } + pixDestroy(&pix2); + + /* Note: by adding only 32 pixels of border, we get + * the normal closing operation, even when calling + * with L_MORPH_CLOSE, because it requires 32 pixels + * of border to be safe. */ + pix1 = pixAddBorder(pixs, 32, 0); + if (h == 1) + pix3 = pixFMorphopGen_1(NULL, pix1, L_MORPH_CLOSE, selnameh); + else if (w == 1) + pix3 = pixFMorphopGen_1(NULL, pix1, L_MORPH_CLOSE, selnamev); + else { + pix2 = pixFMorphopGen_1(NULL, pix1, L_MORPH_DILATE, selnameh); + pix3 = pixFMorphopGen_1(NULL, pix2, L_MORPH_DILATE, selnamev); + pixFMorphopGen_1(pix2, pix3, L_MORPH_ERODE, selnameh); + pixFMorphopGen_1(pix3, pix2, L_MORPH_ERODE, selnamev); + pixDestroy(&pix2); + } + pix4 = pixRemoveBorder(pix3, 32); + pixEqual(pixref, pix4, &same); + if (!same) { + lept_stderr("pixref != pix4 !\n"); ok = FALSE; + } + pixDestroy(&pixref); + pixDestroy(&pix1); + pixDestroy(&pix3); + pixDestroy(&pix4); + + /* ------------- Safe Closing ----------------- */ + lept_stderr("Testing safe closing\n"); + pixref = pixCloseSafe(NULL, pixs, sel); + pix0 = pixCloseSafeBrick(NULL, pixs, w, h); + pixEqual(pixref, pix0, &same); + if (!same) { + lept_stderr("pixref != pix0 !\n"); ok = FALSE; + } + pixDestroy(&pix0); + + pix1 = pixCloseBrickDwa(NULL, pixs, w, h); + pixEqual(pixref, pix1, &same); + if (!same) { + lept_stderr("pixref != pix1 !\n"); ok = FALSE; + } + pixDestroy(&pix1); + + bordercolor = getMorphBorderPixelColor(L_MORPH_ERODE, 1); + if (bordercolor == 0) /* asymmetric b.c. */ + extraborder = 32; + else /* symmetric b.c. */ + extraborder = 0; + + /* Note: for safe closing we need 64 border pixels. + * However, when we implement a separable Sel + * with pixMorphDwa_*(), we must do dilation and + * erosion explicitly, and these functions only + * add/remove a 32-pixel border. Thus, for that + * case we must add an additional 32-pixel border + * before doing the operations. That is the reason + * why the implementation in morphdwa.c adds the + * 64 bit border and then uses the lower-level + * pixFMorphopGen_*() functions. */ + if (h == 1) + pix3 = pixMorphDwa_1(NULL, pixs, L_MORPH_CLOSE, selnameh); + else if (w == 1) + pix3 = pixMorphDwa_1(NULL, pixs, L_MORPH_CLOSE, selnamev); + else { + pix0 = pixAddBorder(pixs, extraborder, 0); + pix1 = pixMorphDwa_1(NULL, pix0, L_MORPH_DILATE, selnameh); + pix2 = pixMorphDwa_1(NULL, pix1, L_MORPH_DILATE, selnamev); + pixMorphDwa_1(pix1, pix2, L_MORPH_ERODE, selnameh); + pixMorphDwa_1(pix2, pix1, L_MORPH_ERODE, selnamev); + pix3 = pixRemoveBorder(pix2, extraborder); + pixDestroy(&pix0); + pixDestroy(&pix1); + pixDestroy(&pix2); + } + pixEqual(pixref, pix3, &same); + if (!same) { + lept_stderr("pixref != pix3 !\n"); ok = FALSE; + } + pixDestroy(&pix3); + + pix1 = pixAddBorder(pixs, 32 + extraborder, 0); + if (h == 1) + pix3 = pixFMorphopGen_1(NULL, pix1, L_MORPH_CLOSE, selnameh); + else if (w == 1) + pix3 = pixFMorphopGen_1(NULL, pix1, L_MORPH_CLOSE, selnamev); + else { + pix2 = pixFMorphopGen_1(NULL, pix1, L_MORPH_DILATE, selnameh); + pix3 = pixFMorphopGen_1(NULL, pix2, L_MORPH_DILATE, selnamev); + pixFMorphopGen_1(pix2, pix3, L_MORPH_ERODE, selnameh); + pixFMorphopGen_1(pix3, pix2, L_MORPH_ERODE, selnamev); + pixDestroy(&pix2); + } + pix4 = pixRemoveBorder(pix3, 32 + extraborder); + pixEqual(pixref, pix4, &same); + if (!same) { + lept_stderr("pixref != pix4 !\n"); ok = FALSE; + } + pixDestroy(&pixref); + pixDestroy(&pix1); + pixDestroy(&pix3); + pixDestroy(&pix4); + + regTestCompareValues(rp, TRUE, ok, 0); + if (ok) + lept_stderr("All morph tests OK!\n\n"); + selDestroy(&sel); + lept_free(selnameh); + lept_free(selnamev); + } + + return 0; +} + diff --git a/leptonica/prog/binmorph4_reg.c b/leptonica/prog/binmorph4_reg.c new file mode 100644 index 00000000..a9023c56 --- /dev/null +++ b/leptonica/prog/binmorph4_reg.c @@ -0,0 +1,544 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * binmorph4_reg.c + * + * Regression test for dwa brick morph operations + * We compare: + * (1) morph composite vs. morph non-composite + * (2) dwa non-composite vs. morph composite + * (3) dwa composite vs. dwa non-composite + * (4) dwa composite vs. morph composite + * (5) dwa composite vs. morph non-composite + * The brick functions all have a pre-allocated pix as the dest. + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + +void TestAll(L_REGPARAMS *rp, PIX *pixs, l_int32 symmetric); + +l_int32 DoComparisonDwa1(L_REGPARAMS *rp, + PIX *pixs, PIX *pix1, PIX *pix2, PIX *pix3, + PIX *pix4, PIX *pix5, PIX *pix6, l_int32 isize); +l_int32 DoComparisonDwa2(L_REGPARAMS *rp, + PIX *pixs, PIX *pix1, PIX *pix2, PIX *pix3, + PIX *pix4, PIX *pix5, PIX *pix6, l_int32 isize); +l_int32 DoComparisonDwa3(L_REGPARAMS *rp, + PIX *pixs, PIX *pix1, PIX *pix2, PIX *pix3, + PIX *pix4, PIX *pix5, PIX *pix6, l_int32 isize); +l_int32 DoComparisonDwa4(L_REGPARAMS *rp, + PIX *pixs, PIX *pix1, PIX *pix2, PIX *pix3, + PIX *pix4, PIX *pix5, PIX *pix6, l_int32 isize); +l_int32 DoComparisonDwa5(L_REGPARAMS *rp, + PIX *pixs, PIX *pix1, PIX *pix2, PIX *pix3, + PIX *pix4, PIX *pix5, PIX *pix6, l_int32 isize); +void PixCompareDwa(L_REGPARAMS *rp, + l_int32 size, const char *type, PIX *pix1, PIX *pix2, + PIX *pix3, PIX *pix4, PIX *pix5, PIX *pix6); + +#define TIMING 0 + + /* Note: the symmetric case requires an extra border of size + * approximately 40 to succeed for all SE up to size 64. With + * a smaller border the differences are small, and most of the + * problem seems to be in the non-dwa code, because we are doing + * sequential erosions without an extra border, and things aren't + * being properly initialized. To avoid these errors, add the border + * in advance for symmetric b.c. + * Note that asymmetric b.c. are recommended for document image + * operations, and this test passes for asymmetric b.c. without + * any added border. */ + +int main(int argc, + char **argv) +{ +PIX *pixs; +L_REGPARAMS *rp; + + if (regTestSetup(argc, argv, &rp)) + return 1; + + pixs = pixRead("feyn-fract.tif"); + TestAll(rp, pixs, FALSE); + TestAll(rp, pixs, TRUE); + pixDestroy(&pixs); + return regTestCleanup(rp); +} + +void +TestAll(L_REGPARAMS *rp, + PIX *pixs, + l_int32 symmetric) +{ +l_int32 i; +PIX *pix1, *pix2, *pix3, *pix4, *pix5, *pix6; + + if (symmetric) { + /* This works properly with an added border of 40 */ + resetMorphBoundaryCondition(SYMMETRIC_MORPH_BC); + pix1 = pixAddBorder(pixs, 40, 0); + pixTransferAllData(pixs, &pix1, 0, 0); + lept_stderr("Testing with symmetric boundary conditions\n"); + } else { + resetMorphBoundaryCondition(ASYMMETRIC_MORPH_BC); + lept_stderr("Testing with asymmetric boundary conditions\n"); + } + + pix1 = pixCreateTemplateNoInit(pixs); + pix2 = pixCreateTemplateNoInit(pixs); + pix3 = pixCreateTemplateNoInit(pixs); + pix4 = pixCreateTemplateNoInit(pixs); + pix5 = pixCreateTemplateNoInit(pixs); + pix6 = pixCreateTemplateNoInit(pixs); + + for (i = 2; i < 64; i++) { + +#if 1 + /* Compare morph composite with morph non-composite */ + DoComparisonDwa1(rp, pixs, pix1, pix2, pix3, pix4, pix5, pix6, i); +#endif + +#if 1 + /* Compare DWA non-composite with morph composite */ + if (i < 16) + DoComparisonDwa2(rp, pixs, pix1, pix2, pix3, pix4, pix5, pix6, i); + /* Compare DWA composite with DWA non-composite */ + if (i < 16) + DoComparisonDwa3(rp, pixs, pix1, pix2, pix3, pix4, pix5, pix6, i); + /* Compare DWA composite with morph composite */ + DoComparisonDwa4(rp, pixs, pix1, pix2, pix3, pix4, pix5, pix6, i); + /* Compare DWA composite with morph non-composite */ + DoComparisonDwa5(rp, pixs, pix1, pix2, pix3, pix4, pix5, pix6, i); +#endif + } + lept_stderr("\n"); + pixDestroy(&pix1); + pixDestroy(&pix2); + pixDestroy(&pix3); + pixDestroy(&pix4); + pixDestroy(&pix5); + pixDestroy(&pix6); +} + + + /* Morph composite with morph non-composite */ +l_int32 +DoComparisonDwa1(L_REGPARAMS *rp, + PIX *pixs, + PIX *pix1, + PIX *pix2, + PIX *pix3, + PIX *pix4, + PIX *pix5, + PIX *pix6, + l_int32 isize) +{ +l_int32 fact1, fact2, size; + + selectComposableSizes(isize, &fact1, &fact2); + size = fact1 * fact2; + + lept_stderr("..%d..", size); + + if (TIMING) startTimer(); + pixDilateCompBrick(pix1, pixs, size, 1); + pixDilateCompBrick(pix3, pixs, 1, size); + pixDilateCompBrick(pix5, pixs, size, size); + if (TIMING) lept_stderr("Time Dwa: %7.3f sec\n", stopTimer()); + if (TIMING) startTimer(); + pixDilateBrick(pix2, pixs, size, 1); + pixDilateBrick(pix4, pixs, 1, size); + pixDilateBrick(pix6, pixs, size, size); + if (TIMING) lept_stderr("Time Rop: %7.3f sec\n", stopTimer()); + PixCompareDwa(rp, size, "dilate", pix1, pix2, pix3, pix4, pix5, pix6); + + if (TIMING) startTimer(); + pixErodeCompBrick(pix1, pixs, size, 1); + pixErodeCompBrick(pix3, pixs, 1, size); + pixErodeCompBrick(pix5, pixs, size, size); + if (TIMING) lept_stderr("Time Dwa: %7.3f sec\n", stopTimer()); + if (TIMING) startTimer(); + pixErodeBrick(pix2, pixs, size, 1); + pixErodeBrick(pix4, pixs, 1, size); + pixErodeBrick(pix6, pixs, size, size); + if (TIMING) lept_stderr("Time Rop: %7.3f sec\n", stopTimer()); + PixCompareDwa(rp, size, "erode", pix1, pix2, pix3, pix4, pix5, pix6); + + if (TIMING) startTimer(); + pixOpenCompBrick(pix1, pixs, size, 1); + pixOpenCompBrick(pix3, pixs, 1, size); + pixOpenCompBrick(pix5, pixs, size, size); + if (TIMING) lept_stderr("Time Dwa: %7.3f sec\n", stopTimer()); + if (TIMING) startTimer(); + pixOpenBrick(pix2, pixs, size, 1); + pixOpenBrick(pix4, pixs, 1, size); + pixOpenBrick(pix6, pixs, size, size); + if (TIMING) lept_stderr("Time Rop: %7.3f sec\n", stopTimer()); + PixCompareDwa(rp, size, "open", pix1, pix2, pix3, pix4, pix5, pix6); + + if (TIMING) startTimer(); + pixCloseSafeCompBrick(pix1, pixs, size, 1); + pixCloseSafeCompBrick(pix3, pixs, 1, size); + pixCloseSafeCompBrick(pix5, pixs, size, size); + if (TIMING) lept_stderr("Time Dwa: %7.3f sec\n", stopTimer()); + if (TIMING) startTimer(); + pixCloseSafeBrick(pix2, pixs, size, 1); + pixCloseSafeBrick(pix4, pixs, 1, size); + pixCloseSafeBrick(pix6, pixs, size, size); + if (TIMING) lept_stderr("Time Rop: %7.3f sec\n", stopTimer()); + PixCompareDwa(rp, size, "close", pix1, pix2, pix3, pix4, pix5, pix6); + + return 0; +} + + + /* Dwa non-composite with morph composite */ +l_int32 +DoComparisonDwa2(L_REGPARAMS *rp, + PIX *pixs, + PIX *pix1, + PIX *pix2, + PIX *pix3, + PIX *pix4, + PIX *pix5, + PIX *pix6, + l_int32 isize) +{ +l_int32 fact1, fact2, size; + + selectComposableSizes(isize, &fact1, &fact2); + size = fact1 * fact2; + + lept_stderr("..%d..", size); + + if (TIMING) startTimer(); + pixDilateBrickDwa(pix1, pixs, size, 1); + pixDilateBrickDwa(pix3, pixs, 1, size); + pixDilateBrickDwa(pix5, pixs, size, size); + if (TIMING) lept_stderr("Time Dwa: %7.3f sec\n", stopTimer()); + if (TIMING) startTimer(); + pixDilateCompBrick(pix2, pixs, size, 1); + pixDilateCompBrick(pix4, pixs, 1, size); + pixDilateCompBrick(pix6, pixs, size, size); + if (TIMING) lept_stderr("Time Rop: %7.3f sec\n", stopTimer()); + PixCompareDwa(rp, size, "dilate", pix1, pix2, pix3, pix4, pix5, pix6); + +/* pixDisplay(pix1, 100, 100); */ +/* pixDisplay(pix2, 800, 100); */ + + if (TIMING) startTimer(); + pixErodeBrickDwa(pix1, pixs, size, 1); + pixErodeBrickDwa(pix3, pixs, 1, size); + pixErodeBrickDwa(pix5, pixs, size, size); + if (TIMING) lept_stderr("Time Dwa: %7.3f sec\n", stopTimer()); + if (TIMING) startTimer(); + pixErodeCompBrick(pix2, pixs, size, 1); + pixErodeCompBrick(pix4, pixs, 1, size); + pixErodeCompBrick(pix6, pixs, size, size); + if (TIMING) lept_stderr("Time Rop: %7.3f sec\n", stopTimer()); + PixCompareDwa(rp, size, "erode", pix1, pix2, pix3, pix4, pix5, pix6); + + if (TIMING) startTimer(); + pixOpenBrickDwa(pix1, pixs, size, 1); + pixOpenBrickDwa(pix3, pixs, 1, size); + pixOpenBrickDwa(pix5, pixs, size, size); + if (TIMING) lept_stderr("Time Dwa: %7.3f sec\n", stopTimer()); + if (TIMING) startTimer(); + pixOpenCompBrick(pix2, pixs, size, 1); + pixOpenCompBrick(pix4, pixs, 1, size); + pixOpenCompBrick(pix6, pixs, size, size); + if (TIMING) lept_stderr("Time Rop: %7.3f sec\n", stopTimer()); + PixCompareDwa(rp, size, "open", pix1, pix2, pix3, pix4, pix5, pix6); + + if (TIMING) startTimer(); + pixCloseBrickDwa(pix1, pixs, size, 1); + pixCloseBrickDwa(pix3, pixs, 1, size); + pixCloseBrickDwa(pix5, pixs, size, size); + if (TIMING) lept_stderr("Time Dwa: %7.3f sec\n", stopTimer()); + if (TIMING) startTimer(); + pixCloseSafeCompBrick(pix2, pixs, size, 1); + pixCloseSafeCompBrick(pix4, pixs, 1, size); + pixCloseSafeCompBrick(pix6, pixs, size, size); + if (TIMING) lept_stderr("Time Rop: %7.3f sec\n", stopTimer()); + PixCompareDwa(rp, size, "close", pix1, pix2, pix3, pix4, pix5, pix6); + + return 0; +} + + + /* Dwa composite with dwa non-composite */ +l_int32 +DoComparisonDwa3(L_REGPARAMS *rp, + PIX *pixs, + PIX *pix1, + PIX *pix2, + PIX *pix3, + PIX *pix4, + PIX *pix5, + PIX *pix6, + l_int32 isize) +{ +l_int32 fact1, fact2, size; + + selectComposableSizes(isize, &fact1, &fact2); + size = fact1 * fact2; + + lept_stderr("..%d..", size); + + if (TIMING) startTimer(); + pixDilateCompBrickDwa(pix1, pixs, size, 1); + pixDilateCompBrickDwa(pix3, pixs, 1, size); + pixDilateCompBrickDwa(pix5, pixs, size, size); + if (TIMING) lept_stderr("Time Dwa: %7.3f sec\n", stopTimer()); + if (TIMING) startTimer(); + pixDilateBrickDwa(pix2, pixs, size, 1); + pixDilateBrickDwa(pix4, pixs, 1, size); + pixDilateBrickDwa(pix6, pixs, size, size); + if (TIMING) lept_stderr("Time Rop: %7.3f sec\n", stopTimer()); + PixCompareDwa(rp, size, "dilate", pix1, pix2, pix3, pix4, pix5, pix6); + +/* pixDisplay(pix1, 100, 100); */ +/* pixDisplay(pix2, 800, 100); */ + + if (TIMING) startTimer(); + pixErodeCompBrickDwa(pix1, pixs, size, 1); + pixErodeCompBrickDwa(pix3, pixs, 1, size); + pixErodeCompBrickDwa(pix5, pixs, size, size); + if (TIMING) lept_stderr("Time Dwa: %7.3f sec\n", stopTimer()); + if (TIMING) startTimer(); + pixErodeBrickDwa(pix2, pixs, size, 1); + pixErodeBrickDwa(pix4, pixs, 1, size); + pixErodeBrickDwa(pix6, pixs, size, size); + if (TIMING) lept_stderr("Time Rop: %7.3f sec\n", stopTimer()); + PixCompareDwa(rp, size, "erode", pix1, pix2, pix3, pix4, pix5, pix6); + + if (TIMING) startTimer(); + pixOpenCompBrickDwa(pix1, pixs, size, 1); + pixOpenCompBrickDwa(pix3, pixs, 1, size); + pixOpenCompBrickDwa(pix5, pixs, size, size); + if (TIMING) lept_stderr("Time Dwa: %7.3f sec\n", stopTimer()); + if (TIMING) startTimer(); + pixOpenBrickDwa(pix2, pixs, size, 1); + pixOpenBrickDwa(pix4, pixs, 1, size); + pixOpenBrickDwa(pix6, pixs, size, size); + if (TIMING) lept_stderr("Time Rop: %7.3f sec\n", stopTimer()); + PixCompareDwa(rp, size, "open", pix1, pix2, pix3, pix4, pix5, pix6); + + if (TIMING) startTimer(); + pixCloseCompBrickDwa(pix1, pixs, size, 1); + pixCloseCompBrickDwa(pix3, pixs, 1, size); + pixCloseCompBrickDwa(pix5, pixs, size, size); + if (TIMING) lept_stderr("Time Dwa: %7.3f sec\n", stopTimer()); + if (TIMING) startTimer(); + pixCloseBrickDwa(pix2, pixs, size, 1); + pixCloseBrickDwa(pix4, pixs, 1, size); + pixCloseBrickDwa(pix6, pixs, size, size); + if (TIMING) lept_stderr("Time Rop: %7.3f sec\n", stopTimer()); + PixCompareDwa(rp, size, "close", pix1, pix2, pix3, pix4, pix5, pix6); + + return 0; +} + + + /* Dwa composite with morph composite */ +l_int32 +DoComparisonDwa4(L_REGPARAMS *rp, + PIX *pixs, + PIX *pix1, + PIX *pix2, + PIX *pix3, + PIX *pix4, + PIX *pix5, + PIX *pix6, + l_int32 isize) +{ +l_int32 fact1, fact2, size; + + selectComposableSizes(isize, &fact1, &fact2); + size = fact1 * fact2; + + lept_stderr("..%d..", size); + + if (TIMING) startTimer(); + pixDilateCompBrickDwa(pix1, pixs, size, 1); + pixDilateCompBrickDwa(pix3, pixs, 1, size); + pixDilateCompBrickDwa(pix5, pixs, size, size); + if (TIMING) lept_stderr("Time Dwa: %7.3f sec\n", stopTimer()); + if (TIMING) startTimer(); + pixDilateCompBrick(pix2, pixs, size, 1); + pixDilateCompBrick(pix4, pixs, 1, size); + pixDilateCompBrick(pix6, pixs, size, size); + if (TIMING) lept_stderr("Time Rop: %7.3f sec\n", stopTimer()); + PixCompareDwa(rp, size, "dilate", pix1, pix2, pix3, pix4, pix5, pix6); + +/* pixDisplay(pix1, 100, 100); */ +/* pixDisplay(pix2, 800, 100); */ + + if (TIMING) startTimer(); + pixErodeCompBrickDwa(pix1, pixs, size, 1); + pixErodeCompBrickDwa(pix3, pixs, 1, size); + pixErodeCompBrickDwa(pix5, pixs, size, size); + if (TIMING) lept_stderr("Time Dwa: %7.3f sec\n", stopTimer()); + if (TIMING) startTimer(); + pixErodeCompBrick(pix2, pixs, size, 1); + pixErodeCompBrick(pix4, pixs, 1, size); + pixErodeCompBrick(pix6, pixs, size, size); + if (TIMING) lept_stderr("Time Rop: %7.3f sec\n", stopTimer()); + PixCompareDwa(rp, size, "erode", pix1, pix2, pix3, pix4, pix5, pix6); + + if (TIMING) startTimer(); + pixOpenCompBrickDwa(pix1, pixs, size, 1); + pixOpenCompBrickDwa(pix3, pixs, 1, size); + pixOpenCompBrickDwa(pix5, pixs, size, size); + if (TIMING) lept_stderr("Time Dwa: %7.3f sec\n", stopTimer()); + if (TIMING) startTimer(); + pixOpenCompBrick(pix2, pixs, size, 1); + pixOpenCompBrick(pix4, pixs, 1, size); + pixOpenCompBrick(pix6, pixs, size, size); + if (TIMING) lept_stderr("Time Rop: %7.3f sec\n", stopTimer()); + PixCompareDwa(rp, size, "open", pix1, pix2, pix3, pix4, pix5, pix6); + + if (TIMING) startTimer(); + pixCloseCompBrickDwa(pix1, pixs, size, 1); + pixCloseCompBrickDwa(pix3, pixs, 1, size); + pixCloseCompBrickDwa(pix5, pixs, size, size); + if (TIMING) lept_stderr("Time Dwa: %7.3f sec\n", stopTimer()); + if (TIMING) startTimer(); + pixCloseSafeCompBrick(pix2, pixs, size, 1); + pixCloseSafeCompBrick(pix4, pixs, 1, size); + pixCloseSafeCompBrick(pix6, pixs, size, size); + if (TIMING) lept_stderr("Time Rop: %7.3f sec\n", stopTimer()); + PixCompareDwa(rp, size, "close", pix1, pix2, pix3, pix4, pix5, pix6); + + return 0; +} + + /* Dwa composite with morph non-composite */ +l_int32 +DoComparisonDwa5(L_REGPARAMS *rp, + PIX *pixs, + PIX *pix1, + PIX *pix2, + PIX *pix3, + PIX *pix4, + PIX *pix5, + PIX *pix6, + l_int32 isize) +{ +l_int32 fact1, fact2, size; + + selectComposableSizes(isize, &fact1, &fact2); + size = fact1 * fact2; + + lept_stderr("..%d..", size); + + if (TIMING) startTimer(); + pixDilateCompBrickDwa(pix1, pixs, size, 1); + pixDilateCompBrickDwa(pix3, pixs, 1, size); + pixDilateCompBrickDwa(pix5, pixs, size, size); + if (TIMING) lept_stderr("Time Dwa: %7.3f sec\n", stopTimer()); + if (TIMING) startTimer(); + pixDilateBrick(pix2, pixs, size, 1); + pixDilateBrick(pix4, pixs, 1, size); + pixDilateBrick(pix6, pixs, size, size); + if (TIMING) lept_stderr("Time Rop: %7.3f sec\n", stopTimer()); + PixCompareDwa(rp, size, "dilate", pix1, pix2, pix3, pix4, pix5, pix6); + +/* pixDisplay(pix1, 100, 100); */ +/* pixDisplay(pix2, 800, 100); */ + + if (TIMING) startTimer(); + pixErodeCompBrickDwa(pix1, pixs, size, 1); + pixErodeCompBrickDwa(pix3, pixs, 1, size); + pixErodeCompBrickDwa(pix5, pixs, size, size); + if (TIMING) lept_stderr("Time Dwa: %7.3f sec\n", stopTimer()); + if (TIMING) startTimer(); + pixErodeBrick(pix2, pixs, size, 1); + pixErodeBrick(pix4, pixs, 1, size); + pixErodeBrick(pix6, pixs, size, size); + if (TIMING) lept_stderr("Time Rop: %7.3f sec\n", stopTimer()); + PixCompareDwa(rp, size, "erode", pix1, pix2, pix3, pix4, pix5, pix6); + + if (TIMING) startTimer(); + pixOpenCompBrickDwa(pix1, pixs, size, 1); + pixOpenCompBrickDwa(pix3, pixs, 1, size); + pixOpenCompBrickDwa(pix5, pixs, size, size); + if (TIMING) lept_stderr("Time Dwa: %7.3f sec\n", stopTimer()); + if (TIMING) startTimer(); + pixOpenBrick(pix2, pixs, size, 1); + pixOpenBrick(pix4, pixs, 1, size); + pixOpenBrick(pix6, pixs, size, size); + if (TIMING) lept_stderr("Time Rop: %7.3f sec\n", stopTimer()); + PixCompareDwa(rp, size, "open", pix1, pix2, pix3, pix4, pix5, pix6); + + if (TIMING) startTimer(); + pixCloseCompBrickDwa(pix1, pixs, size, 1); + pixCloseCompBrickDwa(pix3, pixs, 1, size); + pixCloseCompBrickDwa(pix5, pixs, size, size); + if (TIMING) lept_stderr("Time Dwa: %7.3f sec\n", stopTimer()); + if (TIMING) startTimer(); + pixCloseSafeBrick(pix2, pixs, size, 1); + pixCloseSafeBrick(pix4, pixs, 1, size); + pixCloseSafeBrick(pix6, pixs, size, size); + if (TIMING) lept_stderr("Time Rop: %7.3f sec\n", stopTimer()); + PixCompareDwa(rp, size, "close", pix1, pix2, pix3, pix4, pix5, pix6); + + return 0; +} + + +void +PixCompareDwa(L_REGPARAMS *rp, + l_int32 size, + const char *type, + PIX *pix1, + PIX *pix2, + PIX *pix3, + PIX *pix4, + PIX *pix5, + PIX *pix6) +{ +l_int32 same; + + pixEqual(pix1, pix2, &same); + regTestCompareValues(rp, TRUE, same, 0); + if (!same) + lept_stderr("%s (%d, 1) not same\n", type, size); + pixEqual(pix3, pix4, &same); + regTestCompareValues(rp, TRUE, same, 0); + if (!same) + lept_stderr("%s (1, %d) not same\n", type, size); + pixEqual(pix5, pix6, &same); + regTestCompareValues(rp, TRUE, same, 0); + if (!same) + lept_stderr("%s (%d, %d) not same\n", type, size, size); +} + diff --git a/leptonica/prog/binmorph5_reg.c b/leptonica/prog/binmorph5_reg.c new file mode 100644 index 00000000..22f69a93 --- /dev/null +++ b/leptonica/prog/binmorph5_reg.c @@ -0,0 +1,329 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * binmorph5_reg.c + * + * Regression test for expanded dwa morph operations. + * We compare: + * (1) dwa composite vs. morph composite + * (2) dwa composite vs. morph non-composite + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + +void TestAll(L_REGPARAMS *rp, PIX *pixs, l_int32 symmetric); + +l_int32 DoComparisonDwa1(L_REGPARAMS *rp, + PIX *pixs, PIX *pix1, PIX *pix2, PIX *pix3, + PIX *pix4, PIX *pix5, PIX *pix6, l_int32 isize); +l_int32 DoComparisonDwa2(L_REGPARAMS *rp, + PIX *pixs, PIX *pix1, PIX *pix2, PIX *pix3, + PIX *pix4, PIX *pix5, PIX *pix6, l_int32 size); +void PixCompareDwa(L_REGPARAMS *rp, + l_int32 size, const char *type, PIX *pix1, PIX *pix2, + PIX *pix3, PIX *pix4, PIX *pix5, PIX *pix6); + +#define TIMING 0 +#define FASTER_TEST 1 +#define SLOWER_TEST 1 + + /* Note: this fails on the symmetric case when the added border + * is 64 pixels, but the differences are relatively small. + * Most of the problem seems to be in the non-dwa code, because we + * are doing sequential erosions without an extra border, and + * things aren't being properly initialized. To avoid these errors, + * add a sufficiently large border for symmetric b.c. The size of + * the border needs to be half the size of the largest SE that is + * being used. Here we test up to size 240, and a border of 128 + * pixels is sufficient for symmetric b.c. (For a SE of size 240 + * with its center in the middle at 120, the maximum translation will + * be about 120.) + * Note also that asymmetric b.c. are recommended for document image + * operations, and this test passes with no added border for + * asymmetric b.c. */ + +int main(int argc, + char **argv) +{ +PIX *pixs; +L_REGPARAMS *rp; + + if (regTestSetup(argc, argv, &rp)) + return 1; + + pixs = pixRead("feyn-fract.tif"); + TestAll(rp, pixs, FALSE); + TestAll(rp, pixs, TRUE); + pixDestroy(&pixs); + return regTestCleanup(rp); +} + +void +TestAll(L_REGPARAMS *rp, + PIX *pixs, + l_int32 symmetric) +{ +l_int32 i, n, rsize, fact1, fact2, extra; +l_int32 size, lastsize; +l_int32 dwasize[256]; +l_int32 ropsize[256]; +PIX *pix1, *pix2, *pix3, *pix4, *pix5, *pix6; + + if (symmetric) { + /* This works properly with an added border of 128 */ + resetMorphBoundaryCondition(SYMMETRIC_MORPH_BC); + pix1 = pixAddBorder(pixs, 128, 0); + pixTransferAllData(pixs, &pix1, 0, 0); + lept_stderr("Testing with symmetric boundary conditions\n"); + } else { + resetMorphBoundaryCondition(ASYMMETRIC_MORPH_BC); + lept_stderr("Testing with asymmetric boundary conditions\n"); + } + + pix1 = pixCreateTemplateNoInit(pixs); + pix2 = pixCreateTemplateNoInit(pixs); + pix3 = pixCreateTemplateNoInit(pixs); + pix4 = pixCreateTemplateNoInit(pixs); + pix5 = pixCreateTemplateNoInit(pixs); + pix6 = pixCreateTemplateNoInit(pixs); + + /* ---------------------------------------------------------------- * + * Faster test; testing fewer sizes * + * ---------------------------------------------------------------- */ +#if FASTER_TEST + /* Compute the actual sizes used for each input size 'i' */ + for (i = 0; i < 256; i++) { + dwasize[i] = 0; + ropsize[i] = 0; + } + for (i = 65; i < 256; i++) { + selectComposableSizes(i, &fact1, &fact2); + rsize = fact1 * fact2; + ropsize[i] = rsize; + getExtendedCompositeParameters(i, &n, &extra, &dwasize[i]); + } + + /* Use only values where the resulting sizes are equal */ + for (i = 65; i < 240; i++) { + n = 1 + (l_int32)((i - 63) / 62); + extra = i - 63 - (n - 1) * 62 + 1; + if (extra == 2) continue; /* don't use this one (e.g., i == 126) */ + if (ropsize[i] == dwasize[i]) + DoComparisonDwa1(rp, pixs, pix1, pix2, pix3, pix4, pix5, pix6, i); + } +#endif /* FASTER_TEST */ + + /* ---------------------------------------------------------------- * + * Slower test; testing maximum number of sizes * + * ---------------------------------------------------------------- */ +#if SLOWER_TEST + lastsize = 0; + for (i = 65; i < 199; i++) { + getExtendedCompositeParameters(i, &n, &extra, &size); + if (size == lastsize) continue; + if (size == 126 || size == 188) continue; /* deliberately off by one */ + lastsize = size; + DoComparisonDwa2(rp, pixs, pix1, pix2, pix3, pix4, pix5, pix6, size); + } +#endif /* SLOWER_TEST */ + + lept_stderr("\n"); + pixDestroy(&pix1); + pixDestroy(&pix2); + pixDestroy(&pix3); + pixDestroy(&pix4); + pixDestroy(&pix5); + pixDestroy(&pix6); +} + + +l_int32 +DoComparisonDwa1(L_REGPARAMS *rp, + PIX *pixs, + PIX *pix1, + PIX *pix2, + PIX *pix3, + PIX *pix4, + PIX *pix5, + PIX *pix6, + l_int32 isize) +{ +l_int32 fact1, fact2, size; + + selectComposableSizes(isize, &fact1, &fact2); + size = fact1 * fact2; + + lept_stderr("..%d..", size); + + if (TIMING) startTimer(); + pixDilateCompBrickExtendDwa(pix1, pixs, size, 1); + pixDilateCompBrickExtendDwa(pix3, pixs, 1, size); + pixDilateCompBrickExtendDwa(pix5, pixs, size, size); + if (TIMING) lept_stderr("Time Dwa: %7.3f sec\n", stopTimer()); + if (TIMING) startTimer(); + pixDilateCompBrick(pix2, pixs, size, 1); + pixDilateCompBrick(pix4, pixs, 1, size); + pixDilateCompBrick(pix6, pixs, size, size); + if (TIMING) lept_stderr("Time Rop: %7.3f sec\n", stopTimer()); + PixCompareDwa(rp, size, "dilate", pix1, pix2, pix3, pix4, pix5, pix6); + + if (TIMING) startTimer(); + pixErodeCompBrickExtendDwa(pix1, pixs, size, 1); + pixErodeCompBrickExtendDwa(pix3, pixs, 1, size); + pixErodeCompBrickExtendDwa(pix5, pixs, size, size); + if (TIMING) lept_stderr("Time Dwa: %7.3f sec\n", stopTimer()); + if (TIMING) startTimer(); + pixErodeCompBrick(pix2, pixs, size, 1); + pixErodeCompBrick(pix4, pixs, 1, size); + pixErodeCompBrick(pix6, pixs, size, size); + if (TIMING) lept_stderr("Time Rop: %7.3f sec\n", stopTimer()); + PixCompareDwa(rp, size, "erode", pix1, pix2, pix3, pix4, pix5, pix6); + + if (TIMING) startTimer(); + pixOpenCompBrickExtendDwa(pix1, pixs, size, 1); + pixOpenCompBrickExtendDwa(pix3, pixs, 1, size); + pixOpenCompBrickExtendDwa(pix5, pixs, size, size); + if (TIMING) lept_stderr("Time Dwa: %7.3f sec\n", stopTimer()); + if (TIMING) startTimer(); + pixOpenCompBrick(pix2, pixs, size, 1); + pixOpenCompBrick(pix4, pixs, 1, size); + pixOpenCompBrick(pix6, pixs, size, size); + if (TIMING) lept_stderr("Time Rop: %7.3f sec\n", stopTimer()); + PixCompareDwa(rp, size, "open", pix1, pix2, pix3, pix4, pix5, pix6); + + if (TIMING) startTimer(); + pixCloseCompBrickExtendDwa(pix1, pixs, size, 1); + pixCloseCompBrickExtendDwa(pix3, pixs, 1, size); + pixCloseCompBrickExtendDwa(pix5, pixs, size, size); + if (TIMING) lept_stderr("Time Dwa: %7.3f sec\n", stopTimer()); + if (TIMING) startTimer(); + pixCloseSafeCompBrick(pix2, pixs, size, 1); + pixCloseSafeCompBrick(pix4, pixs, 1, size); + pixCloseSafeCompBrick(pix6, pixs, size, size); + if (TIMING) lept_stderr("Time Rop: %7.3f sec\n", stopTimer()); + PixCompareDwa(rp, size, "close", pix1, pix2, pix3, pix4, pix5, pix6); + + return 0; +} + + +l_int32 +DoComparisonDwa2(L_REGPARAMS *rp, + PIX *pixs, + PIX *pix1, + PIX *pix2, + PIX *pix3, + PIX *pix4, + PIX *pix5, + PIX *pix6, + l_int32 size) /* exactly decomposable */ +{ + lept_stderr("..%d..", size); + + if (TIMING) startTimer(); + pixDilateCompBrickExtendDwa(pix1, pixs, size, 1); + pixDilateCompBrickExtendDwa(pix3, pixs, 1, size); + pixDilateCompBrickExtendDwa(pix5, pixs, size, size); + if (TIMING) lept_stderr("Time Dwa: %7.3f sec\n", stopTimer()); + if (TIMING) startTimer(); + pixDilateBrick(pix2, pixs, size, 1); + pixDilateBrick(pix4, pixs, 1, size); + pixDilateBrick(pix6, pixs, size, size); + if (TIMING) lept_stderr("Time Rop: %7.3f sec\n", stopTimer()); + PixCompareDwa(rp, size, "dilate", pix1, pix2, pix3, pix4, pix5, pix6); + + if (TIMING) startTimer(); + pixErodeCompBrickExtendDwa(pix1, pixs, size, 1); + pixErodeCompBrickExtendDwa(pix3, pixs, 1, size); + pixErodeCompBrickExtendDwa(pix5, pixs, size, size); + if (TIMING) lept_stderr("Time Dwa: %7.3f sec\n", stopTimer()); + if (TIMING) startTimer(); + pixErodeBrick(pix2, pixs, size, 1); + pixErodeBrick(pix4, pixs, 1, size); + pixErodeBrick(pix6, pixs, size, size); + if (TIMING) lept_stderr("Time Rop: %7.3f sec\n", stopTimer()); + PixCompareDwa(rp, size, "erode", pix1, pix2, pix3, pix4, pix5, pix6); + + if (TIMING) startTimer(); + pixOpenCompBrickExtendDwa(pix1, pixs, size, 1); + pixOpenCompBrickExtendDwa(pix3, pixs, 1, size); + pixOpenCompBrickExtendDwa(pix5, pixs, size, size); + if (TIMING) lept_stderr("Time Dwa: %7.3f sec\n", stopTimer()); + if (TIMING) startTimer(); + pixOpenBrick(pix2, pixs, size, 1); + pixOpenBrick(pix4, pixs, 1, size); + pixOpenBrick(pix6, pixs, size, size); + if (TIMING) lept_stderr("Time Rop: %7.3f sec\n", stopTimer()); + PixCompareDwa(rp, size, "open", pix1, pix2, pix3, pix4, pix5, pix6); + + if (TIMING) startTimer(); + pixCloseCompBrickExtendDwa(pix1, pixs, size, 1); + pixCloseCompBrickExtendDwa(pix3, pixs, 1, size); + pixCloseCompBrickExtendDwa(pix5, pixs, size, size); + if (TIMING) lept_stderr("Time Dwa: %7.3f sec\n", stopTimer()); + if (TIMING) startTimer(); + pixCloseSafeBrick(pix2, pixs, size, 1); + pixCloseSafeBrick(pix4, pixs, 1, size); + pixCloseSafeBrick(pix6, pixs, size, size); + if (TIMING) lept_stderr("Time Rop: %7.3f sec\n", stopTimer()); + PixCompareDwa(rp, size, "close", pix1, pix2, pix3, pix4, pix5, pix6); + + return 0; +} + + +void +PixCompareDwa(L_REGPARAMS *rp, + l_int32 size, + const char *type, + PIX *pix1, + PIX *pix2, + PIX *pix3, + PIX *pix4, + PIX *pix5, + PIX *pix6) +{ +l_int32 same; + + pixEqual(pix1, pix2, &same); + regTestCompareValues(rp, TRUE, same, 0); + if (!same) + lept_stderr("%s (%d, 1) not same\n", type, size); + pixEqual(pix3, pix4, &same); + regTestCompareValues(rp, TRUE, same, 0); + if (!same) + lept_stderr("%s (1, %d) not same\n", type, size); + pixEqual(pix5, pix6, &same); + regTestCompareValues(rp, TRUE, same, 0); + if (!same) + lept_stderr("%s (%d, %d) not same\n", type, size, size); +} + diff --git a/leptonica/prog/binmorph6_reg.c b/leptonica/prog/binmorph6_reg.c new file mode 100644 index 00000000..f45a3f9c --- /dev/null +++ b/leptonica/prog/binmorph6_reg.c @@ -0,0 +1,89 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * binmorph6_reg.c + * + * Miscellaneous morphological operations. + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + +int main(int argc, + char **argv) +{ +BOX *box1; +PIX *pix1, *pix2, *pix3, *pix4, *pix5, *pix6, *pix7, *pix8; +PIXA *pixa; +SEL *sel; +L_REGPARAMS *rp; + + if (regTestSetup(argc, argv, &rp)) + return 1; + + /* Test making sel from a pix */ + pixa = pixaCreate(10); + pix1 = pixRead("feyn-fract.tif"); + box1 = boxCreate(507, 65, 60, 36); + pix2 = pixClipRectangle(pix1, box1, NULL); + sel = selCreateFromPix(pix2, 6, 6, "life"); /* 610 hits */ + + /* Note how the closing tries to put the negative + * of the sel, inverted spatially, in the background. */ + pix3 = pixDilate(NULL, pix1, sel); /* note the small holes */ + pix4 = pixOpen(NULL, pix1, sel); /* just the sel */ + pix5 = pixCloseSafe(NULL, pix1, sel); /* expands small holes in dilate */ + pix6 = pixSubtract(NULL, pix3, pix1); + pix7 = pixSubtract(NULL, pix1, pix5); /* no pixels because closing + * is extensive */ + regTestWritePixAndCheck(rp, pix2, IFF_PNG); /* 0 */ + regTestWritePixAndCheck(rp, pix3, IFF_PNG); /* 1 */ + regTestWritePixAndCheck(rp, pix4, IFF_PNG); /* 2 */ + regTestWritePixAndCheck(rp, pix5, IFF_PNG); /* 3 */ + regTestWritePixAndCheck(rp, pix6, IFF_PNG); /* 4 */ + regTestWritePixAndCheck(rp, pix7, IFF_PNG); /* 5 */ + pixaAddPix(pixa, pix1, L_INSERT); + pixaAddPix(pixa, pix3, L_INSERT); + pixaAddPix(pixa, pix4, L_INSERT); + pixaAddPix(pixa, pix5, L_INSERT); + pixaAddPix(pixa, pix6, L_INSERT); + pixaAddPix(pixa, pix7, L_INSERT); + + pix8 = pixaDisplayTiledInColumns(pixa, 2, 0.75, 20, 2); + regTestWritePixAndCheck(rp, pix8, IFF_PNG); /* 6 */ + pixDisplayWithTitle(pix8, 100, 0, NULL, rp->display); + pixDestroy(&pix2); + pixDestroy(&pix8); + pixaDestroy(&pixa); + boxDestroy(&box1); + selDestroy(&sel); + return regTestCleanup(rp); +} + diff --git a/leptonica/prog/blackwhite_reg.c b/leptonica/prog/blackwhite_reg.c new file mode 100644 index 00000000..2af4dde9 --- /dev/null +++ b/leptonica/prog/blackwhite_reg.c @@ -0,0 +1,114 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * blackwhite_reg.c + * + * Tests functions that handle black and white pixels in an image. + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + +const char *fnames[11] = {"test1.png", "speckle2.png", "weasel2.4g.png", + "speckle4.png", "weasel4.11c.png", + "dreyfus8.png", "weasel8.240c.png", + "test16.tif", "marge.jpg", + "test-cmap-alpha.png", "test-gray-alpha.png"}; +const l_int32 setsize = 11; + + +int main(int argc, + char **argv) +{ +l_int32 i, spp; +l_uint32 bval, wval; +PIX *pixs, *pix1, *pix2, *pix3, *pixd; +PIXA *pixa; +L_REGPARAMS *rp; + + if (regTestSetup(argc, argv, &rp)) + return 1; + + /* Scale each image and add a white boundary */ + pixa = pixaCreate(setsize); + for (i = 0; i < setsize; i++) { + pixs = pixRead(fnames[i]); + spp = pixGetSpp(pixs); + pixGetBlackOrWhiteVal(pixs, L_GET_WHITE_VAL, &wval); + pixGetBlackOrWhiteVal(pixs, L_GET_BLACK_VAL, &bval); + lept_stderr("d = %d, spp = %d, bval = %x, wval = %x\n", + pixGetDepth(pixs), spp, bval, wval); + if (spp == 4) /* remove alpha, using white background */ + pix1 = pixAlphaBlendUniform(pixs, wval); + else + pix1 = pixClone(pixs); + pix2 = pixScaleToSize(pix1, 150, 150); + pixGetBlackOrWhiteVal(pix2, L_GET_WHITE_VAL, &wval); + pix3 = pixAddBorderGeneral(pix2, 30, 30, 20, 20, wval); + pixaAddPix(pixa, pix3, L_INSERT); + pixDestroy(&pixs); + pixDestroy(&pix1); + pixDestroy(&pix2); + } + pixd = pixaDisplayTiledInRows(pixa, 32, 1200, 1.0, 1, 30, 0); + regTestWritePixAndCheck(rp, pixd, IFF_PNG); + pixDisplayWithTitle(pixd, 0, 100, NULL, rp->display); + pixDestroy(&pixd); + pixaDestroy(&pixa); + + /* Scale each image and add a black boundary */ + pixa = pixaCreate(setsize); + for (i = 0; i < setsize; i++) { + pixs = pixRead(fnames[i]); + spp = pixGetSpp(pixs); + pixGetBlackOrWhiteVal(pixs, L_GET_WHITE_VAL, &wval); + pixGetBlackOrWhiteVal(pixs, L_GET_BLACK_VAL, &bval); + lept_stderr("d = %d, spp = %d, bval = %x, wval = %x\n", + pixGetDepth(pixs), spp, bval, wval); + if (spp == 4) /* remove alpha, using white background */ + pix1 = pixAlphaBlendUniform(pixs, wval); + else + pix1 = pixClone(pixs); + pix2 = pixScaleToSize(pix1, 150, 150); + pixGetBlackOrWhiteVal(pixs, L_GET_BLACK_VAL, &bval); + pix3 = pixAddBorderGeneral(pix2, 30, 30, 20, 20, bval); + pixaAddPix(pixa, pix3, L_INSERT); + pixDestroy(&pixs); + pixDestroy(&pix1); + pixDestroy(&pix2); + } + pixd = pixaDisplayTiledInRows(pixa, 32, 1200, 1.0, 0, 30, 0); + regTestWritePixAndCheck(rp, pixd, IFF_PNG); + pixDisplayWithTitle(pixd, 1000, 100, NULL, rp->display); + pixDestroy(&pixd); + pixaDestroy(&pixa); + + return regTestCleanup(rp); +} diff --git a/leptonica/prog/blend-green1.jpg b/leptonica/prog/blend-green1.jpg Binary files differnew file mode 100644 index 00000000..4f45cca9 --- /dev/null +++ b/leptonica/prog/blend-green1.jpg diff --git a/leptonica/prog/blend-green2.png b/leptonica/prog/blend-green2.png Binary files differnew file mode 100644 index 00000000..bc0e7ec0 --- /dev/null +++ b/leptonica/prog/blend-green2.png diff --git a/leptonica/prog/blend-green3.png b/leptonica/prog/blend-green3.png Binary files differnew file mode 100644 index 00000000..36acd8d6 --- /dev/null +++ b/leptonica/prog/blend-green3.png diff --git a/leptonica/prog/blend-orange.jpg b/leptonica/prog/blend-orange.jpg Binary files differnew file mode 100644 index 00000000..c4f229a7 --- /dev/null +++ b/leptonica/prog/blend-orange.jpg diff --git a/leptonica/prog/blend-red.png b/leptonica/prog/blend-red.png Binary files differnew file mode 100644 index 00000000..6656e0ce --- /dev/null +++ b/leptonica/prog/blend-red.png diff --git a/leptonica/prog/blend-yellow.jpg b/leptonica/prog/blend-yellow.jpg Binary files differnew file mode 100644 index 00000000..a65678d0 --- /dev/null +++ b/leptonica/prog/blend-yellow.jpg diff --git a/leptonica/prog/blend1_reg.c b/leptonica/prog/blend1_reg.c new file mode 100644 index 00000000..7294f570 --- /dev/null +++ b/leptonica/prog/blend1_reg.c @@ -0,0 +1,328 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * blend1_reg.c + * + * Regression test for these functions: + * pixBlendGray() + * pixBlendGrayAdapt() + * pixBlendColor() + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + +void GrayBlend(PIX *pixs, PIX *pixb, l_int32 op, l_float32 fract); +void AdaptiveGrayBlend(PIX *pixs, PIX *pixb, l_float32 fract); +void ColorBlend(PIX *pixs, PIX *pixb, l_float32 fract); +PIX *MakeGrayWash(l_int32 w, l_int32 h); +PIX *MakeColorWash(l_int32 w, l_int32 h, l_int32 color); + + +int main(int argc, + char **argv) +{ +PIX *pixs, *pixg, *pixc, *pix1; +PIXA *pixa; +L_REGPARAMS *rp; + + if (regTestSetup(argc, argv, &rp)) + return 1; + + /* Set up blenders */ + pixg = pixRead("blender8.png"); + pix1 = pixRead("weasel4.11c.png"); + pixc = pixRemoveColormap(pix1, REMOVE_CMAP_TO_FULL_COLOR); + pixDestroy(&pix1); + pixa = pixaCreate(0); + + /* Gray blend (straight) */ + pixs = pixRead("test24.jpg"); + pix1 = pixScale(pixs, 0.4, 0.4); + GrayBlend(pix1, pixg, L_BLEND_GRAY, 0.3); + regTestWritePixAndCheck(rp, pix1, IFF_JFIF_JPEG); /* 0 */ + pixaAddPix(pixa, pix1, L_INSERT); + pixDisplayWithTitle(pix1, 0, 100, NULL, rp->display); + pixDestroy(&pixs); + + pixs = pixRead("marge.jpg"); + GrayBlend(pixs, pixg, L_BLEND_GRAY, 0.2); + regTestWritePixAndCheck(rp, pixs, IFF_JFIF_JPEG); /* 1 */ + pixaAddPix(pixa, pixs, L_INSERT); + pixDisplayWithTitle(pixs, 100, 100, NULL, rp->display); + + pixs = pixRead("marge.jpg"); + pix1 = pixConvertRGBToLuminance(pixs); + GrayBlend(pix1, pixg, L_BLEND_GRAY, 0.2); + regTestWritePixAndCheck(rp, pix1, IFF_JFIF_JPEG); /* 2 */ + pixaAddPix(pixa, pix1, L_INSERT); + pixDisplayWithTitle(pix1, 200, 100, NULL, rp->display); + pixDestroy(&pixs); + + /* Gray blend (inverse) */ + pixs = pixRead("test24.jpg"); + pix1 = pixScale(pixs, 0.4, 0.4); + GrayBlend(pix1, pixg, L_BLEND_GRAY_WITH_INVERSE, 0.6); + regTestWritePixAndCheck(rp, pix1, IFF_JFIF_JPEG); /* 3 */ + pixaAddPix(pixa, pix1, L_INSERT); + pixDisplayWithTitle(pix1, 300, 100, NULL, rp->display); + pixDestroy(&pixs); + + pixs = pixRead("marge.jpg"); + GrayBlend(pixs, pixg, L_BLEND_GRAY_WITH_INVERSE, 0.6); + regTestWritePixAndCheck(rp, pixs, IFF_JFIF_JPEG); /* 4 */ + pixaAddPix(pixa, pixs, L_INSERT); + pixDisplayWithTitle(pixs, 400, 100, NULL, rp->display); + + pixs = pixRead("marge.jpg"); + pix1 = pixConvertRGBToLuminance(pixs); + GrayBlend(pix1, pixg, L_BLEND_GRAY_WITH_INVERSE, 0.6); + regTestWritePixAndCheck(rp, pix1, IFF_JFIF_JPEG); /* 5 */ + pixaAddPix(pixa, pix1, L_INSERT); + pixDisplayWithTitle(pix1, 500, 100, NULL, rp->display); + pixDestroy(&pixs); + + pixs = MakeGrayWash(1000, 120); + GrayBlend(pixs, pixg, L_BLEND_GRAY_WITH_INVERSE, 0.3); + regTestWritePixAndCheck(rp, pixs, IFF_PNG); /* 6 */ + pixaAddPix(pixa, pixs, L_INSERT); + pixDisplayWithTitle(pixs, 0, 600, NULL, rp->display); + + pixs = MakeColorWash(1000, 120, COLOR_RED); + GrayBlend(pixs, pixg, L_BLEND_GRAY_WITH_INVERSE, 1.0); + regTestWritePixAndCheck(rp, pixs, IFF_PNG); /* 7 */ + pixaAddPix(pixa, pixs, L_INSERT); + pixDisplayWithTitle(pixs, 0, 750, NULL, rp->display); + + /* Adaptive gray blend */ + pixs = pixRead("test24.jpg"); + pix1 = pixScale(pixs, 0.4, 0.4); + AdaptiveGrayBlend(pix1, pixg, 0.8); + regTestWritePixAndCheck(rp, pix1, IFF_JFIF_JPEG); /* 8 */ + pixaAddPix(pixa, pix1, L_INSERT); + pixDisplayWithTitle(pix1, 600, 100, NULL, rp->display); + pixDestroy(&pixs); + + pixs = pixRead("marge.jpg"); + AdaptiveGrayBlend(pixs, pixg, 0.8); + regTestWritePixAndCheck(rp, pixs, IFF_JFIF_JPEG); /* 9 */ + pixaAddPix(pixa, pixs, L_INSERT); + pixDisplayWithTitle(pixs, 700, 100, NULL, rp->display); + + pix1 = pixConvertRGBToLuminance(pixs); + AdaptiveGrayBlend(pix1, pixg, 0.1); + regTestWritePixAndCheck(rp, pix1, IFF_JFIF_JPEG); /* 10 */ + pixaAddPix(pixa, pix1, L_INSERT); + pixDisplayWithTitle(pix1, 800, 100, NULL, rp->display); + + pixs = MakeGrayWash(1000, 120); + AdaptiveGrayBlend(pixs, pixg, 0.3); + regTestWritePixAndCheck(rp, pixs, IFF_PNG); /* 11 */ + pixaAddPix(pixa, pixs, L_INSERT); + pixDisplayWithTitle(pixs, 0, 900, NULL, rp->display); + + pixs = MakeColorWash(1000, 120, COLOR_RED); + AdaptiveGrayBlend(pixs, pixg, 0.5); + regTestWritePixAndCheck(rp, pixs, IFF_PNG); /* 12 */ + pixaAddPix(pixa, pixs, L_INSERT); + pixDisplayWithTitle(pixs, 0, 1050, NULL, rp->display); + + /* Color blend */ + pixs = pixRead("test24.jpg"); + pix1 = pixScale(pixs, 0.4, 0.4); + ColorBlend(pix1, pixc, 0.3); + regTestWritePixAndCheck(rp, pix1, IFF_JFIF_JPEG); /* 13 */ + pixaAddPix(pixa, pix1, L_INSERT); + pixDisplayWithTitle(pix1, 900, 100, NULL, rp->display); + pixDestroy(&pixs); + + pixs = pixRead("marge.jpg"); + ColorBlend(pixs, pixc, 0.30); + regTestWritePixAndCheck(rp, pixs, IFF_JFIF_JPEG); /* 14 */ + pixaAddPix(pixa, pixs, L_INSERT); + pixDisplayWithTitle(pixs, 1000, 100, NULL, rp->display); + + pixs = pixRead("marge.jpg"); + ColorBlend(pixs, pixc, 0.15); + regTestWritePixAndCheck(rp, pixs, IFF_JFIF_JPEG); /* 15 */ + pixaAddPix(pixa, pixs, L_INSERT); + pixDisplayWithTitle(pixs, 1100, 100, NULL, rp->display); + + /* Mosaic all results */ + pix1 = pixaDisplayTiledInRows(pixa, 32, 1700, 1.0, 0, 20, 2); + regTestWritePixAndCheck(rp, pix1, IFF_JFIF_JPEG); /* 16 */ + pixDisplayWithTitle(pix1, 0, 0, NULL, rp->display); + pixaDestroy(&pixa); + pixDestroy(&pix1); + + pixDestroy(&pixg); + pixDestroy(&pixc); + return regTestCleanup(rp); +} + + +void +GrayBlend(PIX *pixs, + PIX *pixb, + l_int32 op, + l_float32 fract) +{ +l_int32 i, j, wb, hb, ws, hs, delx, dely, x, y; + + pixGetDimensions(pixs, &ws, &hs, NULL); + pixGetDimensions(pixb, &wb, &hb, NULL); + delx = wb + 30; + dely = hb + 25; + x = 200; + y = 300; + for (i = 0; i < 20; i++) { + y = 20 + i * dely; + if (y >= hs - hb) + continue; + for (j = 0; j < 20; j++) { + x = 30 + j * delx; + if (x >= ws - wb) + continue; + pixBlendGray(pixs, pixs, pixb, x, y, fract, op, 1, 255); + } + } +} + + +void +AdaptiveGrayBlend(PIX *pixs, + PIX *pixb, + l_float32 fract) +{ +l_int32 i, j, wb, hb, ws, hs, delx, dely, x, y; + + pixGetDimensions(pixs, &ws, &hs, NULL); + pixGetDimensions(pixb, &wb, &hb, NULL); + delx = wb + 30; + dely = hb + 25; + x = 200; + y = 300; + for (i = 0; i < 20; i++) { + y = 20 + i * dely; + if (y >= hs - hb) + continue; + for (j = 0; j < 20; j++) { + x = 30 + j * delx; + if (x >= ws - wb) + continue; + pixBlendGrayAdapt(pixs, pixs, pixb, x, y, fract, 80); + } + } +} + + +void +ColorBlend(PIX *pixs, + PIX *pixb, + l_float32 fract) +{ +l_int32 i, j, wb, hb, ws, hs, delx, dely, x, y; + + pixGetDimensions(pixs, &ws, &hs, NULL); + pixGetDimensions(pixb, &wb, &hb, NULL); + delx = wb + 30; + dely = hb + 25; + x = 200; + y = 300; + for (i = 0; i < 20; i++) { + y = 20 + i * dely; + if (y >= hs - hb) + continue; + for (j = 0; j < 20; j++) { + x = 30 + j * delx; + if (x >= ws - wb) + continue; + pixBlendColor(pixs, pixs, pixb, x, y, fract, 1, 255); + } + } +} + + +PIX * +MakeGrayWash(l_int32 w, + l_int32 h) +{ +l_int32 i, j, wpl, val; +l_uint32 *data, *line; +PIX *pixd; + + pixd = pixCreate(w, h, 8); + data = pixGetData(pixd); + wpl = pixGetWpl(pixd); + for (i = 0; i < h; i++) { + line = data + i * wpl; + for (j = 0; j < w; j++) { + val = (j * 255) / w; + SET_DATA_BYTE(line, j, val); + } + } + return pixd; +} + + +PIX * +MakeColorWash(l_int32 w, + l_int32 h, + l_int32 color) +{ +l_int32 i, j, wpl; +l_uint32 val; +l_uint32 *data, *line; +PIX *pixd; + + pixd = pixCreate(w, h, 32); + data = pixGetData(pixd); + wpl = pixGetWpl(pixd); + for (i = 0; i < h; i++) { + line = data + i * wpl; + for (j = 0; j < w; j++) { + if (color == COLOR_RED) + val = ((j * 255) / w) << L_GREEN_SHIFT | + ((j * 255) / w) << L_BLUE_SHIFT | + 255 << L_RED_SHIFT; + else if (color == COLOR_GREEN) + val = ((j * 255) / w) << L_RED_SHIFT | + ((j * 255) / w) << L_BLUE_SHIFT | + 255 << L_GREEN_SHIFT; + else + val = ((j * 255) / w) << L_RED_SHIFT | + ((j * 255) / w) << L_GREEN_SHIFT | + 255 << L_BLUE_SHIFT; + line[j] = val; + } + } + return pixd; +} + diff --git a/leptonica/prog/blend2_reg.c b/leptonica/prog/blend2_reg.c new file mode 100644 index 00000000..fb10846e --- /dev/null +++ b/leptonica/prog/blend2_reg.c @@ -0,0 +1,182 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * blend2_reg.c + * + * Regression test for this function: + * pixBlendWithGrayMask() + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + + /* In case libpng is not enabled */ +static const char fname_png[64] = "/tmp/lept/regout/blend2.14.png"; +static const char fname_bmp[64] = "/tmp/lept/regout/blend2.14.bmp"; + + +int main(int argc, + char **argv) +{ +l_int32 i, j, w1, h1, w2, h2, w, h; +BOX *box1, *box2; +PIX *pixg, *pixs1, *pixs2, *pix1, *pix2, *pix3, *pix4, *pix5; +PIXA *pixa; +L_REGPARAMS *rp; + + if (regTestSetup(argc, argv, &rp)) + return 1; + + /* --- Set up the 8 bpp blending image --- */ + pixg = pixCreate(660, 500, 8); + for (i = 0; i < 500; i++) + for (j = 0; j < 660; j++) + pixSetPixel(pixg, j, i, (l_int32)(0.775 * j) % 256); + + /* --- Set up the initial color images to be blended together --- */ + pixs1 = pixRead("wyom.jpg"); + pixs2 = pixRead("fish24.jpg"); + pixGetDimensions(pixs1, &w, &h, NULL); + pixGetDimensions(pixs1, &w1, &h1, NULL); + pixGetDimensions(pixs2, &w2, &h2, NULL); + h = L_MIN(h1, h2); + w = L_MIN(w1, w2); + box1 = boxCreate(0, 0, w, h); + box2 = boxCreate(0, 300, 660, 500); + pix1 = pixClipRectangle(pixs1, box1, NULL); + pix2 = pixClipRectangle(pixs2, box2, NULL); + pixDestroy(&pixs1); + pixDestroy(&pixs2); + boxDestroy(&box1); + boxDestroy(&box2); + + /* --- Blend 2 rgb images --- */ + pixa = pixaCreate(0); + pix3 = pixBlendWithGrayMask(pix1, pix2, pixg, 50, 50); + pixaAddPix(pixa, pix1, L_COPY); + pixaAddPix(pixa, pix2, L_COPY); + pixaAddPix(pixa, pix3, L_INSERT); + regTestWritePixAndCheck(rp, pixg, IFF_JFIF_JPEG); /* 0 */ + regTestWritePixAndCheck(rp, pix1, IFF_JFIF_JPEG); /* 1 */ + regTestWritePixAndCheck(rp, pix2, IFF_JFIF_JPEG); /* 2 */ + regTestWritePixAndCheck(rp, pix3, IFF_JFIF_JPEG); /* 3 */ + + /* --- Blend 2 grayscale images --- */ + pix3 = pixConvertRGBToLuminance(pix1); + pix4 = pixConvertRGBToLuminance(pix2); + pix5 = pixBlendWithGrayMask(pix3, pix4, pixg, 50, 50); + pixaAddPix(pixa, pix3, L_INSERT); + pixaAddPix(pixa, pix4, L_INSERT); + pixaAddPix(pixa, pix5, L_INSERT); + regTestWritePixAndCheck(rp, pix3, IFF_JFIF_JPEG); /* 4 */ + regTestWritePixAndCheck(rp, pix4, IFF_JFIF_JPEG); /* 5 */ + regTestWritePixAndCheck(rp, pix5, IFF_JFIF_JPEG); /* 6 */ + + /* --- Blend a colormap image and an rgb image --- */ + pix3 = pixFixedOctcubeQuantGenRGB(pix2, 2); + pix4 = pixBlendWithGrayMask(pix1, pix3, pixg, 50, 50); + pixaAddPix(pixa, pix1, L_COPY); + pixaAddPix(pixa, pix3, L_INSERT); + pixaAddPix(pixa, pix4, L_INSERT); + regTestWritePixAndCheck(rp, pix3, IFF_JFIF_JPEG); /* 7 */ + regTestWritePixAndCheck(rp, pix4, IFF_JFIF_JPEG); /* 8 */ + + /* --- Blend a colormap image and a grayscale image --- */ + pix3 = pixConvertRGBToLuminance(pix1); + pix4 = pixFixedOctcubeQuantGenRGB(pix2, 2); + pix5 = pixBlendWithGrayMask(pix3, pix4, pixg, 50, 50); + pixaAddPix(pixa, pix3, L_COPY); + pixaAddPix(pixa, pix4, L_COPY); + pixaAddPix(pixa, pix5, L_INSERT); + regTestWritePixAndCheck(rp, pix3, IFF_JFIF_JPEG); /* 9 */ + regTestWritePixAndCheck(rp, pix4, IFF_JFIF_JPEG); /* 10 */ + regTestWritePixAndCheck(rp, pix5, IFF_JFIF_JPEG); /* 11 */ + pix5 = pixBlendWithGrayMask(pix3, pix4, pixg, -100, -100); + pixaAddPix(pixa, pix3, L_INSERT); + pixaAddPix(pixa, pix4, L_INSERT); + pixaAddPix(pixa, pix5, L_INSERT); + regTestWritePixAndCheck(rp, pix5, IFF_JFIF_JPEG); /* 12 */ + pixDestroy(&pix1); + pixDestroy(&pix2); + + /* --------- Test png read/write with alpha channel --------- */ + /* First make pix2, using pixg as the alpha channel */ + pix1 = pixRead("fish24.jpg"); + box1 = boxCreate(0, 300, 660, 500); + pix2 = pixClipRectangle(pix1, box1, NULL); + boxDestroy(&box1); + pixaAddPix(pixa, pix2, L_COPY); + regTestWritePixAndCheck(rp, pix2, IFF_JFIF_JPEG); /* 13 */ + pixSetRGBComponent(pix2, pixg, L_ALPHA_CHANNEL); + regTestWritePixAndCheck(rp, pix2, IFF_PNG); /* 14 */ + + /* To see the alpha channel, blend with a black image */ + pix3 = pixCreate(660, 500, 32); + pix4 = pixBlendWithGrayMask(pix3, pix2, NULL, 0, 0); + pixaAddPix(pixa, pix4, L_INSERT); + regTestWritePixAndCheck(rp, pix4, IFF_JFIF_JPEG); /* 15 */ + + /* Read the RGBA image #14 back */ +#if defined(HAVE_LIBPNG) + pix4 = pixRead(fname_png); +#else + pix4 = pixRead(fname_bmp); +#endif + + /* Make sure that the alpha channel image hasn't changed */ + pix5 = pixGetRGBComponent(pix4, L_ALPHA_CHANNEL); + regTestComparePix(rp, pixg, pix5); /* 16 */ + pixDestroy(&pix5); + + /* Blend again with a black image */ + pix5 = pixBlendWithGrayMask(pix3, pix4, NULL, 0, 0); + pixaAddPix(pixa, pix5, L_INSERT); + regTestWritePixAndCheck(rp, pix5, IFF_JFIF_JPEG); /* 17 */ + + /* Blend with a white image */ + pixSetAll(pix3); + pix5 = pixBlendWithGrayMask(pix3, pix4, NULL, 0, 0); + pixaAddPix(pixa, pix5, L_INSERT); + regTestWritePixAndCheck(rp, pix5, IFF_JFIF_JPEG); /* 18 */ + pixDestroy(&pixg); + pixDestroy(&pix1); + pixDestroy(&pix2); + pixDestroy(&pix3); + pixDestroy(&pix4); + + /* Display results */ + pix1 = pixaDisplayTiledInColumns(pixa, 3, 1.0, 40, 2); + pixDisplayWithTitle(pix1, 100, 100, NULL, rp->display); + regTestWritePixAndCheck(rp, pix1, IFF_JFIF_JPEG); /* 19 */ + pixDestroy(&pix1); + pixaDestroy(&pixa); + + return regTestCleanup(rp); +} diff --git a/leptonica/prog/blend3_reg.c b/leptonica/prog/blend3_reg.c new file mode 100644 index 00000000..1f3c35e6 --- /dev/null +++ b/leptonica/prog/blend3_reg.c @@ -0,0 +1,216 @@ +/*====================================================================* + - 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. + *====================================================================*/ + + +/* + * blend3_reg.c + * + * 42 results: 6 input image combinations * 7 blendings + */ + +#include "allheaders.h" + +#define X 140 +#define Y 40 +#define ALL 1 + +static PIX *BlendTest(const char *file1, const char *file2, l_float32 fract); + +int main(int argc, + char **argv) +{ +PIX *pixt, *pixd; +PIXA *pixa; +L_REGPARAMS *rp; + + if (regTestSetup(argc, argv, &rp)) + return 1; + + pixa = pixaCreate(6); + + pixt = BlendTest("marge.jpg", "feyn-word.tif", 0.5); + pixaAddPix(pixa, pixt, L_INSERT); + regTestWritePixAndCheck(rp, pixt, IFF_JFIF_JPEG); /* 0 */ + pixDisplayWithTitle(pixt, 0, 0, NULL, rp->display); + + pixt = BlendTest("marge.jpg", "weasel8.png", 0.3); + pixaAddPix(pixa, pixt, L_INSERT); + regTestWritePixAndCheck(rp, pixt, IFF_JFIF_JPEG); /* 1 */ + pixDisplayWithTitle(pixt, 0, 200, NULL, rp->display); + + pixt = BlendTest("marge.jpg", "weasel8.240c.png", 0.3); + pixaAddPix(pixa, pixt, L_INSERT); + regTestWritePixAndCheck(rp, pixt, IFF_JFIF_JPEG); /* 2 */ + pixDisplayWithTitle(pixt, 0, 400, NULL, rp->display); + + pixt = BlendTest("test8.jpg", "feyn-word.tif", 0.5); + pixaAddPix(pixa, pixt, L_INSERT); + regTestWritePixAndCheck(rp, pixt, IFF_JFIF_JPEG); /* 3 */ + pixDisplayWithTitle(pixt, 0, 600, NULL, rp->display); + + pixt = BlendTest("test8.jpg", "weasel8.png", 0.5); + pixaAddPix(pixa, pixt, L_INSERT); + regTestWritePixAndCheck(rp, pixt, IFF_JFIF_JPEG); /* 4 */ + pixDisplayWithTitle(pixt, 0, 800, NULL, rp->display); + + pixt = BlendTest("test8.jpg", "weasel8.240c.png", 0.6); + pixaAddPix(pixa, pixt, L_INSERT); + regTestWritePixAndCheck(rp, pixt, IFF_JFIF_JPEG); /* 5 */ + pixDisplayWithTitle(pixt, 0, 1000, NULL, rp->display); + + pixd = pixaDisplayTiledInRows(pixa, 32, 1800, 1.0, 0, 20, 2); + pixWrite("/tmp/lept/regout/blendall.jpg", pixd, IFF_JFIF_JPEG); + pixaDestroy(&pixa); + pixDestroy(&pixd); + + return regTestCleanup(rp); +} + + +static PIX * +BlendTest(const char *file1, + const char *file2, + l_float32 fract) +{ +l_int32 d1, d2; +PIX *pixs1, *pixs2, *pix1, *pix2, *pix3, *pix4, *pix5, *pixd; +PIXA *pixa; + + pixs1 = pixRead(file1); + pixs2 = pixRead(file2); + d1 = pixGetDepth(pixs1); + d2 = pixGetDepth(pixs2); + pixa = pixaCreate(7); + +#if ALL + if (d1 == 1) { + pix1 = pixBlend(pixs1, pixs2, X, Y, fract); + pix2 = pixBlend(pix1, pixs2, X, Y + 60, fract); + pix3 = pixBlend(pix2, pixs2, X, Y + 120, fract); + pix4 = pixBlend(pix3, pixs2, X, Y + 180, fract); + pix5 = pixBlend(pix4, pixs2, X, Y + 240, fract); + pixd = pixBlend(pix5, pixs2, X, Y + 300, fract); + pixDestroy(&pix1); + pixDestroy(&pix2); + pixDestroy(&pix3); + pixDestroy(&pix4); + pixDestroy(&pix5); + } else { + pix1 = pixBlend(pixs1, pixs2, X, Y, fract); + pix2 = pixBlend(pix1, pixs2, X + 80, Y + 80, fract); + pix3 = pixBlend(pix2, pixs2, X + 160, Y + 160, fract); + pix4 = pixBlend(pix3, pixs2, X + 240, Y + 240, fract); + pix5 = pixBlend(pix4, pixs2, X + 320, Y + 320, fract); + pixd = pixBlend(pix5, pixs2, X + 360, Y + 360, fract); + pixDestroy(&pix1); + pixDestroy(&pix2); + pixDestroy(&pix3); + pixDestroy(&pix4); + pixDestroy(&pix5); + } + pixaAddPix(pixa, pixd, L_INSERT); +#endif + +#if ALL + /* Gray blend */ + if (d2 >= 8) + pixSnapColor(pixs2, pixs2, 0xff, 0xff, 50); + pixd = pixBlendGray(NULL, pixs1, pixs2, 200, 100, fract, + L_BLEND_GRAY, 1, 0xff); + pixBlendGray(pixd, pixd, pixs2, 200, 200, fract, + L_BLEND_GRAY, 1, 0xff); + pixBlendGray(pixd, pixd, pixs2, 200, 260, fract, + L_BLEND_GRAY, 1, 0xff); + pixBlendGray(pixd, pixd, pixs2, 200, 340, fract, + L_BLEND_GRAY, 1, 0xff); + pixaAddPix(pixa, pixd, L_INSERT); +#endif + +#if ALL /* Gray blend (with inverse) */ + if (d2 >= 8) + pixSnapColor(pixs2, pixs2, 0xff, 0xff, 50); + pixd = pixBlendGray(NULL, pixs1, pixs2, 200, 100, fract, + L_BLEND_GRAY_WITH_INVERSE, 1, 0xff); + pixBlendGray(pixd, pixd, pixs2, 200, 200, fract, + L_BLEND_GRAY_WITH_INVERSE, 1, 0xff); + pixBlendGray(pixd, pixd, pixs2, 200, 260, fract, + L_BLEND_GRAY_WITH_INVERSE, 1, 0xff); + pixBlendGray(pixd, pixd, pixs2, 200, 340, fract, + L_BLEND_GRAY_WITH_INVERSE, 1, 0xff); + pixaAddPix(pixa, pixd, L_INSERT); +#endif + +#if ALL /* Blend Gray for robustness */ + if (d2 >= 8) + pixSnapColor(pixs2, pixs2, 0xff, 0xff, 50); + pixd = pixBlendGrayInverse(NULL, pixs1, pixs2, 200, 100, fract); + pixBlendGrayInverse(pixd, pixd, pixs2, 200, 200, fract); + pixBlendGrayInverse(pixd, pixd, pixs2, 200, 260, fract); + pixBlendGrayInverse(pixd, pixd, pixs2, 200, 340, fract); + pixaAddPix(pixa, pixd, L_INSERT); +#endif + +#if ALL /* Blend Gray adapted */ + if (d2 >= 8) + pixSnapColor(pixs2, pixs2, 0xff, 0xff, 50); + pixd = pixBlendGrayAdapt(NULL, pixs1, pixs2, 200, 100, fract, 120); + pixBlendGrayAdapt(pixd, pixd, pixs2, 200, 200, fract, 120); + pixBlendGrayAdapt(pixd, pixd, pixs2, 200, 260, fract, 120); + pixBlendGrayAdapt(pixd, pixd, pixs2, 200, 340, fract, 120); + pixaAddPix(pixa, pixd, L_INSERT); +#endif + +#if ALL /* Blend color */ + if (d2 >= 8) + pixSnapColor(pixs2, pixs2, 0xffffff00, 0xffffff00, 50); + pixd = pixBlendColor(NULL, pixs1, pixs2, 200, 100, fract, 1, 0xffffff00); + pixBlendColor(pixd, pixd, pixs2, 200, 200, fract, 1, 0xffffff00); + pixBlendColor(pixd, pixd, pixs2, 200, 260, fract, 1, 0xffffff00); + pixBlendColor(pixd, pixd, pixs2, 200, 340, fract, 1, 0xffffff00); + pixaAddPix(pixa, pixd, L_INSERT); +#endif + +#if ALL /* Blend color by channel */ + if (d2 >= 8) + pixSnapColor(pixs2, pixs2, 0xffffff00, 0xffffff00, 50); + pixd = pixBlendColorByChannel(NULL, pixs1, pixs2, 200, 100, 1.6 * fract, + fract, 0.5 * fract, 1, 0xffffff00); + pixBlendColorByChannel(pixd, pixd, pixs2, 200, 200, 1.2 * fract, + fract, 0.2 * fract, 1, 0xffffff00); + pixBlendColorByChannel(pixd, pixd, pixs2, 200, 260, 1.6 * fract, + 1.8 * fract, 0.3 * fract, 1, 0xffffff00); + pixBlendColorByChannel(pixd, pixd, pixs2, 200, 340, 0.4 * fract, + 1.3 * fract, 1.8 * fract, 1, 0xffffff00); + pixaAddPix(pixa, pixd, L_INSERT); +#endif + + pixd = pixaDisplayTiledInRows(pixa, 32, 2500, 0.5, 0, 20, 2); + pixaDestroy(&pixa); + pixDestroy(&pixs1); + pixDestroy(&pixs2); + return pixd; +} + diff --git a/leptonica/prog/blend4_reg.c b/leptonica/prog/blend4_reg.c new file mode 100644 index 00000000..d923f72c --- /dev/null +++ b/leptonica/prog/blend4_reg.c @@ -0,0 +1,102 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * blend4_reg.c + * + * Regression test for this function: + * pixAddAlphaToBlend() + * + * Blending is done using pixBlendWithGrayMask() + */ + +#include "allheaders.h" + +static const char *blenders[] = + {"feyn-word.tif", "weasel4.16c.png", "karen8.jpg"}; + +int main(int argc, + char **argv) +{ +l_int32 i, w, h; +PIX *pix0, *pix1, *pix2, *pix3, *pix4, *pix5; +PIXA *pixa; +L_REGPARAMS *rp; + + if (regTestSetup(argc, argv, &rp)) + return 1; + + pixa = pixaCreate(0); + + /* Blending on a light image */ + pix1 = pixRead("fish24.jpg"); + pixGetDimensions(pix1, &w, &h, NULL); + for (i = 0; i < 3; i++) { + pix2 = pixRead(blenders[i]); + if (i == 2) { + pix3 = pixScale(pix2, 0.5, 0.5); + pixDestroy(&pix2); + pix2 = pix3; + } + pix3 = pixAddAlphaToBlend(pix2, 0.3, 0); + pix4 = pixMirroredTiling(pix3, w, h); + pix5 = pixBlendWithGrayMask(pix1, pix4, NULL, 0, 0); + pixaAddPix(pixa, pix5, L_INSERT); + regTestWritePixAndCheck(rp, pix5, IFF_JFIF_JPEG); /* 0 - 2 */ + pixDisplayWithTitle(pix5, 200 * i, 0, NULL, rp->display); + pixDestroy(&pix2); + pixDestroy(&pix3); + pixDestroy(&pix4); + } + pixDestroy(&pix1); + + /* Blending on a dark image */ + pix0 = pixRead("karen8.jpg"); + pix1 = pixScale(pix0, 2.0, 2.0); + pixGetDimensions(pix1, &w, &h, NULL); + for (i = 0; i < 2; i++) { + pix2 = pixRead(blenders[i]); + pix3 = pixAddAlphaToBlend(pix2, 0.3, 1); + pix4 = pixMirroredTiling(pix3, w, h); + pix5 = pixBlendWithGrayMask(pix1, pix4, NULL, 0, 0); + pixaAddPix(pixa, pix5, L_INSERT); + regTestWritePixAndCheck(rp, pix5, IFF_JFIF_JPEG); /* 3 - 4 */ + pixDisplayWithTitle(pix5, 600 + 200 * i, 0, NULL, rp->display); + pixDestroy(&pix2); + pixDestroy(&pix3); + pixDestroy(&pix4); + } + + pixaConvertToPdf(pixa, 100, 1.0, L_JPEG_ENCODE, 0, + "Blendings: blend4_reg", "/tmp/lept/regout/blend.pdf"); + L_INFO("Output pdf: /tmp/lept/regout/blend.pdf\n", rp->testname); + pixDestroy(&pix0); + pixDestroy(&pix1); + pixaDestroy(&pixa); + + return regTestCleanup(rp); +} + diff --git a/leptonica/prog/blend5_reg.c b/leptonica/prog/blend5_reg.c new file mode 100644 index 00000000..3da53ff0 --- /dev/null +++ b/leptonica/prog/blend5_reg.c @@ -0,0 +1,182 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * blend5_reg.c + * + * Regression test for these functions in blend.c: + * - pixSnapColor(): used here to color the background on images + * in index.html + * - pixLinearEdgeFade() + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + +static const l_uint32 LEPTONICA_YELLOW = 0xffffe400; + +int main(int argc, + char **argv) +{ +l_uint32 val32; +PIX *pixs, *pix1, *pix2; +PIXA *pixa; +L_REGPARAMS *rp; + + if (regTestSetup(argc, argv, &rp)) + return 1; + + pixa = pixaCreate(0); + + /* First, snap the color directly on the input rgb image. */ + pixs = pixRead("Leptonica.jpg"); + pixaAddPix(pixa, pixs, L_COPY); + pixDisplayWithTitle(pixs, 0, 0, NULL, rp->display); + pix1 = pixSnapColor(NULL, pixs, 0xffffff00, LEPTONICA_YELLOW, 30); + pixaAddPix(pixa, pix1, L_INSERT); + regTestWritePixAndCheck(rp, pix1, IFF_JFIF_JPEG); /* 0 */ + pixDisplayWithTitle(pix1, 480, 0, NULL, rp->display); + + /* Then make a colormapped version and snap the color */ + pix1 = pixOctreeQuantNumColors(pixs, 250, 0); + pixaAddPix(pixa, pix1, L_COPY); + pixSnapColor(pix1, pix1, 0xffffff00, LEPTONICA_YELLOW, 30); + pixaAddPix(pixa, pix1, L_INSERT); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 1 */ + pixDisplayWithTitle(pix1, 880, 0, NULL, rp->display); + pixDestroy(&pixs); + + /* Set the background of the google searchbox to yellow. + * The input image is colormapped with all 256 colors used. */ + pixs = pixRead("google-searchbox.png"); + pixaAddPix(pixa, pixs, L_INSERT); + pixDisplayWithTitle(pixs, 0, 200, NULL, rp->display); + pix1 = pixSnapColor(NULL, pixs, 0xffffff00, LEPTONICA_YELLOW, 30); + pixaAddPix(pixa, pix1, L_INSERT); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 2 */ + pixDisplayWithTitle(pix1, 220, 200, NULL, rp->display); + + /* A couple of more, setting pixels near white to strange colors */ + pixs = pixRead("weasel4.11c.png"); + pixaAddPix(pixa, pixs, L_INSERT); + pixDisplayWithTitle(pixs, 0, 300, NULL, rp->display); + pix1 = pixSnapColor(NULL, pixs, 0xfefefe00, 0x80800000, 50); + pixaAddPix(pixa, pix1, L_INSERT); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 3 */ + pixDisplayWithTitle(pix1, 200, 300, NULL, rp->display); + + pixs = pixRead("wyom.jpg"); + pix1 = pixFixedOctcubeQuant256(pixs, 0); + pixaAddPix(pixa, pix1, L_INSERT); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 4 */ + pixDisplayWithTitle(pix1, 0, 450, NULL, rp->display); + pix2 = pixSnapColor(NULL, pix1, 0xf0f0f000, 0x80008000, 100); + pixaAddPix(pixa, pix2, L_INSERT); + regTestWritePixAndCheck(rp, pix2, IFF_PNG); /* 5 */ + pixDisplayWithTitle(pix2, 900, 450, NULL, rp->display); + pixDestroy(&pixs); + + /* --- Display results --- */ + pix1 = pixaDisplayTiledInColumns(pixa, 2, 1.0, 25, 2); + regTestWritePixAndCheck(rp, pix1, IFF_JFIF_JPEG); /* 6 */ + pixDisplayWithTitle(pix1, 500, 0, NULL, rp->display); + pixDestroy(&pix1); + pixaDestroy(&pixa); + + /* Test linear fade to black */ + composeRGBPixel(90, 170, 145, &val32); + pix1 = pixCreate(300, 300, 32); + pixSetAllArbitrary(pix1, val32); + pixLinearEdgeFade(pix1, L_FROM_LEFT, L_BLEND_TO_BLACK, 0.5, 0.8); + pixLinearEdgeFade(pix1, L_FROM_RIGHT, L_BLEND_TO_BLACK, 0.5, 0.8); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 7 */ + pixDisplayWithTitle(pix1, 900, 0, NULL, rp->display); + pixDestroy(&pix1); + pix1 = pixCreate(300, 300, 32); + pixSetAllArbitrary(pix1, val32); + pixLinearEdgeFade(pix1, L_FROM_TOP, L_BLEND_TO_BLACK, 0.5, 0.8); + pixLinearEdgeFade(pix1, L_FROM_BOT, L_BLEND_TO_BLACK, 0.5, 0.8); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 8 */ + pixDisplayWithTitle(pix1, 1250, 0, NULL, rp->display); + pixDestroy(&pix1); + pix1 = pixCreate(300, 300, 32); + pixSetAllArbitrary(pix1, val32); + pixLinearEdgeFade(pix1, L_FROM_LEFT, L_BLEND_TO_BLACK, 0.5, 0.8); + pixLinearEdgeFade(pix1, L_FROM_RIGHT, L_BLEND_TO_BLACK, 0.5, 0.8); + pixLinearEdgeFade(pix1, L_FROM_TOP, L_BLEND_TO_BLACK, 0.5, 0.8); + pixLinearEdgeFade(pix1, L_FROM_BOT, L_BLEND_TO_BLACK, 0.5, 0.8); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 9 */ + pixDisplayWithTitle(pix1, 1600, 0, NULL, rp->display); + pixDestroy(&pix1); + pix1 = pixCreate(300, 300, 8); /* 8 bpp */ + pixSetAll(pix1); + pixLinearEdgeFade(pix1, L_FROM_LEFT, L_BLEND_TO_BLACK, 0.5, 0.8); + pixLinearEdgeFade(pix1, L_FROM_RIGHT, L_BLEND_TO_BLACK, 0.5, 0.8); + pixLinearEdgeFade(pix1, L_FROM_TOP, L_BLEND_TO_BLACK, 0.5, 0.8); + pixLinearEdgeFade(pix1, L_FROM_BOT, L_BLEND_TO_BLACK, 0.5, 0.8); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 10 */ + pixDisplayWithTitle(pix1, 1950, 0, NULL, rp->display); + pixDestroy(&pix1); + + /* Test linear fade to white */ + composeRGBPixel(170, 110, 200, &val32); + pix1 = pixCreate(300, 300, 32); + pixSetAllArbitrary(pix1, val32); + pixLinearEdgeFade(pix1, L_FROM_LEFT, L_BLEND_TO_WHITE, 0.5, 0.8); + pixLinearEdgeFade(pix1, L_FROM_RIGHT, L_BLEND_TO_WHITE, 0.5, 0.8); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 11 */ + pixDisplayWithTitle(pix1, 900, 380, NULL, rp->display); + pixDestroy(&pix1); + pix1 = pixCreate(300, 300, 32); + pixSetAllArbitrary(pix1, val32); + pixLinearEdgeFade(pix1, L_FROM_TOP, L_BLEND_TO_WHITE, 0.5, 0.8); + pixLinearEdgeFade(pix1, L_FROM_BOT, L_BLEND_TO_WHITE, 0.5, 0.8); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 12 */ + pixDisplayWithTitle(pix1, 1250, 380, NULL, rp->display); + pixDestroy(&pix1); + pix1 = pixCreate(300, 300, 32); + pixSetAllArbitrary(pix1, val32); + pixLinearEdgeFade(pix1, L_FROM_LEFT, L_BLEND_TO_WHITE, 0.5, 0.8); + pixLinearEdgeFade(pix1, L_FROM_RIGHT, L_BLEND_TO_WHITE, 0.5, 0.8); + pixLinearEdgeFade(pix1, L_FROM_TOP, L_BLEND_TO_WHITE, 0.5, 0.8); + pixLinearEdgeFade(pix1, L_FROM_BOT, L_BLEND_TO_WHITE, 0.5, 0.8); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 13 */ + pixDisplayWithTitle(pix1, 1600, 380, NULL, rp->display); + pixDestroy(&pix1); + pix1 = pixCreate(300, 300, 8); /* 8 bpp */ + pixLinearEdgeFade(pix1, L_FROM_LEFT, L_BLEND_TO_WHITE, 0.5, 0.8); + pixLinearEdgeFade(pix1, L_FROM_RIGHT, L_BLEND_TO_WHITE, 0.5, 0.8); + pixLinearEdgeFade(pix1, L_FROM_TOP, L_BLEND_TO_WHITE, 0.5, 0.8); + pixLinearEdgeFade(pix1, L_FROM_BOT, L_BLEND_TO_WHITE, 0.5, 0.8); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 14 */ + pixDisplayWithTitle(pix1, 1950, 380, NULL, rp->display); + pixDestroy(&pix1); + + return regTestCleanup(rp); +} diff --git a/leptonica/prog/blendcmaptest.c b/leptonica/prog/blendcmaptest.c new file mode 100644 index 00000000..00a05099 --- /dev/null +++ b/leptonica/prog/blendcmaptest.c @@ -0,0 +1,112 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * blendcmaptest.c + * + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + +static const l_int32 NX = 4; +static const l_int32 NY = 5; +static const l_float32 FADE_FRACTION = 0.75; + +int main(int argc, + char **argv) +{ +l_int32 i, j, sindex, wb, hb, ws, hs, delx, dely, x, y, y0; +PIX *pixs, *pixb, *pix1, *pix2; +PIXA *pixa; +PIXCMAP *cmap; + + setLeptDebugOK(1); + lept_mkdir("lept/blend"); + pixa = pixaCreate(0); + + pixs = pixRead("rabi.png"); /* blendee */ + pixb = pixRead("weasel4.11c.png"); /* blender */ + + /* Fade the blender */ + pixcmapShiftIntensity(pixGetColormap(pixb), FADE_FRACTION); + + /* Downscale the input */ + wb = pixGetWidth(pixb); + hb = pixGetHeight(pixb); + pix1 = pixScaleToGray4(pixs); + + /* Threshold to 5 levels, 4 bpp */ + ws = pixGetWidth(pix1); + hs = pixGetHeight(pix1); + pix2 = pixThresholdTo4bpp(pix1, 5, 1); + pixaAddPix(pixa, pix2, L_COPY); + pixaAddPix(pixa, pixb, L_COPY); + cmap = pixGetColormap(pix2); + pixcmapWriteStream(stderr, cmap); + + /* Overwrite the white pixels (at sindex in pix2) */ + pixcmapGetIndex(cmap, 255, 255, 255, &sindex); + + /* Blend the weasel 20 times */ + delx = ws / NX; + dely = hs / NY; + for (i = 0; i < NY; i++) { + y = 20 + i * dely; + if (y >= hs + hb) + continue; + for (j = 0; j < NX; j++) { + x = 30 + j * delx; + y0 = y; + if (j & 1) { + y0 = y + dely / 2; + if (y0 >= hs + hb) + continue; + } + if (x >= ws + wb) + continue; + pixBlendCmap(pix2, pixb, x, y0, sindex); + } + } + + pixaAddPix(pixa, pix2, L_COPY); + cmap = pixGetColormap(pix2); + pixcmapWriteStream(stderr, cmap); + lept_stderr("Writing to: /tmp/lept/blend/blendcmap.pdf\n"); + pixaConvertToPdf(pixa, 0, 1.0, L_FLATE_ENCODE, 0, "cmap-blendtest", + "/tmp/lept/blend/blendcmap.pdf"); + + pixDestroy(&pixs); + pixDestroy(&pixb); + pixDestroy(&pix1); + pixDestroy(&pix2); + pixaDestroy(&pixa); + return 0; +} + diff --git a/leptonica/prog/blender1.tif b/leptonica/prog/blender1.tif Binary files differnew file mode 100644 index 00000000..b570706d --- /dev/null +++ b/leptonica/prog/blender1.tif diff --git a/leptonica/prog/blender8.png b/leptonica/prog/blender8.png Binary files differnew file mode 100644 index 00000000..122802ca --- /dev/null +++ b/leptonica/prog/blender8.png diff --git a/leptonica/prog/blendtext.tif b/leptonica/prog/blendtext.tif Binary files differnew file mode 100644 index 00000000..b570706d --- /dev/null +++ b/leptonica/prog/blendtext.tif diff --git a/leptonica/prog/bois-2.tif b/leptonica/prog/bois-2.tif Binary files differnew file mode 100644 index 00000000..c6820674 --- /dev/null +++ b/leptonica/prog/bois-2.tif diff --git a/leptonica/prog/bois-3.tif b/leptonica/prog/bois-3.tif Binary files differnew file mode 100644 index 00000000..fc85fd94 --- /dev/null +++ b/leptonica/prog/bois-3.tif diff --git a/leptonica/prog/bois-4.tif b/leptonica/prog/bois-4.tif Binary files differnew file mode 100644 index 00000000..9cef270f --- /dev/null +++ b/leptonica/prog/bois-4.tif diff --git a/leptonica/prog/bois-5.tif b/leptonica/prog/bois-5.tif Binary files differnew file mode 100644 index 00000000..b6314233 --- /dev/null +++ b/leptonica/prog/bois-5.tif diff --git a/leptonica/prog/books_logo.png b/leptonica/prog/books_logo.png Binary files differnew file mode 100644 index 00000000..92f901d9 --- /dev/null +++ b/leptonica/prog/books_logo.png diff --git a/leptonica/prog/boxa1.ba b/leptonica/prog/boxa1.ba new file mode 100644 index 00000000..d87b6b07 --- /dev/null +++ b/leptonica/prog/boxa1.ba @@ -0,0 +1,47 @@ + +Boxa Version 2 +Number of boxes = 44 + Box[0]: x = 282, y = 0, w = 1832, h = 2697 + Box[1]: x = 479, y = 410, w = 1862, h = 2322 + Box[2]: x = 216, y = 0, w = 1746, h = 2732 + Box[3]: x = 514, y = 409, w = 1711, h = 2248 + Box[4]: x = 204, y = 0, w = 1769, h = 2732 + Box[5]: x = 508, y = 409, w = 1752, h = 2248 + Box[6]: x = 199, y = 0, w = 1769, h = 2721 + Box[7]: x = 508, y = 409, w = 1728, h = 2248 + Box[8]: x = 210, y = 0, w = 1757, h = 2721 + Box[9]: x = 496, y = 409, w = 1734, h = 2248 + Box[10]: x = 216, y = 0, w = 1752, h = 2721 + Box[11]: x = 502, y = 409, w = 1762, h = 2248 + Box[12]: x = 193, y = 0, w = 1781, h = 2727 + Box[13]: x = 502, y = 409, w = 1763, h = 2248 + Box[14]: x = 204, y = 0, w = 1763, h = 2721 + Box[15]: x = 502, y = 409, w = 1766, h = 2236 + Box[16]: x = 187, y = 0, w = 1827, h = 2721 + Box[17]: x = 508, y = 409, w = 1762, h = 2236 + Box[18]: x = 199, y = 0, w = 1775, h = 2715 + Box[19]: x = 508, y = 409, w = 1763, h = 2248 + Box[20]: x = 187, y = 0, w = 1833, h = 2337 + Box[21]: x = 473, y = 18, w = 1792, h = 2341 + Box[22]: x = 239, y = 0, w = 1775, h = 2337 + Box[23]: x = 473, y = 18, w = 1792, h = 2347 + Box[24]: x = 245, y = 0, w = 1775, h = 2343 + Box[25]: x = 473, y = 23, w = 1792, h = 2347 + Box[26]: x = 234, y = 0, w = 1781, h = 2325 + Box[27]: x = 473, y = 18, w = 1792, h = 2353 + Box[28]: x = 234, y = 0, w = 1781, h = 2721 + Box[29]: x = 496, y = 397, w = 1798, h = 2265 + Box[30]: x = 216, y = 0, w = 1746, h = 2721 + Box[31]: x = 496, y = 397, w = 1798, h = 2265 + Box[32]: x = 216, y = 0, w = 1746, h = 2709 + Box[33]: x = 485, y = 397, w = 1810, h = 2265 + Box[34]: x = 228, y = 0, w = 1734, h = 2703 + Box[35]: x = 490, y = 397, w = 1792, h = 2248 + Box[36]: x = 234, y = 0, w = 1746, h = 2639 + Box[37]: x = 479, y = 347, w = 1806, h = 2403 + Box[38]: x = 234, y = 0, w = 1746, h = 2639 + Box[39]: x = 485, y = 340, w = 1801, h = 2404 + Box[40]: x = 234, y = 0, w = 1746, h = 2639 + Box[41]: x = 479, y = 343, w = 1808, h = 2407 + Box[42]: x = 234, y = 0, w = 1746, h = 2651 + Box[43]: x = 479, y = 336, w = 1810, h = 2408 diff --git a/leptonica/prog/boxa1_reg.c b/leptonica/prog/boxa1_reg.c new file mode 100644 index 00000000..6f29badb --- /dev/null +++ b/leptonica/prog/boxa1_reg.c @@ -0,0 +1,161 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * boxa1_reg.c + * + * This carries out various operations on boxa, including + * region comparison, transforms and display. + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + +static PIX *DisplayBoxa(BOXA *boxa); + +int main(int argc, + char **argv) +{ +l_uint8 *data1, *data2; +l_int32 same; +size_t size1, size2; +l_float32 diffarea, diffxor; +BOX *box; +BOXA *boxa1, *boxa2, *boxa3; +PIX *pix1; +PTA *pta; +L_REGPARAMS *rp; + + if (regTestSetup(argc, argv, &rp)) + return 1; + + lept_mkdir("lept/boxa"); + + /* Make a boxa and display its contents */ + boxa1 = boxaCreate(6); + box = boxCreate(60, 60, 40, 20); + boxaAddBox(boxa1, box, L_INSERT); + box = boxCreate(120, 50, 20, 50); + boxaAddBox(boxa1, box, L_INSERT); + box = boxCreate(50, 140, 46, 60); + boxaAddBox(boxa1, box, L_INSERT); + box = boxCreate(166, 130, 64, 28); + boxaAddBox(boxa1, box, L_INSERT); + box = boxCreate(64, 224, 44, 34); + boxaAddBox(boxa1, box, L_INSERT); + box = boxCreate(117, 206, 26, 74); + boxaAddBox(boxa1, box, L_INSERT); + pix1 = DisplayBoxa(boxa1); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 0 */ + pixDisplayWithTitle(pix1, 0, 0, NULL, rp->display); + pixDestroy(&pix1); + + boxaCompareRegions(boxa1, boxa1, 100, &same, &diffarea, &diffxor, NULL); + regTestCompareValues(rp, 1, same, 0.0); /* 1 */ + regTestCompareValues(rp, 0.0, diffarea, 0.0); /* 2 */ + regTestCompareValues(rp, 0.0, diffxor, 0.0); /* 3 */ + + boxa2 = boxaTransform(boxa1, -13, -13, 1.0, 1.0); + boxaCompareRegions(boxa1, boxa2, 10, &same, &diffarea, &diffxor, NULL); + regTestCompareValues(rp, 1, same, 0.0); /* 4 */ + regTestCompareValues(rp, 0.0, diffarea, 0.0); /* 5 */ + regTestCompareValues(rp, 0.0, diffxor, 0.0); /* 6 */ + boxaDestroy(&boxa2); + + pta = boxaExtractCorners(boxa1, L_UPPER_LEFT); + boxa2 = boxaShiftWithPta(boxa1, pta, 1); /* shift */ + boxa3 = boxaShiftWithPta(boxa2, pta, -1); /* inverse shift */ + boxaWriteMem(&data1, &size1, boxa1); + boxaWriteMem(&data2, &size2, boxa3); + regTestCompareStrings(rp, data1, size1, data2, size2); /* 7 */ + ptaDestroy(&pta); + boxaDestroy(&boxa2); + boxaDestroy(&boxa3); + lept_free(data1); + lept_free(data2); + + boxa2 = boxaReconcileEvenOddHeight(boxa1, L_ADJUST_TOP_AND_BOT, 6, + L_ADJUST_CHOOSE_MIN, 1.0, 0); + pix1 = DisplayBoxa(boxa2); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 8 */ + pixDisplayWithTitle(pix1, 200, 0, NULL, rp->display); + pixDestroy(&pix1); + + boxaCompareRegions(boxa1, boxa2, 10, &same, &diffarea, &diffxor, &pix1); + regTestCompareValues(rp, 1, same, 0.0); /* 9 */ + regTestCompareValues(rp, 0.053, diffarea, 0.002); /* 10 */ + regTestCompareValues(rp, 0.240, diffxor, 0.002); /* 11 */ + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 12 */ + pixDisplayWithTitle(pix1, 400, 0, NULL, rp->display); + pixDestroy(&pix1); + boxaDestroy(&boxa1); + boxaDestroy(&boxa2); + + /* Test serialized boxa I/O to and from memory */ + data1 = l_binaryRead("boxa2.ba", &size1); + boxa1 = boxaReadMem(data1, size1); + boxaWriteMem(&data2, &size2, boxa1); + boxa2 = boxaReadMem(data2, size2); + boxaWrite("/tmp/lept/boxa/boxa1.ba", boxa1); + boxaWrite("/tmp/lept/boxa/boxa2.ba", boxa2); + filesAreIdentical("/tmp/lept/boxa/boxa1.ba", "/tmp/lept/boxa/boxa2.ba", + &same); + regTestCompareValues(rp, 1, same, 0.0); /* 13 */ + boxaDestroy(&boxa1); + boxaDestroy(&boxa2); + lept_free(data1); + lept_free(data2); + + return regTestCleanup(rp); +} + + +static PIX * +DisplayBoxa(BOXA *boxa) +{ +l_int32 w, h; +BOX *box; +PIX *pix1, *pix2, *pix3; +PIXA *pixa; + + pixa = pixaCreate(2); + boxaGetExtent(boxa, &w, &h, &box); + pix1 = pixCreate(w, h, 1); + pixMaskBoxa(pix1, pix1, boxa, L_SET_PIXELS); + pixaAddPix(pixa, pix1, L_INSERT); + pix2 = pixCreate(w, h, 32); + pixSetAll(pix2); + pixRenderBoxaArb(pix2, boxa, 2, 0, 255, 0); + pixRenderBoxArb(pix2, box, 3, 255, 0, 0); + pixaAddPix(pixa, pix2, L_INSERT); + pix3 = pixaDisplayTiledInRows(pixa, 32, 1000, 1.0, 0, 30, 2); + boxDestroy(&box); + pixaDestroy(&pixa); + return pix3; +} diff --git a/leptonica/prog/boxa2.ba b/leptonica/prog/boxa2.ba new file mode 100644 index 00000000..ed7dcf13 --- /dev/null +++ b/leptonica/prog/boxa2.ba @@ -0,0 +1,379 @@ + +Boxa Version 2 +Number of boxes = 376 + Box[0]: x = 0, y = 0, w = 0, h = 0 + Box[1]: x = 0, y = 0, w = 0, h = 0 + Box[2]: x = 0, y = 0, w = 0, h = 0 + Box[3]: x = 0, y = 0, w = 0, h = 0 + Box[4]: x = 0, y = 0, w = 0, h = 0 + Box[5]: x = 0, y = 0, w = 0, h = 0 + Box[6]: x = 1070, y = 128, w = 1617, h = 4049 + Box[7]: x = 250, y = 175, w = 2531, h = 3793 + Box[8]: x = 355, y = 134, w = 2374, h = 4043 + Box[9]: x = 209, y = 105, w = 2263, h = 3753 + Box[10]: x = 465, y = 140, w = 2257, h = 4043 + Box[11]: x = 268, y = 105, w = 2222, h = 3747 + Box[12]: x = 465, y = 134, w = 2234, h = 4043 + Box[13]: x = 244, y = 111, w = 2246, h = 3741 + Box[14]: x = 465, y = 128, w = 2257, h = 4049 + Box[15]: x = 279, y = 966, w = 1740, h = 1984 + Box[16]: x = 919, y = 943, w = 1815, h = 2025 + Box[17]: x = 337, y = 134, w = 2106, h = 3113 + Box[18]: x = 535, y = 122, w = 2170, h = 3130 + Box[19]: x = 227, y = 134, w = 2217, h = 3124 + Box[20]: x = 448, y = 116, w = 2263, h = 3142 + Box[21]: x = 239, y = 128, w = 2217, h = 3130 + Box[22]: x = 524, y = 70, w = 2188, h = 3142 + Box[23]: x = 239, y = 128, w = 2205, h = 3130 + Box[24]: x = 495, y = 128, w = 2217, h = 3142 + Box[25]: x = 227, y = 116, w = 2217, h = 3130 + Box[26]: x = 495, y = 134, w = 2217, h = 3142 + Box[27]: x = 209, y = 116, w = 2234, h = 3130 + Box[28]: x = 477, y = 99, w = 2228, h = 3118 + Box[29]: x = 227, y = 122, w = 2222, h = 3130 + Box[30]: x = 477, y = 134, w = 2298, h = 3153 + Box[31]: x = 233, y = 116, w = 2211, h = 3124 + Box[32]: x = 460, y = 76, w = 2246, h = 3153 + Box[33]: x = 233, y = 122, w = 2222, h = 3130 + Box[34]: x = 460, y = 140, w = 2321, h = 3147 + Box[35]: x = 233, y = 111, w = 2217, h = 3130 + Box[36]: x = 460, y = 134, w = 2321, h = 3153 + Box[37]: x = 221, y = 128, w = 2240, h = 3130 + Box[38]: x = 471, y = 145, w = 2298, h = 3159 + Box[39]: x = 239, y = 111, w = 2240, h = 3130 + Box[40]: x = 465, y = 70, w = 2327, h = 3159 + Box[41]: x = 233, y = 204, w = 2257, h = 3049 + Box[42]: x = 465, y = 41, w = 2327, h = 3188 + Box[43]: x = 239, y = 157, w = 2252, h = 3095 + Box[44]: x = 460, y = 93, w = 2327, h = 3142 + Box[45]: x = 471, y = 157, w = 2019, h = 3107 + Box[46]: x = 465, y = 111, w = 2327, h = 3118 + Box[47]: x = 233, y = 140, w = 2257, h = 3107 + Box[48]: x = 460, y = 99, w = 2333, h = 3101 + Box[49]: x = 233, y = 128, w = 2252, h = 3113 + Box[50]: x = 140, y = 58, w = 2641, h = 4020 + Box[51]: x = 239, y = 134, w = 2246, h = 3107 + Box[52]: x = 0, y = 58, w = 2781, h = 4078 + Box[53]: x = 227, y = 128, w = 2257, h = 3113 + Box[54]: x = 465, y = 111, w = 2327, h = 3136 + Box[55]: x = 227, y = 111, w = 2263, h = 3118 + Box[56]: x = 489, y = 111, w = 2304, h = 3130 + Box[57]: x = 227, y = 116, w = 2257, h = 3118 + Box[58]: x = 500, y = 105, w = 2292, h = 3136 + Box[59]: x = 227, y = 111, w = 2257, h = 3118 + Box[60]: x = 495, y = 145, w = 2281, h = 3159 + Box[61]: x = 390, y = 105, w = 2100, h = 3107 + Box[62]: x = 483, y = 140, w = 2286, h = 3165 + Box[63]: x = 582, y = 105, w = 1914, h = 3101 + Box[64]: x = 460, y = 105, w = 2333, h = 3142 + Box[65]: x = 268, y = 0, w = 2508, h = 3974 + Box[66]: x = 448, y = 0, w = 2339, h = 4177 + Box[67]: x = 256, y = 0, w = 2525, h = 3863 + Box[68]: x = 448, y = 0, w = 2333, h = 4177 + Box[69]: x = 273, y = 0, w = 2508, h = 3863 + Box[70]: x = 442, y = 0, w = 2316, h = 4177 + Box[71]: x = 367, y = 0, w = 2414, h = 3863 + Box[72]: x = 442, y = 0, w = 2339, h = 4177 + Box[73]: x = 285, y = 0, w = 2496, h = 3869 + Box[74]: x = 442, y = 0, w = 2316, h = 4177 + Box[75]: x = 367, y = 0, w = 2409, h = 3869 + Box[76]: x = 442, y = 0, w = 2327, h = 4177 + Box[77]: x = 273, y = 0, w = 2246, h = 3869 + Box[78]: x = 442, y = 0, w = 2339, h = 4177 + Box[79]: x = 378, y = 0, w = 2397, h = 3869 + Box[80]: x = 442, y = 0, w = 2339, h = 4177 + Box[81]: x = 367, y = 0, w = 2409, h = 3863 + Box[82]: x = 442, y = 0, w = 2339, h = 4177 + Box[83]: x = 268, y = 0, w = 2257, h = 3869 + Box[84]: x = 442, y = 0, w = 2316, h = 4177 + Box[85]: x = 372, y = 0, w = 2403, h = 3869 + Box[86]: x = 442, y = 0, w = 2350, h = 4177 + Box[87]: x = 291, y = 0, w = 2484, h = 3869 + Box[88]: x = 442, y = 0, w = 2345, h = 4177 + Box[89]: x = 413, y = 0, w = 2362, h = 3869 + Box[90]: x = 442, y = 0, w = 2345, h = 4177 + Box[91]: x = 419, y = 0, w = 2356, h = 3869 + Box[92]: x = 442, y = 0, w = 2327, h = 4177 + Box[93]: x = 367, y = 0, w = 2158, h = 3875 + Box[94]: x = 442, y = 0, w = 2345, h = 4177 + Box[95]: x = 262, y = 0, w = 2263, h = 3881 + Box[96]: x = 448, y = 0, w = 2350, h = 4177 + Box[97]: x = 384, y = 0, w = 2019, h = 3875 + Box[98]: x = 483, y = 0, w = 2316, h = 4177 + Box[99]: x = 384, y = 0, w = 2025, h = 3886 + Box[100]: x = 483, y = 0, w = 2316, h = 4177 + Box[101]: x = 303, y = 0, w = 2118, h = 3875 + Box[102]: x = 442, y = 0, w = 2356, h = 4177 + Box[103]: x = 378, y = 0, w = 2013, h = 3863 + Box[104]: x = 687, y = 0, w = 2118, h = 4177 + Box[105]: x = 303, y = 0, w = 2083, h = 3875 + Box[106]: x = 442, y = 0, w = 2362, h = 4177 + Box[107]: x = 390, y = 0, w = 1949, h = 3886 + Box[108]: x = 442, y = 0, w = 2356, h = 4177 + Box[109]: x = 250, y = 151, w = 1745, h = 2321 + Box[110]: x = 1390, y = 140, w = 1460, h = 2356 + Box[111]: x = 384, y = 157, w = 1606, h = 2327 + Box[112]: x = 1385, y = 227, w = 1484, h = 2339 + Box[113]: x = 349, y = 12, w = 1728, h = 3979 + Box[114]: x = 1338, y = 209, w = 1484, h = 2339 + Box[115]: x = 314, y = 6, w = 1728, h = 3979 + Box[116]: x = 1338, y = 215, w = 1478, h = 2333 + Box[117]: x = 314, y = 6, w = 1699, h = 3979 + Box[118]: x = 1344, y = 215, w = 1484, h = 2333 + Box[119]: x = 314, y = 0, w = 1693, h = 3985 + Box[120]: x = 1350, y = 209, w = 1478, h = 2345 + Box[121]: x = 314, y = 6, w = 1693, h = 3985 + Box[122]: x = 1350, y = 209, w = 1478, h = 2345 + Box[123]: x = 314, y = 0, w = 1652, h = 3979 + Box[124]: x = 1344, y = 198, w = 1484, h = 2356 + Box[125]: x = 314, y = 0, w = 1693, h = 3974 + Box[126]: x = 1350, y = 198, w = 1489, h = 2339 + Box[127]: x = 314, y = 0, w = 1646, h = 3974 + Box[128]: x = 1332, y = 163, w = 1536, h = 2356 + Box[129]: x = 413, y = 122, w = 1548, h = 2339 + Box[130]: x = 1338, y = 169, w = 1536, h = 2345 + Box[131]: x = 320, y = 0, w = 1641, h = 3974 + Box[132]: x = 1338, y = 169, w = 1495, h = 2350 + Box[133]: x = 314, y = 0, w = 1693, h = 3985 + Box[134]: x = 1344, y = 163, w = 1495, h = 2356 + Box[135]: x = 349, y = 111, w = 1635, h = 2327 + Box[136]: x = 1332, y = 163, w = 1501, h = 2356 + Box[137]: x = 308, y = 0, w = 1699, h = 3979 + Box[138]: x = 1344, y = 175, w = 1478, h = 2345 + Box[139]: x = 465, y = 105, w = 1518, h = 2316 + Box[140]: x = 1332, y = 163, w = 1484, h = 2362 + Box[141]: x = 489, y = 111, w = 1530, h = 3869 + Box[142]: x = 1332, y = 169, w = 1495, h = 2356 + Box[143]: x = 465, y = 105, w = 1518, h = 2327 + Box[144]: x = 1332, y = 169, w = 1484, h = 2356 + Box[145]: x = 297, y = 87, w = 1687, h = 2316 + Box[146]: x = 1332, y = 169, w = 1478, h = 2356 + Box[147]: x = 471, y = 70, w = 1513, h = 2321 + Box[148]: x = 1332, y = 169, w = 1484, h = 2356 + Box[149]: x = 471, y = 52, w = 1518, h = 2310 + Box[150]: x = 1344, y = 134, w = 1472, h = 2391 + Box[151]: x = 500, y = 122, w = 1484, h = 2316 + Box[152]: x = 1332, y = 163, w = 1484, h = 2362 + Box[153]: x = 471, y = 122, w = 1513, h = 2316 + Box[154]: x = 1338, y = 157, w = 1513, h = 2374 + Box[155]: x = 471, y = 128, w = 1513, h = 2321 + Box[156]: x = 1332, y = 163, w = 1489, h = 2368 + Box[157]: x = 524, y = 128, w = 1454, h = 2316 + Box[158]: x = 1338, y = 163, w = 1530, h = 2368 + Box[159]: x = 372, y = 128, w = 1612, h = 2316 + Box[160]: x = 1332, y = 169, w = 1536, h = 2362 + Box[161]: x = 343, y = 128, w = 1641, h = 2316 + Box[162]: x = 1326, y = 134, w = 1530, h = 2397 + Box[163]: x = 320, y = 140, w = 1670, h = 2310 + Box[164]: x = 1332, y = 163, w = 1472, h = 2374 + Box[165]: x = 372, y = 128, w = 1612, h = 2316 + Box[166]: x = 1332, y = 163, w = 1530, h = 2368 + Box[167]: x = 367, y = 128, w = 1617, h = 2310 + Box[168]: x = 1326, y = 163, w = 1536, h = 2368 + Box[169]: x = 471, y = 128, w = 1513, h = 2316 + Box[170]: x = 1332, y = 163, w = 1536, h = 2374 + Box[171]: x = 471, y = 134, w = 1513, h = 2316 + Box[172]: x = 1332, y = 163, w = 1530, h = 2374 + Box[173]: x = 471, y = 134, w = 1513, h = 2316 + Box[174]: x = 1326, y = 163, w = 1478, h = 2374 + Box[175]: x = 471, y = 151, w = 1513, h = 2310 + Box[176]: x = 1367, y = 157, w = 1495, h = 2385 + Box[177]: x = 477, y = 134, w = 1501, h = 2316 + Box[178]: x = 1338, y = 157, w = 1530, h = 2380 + Box[179]: x = 471, y = 134, w = 1507, h = 2316 + Box[180]: x = 1344, y = 157, w = 1518, h = 2380 + Box[181]: x = 471, y = 134, w = 1513, h = 2316 + Box[182]: x = 1338, y = 175, w = 1524, h = 2374 + Box[183]: x = 367, y = 0, w = 1658, h = 3991 + Box[184]: x = 1373, y = 175, w = 1501, h = 2374 + Box[185]: x = 390, y = 0, w = 1623, h = 3991 + Box[186]: x = 1344, y = 145, w = 1530, h = 2380 + Box[187]: x = 372, y = 169, w = 1617, h = 2321 + Box[188]: x = 1367, y = 163, w = 1507, h = 2374 + Box[189]: x = 372, y = 157, w = 1612, h = 2339 + Box[190]: x = 1344, y = 157, w = 1530, h = 2380 + Box[191]: x = 372, y = 169, w = 1612, h = 2327 + Box[192]: x = 1344, y = 163, w = 1530, h = 2380 + Box[193]: x = 372, y = 169, w = 1612, h = 2321 + Box[194]: x = 1350, y = 163, w = 1530, h = 2374 + Box[195]: x = 367, y = 157, w = 1617, h = 2327 + Box[196]: x = 1344, y = 163, w = 1530, h = 2374 + Box[197]: x = 361, y = 6, w = 1600, h = 3985 + Box[198]: x = 1367, y = 151, w = 1507, h = 2380 + Box[199]: x = 372, y = 175, w = 1617, h = 2321 + Box[200]: x = 1344, y = 157, w = 1530, h = 2380 + Box[201]: x = 343, y = 169, w = 1641, h = 2321 + Box[202]: x = 1385, y = 186, w = 1891, h = 2345 + Box[203]: x = 303, y = 175, w = 1681, h = 2321 + Box[204]: x = 1367, y = 128, w = 1449, h = 2409 + Box[205]: x = 367, y = 163, w = 1600, h = 2333 + Box[206]: x = 1356, y = 128, w = 1518, h = 2409 + Box[207]: x = 367, y = 163, w = 1617, h = 2333 + Box[208]: x = 1350, y = 169, w = 1926, h = 2368 + Box[209]: x = 372, y = 169, w = 1617, h = 2321 + Box[210]: x = 1332, y = 128, w = 1524, h = 2409 + Box[211]: x = 308, y = 180, w = 1687, h = 2321 + Box[212]: x = 1350, y = 140, w = 1449, h = 2397 + Box[213]: x = 372, y = 175, w = 1617, h = 2321 + Box[214]: x = 1326, y = 163, w = 1536, h = 2385 + Box[215]: x = 372, y = 163, w = 1617, h = 2333 + Box[216]: x = 1332, y = 134, w = 1472, h = 2397 + Box[217]: x = 372, y = 175, w = 1617, h = 2327 + Box[218]: x = 1350, y = 151, w = 1454, h = 2391 + Box[219]: x = 308, y = 163, w = 1681, h = 2327 + Box[220]: x = 1396, y = 128, w = 1414, h = 2414 + Box[221]: x = 343, y = 163, w = 1623, h = 2333 + Box[222]: x = 1356, y = 180, w = 1902, h = 2362 + Box[223]: x = 367, y = 169, w = 1617, h = 2327 + Box[224]: x = 1379, y = 128, w = 1484, h = 2414 + Box[225]: x = 343, y = 163, w = 1635, h = 2327 + Box[226]: x = 1420, y = 128, w = 1484, h = 2409 + Box[227]: x = 303, y = 163, w = 1676, h = 2327 + Box[228]: x = 1367, y = 128, w = 1443, h = 2414 + Box[229]: x = 378, y = 6, w = 1582, h = 3991 + Box[230]: x = 1350, y = 134, w = 1454, h = 2409 + Box[231]: x = 308, y = 169, w = 1681, h = 2321 + Box[232]: x = 1332, y = 122, w = 1518, h = 2403 + Box[233]: x = 407, y = 175, w = 1588, h = 2327 + Box[234]: x = 1361, y = 128, w = 1443, h = 2403 + Box[235]: x = 349, y = 175, w = 1646, h = 2327 + Box[236]: x = 1338, y = 122, w = 1466, h = 2409 + Box[237]: x = 320, y = 163, w = 1670, h = 2339 + Box[238]: x = 1373, y = 192, w = 1425, h = 2397 + Box[239]: x = 337, y = 180, w = 1658, h = 2321 + Box[240]: x = 1379, y = 204, w = 1484, h = 2403 + Box[241]: x = 361, y = 163, w = 1606, h = 2339 + Box[242]: x = 1326, y = 215, w = 1530, h = 2391 + Box[243]: x = 465, y = 122, w = 1501, h = 2356 + Box[244]: x = 1326, y = 186, w = 1472, h = 2414 + Box[245]: x = 367, y = 140, w = 1623, h = 2339 + Box[246]: x = 1326, y = 186, w = 1513, h = 2414 + Box[247]: x = 477, y = 122, w = 1513, h = 2345 + Box[248]: x = 1350, y = 186, w = 1518, h = 2420 + Box[249]: x = 477, y = 111, w = 1507, h = 2345 + Box[250]: x = 1326, y = 209, w = 1524, h = 2391 + Box[251]: x = 332, y = 111, w = 1652, h = 2350 + Box[252]: x = 1373, y = 186, w = 1431, h = 2409 + Box[253]: x = 320, y = 105, w = 1664, h = 2380 + Box[254]: x = 1350, y = 186, w = 1553, h = 2414 + Box[255]: x = 471, y = 116, w = 1518, h = 2339 + Box[256]: x = 1367, y = 186, w = 1437, h = 2409 + Box[257]: x = 326, y = 134, w = 1664, h = 2339 + Box[258]: x = 1356, y = 186, w = 1507, h = 2409 + Box[259]: x = 326, y = 128, w = 1664, h = 2362 + Box[260]: x = 1332, y = 186, w = 1577, h = 2414 + Box[261]: x = 326, y = 128, w = 1664, h = 2362 + Box[262]: x = 1361, y = 186, w = 1553, h = 2420 + Box[263]: x = 332, y = 122, w = 1652, h = 2362 + Box[264]: x = 1338, y = 180, w = 1524, h = 2420 + Box[265]: x = 332, y = 116, w = 1652, h = 2362 + Box[266]: x = 1338, y = 186, w = 1518, h = 2420 + Box[267]: x = 332, y = 111, w = 1658, h = 2345 + Box[268]: x = 1321, y = 186, w = 1588, h = 2414 + Box[269]: x = 337, y = 105, w = 1646, h = 2368 + Box[270]: x = 1379, y = 180, w = 1484, h = 2420 + Box[271]: x = 332, y = 116, w = 1652, h = 2333 + Box[272]: x = 1292, y = 198, w = 1612, h = 3974 + Box[273]: x = 337, y = 99, w = 1646, h = 2374 + Box[274]: x = 1414, y = 180, w = 1449, h = 2414 + Box[275]: x = 337, y = 116, w = 1652, h = 2345 + Box[276]: x = 1292, y = 198, w = 1617, h = 3974 + Box[277]: x = 361, y = 122, w = 1629, h = 2339 + Box[278]: x = 1373, y = 180, w = 1484, h = 2414 + Box[279]: x = 361, y = 99, w = 1629, h = 2356 + Box[280]: x = 1292, y = 198, w = 1629, h = 3974 + Box[281]: x = 343, y = 116, w = 1641, h = 2310 + Box[282]: x = 1443, y = 175, w = 1466, h = 2426 + Box[283]: x = 367, y = 111, w = 1623, h = 2339 + Box[284]: x = 1373, y = 180, w = 1489, h = 2426 + Box[285]: x = 390, y = 111, w = 1600, h = 2333 + Box[286]: x = 1454, y = 175, w = 1402, h = 2426 + Box[287]: x = 390, y = 105, w = 1600, h = 2333 + Box[288]: x = 1420, y = 186, w = 1443, h = 2420 + Box[289]: x = 390, y = 111, w = 1600, h = 2339 + Box[290]: x = 1408, y = 180, w = 1454, h = 2426 + Box[291]: x = 372, y = 105, w = 1612, h = 2345 + Box[292]: x = 1437, y = 175, w = 1501, h = 2426 + Box[293]: x = 361, y = 105, w = 1629, h = 2345 + Box[294]: x = 1356, y = 175, w = 1501, h = 2432 + Box[295]: x = 390, y = 105, w = 1594, h = 2339 + Box[296]: x = 1385, y = 175, w = 1466, h = 2432 + Box[297]: x = 355, y = 99, w = 1635, h = 2339 + Box[298]: x = 1443, y = 175, w = 1420, h = 2420 + Box[299]: x = 367, y = 105, w = 1623, h = 2327 + Box[300]: x = 1408, y = 175, w = 1507, h = 2420 + Box[301]: x = 390, y = 105, w = 1600, h = 2327 + Box[302]: x = 1443, y = 175, w = 1507, h = 2432 + Box[303]: x = 401, y = 99, w = 1588, h = 2327 + Box[304]: x = 1292, y = 198, w = 1641, h = 3968 + Box[305]: x = 401, y = 93, w = 1582, h = 2321 + Box[306]: x = 1286, y = 192, w = 1646, h = 3974 + Box[307]: x = 384, y = 93, w = 1600, h = 2327 + Box[308]: x = 1286, y = 198, w = 1641, h = 3968 + Box[309]: x = 401, y = 93, w = 1588, h = 2316 + Box[310]: x = 1379, y = 169, w = 1524, h = 2438 + Box[311]: x = 390, y = 93, w = 1600, h = 2339 + Box[312]: x = 1292, y = 192, w = 1641, h = 3974 + Box[313]: x = 367, y = 93, w = 1617, h = 2321 + Box[314]: x = 1449, y = 163, w = 1414, h = 2438 + Box[315]: x = 367, y = 93, w = 1617, h = 2333 + Box[316]: x = 1396, y = 175, w = 1513, h = 2444 + Box[317]: x = 384, y = 99, w = 1606, h = 2321 + Box[318]: x = 1425, y = 175, w = 1437, h = 2438 + Box[319]: x = 326, y = 122, w = 1658, h = 2333 + Box[320]: x = 1390, y = 192, w = 1466, h = 2420 + Box[321]: x = 384, y = 128, w = 1600, h = 2327 + Box[322]: x = 1286, y = 192, w = 1658, h = 3974 + Box[323]: x = 425, y = 122, w = 1559, h = 2333 + Box[324]: x = 1420, y = 180, w = 1437, h = 2432 + Box[325]: x = 431, y = 122, w = 1553, h = 2333 + Box[326]: x = 1425, y = 180, w = 1437, h = 2432 + Box[327]: x = 431, y = 122, w = 1553, h = 2327 + Box[328]: x = 1286, y = 192, w = 1606, h = 3968 + Box[329]: x = 407, y = 111, w = 1577, h = 2339 + Box[330]: x = 1466, y = 180, w = 1484, h = 2438 + Box[331]: x = 407, y = 122, w = 1571, h = 2339 + Box[332]: x = 1437, y = 180, w = 1460, h = 2444 + Box[333]: x = 349, y = 122, w = 1635, h = 2339 + Box[334]: x = 1332, y = 215, w = 1559, h = 2414 + Box[335]: x = 390, y = 116, w = 1588, h = 2339 + Box[336]: x = 1402, y = 198, w = 1495, h = 2432 + Box[337]: x = 506, y = 116, w = 1472, h = 2339 + Box[338]: x = 1437, y = 175, w = 1414, h = 2455 + Box[339]: x = 448, y = 116, w = 1530, h = 2339 + Box[340]: x = 1460, y = 180, w = 1408, h = 2455 + Box[341]: x = 454, y = 116, w = 1524, h = 2345 + Box[342]: x = 1472, y = 192, w = 1379, h = 2438 + Box[343]: x = 448, y = 157, w = 1530, h = 2345 + Box[344]: x = 1507, y = 180, w = 1356, h = 2449 + Box[345]: x = 419, y = 93, w = 1553, h = 2339 + Box[346]: x = 1472, y = 169, w = 1472, h = 2461 + Box[347]: x = 396, y = 93, w = 1582, h = 2333 + Box[348]: x = 1443, y = 192, w = 1507, h = 2438 + Box[349]: x = 431, y = 99, w = 1548, h = 2327 + Box[350]: x = 1449, y = 169, w = 1536, h = 2461 + Box[351]: x = 465, y = 93, w = 1513, h = 2327 + Box[352]: x = 1449, y = 169, w = 1530, h = 2467 + Box[353]: x = 454, y = 76, w = 1518, h = 2333 + Box[354]: x = 1286, y = 105, w = 1606, h = 4049 + Box[355]: x = 460, y = 76, w = 1518, h = 2333 + Box[356]: x = 1460, y = 186, w = 1524, h = 2444 + Box[357]: x = 465, y = 76, w = 1513, h = 2327 + Box[358]: x = 1454, y = 169, w = 1530, h = 2438 + Box[359]: x = 460, y = 70, w = 1513, h = 2327 + Box[360]: x = 1449, y = 192, w = 1507, h = 2444 + Box[361]: x = 460, y = 58, w = 1513, h = 2333 + Box[362]: x = 1420, y = 192, w = 1553, h = 2438 + Box[363]: x = 460, y = 58, w = 1518, h = 2333 + Box[364]: x = 1466, y = 175, w = 1484, h = 2467 + Box[365]: x = 460, y = 58, w = 1513, h = 2327 + Box[366]: x = 1379, y = 204, w = 1513, h = 2432 + Box[367]: x = 460, y = 58, w = 1513, h = 2327 + Box[368]: x = 1367, y = 204, w = 1582, h = 2438 + Box[369]: x = 465, y = 47, w = 2356, h = 3962 + Box[370]: x = 640, y = 0, w = 2292, h = 3991 + Box[371]: x = 442, y = 47, w = 2380, h = 3915 + Box[372]: x = 495, y = 0, w = 2455, h = 4177 + Box[373]: x = 471, y = 140, w = 2350, h = 3881 + Box[374]: x = 0, y = 0, w = 0, h = 0 + Box[375]: x = 0, y = 0, w = 0, h = 0 diff --git a/leptonica/prog/boxa2_reg.c b/leptonica/prog/boxa2_reg.c new file mode 100644 index 00000000..55d65355 --- /dev/null +++ b/leptonica/prog/boxa2_reg.c @@ -0,0 +1,196 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * boxa2_reg.c + * + * Low-level statistical operations that can be used to identify anomalous + * sized boxes in a boxa, where the widths and heights of the boxes + * are expected to be similar. + * + * This tests a number of operations on boxes in a boxa, including + * separating them into subsets of different parity. + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + +l_int32 main(int argc, + char **argv) +{ +l_int32 i, n, val, ne, no, nbins, minw, maxw, minh, maxh; +l_int32 mine, mino, maxe, maxo; +l_int32 w_diff, h_diff, median_w_diff, median_h_diff; +l_int32 noutw, nouth; +l_float32 medwe, medhe, medwo, medho; +BOXA *boxa1, *boxa2, *boxae, *boxao; +NUMA *na1, *nawe, *nahe, *nawo, *naho; +NUMA *nadiffw, *nadiffh; /* diff from median w and h */ +NUMA *naiw, *naih; /* indicator arrays for small outlier dimensions */ +NUMA *narbwe, *narbhe, *narbwo, *narbho; /* rank-binned w and h */ +PIX *pix1; +PIXA *pixa1; +L_REGPARAMS *rp; + + if (regTestSetup(argc, argv, &rp)) + return 1; + + lept_mkdir("lept/boxa"); + boxa1 = boxaRead("boxa4.ba"); + + /* Fill invalid boxes */ + n = boxaGetCount(boxa1); + na1 = boxaFindInvalidBoxes(boxa1); + if (na1) + boxa2 = boxaFillSequence(boxa1, L_USE_SAME_PARITY_BOXES, 0); + else + boxa2 = boxaCopy(boxa1, L_CLONE); + boxaDestroy(&boxa1); + + /* Get the widths and heights for even and odd parity */ + boxaSplitEvenOdd(boxa2, 0, &boxae, &boxao); + boxaGetSizes(boxae, &nawe, &nahe); + boxaGetSizes(boxao, &nawo, &naho); + boxaDestroy(&boxa2); + + /* Find the medians */ + numaGetMedian(nawe, &medwe); + numaGetMedian(nahe, &medhe); + numaGetMedian(nawo, &medwo); + numaGetMedian(naho, &medho); + + /* Find the median even/odd differences for width and height */ + median_w_diff = L_ABS(medwe - medwo); + median_h_diff = L_ABS(medhe - medho); + regTestCompareValues(rp, 210, median_w_diff, 0.0); /* 0 */ + regTestCompareValues(rp, 15, median_h_diff, 0.0); /* 1 */ + if (rp->display) { + lept_stderr("diff of e/o median widths = %d\n", median_w_diff); + lept_stderr("diff of e/o median heights = %d\n", median_h_diff); + } + + /* Find the differences of box width and height from the median */ + nadiffw = numaMakeConstant(0, n); + nadiffh = numaMakeConstant(0, n); + ne = numaGetCount(nawe); + no = numaGetCount(nawo); + for (i = 0; i < ne; i++) { + numaGetIValue(nawe, i, &val); + numaSetValue(nadiffw, 2 * i, L_ABS(val - medwe)); + numaGetIValue(nahe, i, &val); + numaSetValue(nadiffh, 2 * i, L_ABS(val - medhe)); + } + for (i = 0; i < no; i++) { + numaGetIValue(nawo, i, &val); + numaSetValue(nadiffw, 2 * i + 1, L_ABS(val - medwo)); + numaGetIValue(naho, i, &val); + numaSetValue(nadiffh, 2 * i + 1, L_ABS(val - medho)); + } + + /* Don't count invalid boxes; set the diffs to 0 for them */ + if (na1) { + for (i = 0; i < n; i++) { + numaGetIValue(na1, i, &val); + if (val == 1) { + numaSetValue(nadiffw, i, 0); + numaSetValue(nadiffh, i, 0); + } + } + } + + /* Make an indicator array for boxes that differ from the + * median by more than a threshold value for outliers */ + naiw = numaMakeThresholdIndicator(nadiffw, 90, L_SELECT_IF_GT); + naih = numaMakeThresholdIndicator(nadiffh, 90, L_SELECT_IF_GT); + numaGetCountRelativeToZero(naiw, L_GREATER_THAN_ZERO, &noutw); + numaGetCountRelativeToZero(naih, L_GREATER_THAN_ZERO, &nouth); + regTestCompareValues(rp, 24, noutw, 0.0); /* 2 */ + regTestCompareValues(rp, 0, nouth, 0.0); /* 3 */ + if (rp->display) + lept_stderr("num width outliers = %d, num height outliers = %d\n", + noutw, nouth); + numaDestroy(&nadiffw); + numaDestroy(&nadiffh); + numaDestroy(&naiw); + numaDestroy(&naih); + + /* Find the rank bins for width and height */ + nbins = L_MAX(5, ne / 50); // up to 50 pages/bin + numaGetRankBinValues(nawe, nbins, &narbwe); + numaGetRankBinValues(nawo, nbins, &narbwo); + numaGetRankBinValues(nahe, nbins, &narbhe); + numaGetRankBinValues(naho, nbins, &narbho); + numaDestroy(&nawe); + numaDestroy(&nawo); + numaDestroy(&nahe); + numaDestroy(&naho); + + /* Find min and max binned widths and heights; get the max diffs */ + numaGetIValue(narbwe, 0, &mine); + numaGetIValue(narbwe, nbins - 1, &maxe); + numaGetIValue(narbwo, 0, &mino); + numaGetIValue(narbwo, nbins - 1, &maxo); + minw = L_MIN(mine, mino); + maxw = L_MAX(maxe, maxo); + w_diff = maxw - minw; + numaGetIValue(narbhe, 0, &mine); + numaGetIValue(narbhe, nbins - 1, &maxe); + numaGetIValue(narbho, 0, &mino); + numaGetIValue(narbho, nbins - 1, &maxo); + minh = L_MIN(mine, mino); + maxh = L_MAX(maxe, maxo); + h_diff = maxh - minh; + numaDestroy(&narbwe); + numaDestroy(&narbhe); + numaDestroy(&narbwo); + numaDestroy(&narbho); + regTestCompareValues(rp, 409, w_diff, 0.0); /* 4 */ + regTestCompareValues(rp, 54, h_diff, 0.0); /* 5 */ + if (rp->display) + lept_stderr("Binned rank results: w_diff = %d, h_diff = %d\n", + w_diff, h_diff); + + /* Plot the results */ + if (noutw > 0 || nouth > 0) { + pixa1 = pixaCreate(2); + boxaPlotSizes(boxae, "even", NULL, NULL, &pix1); + pixaAddPix(pixa1, pix1, L_INSERT); + boxaPlotSizes(boxao, "odd", NULL, NULL, &pix1); + pixaAddPix(pixa1, pix1, L_INSERT); + pix1 = pixaDisplayTiledInRows(pixa1, 32, 1500, 1.0, 0, 30, 2); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 6 */ + pixDisplayWithTitle(pix1, 100, 100, NULL, rp->display); + pixDestroy(&pix1); + pixaDestroy(&pixa1); + } + + boxaDestroy(&boxae); + boxaDestroy(&boxao); + return regTestCleanup(rp); +} diff --git a/leptonica/prog/boxa3.ba b/leptonica/prog/boxa3.ba new file mode 100644 index 00000000..eacb6a78 --- /dev/null +++ b/leptonica/prog/boxa3.ba @@ -0,0 +1,379 @@ + +Boxa Version 2 +Number of boxes = 376 + Box[0]: x = 0, y = 0, w = 0, h = 0 + Box[1]: x = 0, y = 0, w = 0, h = 0 + Box[2]: x = 0, y = 0, w = 0, h = 0 + Box[3]: x = 0, y = 0, w = 0, h = 0 + Box[4]: x = 0, y = 0, w = 0, h = 0 + Box[5]: x = 0, y = 0, w = 0, h = 0 + Box[6]: x = 524, y = 128, w = 2182, h = 4049 + Box[7]: x = 250, y = 134, w = 2313, h = 3790 + Box[8]: x = 451, y = 128, w = 2278, h = 4049 + Box[9]: x = 209, y = 105, w = 2281, h = 3753 + Box[10]: x = 465, y = 129, w = 2257, h = 4054 + Box[11]: x = 250, y = 105, w = 2240, h = 3747 + Box[12]: x = 465, y = 129, w = 2238, h = 4048 + Box[13]: x = 244, y = 111, w = 2246, h = 3741 + Box[14]: x = 465, y = 128, w = 2257, h = 4049 + Box[15]: x = 244, y = 129, w = 2211, h = 3130 + Box[16]: x = 493, y = 135, w = 2241, h = 3153 + Box[17]: x = 239, y = 129, w = 2217, h = 3130 + Box[18]: x = 476, y = 122, w = 2234, h = 3161 + Box[19]: x = 227, y = 128, w = 2228, h = 3130 + Box[20]: x = 448, y = 116, w = 2263, h = 3171 + Box[21]: x = 239, y = 128, w = 2217, h = 3130 + Box[22]: x = 470, y = 70, w = 2241, h = 3177 + Box[23]: x = 239, y = 127, w = 2217, h = 3131 + Box[24]: x = 467, y = 128, w = 2257, h = 3156 + Box[25]: x = 227, y = 116, w = 2228, h = 3136 + Box[26]: x = 467, y = 132, w = 2257, h = 3146 + Box[27]: x = 209, y = 116, w = 2246, h = 3136 + Box[28]: x = 467, y = 90, w = 2263, h = 3145 + Box[29]: x = 227, y = 122, w = 2228, h = 3130 + Box[30]: x = 467, y = 134, w = 2308, h = 3153 + Box[31]: x = 233, y = 116, w = 2222, h = 3136 + Box[32]: x = 460, y = 76, w = 2310, h = 3153 + Box[33]: x = 233, y = 122, w = 2222, h = 3130 + Box[34]: x = 460, y = 134, w = 2321, h = 3153 + Box[35]: x = 233, y = 111, w = 2222, h = 3136 + Box[36]: x = 460, y = 134, w = 2321, h = 3153 + Box[37]: x = 221, y = 128, w = 2240, h = 3130 + Box[38]: x = 464, y = 135, w = 2316, h = 3169 + Box[39]: x = 233, y = 111, w = 2246, h = 3136 + Box[40]: x = 465, y = 70, w = 2327, h = 3165 + Box[41]: x = 233, y = 122, w = 2257, h = 3130 + Box[42]: x = 465, y = 41, w = 2327, h = 3188 + Box[43]: x = 233, y = 122, w = 2257, h = 3130 + Box[44]: x = 460, y = 93, w = 2327, h = 3147 + Box[45]: x = 233, y = 116, w = 2257, h = 3147 + Box[46]: x = 465, y = 93, w = 2327, h = 3147 + Box[47]: x = 233, y = 116, w = 2257, h = 3130 + Box[48]: x = 460, y = 93, w = 2333, h = 3149 + Box[49]: x = 233, y = 116, w = 2252, h = 3124 + Box[50]: x = 388, y = 58, w = 2394, h = 3249 + Box[51]: x = 233, y = 116, w = 2257, h = 3124 + Box[52]: x = 388, y = 65, w = 2394, h = 3305 + Box[53]: x = 227, y = 111, w = 2263, h = 3136 + Box[54]: x = 461, y = 87, w = 2332, h = 3165 + Box[55]: x = 227, y = 111, w = 2263, h = 3136 + Box[56]: x = 460, y = 81, w = 2333, h = 3165 + Box[57]: x = 227, y = 111, w = 2263, h = 3142 + Box[58]: x = 461, y = 76, w = 2332, h = 3182 + Box[59]: x = 227, y = 111, w = 2263, h = 3142 + Box[60]: x = 460, y = 122, w = 2323, h = 3188 + Box[61]: x = 268, y = 105, w = 2222, h = 3146 + Box[62]: x = 448, y = 105, w = 2334, h = 4033 + Box[63]: x = 268, y = 105, w = 2228, h = 3158 + Box[64]: x = 448, y = 0, w = 2345, h = 4080 + Box[65]: x = 268, y = 0, w = 2324, h = 3936 + Box[66]: x = 442, y = 0, w = 2345, h = 4177 + Box[67]: x = 256, y = 0, w = 2342, h = 3863 + Box[68]: x = 442, y = 0, w = 2339, h = 4177 + Box[69]: x = 273, y = 0, w = 2508, h = 3863 + Box[70]: x = 442, y = 0, w = 2339, h = 4177 + Box[71]: x = 285, y = 0, w = 2496, h = 3863 + Box[72]: x = 442, y = 0, w = 2339, h = 4177 + Box[73]: x = 285, y = 0, w = 2496, h = 3869 + Box[74]: x = 442, y = 0, w = 2339, h = 4177 + Box[75]: x = 291, y = 0, w = 2484, h = 3869 + Box[76]: x = 442, y = 0, w = 2340, h = 4177 + Box[77]: x = 294, y = 0, w = 2481, h = 3869 + Box[78]: x = 442, y = 0, w = 2340, h = 4177 + Box[79]: x = 367, y = 0, w = 2409, h = 3869 + Box[80]: x = 442, y = 0, w = 2340, h = 4177 + Box[81]: x = 367, y = 0, w = 2409, h = 3869 + Box[82]: x = 442, y = 0, w = 2340, h = 4177 + Box[83]: x = 294, y = 0, w = 2481, h = 3869 + Box[84]: x = 442, y = 0, w = 2343, h = 4177 + Box[85]: x = 367, y = 0, w = 2409, h = 3869 + Box[86]: x = 442, y = 0, w = 2350, h = 4177 + Box[87]: x = 294, y = 0, w = 2481, h = 3869 + Box[88]: x = 442, y = 0, w = 2345, h = 4177 + Box[89]: x = 367, y = 0, w = 2231, h = 3869 + Box[90]: x = 442, y = 0, w = 2345, h = 4177 + Box[91]: x = 367, y = 0, w = 2231, h = 3869 + Box[92]: x = 442, y = 0, w = 2345, h = 4177 + Box[93]: x = 367, y = 0, w = 2158, h = 3875 + Box[94]: x = 442, y = 0, w = 2352, h = 4177 + Box[95]: x = 294, y = 0, w = 2231, h = 3881 + Box[96]: x = 444, y = 0, w = 2355, h = 4177 + Box[97]: x = 367, y = 0, w = 2054, h = 3875 + Box[98]: x = 444, y = 0, w = 2355, h = 4177 + Box[99]: x = 367, y = 0, w = 2042, h = 3888 + Box[100]: x = 444, y = 0, w = 2355, h = 4177 + Box[101]: x = 303, y = 0, w = 2118, h = 3876 + Box[102]: x = 442, y = 0, w = 2356, h = 4177 + Box[103]: x = 314, y = 0, w = 2077, h = 3876 + Box[104]: x = 483, y = 0, w = 2321, h = 4177 + Box[105]: x = 303, y = 0, w = 2083, h = 3876 + Box[106]: x = 442, y = 0, w = 2362, h = 4177 + Box[107]: x = 314, y = 0, w = 2025, h = 3888 + Box[108]: x = 614, y = 0, w = 2190, h = 4177 + Box[109]: x = 250, y = 7, w = 1827, h = 3881 + Box[110]: x = 1361, y = 140, w = 1489, h = 2364 + Box[111]: x = 314, y = 19, w = 1728, h = 3888 + Box[112]: x = 1379, y = 215, w = 1489, h = 2356 + Box[113]: x = 314, y = 12, w = 1763, h = 3974 + Box[114]: x = 1338, y = 198, w = 1484, h = 2356 + Box[115]: x = 314, y = 6, w = 1728, h = 3974 + Box[116]: x = 1332, y = 198, w = 1484, h = 2356 + Box[117]: x = 314, y = 6, w = 1699, h = 3979 + Box[118]: x = 1344, y = 204, w = 1484, h = 2350 + Box[119]: x = 314, y = 0, w = 1693, h = 3985 + Box[120]: x = 1344, y = 204, w = 1484, h = 2350 + Box[121]: x = 314, y = 6, w = 1693, h = 3985 + Box[122]: x = 1350, y = 204, w = 1484, h = 2350 + Box[123]: x = 314, y = 0, w = 1693, h = 3979 + Box[124]: x = 1338, y = 198, w = 1489, h = 2356 + Box[125]: x = 314, y = 0, w = 1693, h = 3974 + Box[126]: x = 1350, y = 192, w = 1489, h = 2345 + Box[127]: x = 314, y = 0, w = 1681, h = 3974 + Box[128]: x = 1332, y = 163, w = 1536, h = 2356 + Box[129]: x = 314, y = 29, w = 1676, h = 3950 + Box[130]: x = 1338, y = 169, w = 1536, h = 2345 + Box[131]: x = 320, y = 0, w = 1670, h = 3974 + Box[132]: x = 1338, y = 169, w = 1495, h = 2350 + Box[133]: x = 314, y = 0, w = 1693, h = 3985 + Box[134]: x = 1344, y = 163, w = 1495, h = 2356 + Box[135]: x = 320, y = 99, w = 1664, h = 3857 + Box[136]: x = 1332, y = 163, w = 1501, h = 2356 + Box[137]: x = 308, y = 32, w = 1699, h = 2478 + Box[138]: x = 1344, y = 163, w = 1484, h = 2356 + Box[139]: x = 372, y = 99, w = 1612, h = 2332 + Box[140]: x = 1332, y = 163, w = 1495, h = 2362 + Box[141]: x = 372, y = 97, w = 1646, h = 2396 + Box[142]: x = 1332, y = 169, w = 1495, h = 2356 + Box[143]: x = 372, y = 103, w = 1612, h = 2329 + Box[144]: x = 1332, y = 163, w = 1489, h = 2362 + Box[145]: x = 300, y = 87, w = 1684, h = 2321 + Box[146]: x = 1332, y = 163, w = 1489, h = 2362 + Box[147]: x = 372, y = 70, w = 1612, h = 2321 + Box[148]: x = 1332, y = 163, w = 1501, h = 2362 + Box[149]: x = 413, y = 52, w = 1577, h = 2326 + Box[150]: x = 1338, y = 134, w = 1495, h = 2391 + Box[151]: x = 465, y = 122, w = 1518, h = 2321 + Box[152]: x = 1332, y = 163, w = 1501, h = 2362 + Box[153]: x = 465, y = 122, w = 1518, h = 2321 + Box[154]: x = 1332, y = 157, w = 1518, h = 2374 + Box[155]: x = 471, y = 128, w = 1513, h = 2321 + Box[156]: x = 1332, y = 163, w = 1495, h = 2368 + Box[157]: x = 471, y = 128, w = 1513, h = 2316 + Box[158]: x = 1332, y = 163, w = 1536, h = 2368 + Box[159]: x = 399, y = 128, w = 1585, h = 2316 + Box[160]: x = 1332, y = 163, w = 1536, h = 2368 + Box[161]: x = 399, y = 128, w = 1585, h = 2317 + Box[162]: x = 1326, y = 134, w = 1530, h = 2397 + Box[163]: x = 399, y = 128, w = 1591, h = 2321 + Box[164]: x = 1332, y = 163, w = 1524, h = 2374 + Box[165]: x = 399, y = 128, w = 1585, h = 2317 + Box[166]: x = 1332, y = 157, w = 1530, h = 2374 + Box[167]: x = 399, y = 128, w = 1585, h = 2317 + Box[168]: x = 1326, y = 157, w = 1536, h = 2374 + Box[169]: x = 471, y = 128, w = 1513, h = 2321 + Box[170]: x = 1332, y = 163, w = 1536, h = 2374 + Box[171]: x = 471, y = 128, w = 1513, h = 2321 + Box[172]: x = 1332, y = 163, w = 1530, h = 2374 + Box[173]: x = 390, y = 127, w = 1594, h = 2323 + Box[174]: x = 1326, y = 157, w = 1530, h = 2380 + Box[175]: x = 372, y = 127, w = 1612, h = 2334 + Box[176]: x = 1332, y = 157, w = 1530, h = 2385 + Box[177]: x = 372, y = 127, w = 1612, h = 2323 + Box[178]: x = 1332, y = 157, w = 1536, h = 2380 + Box[179]: x = 372, y = 127, w = 1612, h = 2323 + Box[180]: x = 1332, y = 157, w = 1530, h = 2380 + Box[181]: x = 372, y = 127, w = 1612, h = 2323 + Box[182]: x = 1326, y = 175, w = 1536, h = 2380 + Box[183]: x = 367, y = 54, w = 1658, h = 2468 + Box[184]: x = 1350, y = 175, w = 1524, h = 2380 + Box[185]: x = 372, y = 54, w = 1641, h = 2468 + Box[186]: x = 1344, y = 145, w = 1530, h = 2397 + Box[187]: x = 372, y = 169, w = 1617, h = 2327 + Box[188]: x = 1344, y = 157, w = 1530, h = 2380 + Box[189]: x = 372, y = 157, w = 1612, h = 2339 + Box[190]: x = 1344, y = 157, w = 1530, h = 2380 + Box[191]: x = 372, y = 169, w = 1612, h = 2327 + Box[192]: x = 1344, y = 163, w = 1530, h = 2380 + Box[193]: x = 372, y = 169, w = 1612, h = 2327 + Box[194]: x = 1350, y = 157, w = 1530, h = 2380 + Box[195]: x = 367, y = 157, w = 1617, h = 2339 + Box[196]: x = 1344, y = 157, w = 1530, h = 2380 + Box[197]: x = 361, y = 96, w = 1623, h = 2473 + Box[198]: x = 1350, y = 151, w = 1524, h = 2385 + Box[199]: x = 372, y = 169, w = 1617, h = 2327 + Box[200]: x = 1344, y = 157, w = 1530, h = 2380 + Box[201]: x = 343, y = 169, w = 1641, h = 2327 + Box[202]: x = 1361, y = 157, w = 1591, h = 2380 + Box[203]: x = 303, y = 169, w = 1681, h = 2327 + Box[204]: x = 1367, y = 128, w = 1513, h = 2409 + Box[205]: x = 367, y = 163, w = 1617, h = 2333 + Box[206]: x = 1356, y = 128, w = 1518, h = 2409 + Box[207]: x = 367, y = 163, w = 1617, h = 2333 + Box[208]: x = 1350, y = 151, w = 1603, h = 2385 + Box[209]: x = 367, y = 163, w = 1623, h = 2327 + Box[210]: x = 1332, y = 128, w = 1524, h = 2409 + Box[211]: x = 308, y = 169, w = 1687, h = 2333 + Box[212]: x = 1350, y = 140, w = 1513, h = 2397 + Box[213]: x = 367, y = 169, w = 1623, h = 2327 + Box[214]: x = 1326, y = 134, w = 1536, h = 2414 + Box[215]: x = 367, y = 163, w = 1623, h = 2333 + Box[216]: x = 1332, y = 134, w = 1530, h = 2403 + Box[217]: x = 361, y = 169, w = 1629, h = 2333 + Box[218]: x = 1350, y = 134, w = 1501, h = 2409 + Box[219]: x = 308, y = 163, w = 1681, h = 2333 + Box[220]: x = 1356, y = 128, w = 1501, h = 2414 + Box[221]: x = 343, y = 163, w = 1646, h = 2333 + Box[222]: x = 1350, y = 134, w = 1574, h = 2409 + Box[223]: x = 361, y = 169, w = 1629, h = 2327 + Box[224]: x = 1350, y = 128, w = 1513, h = 2414 + Box[225]: x = 343, y = 163, w = 1646, h = 2333 + Box[226]: x = 1356, y = 128, w = 1548, h = 2414 + Box[227]: x = 303, y = 163, w = 1687, h = 2333 + Box[228]: x = 1356, y = 128, w = 1489, h = 2414 + Box[229]: x = 367, y = 90, w = 1623, h = 2473 + Box[230]: x = 1350, y = 128, w = 1489, h = 2414 + Box[231]: x = 308, y = 157, w = 1681, h = 2339 + Box[232]: x = 1332, y = 122, w = 1518, h = 2414 + Box[233]: x = 361, y = 163, w = 1635, h = 2339 + Box[234]: x = 1350, y = 122, w = 1489, h = 2414 + Box[235]: x = 349, y = 163, w = 1646, h = 2339 + Box[236]: x = 1338, y = 122, w = 1466, h = 2414 + Box[237]: x = 320, y = 163, w = 1670, h = 2339 + Box[238]: x = 1350, y = 192, w = 1489, h = 2414 + Box[239]: x = 337, y = 163, w = 1658, h = 2339 + Box[240]: x = 1356, y = 192, w = 1507, h = 2414 + Box[241]: x = 343, y = 163, w = 1646, h = 2339 + Box[242]: x = 1326, y = 186, w = 1530, h = 2420 + Box[243]: x = 343, y = 122, w = 1646, h = 2356 + Box[244]: x = 1326, y = 186, w = 1524, h = 2414 + Box[245]: x = 337, y = 140, w = 1652, h = 2339 + Box[246]: x = 1326, y = 186, w = 1524, h = 2414 + Box[247]: x = 332, y = 122, w = 1658, h = 2350 + Box[248]: x = 1350, y = 186, w = 1518, h = 2420 + Box[249]: x = 337, y = 111, w = 1652, h = 2350 + Box[250]: x = 1326, y = 186, w = 1530, h = 2414 + Box[251]: x = 332, y = 111, w = 1658, h = 2350 + Box[252]: x = 1344, y = 186, w = 1513, h = 2414 + Box[253]: x = 320, y = 105, w = 1670, h = 2380 + Box[254]: x = 1338, y = 186, w = 1565, h = 2414 + Box[255]: x = 337, y = 116, w = 1652, h = 2339 + Box[256]: x = 1344, y = 186, w = 1513, h = 2414 + Box[257]: x = 326, y = 128, w = 1664, h = 2345 + Box[258]: x = 1350, y = 186, w = 1513, h = 2414 + Box[259]: x = 326, y = 128, w = 1664, h = 2362 + Box[260]: x = 1332, y = 186, w = 1577, h = 2414 + Box[261]: x = 326, y = 128, w = 1664, h = 2362 + Box[262]: x = 1344, y = 186, w = 1571, h = 2420 + Box[263]: x = 332, y = 122, w = 1658, h = 2362 + Box[264]: x = 1338, y = 180, w = 1524, h = 2420 + Box[265]: x = 332, y = 116, w = 1658, h = 2362 + Box[266]: x = 1338, y = 186, w = 1518, h = 2420 + Box[267]: x = 332, y = 111, w = 1658, h = 2362 + Box[268]: x = 1321, y = 186, w = 1588, h = 2420 + Box[269]: x = 337, y = 105, w = 1652, h = 2368 + Box[270]: x = 1361, y = 180, w = 1501, h = 2420 + Box[271]: x = 332, y = 116, w = 1658, h = 2350 + Box[272]: x = 1300, y = 180, w = 1603, h = 2493 + Box[273]: x = 337, y = 99, w = 1652, h = 2374 + Box[274]: x = 1361, y = 180, w = 1501, h = 2420 + Box[275]: x = 337, y = 111, w = 1652, h = 2350 + Box[276]: x = 1300, y = 180, w = 1609, h = 2493 + Box[277]: x = 343, y = 111, w = 1646, h = 2350 + Box[278]: x = 1367, y = 180, w = 1489, h = 2420 + Box[279]: x = 355, y = 99, w = 1635, h = 2356 + Box[280]: x = 1306, y = 180, w = 1614, h = 2493 + Box[281]: x = 343, y = 105, w = 1646, h = 2345 + Box[282]: x = 1379, y = 175, w = 1530, h = 2426 + Box[283]: x = 361, y = 111, w = 1629, h = 2339 + Box[284]: x = 1373, y = 180, w = 1489, h = 2426 + Box[285]: x = 361, y = 105, w = 1629, h = 2339 + Box[286]: x = 1379, y = 175, w = 1484, h = 2432 + Box[287]: x = 367, y = 105, w = 1623, h = 2339 + Box[288]: x = 1379, y = 180, w = 1524, h = 2426 + Box[289]: x = 367, y = 111, w = 1623, h = 2339 + Box[290]: x = 1379, y = 175, w = 1518, h = 2432 + Box[291]: x = 372, y = 105, w = 1617, h = 2345 + Box[292]: x = 1379, y = 175, w = 1559, h = 2432 + Box[293]: x = 361, y = 105, w = 1629, h = 2345 + Box[294]: x = 1356, y = 175, w = 1536, h = 2432 + Box[295]: x = 372, y = 105, w = 1617, h = 2339 + Box[296]: x = 1385, y = 175, w = 1524, h = 2432 + Box[297]: x = 355, y = 99, w = 1635, h = 2339 + Box[298]: x = 1396, y = 175, w = 1501, h = 2432 + Box[299]: x = 367, y = 93, w = 1623, h = 2339 + Box[300]: x = 1396, y = 175, w = 1518, h = 2432 + Box[301]: x = 384, y = 93, w = 1606, h = 2339 + Box[302]: x = 1396, y = 175, w = 1553, h = 2432 + Box[303]: x = 384, y = 93, w = 1606, h = 2333 + Box[304]: x = 1329, y = 175, w = 1603, h = 2505 + Box[305]: x = 390, y = 93, w = 1600, h = 2333 + Box[306]: x = 1341, y = 175, w = 1591, h = 2510 + Box[307]: x = 384, y = 93, w = 1600, h = 2339 + Box[308]: x = 1324, y = 180, w = 1603, h = 2505 + Box[309]: x = 390, y = 93, w = 1600, h = 2327 + Box[310]: x = 1379, y = 169, w = 1524, h = 2438 + Box[311]: x = 390, y = 93, w = 1600, h = 2339 + Box[312]: x = 1329, y = 180, w = 1603, h = 2510 + Box[313]: x = 367, y = 93, w = 1617, h = 2327 + Box[314]: x = 1390, y = 163, w = 1507, h = 2449 + Box[315]: x = 367, y = 93, w = 1617, h = 2333 + Box[316]: x = 1396, y = 175, w = 1513, h = 2444 + Box[317]: x = 384, y = 87, w = 1606, h = 2333 + Box[318]: x = 1402, y = 175, w = 1495, h = 2444 + Box[319]: x = 326, y = 122, w = 1658, h = 2333 + Box[320]: x = 1390, y = 186, w = 1507, h = 2438 + Box[321]: x = 384, y = 122, w = 1600, h = 2333 + Box[322]: x = 1329, y = 186, w = 1614, h = 2516 + Box[323]: x = 401, y = 122, w = 1582, h = 2333 + Box[324]: x = 1402, y = 180, w = 1495, h = 2444 + Box[325]: x = 401, y = 122, w = 1582, h = 2333 + Box[326]: x = 1420, y = 180, w = 1478, h = 2444 + Box[327]: x = 401, y = 122, w = 1582, h = 2327 + Box[328]: x = 1353, y = 180, w = 1545, h = 2516 + Box[329]: x = 407, y = 111, w = 1577, h = 2339 + Box[330]: x = 1425, y = 180, w = 1524, h = 2449 + Box[331]: x = 407, y = 122, w = 1577, h = 2339 + Box[332]: x = 1437, y = 180, w = 1460, h = 2449 + Box[333]: x = 349, y = 122, w = 1635, h = 2339 + Box[334]: x = 1358, y = 180, w = 1533, h = 2449 + Box[335]: x = 390, y = 116, w = 1588, h = 2339 + Box[336]: x = 1402, y = 186, w = 1495, h = 2444 + Box[337]: x = 431, y = 116, w = 1548, h = 2339 + Box[338]: x = 1431, y = 175, w = 1460, h = 2455 + Box[339]: x = 431, y = 116, w = 1548, h = 2339 + Box[340]: x = 1449, y = 180, w = 1454, h = 2455 + Box[341]: x = 431, y = 116, w = 1548, h = 2345 + Box[342]: x = 1443, y = 186, w = 1454, h = 2449 + Box[343]: x = 448, y = 157, w = 1530, h = 2345 + Box[344]: x = 1449, y = 180, w = 1454, h = 2449 + Box[345]: x = 419, y = 93, w = 1559, h = 2339 + Box[346]: x = 1443, y = 169, w = 1501, h = 2461 + Box[347]: x = 396, y = 93, w = 1582, h = 2333 + Box[348]: x = 1443, y = 186, w = 1507, h = 2449 + Box[349]: x = 431, y = 93, w = 1548, h = 2333 + Box[350]: x = 1443, y = 169, w = 1542, h = 2461 + Box[351]: x = 454, y = 87, w = 1524, h = 2333 + Box[352]: x = 1443, y = 169, w = 1536, h = 2467 + Box[353]: x = 454, y = 76, w = 1524, h = 2333 + Box[354]: x = 1376, y = 105, w = 1574, h = 2598 + Box[355]: x = 460, y = 76, w = 1518, h = 2333 + Box[356]: x = 1449, y = 175, w = 1536, h = 2455 + Box[357]: x = 460, y = 70, w = 1518, h = 2333 + Box[358]: x = 1449, y = 169, w = 1536, h = 2467 + Box[359]: x = 460, y = 64, w = 1518, h = 2333 + Box[360]: x = 1443, y = 169, w = 1513, h = 2467 + Box[361]: x = 460, y = 58, w = 1518, h = 2333 + Box[362]: x = 1420, y = 169, w = 1553, h = 2467 + Box[363]: x = 460, y = 58, w = 1518, h = 2339 + Box[364]: x = 1385, y = 169, w = 1565, h = 2473 + Box[365]: x = 460, y = 58, w = 1518, h = 2333 + Box[366]: x = 1379, y = 169, w = 1565, h = 2473 + Box[367]: x = 460, y = 58, w = 1518, h = 2333 + Box[368]: x = 1367, y = 169, w = 1593, h = 2473 + Box[369]: x = 460, y = 35, w = 1591, h = 2406 + Box[370]: x = 1308, y = 121, w = 1642, h = 2612 + Box[371]: x = 442, y = 47, w = 1609, h = 2406 + Box[372]: x = 1308, y = 121, w = 1642, h = 2612 + Box[373]: x = 460, y = 103, w = 1591, h = 2406 + Box[374]: x = 0, y = 0, w = 0, h = 0 + Box[375]: x = 0, y = 0, w = 0, h = 0 diff --git a/leptonica/prog/boxa3_reg.c b/leptonica/prog/boxa3_reg.c new file mode 100644 index 00000000..a3a5729a --- /dev/null +++ b/leptonica/prog/boxa3_reg.c @@ -0,0 +1,202 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * boxa3_reg.c + * + * Higher-level operations that can search for anomalous-sized boxes + * in a boxa, where the widths and heights of the boxes are expected + * to be similar. These can be corrected by moving the appropriate + * sides of the outlier boxes. + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + +static const char *boxafiles[3] = {"boxap1.ba", "boxap2.ba", "boxap3.ba"}; + +static void TestBoxa(L_REGPARAMS *rp, l_int32 index); +static void PlotBoxa(L_REGPARAMS *rp, l_int32 index); +static l_float32 varp[3] = {0.0165, 0.0432, 0.0716}; +static l_float32 varm[3] = {0.0088, 0.0213, 0.0357}; +static l_int32 same[3] = {1, -1, -1}; +static l_float32 devwidth[3] = {0.0864, 0.0895, 0.1174}; +static l_float32 devheight[3] = {0.0048, 0.0294, 0.0023}; + + +l_int32 main(int argc, + char **argv) +{ +l_int32 i; +L_REGPARAMS *rp; + +#if !defined(HAVE_LIBPNG) + L_ERROR("This test requires libpng to run.\n", "boxa3_reg"); + exit(77); +#endif + + if (regTestSetup(argc, argv, &rp)) + return 1; + + for (i = 0; i < 3; i++) + TestBoxa(rp, i); + for (i = 0; i < 3; i++) + PlotBoxa(rp, i); + return regTestCleanup(rp); +} + +static void +TestBoxa(L_REGPARAMS *rp, + l_int32 index) +{ +l_uint8 *data; +l_int32 w, h, medw, medh, isame; +size_t size; +l_float32 scalefact, devw, devh, ratiowh, fvarp, fvarm; +BOXA *boxa1, *boxa2, *boxa3; +PIX *pix1; + + boxa1 = boxaRead(boxafiles[index]); + + /* Read and display initial boxa */ + boxaGetExtent(boxa1, &w, &h, NULL); + scalefact = 100.0 / (l_float32)w; + boxa2 = boxaTransform(boxa1, 0, 0, scalefact, scalefact); + boxaWriteMem(&data, &size, boxa2); + regTestWriteDataAndCheck(rp, data, size, "ba"); /* 0, 13, 26 */ + lept_free(data); + pix1 = boxaDisplayTiled(boxa2, NULL, 0, -1, 2200, 2, 1.0, 0, 3, 2); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 1, 14, 27 */ + pixDisplayWithTitle(pix1, 0, 0, NULL, rp->display); + pixDestroy(&pix1); + + /* Find the median sizes */ + boxaMedianDimensions(boxa2, &medw, &medh, NULL, NULL, NULL, NULL, + NULL, NULL); + if (rp->display) + lept_stderr("median width = %d, median height = %d\n", medw, medh); + + /* Check for deviations from median by pairs: method 1 */ + boxaSizeConsistency1(boxa2, L_CHECK_HEIGHT, 0.0, 0.0, + &fvarp, &fvarm, &isame); + regTestCompareValues(rp, varp[index], fvarp, 0.003); /* 2, 15, 28 */ + regTestCompareValues(rp, varm[index], fvarm, 0.003); /* 3, 16, 29 */ + regTestCompareValues(rp, same[index], isame, 0); /* 4, 17, 30 */ + if (rp->display) + lept_stderr("fvarp = %7.4f, fvarm = %7.4f, same = %d\n", + fvarp, fvarm, isame); + + /* Check for deviations from median by pairs: method 2 */ + boxaSizeConsistency2(boxa2, &devw, &devh, 0); + regTestCompareValues(rp, devwidth[index], devw, 0.001); /* 5, 18, 31 */ + regTestCompareValues(rp, devheight[index], devh, 0.001); /* 6, 19, 32 */ + if (rp->display) + lept_stderr("dev width = %7.4f, dev height = %7.4f\n", devw, devh); + + /* Reconcile widths */ + boxa3 = boxaReconcileSizeByMedian(boxa2, L_CHECK_WIDTH, 0.05, 0.04, 1.03, + NULL, NULL, &ratiowh); + boxaWriteMem(&data, &size, boxa3); + regTestWriteDataAndCheck(rp, data, size, "ba"); /* 7, 20, 33 */ + lept_free(data); + pix1 = boxaDisplayTiled(boxa3, NULL, 0, -1, 2200, 2, 1.0, 0, 3, 2); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 8, 21, 34 */ + pixDisplayWithTitle(pix1, 500, 0, NULL, rp->display); + if (rp->display) + lept_stderr("ratio median width/height = %6.3f\n", ratiowh); + boxaDestroy(&boxa3); + pixDestroy(&pix1); + + /* Reconcile heights */ + boxa3 = boxaReconcileSizeByMedian(boxa2, L_CHECK_HEIGHT, 0.05, 0.04, 1.03, + NULL, NULL, NULL); + boxaWriteMem(&data, &size, boxa3); + regTestWriteDataAndCheck(rp, data, size, "ba"); /* 9, 22, 35 */ + lept_free(data); + pix1 = boxaDisplayTiled(boxa3, NULL, 0, -1, 2200, 2, 1.0, 0, 3, 2); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 10, 23, 36 */ + pixDisplayWithTitle(pix1, 1000, 0, NULL, rp->display); + boxaDestroy(&boxa3); + pixDestroy(&pix1); + + /* Reconcile both widths and heights */ + boxa3 = boxaReconcileSizeByMedian(boxa2, L_CHECK_BOTH, 0.05, 0.04, 1.03, + NULL, NULL, NULL); + boxaWriteMem(&data, &size, boxa3); + regTestWriteDataAndCheck(rp, data, size, "ba"); /* 11, 24, 37 */ + lept_free(data); + pix1 = boxaDisplayTiled(boxa3, NULL, 0, -1, 2200, 2, 1.0, 0, 3, 2); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 12, 25, 38 */ + pixDisplayWithTitle(pix1, 1500, 0, NULL, rp->display); + boxaDestroy(&boxa3); + pixDestroy(&pix1); + boxaDestroy(&boxa1); + boxaDestroy(&boxa2); + boxaDestroy(&boxa3); +} + + +static void +PlotBoxa(L_REGPARAMS *rp, + l_int32 index) +{ +BOXA *boxa1, *boxa2; +PIX *pix1, *pix2, *pix3; +PIXA *pixa; + + boxa1 = boxaRead(boxafiles[index]); + + /* Read and display initial boxa */ + boxaPlotSizes(boxa1, NULL, NULL, NULL, &pix1); + boxaPlotSides(boxa1, NULL, NULL, NULL, NULL, NULL, &pix2); + pixa = pixaCreate(2); + pixaAddPix(pixa, pix1, L_INSERT); + pixaAddPix(pixa, pix2, L_INSERT); + pix3 = pixaDisplayTiledInColumns(pixa, 2, 1.0, 20, 2); + regTestWritePixAndCheck(rp, pix3, IFF_PNG); /* 39, 41, 43 */ + pixDisplayWithTitle(pix3, 0 + 800 * index, 500, NULL, rp->display); + pixDestroy(&pix3); + pixaDestroy(&pixa); + + /* Read and display reconciled boxa */ + boxa2 = boxaReconcileSizeByMedian(boxa1, L_CHECK_BOTH, 0.05, 0.04, 1.03, + NULL, NULL, NULL); + boxaPlotSizes(boxa2, NULL, NULL, NULL, &pix1); + boxaPlotSides(boxa2, NULL, NULL, NULL, NULL, NULL, &pix2); + pixa = pixaCreate(2); + pixaAddPix(pixa, pix1, L_INSERT); + pixaAddPix(pixa, pix2, L_INSERT); + pix3 = pixaDisplayTiledInColumns(pixa, 2, 1.0, 20, 2); + regTestWritePixAndCheck(rp, pix3, IFF_PNG); /* 40, 42, 44 */ + pixDisplayWithTitle(pix3, 0 + 800 * index, 920, NULL, rp->display); + pixDestroy(&pix3); + pixaDestroy(&pixa); + boxaDestroy(&boxa1); + boxaDestroy(&boxa2); +} diff --git a/leptonica/prog/boxa4.ba b/leptonica/prog/boxa4.ba new file mode 100644 index 00000000..3590453a --- /dev/null +++ b/leptonica/prog/boxa4.ba @@ -0,0 +1,55 @@ + +Boxa Version 2 +Number of boxes = 52 + Box[0]: x = 313, y = 369, w = 892, h = 1255 + Box[1]: x = 877, y = 379, w = 908, h = 1293 + Box[2]: x = 300, y = 355, w = 952, h = 1283 + Box[3]: x = 744, y = 376, w = 896, h = 1305 + Box[4]: x = 333, y = 390, w = 985, h = 1281 + Box[5]: x = 697, y = 490, w = 849, h = 1279 + Box[6]: x = 379, y = 315, w = 992, h = 1328 + Box[7]: x = 801, y = 372, w = 713, h = 1293 + Box[8]: x = 373, y = 383, w = 1040, h = 1273 + Box[9]: x = 713, y = 374, w = 705, h = 1291 + Box[10]: x = 398, y = 376, w = 996, h = 1273 + Box[11]: x = 797, y = 371, w = 726, h = 1296 + Box[12]: x = 421, y = 373, w = 1138, h = 1258 + Box[13]: x = 799, y = 369, w = 725, h = 1294 + Box[14]: x = 379, y = 379, w = 1028, h = 1271 + Box[15]: x = 839, y = 371, w = 709, h = 1292 + Box[16]: x = 399, y = 377, w = 1050, h = 1305 + Box[17]: x = 735, y = 371, w = 742, h = 1292 + Box[18]: x = 363, y = 386, w = 989, h = 1275 + Box[19]: x = 711, y = 386, w = 730, h = 1282 + Box[20]: x = 395, y = 375, w = 1062, h = 1288 + Box[21]: x = 595, y = 491, w = 776, h = 1286 + Box[22]: x = 387, y = 390, w = 963, h = 1271 + Box[23]: x = 845, y = 392, w = 933, h = 1307 + Box[24]: x = 397, y = 412, w = 933, h = 1281 + Box[25]: x = 805, y = 391, w = 912, h = 1273 + Box[26]: x = 351, y = 375, w = 950, h = 1271 + Box[27]: x = 737, y = 405, w = 901, h = 1319 + Box[28]: x = 390, y = 443, w = 984, h = 1305 + Box[29]: x = 806, y = 381, w = 836, h = 1302 + Box[30]: x = 401, y = 373, w = 988, h = 1348 + Box[31]: x = 645, y = 443, w = 745, h = 1305 + Box[32]: x = 660, y = 390, w = 685, h = 1277 + Box[33]: x = 736, y = 398, w = 741, h = 1287 + Box[34]: x = 671, y = 355, w = 645, h = 1277 + Box[35]: x = 741, y = 391, w = 817, h = 1299 + Box[36]: x = 756, y = 365, w = 671, h = 1275 + Box[37]: x = 689, y = 381, w = 853, h = 1314 + Box[38]: x = 728, y = 364, w = 691, h = 1287 + Box[39]: x = 849, y = 389, w = 718, h = 1282 + Box[40]: x = 717, y = 372, w = 665, h = 1276 + Box[41]: x = 792, y = 394, w = 822, h = 1258 + Box[42]: x = 719, y = 374, w = 653, h = 1246 + Box[43]: x = 772, y = 374, w = 653, h = 1275 + Box[44]: x = 570, y = 374, w = 783, h = 1302 + Box[45]: x = 747, y = 370, w = 623, h = 1268 + Box[46]: x = 709, y = 442, w = 674, h = 1269 + Box[47]: x = 812, y = 384, w = 626, h = 1273 + Box[48]: x = 576, y = 384, w = 802, h = 1285 + Box[49]: x = 714, y = 387, w = 641, h = 1276 + Box[50]: x = 705, y = 356, w = 690, h = 1266 + Box[51]: x = 875, y = 380, w = 670, h = 1275 diff --git a/leptonica/prog/boxa4_reg.c b/leptonica/prog/boxa4_reg.c new file mode 100644 index 00000000..cb7a4797 --- /dev/null +++ b/leptonica/prog/boxa4_reg.c @@ -0,0 +1,226 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * boxa4_reg.c + * + * This carries out some smoothing and display operations on boxa. + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + +int main(int argc, + char **argv) +{ +l_uint8 *data; +l_int32 i, same, w, h, width, success, nb; +size_t size; +l_float32 scalefact; +BOXA *boxa1, *boxa1e, *boxa1o, *boxa2, *boxa2e, *boxa2o; +BOXA *boxa3, *boxa3e, *boxa3o; +BOXAA *baa1, *baa2, *baa3; +PIX *pix1, *pix2, *pix3; +PIXA *pixa1, *pixa2; +L_REGPARAMS *rp; + +#if !defined(HAVE_LIBPNG) + L_ERROR("This test requires libpng to run.\n", "boxa4_reg"); + exit(77); +#endif + + if (regTestSetup(argc, argv, &rp)) + return 1; + + lept_mkdir("lept/boxa"); + + /* Input is a fairly clean boxa */ + boxa1 = boxaRead("boxa1.ba"); + boxa2 = boxaReconcileEvenOddHeight(boxa1, L_ADJUST_TOP, 80, + L_ADJUST_CHOOSE_MIN, 1.05, 1); + width = 100; + boxaGetExtent(boxa2, &w, &h, NULL); + scalefact = (l_float32)width / (l_float32)w; + boxa3 = boxaTransform(boxa2, 0, 0, scalefact, scalefact); + pix1 = boxaDisplayTiled(boxa3, NULL, 0, -1, 1500, 2, 1.0, 0, 3, 2); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 0 */ + pixDisplayWithTitle(pix1, 600, 0, NULL, rp->display); + pixDestroy(&pix1); + boxaDestroy(&boxa1); + boxaDestroy(&boxa2); + boxaDestroy(&boxa3); + + /* Input is an unsmoothed and noisy boxa */ + boxa1 = boxaRead("boxa2.ba"); + boxa2 = boxaReconcileEvenOddHeight(boxa1, L_ADJUST_TOP, 80, + L_ADJUST_CHOOSE_MIN, 1.05, 1); + width = 100; + boxaGetExtent(boxa2, &w, &h, NULL); + scalefact = (l_float32)width / (l_float32)w; + boxa3 = boxaTransform(boxa2, 0, 0, scalefact, scalefact); + pix1 = boxaDisplayTiled(boxa3, NULL, 0, -1, 1500, 2, 1.0, 0, 3, 2); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 1 */ + pixDisplayWithTitle(pix1, 800, 0, NULL, rp->display); + pixDestroy(&pix1); + boxaDestroy(&boxa1); + boxaDestroy(&boxa2); + boxaDestroy(&boxa3); + + /* Input is an unsmoothed and noisy boxa */ + boxa1 = boxaRead("boxa2.ba"); + boxa2 = boxaSmoothSequenceMedian(boxa1, 10, L_SUB_ON_LOC_DIFF, 80, 20, 1); + boxa3 = boxaSmoothSequenceMedian(boxa1, 10, L_SUB_ON_SIZE_DIFF, 80, 20, 1); + boxaPlotSides(boxa1, "initial", NULL, NULL, NULL, NULL, &pix1); + boxaPlotSides(boxa2, "side-smoothing", NULL, NULL, NULL, NULL, &pix2); + boxaPlotSides(boxa3, "size-smoothing", NULL, NULL, NULL, NULL, &pix3); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 2 */ + regTestWritePixAndCheck(rp, pix2, IFF_PNG); /* 3 */ + regTestWritePixAndCheck(rp, pix3, IFF_PNG); /* 4 */ + pixDisplayWithTitle(pix1, 1300, 0, NULL, rp->display); + pixDisplayWithTitle(pix2, 1300, 500, NULL, rp->display); + pixDisplayWithTitle(pix3, 1300, 1000, NULL, rp->display); + pixDestroy(&pix1); + pixDestroy(&pix2); + pixDestroy(&pix3); + boxaDestroy(&boxa1); + boxaDestroy(&boxa2); + boxaDestroy(&boxa3); + + /* Reconcile all sides by median */ + boxa1 = boxaRead("boxa5.ba"); + pixa1 = pixaCreate(0); + boxa2 = boxaReconcileAllByMedian(boxa1, L_ADJUST_LEFT_AND_RIGHT, + L_ADJUST_TOP_AND_BOT, 50, 0, pixa1); + boxaWriteMem(&data, &size, boxa2); + regTestWriteDataAndCheck(rp, data, size, "ba"); /* 5 */ + pix1 = pixRead("/tmp/lept/boxa/recon_sides.png"); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 6 */ + pixDisplayWithTitle(pix1, 0, 0, NULL, rp->display); + lept_free(data); + pixaDestroy(&pixa1); + boxaDestroy(&boxa2); + pixDestroy(&pix1); + + /* Reconcile top/bot sides by median */ + pixa1 = pixaCreate(0); + boxa2 = boxaReconcileAllByMedian(boxa1, L_ADJUST_SKIP, + L_ADJUST_TOP_AND_BOT, 50, 0, pixa1); + boxaWriteMem(&data, &size, boxa2); + regTestWriteDataAndCheck(rp, data, size, "ba"); /* 7 */ + pix1 = pixRead("/tmp/lept/boxa/recon_sides.png"); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 8 */ + pixDisplayWithTitle(pix1, 0, 300, NULL, rp->display); + lept_free(data); + pixaDestroy(&pixa1); + boxaDestroy(&boxa1); + boxaDestroy(&boxa2); + pixDestroy(&pix1); + + /* Split even/odd and reconcile all sides by median */ + boxa1 = boxaRead("boxa5.ba"); + pixa1 = pixaCreate(0); + boxaSplitEvenOdd(boxa1, 0, &boxa1e, &boxa1o); + boxa2e = boxaReconcileSidesByMedian(boxa1e, L_ADJUST_TOP_AND_BOT, 50, + 0, pixa1); + boxa3e = boxaReconcileSidesByMedian(boxa2e, L_ADJUST_LEFT_AND_RIGHT, 50, + 0, pixa1); + boxa2o = boxaReconcileSidesByMedian(boxa1o, L_ADJUST_TOP_AND_BOT, 50, + 0, pixa1); + boxa3o = boxaReconcileSidesByMedian(boxa2o, L_ADJUST_LEFT_AND_RIGHT, 50, + 0, pixa1); + boxa3 = boxaMergeEvenOdd(boxa3e, boxa3o, 0); + boxaWriteMem(&data, &size, boxa3); + regTestWriteDataAndCheck(rp, data, size, "ba"); /* 9 */ + if (rp->display) { + pix1 = pixaDisplayTiledInRows(pixa1, 32, 1800, 0.5, 0, 30, 2); + pixDisplay(pix1, 800, 500); + pixDestroy(&pix1); + } + lept_free(data); + pixaDestroy(&pixa1); + boxaDestroy(&boxa1); + boxaDestroy(&boxa1e); + boxaDestroy(&boxa1o); + boxaDestroy(&boxa2e); + boxaDestroy(&boxa2o); + boxaDestroy(&boxa3); + boxaDestroy(&boxa3e); + boxaDestroy(&boxa3o); + + /* Input is a boxa smoothed with a median window filter */ + boxa1 = boxaRead("boxa3.ba"); + boxa2 = boxaReconcileEvenOddHeight(boxa1, L_ADJUST_TOP, 80, + L_ADJUST_CHOOSE_MIN, 1.05, 1); + width = 100; + boxaGetExtent(boxa2, &w, &h, NULL); + scalefact = (l_float32)width / (l_float32)w; + boxa3 = boxaTransform(boxa2, 0, 0, scalefact, scalefact); + pix1 = boxaDisplayTiled(boxa3, NULL, 0, -1, 1500, 2, 1.0, 0, 3, 2); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 10 */ + pixDisplayWithTitle(pix1, 1000, 0, NULL, rp->display); + pixDestroy(&pix1); + boxaDestroy(&boxa1); + boxaDestroy(&boxa2); + boxaDestroy(&boxa3); + + /* ----------- Test pixaDisplayBoxaa() ------------ */ + pixa1 = pixaReadBoth("showboxes.pac"); + baa1 = boxaaRead("showboxes1.baa"); + baa2 = boxaaTranspose(baa1); + baa3 = boxaaTranspose(baa2); + nb = boxaaGetCount(baa1); + success = TRUE; + for (i = 0; i < nb; i++) { + boxa1 = boxaaGetBoxa(baa1, i, L_CLONE); + boxa2 = boxaaGetBoxa(baa3, i, L_CLONE); + boxaEqual(boxa1, boxa2, 0, NULL, &same); + boxaDestroy(&boxa1); + boxaDestroy(&boxa2); + if (!same) success = FALSE; + } + + /* Check that the transpose is reversible */ + regTestCompareValues(rp, 1, success, 0.0); /* 11 */ + pixa2 = pixaDisplayBoxaa(pixa1, baa2, L_DRAW_RGB, 2); + pix1 = pixaDisplayTiledInRows(pixa2, 32, 1400, 1.0, 0, 10, 0); + regTestWritePixAndCheck(rp, pix1, IFF_JFIF_JPEG); /* 12 */ + pixDisplayWithTitle(pix1, 0, 600, NULL, rp->display); + lept_stderr("Writing to: /tmp/lept/boxa/show.pdf\n"); + l_pdfSetDateAndVersion(FALSE); + pixaConvertToPdf(pixa2, 75, 0.6, 0, 0, NULL, "/tmp/lept/boxa/show.pdf"); + regTestCheckFile(rp, "/tmp/lept/boxa/show.pdf"); /* 13 */ + pixDestroy(&pix1); + pixaDestroy(&pixa1); + pixaDestroy(&pixa2); + boxaaDestroy(&baa1); + boxaaDestroy(&baa2); + boxaaDestroy(&baa3); + + return regTestCleanup(rp); +} diff --git a/leptonica/prog/boxa5.ba b/leptonica/prog/boxa5.ba new file mode 100644 index 00000000..f501930e --- /dev/null +++ b/leptonica/prog/boxa5.ba @@ -0,0 +1,21 @@ + +Boxa Version 2 +Number of boxes = 18 + Box[0]: x = 800, y = 808, w = 1600, h = 2016 + Box[1]: x = 0, y = 1318, w = 1956, h = 2406 + Box[2]: x = 800, y = 808, w = 1600, h = 2016 + Box[3]: x = 0, y = 1318, w = 1956, h = 2406 + Box[4]: x = 800, y = 808, w = 1600, h = 2016 + Box[5]: x = 0, y = 1368, w = 1956, h = 2356 + Box[6]: x = 720, y = 1332, w = 1952, h = 2380 + Box[7]: x = 0, y = 1368, w = 1956, h = 2356 + Box[8]: x = 720, y = 1332, w = 1952, h = 2376 + Box[9]: x = 0, y = 1368, w = 1956, h = 2356 + Box[10]: x = 720, y = 1332, w = 1952, h = 2380 + Box[11]: x = 0, y = 1368, w = 1956, h = 2356 + Box[12]: x = 720, y = 1332, w = 1952, h = 2376 + Box[13]: x = 0, y = 1368, w = 1956, h = 2356 + Box[14]: x = 720, y = 1332, w = 1952, h = 2376 + Box[15]: x = 0, y = 1368, w = 1956, h = 2356 + Box[16]: x = 700, y = 1332, w = 1972, h = 2376 + Box[17]: x = 0, y = 1368, w = 1956, h = 2356 diff --git a/leptonica/prog/boxap1.ba b/leptonica/prog/boxap1.ba new file mode 100644 index 00000000..52983fce --- /dev/null +++ b/leptonica/prog/boxap1.ba @@ -0,0 +1,129 @@ + +Boxa Version 2 +Number of boxes = 126 + Box[0]: x = 0, y = 0, w = 0, h = 0 + Box[1]: x = 0, y = 0, w = 0, h = 0 + Box[2]: x = 0, y = 0, w = 0, h = 0 + Box[3]: x = 0, y = 0, w = 0, h = 0 + Box[4]: x = 0, y = 0, w = 0, h = 0 + Box[5]: x = 0, y = 0, w = 2627, h = 3321 + Box[6]: x = 0, y = 59, w = 2575, h = 3292 + Box[7]: x = 558, y = 0, w = 1998, h = 3227 + Box[8]: x = 364, y = 59, w = 2345, h = 3198 + Box[9]: x = 270, y = 0, w = 2433, h = 3245 + Box[10]: x = 335, y = 59, w = 2369, h = 3209 + Box[11]: x = 259, y = 0, w = 2445, h = 3245 + Box[12]: x = 323, y = 59, w = 2375, h = 3274 + Box[13]: x = 247, y = 0, w = 2457, h = 3250 + Box[14]: x = 347, y = 59, w = 2416, h = 3292 + Box[15]: x = 270, y = 0, w = 2433, h = 3245 + Box[16]: x = 312, y = 59, w = 2369, h = 3209 + Box[17]: x = 247, y = 0, w = 2463, h = 3250 + Box[18]: x = 306, y = 59, w = 1910, h = 3203 + Box[19]: x = 241, y = 0, w = 1211, h = 3250 + Box[20]: x = 323, y = 59, w = 2363, h = 3215 + Box[21]: x = 253, y = 0, w = 2451, h = 3250 + Box[22]: x = 294, y = 59, w = 2433, h = 3198 + Box[23]: x = 247, y = 0, w = 1252, h = 3250 + Box[24]: x = 229, y = 59, w = 2433, h = 3292 + Box[25]: x = 223, y = 0, w = 2486, h = 3262 + Box[26]: x = 265, y = 59, w = 2451, h = 3274 + Box[27]: x = 229, y = 0, w = 2475, h = 3256 + Box[28]: x = 294, y = 59, w = 2433, h = 3286 + Box[29]: x = 241, y = 0, w = 2463, h = 3250 + Box[30]: x = 300, y = 59, w = 2428, h = 3203 + Box[31]: x = 259, y = 0, w = 2445, h = 3250 + Box[32]: x = 300, y = 59, w = 2433, h = 3227 + Box[33]: x = 253, y = 0, w = 2451, h = 3250 + Box[34]: x = 282, y = 59, w = 2439, h = 3209 + Box[35]: x = 235, y = 0, w = 2469, h = 3250 + Box[36]: x = 270, y = 59, w = 1969, h = 3227 + Box[37]: x = 229, y = 0, w = 2463, h = 3256 + Box[38]: x = 282, y = 59, w = 1998, h = 3198 + Box[39]: x = 235, y = 0, w = 1869, h = 3256 + Box[40]: x = 282, y = 59, w = 1987, h = 3209 + Box[41]: x = 247, y = 0, w = 2451, h = 3262 + Box[42]: x = 288, y = 59, w = 2439, h = 3215 + Box[43]: x = 259, y = 0, w = 2445, h = 3256 + Box[44]: x = 282, y = 59, w = 2463, h = 3215 + Box[45]: x = 265, y = 0, w = 2433, h = 3256 + Box[46]: x = 241, y = 59, w = 2398, h = 3221 + Box[47]: x = 0, y = 0, w = 2680, h = 3350 + Box[48]: x = 194, y = 59, w = 2457, h = 3250 + Box[49]: x = 247, y = 0, w = 2433, h = 3292 + Box[50]: x = 223, y = 59, w = 2433, h = 3239 + Box[51]: x = 188, y = 0, w = 2486, h = 3280 + Box[52]: x = 170, y = 59, w = 2463, h = 3321 + Box[53]: x = 206, y = 0, w = 2480, h = 3280 + Box[54]: x = 170, y = 59, w = 2492, h = 3245 + Box[55]: x = 212, y = 0, w = 2463, h = 3286 + Box[56]: x = 200, y = 59, w = 2457, h = 3245 + Box[57]: x = 194, y = 0, w = 2469, h = 3280 + Box[58]: x = 223, y = 59, w = 2433, h = 3221 + Box[59]: x = 165, y = 0, w = 2498, h = 3286 + Box[60]: x = 217, y = 59, w = 2433, h = 3233 + Box[61]: x = 182, y = 0, w = 2463, h = 3286 + Box[62]: x = 235, y = 59, w = 2422, h = 3262 + Box[63]: x = 170, y = 0, w = 2486, h = 3286 + Box[64]: x = 217, y = 59, w = 2433, h = 3239 + Box[65]: x = 182, y = 0, w = 2457, h = 3286 + Box[66]: x = 212, y = 59, w = 2439, h = 3245 + Box[67]: x = 159, y = 0, w = 2480, h = 3286 + Box[68]: x = 217, y = 59, w = 2433, h = 3227 + Box[69]: x = 176, y = 0, w = 2463, h = 3286 + Box[70]: x = 165, y = 59, w = 2492, h = 3233 + Box[71]: x = 153, y = 0, w = 2480, h = 3292 + Box[72]: x = 194, y = 59, w = 2451, h = 3221 + Box[73]: x = 165, y = 0, w = 1740, h = 3292 + Box[74]: x = 165, y = 59, w = 2486, h = 3239 + Box[75]: x = 147, y = 0, w = 1769, h = 3292 + Box[76]: x = 176, y = 59, w = 2463, h = 3239 + Box[77]: x = 165, y = 0, w = 1487, h = 3292 + Box[78]: x = 147, y = 59, w = 2134, h = 3215 + Box[79]: x = 129, y = 0, w = 2486, h = 3298 + Box[80]: x = 147, y = 59, w = 2128, h = 3215 + Box[81]: x = 364, y = 0, w = 2269, h = 3292 + Box[82]: x = 147, y = 59, w = 2492, h = 3215 + Box[83]: x = 118, y = 0, w = 1417, h = 3292 + Box[84]: x = 176, y = 59, w = 1934, h = 3215 + Box[85]: x = 535, y = 0, w = 2116, h = 3292 + Box[86]: x = 188, y = 59, w = 2451, h = 3221 + Box[87]: x = 159, y = 0, w = 1440, h = 3298 + Box[88]: x = 176, y = 59, w = 2093, h = 3233 + Box[89]: x = 370, y = 0, w = 2063, h = 3292 + Box[90]: x = 170, y = 59, w = 2081, h = 3233 + Box[91]: x = 170, y = 0, w = 1399, h = 3292 + Box[92]: x = 182, y = 59, w = 2169, h = 3221 + Box[93]: x = 170, y = 0, w = 1258, h = 3298 + Box[94]: x = 176, y = 59, w = 2040, h = 3215 + Box[95]: x = 170, y = 0, w = 1505, h = 3298 + Box[96]: x = 135, y = 59, w = 2087, h = 3233 + Box[97]: x = 165, y = 0, w = 2428, h = 3298 + Box[98]: x = 135, y = 59, w = 2469, h = 3239 + Box[99]: x = 182, y = 0, w = 1734, h = 3298 + Box[100]: x = 165, y = 59, w = 2028, h = 3221 + Box[101]: x = 165, y = 0, w = 2457, h = 3298 + Box[102]: x = 182, y = 59, w = 2075, h = 3262 + Box[103]: x = 165, y = 0, w = 1217, h = 3298 + Box[104]: x = 165, y = 59, w = 2439, h = 3245 + Box[105]: x = 123, y = 0, w = 1775, h = 3292 + Box[106]: x = 123, y = 59, w = 2110, h = 3233 + Box[107]: x = 170, y = 0, w = 1793, h = 3298 + Box[108]: x = 165, y = 59, w = 1916, h = 3209 + Box[109]: x = 153, y = 0, w = 1181, h = 3292 + Box[110]: x = 159, y = 59, w = 2093, h = 3245 + Box[111]: x = 159, y = 0, w = 1387, h = 3298 + Box[112]: x = 153, y = 59, w = 2439, h = 3233 + Box[113]: x = 159, y = 0, w = 1352, h = 3298 + Box[114]: x = 153, y = 59, w = 2439, h = 3280 + Box[115]: x = 165, y = 0, w = 1375, h = 3298 + Box[116]: x = 141, y = 59, w = 2110, h = 3227 + Box[117]: x = 147, y = 0, w = 1763, h = 3298 + Box[118]: x = 94, y = 59, w = 2469, h = 3256 + Box[119]: x = 135, y = 0, w = 1328, h = 3298 + Box[120]: x = 141, y = 59, w = 2551, h = 3215 + Box[121]: x = 276, y = 0, w = 2363, h = 3274 + Box[122]: x = 694, y = 59, w = 1752, h = 3268 + Box[123]: x = 147, y = 0, w = 1963, h = 3386 + Box[124]: x = 200, y = 59, w = 2663, h = 3303 + Box[125]: x = 0, y = 0, w = 0, h = 0 diff --git a/leptonica/prog/boxap2.ba b/leptonica/prog/boxap2.ba new file mode 100644 index 00000000..0adf6aa4 --- /dev/null +++ b/leptonica/prog/boxap2.ba @@ -0,0 +1,303 @@ + +Boxa Version 2 +Number of boxes = 300 + Box[0]: x = 0, y = 0, w = 0, h = 0 + Box[1]: x = 0, y = 0, w = 0, h = 0 + Box[2]: x = 0, y = 0, w = 0, h = 0 + Box[3]: x = 0, y = 0, w = 0, h = 0 + Box[4]: x = 0, y = 0, w = 0, h = 0 + Box[5]: x = 398, y = 0, w = 2133, h = 3011 + Box[6]: x = 78, y = 39, w = 1891, h = 3015 + Box[7]: x = 257, y = 0, w = 2129, h = 3015 + Box[8]: x = 55, y = 39, w = 2235, h = 3038 + Box[9]: x = 335, y = 0, w = 2122, h = 3003 + Box[10]: x = 55, y = 39, w = 2242, h = 3034 + Box[11]: x = 335, y = 0, w = 2122, h = 2995 + Box[12]: x = 62, y = 39, w = 2231, h = 3050 + Box[13]: x = 390, y = 0, w = 2071, h = 2995 + Box[14]: x = 62, y = 39, w = 2262, h = 3054 + Box[15]: x = 472, y = 0, w = 1993, h = 2995 + Box[16]: x = 62, y = 39, w = 2246, h = 3054 + Box[17]: x = 472, y = 0, w = 1993, h = 2999 + Box[18]: x = 66, y = 39, w = 2231, h = 3054 + Box[19]: x = 558, y = 0, w = 1915, h = 2999 + Box[20]: x = 82, y = 39, w = 2219, h = 3054 + Box[21]: x = 495, y = 0, w = 1981, h = 2999 + Box[22]: x = 66, y = 39, w = 2242, h = 3057 + Box[23]: x = 499, y = 0, w = 1977, h = 2995 + Box[24]: x = 70, y = 39, w = 2235, h = 3061 + Box[25]: x = 530, y = 0, w = 1946, h = 2999 + Box[26]: x = 66, y = 39, w = 2239, h = 3061 + Box[27]: x = 534, y = 0, w = 1942, h = 2991 + Box[28]: x = 66, y = 39, w = 2242, h = 3061 + Box[29]: x = 480, y = 0, w = 1997, h = 2999 + Box[30]: x = 66, y = 39, w = 2242, h = 3054 + Box[31]: x = 433, y = 0, w = 2040, h = 2995 + Box[32]: x = 70, y = 39, w = 2239, h = 3057 + Box[33]: x = 452, y = 0, w = 2036, h = 2987 + Box[34]: x = 74, y = 39, w = 2239, h = 3054 + Box[35]: x = 499, y = 0, w = 1985, h = 2991 + Box[36]: x = 74, y = 39, w = 2235, h = 3054 + Box[37]: x = 468, y = 0, w = 2020, h = 2995 + Box[38]: x = 74, y = 39, w = 2239, h = 3050 + Box[39]: x = 511, y = 0, w = 1977, h = 2995 + Box[40]: x = 74, y = 39, w = 2239, h = 3050 + Box[41]: x = 569, y = 0, w = 1915, h = 2995 + Box[42]: x = 70, y = 39, w = 2242, h = 3050 + Box[43]: x = 468, y = 0, w = 2024, h = 2991 + Box[44]: x = 74, y = 39, w = 2242, h = 3050 + Box[45]: x = 749, y = 0, w = 1732, h = 2987 + Box[46]: x = 70, y = 39, w = 2246, h = 3050 + Box[47]: x = 460, y = 0, w = 2028, h = 2991 + Box[48]: x = 70, y = 39, w = 2250, h = 3054 + Box[49]: x = 562, y = 0, w = 1930, h = 2987 + Box[50]: x = 74, y = 39, w = 2242, h = 3054 + Box[51]: x = 628, y = 0, w = 1860, h = 2991 + Box[52]: x = 70, y = 39, w = 2250, h = 3057 + Box[53]: x = 456, y = 0, w = 2028, h = 2991 + Box[54]: x = 70, y = 39, w = 2250, h = 3065 + Box[55]: x = 659, y = 0, w = 1833, h = 2991 + Box[56]: x = 74, y = 39, w = 2246, h = 3050 + Box[57]: x = 538, y = 0, w = 1950, h = 2991 + Box[58]: x = 74, y = 39, w = 2250, h = 3054 + Box[59]: x = 581, y = 0, w = 1911, h = 2991 + Box[60]: x = 74, y = 39, w = 2250, h = 3050 + Box[61]: x = 554, y = 0, w = 1938, h = 2991 + Box[62]: x = 78, y = 39, w = 2246, h = 3054 + Box[63]: x = 651, y = 0, w = 1841, h = 2991 + Box[64]: x = 78, y = 39, w = 2250, h = 3057 + Box[65]: x = 632, y = 0, w = 1860, h = 2987 + Box[66]: x = 74, y = 39, w = 2254, h = 3061 + Box[67]: x = 511, y = 0, w = 1981, h = 2991 + Box[68]: x = 74, y = 39, w = 2258, h = 3057 + Box[69]: x = 530, y = 0, w = 1962, h = 2987 + Box[70]: x = 78, y = 39, w = 2250, h = 3057 + Box[71]: x = 651, y = 0, w = 1841, h = 2987 + Box[72]: x = 105, y = 39, w = 2227, h = 3054 + Box[73]: x = 550, y = 0, w = 1950, h = 2987 + Box[74]: x = 74, y = 39, w = 2258, h = 3065 + Box[75]: x = 526, y = 0, w = 1973, h = 2983 + Box[76]: x = 117, y = 39, w = 2215, h = 3073 + Box[77]: x = 620, y = 0, w = 1876, h = 2987 + Box[78]: x = 109, y = 39, w = 2223, h = 3065 + Box[79]: x = 694, y = 0, w = 1806, h = 2991 + Box[80]: x = 156, y = 39, w = 2231, h = 3069 + Box[81]: x = 647, y = 0, w = 1849, h = 2987 + Box[82]: x = 156, y = 39, w = 2231, h = 3065 + Box[83]: x = 577, y = 0, w = 1919, h = 2987 + Box[84]: x = 168, y = 39, w = 2219, h = 3073 + Box[85]: x = 768, y = 0, w = 1728, h = 2991 + Box[86]: x = 183, y = 39, w = 2211, h = 3065 + Box[87]: x = 745, y = 0, w = 1759, h = 2991 + Box[88]: x = 164, y = 39, w = 2231, h = 3069 + Box[89]: x = 328, y = 0, w = 2176, h = 2987 + Box[90]: x = 164, y = 39, w = 2227, h = 3057 + Box[91]: x = 550, y = 0, w = 1958, h = 2987 + Box[92]: x = 164, y = 39, w = 2235, h = 3061 + Box[93]: x = 640, y = 0, w = 1868, h = 2987 + Box[94]: x = 164, y = 39, w = 2239, h = 3061 + Box[95]: x = 640, y = 0, w = 1868, h = 2991 + Box[96]: x = 168, y = 39, w = 2239, h = 3050 + Box[97]: x = 339, y = 0, w = 2168, h = 2991 + Box[98]: x = 136, y = 39, w = 2266, h = 3057 + Box[99]: x = 686, y = 0, w = 1802, h = 2991 + Box[100]: x = 113, y = 39, w = 2301, h = 3038 + Box[101]: x = 359, y = 0, w = 2122, h = 2987 + Box[102]: x = 55, y = 39, w = 2211, h = 3022 + Box[103]: x = 214, y = 0, w = 2196, h = 3003 + Box[104]: x = 0, y = 39, w = 2371, h = 3022 + Box[105]: x = 218, y = 0, w = 2192, h = 3003 + Box[106]: x = 58, y = 39, w = 2090, h = 3022 + Box[107]: x = 222, y = 0, w = 2188, h = 3003 + Box[108]: x = 0, y = 39, w = 1973, h = 3022 + Box[109]: x = 218, y = 0, w = 2188, h = 3011 + Box[110]: x = 74, y = 39, w = 2200, h = 3022 + Box[111]: x = 296, y = 0, w = 2110, h = 3007 + Box[112]: x = 62, y = 39, w = 2301, h = 3026 + Box[113]: x = 222, y = 0, w = 2188, h = 3007 + Box[114]: x = 58, y = 39, w = 2207, h = 3026 + Box[115]: x = 413, y = 0, w = 1997, h = 3007 + Box[116]: x = 70, y = 39, w = 2012, h = 3030 + Box[117]: x = 179, y = 0, w = 2235, h = 3003 + Box[118]: x = 66, y = 39, w = 2161, h = 3030 + Box[119]: x = 370, y = 0, w = 2036, h = 3003 + Box[120]: x = 43, y = 39, w = 1989, h = 3030 + Box[121]: x = 331, y = 0, w = 2079, h = 2999 + Box[122]: x = 43, y = 39, w = 2231, h = 3026 + Box[123]: x = 316, y = 0, w = 2090, h = 3003 + Box[124]: x = 43, y = 39, w = 2227, h = 3030 + Box[125]: x = 562, y = 0, w = 1849, h = 2999 + Box[126]: x = 47, y = 39, w = 2200, h = 3030 + Box[127]: x = 507, y = 0, w = 1895, h = 3003 + Box[128]: x = 43, y = 39, w = 2149, h = 3030 + Box[129]: x = 370, y = 0, w = 2036, h = 3007 + Box[130]: x = 43, y = 39, w = 2293, h = 3034 + Box[131]: x = 183, y = 0, w = 2223, h = 3003 + Box[132]: x = 43, y = 39, w = 2348, h = 3030 + Box[133]: x = 312, y = 0, w = 2098, h = 3003 + Box[134]: x = 43, y = 39, w = 2231, h = 3038 + Box[135]: x = 339, y = 0, w = 2063, h = 3003 + Box[136]: x = 43, y = 39, w = 1802, h = 3030 + Box[137]: x = 499, y = 0, w = 1907, h = 3003 + Box[138]: x = 43, y = 39, w = 2262, h = 3038 + Box[139]: x = 402, y = 0, w = 2001, h = 3003 + Box[140]: x = 43, y = 39, w = 2153, h = 3030 + Box[141]: x = 616, y = 0, w = 1794, h = 2999 + Box[142]: x = 43, y = 39, w = 2227, h = 3030 + Box[143]: x = 456, y = 0, w = 1950, h = 2999 + Box[144]: x = 43, y = 39, w = 2005, h = 3022 + Box[145]: x = 573, y = 0, w = 1837, h = 2999 + Box[146]: x = 43, y = 39, w = 2301, h = 3015 + Box[147]: x = 367, y = 0, w = 2040, h = 3007 + Box[148]: x = 43, y = 39, w = 2305, h = 3034 + Box[149]: x = 343, y = 0, w = 2063, h = 3007 + Box[150]: x = 43, y = 39, w = 2110, h = 3026 + Box[151]: x = 409, y = 0, w = 1989, h = 3007 + Box[152]: x = 43, y = 39, w = 2274, h = 3034 + Box[153]: x = 550, y = 0, w = 1852, h = 3007 + Box[154]: x = 43, y = 39, w = 2305, h = 3038 + Box[155]: x = 367, y = 0, w = 2036, h = 3007 + Box[156]: x = 43, y = 39, w = 2196, h = 3030 + Box[157]: x = 363, y = 0, w = 2040, h = 3003 + Box[158]: x = 43, y = 39, w = 2223, h = 3030 + Box[159]: x = 246, y = 0, w = 2149, h = 3003 + Box[160]: x = 43, y = 39, w = 2219, h = 3026 + Box[161]: x = 242, y = 0, w = 2176, h = 3003 + Box[162]: x = 47, y = 39, w = 2305, h = 3030 + Box[163]: x = 647, y = 0, w = 1767, h = 3030 + Box[164]: x = 43, y = 39, w = 2309, h = 3015 + Box[165]: x = 421, y = 0, w = 1993, h = 2999 + Box[166]: x = 43, y = 39, w = 2352, h = 3022 + Box[167]: x = 472, y = 0, w = 1938, h = 2999 + Box[168]: x = 43, y = 39, w = 2313, h = 3015 + Box[169]: x = 367, y = 0, w = 2047, h = 2999 + Box[170]: x = 43, y = 39, w = 2313, h = 3015 + Box[171]: x = 261, y = 0, w = 2149, h = 3030 + Box[172]: x = 47, y = 39, w = 2313, h = 3042 + Box[173]: x = 390, y = 0, w = 2020, h = 3026 + Box[174]: x = 43, y = 39, w = 2317, h = 3038 + Box[175]: x = 312, y = 0, w = 2086, h = 3003 + Box[176]: x = 47, y = 39, w = 2254, h = 3030 + Box[177]: x = 491, y = 0, w = 1915, h = 2999 + Box[178]: x = 43, y = 39, w = 2313, h = 3034 + Box[179]: x = 417, y = 0, w = 1985, h = 2999 + Box[180]: x = 43, y = 39, w = 2317, h = 3030 + Box[181]: x = 355, y = 0, w = 2051, h = 2999 + Box[182]: x = 43, y = 39, w = 2317, h = 3034 + Box[183]: x = 370, y = 0, w = 2044, h = 2999 + Box[184]: x = 43, y = 39, w = 2317, h = 3015 + Box[185]: x = 363, y = 0, w = 2036, h = 3007 + Box[186]: x = 43, y = 39, w = 2320, h = 3022 + Box[187]: x = 421, y = 0, w = 1981, h = 3007 + Box[188]: x = 43, y = 39, w = 2317, h = 3011 + Box[189]: x = 374, y = 0, w = 2020, h = 3007 + Box[190]: x = 43, y = 39, w = 2317, h = 3026 + Box[191]: x = 601, y = 0, w = 1802, h = 3003 + Box[192]: x = 47, y = 39, w = 2309, h = 3022 + Box[193]: x = 265, y = 0, w = 2129, h = 2999 + Box[194]: x = 43, y = 39, w = 2320, h = 3038 + Box[195]: x = 285, y = 0, w = 2118, h = 3007 + Box[196]: x = 43, y = 39, w = 2320, h = 3015 + Box[197]: x = 281, y = 0, w = 2122, h = 2999 + Box[198]: x = 47, y = 39, w = 2305, h = 3038 + Box[199]: x = 292, y = 0, w = 2098, h = 3007 + Box[200]: x = 47, y = 39, w = 2317, h = 3015 + Box[201]: x = 273, y = 0, w = 2114, h = 3034 + Box[202]: x = 47, y = 39, w = 2313, h = 3030 + Box[203]: x = 277, y = 0, w = 2242, h = 2995 + Box[204]: x = 195, y = 39, w = 2086, h = 3026 + Box[205]: x = 261, y = 23, w = 1544, h = 2991 + Box[206]: x = 772, y = 292, w = 1634, h = 2714 + Box[207]: x = 265, y = 0, w = 1669, h = 3003 + Box[208]: x = 772, y = 289, w = 1638, h = 2718 + Box[209]: x = 269, y = 0, w = 1657, h = 2999 + Box[210]: x = 788, y = 289, w = 1622, h = 2730 + Box[211]: x = 273, y = 0, w = 1661, h = 2995 + Box[212]: x = 784, y = 289, w = 1626, h = 2710 + Box[213]: x = 273, y = 0, w = 1661, h = 2991 + Box[214]: x = 788, y = 289, w = 1626, h = 2726 + Box[215]: x = 277, y = 0, w = 1661, h = 2995 + Box[216]: x = 784, y = 292, w = 1634, h = 2714 + Box[217]: x = 273, y = 0, w = 1650, h = 3018 + Box[218]: x = 792, y = 292, w = 1630, h = 2706 + Box[219]: x = 273, y = 0, w = 1661, h = 3003 + Box[220]: x = 788, y = 292, w = 1634, h = 2718 + Box[221]: x = 328, y = 0, w = 1611, h = 3018 + Box[222]: x = 792, y = 292, w = 1630, h = 2710 + Box[223]: x = 577, y = 0, w = 1365, h = 3018 + Box[224]: x = 796, y = 292, w = 1630, h = 2706 + Box[225]: x = 277, y = 0, w = 1657, h = 3003 + Box[226]: x = 796, y = 292, w = 1634, h = 2703 + Box[227]: x = 277, y = 0, w = 1657, h = 3018 + Box[228]: x = 799, y = 292, w = 1634, h = 2706 + Box[229]: x = 281, y = 0, w = 1654, h = 3018 + Box[230]: x = 799, y = 292, w = 1638, h = 2706 + Box[231]: x = 281, y = 0, w = 1650, h = 3015 + Box[232]: x = 803, y = 292, w = 1634, h = 2703 + Box[233]: x = 281, y = 0, w = 1650, h = 3015 + Box[234]: x = 799, y = 292, w = 1642, h = 2706 + Box[235]: x = 331, y = 0, w = 1607, h = 3018 + Box[236]: x = 799, y = 300, w = 1642, h = 2703 + Box[237]: x = 285, y = 0, w = 1650, h = 3018 + Box[238]: x = 792, y = 257, w = 1650, h = 2722 + Box[239]: x = 300, y = 0, w = 1646, h = 3034 + Box[240]: x = 803, y = 257, w = 1642, h = 2714 + Box[241]: x = 285, y = 0, w = 1654, h = 3034 + Box[242]: x = 803, y = 257, w = 1642, h = 2722 + Box[243]: x = 347, y = 0, w = 1595, h = 3034 + Box[244]: x = 807, y = 261, w = 1642, h = 2718 + Box[245]: x = 347, y = 0, w = 1587, h = 3038 + Box[246]: x = 811, y = 257, w = 1638, h = 2722 + Box[247]: x = 292, y = 0, w = 1654, h = 3026 + Box[248]: x = 807, y = 257, w = 1646, h = 2718 + Box[249]: x = 308, y = 0, w = 1630, h = 3034 + Box[250]: x = 811, y = 261, w = 1646, h = 2718 + Box[251]: x = 292, y = 0, w = 1646, h = 3038 + Box[252]: x = 811, y = 257, w = 1642, h = 2714 + Box[253]: x = 312, y = 0, w = 1630, h = 3034 + Box[254]: x = 819, y = 257, w = 1642, h = 2718 + Box[255]: x = 312, y = 0, w = 1622, h = 3038 + Box[256]: x = 819, y = 257, w = 1642, h = 2718 + Box[257]: x = 296, y = 0, w = 1646, h = 3038 + Box[258]: x = 815, y = 257, w = 1646, h = 2718 + Box[259]: x = 316, y = 0, w = 1626, h = 3038 + Box[260]: x = 823, y = 257, w = 1646, h = 2718 + Box[261]: x = 316, y = 0, w = 1630, h = 3038 + Box[262]: x = 815, y = 257, w = 1650, h = 2722 + Box[263]: x = 296, y = 0, w = 1642, h = 3042 + Box[264]: x = 819, y = 257, w = 1654, h = 2718 + Box[265]: x = 300, y = 0, w = 1634, h = 3042 + Box[266]: x = 819, y = 257, w = 1654, h = 2718 + Box[267]: x = 316, y = 0, w = 1630, h = 3038 + Box[268]: x = 819, y = 257, w = 1657, h = 2714 + Box[269]: x = 370, y = 0, w = 1576, h = 3038 + Box[270]: x = 819, y = 261, w = 1657, h = 2714 + Box[271]: x = 316, y = 0, w = 1630, h = 3038 + Box[272]: x = 823, y = 261, w = 1654, h = 2714 + Box[273]: x = 351, y = 0, w = 1591, h = 3042 + Box[274]: x = 827, y = 261, w = 1654, h = 2718 + Box[275]: x = 398, y = 0, w = 1548, h = 3038 + Box[276]: x = 827, y = 261, w = 1654, h = 2714 + Box[277]: x = 367, y = 0, w = 1572, h = 3042 + Box[278]: x = 827, y = 261, w = 1661, h = 2714 + Box[279]: x = 347, y = 0, w = 1603, h = 3038 + Box[280]: x = 827, y = 261, w = 1661, h = 2710 + Box[281]: x = 355, y = 0, w = 1591, h = 3042 + Box[282]: x = 823, y = 261, w = 1661, h = 2718 + Box[283]: x = 304, y = 0, w = 1638, h = 3042 + Box[284]: x = 815, y = 261, w = 1669, h = 2718 + Box[285]: x = 324, y = 0, w = 1622, h = 3042 + Box[286]: x = 815, y = 257, w = 1673, h = 2718 + Box[287]: x = 324, y = 0, w = 1626, h = 3042 + Box[288]: x = 807, y = 257, w = 1677, h = 2718 + Box[289]: x = 347, y = 0, w = 1603, h = 3042 + Box[290]: x = 811, y = 257, w = 1681, h = 2718 + Box[291]: x = 304, y = 0, w = 1650, h = 3042 + Box[292]: x = 811, y = 261, w = 1681, h = 2718 + Box[293]: x = 308, y = 0, w = 1650, h = 3038 + Box[294]: x = 776, y = 257, w = 1716, h = 2703 + Box[295]: x = 304, y = 0, w = 2258, h = 3034 + Box[296]: x = 285, y = 39, w = 2168, h = 2952 + Box[297]: x = 530, y = 0, w = 1147, h = 3061 + Box[298]: x = 94, y = 39, w = 2036, h = 2976 + Box[299]: x = 0, y = 0, w = 0, h = 0 diff --git a/leptonica/prog/boxap3.ba b/leptonica/prog/boxap3.ba new file mode 100644 index 00000000..f5068f8f --- /dev/null +++ b/leptonica/prog/boxap3.ba @@ -0,0 +1,15 @@ + +Boxa Version 2 +Number of boxes = 12 + Box[0]: x = 75, y = 58, w = 2093, h = 2747 + Box[1]: x = 162, y = 12, w = 1550, h = 2510 + Box[2]: x = 69, y = 58, w = 2087, h = 2764 + Box[3]: x = 168, y = 17, w = 1550, h = 2510 + Box[4]: x = 75, y = 58, w = 2087, h = 2619 + Box[5]: x = 168, y = 12, w = 1544, h = 2515 + Box[6]: x = 69, y = 58, w = 2267, h = 2648 + Box[7]: x = 578, y = 17, w = 1151, h = 2510 + Box[8]: x = 81, y = 40, w = 1827, h = 2770 + Box[9]: x = 0, y = 0, w = 0, h = 0 + Box[10]: x = 0, y = 0, w = 0, h = 0 + Box[11]: x = 0, y = 0, w = 0, h = 0 diff --git a/leptonica/prog/boxap4.ba b/leptonica/prog/boxap4.ba new file mode 100644 index 00000000..1df4206d --- /dev/null +++ b/leptonica/prog/boxap4.ba @@ -0,0 +1,53 @@ + +Boxa Version 2 +Number of boxes = 50 + Box[0]: x = 0, y = 0, w = 0, h = 0 + Box[1]: x = 0, y = 0, w = 0, h = 0 + Box[2]: x = 0, y = 0, w = 0, h = 0 + Box[3]: x = 0, y = 0, w = 0, h = 0 + Box[4]: x = 0, y = 0, w = 0, h = 0 + Box[5]: x = 346, y = 0, w = 2437, h = 3598 + Box[6]: x = 39, y = 39, w = 2433, h = 3776 + Box[7]: x = 354, y = 47, w = 2390, h = 3571 + Box[8]: x = 75, y = 39, w = 2417, h = 3724 + Box[9]: x = 394, y = 24, w = 2331, h = 3622 + Box[10]: x = 75, y = 39, w = 2413, h = 3724 + Box[11]: x = 382, y = 28, w = 2346, h = 3610 + Box[12]: x = 75, y = 39, w = 2476, h = 3736 + Box[13]: x = 358, y = 31, w = 2370, h = 3606 + Box[14]: x = 75, y = 39, w = 2449, h = 3736 + Box[15]: x = 327, y = 39, w = 2394, h = 3598 + Box[16]: x = 75, y = 39, w = 2457, h = 3740 + Box[17]: x = 0, y = 43, w = 2724, h = 3610 + Box[18]: x = 79, y = 39, w = 2472, h = 3732 + Box[19]: x = 350, y = 43, w = 2374, h = 3606 + Box[20]: x = 79, y = 39, w = 2878, h = 3728 + Box[21]: x = 354, y = 43, w = 2374, h = 3606 + Box[22]: x = 87, y = 39, w = 2441, h = 3720 + Box[23]: x = 354, y = 47, w = 2535, h = 3602 + Box[24]: x = 87, y = 39, w = 2453, h = 3713 + Box[25]: x = 335, y = 39, w = 2394, h = 3606 + Box[26]: x = 91, y = 39, w = 2453, h = 3701 + Box[27]: x = 362, y = 39, w = 2366, h = 3606 + Box[28]: x = 98, y = 39, w = 2441, h = 3713 + Box[29]: x = 378, y = 39, w = 2335, h = 3602 + Box[30]: x = 102, y = 39, w = 2429, h = 3724 + Box[31]: x = 350, y = 39, w = 2374, h = 3602 + Box[32]: x = 98, y = 39, w = 2445, h = 3717 + Box[33]: x = 358, y = 43, w = 2366, h = 3606 + Box[34]: x = 110, y = 39, w = 2445, h = 3720 + Box[35]: x = 343, y = 39, w = 2386, h = 3606 + Box[36]: x = 130, y = 39, w = 2421, h = 3717 + Box[37]: x = 366, y = 43, w = 2362, h = 3606 + Box[38]: x = 122, y = 39, w = 2429, h = 3713 + Box[39]: x = 370, y = 47, w = 2366, h = 3606 + Box[40]: x = 138, y = 39, w = 2417, h = 3713 + Box[41]: x = 256, y = 47, w = 2476, h = 3606 + Box[42]: x = 138, y = 39, w = 2417, h = 3720 + Box[43]: x = 287, y = 43, w = 2449, h = 3610 + Box[44]: x = 134, y = 39, w = 2421, h = 3717 + Box[45]: x = 366, y = 43, w = 2350, h = 3587 + Box[46]: x = 142, y = 39, w = 2421, h = 3709 + Box[47]: x = 374, y = 43, w = 2350, h = 3594 + Box[48]: x = 232, y = 39, w = 2327, h = 3709 + Box[49]: x = 283, y = 47, w = 2441, h = 3594 diff --git a/leptonica/prog/boxap5.ba b/leptonica/prog/boxap5.ba new file mode 100644 index 00000000..fd600b88 --- /dev/null +++ b/leptonica/prog/boxap5.ba @@ -0,0 +1,553 @@ + +Boxa Version 2 +Number of boxes = 550 + Box[0]: x = 0, y = 0, w = 0, h = 0 + Box[1]: x = 0, y = 0, w = 0, h = 0 + Box[2]: x = 0, y = 0, w = 0, h = 0 + Box[3]: x = 0, y = 0, w = 0, h = 0 + Box[4]: x = 0, y = 0, w = 0, h = 0 + Box[5]: x = 0, y = 0, w = 0, h = 0 + Box[6]: x = 0, y = 0, w = 0, h = 0 + Box[7]: x = 0, y = 0, w = 2521, h = 3394 + Box[8]: x = 1141, y = 0, w = 1444, h = 3627 + Box[9]: x = 623, y = 111, w = 1846, h = 3284 + Box[10]: x = 0, y = 99, w = 1985, h = 3458 + Box[11]: x = 442, y = 128, w = 2026, h = 3266 + Box[12]: x = 0, y = 99, w = 1950, h = 3458 + Box[13]: x = 442, y = 128, w = 2020, h = 3266 + Box[14]: x = 0, y = 128, w = 2585, h = 3429 + Box[15]: x = 885, y = 122, w = 1578, h = 3272 + Box[16]: x = 914, y = 122, w = 1386, h = 3429 + Box[17]: x = 146, y = 116, w = 2317, h = 3278 + Box[18]: x = 902, y = 128, w = 1397, h = 3429 + Box[19]: x = 116, y = 116, w = 2341, h = 3278 + Box[20]: x = 0, y = 128, w = 2585, h = 3429 + Box[21]: x = 868, y = 111, w = 1589, h = 3284 + Box[22]: x = 932, y = 134, w = 1485, h = 3423 + Box[23]: x = 99, y = 111, w = 2358, h = 3284 + Box[24]: x = 926, y = 111, w = 1409, h = 1607 + Box[25]: x = 105, y = 105, w = 2341, h = 3290 + Box[26]: x = 769, y = 140, w = 1700, h = 3412 + Box[27]: x = 111, y = 99, w = 2323, h = 3295 + Box[28]: x = 111, y = 58, w = 2341, h = 3435 + Box[29]: x = 169, y = 111, w = 2335, h = 3284 + Box[30]: x = 128, y = 58, w = 2341, h = 3429 + Box[31]: x = 227, y = 111, w = 2271, h = 3290 + Box[32]: x = 1071, y = 87, w = 1386, h = 3406 + Box[33]: x = 215, y = 111, w = 2288, h = 3290 + Box[34]: x = 93, y = 140, w = 2538, h = 3412 + Box[35]: x = 920, y = 140, w = 1566, h = 3260 + Box[36]: x = 186, y = 140, w = 2282, h = 3412 + Box[37]: x = 215, y = 128, w = 2282, h = 3272 + Box[38]: x = 192, y = 146, w = 2276, h = 3406 + Box[39]: x = 192, y = 105, w = 2306, h = 3295 + Box[40]: x = 47, y = 151, w = 2579, h = 3400 + Box[41]: x = 897, y = 122, w = 1589, h = 3278 + Box[42]: x = 47, y = 151, w = 2573, h = 3400 + Box[43]: x = 215, y = 128, w = 2276, h = 3272 + Box[44]: x = 175, y = 58, w = 2410, h = 3423 + Box[45]: x = 908, y = 0, w = 1624, h = 3389 + Box[46]: x = 93, y = 58, w = 2341, h = 3458 + Box[47]: x = 186, y = 12, w = 2323, h = 3406 + Box[48]: x = 116, y = 58, w = 2341, h = 3470 + Box[49]: x = 210, y = 6, w = 2323, h = 3412 + Box[50]: x = 134, y = 58, w = 2352, h = 3464 + Box[51]: x = 210, y = 0, w = 2323, h = 3423 + Box[52]: x = 134, y = 58, w = 2352, h = 3464 + Box[53]: x = 204, y = 0, w = 2317, h = 3412 + Box[54]: x = 146, y = 58, w = 2335, h = 3464 + Box[55]: x = 221, y = 0, w = 2282, h = 3418 + Box[56]: x = 122, y = 58, w = 2358, h = 3464 + Box[57]: x = 210, y = 0, w = 2300, h = 3371 + Box[58]: x = 146, y = 58, w = 2335, h = 3458 + Box[59]: x = 210, y = 0, w = 2294, h = 3371 + Box[60]: x = 134, y = 58, w = 2341, h = 3464 + Box[61]: x = 210, y = 0, w = 2306, h = 3389 + Box[62]: x = 140, y = 58, w = 2341, h = 3464 + Box[63]: x = 215, y = 0, w = 2300, h = 3383 + Box[64]: x = 128, y = 58, w = 2300, h = 3464 + Box[65]: x = 227, y = 0, w = 2288, h = 3400 + Box[66]: x = 64, y = 58, w = 2405, h = 3464 + Box[67]: x = 215, y = 12, w = 2323, h = 3412 + Box[68]: x = 35, y = 58, w = 2434, h = 3458 + Box[69]: x = 204, y = 6, w = 2346, h = 3412 + Box[70]: x = 76, y = 58, w = 2393, h = 3458 + Box[71]: x = 204, y = 0, w = 2329, h = 3412 + Box[72]: x = 41, y = 58, w = 2416, h = 3453 + Box[73]: x = 215, y = 12, w = 2346, h = 3406 + Box[74]: x = 41, y = 58, w = 2422, h = 3453 + Box[75]: x = 221, y = 0, w = 2358, h = 3418 + Box[76]: x = 151, y = 0, w = 2405, h = 3546 + Box[77]: x = 215, y = 0, w = 2306, h = 3453 + Box[78]: x = 0, y = 0, w = 2480, h = 3546 + Box[79]: x = 0, y = 0, w = 2521, h = 3406 + Box[80]: x = 1153, y = 58, w = 1432, h = 3488 + Box[81]: x = 146, y = 279, w = 1718, h = 3144 + Box[82]: x = 565, y = 58, w = 1817, h = 3488 + Box[83]: x = 157, y = 0, w = 1752, h = 3324 + Box[84]: x = 635, y = 58, w = 1799, h = 3488 + Box[85]: x = 198, y = 12, w = 2370, h = 3418 + Box[86]: x = 0, y = 58, w = 2428, h = 3400 + Box[87]: x = 163, y = 6, w = 2410, h = 3429 + Box[88]: x = 0, y = 58, w = 2422, h = 3412 + Box[89]: x = 169, y = 6, w = 2405, h = 3429 + Box[90]: x = 0, y = 58, w = 2410, h = 3406 + Box[91]: x = 169, y = 0, w = 2405, h = 3365 + Box[92]: x = 0, y = 58, w = 2410, h = 3383 + Box[93]: x = 169, y = 12, w = 2405, h = 3423 + Box[94]: x = 0, y = 58, w = 2410, h = 3389 + Box[95]: x = 175, y = 0, w = 1589, h = 3441 + Box[96]: x = 0, y = 58, w = 2405, h = 3383 + Box[97]: x = 175, y = 12, w = 2393, h = 3423 + Box[98]: x = 41, y = 58, w = 2364, h = 3389 + Box[99]: x = 180, y = 0, w = 2387, h = 3354 + Box[100]: x = 0, y = 58, w = 2405, h = 3423 + Box[101]: x = 180, y = 0, w = 2387, h = 3354 + Box[102]: x = 47, y = 58, w = 2358, h = 3423 + Box[103]: x = 186, y = 0, w = 2381, h = 3348 + Box[104]: x = 163, y = 58, w = 2311, h = 3313 + Box[105]: x = 221, y = 0, w = 2346, h = 3348 + Box[106]: x = 35, y = 58, w = 2387, h = 3400 + Box[107]: x = 180, y = 0, w = 2352, h = 3330 + Box[108]: x = 70, y = 58, w = 2341, h = 3359 + Box[109]: x = 204, y = 0, w = 2364, h = 3324 + Box[110]: x = 93, y = 58, w = 2381, h = 3418 + Box[111]: x = 221, y = 0, w = 1531, h = 3371 + Box[112]: x = 99, y = 58, w = 2381, h = 3336 + Box[113]: x = 192, y = 0, w = 2341, h = 3324 + Box[114]: x = 204, y = 58, w = 2224, h = 3418 + Box[115]: x = 180, y = 0, w = 2195, h = 3330 + Box[116]: x = 41, y = 58, w = 2381, h = 3342 + Box[117]: x = 169, y = 0, w = 1747, h = 3319 + Box[118]: x = 716, y = 58, w = 1752, h = 3482 + Box[119]: x = 239, y = 0, w = 2317, h = 3330 + Box[120]: x = 169, y = 58, w = 2317, h = 3348 + Box[121]: x = 239, y = 0, w = 2323, h = 3342 + Box[122]: x = 175, y = 58, w = 2306, h = 3319 + Box[123]: x = 215, y = 0, w = 2335, h = 3348 + Box[124]: x = 186, y = 58, w = 2300, h = 3307 + Box[125]: x = 221, y = 0, w = 2335, h = 3336 + Box[126]: x = 163, y = 58, w = 2323, h = 3324 + Box[127]: x = 204, y = 0, w = 2352, h = 3336 + Box[128]: x = 47, y = 58, w = 2364, h = 3307 + Box[129]: x = 175, y = 0, w = 2341, h = 3307 + Box[130]: x = 326, y = 58, w = 2148, h = 3354 + Box[131]: x = 198, y = 0, w = 2201, h = 3348 + Box[132]: x = 87, y = 58, w = 2393, h = 3342 + Box[133]: x = 204, y = 0, w = 1718, h = 3330 + Box[134]: x = 734, y = 58, w = 1735, h = 3476 + Box[135]: x = 233, y = 0, w = 2294, h = 3354 + Box[136]: x = 58, y = 58, w = 2364, h = 3313 + Box[137]: x = 180, y = 0, w = 2381, h = 3342 + Box[138]: x = 52, y = 58, w = 2364, h = 3330 + Box[139]: x = 198, y = 0, w = 2358, h = 3336 + Box[140]: x = 64, y = 58, w = 2346, h = 3319 + Box[141]: x = 186, y = 0, w = 2370, h = 3324 + Box[142]: x = 58, y = 58, w = 2370, h = 3336 + Box[143]: x = 180, y = 0, w = 2381, h = 3336 + Box[144]: x = 58, y = 58, w = 2364, h = 3319 + Box[145]: x = 180, y = 0, w = 2375, h = 3348 + Box[146]: x = 70, y = 58, w = 2346, h = 3336 + Box[147]: x = 192, y = 0, w = 2364, h = 3324 + Box[148]: x = 76, y = 58, w = 2341, h = 3313 + Box[149]: x = 180, y = 0, w = 2370, h = 3307 + Box[150]: x = 52, y = 58, w = 2375, h = 3330 + Box[151]: x = 186, y = 0, w = 2370, h = 3336 + Box[152]: x = 58, y = 58, w = 2364, h = 3301 + Box[153]: x = 198, y = 0, w = 2352, h = 3330 + Box[154]: x = 52, y = 58, w = 2381, h = 3313 + Box[155]: x = 180, y = 0, w = 2375, h = 3330 + Box[156]: x = 52, y = 58, w = 2387, h = 3319 + Box[157]: x = 192, y = 0, w = 2364, h = 3336 + Box[158]: x = 35, y = 58, w = 2410, h = 3330 + Box[159]: x = 192, y = 0, w = 2375, h = 3319 + Box[160]: x = 35, y = 58, w = 2410, h = 3336 + Box[161]: x = 198, y = 0, w = 2358, h = 3324 + Box[162]: x = 35, y = 58, w = 2364, h = 3324 + Box[163]: x = 175, y = 0, w = 2341, h = 3423 + Box[164]: x = 0, y = 0, w = 2474, h = 3534 + Box[165]: x = 821, y = 116, w = 1001, h = 3324 + Box[166]: x = 0, y = 58, w = 2591, h = 3476 + Box[167]: x = 0, y = 0, w = 2515, h = 3423 + Box[168]: x = 710, y = 58, w = 1642, h = 3429 + Box[169]: x = 134, y = 0, w = 2405, h = 3394 + Box[170]: x = 0, y = 58, w = 2375, h = 3330 + Box[171]: x = 111, y = 0, w = 2428, h = 3371 + Box[172]: x = 0, y = 58, w = 2364, h = 3330 + Box[173]: x = 111, y = 0, w = 2428, h = 3330 + Box[174]: x = 0, y = 58, w = 2038, h = 3336 + Box[175]: x = 221, y = 0, w = 2317, h = 3365 + Box[176]: x = 0, y = 58, w = 2370, h = 3330 + Box[177]: x = 111, y = 0, w = 2422, h = 3336 + Box[178]: x = 0, y = 58, w = 2375, h = 3330 + Box[179]: x = 105, y = 0, w = 2405, h = 3359 + Box[180]: x = 0, y = 58, w = 1950, h = 3324 + Box[181]: x = 617, y = 0, w = 1916, h = 3324 + Box[182]: x = 0, y = 58, w = 2393, h = 3348 + Box[183]: x = 105, y = 0, w = 2399, h = 3354 + Box[184]: x = 0, y = 58, w = 2364, h = 3336 + Box[185]: x = 0, y = 0, w = 2498, h = 3354 + Box[186]: x = 0, y = 58, w = 2370, h = 3470 + Box[187]: x = 111, y = 0, w = 2381, h = 3348 + Box[188]: x = 0, y = 58, w = 2009, h = 3307 + Box[189]: x = 530, y = 0, w = 1962, h = 3429 + Box[190]: x = 0, y = 58, w = 2370, h = 3348 + Box[191]: x = 128, y = 0, w = 2358, h = 3371 + Box[192]: x = 0, y = 58, w = 2358, h = 3470 + Box[193]: x = 146, y = 0, w = 2346, h = 3330 + Box[194]: x = 47, y = 58, w = 2323, h = 3324 + Box[195]: x = 122, y = 0, w = 2370, h = 3324 + Box[196]: x = 52, y = 58, w = 2335, h = 3342 + Box[197]: x = 146, y = 0, w = 2329, h = 3336 + Box[198]: x = 52, y = 58, w = 2352, h = 3313 + Box[199]: x = 233, y = 0, w = 2247, h = 3365 + Box[200]: x = 52, y = 58, w = 2358, h = 3470 + Box[201]: x = 157, y = 0, w = 2370, h = 3324 + Box[202]: x = 41, y = 58, w = 2381, h = 3307 + Box[203]: x = 111, y = 0, w = 2410, h = 3319 + Box[204]: x = 41, y = 58, w = 2387, h = 3301 + Box[205]: x = 111, y = 0, w = 2416, h = 3365 + Box[206]: x = 35, y = 58, w = 2375, h = 3319 + Box[207]: x = 116, y = 0, w = 1246, h = 3365 + Box[208]: x = 35, y = 58, w = 2387, h = 3319 + Box[209]: x = 640, y = 0, w = 1834, h = 3359 + Box[210]: x = 507, y = 58, w = 1846, h = 3307 + Box[211]: x = 29, y = 0, w = 2399, h = 3336 + Box[212]: x = 0, y = 58, w = 2370, h = 3290 + Box[213]: x = 64, y = 0, w = 2416, h = 3342 + Box[214]: x = 35, y = 58, w = 2405, h = 3295 + Box[215]: x = 76, y = 0, w = 1205, h = 3371 + Box[216]: x = 0, y = 58, w = 2346, h = 3464 + Box[217]: x = 70, y = 0, w = 2375, h = 3342 + Box[218]: x = 0, y = 58, w = 2352, h = 3464 + Box[219]: x = 76, y = 0, w = 2405, h = 3348 + Box[220]: x = 0, y = 58, w = 2341, h = 3464 + Box[221]: x = 76, y = 0, w = 2393, h = 3354 + Box[222]: x = 536, y = 58, w = 1805, h = 3319 + Box[223]: x = 76, y = 0, w = 1490, h = 3365 + Box[224]: x = 0, y = 58, w = 2352, h = 3464 + Box[225]: x = 70, y = 0, w = 2405, h = 3359 + Box[226]: x = 0, y = 58, w = 2451, h = 3295 + Box[227]: x = 128, y = 0, w = 1263, h = 3365 + Box[228]: x = 35, y = 58, w = 2428, h = 3307 + Box[229]: x = 128, y = 0, w = 2405, h = 3324 + Box[230]: x = 0, y = 58, w = 2457, h = 3295 + Box[231]: x = 134, y = 0, w = 2399, h = 3348 + Box[232]: x = 35, y = 58, w = 2410, h = 3290 + Box[233]: x = 146, y = 0, w = 2387, h = 3324 + Box[234]: x = 0, y = 58, w = 2428, h = 3464 + Box[235]: x = 116, y = 0, w = 2422, h = 3342 + Box[236]: x = 0, y = 0, w = 2364, h = 3522 + Box[237]: x = 0, y = 41, w = 1263, h = 3394 + Box[238]: x = 0, y = 82, w = 2428, h = 3441 + Box[239]: x = 99, y = 151, w = 2276, h = 3284 + Box[240]: x = 0, y = 58, w = 2393, h = 3377 + Box[241]: x = 128, y = 0, w = 2300, h = 3389 + Box[242]: x = 146, y = 41, w = 2440, h = 2084 + Box[243]: x = 0, y = 0, w = 2573, h = 3383 + Box[244]: x = 0, y = 0, w = 1968, h = 3517 + Box[245]: x = 0, y = 0, w = 1124, h = 3458 + Box[246]: x = 1392, y = 41, w = 1141, h = 3476 + Box[247]: x = 116, y = 0, w = 2236, h = 3389 + Box[248]: x = 0, y = 58, w = 2346, h = 3389 + Box[249]: x = 93, y = 0, w = 2253, h = 3389 + Box[250]: x = 0, y = 58, w = 2375, h = 3295 + Box[251]: x = 221, y = 0, w = 2131, h = 3394 + Box[252]: x = 0, y = 0, w = 2591, h = 3517 + Box[253]: x = 76, y = 0, w = 1048, h = 3458 + Box[254]: x = 1467, y = 41, w = 926, h = 2940 + Box[255]: x = 140, y = 17, w = 2183, h = 3412 + Box[256]: x = 0, y = 58, w = 2585, h = 3458 + Box[257]: x = 0, y = 0, w = 1118, h = 3458 + Box[258]: x = 1409, y = 41, w = 978, h = 3476 + Box[259]: x = 105, y = 0, w = 2381, h = 3354 + Box[260]: x = 396, y = 76, w = 2259, h = 3441 + Box[261]: x = 0, y = 0, w = 1130, h = 3458 + Box[262]: x = 0, y = 58, w = 2393, h = 3470 + Box[263]: x = 122, y = 0, w = 2381, h = 3383 + Box[264]: x = 0, y = 0, w = 1857, h = 3517 + Box[265]: x = 0, y = 0, w = 0, h = 0 + Box[266]: x = 0, y = 58, w = 2393, h = 3482 + Box[267]: x = 134, y = 82, w = 2183, h = 3330 + Box[268]: x = 76, y = 146, w = 2311, h = 3371 + Box[269]: x = 105, y = 111, w = 2195, h = 3330 + Box[270]: x = 390, y = 58, w = 2265, h = 3458 + Box[271]: x = 0, y = 0, w = 2480, h = 3447 + Box[272]: x = 1048, y = 76, w = 1549, h = 3441 + Box[273]: x = 0, y = 12, w = 2527, h = 3377 + Box[274]: x = 221, y = 58, w = 2131, h = 3458 + Box[275]: x = 116, y = 105, w = 1188, h = 3342 + Box[276]: x = 76, y = 140, w = 2358, h = 3377 + Box[277]: x = 163, y = 146, w = 2166, h = 3301 + Box[278]: x = 64, y = 128, w = 2335, h = 3389 + Box[279]: x = 116, y = 111, w = 2195, h = 3336 + Box[280]: x = 64, y = 128, w = 2323, h = 3389 + Box[281]: x = 146, y = 111, w = 2160, h = 3336 + Box[282]: x = 41, y = 134, w = 2352, h = 3383 + Box[283]: x = 140, y = 116, w = 2189, h = 3330 + Box[284]: x = 70, y = 122, w = 2329, h = 3394 + Box[285]: x = 140, y = 134, w = 2352, h = 3313 + Box[286]: x = 58, y = 116, w = 2329, h = 3394 + Box[287]: x = 215, y = 116, w = 2102, h = 3330 + Box[288]: x = 210, y = 116, w = 1601, h = 3394 + Box[289]: x = 111, y = 134, w = 2224, h = 3313 + Box[290]: x = 70, y = 116, w = 2346, h = 3394 + Box[291]: x = 111, y = 116, w = 2207, h = 3330 + Box[292]: x = 70, y = 111, w = 2329, h = 3400 + Box[293]: x = 116, y = 29, w = 2207, h = 3423 + Box[294]: x = 70, y = 111, w = 2311, h = 3400 + Box[295]: x = 122, y = 93, w = 1688, h = 3354 + Box[296]: x = 82, y = 111, w = 2294, h = 3400 + Box[297]: x = 128, y = 87, w = 2341, h = 3359 + Box[298]: x = 70, y = 111, w = 2335, h = 3400 + Box[299]: x = 116, y = 93, w = 2352, h = 3354 + Box[300]: x = 76, y = 105, w = 2323, h = 3406 + Box[301]: x = 146, y = 134, w = 2183, h = 3319 + Box[302]: x = 58, y = 105, w = 2346, h = 3406 + Box[303]: x = 111, y = 87, w = 2236, h = 3435 + Box[304]: x = 70, y = 99, w = 2242, h = 3412 + Box[305]: x = 128, y = 122, w = 2201, h = 3330 + Box[306]: x = 82, y = 105, w = 2323, h = 3406 + Box[307]: x = 128, y = 17, w = 2346, h = 3365 + Box[308]: x = 82, y = 105, w = 2335, h = 3406 + Box[309]: x = 140, y = 0, w = 2346, h = 3464 + Box[310]: x = 58, y = 99, w = 2364, h = 3412 + Box[311]: x = 134, y = 140, w = 2393, h = 3313 + Box[312]: x = 221, y = 122, w = 2207, h = 3389 + Box[313]: x = 111, y = 0, w = 2393, h = 3453 + Box[314]: x = 0, y = 58, w = 2591, h = 3453 + Box[315]: x = 0, y = 0, w = 2504, h = 3453 + Box[316]: x = 0, y = 58, w = 2201, h = 3453 + Box[317]: x = 17, y = 0, w = 2515, h = 3453 + Box[318]: x = 0, y = 128, w = 2434, h = 3383 + Box[319]: x = 0, y = 134, w = 2527, h = 3319 + Box[320]: x = 52, y = 151, w = 2352, h = 3354 + Box[321]: x = 111, y = 146, w = 2311, h = 3307 + Box[322]: x = 344, y = 146, w = 2026, h = 3359 + Box[323]: x = 70, y = 134, w = 2358, h = 3319 + Box[324]: x = 99, y = 151, w = 2323, h = 3354 + Box[325]: x = 76, y = 134, w = 2358, h = 3319 + Box[326]: x = 128, y = 151, w = 2306, h = 3354 + Box[327]: x = 291, y = 116, w = 2038, h = 3336 + Box[328]: x = 93, y = 146, w = 2323, h = 3359 + Box[329]: x = 99, y = 151, w = 2323, h = 3301 + Box[330]: x = 1287, y = 169, w = 1287, h = 3336 + Box[331]: x = 291, y = 151, w = 2049, h = 3307 + Box[332]: x = 157, y = 105, w = 1624, h = 3400 + Box[333]: x = 0, y = 134, w = 2428, h = 3324 + Box[334]: x = 239, y = 122, w = 2375, h = 3383 + Box[335]: x = 0, y = 140, w = 2451, h = 3319 + Box[336]: x = 1293, y = 82, w = 1112, h = 3423 + Box[337]: x = 169, y = 116, w = 2288, h = 3342 + Box[338]: x = 151, y = 140, w = 2463, h = 3365 + Box[339]: x = 0, y = 116, w = 1589, h = 3342 + Box[340]: x = 128, y = 0, w = 2486, h = 3505 + Box[341]: x = 600, y = 0, w = 1846, h = 3458 + Box[342]: x = 151, y = 0, w = 2224, h = 3505 + Box[343]: x = 99, y = 0, w = 2399, h = 3458 + Box[344]: x = 99, y = 70, w = 2329, h = 3435 + Box[345]: x = 204, y = 122, w = 2020, h = 3336 + Box[346]: x = 349, y = 134, w = 2003, h = 3371 + Box[347]: x = 198, y = 122, w = 2014, h = 3336 + Box[348]: x = 367, y = 134, w = 1980, h = 3371 + Box[349]: x = 175, y = 116, w = 2009, h = 3342 + Box[350]: x = 361, y = 134, w = 1991, h = 3371 + Box[351]: x = 175, y = 116, w = 2038, h = 3342 + Box[352]: x = 122, y = 134, w = 2311, h = 3371 + Box[353]: x = 175, y = 111, w = 2224, h = 3348 + Box[354]: x = 105, y = 122, w = 2230, h = 3383 + Box[355]: x = 175, y = 93, w = 2212, h = 3365 + Box[356]: x = 332, y = 116, w = 1607, h = 3389 + Box[357]: x = 169, y = 116, w = 2014, h = 3342 + Box[358]: x = 128, y = 128, w = 2358, h = 3377 + Box[359]: x = 163, y = 111, w = 2218, h = 3348 + Box[360]: x = 122, y = 128, w = 2218, h = 3377 + Box[361]: x = 180, y = 116, w = 1368, h = 3348 + Box[362]: x = 355, y = 122, w = 1572, h = 3377 + Box[363]: x = 227, y = 111, w = 2009, h = 3354 + Box[364]: x = 344, y = 122, w = 1991, h = 3377 + Box[365]: x = 233, y = 105, w = 2038, h = 3359 + Box[366]: x = 326, y = 122, w = 2003, h = 3377 + Box[367]: x = 192, y = 111, w = 2038, h = 3354 + Box[368]: x = 99, y = 116, w = 2288, h = 3383 + Box[369]: x = 180, y = 99, w = 2224, h = 3365 + Box[370]: x = 309, y = 122, w = 2148, h = 3377 + Box[371]: x = 0, y = 111, w = 2457, h = 3354 + Box[372]: x = 291, y = 122, w = 2038, h = 3377 + Box[373]: x = 221, y = 116, w = 2049, h = 3348 + Box[374]: x = 291, y = 122, w = 2044, h = 3377 + Box[375]: x = 122, y = 140, w = 2125, h = 3324 + Box[376]: x = 361, y = 128, w = 1956, h = 3371 + Box[377]: x = 99, y = 0, w = 2399, h = 3464 + Box[378]: x = 0, y = 175, w = 2597, h = 3324 + Box[379]: x = 0, y = 58, w = 2498, h = 3406 + Box[380]: x = 0, y = 111, w = 2224, h = 3389 + Box[381]: x = 0, y = 0, w = 2492, h = 3464 + Box[382]: x = 0, y = 58, w = 2597, h = 3441 + Box[383]: x = 0, y = 0, w = 2492, h = 3464 + Box[384]: x = 0, y = 58, w = 2288, h = 3383 + Box[385]: x = 82, y = 0, w = 2451, h = 3464 + Box[386]: x = 0, y = 58, w = 2276, h = 3383 + Box[387]: x = 12, y = 0, w = 2457, h = 3464 + Box[388]: x = 93, y = 58, w = 2504, h = 3441 + Box[389]: x = 0, y = 0, w = 2533, h = 3464 + Box[390]: x = 0, y = 58, w = 2306, h = 3383 + Box[391]: x = 76, y = 0, w = 2416, h = 3470 + Box[392]: x = 70, y = 58, w = 2207, h = 3406 + Box[393]: x = 116, y = 23, w = 2399, h = 3435 + Box[394]: x = 0, y = 58, w = 2346, h = 3383 + Box[395]: x = 87, y = 29, w = 2410, h = 3435 + Box[396]: x = 17, y = 0, w = 2335, h = 3406 + Box[397]: x = 87, y = 23, w = 2405, h = 3441 + Box[398]: x = 0, y = 58, w = 2375, h = 3435 + Box[399]: x = 76, y = 23, w = 2434, h = 3441 + Box[400]: x = 29, y = 58, w = 2335, h = 3394 + Box[401]: x = 87, y = 17, w = 2399, h = 3441 + Box[402]: x = 35, y = 58, w = 2341, h = 3394 + Box[403]: x = 87, y = 29, w = 2381, h = 3441 + Box[404]: x = 0, y = 0, w = 0, h = 0 + Box[405]: x = 0, y = 35, w = 2486, h = 3447 + Box[406]: x = 169, y = 2865, w = 681, h = 378 + Box[407]: x = 0, y = 0, w = 2492, h = 3488 + Box[408]: x = 29, y = 58, w = 2346, h = 3406 + Box[409]: x = 93, y = 23, w = 2375, h = 3418 + Box[410]: x = 23, y = 116, w = 1980, h = 3383 + Box[411]: x = 122, y = 23, w = 2341, h = 3453 + Box[412]: x = 29, y = 58, w = 2317, h = 3406 + Box[413]: x = 76, y = 0, w = 2364, h = 3441 + Box[414]: x = 58, y = 99, w = 2300, h = 3400 + Box[415]: x = 6, y = 0, w = 2445, h = 3470 + Box[416]: x = 35, y = 0, w = 2341, h = 3493 + Box[417]: x = 76, y = 29, w = 2352, h = 3464 + Box[418]: x = 29, y = 58, w = 2352, h = 3412 + Box[419]: x = 70, y = 0, w = 2381, h = 3394 + Box[420]: x = 58, y = 58, w = 2329, h = 3383 + Box[421]: x = 76, y = 23, w = 2381, h = 3464 + Box[422]: x = 70, y = 58, w = 2317, h = 3389 + Box[423]: x = 99, y = 17, w = 2370, h = 3464 + Box[424]: x = 29, y = 58, w = 2341, h = 3389 + Box[425]: x = 70, y = 17, w = 2393, h = 3464 + Box[426]: x = 58, y = 58, w = 2317, h = 3412 + Box[427]: x = 76, y = 23, w = 2370, h = 3441 + Box[428]: x = 35, y = 58, w = 2335, h = 3394 + Box[429]: x = 70, y = 0, w = 2375, h = 3418 + Box[430]: x = 47, y = 58, w = 2335, h = 3394 + Box[431]: x = 70, y = 17, w = 2422, h = 3453 + Box[432]: x = 47, y = 58, w = 2329, h = 3406 + Box[433]: x = 70, y = 41, w = 2381, h = 3441 + Box[434]: x = 47, y = 58, w = 2341, h = 3406 + Box[435]: x = 70, y = 29, w = 2393, h = 3447 + Box[436]: x = 41, y = 58, w = 2358, h = 3400 + Box[437]: x = 93, y = 23, w = 2410, h = 3453 + Box[438]: x = 41, y = 58, w = 2358, h = 3389 + Box[439]: x = 76, y = 23, w = 2399, h = 3453 + Box[440]: x = 41, y = 58, w = 2387, h = 3389 + Box[441]: x = 82, y = 0, w = 2399, h = 3435 + Box[442]: x = 29, y = 58, w = 2399, h = 3394 + Box[443]: x = 58, y = 29, w = 2451, h = 3435 + Box[444]: x = 29, y = 58, w = 2393, h = 3342 + Box[445]: x = 87, y = 29, w = 2422, h = 3435 + Box[446]: x = 35, y = 58, w = 2393, h = 3400 + Box[447]: x = 64, y = 17, w = 2451, h = 3447 + Box[448]: x = 23, y = 58, w = 2422, h = 3389 + Box[449]: x = 93, y = 23, w = 2445, h = 3464 + Box[450]: x = 6, y = 58, w = 2422, h = 3330 + Box[451]: x = 111, y = 0, w = 2375, h = 3482 + Box[452]: x = 1205, y = 58, w = 1164, h = 3429 + Box[453]: x = 250, y = 35, w = 2201, h = 3418 + Box[454]: x = 186, y = 58, w = 2440, h = 3348 + Box[455]: x = 0, y = 23, w = 2364, h = 3423 + Box[456]: x = 0, y = 58, w = 2393, h = 3423 + Box[457]: x = 99, y = 6, w = 2410, h = 3435 + Box[458]: x = 0, y = 58, w = 2626, h = 3418 + Box[459]: x = 0, y = 12, w = 2352, h = 3441 + Box[460]: x = 0, y = 58, w = 2632, h = 3348 + Box[461]: x = 489, y = 6, w = 2020, h = 3441 + Box[462]: x = 122, y = 58, w = 2218, h = 3377 + Box[463]: x = 111, y = 582, w = 2311, h = 2381 + Box[464]: x = 198, y = 547, w = 2416, h = 2346 + Box[465]: x = 0, y = 559, w = 2399, h = 2399 + Box[466]: x = 233, y = 541, w = 1357, h = 2341 + Box[467]: x = 332, y = 571, w = 1176, h = 2405 + Box[468]: x = 221, y = 559, w = 2178, h = 2335 + Box[469]: x = 157, y = 0, w = 2230, h = 3493 + Box[470]: x = 239, y = 0, w = 2160, h = 3499 + Box[471]: x = 163, y = 0, w = 2224, h = 3493 + Box[472]: x = 239, y = 1531, w = 1403, h = 1333 + Box[473]: x = 0, y = 140, w = 2381, h = 3348 + Box[474]: x = 291, y = 565, w = 2014, h = 2288 + Box[475]: x = 0, y = 0, w = 0, h = 0 + Box[476]: x = 285, y = 623, w = 2102, h = 2253 + Box[477]: x = 146, y = 87, w = 2323, h = 3458 + Box[478]: x = 140, y = 58, w = 2276, h = 3348 + Box[479]: x = 116, y = 29, w = 2381, h = 3482 + Box[480]: x = 338, y = 58, w = 2073, h = 3377 + Box[481]: x = 146, y = 23, w = 2306, h = 3458 + Box[482]: x = 128, y = 58, w = 2201, h = 3377 + Box[483]: x = 82, y = 29, w = 2201, h = 3464 + Box[484]: x = 326, y = 58, w = 2079, h = 3377 + Box[485]: x = 146, y = 17, w = 2300, h = 3470 + Box[486]: x = 105, y = 58, w = 2247, h = 3371 + Box[487]: x = 70, y = 12, w = 2195, h = 3476 + Box[488]: x = 111, y = 58, w = 2242, h = 3371 + Box[489]: x = 76, y = 12, w = 2189, h = 3476 + Box[490]: x = 111, y = 58, w = 2300, h = 3348 + Box[491]: x = 105, y = 6, w = 2352, h = 3453 + Box[492]: x = 99, y = 58, w = 2306, h = 3354 + Box[493]: x = 105, y = 12, w = 2335, h = 3476 + Box[494]: x = 87, y = 58, w = 2317, h = 3354 + Box[495]: x = 93, y = 0, w = 2341, h = 3488 + Box[496]: x = 105, y = 58, w = 2288, h = 3307 + Box[497]: x = 116, y = 0, w = 2346, h = 3447 + Box[498]: x = 87, y = 58, w = 2253, h = 3348 + Box[499]: x = 70, y = 0, w = 2393, h = 3488 + Box[500]: x = 140, y = 58, w = 2276, h = 3435 + Box[501]: x = 99, y = 0, w = 2154, h = 3482 + Box[502]: x = 58, y = 58, w = 2341, h = 3319 + Box[503]: x = 64, y = 0, w = 1950, h = 3499 + Box[504]: x = 87, y = 58, w = 2311, h = 3423 + Box[505]: x = 111, y = 23, w = 2387, h = 3476 + Box[506]: x = 99, y = 58, w = 2306, h = 3423 + Box[507]: x = 116, y = 17, w = 2387, h = 3476 + Box[508]: x = 111, y = 58, w = 2294, h = 3435 + Box[509]: x = 122, y = 17, w = 2381, h = 3476 + Box[510]: x = 87, y = 58, w = 2311, h = 3423 + Box[511]: x = 111, y = 35, w = 2387, h = 3458 + Box[512]: x = 128, y = 58, w = 2276, h = 3441 + Box[513]: x = 122, y = 17, w = 2370, h = 3488 + Box[514]: x = 76, y = 58, w = 2306, h = 3429 + Box[515]: x = 111, y = 0, w = 1281, h = 3511 + Box[516]: x = 58, y = 58, w = 2317, h = 3365 + Box[517]: x = 105, y = 17, w = 2352, h = 3488 + Box[518]: x = 70, y = 58, w = 2311, h = 3429 + Box[519]: x = 111, y = 0, w = 1921, h = 3511 + Box[520]: x = 58, y = 58, w = 2317, h = 3348 + Box[521]: x = 105, y = 0, w = 2346, h = 3511 + Box[522]: x = 52, y = 58, w = 2311, h = 3423 + Box[523]: x = 105, y = 0, w = 1467, h = 3522 + Box[524]: x = 52, y = 58, w = 1723, h = 3371 + Box[525]: x = 111, y = 0, w = 1461, h = 3511 + Box[526]: x = 47, y = 58, w = 2335, h = 3418 + Box[527]: x = 105, y = 17, w = 2381, h = 3482 + Box[528]: x = 47, y = 58, w = 2323, h = 3359 + Box[529]: x = 146, y = 12, w = 2335, h = 3464 + Box[530]: x = 35, y = 58, w = 2335, h = 3359 + Box[531]: x = 151, y = 52, w = 2329, h = 3458 + Box[532]: x = 52, y = 58, w = 2335, h = 3359 + Box[533]: x = 157, y = 12, w = 2335, h = 3493 + Box[534]: x = 35, y = 58, w = 2346, h = 3324 + Box[535]: x = 157, y = 35, w = 2335, h = 3470 + Box[536]: x = 35, y = 58, w = 2358, h = 3359 + Box[537]: x = 163, y = 35, w = 2352, h = 3464 + Box[538]: x = 35, y = 58, w = 2358, h = 3365 + Box[539]: x = 157, y = 29, w = 2364, h = 3464 + Box[540]: x = 35, y = 58, w = 2364, h = 3354 + Box[541]: x = 163, y = 23, w = 2381, h = 3441 + Box[542]: x = 35, y = 58, w = 2358, h = 3324 + Box[543]: x = 163, y = 35, w = 2381, h = 3435 + Box[544]: x = 35, y = 58, w = 2358, h = 3359 + Box[545]: x = 157, y = 35, w = 2387, h = 3453 + Box[546]: x = 0, y = 58, w = 2370, h = 3365 + Box[547]: x = 134, y = 0, w = 2346, h = 3499 + Box[548]: x = 151, y = 58, w = 2160, h = 3359 + Box[549]: x = 0, y = 0, w = 0, h = 0 diff --git a/leptonica/prog/boxedpage.jpg b/leptonica/prog/boxedpage.jpg Binary files differnew file mode 100644 index 00000000..1b7030f1 --- /dev/null +++ b/leptonica/prog/boxedpage.jpg diff --git a/leptonica/prog/brev.06.75.jpg b/leptonica/prog/brev.06.75.jpg Binary files differnew file mode 100644 index 00000000..03ec00bf --- /dev/null +++ b/leptonica/prog/brev.06.75.jpg diff --git a/leptonica/prog/brev.10.75.jpg b/leptonica/prog/brev.10.75.jpg Binary files differnew file mode 100644 index 00000000..af809928 --- /dev/null +++ b/leptonica/prog/brev.10.75.jpg diff --git a/leptonica/prog/brev.14.75.jpg b/leptonica/prog/brev.14.75.jpg Binary files differnew file mode 100644 index 00000000..955e5045 --- /dev/null +++ b/leptonica/prog/brev.14.75.jpg diff --git a/leptonica/prog/brev.20.75.jpg b/leptonica/prog/brev.20.75.jpg Binary files differnew file mode 100644 index 00000000..b2c22f5b --- /dev/null +++ b/leptonica/prog/brev.20.75.jpg diff --git a/leptonica/prog/brev.36.75.jpg b/leptonica/prog/brev.36.75.jpg Binary files differnew file mode 100644 index 00000000..8f7e3cc2 --- /dev/null +++ b/leptonica/prog/brev.36.75.jpg diff --git a/leptonica/prog/brev.53.75.jpg b/leptonica/prog/brev.53.75.jpg Binary files differnew file mode 100644 index 00000000..134bccb9 --- /dev/null +++ b/leptonica/prog/brev.53.75.jpg diff --git a/leptonica/prog/brev.56.75.jpg b/leptonica/prog/brev.56.75.jpg Binary files differnew file mode 100644 index 00000000..53ad703a --- /dev/null +++ b/leptonica/prog/brev.56.75.jpg diff --git a/leptonica/prog/breviar.38.150.jpg b/leptonica/prog/breviar.38.150.jpg Binary files differnew file mode 100644 index 00000000..0a564e59 --- /dev/null +++ b/leptonica/prog/breviar.38.150.jpg diff --git a/leptonica/prog/brothers.150.jpg b/leptonica/prog/brothers.150.jpg Binary files differnew file mode 100644 index 00000000..74fb9bf0 --- /dev/null +++ b/leptonica/prog/brothers.150.jpg diff --git a/leptonica/prog/buffertest.c b/leptonica/prog/buffertest.c new file mode 100644 index 00000000..5e5d569d --- /dev/null +++ b/leptonica/prog/buffertest.c @@ -0,0 +1,114 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * buffertest.c + * + * Tests the bbuffer operations + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + +#define NBLOCKS 11 + +int main(int argc, + char **argv) +{ +char *filein, *fileout; +l_uint8 *array1, *array2, *dataout, *dataout2; +l_int32 i, blocksize, same; +size_t nbytes, nout, nout2; +L_BBUFFER *bb, *bb2; +FILE *fp; +static char mainName[] = "buffertest"; + + if (argc != 3) + return ERROR_INT(" Syntax: buffertest filein fileout", mainName, 1); + filein = argv[1]; + fileout = argv[2]; + setLeptDebugOK(1); + + if ((array1 = l_binaryRead(filein, &nbytes)) == NULL) + return ERROR_INT("array not made", mainName, 1); + lept_stderr("Bytes read from file: %lu\n", (unsigned long)nbytes); + + /* Application of byte buffer ops: compress/decompress in memory */ +#if 1 + dataout = zlibCompress(array1, nbytes, &nout); + l_binaryWrite(fileout, "w", dataout, nout); + + dataout2 = zlibUncompress(dataout, nout, &nout2); + l_binaryWrite("/tmp/dataout2", "w", dataout2, nout2); + + filesAreIdentical(filein, "/tmp/dataout2", &same); + if (same) + lept_stderr("Correct: data is the same\n"); + else + lept_stderr("Error: data is different\n"); + + lept_stderr("nbytes in = %lu, nbytes comp = %lu, nbytes uncomp = %lu\n", + (unsigned long)nbytes, (unsigned long)nout, (unsigned long)nout2); + lept_free(dataout); + lept_free(dataout2); +#endif + + /* Low-level byte buffer read/write test */ +#if 1 + bb = bbufferCreate(array1, nbytes); + bbufferRead(bb, array1, nbytes); + + array2 = (l_uint8 *)lept_calloc(2 * nbytes, sizeof(l_uint8)); + + lept_stderr(" Bytes initially in buffer: %d\n", bb->n); + + blocksize = (2 * nbytes) / NBLOCKS; + for (i = 0; i <= NBLOCKS; i++) { + bbufferWrite(bb, array2, blocksize, &nout); + lept_stderr(" block %d: wrote %lu bytes\n", i + 1, + (unsigned long)nout); + } + + lept_stderr(" Bytes left in buffer: %d\n", bb->n); + + bb2 = bbufferCreate(NULL, 0); + bbufferRead(bb2, array1, nbytes); + fp = lept_fopen(fileout, "wb"); + bbufferWriteStream(bb2, fp, nbytes, &nout); + lept_stderr(" bytes written out to fileout: %lu\n", (unsigned long)nout); + lept_fclose(fp); + + bbufferDestroy(&bb); + bbufferDestroy(&bb2); + lept_free(array2); +#endif + + lept_free(array1); + return 0; +} diff --git a/leptonica/prog/bytea_reg.c b/leptonica/prog/bytea_reg.c new file mode 100644 index 00000000..d62614ea --- /dev/null +++ b/leptonica/prog/bytea_reg.c @@ -0,0 +1,180 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * bytea_reg.c + * + * This tests the byte array utility. + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include <string.h> +#include "allheaders.h" + +int main(int argc, + char **argv) +{ +char *str1, *str2; +l_uint8 *data1, *data2; +l_int32 i, n; +size_t size1, size2, slice, total, start; +FILE *fp; +L_DNA *da; +SARRAY *sa; +L_BYTEA *lba1, *lba2, *lba3, *lba4; +L_REGPARAMS *rp; + +#if !defined(HAVE_LIBJPEG) + L_ERROR("This test requires libjpeg to run.\n", "bytea_reg"); + exit(77); +#endif + + if (regTestSetup(argc, argv, &rp)) + return 1; + + lept_mkdir("lept/bytea"); + + /* Test basic init and join */ + lba1 = l_byteaInitFromFile("feyn.tif"); + lba2 = l_byteaInitFromFile("test24.jpg"); + lba3 = l_byteaCopy(lba2, L_COPY); + size1 = l_byteaGetSize(lba1); + size2 = l_byteaGetSize(lba2); + l_byteaJoin(lba1, &lba3); /* destroys lba3 */ + l_byteaWrite("/tmp/lept/bytea/lba2.bya", lba2, 0, 0); + regTestCheckFile(rp, "/tmp/lept/bytea/lba2.bya"); /* 0 */ + + /* Test split, using init from memory */ + lba3 = l_byteaInitFromMem(lba1->data, size1); + lba4 = l_byteaInitFromMem(lba1->data + size1, size2); + regTestCompareStrings(rp, lba1->data, size1, lba3->data, lba3->size); + regTestCompareStrings(rp, lba2->data, size2, lba4->data, lba4->size); + /* 1, 2 */ + l_byteaDestroy(&lba4); + + /* Test split using the split function */ + l_byteaSplit(lba1, size1, &lba4); /* zeroes lba1 beyond size1 */ + regTestCompareStrings(rp, lba2->data, size2, lba4->data, lba4->size); + /* 3 */ + l_byteaDestroy(&lba1); + l_byteaDestroy(&lba2); + l_byteaDestroy(&lba3); + l_byteaDestroy(&lba4); + + /* Test appending with strings + * In order to make sure it succeeds on windows, where text + * lines are typically terminated with with "\r\n" instead + * of '\n', we remove the '\r' characters. Also, note that + * for files opened for read with "rb", as we do throughout + * leptonica with fopenReadStream(), windows will not + * append the '\r'. We have 3 ways to remove the '\r' + * characters from the byte array data1 with size1 bytes: + * str1 = (char *)arrayReplaceEachSequence(data1, size1, + * (l_uint8 *)"\r", 1, NULL, 0, &size2, NULL); + * str1 = stringReplaceEachSubstr((char *)data1, "\r", + * "", NULL); + * str1 = stringRemoveChars((char *)data1, "\r"); + * which can then be used to initialize a L_Bytea using + * lba1 = l_byteaInitFromMem((l_uint8 *)str1, strlen(str1)); + */ + + data1 = l_binaryRead("kernel_reg.c", &size1); +#if 0 + str1 = (char *)arrayReplaceEachSequence(data1, size1, (l_uint8 *)"\r", 1, + NULL, 0, &size2, NULL); + lba1 = l_byteaInitFromMem((l_uint8 *)str1, size2); +#elif 0 + str1 = stringReplaceEachSubstr((char *)data1, "\r", "", NULL); + lba1 = l_byteaInitFromMem((l_uint8 *)str1, strlen(str1)); +#else + str1 = stringRemoveChars((char *)data1, "\r"); + lba1 = l_byteaInitFromMem((l_uint8 *)str1, strlen(str1)); +#endif + sa = sarrayCreateLinesFromString(str1, 1); + lba2 = l_byteaCreate(0); + n = sarrayGetCount(sa); + for (i = 0; i < n; i++) { + str2 = sarrayGetString(sa, i, L_NOCOPY); + l_byteaAppendString(lba2, str2); + l_byteaAppendString(lba2, "\n"); + } + data2 = l_byteaGetData(lba1, &size2); + regTestCompareStrings(rp, lba1->data, lba1->size, lba2->data, lba2->size); + /* 4 */ + lept_free(data1); + lept_free(str1); + sarrayDestroy(&sa); + l_byteaDestroy(&lba1); + l_byteaDestroy(&lba2); + + /* Test appending with binary data */ + slice = 1000; + total = nbytesInFile("breviar.38.150.jpg"); + lba1 = l_byteaCreate(100); + n = 2 + total / slice; /* using 1 is correct; using 2 gives two errors */ + lept_stderr("******************************************************\n"); + lept_stderr("* Testing error checking: ignore two reported errors *\n"); + for (i = 0, start = 0; i < n; i++, start += slice) { + data2 = l_binaryReadSelect("breviar.38.150.jpg", start, slice, &size2); + l_byteaAppendData(lba1, data2, size2); + lept_free(data2); + } + lept_stderr("******************************************************\n"); + data1 = l_byteaGetData(lba1, &size1); + data2 = l_binaryRead("breviar.38.150.jpg", &size2); + regTestCompareStrings(rp, data1, size1, data2, size2); /* 5 */ + l_byteaDestroy(&lba1); + lept_free(data2); + + /* Test search */ + convertToPdf("test24.jpg", L_JPEG_ENCODE, 0, "/tmp/lept/bytea/test24.pdf", + 0, 0, 100, NULL, NULL, 0); + lba1 = l_byteaInitFromFile("/tmp/lept/bytea/test24.pdf"); + l_byteaFindEachSequence(lba1, (l_uint8 *)" 0 obj\n", 7, &da); + n = l_dnaGetCount(da); + regTestCompareValues(rp, 6, n, 0.0); /* 6 */ + l_byteaDestroy(&lba1); + l_dnaDestroy(&da); + + /* Test write to file */ + lba1 = l_byteaInitFromFile("feyn.tif"); + size1 = l_byteaGetSize(lba1); + fp = lept_fopen("/tmp/lept/bytea/feyn.dat", "wb"); + for (start = 0; start < size1; start += 1000) { + l_byteaWriteStream(fp, lba1, start, 1000); + } + lept_fclose(fp); + lba2 = l_byteaInitFromFile("/tmp/lept/bytea/feyn.dat"); + regTestCompareStrings(rp, lba1->data, size1, lba2->data, + lba2->size); /* 7 */ + l_byteaDestroy(&lba1); + l_byteaDestroy(&lba2); + + return regTestCleanup(rp); +} diff --git a/leptonica/prog/candelabrum.011.jpg b/leptonica/prog/candelabrum.011.jpg Binary files differnew file mode 100644 index 00000000..a4b26bf5 --- /dev/null +++ b/leptonica/prog/candelabrum.011.jpg diff --git a/leptonica/prog/cat-and-mouse.png b/leptonica/prog/cat-and-mouse.png Binary files differnew file mode 100644 index 00000000..6c292b06 --- /dev/null +++ b/leptonica/prog/cat-and-mouse.png diff --git a/leptonica/prog/cat.007.jpg b/leptonica/prog/cat.007.jpg Binary files differnew file mode 100644 index 00000000..00466c36 --- /dev/null +++ b/leptonica/prog/cat.007.jpg diff --git a/leptonica/prog/cat.035.jpg b/leptonica/prog/cat.035.jpg Binary files differnew file mode 100644 index 00000000..82428395 --- /dev/null +++ b/leptonica/prog/cat.035.jpg diff --git a/leptonica/prog/cavalerie.11.jpg b/leptonica/prog/cavalerie.11.jpg Binary files differnew file mode 100644 index 00000000..68375b0b --- /dev/null +++ b/leptonica/prog/cavalerie.11.jpg diff --git a/leptonica/prog/cavalerie.29.jpg b/leptonica/prog/cavalerie.29.jpg Binary files differnew file mode 100644 index 00000000..00169630 --- /dev/null +++ b/leptonica/prog/cavalerie.29.jpg diff --git a/leptonica/prog/ccbord_reg.c b/leptonica/prog/ccbord_reg.c new file mode 100644 index 00000000..2e01b8f6 --- /dev/null +++ b/leptonica/prog/ccbord_reg.c @@ -0,0 +1,231 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * ccbord_reg.c + * + * Regression test for border-following representations of binary images. + * This uses the steps in ccbordtest.c to test specified images. + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include <string.h> +#include "allheaders.h" + +void RunCCBordTest(const char *fname, L_REGPARAMS *rp); + +int main(int argc, + char **argv) +{ +L_REGPARAMS *rp; + + if (regTestSetup(argc, argv, &rp)) + return 1; + lept_mkdir("lept/ccbord"); + + RunCCBordTest("feyn-fract.tif", rp); + RunCCBordTest("dreyfus1.png", rp); + return regTestCleanup(rp); +} + +/* ----------------------------------------------- */ +void RunCCBordTest(const char *fname, + L_REGPARAMS *rp) +{ +char *svgstr; +l_int32 count, disp; +CCBORDA *ccba, *ccba2; +PIX *pixs, *pixd, *pixd2, *pixd3; +PIX *pixt, *pixc, *pixc2; + + pixs = pixRead(fname); + disp = rp->display; + + /*------------------------------------------------------------------* + * Get border representation and verify border pixels * + *------------------------------------------------------------------*/ + if(disp) lept_stderr("Get border representation..."); + ccba = pixGetAllCCBorders(pixs); + + /* Get global locs directly and display borders */ + if (disp) lept_stderr("Convert from local to global locs..."); + ccbaGenerateGlobalLocs(ccba); + if (disp) lept_stderr("display border representation..."); + pixd = ccbaDisplayBorder(ccba); + regTestWritePixAndCheck(rp, pixd, IFF_PNG); /* 0,7 */ + pixDisplayWithTitle(pixd, 0, 0, NULL, rp->display); + pixDestroy(&pixd); + + /* Get step chain code, then global coords, and display borders */ + if (disp) lept_stderr("get step chain code..."); + ccbaGenerateStepChains(ccba); + if (disp) lept_stderr("convert from step chain to global locs..."); + ccbaStepChainsToPixCoords(ccba, CCB_GLOBAL_COORDS); + if (disp) lept_stderr("display border representation\n"); + pixd = ccbaDisplayBorder(ccba); + regTestWritePixAndCheck(rp, pixd, IFF_PNG); /* 1,8 */ + pixDisplayWithTitle(pixd, 200, 0, NULL, rp->display); + + /* Check if border pixels are in original set */ + lept_stderr("Check if border pixels are in original set\n"); + pixt = pixSubtract(NULL, pixd, pixs); + pixCountPixels(pixt, &count, NULL); + if (count == 0) + lept_stderr(" ==> all border pixels are in original set\n"); + else + lept_stderr(" ==> %d border pixels are not in original set\n", count); + pixDestroy(&pixt); + + /* Display image */ + lept_stderr("Reconstruct image\n"); + pixc = ccbaDisplayImage2(ccba); + regTestWritePixAndCheck(rp, pixc, IFF_PNG); /* 2,9 */ + pixDisplayWithTitle(pixc, 400, 0, NULL, rp->display); + + /* Check with original to see if correct */ + pixXor(pixc, pixc, pixs); + pixCountPixels(pixc, &count, NULL); + if (count == 0) + lept_stderr(" ==> perfect direct reconstruction\n"); + else { + l_int32 w, h, i, j; + l_uint32 val; + lept_stderr(" ==> %d pixels in error in reconstruction\n", count); +#if 1 + w = pixGetWidth(pixc); + h = pixGetHeight(pixc); + for (i = 0; i < h; i++) { + for (j = 0; j < w; j++) { + pixGetPixel(pixc, j, i, &val); + if (val == 1) + lept_stderr("bad pixel at (%d, %d)\n", j, i); + } + } + pixWrite("/tmp/lept/ccbord/badpixels1.png", pixc, IFF_PNG); +#endif + } + + /*----------------------------------------------------------* + * Write to file (compressed) and read back * + *----------------------------------------------------------*/ + if (disp) lept_stderr("Write serialized step data..."); + ccbaWrite("/tmp/lept/ccbord/stepdata.ccb", ccba); + if (disp) lept_stderr("read serialized step data..."); + ccba2 = ccbaRead("/tmp/lept/ccbord/stepdata.ccb"); + + /* Display the border pixels again */ + if (disp) lept_stderr("convert from step chain to global locs..."); + ccbaStepChainsToPixCoords(ccba2, CCB_GLOBAL_COORDS); + if (disp) lept_stderr("display border representation\n"); + pixd2 = ccbaDisplayBorder(ccba2); + regTestWritePixAndCheck(rp, pixd2, IFF_PNG); /* 3,10 */ + pixDisplayWithTitle(pixd2, 600, 0, NULL, rp->display); + + /* Check if border pixels are same as first time */ + lept_stderr("Check border after write/read\n"); + pixXor(pixd2, pixd2, pixd); + pixCountPixels(pixd2, &count, NULL); + if (count == 0) + lept_stderr(" ==> perfect w/r border recon\n"); + else + lept_stderr(" ==> %d pixels in error in w/r recon\n", count); + pixDestroy(&pixd2); + + /* Display image again */ + if (disp) lept_stderr("Convert from step chain to local coords...\n"); + ccbaStepChainsToPixCoords(ccba2, CCB_LOCAL_COORDS); + lept_stderr("Reconstruct image from file\n"); + pixc2 = ccbaDisplayImage2(ccba2); + regTestWritePixAndCheck(rp, pixc2, IFF_PNG); /* 4,11 */ + pixDisplayWithTitle(pixc2, 800, 0, NULL, rp->display); + + /* Check with original to see if correct */ + pixXor(pixc2, pixc2, pixs); + pixCountPixels(pixc2, &count, NULL); + if (count == 0) + lept_stderr(" ==> perfect image recon\n"); + else { + l_int32 w, h, i, j; + l_uint32 val; + lept_stderr(" ==> %d pixels in error in image recon\n", count); +#if 1 + w = pixGetWidth(pixc2); + h = pixGetHeight(pixc2); + for (i = 0; i < h; i++) { + for (j = 0; j < w; j++) { + pixGetPixel(pixc2, j, i, &val); + if (val == 1) + lept_stderr("bad pixel at (%d, %d)\n", j, i); + } + } + pixWrite("/tmp/lept/ccbord/badpixels2.png", pixc, IFF_PNG); +#endif + } + + /*----------------------------------------------------------* + * Make, display and check single path border for svg * + *----------------------------------------------------------*/ + /* Make local single path border for svg */ + if (disp) lept_stderr("Make local single path borders for svg ..."); + ccbaGenerateSinglePath(ccba); + + /* Generate global single path border */ + if (disp) lept_stderr("generate global single path borders ..."); + ccbaGenerateSPGlobalLocs(ccba, CCB_SAVE_TURNING_PTS); + + /* Display border pixels from single path */ + if (disp) lept_stderr("display border from single path\n"); + pixd3 = ccbaDisplaySPBorder(ccba); + regTestWritePixAndCheck(rp, pixd3, IFF_PNG); /* 5,12 */ + pixDisplayWithTitle(pixd3, 1000, 0, NULL, rp->display); + + /* Check if border pixels are in original set */ + lept_stderr("Check if border pixels are in original set\n"); + pixt = pixSubtract(NULL, pixd3, pixs); + pixCountPixels(pixt, &count, NULL); + if (count == 0) + lept_stderr(" ==> all border pixels are in original set\n"); + else + lept_stderr(" ==> %d border pixels are not in original set\n", count); + lept_stderr("============================================\n"); + pixDestroy(&pixt); + pixDestroy(&pixd3); + + /* Output in svg file format */ + svgstr = ccbaWriteSVGString(ccba); + regTestWriteDataAndCheck(rp, svgstr, strlen(svgstr), "ccb"); /* 6,13 */ + + ccbaDestroy(&ccba2); + ccbaDestroy(&ccba); + pixDestroy(&pixs); + pixDestroy(&pixd); + pixDestroy(&pixc); + pixDestroy(&pixc2); + lept_free(svgstr); +} diff --git a/leptonica/prog/ccbordtest.c b/leptonica/prog/ccbordtest.c new file mode 100644 index 00000000..828a1ed1 --- /dev/null +++ b/leptonica/prog/ccbordtest.c @@ -0,0 +1,246 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * ccbordtest.c + * + * Comprehensive test for border-following representations + * of binary images. + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + +int main(int argc, + char **argv) +{ +char *filein; +l_int32 count; +CCBORDA *ccba, *ccba2; +PIX *pixs, *pixd, *pixd2, *pixd3; +PIX *pixt, *pixc, *pixc2; +static char mainName[] = "ccbordtest"; + + if (argc != 2) + return ERROR_INT(" Syntax: ccbordtest filein", mainName, 1); + filein = argv[1]; + + setLeptDebugOK(1); + lept_mkdir("lept/ccbord"); + + if ((pixs = pixRead(filein)) == NULL) + return ERROR_INT("pixs not made", mainName, 1); + + lept_stderr("Get border representation..."); + startTimer(); + ccba = pixGetAllCCBorders(pixs); + lept_stderr("%6.3f sec\n", stopTimer()); + + /* Get global locs directly and display borders */ + lept_stderr("Convert from local to global locs..."); + startTimer(); + ccbaGenerateGlobalLocs(ccba); + lept_stderr("%6.3f sec\n", stopTimer()); + lept_stderr("Display border representation..."); + startTimer(); + pixd = ccbaDisplayBorder(ccba); + lept_stderr("%6.3f sec\n", stopTimer()); + pixWrite("/tmp/lept/ccbord/junkborder1.png", pixd, IFF_PNG); + pixDestroy(&pixd); + + /* Get step chain code, then global coords, and display borders */ + lept_stderr("Get step chain code..."); + startTimer(); + ccbaGenerateStepChains(ccba); + lept_stderr("%6.3f sec\n", stopTimer()); + lept_stderr("Convert from step chain to global locs..."); + startTimer(); + ccbaStepChainsToPixCoords(ccba, CCB_GLOBAL_COORDS); + lept_stderr("%6.3f sec\n", stopTimer()); + lept_stderr("Display border representation..."); + startTimer(); + pixd = ccbaDisplayBorder(ccba); + lept_stderr("%6.3f sec\n", stopTimer()); + pixWrite("/tmp/lept/ccbord/junkborder1.png", pixd, IFF_PNG); + + /* Check if border pixels are in original set */ + lept_stderr("Check if border pixels are in original set ...\n"); + pixt = pixSubtract(NULL, pixd, pixs); + pixCountPixels(pixt, &count, NULL); + if (count == 0) + lept_stderr(" all border pixels are in original set\n"); + else + lept_stderr(" %d border pixels are not in original set\n", count); + pixDestroy(&pixt); + + /* Display image */ + lept_stderr("Reconstruct image ..."); + startTimer(); +/* pixc = ccbaDisplayImage1(ccba); */ + pixc = ccbaDisplayImage2(ccba); + lept_stderr("%6.3f sec\n", stopTimer()); + pixWrite("/tmp/lept/ccbord/junkrecon1.png", pixc, IFF_PNG); + + /* check with original to see if correct */ + lept_stderr("Check with original to see if correct ...\n"); + pixXor(pixc, pixc, pixs); + pixCountPixels(pixc, &count, NULL); + if (count == 0) + lept_stderr(" perfect direct recon\n"); + else { + l_int32 w, h, i, j; + l_uint32 val; + lept_stderr(" %d pixels in error in recon\n", count); +#if 1 + w = pixGetWidth(pixc); + h = pixGetHeight(pixc); + for (i = 0; i < h; i++) { + for (j = 0; j < w; j++) { + pixGetPixel(pixc, j, i, &val); + if (val == 1) + lept_stderr("bad pixel at (%d, %d)\n", j, i); + } + } + pixWrite("/tmp/lept/ccbord/junkbadpixels.png", pixc, IFF_PNG); +#endif + } + + + /*----------------------------------------------------------* + * write to file (compressed) and read back * + *----------------------------------------------------------*/ + lept_stderr("Write serialized step data..."); + startTimer(); + ccbaWrite("/tmp/junkstepout", ccba); + lept_stderr("%6.3f sec\n", stopTimer()); + lept_stderr("Read serialized step data..."); + startTimer(); + ccba2 = ccbaRead("/tmp/junkstepout"); + lept_stderr("%6.3f sec\n", stopTimer()); + + /* display the border pixels again */ + lept_stderr("Convert from step chain to global locs..."); + startTimer(); + ccbaStepChainsToPixCoords(ccba2, CCB_GLOBAL_COORDS); + lept_stderr("%6.3f sec\n", stopTimer()); + lept_stderr("Display border representation..."); + startTimer(); + pixd2 = ccbaDisplayBorder(ccba2); + lept_stderr("%6.3f sec\n", stopTimer()); + pixWrite("/tmp/lept/ccbord/junkborder2.png", pixd2, IFF_PNG); + + /* check if border pixels are same as first time */ + pixXor(pixd2, pixd2, pixd); + pixCountPixels(pixd2, &count, NULL); + if (count == 0) + lept_stderr(" perfect w/r border recon\n"); + else + lept_stderr(" %d pixels in error in w/r recon\n", count); + pixDestroy(&pixd2); + + /* display image again */ + lept_stderr("Convert from step chain to local coords..."); + startTimer(); + ccbaStepChainsToPixCoords(ccba2, CCB_LOCAL_COORDS); + lept_stderr("%6.3f sec\n", stopTimer()); + lept_stderr("Reconstruct image from file ..."); + startTimer(); +/* pixc2 = ccbaDisplayImage1(ccba2); */ + pixc2 = ccbaDisplayImage2(ccba2); + lept_stderr("%6.3f sec\n", stopTimer()); + pixWrite("/tmp/lept/ccbord/junkrecon2.png", pixc2, IFF_PNG); + + /* check with original to see if correct */ + lept_stderr("Check with original to see if correct ...\n"); + pixXor(pixc2, pixc2, pixs); + pixCountPixels(pixc2, &count, NULL); + if (count == 0) + lept_stderr(" perfect image recon\n"); + else { + l_int32 w, h, i, j; + l_uint32 val; + lept_stderr(" %d pixels in error in image recon\n", count); +#if 1 + w = pixGetWidth(pixc2); + h = pixGetHeight(pixc2); + for (i = 0; i < h; i++) { + for (j = 0; j < w; j++) { + pixGetPixel(pixc2, j, i, &val); + if (val == 1) + lept_stderr("bad pixel at (%d, %d)\n", j, i); + } + } + pixWrite("/tmp/lept/ccbord/junkbadpixels2.png", pixc2, IFF_PNG); +#endif + } + + /*----------------------------------------------------------* + * make, display and check single path border for svg * + *----------------------------------------------------------*/ + /* make local single path border for svg */ + lept_stderr("Make local single path borders for svg ..."); + startTimer(); + ccbaGenerateSinglePath(ccba); + lept_stderr("%6.3f sec\n", stopTimer()); + /* generate global single path border */ + lept_stderr("Generate global single path borders ..."); + startTimer(); + ccbaGenerateSPGlobalLocs(ccba, CCB_SAVE_TURNING_PTS); + lept_stderr("%6.3f sec\n", stopTimer()); + /* display border pixels from single path */ + lept_stderr("Display border from single path..."); + startTimer(); + pixd3 = ccbaDisplaySPBorder(ccba); + lept_stderr("%6.3f sec\n", stopTimer()); + pixWrite("/tmp/lept/ccbord/junkborder3.png", pixd3, IFF_PNG); + /* check if border pixels are in original set */ + lept_stderr("Check if border pixels are in original set ...\n"); + pixt = pixSubtract(NULL, pixd3, pixs); + pixCountPixels(pixt, &count, NULL); + if (count == 0) + lept_stderr(" all border pixels are in original set\n"); + else + lept_stderr(" %d border pixels are not in original set\n", count); + pixDestroy(&pixt); + pixDestroy(&pixd3); + + /* output in svg file format */ + lept_stderr("Write output in svg file format ...\n"); + startTimer(); + ccbaWriteSVG("/tmp/junksvg", ccba); + lept_stderr("%6.3f sec\n", stopTimer()); + + ccbaDestroy(&ccba2); + ccbaDestroy(&ccba); + pixDestroy(&pixs); + pixDestroy(&pixd); + pixDestroy(&pixc); + pixDestroy(&pixc2); + return 0; +} diff --git a/leptonica/prog/cctest1.c b/leptonica/prog/cctest1.c new file mode 100644 index 00000000..4bc8efce --- /dev/null +++ b/leptonica/prog/cctest1.c @@ -0,0 +1,125 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * cctest1.c + * + * This is a test of the following function: + * + * BOXA *pixConnComp(PIX *pixs, PIXA **ppixa, l_int32 connectivity) + * + * pixs: input pix + * ppixa: &pixa (<optional> pixa of each c.c.) + * connectivity (4 or 8) + * boxa: returned array of boxes of c.c. + * + * Use NULL for &pixa if you don't want the pixa array. + * + * It also demonstrates a few display modes. + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + +#define NTIMES 2 + +l_int32 main(l_int32 argc, + char **argv) +{ +char *filein; +l_int32 i, n, count; +BOX *box; +BOXA *boxa; +PIX *pixs, *pixd; +PIXA *pixa; +PIXCMAP *cmap; +static char mainName[] = "cctest1"; + + if (argc != 2) + return ERROR_INT(" Syntax: cctest1 filein", mainName, 1); + filein = argv[1]; + + if ((pixs = pixRead(filein)) == NULL) + return ERROR_INT("pixs not made", mainName, 1); + if (pixGetDepth(pixs) != 1) + return ERROR_INT("pixs not 1 bpp", mainName, 1); + + /* Test speed of pixCountConnComp() */ + startTimer(); + for (i = 0; i < NTIMES; i++) + pixCountConnComp(pixs, 4, &count); + lept_stderr("Time to compute 4-cc: %6.3f sec\n", stopTimer()/NTIMES); + lept_stderr("Number of 4-cc: %d\n", count); + startTimer(); + for (i = 0; i < NTIMES; i++) + pixCountConnComp(pixs, 8, &count); + lept_stderr("Time to compute 8-cc: %6.3f sec\n", stopTimer()/NTIMES); + lept_stderr("Number of 8-cc: %d\n", count); + + /* Test speed of pixConnComp(), with only boxa output */ + startTimer(); + for (i = 0; i < NTIMES; i++) { + boxa = pixConnComp(pixs, NULL, 4); + boxaDestroy(&boxa); + } + lept_stderr("Time to compute 4-cc: %6.3f sec\n", stopTimer()/NTIMES); + startTimer(); + for (i = 0; i < NTIMES; i++) { + boxa = pixConnComp(pixs, NULL, 8); + boxaDestroy(&boxa); + } + lept_stderr("Time to compute 8-cc: %6.3f sec\n", stopTimer()/NTIMES); + + /* Draw outline of each c.c. box */ + boxa = pixConnComp(pixs, NULL, 4); + n = boxaGetCount(boxa); + lept_stderr("Num 4-cc boxes: %d\n", n); + for (i = 0; i < n; i++) { + box = boxaGetBox(boxa, i, L_CLONE); + pixRenderBox(pixs, box, 3, L_FLIP_PIXELS); + boxDestroy(&box); /* remember, clones need to be destroyed */ + } + boxaDestroy(&boxa); + + /* Display each component as a random color in cmapped 8 bpp. + * Background is color 0; it is set to white. */ + boxa = pixConnComp(pixs, &pixa, 4); + pixd = pixaDisplayRandomCmap(pixa, pixGetWidth(pixs), pixGetHeight(pixs)); + cmap = pixGetColormap(pixd); + pixcmapResetColor(cmap, 0, 255, 255, 255); /* reset background to white */ + pixDisplay(pixd, 100, 100); + boxaDestroy(&boxa); + pixDestroy(&pixd); + pixaDestroy(&pixa); + + pixDestroy(&pixs); + return 0; +} + + diff --git a/leptonica/prog/ccthin1_reg.c b/leptonica/prog/ccthin1_reg.c new file mode 100644 index 00000000..ea25172f --- /dev/null +++ b/leptonica/prog/ccthin1_reg.c @@ -0,0 +1,202 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * ccthin1_reg.c + * + * Tests the "best" cc-preserving thinning functions. + * Displays all the strong cc-preserving 3x3 Sels. + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + +int main(int argc, + char **argv) +{ +BOX *box; +PIX *pix1, *pix2; +PIXA *pixa; +SEL *sel, *sel1, *sel2, *sel3; +SELA *sela, *sela4, *sela8, *sela48; +L_REGPARAMS *rp; + + if (regTestSetup(argc, argv, &rp)) + return 1; + + pixa = pixaCreate(0); + + /* Generate and display all of the 4-cc sels */ + sela4 = sela4ccThin(NULL); + pix1 = selaDisplayInPix(sela4, 35, 3, 15, 3); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 0 */ + pixDisplayWithTitle(pix1, 400, 0, NULL, rp->display); + pixaAddPix(pixa, pix1, L_INSERT); + selaDestroy(&sela4); + + /* Generate and display all of the 8-cc sels */ + sela8 = sela8ccThin(NULL); + pix1 = selaDisplayInPix(sela8, 35, 3, 15, 3); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 1 */ + pixDisplayWithTitle(pix1, 850, 0, NULL, rp->display); + pixaAddPix(pixa, pix1, L_INSERT); + selaDestroy(&sela8); + + /* Generate and display all of the 4 and 8-cc preserving sels */ + sela48 = sela4and8ccThin(NULL); + pix1 = selaDisplayInPix(sela48, 35, 3, 15, 4); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 2 */ + pixDisplayWithTitle(pix1, 1300, 0, NULL, rp->display); + pixaAddPix(pixa, pix1, L_INSERT); + selaDestroy(&sela48); + + /* Generate and display three of the 4-cc sels and their rotations */ + sela = sela4ccThin(NULL); + sela4 = selaCreate(0); + selaFindSelByName(sela, "sel_4_1", NULL, &sel); + sel1 = selRotateOrth(sel, 1); + sel2 = selRotateOrth(sel, 2); + sel3 = selRotateOrth(sel, 3); + selaAddSel(sela4, sel, NULL, L_COPY); + selaAddSel(sela4, sel1, "sel_4_1_90", L_INSERT); + selaAddSel(sela4, sel2, "sel_4_1_180", L_INSERT); + selaAddSel(sela4, sel3, "sel_4_1_270", L_INSERT); + selaFindSelByName(sela, "sel_4_2", NULL, &sel); + sel1 = selRotateOrth(sel, 1); + sel2 = selRotateOrth(sel, 2); + sel3 = selRotateOrth(sel, 3); + selaAddSel(sela4, sel, NULL, L_COPY); + selaAddSel(sela4, sel1, "sel_4_2_90", L_INSERT); + selaAddSel(sela4, sel2, "sel_4_2_180", L_INSERT); + selaAddSel(sela4, sel3, "sel_4_2_270", L_INSERT); + selaFindSelByName(sela, "sel_4_3", NULL, &sel); + sel1 = selRotateOrth(sel, 1); + sel2 = selRotateOrth(sel, 2); + sel3 = selRotateOrth(sel, 3); + selaAddSel(sela4, sel, NULL, L_COPY); + selaAddSel(sela4, sel1, "sel_4_3_90", L_INSERT); + selaAddSel(sela4, sel2, "sel_4_3_180", L_INSERT); + selaAddSel(sela4, sel3, "sel_4_3_270", L_INSERT); + pix1 = selaDisplayInPix(sela4, 35, 3, 15, 4); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 3 */ + pixDisplayWithTitle(pix1, 400, 500, NULL, rp->display); + pixaAddPix(pixa, pix1, L_INSERT); + selaDestroy(&sela); + selaDestroy(&sela4); + + /* Generate and display four of the 8-cc sels and their rotations */ + sela = sela8ccThin(NULL); + sela8 = selaCreate(0); + selaFindSelByName(sela, "sel_8_2", NULL, &sel); + sel1 = selRotateOrth(sel, 1); + sel2 = selRotateOrth(sel, 2); + sel3 = selRotateOrth(sel, 3); + selaAddSel(sela8, sel, NULL, L_COPY); + selaAddSel(sela8, sel1, "sel_8_2_90", L_INSERT); + selaAddSel(sela8, sel2, "sel_8_2_180", L_INSERT); + selaAddSel(sela8, sel3, "sel_8_2_270", L_INSERT); + selaFindSelByName(sela, "sel_8_3", NULL, &sel); + sel1 = selRotateOrth(sel, 1); + sel2 = selRotateOrth(sel, 2); + sel3 = selRotateOrth(sel, 3); + selaAddSel(sela8, sel, NULL, L_COPY); + selaAddSel(sela8, sel1, "sel_8_3_90", L_INSERT); + selaAddSel(sela8, sel2, "sel_8_3_180", L_INSERT); + selaAddSel(sela8, sel3, "sel_8_3_270", L_INSERT); + selaFindSelByName(sela, "sel_8_5", NULL, &sel); + sel1 = selRotateOrth(sel, 1); + sel2 = selRotateOrth(sel, 2); + sel3 = selRotateOrth(sel, 3); + selaAddSel(sela8, sel, NULL, L_COPY); + selaAddSel(sela8, sel1, "sel_8_5_90", L_INSERT); + selaAddSel(sela8, sel2, "sel_8_5_180", L_INSERT); + selaAddSel(sela8, sel3, "sel_8_5_270", L_INSERT); + selaFindSelByName(sela, "sel_8_6", NULL, &sel); + sel1 = selRotateOrth(sel, 1); + sel2 = selRotateOrth(sel, 2); + sel3 = selRotateOrth(sel, 3); + selaAddSel(sela8, sel, NULL, L_COPY); + selaAddSel(sela8, sel1, "sel_8_6_90", L_INSERT); + selaAddSel(sela8, sel2, "sel_8_6_180", L_INSERT); + selaAddSel(sela8, sel3, "sel_8_6_270", L_INSERT); + pix1 = selaDisplayInPix(sela8, 35, 3, 15, 4); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 4 */ + pixDisplayWithTitle(pix1, 1000, 500, NULL, rp->display); + pixaAddPix(pixa, pix1, L_INSERT); + selaDestroy(&sela); + selaDestroy(&sela8); + + /* Optional display */ + if (rp->display) { + lept_mkdir("/lept/thin"); + lept_stderr("Writing to: /tmp/lept/thin/ccthin1-1.pdf"); + pixaConvertToPdf(pixa, 0, 1.0, 0, 0, "Thin 1 Sels", + "/tmp/lept/thin/ccthin1-1.pdf"); + } + pixaDestroy(&pixa); + + pixa = pixaCreate(0); + + /* Test the best 4 and 8 cc thinning */ + pix2 = pixRead("feyn.tif"); + box = boxCreate(683, 799, 970, 479); + pix1 = pixClipRectangle(pix2, box, NULL); + boxDestroy(&box); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 5 */ + pixaAddPix(pixa, pix1, L_INSERT); + pixDestroy(&pix2); + + pix2 = pixThinConnected(pix1, L_THIN_FG, 4, 0); + regTestWritePixAndCheck(rp, pix2, IFF_PNG); /* 6 */ + pixaAddPix(pixa, pix2, L_INSERT); + pix2 = pixThinConnected(pix1, L_THIN_BG, 4, 0); + regTestWritePixAndCheck(rp, pix2, IFF_PNG); /* 7 */ + pixaAddPix(pixa, pix2, L_INSERT); + + pix2 = pixThinConnected(pix1, L_THIN_FG, 8, 0); + regTestWritePixAndCheck(rp, pix2, IFF_PNG); /* 8 */ + pixaAddPix(pixa, pix2, L_INSERT); + pix2 = pixThinConnected(pix1, L_THIN_BG, 8, 0); + regTestWritePixAndCheck(rp, pix2, IFF_PNG); /* 9 */ + pixaAddPix(pixa, pix2, L_INSERT); + + /* Display tiled */ + pix1 = pixaDisplayTiledAndScaled(pixa, 8, 500, 1, 0, 25, 2); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 10 */ + pixDisplayWithTitle(pix1, 0, 0, NULL, rp->display); + pixDestroy(&pix1); + if (rp->display) { + lept_stderr("Writing to: /tmp/lept/thin/ccthin1-2.pdf"); + pixaConvertToPdf(pixa, 0, 1.0, 0, 0, "Thin 1 Results", + "/tmp/lept/thin/ccthin1-2.pdf"); + } + pixaDestroy(&pixa); + + return regTestCleanup(rp); +} diff --git a/leptonica/prog/ccthin2_reg.c b/leptonica/prog/ccthin2_reg.c new file mode 100644 index 00000000..a5296578 --- /dev/null +++ b/leptonica/prog/ccthin2_reg.c @@ -0,0 +1,192 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * ccthin2_reg.c + * + * Tests: + * - The examples in pixThinConnectedBySet() + * - Use of thinning and thickening in stroke width normalization + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + +int main(int argc, + char **argv) +{ +l_int32 i; +BOX *box; +PIX *pixs, *pix1, *pix2; +PIXA *pixa1, *pixa2, *pixa3, *pixa4, *pixa5; +PIXAA *paa; +L_REGPARAMS *rp; +SELA *sela; + +#if !defined(HAVE_LIBPNG) + L_ERROR("This test requires libpng to run.\n", "ccthin_reg"); + exit(77); +#endif + + if (regTestSetup(argc, argv, &rp)) + return 1; + + /* Clip to foreground to see if there are any boundary + * artifacts from thinning and thickening. (There are not.) */ + pix1 = pixRead("feyn.tif"); + box = boxCreate(683, 799, 970, 479); + pix2 = pixClipRectangle(pix1, box, NULL); + pixClipToForeground(pix2, &pixs, NULL); + + pixDestroy(&pix1); + pixDestroy(&pix2); + boxDestroy(&box); + + pixa1 = pixaCreate(0); + + sela = selaMakeThinSets(1, 0); + pix1 = pixThinConnectedBySet(pixs, L_THIN_FG, sela, 0); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 0 */ + pixaAddPix(pixa1, pix1, L_INSERT); + selaDestroy(&sela); + + sela = selaMakeThinSets(2, 0); + pix1 = pixThinConnectedBySet(pixs, L_THIN_FG, sela, 0); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 1 */ + pixaAddPix(pixa1, pix1, L_INSERT); + selaDestroy(&sela); + + sela = selaMakeThinSets(3, 0); + pix1 = pixThinConnectedBySet(pixs, L_THIN_FG, sela, 0); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 2 */ + pixaAddPix(pixa1, pix1, L_INSERT); + selaDestroy(&sela); + + sela = selaMakeThinSets(4, 0); + pix1 = pixThinConnectedBySet(pixs, L_THIN_FG, sela, 0); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 3 */ + pixaAddPix(pixa1, pix1, L_INSERT); + selaDestroy(&sela); + + sela = selaMakeThinSets(5, 0); + pix1 = pixThinConnectedBySet(pixs, L_THIN_FG, sela, 0); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 4 */ + pixaAddPix(pixa1, pix1, L_INSERT); + selaDestroy(&sela); + + sela = selaMakeThinSets(6, 0); + pix1 = pixThinConnectedBySet(pixs, L_THIN_FG, sela, 0); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 5 */ + pixaAddPix(pixa1, pix1, L_INSERT); + selaDestroy(&sela); + + sela = selaMakeThinSets(7, 0); + pix1 = pixThinConnectedBySet(pixs, L_THIN_FG, sela, 0); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 6 */ + pixaAddPix(pixa1, pix1, L_INSERT); + selaDestroy(&sela); + + sela = selaMakeThinSets(8, 0); + pix1 = pixThinConnectedBySet(pixs, L_THIN_FG, sela, 0); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 7 */ + pixaAddPix(pixa1, pix1, L_INSERT); + selaDestroy(&sela); + + sela = selaMakeThinSets(9, 0); + pix1 = pixThinConnectedBySet(pixs, L_THIN_FG, sela, 0); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 8 */ + pixaAddPix(pixa1, pix1, L_INSERT); + selaDestroy(&sela); + + sela = selaMakeThinSets(10, 0); + pix1 = pixThinConnectedBySet(pixs, L_THIN_BG, sela, 5); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 9 */ + pixaAddPix(pixa1, pix1, L_INSERT); + selaDestroy(&sela); + + sela = selaMakeThinSets(11, 0); + pix1 = pixThinConnectedBySet(pixs, L_THIN_BG, sela, 5); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 10 */ + pixaAddPix(pixa1, pix1, L_INSERT); + selaDestroy(&sela); + + /* Display the thinning results */ + pix1 = pixaDisplayTiledAndScaled(pixa1, 8, 500, 1, 0, 25, 2); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 11 */ + if (rp->display) { + lept_mkdir("lept/thin"); + pixDisplayWithTitle(pix1, 0, 0, NULL, rp->display); + lept_stderr("Writing to: /tmp/lept/thin/ccthin2-1.pdf"); + pixaConvertToPdf(pixa1, 0, 1.0, 0, 0, "Thin 2 Results", + "/tmp/lept/thin/ccthin2-1.pdf"); + } + pixDestroy(&pix1); + pixDestroy(&pixs); + pixaDestroy(&pixa1); + + /* Show thinning using width normalization */ + paa = pixaaCreate(3); + pixa1 = l_bootnum_gen3(); + pixa2 = pixaScaleToSize(pixa1, 0, 36); + pixaaAddPixa(paa, pixa2, L_INSERT); + pixa3 = pixaScaleToSizeRel(pixa2, -4, 0); + pixaaAddPixa(paa, pixa3, L_INSERT); + pixa3 = pixaScaleToSizeRel(pixa2, 4, 0); + pixaaAddPixa(paa, pixa3, L_INSERT); + pixa5 = pixaCreate(6); + for (i = 0; i < 3; i++) { + pixa3 = pixaaGetPixa(paa, i, L_CLONE); + pix1 = pixaDisplayTiledInColumns(pixa3, 15, 1.0, 10, 1); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 12, 14, 16 */ + pixaAddPix(pixa5, pix1, L_INSERT); + pixa4 = pixaSetStrokeWidth(pixa3, 5, 1, 8); +/* pixa4 = pixaSetStrokeWidth(pixa3, 1, 1, 8); */ + pix1 = pixaDisplayTiledInColumns(pixa4, 15, 1.0, 10, 1); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 13, 15, 17 */ + pixaAddPix(pixa5, pix1, L_INSERT); + pixaDestroy(&pixa3); + pixaDestroy(&pixa4); + } + pix1 = pixaDisplayTiledInColumns(pixa5, 2, 1.0, 25, 2); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 18 */ + if (rp->display) { + pixDisplayWithTitle(pix1, 0, 0, NULL, rp->display); + lept_stderr("Writing to: /tmp/lept/thin/ccthin2-2.pdf"); + pixaConvertToPdf(pixa5, 0, 1.0, 0, 0, "Thin strokes", + "/tmp/lept/thin/ccthin2-2.pdf"); + } + pixaaDestroy(&paa); + pixaDestroy(&pixa1); + pixaDestroy(&pixa5); + pixDestroy(&pix1); + + return regTestCleanup(rp); +} + + diff --git a/leptonica/prog/char.tif b/leptonica/prog/char.tif Binary files differnew file mode 100644 index 00000000..de2511d6 --- /dev/null +++ b/leptonica/prog/char.tif diff --git a/leptonica/prog/chars-10.tif b/leptonica/prog/chars-10.tif Binary files differnew file mode 100644 index 00000000..76a0855b --- /dev/null +++ b/leptonica/prog/chars-10.tif diff --git a/leptonica/prog/chars-12.tif b/leptonica/prog/chars-12.tif Binary files differnew file mode 100644 index 00000000..db791955 --- /dev/null +++ b/leptonica/prog/chars-12.tif diff --git a/leptonica/prog/chars-14.tif b/leptonica/prog/chars-14.tif Binary files differnew file mode 100644 index 00000000..98508874 --- /dev/null +++ b/leptonica/prog/chars-14.tif diff --git a/leptonica/prog/chars-16.tif b/leptonica/prog/chars-16.tif Binary files differnew file mode 100644 index 00000000..2b8bbf75 --- /dev/null +++ b/leptonica/prog/chars-16.tif diff --git a/leptonica/prog/chars-18.tif b/leptonica/prog/chars-18.tif Binary files differnew file mode 100644 index 00000000..3c101bec --- /dev/null +++ b/leptonica/prog/chars-18.tif diff --git a/leptonica/prog/chars-20.tif b/leptonica/prog/chars-20.tif Binary files differnew file mode 100644 index 00000000..fba7b5f2 --- /dev/null +++ b/leptonica/prog/chars-20.tif diff --git a/leptonica/prog/chars-4.tif b/leptonica/prog/chars-4.tif Binary files differnew file mode 100644 index 00000000..b535b368 --- /dev/null +++ b/leptonica/prog/chars-4.tif diff --git a/leptonica/prog/chars-6.tif b/leptonica/prog/chars-6.tif Binary files differnew file mode 100644 index 00000000..27679b40 --- /dev/null +++ b/leptonica/prog/chars-6.tif diff --git a/leptonica/prog/chars-8.tif b/leptonica/prog/chars-8.tif Binary files differnew file mode 100644 index 00000000..76e08b90 --- /dev/null +++ b/leptonica/prog/chars-8.tif diff --git a/leptonica/prog/checkerboard1.tif b/leptonica/prog/checkerboard1.tif Binary files differnew file mode 100644 index 00000000..64e0b545 --- /dev/null +++ b/leptonica/prog/checkerboard1.tif diff --git a/leptonica/prog/checkerboard2.tif b/leptonica/prog/checkerboard2.tif Binary files differnew file mode 100644 index 00000000..8d0cb9e2 --- /dev/null +++ b/leptonica/prog/checkerboard2.tif diff --git a/leptonica/prog/checkerboard_reg.c b/leptonica/prog/checkerboard_reg.c new file mode 100644 index 00000000..96e14666 --- /dev/null +++ b/leptonica/prog/checkerboard_reg.c @@ -0,0 +1,94 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * checkerboard_reg.c + * + * This tests the function that locates corners where four checkerboard + * squares are joined. + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + +void LocateCheckerboardCorners(L_REGPARAMS *rp, + const char *fname, + l_int32 nsels); + +int main(int argc, + char **argv) +{ +L_REGPARAMS *rp; + + if (regTestSetup(argc, argv, &rp)) + return 1; + + LocateCheckerboardCorners(rp, "checkerboard1.tif", 2); + LocateCheckerboardCorners(rp, "checkerboard2.tif", 4); + return regTestCleanup(rp); +} + + +void +LocateCheckerboardCorners(L_REGPARAMS *rp, + const char *fname, + l_int32 nsels) +{ +l_int32 w, h, n, i; +PIX *pix1, *pix2, *pix3, *pix4; +PIXA *pixa1; +PTA *pta1; + + pix1 = pixRead(fname); + pixa1 = pixaCreate(0); + pixFindCheckerboardCorners(pix1, 15, 3, nsels, &pix2, &pta1, pixa1); + regTestWritePixAndCheck(rp, pix2, IFF_PNG); /* 0, 3 */ + pix3 = pixaDisplayTiledInColumns(pixa1, 1, 1.0, 20, 2); + regTestWritePixAndCheck(rp, pix3, IFF_PNG); /* 1, 4 */ + pixDisplayWithTitle(pix3, 100 * (nsels - 2), 100, NULL, rp->display); + pixGetDimensions(pix1, &w, &h, NULL); + pix4 = pixGenerateFromPta(pta1, w, h); + pixDilateBrick(pix4, pix4, 5, 5); + regTestWritePixAndCheck(rp, pix4, IFF_PNG); /* 2, 5 */ + pixDestroy(&pix1); + + if (rp->display) { + n = pixaGetCount(pixa1); + for (i = 0; i < n; i++) { + pix1 = pixaGetPix(pixa1, i, L_CLONE); + pixDisplay(pix1, 350 + 200 * i, 300 * (nsels - 2)); + pixDestroy(&pix1); + } + } + pixDestroy(&pix2); + pixDestroy(&pix3); + pixDestroy(&pix4); + pixaDestroy(&pixa1); + ptaDestroy(&pta1); +} diff --git a/leptonica/prog/church.png b/leptonica/prog/church.png Binary files differnew file mode 100644 index 00000000..ebe64c96 --- /dev/null +++ b/leptonica/prog/church.png diff --git a/leptonica/prog/circle_reg.c b/leptonica/prog/circle_reg.c new file mode 100644 index 00000000..ab5b7b0f --- /dev/null +++ b/leptonica/prog/circle_reg.c @@ -0,0 +1,140 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * circle_reg.c + * + * Extract the digits from within a circle. In some cases the circle + * touches the digits, so this cannot be done by simply selecting + * connected components. + * + * Method: + * (1) Find a solid circle that covers the fg pixels. + * (2) Progressively erode the circle, computing the number of + * 8-connected components after each successive 3x3 erosion. + * (3) Stop when the minimum number of components is first reached, + * after passing the maximum number of components. Disregard the + * original image in the counting, because it can have noise. + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + +static const l_int32 num_erodes = 8; + +int main(int argc, + char **argv) +{ +l_int32 i, k, prevcount, count, nfiles, n, maxloc, maxval, minval; +NUMA *na; +PIX *pixs, *pixsi, *pixc, *pixoc, *pix1, *pix2, *pix3; +PIXA *pixas, *pixa1, *pixa2; +L_REGPARAMS *rp; + +#if !defined(HAVE_LIBPNG) + L_ERROR("This test requires libpng to run.\n", "circle_reg"); + exit(77); +#endif + + if (regTestSetup(argc, argv, &rp)) + return 1; + + /* Read the images */ + pixas = pixaRead("circles.pa"); + n = pixaGetCount(pixas); + + pixa2 = pixaCreate(0); + for (k = 0; k < n; k++) { + pixa1 = pixaCreate(0); + na = numaCreate(0); + pixs = pixaGetPix(pixas, k, L_COPY); + pixaAddPix(pixa1, pixs, L_INSERT); + pixsi = pixInvert(NULL, pixs); + pixc = pixCreateTemplate(pixs); + pixSetOrClearBorder(pixc, 1, 1, 1, 1, PIX_SET); + pixSeedfillBinary(pixc, pixc, pixsi, 4); + pixInvert(pixc, pixc); + pixoc = pixCopy(NULL, pixc); /* original circle */ + pixaAddPix(pixa1, pixoc, L_INSERT); + pix1 = pixAnd(NULL, pixs, pixc); + pixaAddPix(pixa1, pix1, L_INSERT); + pixCountConnComp(pix1, 8, &count); + numaAddNumber(na, count); + if (rp->display) lept_stderr("count[0] = %d\n", count); + for (i = 1; i < num_erodes; i++) { + pixErodeBrick(pixc, pixc, 3, 3); + pix1 = pixAnd(NULL, pixs, pixc); + pixaAddPix(pixa1, pix1, L_INSERT); + pixCountConnComp(pix1, 8, &count); + numaAddNumber(na, count); + if (rp->display) lept_stderr("count[%d] = %d\n", i, count); + } + + /* Find the max value, not including the original image, which + * may have noise. Then find the first occurrence of the + * min value that follows this max value. */ + maxval = maxloc = 0; + for (i = 1; i < num_erodes; i++) { /* get max value starting at 1 */ + numaGetIValue(na, i, &count); + if (count > maxval) { + maxval = count; + maxloc = i; + } + } + minval = 1000; + for (i = maxloc + 1; i < num_erodes; i++) { /* get the min value */ + numaGetIValue(na, i, &count); + if (count < minval) minval = count; + } + for (i = maxloc + 1; i < num_erodes; i++) { /* get first occurrence */ + numaGetIValue(na, i, &count); + if (count == minval) break; + } + + pix1 = pixErodeBrick(NULL, pixoc, 2 * i + 1, 2 * i + 1); + pix2 = pixAnd(NULL, pixs, pix1); + pixaAddPix(pixa1, pix2, L_INSERT); + pix3 = pixaDisplayTiledInColumns(pixa1, 11, 1.0, 10, 2); + regTestWritePixAndCheck(rp, pix3, IFF_PNG); + pixaAddPix(pixa2, pix3, L_INSERT); + pixaDestroy(&pixa1); + pixDestroy(&pix1); + pixDestroy(&pixsi); + pixDestroy(&pixc); + numaDestroy(&na); + } + + pix1 = pixaDisplayTiledInColumns(pixa2, 1, 1.0, 10, 0); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); + pixDisplayWithTitle(pix1, 100, 100, NULL, rp->display); + pixaDestroy(&pixas); + pixaDestroy(&pixa2); + pixDestroy(&pix1); + return regTestCleanup(rp); +} diff --git a/leptonica/prog/circles.pa b/leptonica/prog/circles.pa Binary files differnew file mode 100644 index 00000000..c638ce20 --- /dev/null +++ b/leptonica/prog/circles.pa diff --git a/leptonica/prog/cleanpdf.c b/leptonica/prog/cleanpdf.c new file mode 100644 index 00000000..ae4ee093 --- /dev/null +++ b/leptonica/prog/cleanpdf.c @@ -0,0 +1,278 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * cleanpdf.c + * + * This program is intended to take as input pdf files that have + * been constructed from poorly compressed images -- typically images + * that have been scanned in grayscale or color but should be rendered + * in black and white (1 bpp). It cleans and compresses them, and + * generates a pdf composed of tiff-g4 compressed images. + * + * It will also take as input clean, orthographically-generated pdfs, + * and concatenate them into a single pdf file of images. + * + * Syntax: cleanpdf basedir threshold resolution outfile [rotation] + * + * The %basedir is a directory where the input pdf files are located. + * The program will operate on every file in this directory with + * the ".pdf" extension. + * + * The input binarization %threshold should be somewhere in the + * range [130 - 190]. The result is typically not very sensitive to + * the value, because internally we use a pixel mapping that is adapted + * to the local background before thresholding to binarize the image. + * + * The output %resolution parameter can take on two values: + * 300 (binarize at the same resolution as the gray or color input, + * which is typically 300 ppi) + * 600 (binarize at twice the resolution of the gray or color input, + * by doing an interpolated 2x expansion on the grayscale + * image, followed by thresholding to 1 bpp) + * At 300 ppi, an 8.5 x 11 page would have 2550 x 3300 pixels. + * You can also input 0 for the default output resolution of 300 ppi. + * + * The pdf output is written to %outfile. It is advisable (but not + * required) to have a '.pdf' extension. + * + * The optional %rotation is an integer: + * 0 no rotation + * 1 90 degrees cw + * 1 180 degrees cw + * 1 270 degrees cw + * + * Whenever possible, the images will be deskewed. + * + * Notes on using filenames with internal spaces. + * * The file-handling functions in leptonica do not support filenames + * that have spaces. To use cleanpdf in linux with such input + * filenames, substitute an ascii character for the spaces; e.g., '^'. + * char *newstr = stringReplaceEachSubstr(str, " ", "^", NULL); + * Then run cleanpdf on the file(s). + * * To get an output filename with spaces, use single quotes; e.g., + * cleanpdf dir thresh res 'filename with spaces' + * + * N.B. This requires the Poppler package of pdf utilities, such as + * pdfimages and pdftoppm. For non-unix systems, this requires + * installation of the cygwin Poppler package: + * https://cygwin.com/cgi-bin2/package-cat.cgi?file=x86/poppler/ + * poppler-0.26.5-1 + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#ifdef _WIN32 +# if defined(_MSC_VER) || defined(__MINGW32__) +# include <direct.h> +# else +# include <io.h> +# endif /* _MSC_VER || __MINGW32__ */ +#endif /* _WIN32 */ + + /* Set to 1 to use pdftoppm; 0 for pdfimages */ +#define USE_PDFTOPPM 1 + +#include "string.h" +#include <sys/stat.h> +#include <sys/types.h> +#include "allheaders.h" + + /* Special version */ +PIX *pixConvertTo8Special(PIX *pix); + +l_int32 main(int argc, + char **argv) +{ +char buf[256]; +char *basedir, *fname, *tail, *basename, *imagedir, *outfile, *firstpath; +l_int32 thresh, res, rotation, i, n, ret; +PIX *pixs, *pix1, *pix2, *pix3, *pix4, *pix5; +SARRAY *sa; +static char mainName[] = "cleanpdf"; + + if (argc != 5 && argc != 6) + return ERROR_INT( + "Syntax: cleanpdf basedir threshold resolution outfile [rotation]", + mainName, 1); + basedir = argv[1]; + thresh = atoi(argv[2]); + res = atoi(argv[3]); + outfile = argv[4]; + if (argc == 6) + rotation = atoi(argv[5]); + else + rotation = 0; + if (rotation < 0 || rotation > 3) { + L_ERROR("rotation not in valid set {0,1,2,3}; setting to 0", mainName); + rotation = 0; + } + if (res == 0) + res = 300; + if (res != 300 && res != 600) { + L_ERROR("invalid res = %d; res must be in {0, 300, 600}\n", + mainName, res); + return 1; + } + setLeptDebugOK(1); + +#if 1 + /* Get the names of the pdf files */ + if ((sa = getSortedPathnamesInDirectory(basedir, "pdf", 0, 0)) == NULL) + return ERROR_INT("files not found", mainName, 1); + sarrayWriteStream(stderr, sa); + n = sarrayGetCount(sa); +#endif + + /* Rasterize: use either + * pdftoppm -r 300 fname outroot (-r 300 renders output at 300 ppi) + * or + * pdfimages -j fname outroot (-j outputs jpeg if input is dct) + * Use of pdftoppm: + * This works on all pdf pages, both wrapped images and pages that + * were made orthographically. The default output resolution for + * pdftoppm is 150 ppi, but we use 300 ppi. This makes large + * uncompressed files (e.g., a standard size RGB page image at 300 + * ppi is 25 MB), but it is very fast. This is now preferred over + * using pdfimages. + * Use of pdfimages: + * This only works when all pages are pdf wrappers around images. + * In some cases, it scrambles the order of the output pages + * and inserts extra images. */ + imagedir = stringJoin(basedir, "/image"); +#if 1 +#ifndef _WIN32 + mkdir(imagedir, 0777); +#else + _mkdir(imagedir); +#endif /* _WIN32 */ + for (i = 0; i < n; i++) { + fname = sarrayGetString(sa, i, L_NOCOPY); + splitPathAtDirectory(fname, NULL, &tail); + splitPathAtExtension(tail, &basename, NULL); + #if USE_PDFTOPPM + snprintf(buf, sizeof(buf), "pdftoppm -r 300 %s %s/%s", + fname, imagedir, basename); + #else + snprintf(buf, sizeof(buf), "pdfimages -j %s %s/%s", + fname, imagedir, basename); + #endif /* USE_PDFTOPPM */ + lept_free(tail); + lept_free(basename); + fprintf(stderr, "%s\n", buf); + ret = system(buf); /* pdfimages or pdftoppm */ + } + sarrayDestroy(&sa); +#endif + +#if 1 + /* Clean, deskew and compress */ + sa = getSortedPathnamesInDirectory(imagedir, NULL, 0, 0); + sarrayWriteStream(stderr, sa); + n = sarrayGetCount(sa); + firstpath = NULL; + for (i = 0; i < n; i++) { + fname = sarrayGetString(sa, i, L_NOCOPY); + pixs = pixRead(fname); + pix1 = pixConvertTo8Special(pixs); + if (rotation > 0) + pix2 = pixRotateOrth(pix1, rotation); + else + pix2 = pixClone(pix1); + pix3 = pixFindSkewAndDeskew(pix2, 2, NULL, NULL); + pix4 = pixBackgroundNormSimple(pix3, NULL, NULL); + pixGammaTRC(pix4, pix4, 2.0, 50, 250); + if (res == 300) + pix5 = pixThresholdToBinary(pix4, thresh); + else /* res == 600 */ + pix5 = pixScaleGray2xLIThresh(pix4, thresh); + splitPathAtDirectory(fname, NULL, &tail); + splitPathAtExtension(tail, &basename, NULL); + snprintf(buf, sizeof(buf), "%s/%s.tif", imagedir, basename); + fprintf(stderr, "%s\n", buf); + pixWrite(buf, pix5, IFF_TIFF_G4); + if (i == 0) /* save full path to first image */ + firstpath = stringNew(buf); + pixDestroy(&pixs); + pixDestroy(&pix1); + pixDestroy(&pix2); + pixDestroy(&pix3); + pixDestroy(&pix4); + pixDestroy(&pix5); + lept_free(tail); + lept_free(basename); + } + sarrayDestroy(&sa); +#endif + +#if 1 + /* Generate the pdf. Compute the actual input resolution from + * the pixel dimensions of the first image. This will cause each + * page to be printed to cover an 8.5 x 11 inch sheet of paper. + * We use flate encoding to avoid photometric reversal which + * happens when encoded with G4 tiff. */ + fprintf(stderr, "Write output to %s\n", outfile); + pix1 = pixRead(firstpath); + pixInferResolution(pix1, 11.0, &res); + pixDestroy(&pix1); + lept_free(firstpath); + convertFilesToPdf(imagedir, "tif", res, 1.0, L_G4_ENCODE, + 0, NULL, outfile); +#endif + + return 0; +} + + + /* A special version of pixConvertTo8() that returns an image without + * a colormap and uses pixConvertRGBToGrayMinMax() to strongly + * render color into black. */ +PIX * +pixConvertTo8Special(PIX *pixs) +{ + l_int32 d = pixGetDepth(pixs); + if (d == 1) { + return pixConvert1To8(NULL, pixs, 255, 0); + } else if (d == 2) { + return pixConvert2To8(pixs, 0, 85, 170, 255, FALSE); + } else if (d == 4) { + return pixConvert4To8(pixs, FALSE); + } else if (d == 8) { + if (pixGetColormap(pixs) != NULL) + return pixRemoveColormap(pixs, REMOVE_CMAP_TO_GRAYSCALE); + else + return pixCopy(NULL, pixs); + } else if (d == 16) { + return pixConvert16To8(pixs, L_MS_BYTE); + } else if (d == 32) { + return pixConvertRGBToGrayMinMax(pixs, L_CHOOSE_MIN); + } + + L_ERROR("Invalid depth d = %d\n", "pixConvertSpecialTo8", d); + return NULL; +} diff --git a/leptonica/prog/cmapquant_reg.c b/leptonica/prog/cmapquant_reg.c new file mode 100644 index 00000000..54995d92 --- /dev/null +++ b/leptonica/prog/cmapquant_reg.c @@ -0,0 +1,136 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * cmapquant_reg.c + * + * Tests quantization of rgb image to a specific colormap. + * Does this by starting with a grayscale image, doing a grayscale + * quantization with a colormap in the dest, then adding new + * colors, scaling (which removes the colormap), and finally + * re-quantizing back to the original colormap. + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + +#define LEVEL 3 +#define MIN_DEPTH 4 + +int main(int argc, + char **argv) +{ +BOX *box; +PIX *pixs, *pix1, *pix2, *pix3, *pix4, *pix5, *pix6, *pix7; +PIX *pix8, *pix9; +PIXCMAP *cmap; +L_REGPARAMS *rp; + + if (regTestSetup(argc, argv, &rp)) + return 1; + + pixs = pixRead("lucasta-frag.jpg"); + + /* Convert to 4 bpp with 6 levels and a colormap */ + pix1 = pixThresholdTo4bpp(pixs, 6, 1); + + /* Color some non-white pixels, preserving antialiasing, and + * adding these colors to the colormap */ + box = boxCreate(120, 30, 200, 200); + pixColorGray(pix1, box, L_PAINT_DARK, 220, 0, 0, 255); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 0 */ + pixDisplayWithTitle(pix1, 0, 0, NULL, rp->display); + boxDestroy(&box); + + /* Scale up by 1.5; losing the colormap */ + pix2 = pixScale(pix1, 1.5, 1.5); + regTestWritePixAndCheck(rp, pix2, IFF_JFIF_JPEG); /* 1 */ + pixDisplayWithTitle(pix2, 0, 0, NULL, rp->display); + + /* Octcube quantize using the same colormap */ + startTimer(); + cmap = pixGetColormap(pix1); + pix3 = pixOctcubeQuantFromCmap(pix2, cmap, MIN_DEPTH, + LEVEL, L_EUCLIDEAN_DISTANCE); + lept_stderr("Time to re-quantize to cmap = %7.3f sec\n", stopTimer()); + regTestWritePixAndCheck(rp, pix3, IFF_PNG); /* 2 */ + pixDisplayWithTitle(pix3, 0, 0, NULL, rp->display); + + /* Convert the quantized image to rgb */ + pix4 = pixConvertTo32(pix3); + + /* Re-quantize using median cut */ + pix5 = pixMedianCutQuant(pix4, 0); + regTestWritePixAndCheck(rp, pix5, IFF_PNG); /* 3 */ + pixDisplayWithTitle(pix5, 0, 0, NULL, rp->display); + + /* Re-quantize to few colors using median cut */ + pix6 = pixFewColorsMedianCutQuantMixed(pix4, 30, 30, 100, 0, 0, 0); + regTestWritePixAndCheck(rp, pix6, IFF_PNG); /* 4 */ + pixDisplayWithTitle(pix6, 0, 0, NULL, rp->display); + + /* Octcube quantize mixed with gray */ + startTimer(); + pix7 = pixOctcubeQuantMixedWithGray(pix2, 4, 5, 5); + lept_stderr("Time to re-quantize mixed = %7.3f sec\n", stopTimer()); + regTestWritePixAndCheck(rp, pix7, IFF_PNG); /* 5 */ + pixDisplayWithTitle(pix7, 0, 0, NULL, rp->display); + + /* Fixed octcube quantization */ + startTimer(); + pix8 = pixFixedOctcubeQuant256(pix2, 0); + lept_stderr("Time to re-quantize 256 = %7.3f sec\n", stopTimer()); + regTestWritePixAndCheck(rp, pix8, IFF_PNG); /* 6 */ + pixDisplayWithTitle(pix8, 0, 0, NULL, rp->display); + + /* Remove unused colors */ + startTimer(); + pix9 = pixCopy(NULL, pix8); + pixRemoveUnusedColors(pix9); + lept_stderr("Time to remove unused colors = %7.3f sec\n", stopTimer()); + regTestWritePixAndCheck(rp, pix9, IFF_PNG); /* 7 */ + pixDisplayWithTitle(pix8, 0, 0, NULL, rp->display); + + /* Compare before and after colors removed */ + regTestComparePix(rp, pix8, pix9); /* 8 */ + + pixDestroy(&pixs); + pixDestroy(&pix1); + pixDestroy(&pix2); + pixDestroy(&pix3); + pixDestroy(&pix4); + pixDestroy(&pix5); + pixDestroy(&pix6); + pixDestroy(&pix7); + pixDestroy(&pix8); + pixDestroy(&pix9); + return regTestCleanup(rp); +} + + diff --git a/leptonica/prog/coffeebeans.png b/leptonica/prog/coffeebeans.png Binary files differnew file mode 100644 index 00000000..489b7b01 --- /dev/null +++ b/leptonica/prog/coffeebeans.png diff --git a/leptonica/prog/color-wheel-hue.jpg b/leptonica/prog/color-wheel-hue.jpg Binary files differnew file mode 100644 index 00000000..e00bbf6a --- /dev/null +++ b/leptonica/prog/color-wheel-hue.jpg diff --git a/leptonica/prog/colorcontent_reg.c b/leptonica/prog/colorcontent_reg.c new file mode 100644 index 00000000..d5067d81 --- /dev/null +++ b/leptonica/prog/colorcontent_reg.c @@ -0,0 +1,170 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * colorcontent_reg.c + * + * This tests various color content functions, including a simple + * color quantization method. + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "string.h" +#include "allheaders.h" + +l_int32 main(int argc, + char **argv) +{ +//char *fname[64]; +char fname[] = "/tmp/lept/colorcontent/maskgen.pdf"; +l_uint32 *colors; +l_int32 ncolors, w, h; +l_float32 fcolor; +PIX *pix1, *pix2, *pix3, *pix4, *pix5, *pix6, *pix7, *pix8; +PIXA *pixa1; +L_REGPARAMS *rp; + +#if !defined(HAVE_LIBPNG) + L_ERROR("This test requires libpng to run.\n", "colorcontent_reg"); + exit(77); +#endif + + if (regTestSetup(argc, argv, &rp)) + return 1; + + /* Find the most populated colors */ + pix1 = pixRead("fish24.jpg"); + pixGetMostPopulatedColors(pix1, 2, 3, 10, &colors, NULL); + pix2 = pixDisplayColorArray(colors, 10, 200, 5, 6); + pixDisplayWithTitle(pix2, 0, 0, NULL, rp->display); + regTestWritePixAndCheck(rp, pix2, IFF_PNG); /* 0 */ + lept_free(colors); + pixDestroy(&pix2); + + /* Do a simple color quantization with sigbits = 2 */ + pix2 = pixSimpleColorQuantize(pix1, 2, 3, 10); + pixDisplayWithTitle(pix2, 0, 400, NULL, rp->display); + regTestWritePixAndCheck(rp, pix2, IFF_PNG); /* 1 */ + pix3 = pixRemoveColormap(pix2, REMOVE_CMAP_TO_FULL_COLOR); + regTestComparePix(rp, pix2, pix3); /* 2 */ + pixNumColors(pix3, 1, &ncolors); + regTestCompareValues(rp, ncolors, 10, 0.0); /* 3 */ + pixDestroy(&pix1); + pixDestroy(&pix2); + pixDestroy(&pix3); + + /* Do a simple color quantization with sigbits = 3 */ + pix1 = pixRead("wyom.jpg"); + pixNumColors(pix1, 1, &ncolors); /* >255, so should give 0 */ + regTestCompareValues(rp, ncolors, 132165, 0.0); /* 4 */ + pix2 = pixSimpleColorQuantize(pix1, 3, 3, 20); + pixDisplayWithTitle(pix2, 1000, 0, NULL, rp->display); + regTestWritePixAndCheck(rp, pix2, IFF_PNG); /* 5 */ + ncolors = pixcmapGetCount(pixGetColormap(pix2)); + regTestCompareValues(rp, ncolors, 20, 0.0); /* 6 */ + pixDestroy(&pix1); + pixDestroy(&pix2); + + /* Find the number of perceptually significant gray intensities */ + pix1 = pixRead("marge.jpg"); + pix2 = pixConvertTo8(pix1, 0); + pixNumSignificantGrayColors(pix2, 20, 236, 0.0001, 1, &ncolors); + regTestCompareValues(rp, ncolors, 219, 0.0); /* 7 */ + pixDestroy(&pix1); + pixDestroy(&pix2); + + /* Find background color in image with light color regions */ + pix1 = pixRead("map.057.jpg"); + pixa1 = pixaCreate(0); + pixFindColorRegions(pix1, NULL, 4, 200, 70, 10, 90, 0.05, + &fcolor, &pix2, NULL, pixa1); + regTestWritePixAndCheck(rp, pix2, IFF_PNG); /* 8 */ + pix3 = pixaDisplayTiledInColumns(pixa1, 5, 0.3, 20, 2); + regTestWritePixAndCheck(rp, pix3, IFF_PNG); /* 9 */ + pixDisplayWithTitle(pix3, 1000, 500, NULL, rp->display); + pixDestroy(&pix1); + pixDestroy(&pix2); + pixDestroy(&pix3); + pixaDestroy(&pixa1); + + /* Show binary classification of RGB colors using a plane */ + pix1 = pixMakeGamutRGB(3); + pix2 = pixMakeArbMaskFromRGB(pix1, -0.5, -0.5, 1.0, 20); + pixGetDimensions(pix1, &w, &h, NULL); + pix3 = pixCreate(w, h, 32); + pixSetAll(pix3); + pixCombineMasked(pix3, pix1, pix2); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 10 */ + regTestWritePixAndCheck(rp, pix2, IFF_PNG); /* 11 */ + regTestWritePixAndCheck(rp, pix3, IFF_PNG); /* 12 */ + pixDisplayWithTitle(pix3, 0, 1300, NULL, rp->display); + pixDestroy(&pix1); + pixDestroy(&pix2); + pixDestroy(&pix3); + + /* Show use of more than one plane to further restrict the + allowed region of RGB color space */ + pixa1 = pixaCreate(0); + pix1 = pixMakeGamutRGB(3); + pix2 = pixMakeArbMaskFromRGB(pix1, -0.5, -0.5, 1.0, 20); + pix3 = pixMakeArbMaskFromRGB(pix1, 1.5, -0.5, -1.0, 0); + pix4 = pixMakeArbMaskFromRGB(pix1, 0.4, 0.3, 0.3, 60); + pixInvert(pix4, pix4); + pix5 = pixSubtract(NULL, pix2, pix3); + pix6 = pixSubtract(NULL, pix5, pix4); + pixGetDimensions(pix1, &w, &h, NULL); + pix7 = pixCreate(w, h, 32); + pixSetAll(pix7); + pixCombineMasked(pix7, pix1, pix6); + regTestWritePixAndCheck(rp, pix3, IFF_PNG); /* 13 */ + regTestWritePixAndCheck(rp, pix4, IFF_PNG); /* 14 */ + regTestWritePixAndCheck(rp, pix5, IFF_PNG); /* 15 */ + regTestWritePixAndCheck(rp, pix6, IFF_PNG); /* 16 */ + regTestWritePixAndCheck(rp, pix7, IFF_PNG); /* 17 */ + pixaAddPix(pixa1, pix1, L_INSERT); + pixaAddPix(pixa1, pix2, L_INSERT); + pixaAddPix(pixa1, pix3, L_INSERT); + pixaAddPix(pixa1, pix4, L_INSERT); + pixaAddPix(pixa1, pix5, L_INSERT); + pixaAddPix(pixa1, pix6, L_INSERT); + pixaAddPix(pixa1, pix7, L_INSERT); + lept_mkdir("lept/colorcontent"); + l_pdfSetDateAndVersion(FALSE); + pixaConvertToPdf(pixa1, 0, 0.5, L_FLATE_ENCODE, 0, NULL, fname); + regTestCheckFile(rp, fname); /* 18 */ + lept_stderr("Wrote %s\n", fname); + if (rp->display) { + pix8 = pixaDisplayTiledInColumns(pixa1, 2, 0.5, 15, 2); + pixDisplay(pix8, 800, 1300); + pixDestroy(&pix8); + } + pixaDestroy(&pixa1); + + return regTestCleanup(rp); +} diff --git a/leptonica/prog/colorfill_reg.c b/leptonica/prog/colorfill_reg.c new file mode 100644 index 00000000..3f70ce69 --- /dev/null +++ b/leptonica/prog/colorfill_reg.c @@ -0,0 +1,167 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * colorfill_reg.c + * + * This tests the utility that does color segmentation by region growing. + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + +static PIX *makeSmallTestPix(l_uint32 c1, l_uint32 c2); + + +int main(int argc, + char **argv) +{ +L_COLORFILL *cf; +PIX *pix1, *pix2, *pix3, *pix4; +PIXA *pixa1, *pixa2; +L_REGPARAMS *rp; + + if (regTestSetup(argc, argv, &rp)) + return 1; + + /* Test on a small image */ + pix1 = makeSmallTestPix(0x3070A000, 0xA0703000); + pix2 = pixExpandReplicate(pix1, 15); + regTestWritePixAndCheck(rp, pix2, IFF_PNG); /* 0 */ + pixDisplayWithTitle(pix2, 0, 0, NULL, rp->display); + pixDestroy(&pix2); + cf = l_colorfillCreate(pix1, 1, 1); + pixColorContentByLocation(cf, 0, 0, 0, 70, 15, 3, 1, 1); + pix2 = pixaDisplayTiledInColumns(cf->pixadb, cf->nx, 1.0, 10, 1); + pix3 = pixExpandReplicate(pix2, 10); + regTestWritePixAndCheck(rp, pix3, IFF_PNG); /* 1 */ + pixDisplayWithTitle(pix3, 300, 0, NULL, rp->display); + pixDestroy(&pix1); + pixDestroy(&pix2); + pixDestroy(&pix3); + l_colorfillDestroy(&cf); + + /* Test on simple random image with many colors (1 tile and 4 tiles */ + pixa1 = makeColorfillTestData(350, 350, 35, 100); + pixa2 = pixaCreate(5); + pix1 = pixaGetPix(pixa1, 0, L_COPY); + pix2 = pixConvertTo32(pix1); + pixDestroy(&pix1); + regTestWritePixAndCheck(rp, pix2, IFF_PNG); /* 2 */ + pixaAddPix(pixa2, pix2, L_INSERT); + cf = l_colorfillCreate(pix2, 1, 1); /* 1 tile */ + pixColorContentByLocation(cf, 0, 0, 0, 70, 30, 500, 1, 1); + pix3 = pixaDisplayTiledInColumns(cf->pixam, cf->nx, 1.0, 10, 1); + pix4 = pixaDisplayTiledInColumns(cf->pixadb, cf->nx, 1.0, 10, 1); + regTestWritePixAndCheck(rp, pix3, IFF_PNG); /* 3 */ + regTestWritePixAndCheck(rp, pix4, IFF_PNG); /* 4 */ + pixaAddPix(pixa2, pix3, L_INSERT); + pixaAddPix(pixa2, pix4, L_INSERT); + l_colorfillDestroy(&cf); + + cf = l_colorfillCreate(pix2, 2, 2); /* 4 tiles */ + pixColorContentByLocation(cf, 0, 0, 0, 70, 30, 500, 1, 1); + pix3 = pixaDisplayTiledInColumns(cf->pixam, cf->nx, 1.0, 10, 1); + pix4 = pixaDisplayTiledInColumns(cf->pixadb, cf->nx, 1.0, 10, 1); + regTestWritePixAndCheck(rp, pix3, IFF_PNG); /* 5 */ + regTestWritePixAndCheck(rp, pix4, IFF_PNG); /* 6 */ + pixaAddPix(pixa2, pix3, L_INSERT); + pixaAddPix(pixa2, pix4, L_INSERT); + if (rp->display) { + pix1 = pixaDisplayTiledInColumns(pixa2, 5, 1.0, 15, 2); + pixDisplay(pix1, 0, 400); + pixDestroy(&pix1); + } + pixaDestroy(&pixa1); + pixaDestroy(&pixa2); + l_colorfillDestroy(&cf); + + /* Test on an image with lots of color (with 1 tile and 9 tiles) */ + pix1 = pixRead("lyra.005.jpg"); + pix2 = pixScale(pix1, 0.5, 0.5); + pixDestroy(&pix1); + cf = l_colorfillCreate(pix2, 1, 1); /* 1 tile */ + pixColorContentByLocation(cf, 0, 0, 0, 70, 30, 100, 1, 1); + pix3 = pixaDisplayTiledInColumns(cf->pixam, cf->nx, 1.0, 10, 1); + pix4 = pixaDisplayTiledInColumns(cf->pixadb, cf->nx, 1.0, 10, 1); + regTestWritePixAndCheck(rp, pix2, IFF_PNG); /* 7 */ + regTestWritePixAndCheck(rp, pix3, IFF_PNG); /* 8 */ + regTestWritePixAndCheck(rp, pix4, IFF_PNG); /* 9 */ + pixa2 = pixaCreate(3); + pixaAddPix(pixa2, pix2, L_COPY); + pixaAddPix(pixa2, pix3, L_INSERT); + pixaAddPix(pixa2, pix4, L_INSERT); + if (rp->display) { + pix1 = pixaDisplayTiledInColumns(pixa2, 3, 0.8, 15, 2); + pixDisplay(pix1, 0, 650); + pixDestroy(&pix1); + } + l_colorfillDestroy(&cf); + pixaDestroy(&pixa2); + + cf = l_colorfillCreate(pix2, 3, 3); /* 9 tiles */ + pixColorContentByLocation(cf, 0, 0, 0, 70, 30, 100, 1, 1); + pix3 = pixaDisplayTiledInColumns(cf->pixam, cf->nx, 1.0, 10, 1); + pix4 = pixaDisplayTiledInColumns(cf->pixadb, cf->nx, 1.0, 10, 1); + regTestWritePixAndCheck(rp, pix3, IFF_PNG); /* 10 */ + regTestWritePixAndCheck(rp, pix4, IFF_PNG); /* 11 */ + pixa2 = pixaCreate(2); + pixaAddPix(pixa2, pix3, L_INSERT); + pixaAddPix(pixa2, pix4, L_INSERT); + if (rp->display) { + pix1 = pixaDisplayTiledInColumns(pixa2, 2, 0.8, 15, 2); + pixDisplay(pix1, 0, 1000); + pixDestroy(&pix1); + } + l_colorfillDestroy(&cf); + pixDestroy(&pix2); + pixaDestroy(&pixa2); + + return regTestCleanup(rp); +} + +static PIX *makeSmallTestPix(l_uint32 c1, l_uint32 c2) +{ +l_int32 i, j; +PIX *pix1; + + pix1 = pixCreate(17, 17, 32); + pixSetAllArbitrary(pix1, c1); + for (i = 0; i < 15; i++) { + for (j = 0; j < i; j++) + pixSetPixel(pix1, j, i, c2); + } + for (i = 0; i < 15; i++) { + for (j = 17 - i; j < 17; j++) + pixSetPixel(pix1, j, i, c2); + } + for (i = 9; i < 17; i++) + pixSetPixel(pix1, 8, i, c1); + return pix1; +} diff --git a/leptonica/prog/coloring_reg.c b/leptonica/prog/coloring_reg.c new file mode 100644 index 00000000..f9c722a3 --- /dev/null +++ b/leptonica/prog/coloring_reg.c @@ -0,0 +1,158 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * coloring_reg.c + * + * This tests simple coloring functions. + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "string.h" +#include "allheaders.h" + +static const char *bgcolors[] = {"255 255 235", + "255 245 235", + "255 235 245", + "235 245 255"}; + + +l_int32 main(int argc, + char **argv) +{ +char buf[512]; +l_int32 i, n, index; +l_int32 rval[4], gval[4], bval[4]; +l_uint32 scolor, dcolor; +L_BMF *bmf; +PIX *pix0, *pix1, *pix2, *pix3, *pix4, *pix5; +PIXA *pixa; +PIXCMAP *cmap; +L_REGPARAMS *rp; + +#if !defined(HAVE_LIBPNG) + L_ERROR("This test requires libpng to run.\n", "coloring_reg"); + exit(77); +#endif + + if (regTestSetup(argc, argv, &rp)) + return 1; + + /* Read in the bg colors */ + for (i = 0; i < 4; i++) + sscanf(bgcolors[i], "%d %d %d", &rval[i], &gval[i], &bval[i]); + bmf = bmfCreate("fonts", 8); + + /* Get the input image (100 ppi resolution) */ + pix0 = pixRead("harmoniam100-11.png"); + cmap = pixGetColormap(pix0); + pixa = pixaCreate(0); + + /* Do cmapped coloring on the white pixels only */ + pixcmapGetIndex(cmap, 255, 255, 255, &index); /* index of white pixels */ + for (i = 0; i < 4; i++) { + pixcmapResetColor(cmap, index, rval[i], gval[i], bval[i]); + snprintf(buf, sizeof(buf), "(rval, bval, gval) = (%d, %d, %d)", + rval[i], gval[i], bval[i]); + pix1 = pixAddSingleTextblock(pix0, bmf, buf, 0xff000000, + L_ADD_AT_BOT, NULL); + pixaAddPix(pixa, pix1, L_INSERT); + } + + /* Do cmapped background coloring on all the pixels */ + for (i = 0; i < 4; i++) { + scolor = 0xffffff00; /* source color */ + composeRGBPixel(rval[i], gval[i], bval[i], &dcolor); /* dest color */ + pix1 = pixShiftByComponent(NULL, pix0, scolor, dcolor); + snprintf(buf, sizeof(buf), "(rval, bval, gval) = (%d, %d, %d)", + rval[i], gval[i], bval[i]); + pix2 = pixAddSingleTextblock(pix1, bmf, buf, 0xff000000, + L_ADD_AT_BOT, NULL); + pixaAddPix(pixa, pix2, L_INSERT); + pixDestroy(&pix1); + } + + + /* Do background coloring on rgb */ + pix1 = pixConvertTo32(pix0); + for (i = 0; i < 4; i++) { + scolor = 0xffffff00; + composeRGBPixel(rval[i], gval[i], bval[i], &dcolor); + pix2 = pixShiftByComponent(NULL, pix1, scolor, dcolor); + snprintf(buf, sizeof(buf), "(rval, bval, gval) = (%d, %d, %d)", + rval[i], gval[i], bval[i]); + pix3 = pixAddSingleTextblock(pix2, bmf, buf, 0xff000000, + L_ADD_AT_BOT, NULL); + pixaAddPix(pixa, pix3, L_INSERT); + pixDestroy(&pix2); + } + pixDestroy(&pix1); + + /* Compare cmapped & rgb foreground coloring */ + scolor = 0x0; /* source color */ + composeRGBPixel(200, 30, 150, &dcolor); /* ugly fg dest color */ + pix1 = pixShiftByComponent(NULL, pix0, scolor, dcolor); /* cmapped */ + snprintf(buf, sizeof(buf), "(rval, bval, gval) = (%d, %d, %d)", + 200, 100, 50); + pix2 = pixAddSingleTextblock(pix1, bmf, buf, 0xff000000, + L_ADD_AT_BOT, NULL); + pixaAddPix(pixa, pix2, L_INSERT); + pix3 = pixConvertTo32(pix0); + pix4 = pixShiftByComponent(NULL, pix3, scolor, dcolor); /* rgb */ + snprintf(buf, sizeof(buf), "(rval, bval, gval) = (%d, %d, %d)", + 200, 100, 50); + pix5 = pixAddSingleTextblock(pix4, bmf, buf, 0xff000000, + L_ADD_AT_BOT, NULL); + pixaAddPix(pixa, pix5, L_INSERT); + regTestComparePix(rp, pix1, pix4); + regTestComparePix(rp, pix2, pix5); + pixDestroy(&pix1); + pixDestroy(&pix3); + pixDestroy(&pix4); + + /* Log all the results */ + n = pixaGetCount(pixa); + for (i = 0; i < n; i++) { + pix1 = pixaGetPix(pixa, i, L_CLONE); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); + pixDestroy(&pix1); + } + + /* If in testing mode, make a pdf */ + if (rp->display) { + pixaConvertToPdf(pixa, 100, 1.0, L_FLATE_ENCODE, 0, + "Colored background", "/tmp/lept/regout/coloring.pdf"); + L_INFO("Output pdf: /tmp/lept/regout/coloring.pdf\n", rp->testname); + } + + pixaDestroy(&pixa); + pixDestroy(&pix0); + bmfDestroy(&bmf); + return regTestCleanup(rp); +} diff --git a/leptonica/prog/colorize_reg.c b/leptonica/prog/colorize_reg.c new file mode 100644 index 00000000..c885eafc --- /dev/null +++ b/leptonica/prog/colorize_reg.c @@ -0,0 +1,290 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * colorize_reg.c + * + * This regresstion test demonstrates the detection of red highlight + * color in an image, and the generation of a colormapped version + * with clean background and colorized highlighting. + * + * The input image is rgb. Other examples are breviar.32 and amoris.2. + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + +PIX *TestForRedColor(L_REGPARAMS *rp, const char *fname, + l_float32 gold_red, L_BMF *bmf); + +l_int32 main(int argc, + char **argv) +{ +l_int32 irval, igval, ibval; +l_float32 rval, gval, bval, fract, fgfract; +L_BMF *bmf; +BOX *box; +BOXA *boxa; +FPIX *fpix; +PIX *pixs, *pix1, *pix2, *pix3, *pix4, *pix5, *pix6, *pix7; +PIX *pix8, *pix9, *pix10, *pix11, *pix12, *pix13, *pix14, *pix15; +PIXA *pixa; +L_REGPARAMS *rp; + +#if !defined(HAVE_LIBPNG) + L_ERROR("This test requires libpng to run.\n", "colorize_reg"); + exit(77); +#endif + + if (regTestSetup(argc, argv, &rp)) + return 1; + + pixa = pixaCreate(0); + pixs = pixRead("breviar.38.150.jpg"); + pixaAddPix(pixa, pixs, L_CLONE); + regTestWritePixAndCheck(rp, pixs, IFF_JFIF_JPEG); /* 0 */ + pixDisplayWithTitle(pixs, 0, 0, "Input image", rp->display); + + /* Extract the blue component, which is small in all the text + * regions, including in the highlight color region */ + pix1 = pixGetRGBComponent(pixs, COLOR_BLUE); + pixaAddPix(pixa, pix1, L_CLONE); + regTestWritePixAndCheck(rp, pix1, IFF_JFIF_JPEG); /* 1 */ + pixDisplayWithTitle(pix1, 200, 0, "Blue component", rp->display); + + /* Do a background normalization, with the background set to + * approximately 200 */ + pix2 = pixBackgroundNormSimple(pix1, NULL, NULL); + pixaAddPix(pixa, pix2, L_COPY); + regTestWritePixAndCheck(rp, pix2, IFF_JFIF_JPEG); /* 2 */ + pixDisplayWithTitle(pix2, 400, 0, "BG normalized to 200", rp->display); + + /* Do a linear transform on the gray pixels, with 50 going to + * black and 160 going to white. 50 is sufficiently low to + * make both the red and black print quite dark. Quantize + * to a few equally spaced gray levels. This is the image + * to which highlight color will be applied. */ + pixGammaTRC(pix2, pix2, 1.0, 50, 160); + pix3 = pixThresholdOn8bpp(pix2, 7, 1); + pixaAddPix(pixa, pix3, L_CLONE); + regTestWritePixAndCheck(rp, pix3, IFF_JFIF_JPEG); /* 3 */ + pixDisplayWithTitle(pix3, 600, 0, "Basic quantized with white bg", + rp->display); + + /* Identify the regions of red text. First, make a mask + * consisting of all pixels such that (R-B)/B is larger + * than 2.0. This will have all the red, plus a lot of + * the dark pixels. */ + fpix = pixComponentFunction(pixs, 1.0, 0.0, -1.0, 0.0, 0.0, 1.0); + pix4 = fpixThresholdToPix(fpix, 2.0); + pixInvert(pix4, pix4); /* red plus some dark text */ + pixaAddPix(pixa, pix4, L_CLONE); + regTestWritePixAndCheck(rp, pix4, IFF_PNG); /* 4 */ + pixDisplayWithTitle(pix4, 800, 0, "Red plus dark pixels", rp->display); + + /* Make a mask consisting of all the red and background pixels */ + pix5 = pixGetRGBComponent(pixs, COLOR_RED); + pix6 = pixThresholdToBinary(pix5, 128); + pixInvert(pix6, pix6); /* red plus background (white) */ + + /* Intersect the two masks to get a mask consisting of pixels + * that are almost certainly red. This is the seed. */ + pix7 = pixAnd(NULL, pix4, pix6); /* red only (seed) */ + pixaAddPix(pixa, pix7, L_COPY); + regTestWritePixAndCheck(rp, pix7, IFF_PNG); /* 5 */ + pixDisplayWithTitle(pix7, 0, 600, "Seed for red color", rp->display); + + /* Make the clipping mask by thresholding the image with + * the background cleaned to white. */ + pix8 = pixThresholdToBinary(pix2, 230); /* mask */ + pixaAddPix(pixa, pix8, L_CLONE); + regTestWritePixAndCheck(rp, pix8, IFF_PNG); /* 6 */ + pixDisplayWithTitle(pix8, 200, 600, "Clipping mask for red components", + rp->display); + + /* Fill into the mask from the seed */ + pixSeedfillBinary(pix7, pix7, pix8, 8); /* filled: red plus touching */ + regTestWritePixAndCheck(rp, pix7, IFF_PNG); /* 7 */ + pixDisplayWithTitle(pix7, 400, 600, "Red component mask filled", + rp->display); + + /* Small closing on regions to be colored */ + pix9 = pixMorphSequence(pix7, "c5.1", 0); + pixaAddPix(pixa, pix9, L_CLONE); + regTestWritePixAndCheck(rp, pix9, IFF_PNG); /* 8 */ + pixDisplayWithTitle(pix9, 600, 600, + "Components defining regions allowing coloring", + rp->display); + + /* Sanity check on amount to be colored. Only accept images + * with less than 10% of all the pixels with highlight color */ + pixForegroundFraction(pix9, &fgfract); + if (fgfract >= 0.10) { + L_INFO("too much highlighting: fract = %6.3f; removing it\n", + rp->testname, fgfract); + pixClearAll(pix9); + pixSetPixel(pix9, 0, 0, 1); + } + + /* Get a color to paint that is representative of the + * actual highlight color in the image. Scale each + * color component up from the average by an amount necessary + * to saturate the red. Then divide the green and + * blue components by 2.0. */ + pixGetAverageMaskedRGB(pixs, pix7, 0, 0, 1, L_MEAN_ABSVAL, + &rval, &gval, &bval); + fract = 255.0 / rval; + irval = lept_roundftoi(fract * rval); + igval = lept_roundftoi(fract * gval / 2.0); + ibval = lept_roundftoi(fract * bval / 2.0); + lept_stderr("(r,g,b) = (%d,%d,%d)\n", irval, igval, ibval); + + /* Test mask-based colorization on gray and cmapped gray */ + pix10 = pixColorGrayMasked(pix2, pix9, L_PAINT_DARK, 225, + irval, igval, ibval); + pixaAddPix(pixa, pix10, L_CLONE); + regTestWritePixAndCheck(rp, pix10, IFF_PNG); /* 9 */ + pixDisplayWithTitle(pix10, 800, 600, "Colorize mask gray", rp->display); + pixaAddPix(pixa, pixs, L_CLONE); + + pix11 = pixColorGrayMasked(pix3, pix9, L_PAINT_DARK, 225, + irval, igval, ibval); + pixaAddPix(pixa, pix11, L_CLONE); + regTestWritePixAndCheck(rp, pix11, IFF_PNG); /* 10 */ + pixDisplayWithTitle(pix11, 900, 600, "Colorize mask cmapped", rp->display); + + /* Get the bounding boxes of the mask components to be colored */ + boxa = pixConnCompBB(pix9, 8); + + /* Test region colorization on gray and cmapped gray */ + pix12 = pixColorGrayRegions(pix2, boxa, L_PAINT_DARK, 220, 0, 255, 0); + pixaAddPix(pixa, pix12, L_CLONE); + regTestWritePixAndCheck(rp, pix12, IFF_PNG); /* 11 */ + pixDisplayWithTitle(pix12, 900, 600, "Colorize boxa gray", rp->display); + + box = boxCreate(200, 200, 250, 350); + pix13 = pixCopy(NULL, pix2); + pixColorGray(pix13, box, L_PAINT_DARK, 220, 0, 0, 255); + pixaAddPix(pixa, pix13, L_CLONE); + regTestWritePixAndCheck(rp, pix13, IFF_PNG); /* 12 */ + pixDisplayWithTitle(pix13, 1000, 600, "Colorize box gray", rp->display); + + pix14 = pixThresholdTo4bpp(pix2, 6, 1); + pix15 = pixColorGrayRegions(pix14, boxa, L_PAINT_DARK, 220, 0, 0, 255); + pixaAddPix(pixa, pix15, L_CLONE); + regTestWritePixAndCheck(rp, pix15, IFF_PNG); /* 13 */ + pixDisplayWithTitle(pix15, 1100, 600, "Colorize boxa cmap", rp->display); + + pixColorGrayCmap(pix14, box, L_PAINT_DARK, 0, 255, 255); + pixaAddPix(pixa, pix14, L_CLONE); + regTestWritePixAndCheck(rp, pix14, IFF_PNG); /* 14 */ + pixDisplayWithTitle(pix14, 1200, 600, "Colorize box cmap", rp->display); + boxDestroy(&box); + + /* Generate a pdf of the intermediate results */ + lept_mkdir("lept/color"); + L_INFO("Writing to /tmp/lept/color/colorize.pdf\n", rp->testname); + pixaConvertToPdf(pixa, 90, 1.0, 0, 0, "Colorizing highlighted text", + "/tmp/lept/color/colorize.pdf"); + + + pixaDestroy(&pixa); + fpixDestroy(&fpix); + boxDestroy(&box); + boxaDestroy(&boxa); + pixDestroy(&pixs); + pixDestroy(&pix1); + pixDestroy(&pix2); + pixDestroy(&pix3); + pixDestroy(&pix4); + pixDestroy(&pix5); + pixDestroy(&pix6); + pixDestroy(&pix7); + pixDestroy(&pix8); + pixDestroy(&pix9); + pixDestroy(&pix10); + pixDestroy(&pix11); + pixDestroy(&pix12); + pixDestroy(&pix13); + pixDestroy(&pix14); + pixDestroy(&pix15); + + /* Test the color detector */ + pixa = pixaCreate(7); + bmf = bmfCreate(NULL, 4); + pix1 = TestForRedColor(rp, "brev.06.75.jpg", 1, bmf); /* 14 */ + pixaAddPix(pixa, pix1, L_INSERT); + pix1 = TestForRedColor(rp, "brev.10.75.jpg", 0, bmf); /* 15 */ + pixaAddPix(pixa, pix1, L_INSERT); + pix1 = TestForRedColor(rp, "brev.14.75.jpg", 1, bmf); /* 16 */ + pixaAddPix(pixa, pix1, L_INSERT); + pix1 = TestForRedColor(rp, "brev.20.75.jpg", 1, bmf); /* 17 */ + pixaAddPix(pixa, pix1, L_INSERT); + pix1 = TestForRedColor(rp, "brev.36.75.jpg", 0, bmf); /* 18 */ + pixaAddPix(pixa, pix1, L_INSERT); + pix1 = TestForRedColor(rp, "brev.53.75.jpg", 1, bmf); /* 19 */ + pixaAddPix(pixa, pix1, L_INSERT); + pix1 = TestForRedColor(rp, "brev.56.75.jpg", 1, bmf); /* 20 */ + pixaAddPix(pixa, pix1, L_INSERT); + + /* Generate a pdf of the color detector results */ + L_INFO("Writing to /tmp/lept/color/colordetect.pdf\n", rp->testname); + pixaConvertToPdf(pixa, 45, 1.0, 0, 0, "Color detection", + "/tmp/lept/color/colordetect.pdf"); + pixaDestroy(&pixa); + bmfDestroy(&bmf); + + return regTestCleanup(rp); +} + + +PIX * +TestForRedColor(L_REGPARAMS *rp, + const char *fname, + l_float32 gold_red, + L_BMF *bmf) +{ +char text[64]; +PIX *pix1, *pix2; +l_int32 hasred; +l_float32 ratio; + + pix1 = pixRead(fname); + pixHasHighlightRed(pix1, 1, 0.0001, 2.5, &hasred, &ratio, NULL); + regTestCompareValues(rp, gold_red, hasred, 0.0); + if (hasred) + snprintf(text, sizeof(text), "Has red: ratio = %6.1f", ratio); + else + snprintf(text, sizeof(text), "Does not have red: ratio = %6.1f", ratio); + pix2 = pixAddSingleTextblock(pix1, bmf, text, 0x0000ff00, + L_ADD_BELOW, NULL); + pixDestroy(&pix1); + return pix2; +} + diff --git a/leptonica/prog/colormask_reg.c b/leptonica/prog/colormask_reg.c new file mode 100644 index 00000000..091ced98 --- /dev/null +++ b/leptonica/prog/colormask_reg.c @@ -0,0 +1,158 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * colormask_reg.c + * + * This tests the ability to identify regions in HSV color space + * by analyzing the HS histogram and building masks that cover + * peaks in HS. + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + +int main(int argc, + char **argv) +{ +l_int32 i, j, x, y, rval, gval, bval; +l_uint32 pixel1, pixel2; +l_float32 frval, fgval, fbval; +NUMA *nahue, *nasat, *napk; +PIX *pixs, *pixhsv, *pixh, *pixg, *pixf, *pixd, *pixr; +PIX *pix1, *pix2, *pix3; +PIXA *pixa, *pixapk; +PTA *ptapk; +L_REGPARAMS *rp; + +#if !defined(HAVE_LIBPNG) + L_ERROR("This test requires libpng to run.\n", "colormask_reg"); + exit(77); +#endif + + if (regTestSetup(argc, argv, &rp)) + return 1; + + /* Make a graded frame color */ + pixs = pixCreate(650, 900, 32); + for (i = 0; i < 900; i++) { + rval = 40 + i / 30; + for (j = 0; j < 650; j++) { + gval = 255 - j / 30; + bval = 70 + j / 30; + composeRGBPixel(rval, gval, bval, &pixel1); + pixSetPixel(pixs, j, i, pixel1); + } + } + + /* Place an image inside the frame and convert to HSV */ + pix1 = pixRead("1555.003.jpg"); + pix2 = pixScale(pix1, 0.5, 0.5); + pixRasterop(pixs, 100, 100, 2000, 2000, PIX_SRC, pix2, 0, 0); + pixDestroy(&pix1); + pixDestroy(&pix2); + pixDisplayWithTitle(pixs, 400, 0, "Input image", rp->display); + pixa = pixaCreate(0); + pixhsv = pixConvertRGBToHSV(NULL, pixs); + + /* Work in the HS projection of HSV */ + pixh = pixMakeHistoHS(pixhsv, 5, &nahue, &nasat); + pixg = pixMaxDynamicRange(pixh, L_LOG_SCALE); + pixf = pixConvertGrayToFalseColor(pixg, 1.0); + regTestWritePixAndCheck(rp, pixf, IFF_PNG); /* 0 */ + pixDisplayWithTitle(pixf, 100, 0, "False color HS histo", rp->display); + pixaAddPix(pixa, pixs, L_COPY); + pixaAddPix(pixa, pixhsv, L_INSERT); + pixaAddPix(pixa, pixg, L_INSERT); + pixaAddPix(pixa, pixf, L_INSERT); + gplotSimple1(nahue, GPLOT_PNG, "/tmp/lept/regout/junkhue", + "Histogram of hue values"); + pix3 = pixRead("/tmp/lept/regout/junkhue.png"); + regTestWritePixAndCheck(rp, pix3, IFF_PNG); /* 1 */ + pixDisplayWithTitle(pix3, 100, 300, "Histo of hue", rp->display); + pixaAddPix(pixa, pix3, L_INSERT); + gplotSimple1(nasat, GPLOT_PNG, "/tmp/lept/regout/junksat", + "Histogram of saturation values"); + pix3 = pixRead("/tmp/lept/regout/junksat.png"); + regTestWritePixAndCheck(rp, pix3, IFF_PNG); /* 2 */ + pixDisplayWithTitle(pix3, 100, 800, "Histo of saturation", rp->display); + pixaAddPix(pixa, pix3, L_INSERT); + pixd = pixaDisplayTiledAndScaled(pixa, 32, 270, 7, 0, 30, 3); + regTestWritePixAndCheck(rp, pixd, IFF_PNG); /* 3 */ + pixDisplayWithTitle(pixd, 0, 400, "Hue and Saturation Mosaic", rp->display); + pixDestroy(&pixd); + pixaDestroy(&pixa); + numaDestroy(&nahue); + numaDestroy(&nasat); + + /* Find all the peaks */ + pixFindHistoPeaksHSV(pixh, L_HS_HISTO, 20, 20, 6, 2.0, + &ptapk, &napk, &pixapk); + numaWriteStream(stderr, napk); + ptaWriteStream(stderr, ptapk, 1); + pixd = pixaDisplayTiledInRows(pixapk, 32, 1400, 1.0, 0, 30, 2); + regTestWritePixAndCheck(rp, pixd, IFF_PNG); /* 4 */ + pixDisplayWithTitle(pixd, 0, 550, "Peaks in HS", rp->display); + pixDestroy(&pixh); + pixDestroy(&pixd); + pixaDestroy(&pixapk); + + /* Make masks for each of the peaks */ + pixa = pixaCreate(0); + pixr = pixScaleBySampling(pixs, 0.4, 0.4); + for (i = 0; i < 6; i++) { + ptaGetIPt(ptapk, i, &x, &y); + pix1 = pixMakeRangeMaskHS(pixr, y, 20, x, 20, L_INCLUDE_REGION); + pixaAddPix(pixa, pix1, L_INSERT); + pixGetAverageMaskedRGB(pixr, pix1, 0, 0, 1, L_MEAN_ABSVAL, + &frval, &fgval, &fbval); + composeRGBPixel((l_int32)frval, (l_int32)fgval, (l_int32)fbval, + &pixel1); + pixGetPixelAverage(pixr, pix1, 0, 0, 1, &pixel2); + regTestCompareValues(rp, pixel1 >> 8, pixel2 >> 8, 0.0); /* 5 - 10 */ + pix2 = pixCreateTemplate(pixr); + pixSetAll(pix2); + pixPaintThroughMask(pix2, pix1, 0, 0, pixel1); + pixaAddPix(pixa, pix2, L_INSERT); + pix3 = pixCreateTemplate(pixr); + pixSetAllArbitrary(pix3, pixel1); + pixaAddPix(pixa, pix3, L_INSERT); + } + pixd = pixaDisplayTiledAndScaled(pixa, 32, 225, 3, 0, 30, 3); + regTestWritePixAndCheck(rp, pixd, IFF_PNG); /* 8 */ + pixDisplayWithTitle(pixd, 600, 0, "Masks over peaks", rp->display); + pixDestroy(&pixs); + pixDestroy(&pixr); + pixDestroy(&pixd); + pixaDestroy(&pixa); + ptaDestroy(&ptapk); + numaDestroy(&napk); + + return regTestCleanup(rp); +} diff --git a/leptonica/prog/colormorph_reg.c b/leptonica/prog/colormorph_reg.c new file mode 100644 index 00000000..56b80035 --- /dev/null +++ b/leptonica/prog/colormorph_reg.c @@ -0,0 +1,101 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * colormorph_reg.c + * + * Regression test for simple color morphological operations + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + +static const l_int32 SIZE = 7; + +int main(int argc, + char **argv) +{ +char buf[256]; +PIX *pixs, *pix1, *pix2; +PIXA *pixa; +L_REGPARAMS *rp; + + if (regTestSetup(argc, argv, &rp)) + return 1; + + pixs = pixRead("wyom.jpg"); + pixa = pixaCreate(0); + + pix1 = pixColorMorph(pixs, L_MORPH_DILATE, SIZE, SIZE); + regTestWritePixAndCheck(rp, pix1, IFF_JFIF_JPEG); /* 0 */ + snprintf(buf, sizeof(buf), "d%d.%d", SIZE, SIZE); + pix2 = pixColorMorphSequence(pixs, buf, 0, 0); + regTestComparePix(rp, pix1, pix2); /* 1 */ + pixaAddPix(pixa, pix1, L_INSERT); + pixDestroy(&pix2); + + pix1 = pixColorMorph(pixs, L_MORPH_ERODE, SIZE, SIZE); + regTestWritePixAndCheck(rp, pix1, IFF_JFIF_JPEG); /* 2 */ + snprintf(buf, sizeof(buf), "e%d.%d", SIZE, SIZE); + pix2 = pixColorMorphSequence(pixs, buf, 0, 0); + regTestComparePix(rp, pix1, pix2); /* 3 */ + pixaAddPix(pixa, pix1, L_INSERT); + pixDestroy(&pix2); + + pix1 = pixColorMorph(pixs, L_MORPH_OPEN, SIZE, SIZE); + regTestWritePixAndCheck(rp, pix1, IFF_JFIF_JPEG); /* 4 */ + snprintf(buf, sizeof(buf), "o%d.%d", SIZE, SIZE); + pix2 = pixColorMorphSequence(pixs, buf, 0, 0); + regTestComparePix(rp, pix1, pix2); /* 5 */ + pixaAddPix(pixa, pix1, L_INSERT); + pixDestroy(&pix2); + + pix1 = pixColorMorph(pixs, L_MORPH_CLOSE, SIZE, SIZE); + regTestWritePixAndCheck(rp, pix1, IFF_JFIF_JPEG); /* 6 */ + snprintf(buf, sizeof(buf), "c%d.%d", SIZE, SIZE); + pix2 = pixColorMorphSequence(pixs, buf, 0, 0); + regTestComparePix(rp, pix1, pix2); /* 7 */ + pixaAddPix(pixa, pix1, L_INSERT); + pixDestroy(&pix2); + + if (rp->display) { + lept_mkdir("lept/cmorph"); + lept_stderr("Writing to: /tmp/lept/cmorph/colormorph.pdf\n"); + pixaConvertToPdf(pixa, 0, 1.0, L_FLATE_ENCODE, 0, "colormorph-test", + "/tmp/lept/cmorph/colormorph.pdf"); + lept_stderr("Writing to: /tmp/lept/cmorph/colormorph.jpg\n"); + pix1 = pixaDisplayTiledInColumns(pixa, 2, 1.0, 30, 2); + pixWrite("/tmp/lept/cmorph/colormorph.jpg", pix1, IFF_JFIF_JPEG); + pixDisplay(pix1, 100, 100); + pixDestroy(&pix1); + } + pixaDestroy(&pixa); + pixDestroy(&pixs); + return regTestCleanup(rp); +} diff --git a/leptonica/prog/colorpage.030.jpg b/leptonica/prog/colorpage.030.jpg Binary files differnew file mode 100644 index 00000000..fef4c12d --- /dev/null +++ b/leptonica/prog/colorpage.030.jpg diff --git a/leptonica/prog/colorquant_reg.c b/leptonica/prog/colorquant_reg.c new file mode 100644 index 00000000..9b5682c5 --- /dev/null +++ b/leptonica/prog/colorquant_reg.c @@ -0,0 +1,241 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * colorquant_reg.c + * + * Regression test for various color quantizers + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + +static const l_int32 SPACE = 30; +static const l_int32 MAX_WIDTH = 350; +static const char *image[4] = {"marge.jpg", + "test24.jpg", + "juditharismax.jpg", + "hardlight2_2.jpg"}; + +static l_int32 TestImage(const char *filename, l_int32 i, L_REGPARAMS *rp); +static void PixSave32(PIXA *pixa, PIX *pixc, L_REGPARAMS *rp); + + +int main(int argc, + char **argv) +{ +l_int32 i; +L_REGPARAMS *rp; + + if (regTestSetup(argc, argv, &rp)) + return 1; + + for (i = 0; i < 4; i++) { +/* if (i != 2) continue; */ + TestImage(image[i], i, rp); + } + + return regTestCleanup(rp); +} + + +static l_int32 +TestImage(const char *filename, + l_int32 i, + L_REGPARAMS *rp) +{ +char buf[256]; +l_int32 w, h; +l_float32 factor; +PIX *pix, *pixs, *pixc, *pix32, *pixt, *pixd; +PIXA *pixa; + + PROCNAME("TestImage"); + + if ((pix = pixRead(filename)) == NULL) { + rp->success = FALSE; + return ERROR_INT("pix not made", procName, 1); + } + pixGetDimensions(pix, &w, &h, NULL); + if (w > MAX_WIDTH) { + factor = (l_float32)MAX_WIDTH / (l_float32)w; + pixs = pixScale(pix, factor, factor); + } + else + pixs = pixClone(pix); + pixDestroy(&pix); + + pixa = pixaCreate(0); + + /* Median cut quantizer (no dither; 5 sigbits) */ + pixaAddPix(pixa, pixs, L_COPY); + pixc = pixMedianCutQuantGeneral(pixs, 0, 0, 16, 5, 1, 1); + PixSave32(pixa, pixc, rp); + pixc = pixMedianCutQuantGeneral(pixs, 0, 0, 128, 5, 1, 1); + PixSave32(pixa, pixc, rp); + pixc = pixMedianCutQuantGeneral(pixs, 0, 0, 256, 5, 1, 1); + PixSave32(pixa, pixc, rp); + + /* Median cut quantizer (with dither; 5 sigbits) */ + pixaAddPix(pixa, pixs, L_COPY); + pixc = pixMedianCutQuantGeneral(pixs, 1, 0, 16, 5, 1, 1); + PixSave32(pixa, pixc, rp); + pixc = pixMedianCutQuantGeneral(pixs, 1, 0, 128, 5, 1, 1); + PixSave32(pixa, pixc, rp); + pixc = pixMedianCutQuantGeneral(pixs, 1, 0, 256, 5, 1, 1); + PixSave32(pixa, pixc, rp); + + /* Median cut quantizer (no dither; 6 sigbits) */ + pixaAddPix(pixa, pixs, L_COPY); + pixc = pixMedianCutQuantGeneral(pixs, 0, 0, 16, 6, 1, 1); + PixSave32(pixa, pixc, rp); + pixc = pixMedianCutQuantGeneral(pixs, 0, 0, 128, 6, 1, 1); + PixSave32(pixa, pixc, rp); + pixc = pixMedianCutQuantGeneral(pixs, 0, 0, 256, 6, 1, 1); + PixSave32(pixa, pixc, rp); + + /* Median cut quantizer (with dither; 6 sigbits) */ + pixaAddPix(pixa, pixs, L_COPY); + pixc = pixMedianCutQuantGeneral(pixs, 1, 0, 16, 6, 1, 1); + PixSave32(pixa, pixc, rp); + pixc = pixMedianCutQuantGeneral(pixs, 1, 0, 128, 6, 1, 1); + PixSave32(pixa, pixc, rp); + pixc = pixMedianCutQuantGeneral(pixs, 1, 0, 256, 6, 10, 1); + PixSave32(pixa, pixc, rp); + + /* Median cut quantizer (mixed color/gray) */ + pixaAddPix(pixa, pixs, L_COPY); + pixc = pixMedianCutQuantMixed(pixs, 20, 10, 0, 0, 0); + PixSave32(pixa, pixc, rp); + pixc = pixMedianCutQuantMixed(pixs, 60, 20, 0, 0, 0); + PixSave32(pixa, pixc, rp); + pixc = pixMedianCutQuantMixed(pixs, 180, 40, 0, 0, 0); + PixSave32(pixa, pixc, rp); + + /* Simple 256 cube octcube quantizer */ + pixaAddPix(pixa, pixs, L_COPY); + pixc = pixFixedOctcubeQuant256(pixs, 0); /* no dither */ + PixSave32(pixa, pixc, rp); + pixc = pixFixedOctcubeQuant256(pixs, 1); /* dither */ + PixSave32(pixa, pixc, rp); + pixc = pixFixedOctcubeQuant256(pixs, 1); /* dither */ + PixSave32(pixa, pixc, rp); + + /* 2-pass octree quantizer */ + pixc = pixOctreeColorQuant(pixs, 128, 0); /* no dither */ + PixSave32(pixa, pixc, rp); + pixc = pixOctreeColorQuant(pixs, 240, 0); /* no dither */ + PixSave32(pixa, pixc, rp); + pixc = pixOctreeColorQuant(pixs, 128, 1); /* dither */ + PixSave32(pixa, pixc, rp); + pixc = pixOctreeColorQuant(pixs, 240, 1); /* dither */ + PixSave32(pixa, pixc, rp); + + /* Simple adaptive quantization to 4 or 8 bpp, specifying ncolors */ + pixc = pixOctreeQuantNumColors(pixs, 8, 0); /* fixed: 8 colors */ + PixSave32(pixa, pixc, rp); + pixc = pixOctreeQuantNumColors(pixs, 16, 0); /* fixed: 16 colors */ + PixSave32(pixa, pixc, rp); + pixc = pixOctreeQuantNumColors(pixs, 64, 0); /* fixed: 64 colors */ + PixSave32(pixa, pixc, rp); + pixc = pixOctreeQuantNumColors(pixs, 256, 0); /* fixed: 256 colors */ + PixSave32(pixa, pixc, rp); + + /* Quantize to fully populated octree (RGB) at given level */ + pixc = pixFixedOctcubeQuantGenRGB(pixs, 2); /* level 2 */ + PixSave32(pixa, pixc, rp); + pixc = pixFixedOctcubeQuantGenRGB(pixs, 3); /* level 3 */ + PixSave32(pixa, pixc, rp); + pixc = pixFixedOctcubeQuantGenRGB(pixs, 4); /* level 4 */ + PixSave32(pixa, pixc, rp); + pixc = pixFixedOctcubeQuantGenRGB(pixs, 5); /* level 5 */ + PixSave32(pixa, pixc, rp); + + /* Generate 32 bpp RGB image with num colors <= 256 */ + pixt = pixOctreeQuantNumColors(pixs, 256, 0); /* cmapped version */ + pix32 = pixRemoveColormap(pixt, REMOVE_CMAP_BASED_ON_SRC); + + /* Quantize image with few colors at fixed octree leaf level */ + pixc = pixFewColorsOctcubeQuant1(pix32, 2); /* level 2 */ + PixSave32(pixa, pixc, rp); + pixc = pixFewColorsOctcubeQuant1(pix32, 3); /* level 3 */ + PixSave32(pixa, pixc, rp); + pixc = pixFewColorsOctcubeQuant1(pix32, 4); /* level 4 */ + PixSave32(pixa, pixc, rp); + pixc = pixFewColorsOctcubeQuant1(pix32, 5); /* level 5 */ + PixSave32(pixa, pixc, rp); + + /* Quantize image by population */ + pixc = pixOctreeQuantByPopulation(pixs, 3, 0); /* level 3, no dither */ + PixSave32(pixa, pixc, rp); + pixc = pixOctreeQuantByPopulation(pixs, 3, 1); /* level 3, dither */ + PixSave32(pixa, pixc, rp); + pixc = pixOctreeQuantByPopulation(pixs, 4, 0); /* level 4, no dither */ + PixSave32(pixa, pixc, rp); + pixc = pixOctreeQuantByPopulation(pixs, 4, 1); /* level 4, dither */ + PixSave32(pixa, pixc, rp); + + /* Mixed color/gray octree quantizer */ + pixaAddPix(pixa, pixt, L_COPY); + pixc = pixOctcubeQuantMixedWithGray(pix32, 8, 64, 10); /* max delta = 10 */ + PixSave32(pixa, pixc, rp); + pixc = pixOctcubeQuantMixedWithGray(pix32, 8, 64, 30); /* max delta = 30 */ + PixSave32(pixa, pixc, rp); + pixc = pixOctcubeQuantMixedWithGray(pix32, 8, 64, 50); /* max delta = 50 */ + PixSave32(pixa, pixc, rp); + + /* Run the high-level converter */ + pixaAddPix(pixa, pixt, L_COPY); + pixc = pixConvertRGBToColormap(pix32, 1); + PixSave32(pixa, pixc, rp); + + pixDestroy(&pix32); + pixDestroy(&pixt); + + pixd = pixaDisplayTiledInColumns(pixa, 4, 1.0, 25, 2); + pixDisplayWithTitle(pixd, 100, 100, NULL, rp->display); + snprintf(buf, sizeof(buf), "/tmp/lept/regout/disp.%d.jpg", i); + pixWrite(buf, pixd, IFF_JFIF_JPEG); + + pixDestroy(&pixs); + pixDestroy(&pixd); + pixaDestroy(&pixa); + return 0; +} + +static void +PixSave32(PIXA *pixa, PIX *pixc, L_REGPARAMS *rp) +{ +PIX *pix32; + + pix32 = pixConvertTo32(pixc); + pixaAddPix(pixa, pix32, L_INSERT); + regTestWritePixAndCheck(rp, pix32, IFF_JFIF_JPEG); + pixDestroy(&pixc); +} diff --git a/leptonica/prog/colorseg.jpg b/leptonica/prog/colorseg.jpg Binary files differnew file mode 100644 index 00000000..ef502eff --- /dev/null +++ b/leptonica/prog/colorseg.jpg diff --git a/leptonica/prog/colorseg_reg.c b/leptonica/prog/colorseg_reg.c new file mode 100644 index 00000000..4a212e84 --- /dev/null +++ b/leptonica/prog/colorseg_reg.c @@ -0,0 +1,113 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * colorseg_reg.c + * + * This explores the space of the four parameters input for color + * segmentation. Of the four, only two strongly determine the + * output result: + * maxdist (the maximum distance between pixels that get + * clustered: 20 is very small, 180 is very large) + * selsize (responsible for smoothing the result: 0 is no + * smoothing (fine texture), 8 is large smoothing) + * + * For large selsize (>~ 6), large regions get the same color, + * and there are few colors in the final result. + * + * The other two parameters, maxcolors and finalcolors, can be + * set small (~4) or large (~20). When set large, @maxdist will + * be most influential in determining the actual number of colors. + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + +static const l_int32 MaxColors[] = {4, 8, 16}; +static const l_int32 FinalColors[] = {4, 8, 16}; + +int main(int argc, + char **argv) +{ +l_int32 i, j, k, maxdist, maxcolors, selsize, finalcolors; +l_int32 nc, rval, gval, bval; +PIX *pixs, *pix1, *pix2; +PIXA *pixa; +PIXCMAP *cmap, *cmapr; +L_REGPARAMS *rp; + + if (regTestSetup(argc, argv, &rp)) + return 1; + + pixs = pixRead("tetons.jpg"); + for (k = 0; k < 3; k++) { + maxcolors = MaxColors[k]; + finalcolors = FinalColors[k]; + pixa = pixaCreate(0); + for (i = 1; i <= 9; i++) { + maxdist = 20 * i; + for (j = 0; j <= 6; j++) { + selsize = j; + pix1 = pixColorSegment(pixs, maxdist, maxcolors, selsize, + finalcolors, 0); + pixaAddPix(pixa, pix1, L_INSERT); + } + } + + pix2 = pixaDisplayTiledInColumns(pixa, 7, 1.0, 15, 2); + regTestWritePixAndCheck(rp, pix2, IFF_JFIF_JPEG); /* 0, 1, 2 */ + pixDisplayWithTitle(pix2, 100, k * 300, "colorseg", rp->display); + pixDestroy(&pix2); + pixaDestroy(&pixa); + } + pixDestroy(&pixs); + + pixs = pixRead("wyom.jpg"); + pix1 = pixColorSegment(pixs, 50, 6, 6, 6, 0); + cmap = pixGetColormap(pix1); + nc = pixcmapGetCount(cmap); + cmapr = pixcmapCreateRandom(8, 0, 0); + for (i = 0; i < nc; i++) { + pix2 = pixMakeMaskFromVal(pix1, i); + pixcmapGetColor(cmapr, i, &rval, &gval, &bval); + pixRenderHashMaskArb(pixs, pix2, 0, 0, 8, 3, i % 4, 0, + rval, gval, bval); + pixDestroy(&pix2); + } + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 3 */ + regTestWritePixAndCheck(rp, pixs, IFF_JFIF_JPEG); /* 4 */ + pixDisplayWithTitle(pix1, 800, 0, NULL, rp->display); + pixDisplayWithTitle(pixs, 800, 640, NULL, rp->display); + pixDestroy(&pix1); + pixDestroy(&pixs); + pixcmapDestroy(&cmapr); + + return regTestCleanup(rp); +} + diff --git a/leptonica/prog/colorsegtest.c b/leptonica/prog/colorsegtest.c new file mode 100644 index 00000000..121c0e2a --- /dev/null +++ b/leptonica/prog/colorsegtest.c @@ -0,0 +1,109 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * colorsegtest.c + * + * See colorseg.c for details. + * + * Just for fun, try these combinations of the 4 parameters below on + * the image tetons.jpg: + * 30 20 5 10 (20 colors) + * 40 20 7 15 (19 colors) + * 50 12 5 12 (12 colors) + * 50 12 3 12 (12 colors) + * 30 13 3 13 (12 colors) + * 30 20 3 20 (20 colors) + * 15 20 5 15 (19 colors) + * 80 20 3 20 (12 colors) + * 100 15 5 15 (7 colors) + * 100 15 2 15 (7 colors) + * 100 15 0 15 (7 colors) + * 30 15 0 15 (12 colors) + * 150 15 0 15 (4 colors) + * 150 15 2 15 (4 colors) + * 180 6 2 6 (3 colors) + * 180 6 0 6 (3 colors) + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + +static const l_int32 MAX_DIST = 120; +static const l_int32 MAX_COLORS = 15; +static const l_int32 SEL_SIZE = 4; +static const l_int32 FINAL_COLORS = 15; + + +int main(int argc, + char **argv) +{ +l_int32 max_dist, max_colors, sel_size, final_colors; +PIX *pixs, *pixd, *pixt; +char *filein, *fileout; +static char mainName[] = "colorsegtest"; + + if (argc != 3 && argc != 7) + return ERROR_INT( + "Syntax: colorsegtest filein fileout" + " [max_dist max_colors sel_size final_colors]\n" + " Default values are: max_dist = 120\n" + " max_colors = 15\n" + " sel_size = 4\n" + " final_colors = 15\n", mainName, 1); + filein = argv[1]; + fileout = argv[2]; + if (argc == 3) { /* use default values */ + max_dist = MAX_DIST; + max_colors = MAX_COLORS; + sel_size = SEL_SIZE; + final_colors = FINAL_COLORS; + } + else { /* 6 input args */ + max_dist = atoi(argv[3]); + max_colors = atoi(argv[4]); + sel_size = atoi(argv[5]); + final_colors = atoi(argv[6]); + } + setLeptDebugOK(1); + + if ((pixs = pixRead(filein)) == NULL) + return ERROR_INT("pixs not made", mainName, 1); + startTimer(); + pixt = pixRemoveColormap(pixs, REMOVE_CMAP_BASED_ON_SRC); + pixd = pixColorSegment(pixt, max_dist, max_colors, sel_size, + final_colors, 1); + lept_stderr("Time to segment: %7.3f sec\n", stopTimer()); + pixWrite(fileout, pixd, IFF_PNG); + + pixDestroy(&pixs); + pixDestroy(&pixd); + return 0; +} + diff --git a/leptonica/prog/colorspace_reg.c b/leptonica/prog/colorspace_reg.c new file mode 100644 index 00000000..07284c6a --- /dev/null +++ b/leptonica/prog/colorspace_reg.c @@ -0,0 +1,208 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * colorspace_reg.c + * + * Tests: + * - conversions between HSV and both RGB and colormapped images. + * - global linear color mapping and extraction of color magnitude + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + +int main(int argc, + char **argv) +{ +char label[512]; +l_int32 rval, gval, bval, w, h, i, j, rwhite, gwhite, bwhite, count; +l_uint32 pixel; +GPLOT *gplot1, *gplot2; +NUMA *naseq, *na; +NUMAA *naa1, *naa2; +PIX *pixs, *pix0, *pix1, *pix2, *pix3; +PIX *pixr, *pixg, *pixb; /* for color content extraction */ +PIXA *pixa, *pixat; +PIXCMAP *cmap; +L_REGPARAMS *rp; + +#if !defined(HAVE_LIBPNG) + L_ERROR("This test requires libpng to run.\n", "colorspace_reg"); + exit(77); +#endif + + if (regTestSetup(argc, argv, &rp)) + return 1; + + /* Generate a pdf of results when called with display */ + pixa = pixaCreate(0); + + /* Generate colors by sampling hue with max sat and value. + * This image has been saved as 19-colors.png. */ + pixat = pixaCreate(19); + for (i = 0; i < 19; i++) { + convertHSVToRGB((240 * i / 18), 255, 255, &rval, &gval, &bval); + composeRGBPixel(rval, gval, bval, &pixel); + pix1 = pixCreate(50, 100, 32); + pixSetAllArbitrary(pix1, pixel); + pixaAddPix(pixat, pix1, L_INSERT); + } + pix2 = pixaDisplayTiledInRows(pixat, 32, 1100, 1.0, 0, 0, 0); + regTestWritePixAndCheck(rp, pix2, IFF_PNG); /* 0 */ + pixaAddPix(pixa, pix2, L_INSERT); + pixaDestroy(&pixat); + + /* Colorspace conversion in rgb */ + pixs = pixRead("wyom.jpg"); + pixaAddPix(pixa, pixs, L_INSERT); + pix3 = pixConvertRGBToHSV(NULL, pixs); + regTestWritePixAndCheck(rp, pix3, IFF_JFIF_JPEG); /* 1 */ + pixaAddPix(pixa, pix3, L_COPY); + pixConvertHSVToRGB(pix3, pix3); + regTestWritePixAndCheck(rp, pix3, IFF_JFIF_JPEG); /* 2 */ + pixaAddPix(pixa, pix3, L_INSERT); + + /* Colorspace conversion on a colormap */ + pix3 = pixOctreeQuantNumColors(pixs, 25, 0); + regTestWritePixAndCheck(rp, pix3, IFF_JFIF_JPEG); /* 3 */ + pixaAddPix(pixa, pix3, L_COPY); + cmap = pixGetColormap(pix3); + if (rp->display) pixcmapWriteStream(stderr, cmap); + pixcmapConvertRGBToHSV(cmap); + if (rp->display) pixcmapWriteStream(stderr, cmap); + regTestWritePixAndCheck(rp, pix3, IFF_JFIF_JPEG); /* 4 */ + pixaAddPix(pixa, pix3, L_COPY); + pixcmapConvertHSVToRGB(cmap); + if (rp->display) pixcmapWriteStream(stderr, cmap); + regTestWritePixAndCheck(rp, pix3, IFF_JFIF_JPEG); /* 5 */ + pixaAddPix(pixa, pix3, L_INSERT); + + /* Color content extraction */ + pixColorContent(pixs, 0, 0, 0, 0, &pixr, &pixg, &pixb); + regTestWritePixAndCheck(rp, pixr, IFF_JFIF_JPEG); /* 6 */ + pixaAddPix(pixa, pixr, L_INSERT); + regTestWritePixAndCheck(rp, pixg, IFF_JFIF_JPEG); /* 7 */ + pixaAddPix(pixa, pixg, L_INSERT); + regTestWritePixAndCheck(rp, pixb, IFF_JFIF_JPEG); /* 8 */ + pixaAddPix(pixa, pixb, L_INSERT); + + /* Color content measurement. This tests the global + * mapping of (r,g,b) --> (white), for 20 different + * values of (r,g,b). For each mappings, we compute + * the color magnitude and threshold it at six values. + * For each of those six thresholds, we plot the + * fraction of pixels that exceeds the threshold + * color magnitude, where the red value (mapped to + * white) goes between 100 and 195. */ + pixat = pixaCreate(20); + naseq = numaMakeSequence(100, 5, 20); + naa1 = numaaCreate(6); + naa2 = numaaCreate(6); + for (i = 0; i < 6; i++) { + na = numaCreate(20); + numaaAddNuma(naa1, na, L_COPY); + numaaAddNuma(naa2, na, L_INSERT); + } + pixGetDimensions(pixs, &w, &h, NULL); + for (i = 0; i < 20; i++) { + rwhite = 100 + 5 * i; + gwhite = 200 - 5 * i; + bwhite = 150; + pix0 = pixGlobalNormRGB(NULL, pixs, rwhite, gwhite, bwhite, 255); + pixaAddPix(pixat, pix0, L_INSERT); + pix1 = pixColorMagnitude(pixs, rwhite, gwhite, bwhite, + L_AVE_MAX_DIFF_2); + for (j = 0; j < 6; j++) { + pix2 = pixThresholdToBinary(pix1, 30 + 10 * j); + pixInvert(pix2, pix2); + pixCountPixels(pix2, &count, NULL); + na = numaaGetNuma(naa1, j, L_CLONE); + numaAddNumber(na, (l_float32)count / (l_float32)(w * h)); + numaDestroy(&na); + pixDestroy(&pix2); + } + pixDestroy(&pix1); + pix1 = pixColorMagnitude(pixs, rwhite, gwhite, bwhite, L_INTERMED_DIFF); + for (j = 0; j < 6; j++) { + pix2 = pixThresholdToBinary(pix1, 30 + 10 * j); + pixInvert(pix2, pix2); + pixCountPixels(pix2, &count, NULL); + na = numaaGetNuma(naa2, j, L_CLONE); + numaAddNumber(na, (l_float32)count / (l_float32)(w * h)); + numaDestroy(&na); + pixDestroy(&pix2); + } + pixDestroy(&pix1); + } + gplot1 = gplotCreate("/tmp/lept/regout/colorspace.10", GPLOT_PNG, + "Fraction with given color (diff from average)", + "white point space for red", "amount of color"); + gplot2 = gplotCreate("/tmp/lept/regout/colorspace.11", GPLOT_PNG, + "Fraction with given color (min diff)", + "white point space for red", "amount of color"); + for (j = 0; j < 6; j++) { + na = numaaGetNuma(naa1, j, L_CLONE); + snprintf(label, sizeof(label), "thresh %d", 30 + 10 * j); + gplotAddPlot(gplot1, naseq, na, GPLOT_LINES, label); + numaDestroy(&na); + na = numaaGetNuma(naa2, j, L_CLONE); + gplotAddPlot(gplot2, naseq, na, GPLOT_LINES, label); + numaDestroy(&na); + } + gplotMakeOutput(gplot1); + gplotMakeOutput(gplot2); + gplotDestroy(&gplot1); + gplotDestroy(&gplot2); + pix1 = pixaDisplayTiledAndScaled(pixat, 32, 250, 4, 0, 10, 2); + regTestWritePixAndCheck(rp, pix1, IFF_JFIF_JPEG); /* 9 */ + pixaAddPix(pixa, pix1, L_INSERT); + pixDisplayWithTitle(pix1, 0, 100, "Color magnitude", rp->display); + pixaDestroy(&pixat); + numaDestroy(&naseq); + numaaDestroy(&naa1); + numaaDestroy(&naa2); + + /* Save as golden files, or check against them */ + regTestCheckFile(rp, "/tmp/lept/regout/colorspace.10.png"); /* 10 */ + regTestCheckFile(rp, "/tmp/lept/regout/colorspace.11.png"); /* 11 */ + + if (rp->display) { + pix3 = pixRead("/tmp/lept/regout/colorspace.10.png"); + pixaAddPix(pixa, pix3, L_INSERT); + pix3 = pixRead("/tmp/lept/regout/colorspace.11.png"); + pixaAddPix(pixa, pix3, L_INSERT); + pixaConvertToPdf(pixa, 0, 1.0, 0, 0, "colorspace tests", + "/tmp/lept/regout/colorspace.pdf"); + L_INFO("Output pdf: /tmp/lept/regout/colorspace.pdf\n", rp->testname); + } + pixaDestroy(&pixa); + + return regTestCleanup(rp); +} diff --git a/leptonica/prog/comap.063.jpg b/leptonica/prog/comap.063.jpg Binary files differnew file mode 100644 index 00000000..cda10e35 --- /dev/null +++ b/leptonica/prog/comap.063.jpg diff --git a/leptonica/prog/comap.068.jpg b/leptonica/prog/comap.068.jpg Binary files differnew file mode 100644 index 00000000..c8e64a4c --- /dev/null +++ b/leptonica/prog/comap.068.jpg diff --git a/leptonica/prog/comap.073.jpg b/leptonica/prog/comap.073.jpg Binary files differnew file mode 100644 index 00000000..ec28b4fa --- /dev/null +++ b/leptonica/prog/comap.073.jpg diff --git a/leptonica/prog/comap.100.jpg b/leptonica/prog/comap.100.jpg Binary files differnew file mode 100644 index 00000000..fdf65952 --- /dev/null +++ b/leptonica/prog/comap.100.jpg diff --git a/leptonica/prog/comap.110.jpg b/leptonica/prog/comap.110.jpg Binary files differnew file mode 100644 index 00000000..fdda284a --- /dev/null +++ b/leptonica/prog/comap.110.jpg diff --git a/leptonica/prog/comap.118.jpg b/leptonica/prog/comap.118.jpg Binary files differnew file mode 100644 index 00000000..96ae6f26 --- /dev/null +++ b/leptonica/prog/comap.118.jpg diff --git a/leptonica/prog/compare_reg.c b/leptonica/prog/compare_reg.c new file mode 100644 index 00000000..de5fe5a7 --- /dev/null +++ b/leptonica/prog/compare_reg.c @@ -0,0 +1,143 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * compare_reg.c + * + * This tests comparison of images that are: + * + * (1) translated with respect to each other + * (2) only slightly different in content + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "string.h" +#include "allheaders.h" + +l_int32 main(int argc, + char **argv) +{ +l_int32 delx, dely, etransx, etransy, w, h, area1, area2; +l_int32 *stab, *ctab; +l_float32 cx1, cy1, cx2, cy2, score, fract; +PIX *pix0, *pix1, *pix2, *pix3, *pix4, *pix5; +L_REGPARAMS *rp; + +#if !defined(HAVE_LIBPNG) + L_ERROR("This test requires libpng to run.\n", "compare_reg"); + exit(77); +#endif + + if (regTestSetup(argc, argv, &rp)) + return 1; + + /* ------------ Test of pixBestCorrelation() --------------- */ + pix0 = pixRead("harmoniam100-11.png"); + pix1 = pixConvertTo1(pix0, 160); + pixGetDimensions(pix1, &w, &h, NULL); + + /* Now make a smaller image, translated by (-32, -12) + * Except for the resizing, this is equivalent to + * pix2 = pixTranslate(NULL, pix1, -32, -12, L_BRING_IN_WHITE); */ + pix2 = pixCreate(w - 10, h, 1); + pixRasterop(pix2, 0, 0, w, h, PIX_SRC, pix1, 32, 12); + + /* Get the number of FG pixels and the centroid locations */ + stab = makePixelSumTab8(); + ctab = makePixelCentroidTab8(); + pixCountPixels(pix1, &area1, stab); + pixCountPixels(pix2, &area2, stab); + pixCentroid(pix1, ctab, stab, &cx1, &cy1); + pixCentroid(pix2, ctab, stab, &cx2, &cy2); + etransx = lept_roundftoi(cx1 - cx2); + etransy = lept_roundftoi(cy1 - cy2); + lept_stderr("delta cx = %d, delta cy = %d\n", etransx, etransy); + + /* Get the best correlation, searching around the translation + * where the centroids coincide */ + pixBestCorrelation(pix1, pix2, area1, area2, etransx, etransy, + 4, stab, &delx, &dely, &score, 5); + lept_stderr("delx = %d, dely = %d, score = %7.4f\n", delx, dely, score); + regTestCompareValues(rp, 32, delx, 0); /* 0 */ + regTestCompareValues(rp, 12, dely, 0); /* 1 */ + lept_mv("/tmp/lept/comp/correl_5.png", "lept/regout", NULL, NULL); + regTestCheckFile(rp, "/tmp/lept/regout/correl_5.png"); /* 2 */ + lept_free(stab); + lept_free(ctab); + pixDestroy(&pix0); + pixDestroy(&pix1); + pixDestroy(&pix2); + + + /* ------------ Test of pixCompareWithTranslation() ------------ */ + /* Now use the pyramid to get the result. Do a translation + * to remove pixels at the bottom from pix2, so that the + * centroids are initially far apart. */ + pix1 = pixRead("harmoniam-11.tif"); + pix2 = pixTranslate(NULL, pix1, -45, 25, L_BRING_IN_WHITE); + l_pdfSetDateAndVersion(0); + pixCompareWithTranslation(pix1, pix2, 160, &delx, &dely, &score, 1); + pixDestroy(&pix1); + pixDestroy(&pix2); + lept_stderr("delx = %d, dely = %d\n", delx, dely); + regTestCompareValues(rp, 45, delx, 0); /* 3 */ + regTestCompareValues(rp, -25, dely, 0); /* 4 */ + lept_mv("/tmp/lept/comp/correl.pdf", "lept/regout", NULL, NULL); + lept_mv("/tmp/lept/comp/compare.pdf", "lept/regout", NULL, NULL); + regTestCheckFile(rp, "/tmp/lept/regout/compare.pdf"); /* 5 */ + regTestCheckFile(rp, "/tmp/lept/regout/correl.pdf"); /* 6 */ + + /* ------------ Test of pixGetPerceptualDiff() --------------- */ + pix0 = pixRead("greencover.jpg"); + pix1 = pixRead("redcover.jpg"); /* pre-scaled to the same size */ + /* Apply directly to the color images */ + pixGetPerceptualDiff(pix0, pix1, 1, 3, 20, &fract, &pix2, &pix3); + lept_stderr("Fraction of color pixels = %f\n", fract); + regTestCompareValues(rp, 0.061252, fract, 0.01); /* 7 */ + regTestWritePixAndCheck(rp, pix2, IFF_JFIF_JPEG); /* 8 */ + regTestWritePixAndCheck(rp, pix3, IFF_TIFF_G4); /* 9 */ + pixDestroy(&pix2); + pixDestroy(&pix3); + /* Apply to grayscale images */ + pix2 = pixConvertTo8(pix0, 0); + pix3 = pixConvertTo8(pix1, 0); + pixGetPerceptualDiff(pix2, pix3, 1, 3, 20, &fract, &pix4, &pix5); + lept_stderr("Fraction of grayscale pixels = %f\n", fract); + regTestCompareValues(rp, 0.046928, fract, 0.0002); /* 10 */ + regTestWritePixAndCheck(rp, pix4, IFF_JFIF_JPEG); /* 11 */ + regTestWritePixAndCheck(rp, pix5, IFF_TIFF_G4); /* 12 */ + pixDestroy(&pix0); + pixDestroy(&pix1); + pixDestroy(&pix2); + pixDestroy(&pix3); + pixDestroy(&pix4); + pixDestroy(&pix5); + + return regTestCleanup(rp); +} diff --git a/leptonica/prog/comparepages.c b/leptonica/prog/comparepages.c new file mode 100644 index 00000000..45437356 --- /dev/null +++ b/leptonica/prog/comparepages.c @@ -0,0 +1,116 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * comparepages.c + * + * This compares text pages using the location of word bounding boxes. + * The goal is to get a fast and robust determination for whether + * two pages are the same. + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + +int main(int argc, + char **argv) +{ +l_int32 w, h, n, same; +BOXA *boxa1, *boxa2; +NUMA *nai1, *nai2; +NUMAA *naa1, *naa2; +PIX *pixs, *pixt, *pixb1, *pixb2; + + setLeptDebugOK(1); + lept_mkdir("lept/comp"); + + pixs = pixRead("lucasta.047.jpg"); + pixb1 = pixConvertTo1(pixs, 128); + pixGetWordBoxesInTextlines(pixb1, 10, 10, 500, 50, &boxa1, &nai1); + pixt = pixDrawBoxaRandom(pixs, boxa1, 2); + pixDisplay(pixt, 100, 100); + pixWrite("/tmp/lept/comp/pixt.png", pixt, IFF_PNG); + naa1 = boxaExtractSortedPattern(boxa1, nai1); + numaaWrite("/tmp/lept/comp/naa1.naa", naa1); + n = numaaGetCount(naa1); + lept_stderr("Number of textlines = %d\n", n); + pixDisplay(pixb1, 300, 0); + + /* Translate */ + pixb2 = pixCreateTemplate(pixb1); + pixGetDimensions(pixb1, &w, &h, NULL); + pixRasterop(pixb2, 148, 133, w, h, PIX_SRC, pixb1, 0, 0); + pixDisplay(pixb2, 600, 0); + pixGetWordBoxesInTextlines(pixb2, 10, 10, 500, 50, &boxa2, &nai2); + naa2 = boxaExtractSortedPattern(boxa2, nai2); + numaaCompareImagesByBoxes(naa1, naa2, 5, 10, 150, 150, 20, 20, &same, 1); + lept_stderr("Translation. same?: %d\n\n", same); + boxaDestroy(&boxa2); + numaDestroy(&nai2); + pixDestroy(&pixb2); + numaaDestroy(&naa2); + + /* Aligned part is below h/3 */ + pixb2 = pixCreateTemplate(pixb1); + pixGetDimensions(pixb1, &w, &h, NULL); + pixRasterop(pixb2, 0, 0, w, h / 3, PIX_SRC, pixb1, 0, 2 * h / 3); + pixRasterop(pixb2, 0, h / 3, w, 2 * h / 3, PIX_SRC, pixb1, 0, h / 3); + pixDisplay(pixb2, 900, 0); + pixGetWordBoxesInTextlines(pixb2, 10, 10, 500, 50, &boxa2, &nai2); + naa2 = boxaExtractSortedPattern(boxa2, nai2); + numaaCompareImagesByBoxes(naa1, naa2, 5, 10, 150, 150, 20, 20, &same, 1); + lept_stderr("Aligned part below h/3. same?: %d\n\n", same); + boxaDestroy(&boxa2); + numaDestroy(&nai2); + pixDestroy(&pixb2); + numaaDestroy(&naa2); + + /* Top and bottom switched; no aligned parts */ + pixb2 = pixCreateTemplate(pixb1); + pixGetDimensions(pixb1, &w, &h, NULL); + pixRasterop(pixb2, 0, 0, w, h / 3, PIX_SRC, pixb1, 0, 2 * h / 3); + pixRasterop(pixb2, 0, h / 3, w, 2 * h / 3, PIX_SRC, pixb1, 0, 0); + pixDisplay(pixb2, 1200, 0); + pixGetWordBoxesInTextlines(pixb2, 10, 10, 500, 50, &boxa2, &nai2); + naa2 = boxaExtractSortedPattern(boxa2, nai2); + numaaCompareImagesByBoxes(naa1, naa2, 5, 10, 150, 150, 20, 20, &same, 1); + lept_stderr("Top/Bot switched; no alignment. Same?: %d\n", same); + boxaDestroy(&boxa2); + numaDestroy(&nai2); + pixDestroy(&pixb2); + numaaDestroy(&naa2); + + boxaDestroy(&boxa1); + numaDestroy(&nai1); + pixDestroy(&pixs); + pixDestroy(&pixb1); + pixDestroy(&pixt); + numaaDestroy(&naa1); + return 0; +} diff --git a/leptonica/prog/comparepixa.c b/leptonica/prog/comparepixa.c new file mode 100644 index 00000000..d8dace51 --- /dev/null +++ b/leptonica/prog/comparepixa.c @@ -0,0 +1,101 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * comparepixa.c + * + * comparepixa file1 file2 nx ny tw spacing border fontsize fileout + * + * This reads two pixa or pixacomp from files and renders them + * interleaved, side-by-side in a pdf. A warning is issued if the + * input image arrays have different lengths. + * + * The integers nx and ny specify how many side-by-side pairs + * are displayed on each pdf page. For example, if nx = 1 and ny = 2, + * then two pairs are shown, one above the other. + * + * The input pix are scaled to tw, the target width, then paired + * up with %spacing and an optional %border. + * + * The pairs are then mosaiced, depending on %nx and %ny, into + * a set of larger images. The %spacing and %border parameters + * are used here as well. To label each pair with the index from + * the input arrays, choose fontsize in {4, 6, 8, 10, 12, 14, 16, 18, 20}. + * To skip labelling, set %fontsize = 0. + * + * This set of images is rendered into a pdf and written to %fileont. + * + * Typical numbers for the input parameters are: + * %nx = small integer (1 - 4) + * %ny = 2 * %nx + * %tw = 200 - 500 pixels + * %spacing = 10 + * %border = 2 + * %fontsize = 10 + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + +int main(int argc, + char **argv) +{ +char *fileout; +l_int32 nx, ny, tw, spacing, border, fontsize; +PIXA *pixa1, *pixa2; +static char mainName[] = "comparepixa"; + + if (argc != 10) { + lept_stderr("Syntax error in comparepixa:\n" + " comparepixa file1 file2 nx ny tw spacing border" + " fontsize fileout\n"); + return 1; + } + setLeptDebugOK(1); + + /* Input files can be either pixa or pixacomp */ + if ((pixa1 = pixaReadBoth(argv[1])) == NULL) + return ERROR_INT("pixa1 not read", mainName, 1); + if ((pixa2 = pixaReadBoth(argv[2])) == NULL) + return ERROR_INT("pixa2 not read", mainName, 1); + nx = atoi(argv[3]); + ny = atoi(argv[4]); + tw = atoi(argv[5]); + spacing = atoi(argv[6]); + border = atoi(argv[7]); + fontsize = atoi(argv[8]); + fileout = argv[9]; + + pixaCompareInPdf(pixa1, pixa2, nx, ny, tw, spacing, border, + fontsize, fileout); + pixaDestroy(&pixa1); + pixaDestroy(&pixa2); + return 0; +} + diff --git a/leptonica/prog/comparetest.c b/leptonica/prog/comparetest.c new file mode 100644 index 00000000..a094efd1 --- /dev/null +++ b/leptonica/prog/comparetest.c @@ -0,0 +1,159 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * comparetest.c + * + * comparetest filein1 filein2 type fileout + * + * where + * type = {0, 1} for {abs-diff and subtraction} comparisons + * + * Compares two images, using either the absolute value of the + * pixel differences or the difference clipped to 0. For RGB, + * the differences are computed separately on each component. + * If one has a colormap and the other doesn't, the colormap + * is removed before making the comparison. + * + * Warning: you usually want to use abs-diff to compare + * two grayscale or color images. If you use subtraction, + * the result you get will depend on the order of the input images. + * For example, if pix2 = pixDilateGray(pix1), then every + * pixel in pix1 will be equal to or greater than pix2. So if + * you subtract pix2 from pix1, you will get 0 for all pixels, + * which looks like they're the same! + * + * Here's an interesting observation. Take an image that has + * been jpeg compressed at a quality = 75. If you re-compress + * the image, what quality factor should be used to minimize + * the change? Answer: 75 (!) + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + +int main(int argc, + char **argv) +{ +l_int32 type, comptype, d1, d2, same, first, last; +l_float32 fract, diff, rmsdiff; +char *filein1, *filein2, *fileout; +GPLOT *gplot; +NUMA *na1, *na2; +PIX *pixs1, *pixs2, *pixd; +static char mainName[] = "comparetest"; + + if (argc != 5) + return ERROR_INT(" Syntax: comparetest filein1 filein2 type fileout", + mainName, 1); + filein1 = argv[1]; + filein2 = argv[2]; + type = atoi(argv[3]); + pixd = NULL; + fileout = argv[4]; + setLeptDebugOK(1); + + /* If comparing image files with 16 bps and spp > 1, + * comment this line out to strip 16 --> 8 spp */ + l_pngSetReadStrip16To8(0); + + if ((pixs1 = pixRead(filein1)) == NULL) + return ERROR_INT("pixs1 not made", mainName, 1); + if ((pixs2 = pixRead(filein2)) == NULL) + return ERROR_INT("pixs2 not made", mainName, 1); + d1 = pixGetDepth(pixs1); + d2 = pixGetDepth(pixs2); + + if (d1 == 1 && d2 == 1) { + pixEqual(pixs1, pixs2, &same); + if (same) { + lept_stderr("Images are identical\n"); + pixd = pixCreateTemplate(pixs1); /* write empty pix for diff */ + } else { + if (type == 0) + comptype = L_COMPARE_XOR; + else + comptype = L_COMPARE_SUBTRACT; + pixCompareBinary(pixs1, pixs2, comptype, &fract, &pixd); + lept_stderr("Fraction of different pixels: %10.6f\n", fract); + } + pixWrite(fileout, pixd, IFF_PNG); + } else { + if (type == 0) + comptype = L_COMPARE_ABS_DIFF; + else + comptype = L_COMPARE_SUBTRACT; + pixCompareGrayOrRGB(pixs1, pixs2, comptype, GPLOT_PNG, &same, &diff, + &rmsdiff, &pixd); + if (type == 0) { + if (same) { + lept_stderr("Images are identical\n"); + } else { + lept_stderr("Images differ: <diff> = %10.6f\n", diff); + lept_stderr(" <rmsdiff> = %10.6f\n", rmsdiff); + } + } + else { /* subtraction */ + if (same) { + lept_stderr("pixs2 strictly greater than pixs1\n"); + } else { + lept_stderr("Images differ: <diff> = %10.6f\n", diff); + lept_stderr(" <rmsdiff> = %10.6f\n", rmsdiff); + } + } + if (d1 != 16) + pixWrite(fileout, pixd, IFF_JFIF_JPEG); + else + pixWrite(fileout, pixd, IFF_PNG); + + if (d1 != 16 && !same) { + na1 = pixCompareRankDifference(pixs1, pixs2, 1); + if (na1) { + numaGetNonzeroRange(na1, 0.00005, &first, &last); + lept_stderr("Nonzero diff range: first = %d, last = %d\n", + first, last); + na2 = numaClipToInterval(na1, first, last); + gplot = gplotCreate("/tmp/lept/comp/rank", GPLOT_PNG, + "Pixel Rank Difference", + "pixel val difference", "rank"); + gplotAddPlot(gplot, NULL, na2, GPLOT_LINES, "rank"); + gplotMakeOutput(gplot); + gplotDestroy(&gplot); + l_fileDisplay("/tmp/lept/comp/rank.png", 100, 100, 1.0); + numaDestroy(&na1); + numaDestroy(&na2); + } + } + } + + pixDestroy(&pixs1); + pixDestroy(&pixs2); + pixDestroy(&pixd); + return 0; +} diff --git a/leptonica/prog/compfilter_reg.c b/leptonica/prog/compfilter_reg.c new file mode 100644 index 00000000..1ceaee90 --- /dev/null +++ b/leptonica/prog/compfilter_reg.c @@ -0,0 +1,346 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * compfilter_reg.c + * + * Regression test for filters that select connected components + * based on size, using logical combinations of indicator arrays. + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + +static void Count_pieces(L_REGPARAMS *rp, PIX *pix, l_int32 nexp); +static void Count_pieces2(L_REGPARAMS *rp, BOXA *boxa, l_int32 nexp); +static l_int32 Count_ones(L_REGPARAMS *rp, NUMA *na, l_int32 nexp, + l_int32 index, const char *name); + +static const l_float32 edges[13] = {0.0f, 0.2f, 0.3f, 0.35f, 0.4f, 0.45f, 0.5f, + 0.55f, 0.6f, 0.7f, 0.8f, 0.9f, 1.0f}; + + /* for feyn.tif */ +static const l_int32 band[12] = {1, 11, 48, 264, 574, 704, 908, 786, 466, + 157, 156, 230}; +static const l_int32 total[12] = {1, 12, 60, 324, 898, 1602, 2510, 3296, + 3762, 3919, 4075, 4305}; +#if 0 + /* for rabi.png */ +static const l_int32 band[12] = {24, 295, 490, 817, 1768, 962, 8171, + 63, 81, 51, 137, 8619}; +static const l_int32 total[12] = {24, 319, 809, 1626, 3394, 4356, 12527, + 12590, 12671, 12722, 12859, 21478}; +#endif + + +int main(int argc, + char **argv) +{ +l_int32 w, h, n, i, sum, sumi, empty; +BOX *box1, *box2, *box3, *box4; +BOXA *boxa1, *boxa2; +NUMA *na1, *na2, *na3, *na4, *na5; +NUMA *na2i, *na3i, *na4i, *nat, *naw, *nah; +PIX *pixs, *pix1, *pix2, *pix3, *pix4; +PIXA *pixa1, *pixa2, *pixa3; +L_REGPARAMS *rp; + + if (regTestSetup(argc, argv, &rp)) + return 1; + + /* Draw 4 filled boxes of different sizes */ + pixs = pixCreate(200, 200, 1); + box1 = boxCreate(10, 10, 20, 30); + box2 = boxCreate(50, 10, 40, 20); + box3 = boxCreate(110, 10, 35, 5); + box4 = boxCreate(160, 10, 5, 15); + boxa1 = boxaCreate(4); + boxaAddBox(boxa1, box1, L_INSERT); + boxaAddBox(boxa1, box2, L_INSERT); + boxaAddBox(boxa1, box3, L_INSERT); + boxaAddBox(boxa1, box4, L_INSERT); + pixRenderBox(pixs, box1, 1, L_SET_PIXELS); + pixRenderBox(pixs, box2, 1, L_SET_PIXELS); + pixRenderBox(pixs, box3, 1, L_SET_PIXELS); + pixRenderBox(pixs, box4, 1, L_SET_PIXELS); + pix1 = pixFillClosedBorders(pixs, 4); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 0 */ + pix2 = pixCreateTemplate(pixs); + pixRenderHashBox(pix2, box1, 6, 4, L_POS_SLOPE_LINE, 1, L_SET_PIXELS); + pixRenderHashBox(pix2, box2, 7, 2, L_POS_SLOPE_LINE, 1, L_SET_PIXELS); + pixRenderHashBox(pix2, box3, 4, 2, L_VERTICAL_LINE, 1, L_SET_PIXELS); + pixRenderHashBox(pix2, box4, 3, 1, L_HORIZONTAL_LINE, 1, L_SET_PIXELS); + regTestWritePixAndCheck(rp, pix2, IFF_PNG); /* 1 */ + + /* Exercise the parameters: Reg indices 2-27 */ + pix3 = pixSelectBySize(pix1, 0, 22, 8, L_SELECT_HEIGHT, + L_SELECT_IF_GT, NULL); + Count_pieces(rp, pix3, 1); + pix3 = pixSelectBySize(pix1, 0, 30, 8, L_SELECT_HEIGHT, + L_SELECT_IF_LT, NULL); + Count_pieces(rp, pix3, 3); + pix3 = pixSelectBySize(pix1, 0, 5, 8, L_SELECT_HEIGHT, + L_SELECT_IF_GT, NULL); + Count_pieces(rp, pix3, 3); + pix3 = pixSelectBySize(pix1, 0, 6, 8, L_SELECT_HEIGHT, + L_SELECT_IF_LT, NULL); + Count_pieces(rp, pix3, 1); + pix3 = pixSelectBySize(pix1, 20, 0, 8, L_SELECT_WIDTH, + L_SELECT_IF_GT, NULL); + Count_pieces(rp, pix3, 2); + pix3 = pixSelectBySize(pix1, 31, 0, 8, L_SELECT_WIDTH, + L_SELECT_IF_LT, NULL); + Count_pieces(rp, pix3, 2); + pix3 = pixSelectBySize(pix1, 21, 10, 8, L_SELECT_IF_EITHER, + L_SELECT_IF_LT, NULL); + Count_pieces(rp, pix3, 3); + pix3 = pixSelectBySize(pix1, 20, 30, 8, L_SELECT_IF_EITHER, + L_SELECT_IF_GT, NULL); + Count_pieces(rp, pix3, 2); + pix3 = pixSelectBySize(pix1, 22, 32, 8, L_SELECT_IF_BOTH, + L_SELECT_IF_LT, NULL); + Count_pieces(rp, pix3, 2); + pix3 = pixSelectBySize(pix1, 6, 32, 8, L_SELECT_IF_BOTH, + L_SELECT_IF_LT, NULL); + Count_pieces(rp, pix3, 1); + pix3 = pixSelectBySize(pix1, 5, 25, 8, L_SELECT_IF_BOTH, + L_SELECT_IF_GT, NULL); + Count_pieces(rp, pix3, 1); + pix3 = pixSelectBySize(pix1, 25, 5, 8, L_SELECT_IF_BOTH, + L_SELECT_IF_GT, NULL); + Count_pieces(rp, pix3, 1); + + pix3 = pixSelectByPerimToAreaRatio(pix1, 0.3, 8, L_SELECT_IF_GT, NULL); + Count_pieces(rp, pix3, 2); + pix3 = pixSelectByPerimToAreaRatio(pix1, 0.15, 8, L_SELECT_IF_GT, NULL); + Count_pieces(rp, pix3, 3); + pix3 = pixSelectByPerimToAreaRatio(pix1, 0.4, 8, L_SELECT_IF_LTE, NULL); + Count_pieces(rp, pix3, 2); + pix3 = pixSelectByPerimToAreaRatio(pix1, 0.45, 8, L_SELECT_IF_LT, NULL); + Count_pieces(rp, pix3, 3); + + pix3 = pixSelectByPerimSizeRatio(pix2, 2.3, 8, L_SELECT_IF_GT, NULL); + Count_pieces(rp, pix3, 2); + pix3 = pixSelectByPerimSizeRatio(pix2, 1.2, 8, L_SELECT_IF_GT, NULL); + Count_pieces(rp, pix3, 3); + pix3 = pixSelectByPerimSizeRatio(pix2, 1.7, 8, L_SELECT_IF_LTE, NULL); + Count_pieces(rp, pix3, 1); + pix3 = pixSelectByPerimSizeRatio(pix2, 2.9, 8, L_SELECT_IF_LT, NULL); + Count_pieces(rp, pix3, 3); + + pix3 = pixSelectByAreaFraction(pix2, 0.3, 8, L_SELECT_IF_LT, NULL); + Count_pieces(rp, pix3, 0); + pix3 = pixSelectByAreaFraction(pix2, 0.9, 8, L_SELECT_IF_LT, NULL); + Count_pieces(rp, pix3, 4); + pix3 = pixSelectByAreaFraction(pix2, 0.5, 8, L_SELECT_IF_GTE, NULL); + Count_pieces(rp, pix3, 3); + pix3 = pixSelectByAreaFraction(pix2, 0.7, 8, L_SELECT_IF_GT, NULL); + Count_pieces(rp, pix3, 2); + + boxa2 = boxaSelectBySize(boxa1, 21, 10, L_SELECT_IF_EITHER, + L_SELECT_IF_LT, NULL); + Count_pieces2(rp, boxa2, 3); + boxa2 = boxaSelectBySize(boxa1, 22, 32, L_SELECT_IF_BOTH, + L_SELECT_IF_LT, NULL); + Count_pieces2(rp, boxa2, 2); + boxaDestroy(&boxa1); + pixDestroy(&pixs); + pixDestroy(&pix1); + pixDestroy(&pix2); + + /* Here's the most general method for selecting components. * + * We do it for area fraction, but any combination of * + * size, area/perimeter ratio and area fraction can be used. * + * Reg indices 28-85 */ + pixs = pixRead("feyn.tif"); + pix1 = pixCopy(NULL, pixs); /* subtract bands from this */ + pix2 = pixCreateTemplate(pixs); /* add bands to this */ + pixGetDimensions(pixs, &w, &h, NULL); + boxa1 = pixConnComp(pixs, &pixa1, 8); + n = boxaGetCount(boxa1); + na1 = pixaFindAreaFraction(pixa1); + nat = numaCreate(0); + numaSetCount(nat, n); /* initialize to all 0 */ + sum = sumi = 0; + pixa3 = pixaCreate(0); + for (i = 0; i < 12; i++) { + /* Compute within the intervals using an intersection. */ + na2 = numaMakeThresholdIndicator(na1, edges[i], L_SELECT_IF_GTE); + if (i != 11) + na3 = numaMakeThresholdIndicator(na1, edges[i + 1], L_SELECT_IF_LT); + else + na3 = numaMakeThresholdIndicator(na1, edges[i + 1], + L_SELECT_IF_LTE); + na4 = numaLogicalOp(NULL, na2, na3, L_INTERSECTION); + sum += Count_ones(rp, na4, 0, 0, NULL); + + /* Compute outside the intervals using a union, and invert */ + na2i = numaMakeThresholdIndicator(na1, edges[i], L_SELECT_IF_LT); + if (i != 11) + na3i = numaMakeThresholdIndicator(na1, edges[i + 1], + L_SELECT_IF_GTE); + else + na3i = numaMakeThresholdIndicator(na1, edges[i + 1], + L_SELECT_IF_GT); + na4i = numaLogicalOp(NULL, na3i, na2i, L_UNION); + numaInvert(na4i, na4i); + sumi += Count_ones(rp, na4i, 0, 0, NULL); + + /* Compare the two methods */ + if (sum != sumi) + lept_stderr("WRONG: sum = %d, sumi = %d\n", sum, sumi); + + /* Reconstruct the image, band by band. */ + numaLogicalOp(nat, nat, na4, L_UNION); + pixa2 = pixaSelectWithIndicator(pixa1, na4, NULL); + pix3 = pixaDisplay(pixa2, w, h); + pixOr(pix2, pix2, pix3); /* add them in */ + pix4 = pixCopy(NULL, pix2); /* destroyed by Count_pieces */ + Count_ones(rp, na4, band[i], i, "band"); + Count_pieces(rp, pix3, band[i]); + Count_ones(rp, nat, total[i], i, "total"); + Count_pieces(rp, pix4, total[i]); + pixaDestroy(&pixa2); + + /* Remove band successively from full image */ + pixRemoveWithIndicator(pix1, pixa1, na4); + pixaAddPix(pixa3, pix1, L_COPY); + numaDestroy(&na2); + numaDestroy(&na3); + numaDestroy(&na4); + numaDestroy(&na2i); + numaDestroy(&na3i); + numaDestroy(&na4i); + } + + /* Did we remove all components from pix1? */ + pixZero(pix1, &empty); + regTestCompareValues(rp, 1, empty, 0.0); + if (!empty) + lept_stderr("\nWRONG: not all pixels removed from pix1\n"); + + pixDestroy(&pixs); + pixDestroy(&pix1); + pixDestroy(&pix2); + boxaDestroy(&boxa1); + pixaDestroy(&pixa1); + numaDestroy(&na1); + numaDestroy(&nat); + + /* One last extraction. Get all components that have either + * a height of at least 50 or a width of between 30 and 35, + * and also have a relatively large perimeter/area ratio. */ + pixs = pixRead("feyn.tif"); + boxa1 = pixConnComp(pixs, &pixa1, 8); + n = boxaGetCount(boxa1); + pixaFindDimensions(pixa1, &naw, &nah); + na1 = pixaFindPerimToAreaRatio(pixa1); + na2 = numaMakeThresholdIndicator(nah, 50, L_SELECT_IF_GTE); + na3 = numaMakeThresholdIndicator(naw, 30, L_SELECT_IF_GTE); + na4 = numaMakeThresholdIndicator(naw, 35, L_SELECT_IF_LTE); + na5 = numaMakeThresholdIndicator(na1, 0.4, L_SELECT_IF_GTE); + numaLogicalOp(na3, na3, na4, L_INTERSECTION); + numaLogicalOp(na2, na2, na3, L_UNION); + numaLogicalOp(na2, na2, na5, L_INTERSECTION); + numaInvert(na2, na2); /* get components to be removed */ + pixRemoveWithIndicator(pixs, pixa1, na2); + regTestWritePixAndCheck(rp, pixs, IFF_PNG); /* 86 */ + pixaAddPix(pixa3, pixs, L_INSERT); + boxaDestroy(&boxa1); + pixaDestroy(&pixa1); + numaDestroy(&naw); + numaDestroy(&nah); + numaDestroy(&na1); + numaDestroy(&na2); + numaDestroy(&na3); + numaDestroy(&na4); + numaDestroy(&na5); + + if (rp->display) { + pix1 = pixaDisplayTiledInColumns(pixa3, 2, 0.25, 25, 2); + pixDisplay(pix1, 100, 100); + pixWrite("/tmp/lept/filter/result.png", pix1, IFF_PNG); + pixDestroy(&pix1); + } + pixaDestroy(&pixa3); + + return regTestCleanup(rp); +} + + +/* --------------------- Helpers -------------------------- */ + +static void +Count_pieces(L_REGPARAMS *rp, PIX *pix, l_int32 nexp) +{ +l_int32 n; +BOXA *boxa; + + if (rp->index > 28 && rp->index < 55) + regTestWritePixAndCheck(rp, pix, IFF_PNG); /* ... */ + boxa = pixConnComp(pix, NULL, 8); + n = boxaGetCount(boxa); + regTestCompareValues(rp, nexp, n, 0.0); + if (n != nexp) + lept_stderr("WRONG!: Num. comps = %d; expected = %d\n", n, nexp); + boxaDestroy(&boxa); + pixDestroy(&pix); +} + +static void +Count_pieces2(L_REGPARAMS *rp, BOXA *boxa, l_int32 nexp) +{ +l_int32 n; + + n = boxaGetCount(boxa); + regTestCompareValues(rp, nexp, n, 0.0); + if (n != nexp) + lept_stderr("WRONG!: Num. boxes = %d; expected = %d\n", n, nexp); + boxaDestroy(&boxa); +} + +static l_int32 +Count_ones(L_REGPARAMS *rp, NUMA *na, l_int32 nexp, + l_int32 index, const char *name) +{ +l_int32 i, n, val, sum; + + n = numaGetCount(na); + sum = 0; + for (i = 0; i < n; i++) { + numaGetIValue(na, i, &val); + if (val == 1) sum++; + } + if (!name) return sum; + regTestCompareValues(rp, nexp, sum, 0.0); + if (nexp != sum) + lept_stderr("WRONG! %s[%d]: num. ones = %d; expected = %d\n", + name, index, sum, nexp); + return 0; +} diff --git a/leptonica/prog/concatpdf.c b/leptonica/prog/concatpdf.c new file mode 100644 index 00000000..2d3976b0 --- /dev/null +++ b/leptonica/prog/concatpdf.c @@ -0,0 +1,177 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * concatpdf.c + * + * This program concatenates all pdfs in a directory by rendering them + * as images, optionally scaling the images, and generating an output pdf. + * The pdfs are taken in lexical order. + * + * It makes no other changes to the images, which are rendered + * by Poppler's pdftoppm. Compare with cleanpdf.c, which carries + * out several operations to make high resolution, 1 bpp g4-tiff + * encoded images in the pdf. + * + * Syntax: cconcatpdf basedir scalefactor outfile + * + * The %basedir is a directory where the input pdf files are located. + * The program will operate on every file in this directory with + * the ".pdf" extension. + * + * The %scalefactor is typically used to downscale the image to + * reduce the size of the generated pdf. It should not affect the + * pdf display otherwise. For normal text on images scanned at 300 ppi, + * a 2x reduction (%scalefactor = 0.5) may be satisfactory. + * We compute an output resolution for that pdf that will cause it + * to print 11 inches high, based on the height in pixels of the + * first image in the set. + * + * The pdf encoding for each page is chosen by the default mechanism. + * See selectDefaultPdfEncoding() for details. + * If DCT encoding (jpeg) is used, the quality factor is set to 50. + * This makes smaller files with (usually) decent image quality. + * + * The pdf output is written to %outfile. It is advisable (but not + * required) to have a '.pdf' extension. + * + * N.B. This requires the Poppler package of pdf utilities, such as + * pdfimages and pdftoppm. For non-unix systems, this requires + * installation of the cygwin Poppler package: + * https://cygwin.com/cgi-bin2/package-cat.cgi?file=x86/poppler/ + * poppler-0.26.5-1 + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#ifdef _WIN32 +# if defined(_MSC_VER) || defined(__MINGW32__) +# include <direct.h> +# else +# include <io.h> +# endif /* _MSC_VER || __MINGW32__ */ +#endif /* _WIN32 */ + +#include "string.h" +#include <sys/stat.h> +#include <sys/types.h> +#include "allheaders.h" + +l_int32 main(int argc, + char **argv) +{ +char buf[256]; +char *basedir, *fname, *tail, *basename, *imagedir, *outfile; +l_int32 res, i, n, ret; +l_float32 scalefactor; +PIX *pixs, *pix1; +PIXA *pixa1; +SARRAY *sa; +static char mainName[] = "concatpdf"; + + if (argc != 4) + return ERROR_INT( + "Syntax: concatpdf basedir scalefactor outfile", + mainName, 1); + basedir = argv[1]; + scalefactor = atof(argv[2]); + outfile = argv[3]; + setLeptDebugOK(1); + +#if 1 + /* Get the names of the pdf files */ + if ((sa = getSortedPathnamesInDirectory(basedir, "pdf", 0, 0)) == NULL) + return ERROR_INT("files not found", mainName, 1); + sarrayWriteStream(stderr, sa); + n = sarrayGetCount(sa); +#endif + + /* Rasterize: + * pdftoppm -r 150 fname outroot + * Use of pdftoppm: + * This works on all pdf pages, both wrapped images and pages that + * were made orthographically. We use the default output resolution + * of 150 ppi for pdftoppm, which makes uncompressed 6 MB files + * and is very fast. If you want higher resolution 1 bpp output, + * use cleanpdf.c. */ + imagedir = stringJoin(basedir, "/image"); +#if 1 +#ifndef _WIN32 + mkdir(imagedir, 0777); +#else + _mkdir(imagedir); +#endif /* _WIN32 */ + for (i = 0; i < n; i++) { + fname = sarrayGetString(sa, i, L_NOCOPY); + splitPathAtDirectory(fname, NULL, &tail); + splitPathAtExtension(tail, &basename, NULL); + snprintf(buf, sizeof(buf), "pdftoppm -r 150 %s %s/%s", + fname, imagedir, basename); + lept_free(tail); + lept_free(basename); + lept_stderr("%s\n", buf); + ret = system(buf); + } + sarrayDestroy(&sa); +#endif + +#if 1 + /* Scale and collect */ + sa = getSortedPathnamesInDirectory(imagedir, NULL, 0, 0); + sarrayWriteStream(stderr, sa); + n = sarrayGetCount(sa); + pixa1 = pixaCreate(n); + for (i = 0; i < n; i++) { + fname = sarrayGetString(sa, i, L_NOCOPY); + pixs = pixRead(fname); + if (scalefactor == 1.0) + pix1 = pixClone(pixs); + else + pix1 = pixScale(pixs, scalefactor, scalefactor); + pixaAddPix(pixa1, pix1, L_INSERT); + pixDestroy(&pixs); + } + sarrayDestroy(&sa); +#endif + +#if 1 + /* Generate the pdf. Compute the actual input resolution from + * the pixel dimensions of the first image. This will cause each + * page to be printed to cover an 8.5 x 11 inch sheet of paper. */ + lept_stderr("Write output to %s\n", outfile); + pix1 = pixaGetPix(pixa1, 0, L_CLONE); + pixInferResolution(pix1, 11.0, &res); + pixDestroy(&pix1); + pixaConvertToPdf(pixa1, res, 1.0, L_DEFAULT_ENCODE, 50, NULL, outfile); + pixaDestroy(&pixa1); +#endif + + return 0; +} + + diff --git a/leptonica/prog/conncomp_reg.c b/leptonica/prog/conncomp_reg.c new file mode 100644 index 00000000..a63569d8 --- /dev/null +++ b/leptonica/prog/conncomp_reg.c @@ -0,0 +1,163 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * conncomp_reg.c + * + * Regression test for connected components (both 4 and 8 + * connected), including regeneration of the original + * image from the components. This is also an implicit + * test of rasterop. + * + * Also tests iterative covering of connected components by + * minimum spanning rectangles. + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + +int main(int argc, + char **argv) +{ +l_uint8 *array1, *array2; +l_int32 i, n1, n2, n3; +size_t size1, size2; +FILE *fp; +BOXA *boxa1, *boxa2; +PIX *pixs, *pix1, *pix2, *pix3; +PIXA *pixa1; +PIXCMAP *cmap; +L_REGPARAMS *rp; + + if (regTestSetup(argc, argv, &rp)) + return 1; + + pixs = pixRead("feyn.tif"); + + /* --------------------------------------------------------------- * + * Test pixConnComp() and pixCountConnComp(), * + * with output to both boxa and pixa * + * --------------------------------------------------------------- */ + /* First, test with 4-cc */ + boxa1= pixConnComp(pixs, &pixa1, 4); + n1 = boxaGetCount(boxa1); + boxa2= pixConnComp(pixs, NULL, 4); + n2 = boxaGetCount(boxa2); + pixCountConnComp(pixs, 4, &n3); + lept_stderr("Number of 4 c.c.: n1 = %d; n2 = %d, n3 = %d\n", n1, n2, n3); + regTestCompareValues(rp, n1, n2, 0); /* 0 */ + regTestCompareValues(rp, n1, n3, 0); /* 1 */ + regTestCompareValues(rp, n1, 4452, 0); /* 2 */ + pix1 = pixaDisplay(pixa1, pixGetWidth(pixs), pixGetHeight(pixs)); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 3 */ + regTestComparePix(rp, pixs, pix1); /* 4 */ + pixaDestroy(&pixa1); + boxaDestroy(&boxa1); + boxaDestroy(&boxa2); + pixDestroy(&pix1); + + /* Test with 8-cc */ + boxa1= pixConnComp(pixs, &pixa1, 8); + n1 = boxaGetCount(boxa1); + boxa2= pixConnComp(pixs, NULL, 8); + n2 = boxaGetCount(boxa2); + pixCountConnComp(pixs, 8, &n3); + lept_stderr("Number of 8 c.c.: n1 = %d; n2 = %d, n3 = %d\n", n1, n2, n3); + regTestCompareValues(rp, n1, n2, 0); /* 5 */ + regTestCompareValues(rp, n1, n3, 0); /* 6 */ + regTestCompareValues(rp, n1, 4305, 0); /* 7 */ + pix1 = pixaDisplay(pixa1, pixGetWidth(pixs), pixGetHeight(pixs)); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 8 */ + regTestComparePix(rp, pixs, pix1); /* 9 */ + pixaDestroy(&pixa1); + boxaDestroy(&boxa1); + boxaDestroy(&boxa2); + pixDestroy(&pix1); + + /* --------------------------------------------------------------- * + * Test boxa I/O * + * --------------------------------------------------------------- */ + lept_mkdir("lept/conn"); + boxa1 = pixConnComp(pixs, NULL, 4); + fp = lept_fopen("/tmp/lept/conn/boxa1.ba", "wb+"); + boxaWriteStream(fp, boxa1); + lept_fclose(fp); + fp = lept_fopen("/tmp/lept/conn/boxa1.ba", "rb"); + boxa2 = boxaReadStream(fp); + lept_fclose(fp); + fp = lept_fopen("/tmp/lept/conn/boxa2.ba", "wb+"); + boxaWriteStream(fp, boxa2); + lept_fclose(fp); + array1 = l_binaryRead("/tmp/lept/conn/boxa1.ba", &size1); + array2 = l_binaryRead("/tmp/lept/conn/boxa2.ba", &size2); + regTestCompareStrings(rp, array1, size1, array2, size2); /* 10 */ + lept_free(array1); + lept_free(array2); + boxaDestroy(&boxa1); + boxaDestroy(&boxa2); + + /* --------------------------------------------------------------- * + * Just for fun, display each component as a random color in * + * cmapped 8 bpp. Background is color 0; it is set to white. * + * --------------------------------------------------------------- */ + boxa1 = pixConnComp(pixs, &pixa1, 4); + pix1 = pixaDisplayRandomCmap(pixa1, pixGetWidth(pixs), pixGetHeight(pixs)); + cmap = pixGetColormap(pix1); + pixcmapResetColor(cmap, 0, 255, 255, 255); /* reset background to white */ + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 11 */ + if (rp->display) pixDisplay(pix1, 100, 0); + boxaDestroy(&boxa1); + pixDestroy(&pix1); + pixaDestroy(&pixa1); + pixDestroy(&pixs); + + /* --------------------------------------------------------------- * + * Test iterative covering of connected components by rectangles * + * --------------------------------------------------------------- */ + pixa1 = pixaCreate(0); + pix1 = pixRead("rabi.png"); + pix2 = pixReduceRankBinaryCascade(pix1, 1, 1, 1, 0); + regTestWritePixAndCheck(rp, pix2, IFF_PNG); /* 12 - */ + pixaAddPix(pixa1, pix2, L_INSERT); + for (i = 1; i < 6; i++) { + pix3 = pixMakeCoveringOfRectangles(pix2, i); + regTestWritePixAndCheck(rp, pix3, IFF_PNG); /* 13 - 17 */ + pixaAddPix(pixa1, pix3, L_INSERT); + } + pix3 = pixaDisplayTiledInRows(pixa1, 1, 2500, 1.0, 0, 30, 0); + regTestWritePixAndCheck(rp, pix3, IFF_PNG); /* 18 */ + pixDisplayWithTitle(pix3, 100, 900, NULL, rp->display); + pixDestroy(&pix1); + pixDestroy(&pix3); + pixaDestroy(&pixa1); + + return regTestCleanup(rp); +} + + diff --git a/leptonica/prog/contrast-orig-60.jpg b/leptonica/prog/contrast-orig-60.jpg Binary files differnew file mode 100644 index 00000000..a9772c50 --- /dev/null +++ b/leptonica/prog/contrast-orig-60.jpg diff --git a/leptonica/prog/contrast1.jpg b/leptonica/prog/contrast1.jpg Binary files differnew file mode 100644 index 00000000..a185e686 --- /dev/null +++ b/leptonica/prog/contrast1.jpg diff --git a/leptonica/prog/contrasttest.c b/leptonica/prog/contrasttest.c new file mode 100644 index 00000000..49cfef5d --- /dev/null +++ b/leptonica/prog/contrasttest.c @@ -0,0 +1,94 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * contrasttest.c + * + * This appplies @factor contrast enhancement to the input image. + * It also plots atan curves for different width parameters. + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include <math.h> +#include "allheaders.h" + +int main(int argc, + char **argv) +{ +char *filein, *fileout; +char buf[512]; +l_int32 iplot; +l_float32 factor; /* scaled width of atan curve */ +l_float32 fact[] = {0.2f, 0.4f, 0.6f, 0.8f, 1.0f, -1.0f}; +GPLOT *gplot; +NUMA *na, *nax; +PIX *pixs; +static char mainName[] = "contrasttest"; + + if (argc != 4) + return ERROR_INT(" Syntax: contrasttest filein factor fileout", + mainName, 1); + filein = argv[1]; + factor = atof(argv[2]); + fileout = argv[3]; + + setLeptDebugOK(1); + lept_mkdir("lept/contrast"); + + if ((pixs = pixRead(filein)) == NULL) + return ERROR_INT("pixs not made", mainName, 1); + + na = numaContrastTRC(factor); + gplotSimple1(na, GPLOT_PNG, "/tmp/lept/contrast/trc1", "contrast trc"); + l_fileDisplay("/tmp/lept/contrast/trc1.png", 0, 100, 1.0); + numaDestroy(&na); + + /* Plot contrast TRC maps */ + nax = numaMakeSequence(0.0, 1.0, 256); + gplot = gplotCreate("/tmp/lept/contrast/trc2", GPLOT_PNG, + "Atan mapping function for contrast enhancement", + "value in", "value out"); + for (iplot = 0; fact[iplot] >= 0.0; iplot++) { + na = numaContrastTRC(fact[iplot]); + snprintf(buf, sizeof(buf), "factor = %3.1f", fact[iplot]); + gplotAddPlot(gplot, nax, na, GPLOT_LINES, buf); + numaDestroy(&na); + } + gplotMakeOutput(gplot); + gplotDestroy(&gplot); + l_fileDisplay("/tmp/lept/contrast/trc2.png", 600, 100, 1.0); + numaDestroy(&nax); + + /* Apply the input contrast enhancement */ + pixContrastTRC(pixs, pixs, factor); + pixWrite(fileout, pixs, IFF_PNG); + pixDestroy(&pixs); + return 0; +} + diff --git a/leptonica/prog/conversion_reg.c b/leptonica/prog/conversion_reg.c new file mode 100644 index 00000000..dee21847 --- /dev/null +++ b/leptonica/prog/conversion_reg.c @@ -0,0 +1,424 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * conversion_reg.c + * + * Regression test for depth conversion functions, + * including some of the octcube quantization. + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + +int main(int argc, + char **argv) +{ +char *errorstr; +l_int32 same, error; +PIX *pixs1, *pixs2, *pixs4, *pixs8, *pixs16, *pixs32; +PIX *pixc2, *pixc4, *pixc8; +PIX *pix1, *pix2, *pix3, *pix4, *pix5, *pix6; +PIXA *pixa; +PIXCMAP *cmap; +SARRAY *sa; +L_REGPARAMS *rp; + + if (regTestSetup(argc, argv, &rp)) + return 1; + + pixs1 = pixRead("test1.png"); + pixs2 = pixRead("dreyfus2.png"); + pixc2 = pixRead("weasel2.4c.png"); + pixs4 = pixRead("weasel4.16g.png"); + pixc4 = pixRead("weasel4.11c.png"); + pixs8 = pixRead("karen8.jpg"); + pixc8 = pixRead("weasel8.240c.png"); + pixs16 = pixRead("test16.tif"); + pixs32 = pixRead("marge.jpg"); + error = FALSE; + sa = sarrayCreate(0); + + /* Conversion: 1 bpp --> 8 bpp --> 1 bpp */ + pix1 = pixConvertTo8(pixs1, FALSE); + pix2 = pixThreshold8(pix1, 1, 0, 0); + regTestComparePix(rp, pixs1, pix2); /* 0 */ + pixEqual(pixs1, pix2, &same); + if (!same) { + pixDisplayWithTitle(pixs1, 100, 100, "1 bpp, no cmap", 1); + pixDisplayWithTitle(pix2, 500, 100, "1 bpp, no cmap", 1); + error = TRUE; + sarrayAddString(sa, "conversion 1 bpp <==> 8 bpp", L_COPY); + } else { + lept_stderr("OK: conversion 1 bpp <==> 8 bpp\n"); + } + pixDestroy(&pix1); + pixDestroy(&pix2); + + /* Conversion: 2 bpp --> 8 bpp --> 2 bpp */ + /* Conversion: 2 bpp cmap --> 8 bpp cmap --> 2 bpp cmap */ + pix1 = pixRemoveColormap(pixs2, REMOVE_CMAP_TO_GRAYSCALE); + pix2 = pixThreshold8(pix1, 2, 4, 0); + pix3 = pixConvertTo8(pix2, FALSE); + pix4 = pixThreshold8(pix3, 2, 4, 0); + regTestComparePix(rp, pix2, pix4); /* 1 */ + pixEqual(pix2, pix4, &same); + if (!same) { + pixDisplayWithTitle(pix2, 100, 100, "2 bpp, no cmap", 1); + pixDisplayWithTitle(pix4, 500, 100, "2 bpp, no cmap", 1); + error = TRUE; + sarrayAddString(sa, "conversion 2 bpp <==> 8 bpp", L_COPY); + } else { + lept_stderr("OK: conversion 2 bpp <==> 8 bpp\n"); + } + pix5 = pixConvertTo8(pixs2, TRUE); + pix6 = pixThreshold8(pix5, 2, 4, 1); + regTestComparePix(rp, pixs2, pix6); /* 2 */ + pixEqual(pixs2, pix6, &same); + if (!same) { + pixDisplayWithTitle(pixs2, 100, 100, "2 bpp, cmap", 1); + pixDisplayWithTitle(pix6, 500, 100, "2 bpp, cmap", 1); + error = TRUE; + sarrayAddString(sa, "conversion 2 bpp <==> 8 bpp; cmap", + L_COPY); + } else { + lept_stderr("OK: conversion 2 bpp <==> 8 bpp; cmap\n"); + } + pixDestroy(&pix1); + pixDestroy(&pix2); + pixDestroy(&pix3); + pixDestroy(&pix4); + pixDestroy(&pix5); + pixDestroy(&pix6); + + /* Conversion: 4 bpp --> 8 bpp --> 4 bpp */ + /* Conversion: 4 bpp cmap --> 8 bpp cmap --> 4 bpp cmap */ + pix1 = pixRemoveColormap(pixs4, REMOVE_CMAP_TO_GRAYSCALE); + pix2 = pixThreshold8(pix1, 4, 16, 0); + pix3 = pixConvertTo8(pix2, FALSE); + pix4 = pixThreshold8(pix3, 4, 16, 0); + regTestComparePix(rp, pix2, pix4); /* 3 */ + pixEqual(pix2, pix4, &same); + if (!same) { + pixDisplayWithTitle(pix2, 100, 100, "4 bpp, no cmap", 1); + pixDisplayWithTitle(pix4, 500, 100, "4 bpp, no cmap", 1); + error = TRUE; + sarrayAddString(sa, "conversion 4 bpp <==> 8 bpp", L_COPY); + } else { + lept_stderr("OK: conversion 4 bpp <==> 8 bpp\n"); + } + pix5 = pixConvertTo8(pixs4, TRUE); + pix6 = pixThreshold8(pix5, 4, 16, 1); + regTestComparePix(rp, pixs4, pix6); /* 4 */ + pixEqual(pixs4, pix6, &same); + if (!same) { + pixDisplayWithTitle(pixs4, 100, 100, "4 bpp, cmap", 1); + pixDisplayWithTitle(pix6, 500, 100, "4 bpp, cmap", 1); + error = TRUE; + sarrayAddString(sa, "conversion 4 bpp <==> 8 bpp, cmap", + L_COPY); + } else { + lept_stderr("OK: conversion 4 bpp <==> 8 bpp; cmap\n"); + } + pixDestroy(&pix1); + pixDestroy(&pix2); + pixDestroy(&pix3); + pixDestroy(&pix4); + pixDestroy(&pix5); + pixDestroy(&pix6); + + /* Conversion: 2 bpp cmap --> 2 bpp --> 2 bpp cmap --> 2 bpp */ + pix1 = pixRemoveColormap(pixs2, REMOVE_CMAP_TO_GRAYSCALE); + pix2 = pixConvertGrayToColormap(pix1); + pix3 = pixRemoveColormap(pix2, REMOVE_CMAP_TO_GRAYSCALE); + pix4 = pixThresholdTo2bpp(pix3, 4, 1); + regTestComparePix(rp, pix1, pix4); /* 5 */ + pixEqual(pix1, pix4, &same); + if (!same) { + pixDisplayWithTitle(pixs2, 100, 100, "2 bpp, cmap", 1); + pixDisplayWithTitle(pix4, 500, 100, "2 bpp, cmap", 1); + error = TRUE; + sarrayAddString(sa, "conversion 2 bpp <==> 2 bpp", L_COPY); + } else { + lept_stderr("OK: conversion 2 bpp <==> 2 bpp\n"); + } + pixDestroy(&pix1); + pixDestroy(&pix2); + pixDestroy(&pix3); + pixDestroy(&pix4); + + /* Conversion: 4 bpp cmap --> 4 bpp --> 4 bpp cmap --> 4 bpp */ + pix1 = pixRemoveColormap(pixs4, REMOVE_CMAP_TO_GRAYSCALE); + pix2 = pixConvertGrayToColormap(pix1); + pix3 = pixRemoveColormap(pix2, REMOVE_CMAP_TO_GRAYSCALE); + pix4 = pixThresholdTo4bpp(pix3, 16, 1); + regTestComparePix(rp, pix1, pix4); /* 6 */ + pixEqual(pix1, pix4, &same); + if (!same) { + pixDisplayWithTitle(pixs4, 100, 100, "4 bpp, cmap", 1); + pixDisplayWithTitle(pix4, 500, 100, "4 bpp, cmap", 1); + error = TRUE; + sarrayAddString(sa, "conversion 4 bpp <==> 4 bpp", L_COPY); + } else { + lept_stderr("OK: conversion 4 bpp <==> 4 bpp\n"); + } + pixDestroy(&pix1); + pixDestroy(&pix2); + pixDestroy(&pix3); + pixDestroy(&pix4); + + /* Conversion: 8 bpp --> 8 bpp cmap --> 8 bpp */ + pix1 = pixConvertTo8(pixs8, TRUE); + pix2 = pixConvertTo8(pix1, FALSE); + regTestComparePix(rp, pixs8, pix2); /* 7 */ + pixEqual(pixs8, pix2, &same); + if (!same) { + pixDisplayWithTitle(pix1, 100, 100, "8 bpp, cmap", 1); + pixDisplayWithTitle(pix2, 500, 100, "8 bpp, no cmap", 1); + error = TRUE; + sarrayAddString(sa, "conversion 8 bpp <==> 8 bpp", L_COPY); + } else { + lept_stderr("OK: conversion 8 bpp <==> 8 bpp\n"); + } + pixDestroy(&pix1); + pixDestroy(&pix2); + + /* Conversion: 2 bpp cmap --> 32 bpp --> 2 bpp cmap */ + pix1 = pixConvertTo8(pixc2, TRUE); + pix2 = pixConvertTo32(pix1); + pix3 = pixConvertTo32(pixc2); + regTestComparePix(rp, pix2, pix3); /* 8 */ + pixEqual(pix2, pix3, &same); + if (!same) { + pixDisplayWithTitle(pix2, 100, 100, "32 bpp", 1); + pixDisplayWithTitle(pix3, 500, 100, "32 bpp", 1); + error = TRUE; + sarrayAddString(sa, "conversion 2 bpp ==> 32 bpp", L_COPY); + } else { + lept_stderr("OK: conversion 2 bpp <==> 32 bpp\n"); + } + cmap = pixGetColormap(pixc2); + pix4 = pixOctcubeQuantFromCmap(pix3, cmap, 2, 4, L_EUCLIDEAN_DISTANCE); + regTestComparePix(rp, pixc2, pix4); /* 9 */ + pixEqual(pixc2, pix4, &same); + if (!same) { + pixDisplayWithTitle(pixc2, 100, 100, "4 bpp, cmap", 1); + pixDisplayWithTitle(pix4, 500, 100, "4 bpp, cmap", 1); + error = TRUE; + sarrayAddString(sa, "conversion 2 bpp <==> 32 bpp", L_COPY); + } else { + lept_stderr("OK: conversion 2 bpp <==> 32 bpp\n"); + } + pixDestroy(&pix1); + pixDestroy(&pix2); + pixDestroy(&pix3); + pixDestroy(&pix4); + + /* Conversion: 4 bpp cmap --> 32 bpp --> 4 bpp cmap */ + pix1 = pixConvertTo8(pixc4, TRUE); + pix2 = pixConvertTo32(pix1); + pix3 = pixConvertTo32(pixc4); + regTestComparePix(rp, pix2, pix3); /* 10 */ + pixEqual(pix2, pix3, &same); + if (!same) { + pixDisplayWithTitle(pix2, 100, 100, "32 bpp", 1); + pixDisplayWithTitle(pix3, 500, 100, "32 bpp", 1); + error = TRUE; + sarrayAddString(sa, "conversion 4 bpp ==> 32 bpp", L_COPY); + } else { + lept_stderr("OK: conversion 4 bpp <==> 32 bpp\n"); + } + cmap = pixGetColormap(pixc4); + pix4 = pixOctcubeQuantFromCmap(pix3, cmap, 2, 4, L_EUCLIDEAN_DISTANCE); + regTestComparePix(rp, pixc4, pix4); /* 11 */ + pixEqual(pixc4, pix4, &same); + if (!same) { + pixDisplayWithTitle(pixc4, 100, 100, "4 bpp, cmap", 1); + pixDisplayWithTitle(pix4, 500, 100, "4 bpp, cmap", 1); + error = TRUE; + sarrayAddString(sa, "conversion 4 bpp <==> 32 bpp", L_COPY); + } else { + lept_stderr("OK: conversion 4 bpp <==> 32 bpp\n"); + } + pixDestroy(&pix1); + pixDestroy(&pix2); + pixDestroy(&pix3); + pixDestroy(&pix4); + + /* Conversion: 8 bpp --> 32 bpp --> 8 bpp */ + pix1 = pixConvertTo32(pixs8); + pix2 = pixConvertTo8(pix1, FALSE); + regTestComparePix(rp, pixs8, pix2); /* 12 */ + pixEqual(pixs8, pix2, &same); + if (!same) { + pixDisplayWithTitle(pixs8, 100, 100, "8 bpp", 1); + pixDisplayWithTitle(pix2, 500, 100, "8 bpp", 1); + error = TRUE; + sarrayAddString(sa, "conversion 8 bpp <==> 32 bpp", L_COPY); + } else { + lept_stderr("OK: conversion 8 bpp <==> 32 bpp\n"); + } + pixDestroy(&pix1); + pixDestroy(&pix2); + + /* Conversion: 8 bpp --> 16 bpp --> 8 bpp */ + pix1 = pixConvert8To16(pixs8, 8); + pix2 = pixConvertTo8(pix1, FALSE); + regTestComparePix(rp, pixs8, pix2); /* 13 */ + pixEqual(pixs8, pix2, &same); + if (!same) { + pixDisplayWithTitle(pixs8, 100, 100, "8 bpp", 1); + pixDisplayWithTitle(pix2, 500, 100, "8 bpp", 1); + error = TRUE; + sarrayAddString(sa, "conversion 8 bpp <==> 16 bpp", L_COPY); + } else { + lept_stderr("OK: conversion 8 bpp <==> 16 bpp\n"); + } + pixDestroy(&pix1); + pixDestroy(&pix2); + + /* Conversion: 16 bpp --> 8 bpp --> 16 bpp */ + pix1 = pixConvert16To8(pixs16, 1); + pix2 = pixConvertTo16(pix1); + regTestComparePix(rp, pixs16, pix2); /* 14 */ + pixEqual(pixs16, pix2, &same); + if (!same) { + pixDisplayWithTitle(pixs16, 100, 100, "16 bpp", 1); + pixDisplayWithTitle(pix2, 500, 100, "16 bpp", 1); + error = TRUE; + sarrayAddString(sa, "conversion 16 bpp <==> 8 bpp", L_COPY); + } else { + lept_stderr("OK: conversion 16 bpp <==> 8 bpp\n"); + } + pixDestroy(&pix1); + pixDestroy(&pix2); + + /* Conversion: 8 bpp cmap --> 32 bpp --> 8 bpp cmap */ + /* Required to go to level 6 of octcube to get identical result */ + pix1 = pixConvertTo32(pixc8); + cmap = pixGetColormap(pixc8); + pix2 = pixOctcubeQuantFromCmap(pix1, cmap, 2, 6, L_EUCLIDEAN_DISTANCE); + regTestComparePix(rp, pixc8, pix2); /* 15 */ + pixEqual(pixc8, pix2, &same); + if (!same) { + pixDisplayWithTitle(pixc8, 100, 100, "8 bpp cmap", 1); + pixDisplayWithTitle(pix2, 500, 100, "8 bpp cmap", 1); + error = TRUE; + sarrayAddString(sa, "conversion 8 bpp cmap <==> 32 bpp cmap", + L_COPY); + } else { + lept_stderr("OK: conversion 8 bpp <==> 32 bpp\n"); + } + pixDestroy(&pix1); + pixDestroy(&pix2); + + /* Summarize results so far */ + if (error == FALSE) { + lept_stderr("No errors found\n"); + } else { + errorstr = sarrayToString(sa, 1); + lept_stderr("Errors in the following:\n %s", errorstr); + lept_free(errorstr); + } + + /* General onversion to 2 bpp */ + pixa = pixaCreate(0); + pix1 = pixConvertTo2(pixs1); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 16 */ + pixaAddPix(pixa, pix1, L_INSERT); + pix1 = pixConvertTo2(pixs2); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 17 */ + pixaAddPix(pixa, pix1, L_INSERT); + pix1 = pixConvertTo2(pixc2); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 18 */ + pixaAddPix(pixa, pix1, L_INSERT); + pix1 = pixConvertTo2(pixs4); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 19 */ + pixaAddPix(pixa, pix1, L_INSERT); + pix1 = pixConvertTo2(pixc4); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 20 */ + pixaAddPix(pixa, pix1, L_INSERT); + pix1 = pixConvertTo2(pixs8); + regTestWritePixAndCheck(rp, pix1, IFF_JFIF_JPEG); /* 21 */ + pixaAddPix(pixa, pix1, L_INSERT); + pix1 = pixConvertTo2(pixc8); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 22 */ + pixaAddPix(pixa, pix1, L_INSERT); + pix1 = pixConvertTo2(pixs32); + regTestWritePixAndCheck(rp, pix1, IFF_JFIF_JPEG); /* 23 */ + pixaAddPix(pixa, pix1, L_INSERT); + pix2 = pixaDisplayTiledAndScaled(pixa, 32, 300, 4, 0, 30, 2); + pixDisplayWithTitle(pix2, 500, 0, NULL, rp->display); + pixDestroy(&pix2); + pixaDestroy(&pixa); + + /* General onversion to 4 bpp */ + pixa = pixaCreate(0); + pix1 = pixConvertTo4(pixs1); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 24 */ + pixaAddPix(pixa, pix1, L_INSERT); + pix1 = pixConvertTo4(pixs2); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 25 */ + pixaAddPix(pixa, pix1, L_INSERT); + pix1 = pixConvertTo4(pixc2); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 26 */ + pixaAddPix(pixa, pix1, L_INSERT); + pix1 = pixConvertTo4(pixs4); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 27 */ + pixaAddPix(pixa, pix1, L_INSERT); + pix1 = pixConvertTo4(pixc4); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 28 */ + pixaAddPix(pixa, pix1, L_INSERT); + pix1 = pixConvertTo4(pixs8); + regTestWritePixAndCheck(rp, pix1, IFF_JFIF_JPEG); /* 29 */ + pixaAddPix(pixa, pix1, L_INSERT); + pix1 = pixConvertTo4(pixc8); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 30 */ + pixaAddPix(pixa, pix1, L_INSERT); + pix1 = pixConvertTo4(pixs32); + regTestWritePixAndCheck(rp, pix1, IFF_JFIF_JPEG); /* 31 */ + pixaAddPix(pixa, pix1, L_INSERT); + pix2 = pixaDisplayTiledAndScaled(pixa, 32, 300, 4, 0, 30, 2); + pixDisplayWithTitle(pix2, 500, 750, NULL, rp->display); + pixDestroy(&pix2); + pixaDestroy(&pixa); + + sarrayDestroy(&sa); + pixDestroy(&pixs1); + pixDestroy(&pixs2); + pixDestroy(&pixs4); + pixDestroy(&pixc2); + pixDestroy(&pixc4); + pixDestroy(&pixs8); + pixDestroy(&pixc8); + pixDestroy(&pixs16); + pixDestroy(&pixs32); + return regTestCleanup(rp); +} + diff --git a/leptonica/prog/convertfilestopdf.c b/leptonica/prog/convertfilestopdf.c new file mode 100644 index 00000000..ac6f5fd5 --- /dev/null +++ b/leptonica/prog/convertfilestopdf.c @@ -0,0 +1,109 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * convertfilestopdf.c + * + * Converts all image files in the given directory with matching substring + * to a pdf, with the specified scaling factor <= 1.0 applied to all + * images. + * + * See below for syntax and usage. + * + * The images are displayed at a resolution that depends on the + * input resolution (res) and the scaling factor (scalefact) that + * is applied to the images before conversion to pdf. Internally + * we multiply these, so that the generated pdf will render at the + * same resolution as if it hadn't been scaled. By downscaling, you + * reduce the size of the images. + * + * For jpeg and jp2k, downscaling reduces pdf size by the square of + * the scale factor. + * * The jpeg quality can be specified from 1 (very poor) to 100 + * (best available, but still lossy); use 0 for the default (75). + * * The jp2k quality can be specified from 27 (very poor) to 45 (nearly + * lossless; use 0 for the default (34). You can use 100 to + * require lossless, but this is very expensive and not recommended. + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include <string.h> +#include "allheaders.h" + +int main(int argc, + char **argv) +{ +char *dirin, *substr, *title, *fileout; +l_int32 ret, res, type, quality; +l_float32 scalefactor; +static char mainName[] = "convertfilestopdf"; + + if (argc != 9) { + lept_stderr( + " Syntax: convertfilestopdf dirin substr res" + " scalefactor encoding_type quality title fileout\n" + " dirin: input directory for image files\n" + " substr: Use 'allfiles' to convert all files\n" + " in the directory.\n" + " res: Input resolution of each image;\n" + " assumed to all be the same\n" + " scalefactor: Use to scale all images\n" + " encoding_type:\n" + " L_JPEG_ENCODE = 1\n" + " L_G4_ENCODE = 2\n" + " L_FLATE_ENCODE = 3\n" + " L_JP2K_ENCODE = 4, or 0 for per-page default)\n" + " quality: used for jpeg; 1-100, 0 for default (75);\n" + " used for jp2k: 27-45, 0 for default (34)\n" + " title: Use 'none' to omit\n" + " fileout: Output pdf file\n"); + return 1; + } + dirin = argv[1]; + substr = argv[2]; + res = atoi(argv[3]); + scalefactor = atof(argv[4]); + type = atoi(argv[5]); + quality = atoi(argv[6]); + title = argv[7]; + fileout = argv[8]; + if (!strcmp(substr, "allfiles")) + substr = NULL; + if (scalefactor <= 0.0 || scalefactor > 2.0) { + L_WARNING("invalid scalefactor: setting to 1.0\n", mainName); + scalefactor = 1.0; + } + if (!strcmp(title, "none")) + title = NULL; + + setLeptDebugOK(1); + ret = convertFilesToPdf(dirin, substr, res, scalefactor, type, + quality, title, fileout); + return ret; +} diff --git a/leptonica/prog/convertfilestops.c b/leptonica/prog/convertfilestops.c new file mode 100644 index 00000000..d70c27e2 --- /dev/null +++ b/leptonica/prog/convertfilestops.c @@ -0,0 +1,85 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * convertfilestops.c + * + * Converts all files in the given directory with matching substring + * to a level 3 compressed PostScript file, at the specified resolution. + * To convert all files in the directory, use 'allfiles' for the substring. + * + * See below for syntax and usage. + * + * To generate a ps that scales the images to fit a standard 8.5 x 11 + * page, use res = 0. + * + * Otherwise, this will convert based on a specified input resolution. + * Decreasing the input resolution will cause the image to be rendered + * larger, and v.v. For example, if the page was originally scanned + * at 400 ppi and you use 300 ppi for the resolution, the page will + * be rendered with larger pixels (i.e., be magnified) and you will + * lose a quarter of the page on the right side and a quarter + * at the bottom. + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include <string.h> +#include "allheaders.h" + +int main(int argc, + char **argv) +{ +char *dirin, *substr, *fileout; +l_int32 res; + + if (argc != 5) { + lept_stderr( + " Syntax: convertfilestops dirin substr res fileout\n" + " where\n" + " dirin: input directory for image files\n" + " substr: Use 'allfiles' to convert all files\n" + " in the directory.\n" + " res: Input resolution of each image;\n" + " assumed to all be the same\n" + " fileout: Output ps file.\n"); + return 1; + } + dirin = argv[1]; + substr = argv[2]; + res = atoi(argv[3]); + fileout = argv[4]; + + setLeptDebugOK(1); + if (!strcmp(substr, "allfiles")) + substr = NULL; + if (res != 0) + return convertFilesToPS(dirin, substr, res, fileout); + else + return convertFilesFittedToPS(dirin, substr, 0.0, 0.0, fileout); +} diff --git a/leptonica/prog/convertformat.c b/leptonica/prog/convertformat.c new file mode 100644 index 00000000..38ebd8ef --- /dev/null +++ b/leptonica/prog/convertformat.c @@ -0,0 +1,181 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * convertformat.c + * + * Converts an image file from one format to another. + * + * Syntax: convertformat filein fileout [format] + * + * where format is one of these: + * + * BMP + * JPEG (only applicable for 8 bpp or rgb; if not, transcode to png) + * PNG + * TIFF + * TIFF_G4 (only applicable for 1 bpp; if not, transcode to png) + * PNM + * GIF + * WEBP + * JP2 (only available for 8 bpp or rgb; if not, transcode to png) + * + * The output format can be chosen either explicitly with the %format + * arg, or implicitly using the extension of @fileout: + * + * BMP .bmp + * JPEG .jpg + * PNG .png + * TIFF (zip compressed: use explicitly with %format arg) + * TIFFG4 .tif + * PNM .pnm + * GIF .gif + * WEBP .webp + * JP2 .jp2 + * + * If the requested output format does not support the image type, + * the image is written in png format, with filename extension 'png'. + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include <string.h> +#include "allheaders.h" + +int main(int argc, + char **argv) +{ +char *filein, *fileout, *base, *ext; +const char *formatstr; +l_int32 format, d, change; +PIX *pixs; +static char mainName[] = "convertformat"; + + if (argc != 3 && argc != 4) { + lept_stderr("Syntax: convertformat filein fileout [format]\n" + "Either specify a format from one of these:\n" + " BMP, JPEG, PNG, TIFF, TIFFG4, PNM, GIF, WEBP, JP2\n" + "Or specify the extensions to the output file:\n" + " bmp, jpg, png, tif, pnm, gif, webp, jp2\n"); + return 1; + } + filein = argv[1]; + fileout = argv[2]; + + if (argc == 3) { + splitPathAtExtension(fileout, NULL, &ext); + if (!strcmp(ext, ".bmp")) + format = IFF_BMP; + else if (!strcmp(ext, ".jpg")) + format = IFF_JFIF_JPEG; + else if (!strcmp(ext, ".png")) + format = IFF_PNG; + else if (!strcmp(ext, ".tif")) /* requesting g4-tiff binary comp */ + format = IFF_TIFF_G4; + else if (!strcmp(ext, ".pnm")) + format = IFF_PNM; + else if (!strcmp(ext, ".gif")) + format = IFF_GIF; + else if (!strcmp(ext, ".webp")) + format = IFF_WEBP; + else if (!strcmp(ext, ".jp2")) + format = IFF_JP2; + else { + return ERROR_INT( + "Valid extensions: bmp, jpg, png, tif, pnm, gif, webp, jp2", + mainName, 1); + } + lept_free(ext); + } + else { + formatstr = argv[3]; + if (!strcmp(formatstr, "BMP")) + format = IFF_BMP; + else if (!strcmp(formatstr, "JPEG")) + format = IFF_JFIF_JPEG; + else if (!strcmp(formatstr, "PNG")) + format = IFF_PNG; + else if (!strcmp(formatstr, "TIFF")) + format = IFF_TIFF_ZIP; /* zip compressed tif */ + else if (!strcmp(formatstr, "TIFFG4")) + format = IFF_TIFF_G4; + else if (!strcmp(formatstr, "PNM")) + format = IFF_PNM; + else if (!strcmp(formatstr, "GIF")) + format = IFF_GIF; + else if (!strcmp(formatstr, "WEBP")) + format = IFF_WEBP; + else if (!strcmp(formatstr, "JP2")) + format = IFF_JP2; + else { + return ERROR_INT( + "Valid formats: BMP, JPEG, PNG, TIFF, TIFFG4, PNM, " + "GIF, WEBP, JP2", + mainName, 1); + } + } + + setLeptDebugOK(1); + if ((pixs = pixRead(filein)) == NULL) { + L_ERROR("read fail for %s\n", mainName, filein); + return 1; + } + + /* Change output format if necessary */ + change = FALSE; + d = pixGetDepth(pixs); + if (d != 1 && format == IFF_TIFF_G4) { + L_WARNING("can't convert to tiff_g4; converting to png\n", mainName); + change = TRUE; + } + if (d < 8) { + switch(format) + { + case IFF_JFIF_JPEG: + L_WARNING("can't convert to jpeg; converting to png\n", mainName); + change = TRUE; + break; + case IFF_WEBP: + L_WARNING("can't convert to webp; converting to png\n", mainName); + change = TRUE; + break; + case IFF_JP2: + L_WARNING("can't convert to jp2; converting to png\n", mainName); + change = TRUE; + break; + } + } + if (change) { + splitPathAtExtension(fileout, &base, &ext); + fileout = stringJoin(base, ".png"); + format = IFF_PNG; + } + + pixWrite(fileout, pixs, format); + return 0; +} diff --git a/leptonica/prog/convertsegfilestopdf.c b/leptonica/prog/convertsegfilestopdf.c new file mode 100644 index 00000000..f79ce8ad --- /dev/null +++ b/leptonica/prog/convertsegfilestopdf.c @@ -0,0 +1,162 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * convertsegfilestopdf.c + * + * Converts all image files in the page directory with matching substring + * to a pdf. Image regions are downscaled by the scalefactor and + * encoded as jpeg. Non-image regions with depth > 1 are automatically + * scaled up by 2x and thresholded if the encoding type is G4; + * otherwise, no scaling is performed on them. To convert all + * files in the page directory, use 'allfiles' for its substring. + * Likewise to use all files in the mask directory, use 'allfiles' + * for its substring. + * + * A typical invocation would be something like: + * convertsegfilestopdf /tmp/segpages allfiles /tmp/segmasks allfiles \ + * 300 2 160 skip 0.5 [title] [output pdf] + * This upscales by 2x all non-image regions to 600 ppi, and downscales + * by 0.5 all image regions to 150 ppi. + * + * If used on a set of images without segmentation data, a typical + * invocation would be: + * convertsegfilestopdf /tmp/pages allfiles skip skip \ + * 300 2 160 skip 1.0 [title] [output pdf] + * If the page images have depth > 1 bpp, this will upscale all pages + * by 2x (to 600 ppi), and then convert the images to 1 bpp. + * Note that 'skip' is used three times to omit all segmentation data. + * + * See below for further syntax and usage. + * + * Again, note that the image regions are displayed at a resolution + * that depends on the input resolution (res) and the scaling factor + * (scalefact) that is applied to the images before conversion to pdf. + * Internally we multiply these, so that the generated pdf will render + * at the same resolution as if it hadn't been scaled. When we + * downscale the image regions, this: + * (1) reduces the size of the images. For jpeg, downscaling + * reduces by square of the scale factor the 'image' segmented part. + * (2) regenerates the jpeg with quality = 75 after downscaling. + * + * If you already have a boxaafile of the image regions, use 'skip' for + * maskdir. Otherwise, this will generate the boxaa from the mask images. + * + * A regression test that uses this is pdfseg_reg, which + * generates images and the boxaa file in /tmp/segtest/. + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include <string.h> +#include "allheaders.h" + +int main(int argc, + char **argv) +{ +char *pagedir, *pagesubstr, *maskdir, *masksubstr; +char *title, *fileout, *boxaafile, *boxaapath; +l_int32 ret, res, type, thresh; +l_float32 scalefactor; +BOXAA *baa; +static char mainName[] = "convertsegfilestopdf"; + + if (argc != 12) { + lept_stderr( + " Syntax: convertsegfilestopdf dirin substr res type thresh \\ \n" + " boxaafile scalefactor title fileout\n" + " where\n" + " pagedir: input directory for image files\n" + " pagesubstr: Use 'allfiles' to convert all files\n" + " in the directory\n" + " maskdir: input directory for mask files;\n" + " use 'skip' to skip \n" + " masksubstr: Use 'allfiles' to convert all files\n" + " in the directory; 'skip' to skip\n" + " res: Input resolution of each image;\n" + " assumed to all be the same\n" + " type: compression used for non-image regions:\n" + " 0: default (G4 encoding)\n" + " 1: JPEG encoding\n" + " 2: G4 encoding\n" + " 3: PNG encoding\n" + " thresh: threshold for binarization; use 0 for default\n" + " boxaafile: Optional file of 'image' regions within\n" + " each page. This contains a boxa for each\n" + " page, consisting of a set of regions.\n" + " Use 'skip' to skip.\n" + " scalefactor: Use to scale down the image regions\n" + " title: Use 'none' to omit\n" + " fileout: Output pdf file\n"); + return 1; + } + pagedir = argv[1]; + pagesubstr = argv[2]; + maskdir = argv[3]; + masksubstr = argv[4]; + res = atoi(argv[5]); + type = atoi(argv[6]); + thresh = atoi(argv[7]); + boxaafile = argv[8]; + scalefactor = atof(argv[9]); + title = argv[10]; + fileout = argv[11]; + + if (!strcmp(pagesubstr, "allfiles")) + pagesubstr = NULL; + if (!strcmp(maskdir, "skip")) + maskdir = NULL; + if (!strcmp(masksubstr, "allfiles")) + masksubstr = NULL; + if (scalefactor <= 0.0 || scalefactor > 1.0) { + L_WARNING("invalid scalefactor: setting to 1.0\n", mainName); + scalefactor = 1.0; + } + if (type != 1 && type != 2 && type != 3) + type = L_G4_ENCODE; + if (thresh <= 0) + thresh = 150; + if (!strcmp(title, "none")) + title = NULL; + + setLeptDebugOK(1); + if (maskdir) /* use this; ignore any input boxaafile */ + baa = convertNumberedMasksToBoxaa(maskdir, masksubstr, 0, 0); + else if (strcmp(boxaafile, "skip") != 0) { /* use the boxaafile */ + boxaapath = genPathname(boxaafile, NULL); + baa = boxaaRead(boxaapath); + lept_free(boxaapath); + } + else /* no maskdir and no input boxaafile */ + baa = NULL; + + ret = convertSegmentedFilesToPdf(pagedir, pagesubstr, res, type, thresh, + baa, 75, scalefactor, title, fileout); + boxaaDestroy(&baa); + return ret; +} diff --git a/leptonica/prog/convertsegfilestops.c b/leptonica/prog/convertsegfilestops.c new file mode 100644 index 00000000..da74d425 --- /dev/null +++ b/leptonica/prog/convertsegfilestops.c @@ -0,0 +1,137 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * convertsegfilestops.c + * + * Converts all image files in a 'page' directory, using optional + * corresponding segmentation mask files in a 'mask' directory, + * to a level 2 compressed PostScript file. This is done + * automatically at a resolution that fits to a letter-sized + * (8.5 x 11) inch page. The 'page' and 'mask' files are paired + * by having the same number embedded in their name. + * The 'numpre' and 'numpost' args specify the number of + * characters at the beginning and end of the filename (not + * counting any extension) that are NOT part of the page number. + * For example, if the page numbers are 00000.jpg, 00001.jpg, ... + * then numpre = numpost = 0. + * + * The mask directory must exist, but it does not need to have + * any image mask files. + * + * The pages are taken in lexical order of the filenames. Therefore, + * the embedded numbers should be 0-padded on the left up to + * a fixed number of digits. + * + * PostScript (and pdf) allow regions of the image to be encoded + * differently. Regions can be over-written, with the last writing + * determining the final output. Black "ink" can also be written + * through a mask that is given by a 1 bpp image. + * + * The page images are typically grayscale or color. To take advantage + * of this depth, one typically upscales the text by 2.0. Likewise, + * the images regions, denoted by foreground in the corresponding + * segmentation mask, can be rendered at lower resolution, and + * it is often useful to downscale the image parts by 0.5. + * + * If the mask does not exist, the entire page is interpreted as + * text; it is converted to 1 bpp and written to file with + * ccitt-g4 compression at the requested "textscale" relative + * to the page image. If the mask exists and the foreground + * covers the entire page, the entire page is saved with jpeg + * ("dct") compression at the requested "imagescale". + * If the mask exists and partially covers the page image, the + * page is saved as a mixture of grayscale or rgb dct and 1 bpp g4. + * + * This uses a single global threshold for binarizing the text + * (i.e., non-image) regions of every page. + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include <string.h> +#include "allheaders.h" + +int main(int argc, + char **argv) +{ +char *pagedir, *pagestr, *maskdir, *maskstr, *fileout; +l_int32 threshold, page_numpre, mask_numpre, numpost, maxnum; +l_float32 textscale, imagescale; + + if (argc != 13) { + lept_stderr( + " Syntax: convertsegfilestops pagedir pagestr page_numpre \\ \n" + " maskdir maskstr mask_numpre \\ \n" + " numpost maxnum textscale \\ \n" + " imagescale thresh fileout\n" + " where\n" + " pagedir: Input directory for page image files\n" + " pagestr: Substring for matching; use 'allfiles' to\n" + " convert all files in the page directory\n" + " page_numpre: Number of characters in page name " + "before number\n" + " maskdir: Input directory for mask image files\n" + " maskstr: Substring for matching; use 'allfiles' to\n" + " convert all files in the mask directory\n" + " mask_numpre: Number of characters in mask name " + "before number\n" + " numpost: Number of characters in name after number\n" + " maxnum: Only consider page numbers up to this value\n" + " textscale: Scale of text output relative to pixs\n" + " imagescale: Scale of image output relative to pixs\n" + " thresh: threshold for binarization; typically about\n" + " 180; use 0 for default\n" + " fileout: Output p file\n"); + return 1; + } + pagedir = argv[1]; + pagestr = argv[2]; + page_numpre = atoi(argv[3]); + maskdir = argv[4]; + maskstr = argv[5]; + mask_numpre = atoi(argv[6]); + numpost = atoi(argv[7]); + maxnum = atoi(argv[8]); + textscale = atof(argv[9]); + imagescale = atof(argv[10]); + threshold = atoi(argv[11]); + fileout = argv[12]; + + if (!strcmp(pagestr, "allfiles")) + pagestr = NULL; + if (!strcmp(maskstr, "allfiles")) + maskstr = NULL; + + setLeptDebugOK(1); + return convertSegmentedPagesToPS(pagedir, pagestr, page_numpre, + maskdir, maskstr, mask_numpre, + numpost, maxnum, textscale, + imagescale, threshold, fileout); +} + diff --git a/leptonica/prog/converttogray.c b/leptonica/prog/converttogray.c new file mode 100644 index 00000000..eaa3d837 --- /dev/null +++ b/leptonica/prog/converttogray.c @@ -0,0 +1,123 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * converttogray.c + * + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + +int main(int argc, + char **argv) +{ +char *filein; +char *fileout = NULL; +l_int32 d, same; +PIX *pixs, *pixd, *pix1, *pix2, *pix3, *pix4; +static char mainName[] = "converttogray"; + + if (argc != 2 && argc != 3) + return ERROR_INT(" Syntax: converttogray filein [fileout]", + mainName, 1); + + setLeptDebugOK(1); + lept_mkdir("lept/gray"); + + filein = argv[1]; + if (argc == 3) fileout = argv[2]; + if ((pixs = pixRead(filein)) == NULL) + return ERROR_INT("pixs not made", mainName, 1); + + if (fileout) { + pixd = pixConvertRGBToGray(pixs, 0.33, 0.34, 0.33); + pixWrite(fileout, pixd, IFF_PNG); + pixDestroy(&pixs); + pixDestroy(&pixd); + return 0; + } + + d = pixGetDepth(pixs); + if (d == 2) { + pix1 = pixConvert2To8(pixs, 0x00, 0x55, 0xaa, 0xff, TRUE); + pix2 = pixConvert2To8(pixs, 0x00, 0x55, 0xaa, 0xff, FALSE); + pixEqual(pix1, pix2, &same); + if (same) + lept_stderr("images are the same\n"); + else + lept_stderr("images are different!\n"); + pixWrite("/tmp/lept/gray/pix1.png", pix1, IFF_PNG); + pixWrite("/tmp/lept/gray/pix2.png", pix2, IFF_PNG); + pixDestroy(&pix1); + pixDestroy(&pix2); + pixSetColormap(pixs, NULL); + pix3 = pixConvert2To8(pixs, 0x00, 0x55, 0xaa, 0xff, TRUE); + pix4 = pixConvert2To8(pixs, 0x00, 0x55, 0xaa, 0xff, FALSE); + pixEqual(pix3, pix4, &same); + if (same) + lept_stderr("images are the same\n"); + else + lept_stderr("images are different!\n"); + pixWrite("/tmp/lept/gray/pix3.png", pix3, IFF_PNG); + pixWrite("/tmp/lept/gray/pix4.png", pix4, IFF_PNG); + pixDestroy(&pix3); + pixDestroy(&pix4); + } else if (d == 4) { + pix1 = pixConvert4To8(pixs, TRUE); + pix2 = pixConvert4To8(pixs, FALSE); + pixEqual(pix1, pix2, &same); + if (same) + lept_stderr("images are the same\n"); + else + lept_stderr("images are different!\n"); + pixWrite("/tmp/lept/gray/pix1.png", pix1, IFF_PNG); + pixWrite("/tmp/lept/gray/pix2.png", pix2, IFF_PNG); + pixDestroy(&pix1); + pixDestroy(&pix2); + pixSetColormap(pixs, NULL); + pix3 = pixConvert4To8(pixs, TRUE); + pix4 = pixConvert4To8(pixs, FALSE); + pixEqual(pix3, pix4, &same); + if (same) + lept_stderr("images are the same\n"); + else + lept_stderr("images are different!\n"); + pixWrite("/tmp/lept/gray/pix3.png", pix3, IFF_PNG); + pixWrite("/tmp/lept/gray/pix4.png", pix4, IFF_PNG); + pixDestroy(&pix3); + pixDestroy(&pix4); + } else { + L_INFO("only converts 2 and 4 bpp; d = %d\n", mainName, d); + } + + pixDestroy(&pixs); + return 0; +} + diff --git a/leptonica/prog/converttopdf.c b/leptonica/prog/converttopdf.c new file mode 100644 index 00000000..4e7f62e6 --- /dev/null +++ b/leptonica/prog/converttopdf.c @@ -0,0 +1,78 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * converttopdf.c + * + * Bundles all image files that are in the designated directory, with + * optional matching substring, into a pdf. + * + * The encoding type depends on the input file format: + * jpeg ==> DCT (not transcoded) + * jp2k ==> JPX (not transcoded) + * tiff-g4 ==> G4 + * png ==> FLATE (some are not transcoded) + * The default resolution is set at 300 ppi if not given in the + * individual images, and the images are wrapped at full resolution. + * No title is attached. + * + * This is meant for the simplest set of input arguments. It is + * very fast for jpeg, jp2k and some png. + * The syntax for using all files in the directory is: + * convertopdf <directory> <pdf_outfile> + * The syntax using some substring to be matched in the file names is: + * converttopdf <directory> <substring> <pdf_outfile> + * If you want something more general, use convertfilestopdf. + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include <string.h> +#include "allheaders.h" + +int main(int argc, + char **argv) +{ +l_int32 ret; +char *dirin, *substr, *fileout; + + if (argc != 3 && argc != 4) { + lept_stderr( + " Syntax: converttopdf dir [substr] fileout\n" + " substr: Leave this out to bundle all files\n" + " fileout: Output pdf file\n"); + return 1; + } + dirin = argv[1]; + substr = (argc == 4) ? argv[2] : NULL; + fileout = (argc == 4) ? argv[3] : argv[2]; + + setLeptDebugOK(1); + ret = convertUnscaledFilesToPdf(dirin, substr, "", fileout); + return ret; +} diff --git a/leptonica/prog/converttops.c b/leptonica/prog/converttops.c new file mode 100644 index 00000000..855376f4 --- /dev/null +++ b/leptonica/prog/converttops.c @@ -0,0 +1,68 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * converttops.c + * + * Syntax: converttops filein fileout [level] + * + * where level = {1,2,3} and 2 is the default + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + +int main(int argc, + char **argv) +{ +char *filein, *fileout; +char error_msg[] = " ps level = {1,2,3}; level 2 is default"; +l_int32 level; +static char mainName[] = "converttops"; + + if (argc != 3 && argc != 4) { + lept_stderr("Syntax: converttops filein fileout [level]\n"); + lept_stderr("%s\n", error_msg); + return 1; + } + filein = argv[1]; + fileout = argv[2]; + level = 2; + if (argc == 4) { + level = atoi(argv[3]); + if (level != 1 && level != 2 && level != 3) { + L_WARNING("ps level must be 1, 2 or 3; setting to 2\n", mainName); + level = 2; + } + } + + setLeptDebugOK(1); + convertToPSEmbed(filein, fileout, level); + return 0; +} diff --git a/leptonica/prog/convolve_reg.c b/leptonica/prog/convolve_reg.c new file mode 100644 index 00000000..caf2422b --- /dev/null +++ b/leptonica/prog/convolve_reg.c @@ -0,0 +1,211 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * convolve_reg.c + * + * Tests a number of convolution functions. + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + +static const char *kel1str = " 20 50 80 50 20 " + " 50 100 140 100 50 " + " 90 160 200 160 90 " + " 50 100 140 100 50 " + " 20 50 80 50 20 "; + +static const char *kel2str = " -20 -50 -80 -50 -20 " + " -50 50 80 50 -50 " + " -90 90 200 90 -90 " + " -50 50 80 50 -50 " + " -20 -50 -80 -50 -20 "; + +static const char *kel3xstr = " -70 40 100 40 -70 "; +static const char *kel3ystr = " 20 -70 40 100 40 -70 20 "; + + +int main(int argc, + char **argv) +{ +l_int32 i, j, sizex, sizey, bias; +FPIX *fpixv, *fpixrv; +L_KERNEL *kel1, *kel2, *kel3x, *kel3y; +PIX *pixs, *pixacc, *pixg, *pixt, *pixd; +PIX *pixb, *pixm, *pixms, *pixrv, *pix1, *pix2, *pix3, *pix4; +L_REGPARAMS *rp; + + if (regTestSetup(argc, argv, &rp)) + return 1; + + /* Test pixBlockconvGray() on 8 bpp */ + pixs = pixRead("test8.jpg"); + pixacc = pixBlockconvAccum(pixs); + pixd = pixBlockconvGray(pixs, pixacc, 3, 5); + regTestWritePixAndCheck(rp, pixd, IFF_JFIF_JPEG); /* 0 */ + pixDisplayWithTitle(pixd, 100, 0, NULL, rp->display); + pixDestroy(&pixacc); + pixDestroy(&pixd); + + /* Test pixBlockconv() on 8 bpp */ + pixd = pixBlockconv(pixs, 9, 8); + regTestWritePixAndCheck(rp, pixd, IFF_JFIF_JPEG); /* 1 */ + pixDisplayWithTitle(pixd, 200, 0, NULL, rp->display); + pixDestroy(&pixd); + pixDestroy(&pixs); + + /* Test pixBlockrank() on 1 bpp */ + pixs = pixRead("test1.png"); + pixacc = pixBlockconvAccum(pixs); + for (i = 0; i < 3; i++) { + pixd = pixBlockrank(pixs, pixacc, 4, 4, 0.25 + 0.25 * i); + regTestWritePixAndCheck(rp, pixd, IFF_PNG); /* 2 - 4 */ + pixDisplayWithTitle(pixd, 300 + 100 * i, 0, NULL, rp->display); + pixDestroy(&pixd); + } + + /* Test pixBlocksum() on 1 bpp */ + pixd = pixBlocksum(pixs, pixacc, 16, 16); + regTestWritePixAndCheck(rp, pixd, IFF_JFIF_JPEG); /* 5 */ + pixDisplayWithTitle(pixd, 700, 0, NULL, rp->display); + pixDestroy(&pixd); + pixDestroy(&pixacc); + pixDestroy(&pixs); + + /* Test pixCensusTransform() */ + pixs = pixRead("test24.jpg"); + pixg = pixScaleRGBToGrayFast(pixs, 2, COLOR_GREEN); + pixd = pixCensusTransform(pixg, 10, NULL); + regTestWritePixAndCheck(rp, pixd, IFF_PNG); /* 6 */ + pixDisplayWithTitle(pixd, 800, 0, NULL, rp->display); + pixDestroy(&pixd); + + /* Test generic convolution with kel1 */ + kel1 = kernelCreateFromString(5, 5, 2, 2, kel1str); + pixd = pixConvolve(pixg, kel1, 8, 1); + regTestWritePixAndCheck(rp, pixd, IFF_JFIF_JPEG); /* 7 */ + pixDisplayWithTitle(pixd, 100, 500, NULL, rp->display); + pixDestroy(&pixd); + + /* Test convolution with flat rectangular kel */ + kel2 = kernelCreate(11, 11); + kernelSetOrigin(kel2, 5, 5); + for (i = 0; i < 11; i++) { + for (j = 0; j < 11; j++) + kernelSetElement(kel2, i, j, 1); + } + pixd = pixConvolve(pixg, kel2, 8, 1); + regTestWritePixAndCheck(rp, pixd, IFF_JFIF_JPEG); /* 8 */ + pixDisplayWithTitle(pixd, 200, 500, NULL, rp->display); + pixDestroy(&pixd); + kernelDestroy(&kel1); + kernelDestroy(&kel2); + + /* Test pixBlockconv() on 32 bpp */ + pixt = pixScaleBySampling(pixs, 0.5, 0.5); + pixd = pixBlockconv(pixt, 4, 6); + regTestWritePixAndCheck(rp, pixd, IFF_JFIF_JPEG); /* 9 */ + pixDisplayWithTitle(pixd, 300, 500, NULL, rp->display); + pixDestroy(&pixt); + pixDestroy(&pixs); + pixDestroy(&pixg); + pixDestroy(&pixd); + + /* Test bias convolution non-separable with kel2 */ + pixs = pixRead("marge.jpg"); + pixg = pixScaleRGBToGrayFast(pixs, 2, COLOR_GREEN); + kel2 = kernelCreateFromString(5, 5, 2, 2, kel2str); + pixd = pixConvolveWithBias(pixg, kel2, NULL, TRUE, &bias); + regTestWritePixAndCheck(rp, pixd, IFF_JFIF_JPEG); /* 10 */ + pixDisplayWithTitle(pixd, 400, 500, NULL, rp->display); + lept_stderr("bias = %d\n", bias); + kernelDestroy(&kel2); + pixDestroy(&pixd); + + /* Test bias convolution separable with kel3x and kel3y */ + kel3x = kernelCreateFromString(1, 5, 0, 2, kel3xstr); + kel3y = kernelCreateFromString(7, 1, 3, 0, kel3ystr); + pixd = pixConvolveWithBias(pixg, kel3x, kel3y, TRUE, &bias); + regTestWritePixAndCheck(rp, pixd, IFF_JFIF_JPEG); /* 11 */ + pixDisplayWithTitle(pixd, 500, 500, NULL, rp->display); + lept_stderr("bias = %d\n", bias); + kernelDestroy(&kel3x); + kernelDestroy(&kel3y); + pixDestroy(&pixd); + pixDestroy(&pixs); + pixDestroy(&pixg); + + /* Test pixWindowedMean() and pixWindowedMeanSquare() on 8 bpp */ + pixs = pixRead("feyn-fract2.tif"); + pixg = pixConvertTo8(pixs, 0); + sizex = 5; + sizey = 20; + pixb = pixAddBorderGeneral(pixg, sizex + 1, sizex + 1, + sizey + 1, sizey + 1, 0); + pixm = pixWindowedMean(pixb, sizex, sizey, 1, 1); + pixms = pixWindowedMeanSquare(pixb, sizex, sizey, 1); + regTestWritePixAndCheck(rp, pixm, IFF_JFIF_JPEG); /* 12 */ + pixDisplayWithTitle(pixm, 100, 0, NULL, rp->display); + pixDestroy(&pixs); + pixDestroy(&pixb); + + /* Test pixWindowedVariance() on 8 bpp */ + pixWindowedVariance(pixm, pixms, &fpixv, &fpixrv); + pixrv = fpixConvertToPix(fpixrv, 8, L_CLIP_TO_ZERO, 1); + regTestWritePixAndCheck(rp, pixrv, IFF_JFIF_JPEG); /* 13 */ + pixDisplayWithTitle(pixrv, 100, 250, NULL, rp->display); + pix1 = fpixDisplayMaxDynamicRange(fpixv); + pix2 = fpixDisplayMaxDynamicRange(fpixrv); + pixDisplayWithTitle(pix1, 100, 500, "Variance", rp->display); + pixDisplayWithTitle(pix2, 100, 750, "RMS deviation", rp->display); + regTestWritePixAndCheck(rp, pix1, IFF_JFIF_JPEG); /* 14 */ + regTestWritePixAndCheck(rp, pix2, IFF_JFIF_JPEG); /* 15 */ + fpixDestroy(&fpixv); + fpixDestroy(&fpixrv); + pixDestroy(&pixm); + pixDestroy(&pixms); + pixDestroy(&pixrv); + + /* Test again all windowed functions with simpler interface */ + pixWindowedStats(pixg, sizex, sizey, 0, NULL, NULL, &fpixv, &fpixrv); + pix3 = fpixDisplayMaxDynamicRange(fpixv); + pix4 = fpixDisplayMaxDynamicRange(fpixrv); + regTestComparePix(rp, pix1, pix3); /* 16 */ + regTestComparePix(rp, pix2, pix4); /* 17 */ + pixDestroy(&pixg); + pixDestroy(&pix1); + pixDestroy(&pix2); + pixDestroy(&pix3); + pixDestroy(&pix4); + fpixDestroy(&fpixv); + fpixDestroy(&fpixrv); + + return regTestCleanup(rp); +} diff --git a/leptonica/prog/cootoots.png b/leptonica/prog/cootoots.png Binary files differnew file mode 100644 index 00000000..4daabf99 --- /dev/null +++ b/leptonica/prog/cootoots.png diff --git a/leptonica/prog/copernicus.png b/leptonica/prog/copernicus.png Binary files differnew file mode 100644 index 00000000..1c1cb6f9 --- /dev/null +++ b/leptonica/prog/copernicus.png diff --git a/leptonica/prog/cornertest.c b/leptonica/prog/cornertest.c new file mode 100644 index 00000000..d069bc21 --- /dev/null +++ b/leptonica/prog/cornertest.c @@ -0,0 +1,104 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * cornertest.c + * + * e.g., use on witten.png + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + +#define LINE_SIZE 29 + + +int main(int argc, + char **argv) +{ +char *filein, *fileout; +l_int32 x, y, n, i; +PIX *pixs; +PTA *pta; +PTAA *ptaa, *ptaa2, *ptaa3; +static char mainName[] = "cornertest"; + + if (argc != 3) + return ERROR_INT(" Syntax: cornertest filein fileout", mainName, 1); + filein = argv[1]; + fileout = argv[2]; + + setLeptDebugOK(1); + if ((pixs = pixRead(filein)) == NULL) + return ERROR_INT("pixs not made", mainName, 1); + + /* Clean noise in LR corner of witten.tif */ + pixSetPixel(pixs, 2252, 3051, 0); + pixSetPixel(pixs, 2252, 3050, 0); + pixSetPixel(pixs, 2251, 3050, 0); + + pta = pixFindCornerPixels(pixs); + ptaWriteStream(stderr, pta, 1); + + /* Test pta and ptaa I/O */ +#if 1 + ptaa = ptaaCreate(3); + ptaaAddPta(ptaa, pta, L_COPY); + ptaaAddPta(ptaa, pta, L_COPY); + ptaaAddPta(ptaa, pta, L_COPY); + ptaaWriteStream(stderr, ptaa, 1); + ptaaWrite("/tmp/junkptaa", ptaa, 1); + ptaa2 = ptaaRead("/tmp/junkptaa"); + ptaaWrite("/tmp/junkptaa2", ptaa2, 1); + ptaaWrite("/tmp/junkptaa3", ptaa, 0); + ptaa3 = ptaaRead("/tmp/junkptaa3"); + ptaaWrite("/tmp/junkptaa4", ptaa3, 0); + ptaaDestroy(&ptaa); + ptaaDestroy(&ptaa2); + ptaaDestroy(&ptaa3); +#endif + + /* mark corner pixels */ + n = ptaGetCount(pta); + for (i = 0; i < n; i++) { + ptaGetIPt(pta, i, &x, &y); + pixRenderLine(pixs, x - LINE_SIZE, y, x + LINE_SIZE, y, 5, + L_FLIP_PIXELS); + pixRenderLine(pixs, x, y - LINE_SIZE, x, y + LINE_SIZE, 5, + L_FLIP_PIXELS); + } + + pixWrite(fileout, pixs, IFF_PNG); + + pixDestroy(&pixs); + ptaDestroy(&pta); + ptaDestroy(&pta); + return 0; +} + diff --git a/leptonica/prog/corrupttest.c b/leptonica/prog/corrupttest.c new file mode 100644 index 00000000..8ff6aec6 --- /dev/null +++ b/leptonica/prog/corrupttest.c @@ -0,0 +1,271 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * corrupttest.c + * + * Excises or permutes a given fraction of bytes, starting from + * a specified location. The parameters @loc and @size are fractions + * of the entire file (between 0.0 and 1.0). + * + * Syntax: corrupttest <file> <deletion> [loc size] + * + * where <deletion> == 1 means that bytes are deleted + * <deletion> == 0 means that random bytes are substituted + * + * Use: "fuzz testing" jpeg, png, tiff, bmp, webp and pnm reading, + * under corruption by either random byte substitution or + * deletion of part of the compressed file. + * + * For example, + * corrupttest rabi.png 0 0.0001 0.0001 + * which tests read functions on rabi.png after 23 bytes (0.01%) + * starting at byte 23 have been randomly permuted, emits the following: + * > Info in fileCorruptByMutation: Randomizing 23 bytes at location 23 + * > libpng error: IHDR: CRC error + * > Error in pixReadMemPng: internal png error + * > Error in pixReadStream: png: no pix returned + * > Error in pixRead: pix not read + * > libpng error: IHDR: CRC error + * > Error in fgetPngResolution: internal png error + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "string.h" +#include "allheaders.h" + +static const char *corruptfile = "/tmp/lept/corrupt/badfile"; + +int main(int argc, + char **argv) +{ +size_t filesize; +l_float32 loc, size; +l_float32 coeff1[15], coeff2[25]; +l_int32 i, j, w, xres, yres, format, ret, nwarn, hint, deletion, show; +l_uint8 *comment, *filedata; +char *filein; +size_t nbytes; +FILE *fp; +PIX *pix; +static char mainName[] = "corrupttest"; + + if (argc != 3 && argc != 5) + return ERROR_INT("syntax: corrupttest filein deletion [loc size]", + mainName, 1); + filein = argv[1]; + deletion = atoi(argv[2]); + findFileFormat(filein, &format); + nbytes = nbytesInFile(filein); + lept_stderr("file size: %lu bytes\n", (unsigned long)nbytes); + + setLeptDebugOK(1); + lept_mkdir("lept/corrupt"); + + hint = 0; + if (argc == 5) { /* Single test */ + loc = atof(argv[3]); + size = atof(argv[4]); + if (deletion == TRUE) { + fileCorruptByDeletion(filein, loc, size, corruptfile); + } else { /* mutation */ + fileCorruptByMutation(filein, loc, size, corruptfile); + } + if ((fp = fopenReadStream(corruptfile)) == NULL) + return ERROR_INT("stream not opened", mainName, 1); + if (format == IFF_JFIF_JPEG) { + if ((pix = pixReadJpeg(corruptfile, 0, 1, &nwarn, hint)) != NULL) { + pixDisplay(pix, 100, 100); + pixDestroy(&pix); + } + freadHeaderJpeg(fp, &w, NULL, NULL, NULL, NULL); + fgetJpegResolution(fp, &xres, &yres); + ret = fgetJpegComment(fp, &comment); + if (!ret && comment) { + lept_stderr("comment: %s\n", comment); + lept_free(comment); + } + } else if (format == IFF_PNG) { + if ((pix = pixRead(corruptfile)) != NULL) { + pixDisplay(pix, 100, 100); + pixDestroy(&pix); + } + freadHeaderPng(fp, &w, NULL, NULL, NULL, NULL); + fgetPngResolution(fp, &xres, &yres); + } else if (format == IFF_WEBP) { + if ((pix = pixRead(corruptfile)) != NULL) { + pixDisplay(pix, 100, 100); + pixDestroy(&pix); + } + readHeaderWebP(corruptfile, &w, NULL, NULL); + } else if (format == IFF_PNM) { + if ((pix = pixRead(corruptfile)) != NULL) { + pixDisplay(pix, 100, 100); + pixDestroy(&pix); + } + freadHeaderPnm(fp, &w, NULL, NULL, NULL, NULL, NULL); + } + fclose(fp); + return 0; + } + + /* Generate coefficients so that the size of the mangled + * or deleted data can range from 0.001% to 1% of the file, + * and the location of deleted data ranges from 0.001% + * to 90% of the file. */ + for (i = 0; i < 15; i++) { + if (i < 5) coeff1[i] = 0.00001; + else if (i < 10) coeff1[i] = 0.0001; + else coeff1[i] = 0.001; + } + for (i = 0; i < 25; i++) { + if (i < 5) coeff2[i] = 0.00001; + else if (i < 10) coeff2[i] = 0.0001; + else if (i < 15) coeff2[i] = 0.001; + else if (i < 20) coeff2[i] = 0.01; + else coeff2[i] = 0.1; + } + + /* Multiple test (argc == 3) */ + show = TRUE; + for (i = 0; i < 25; i++) { + loc = coeff2[i] * (2 * (i % 5) + 1); + for (j = 0; j < 15; j++) { + size = coeff1[j] * (2 * (j % 5) + 1); + + /* Write corrupt file */ + if (deletion == TRUE) { + fileCorruptByDeletion(filein, loc, size, corruptfile); + } else { + fileCorruptByMutation(filein, loc, size, corruptfile); + } + + /* Attempt to read the file */ + pix = NULL; + if (format == IFF_JFIF_JPEG) { + /* The pix is usually returned as long as the header + * information is not damaged. + * We expect nwarn > 0 (typically 1) for nearly every + * corrupted image. In the situation where only a few + * bytes are removed, a corrupted image will occasionally + * have nwarn == 0 even though it's visually defective. */ + pix = pixReadJpeg(corruptfile, 0, 1, &nwarn, 0); + if (pix && nwarn != 1 && deletion == TRUE) { + lept_stderr("nwarn[%d,%d] = %d\n", j, i, nwarn); + if (show) pixDisplay(pix, 20 * i, 30 * j); + show = FALSE; + } + } else if (format == IFF_PNG) { + pix = pixRead(corruptfile); + if (pix) { + lept_stderr("pix[%d,%d] is read\n", j, i); + if (show) pixDisplay(pix, 20 * i, 30 * j); + show = FALSE; + } + pixDestroy(&pix); + filedata = l_binaryRead(corruptfile, &filesize); + pix = pixReadMemPng(filedata, filesize); + lept_free(filedata); + } else if (L_FORMAT_IS_TIFF(format)) { + /* A corrupted pix is often returned, as long as the + * header is not damaged, so we do not display them. */ + pix = pixRead(corruptfile); + if (pix) lept_stderr("pix[%d,%d] is read\n", j, i); + pixDestroy(&pix); + filedata = l_binaryRead(corruptfile, &filesize); + pix = pixReadMemTiff(filedata, filesize, 0); + if (!pix) lept_stderr("no pix!\n"); + lept_free(filedata); + } else if (format == IFF_BMP) { + /* A corrupted pix is always returned if the header is + * not damaged, so we do not display them. */ + pix = pixRead(corruptfile); + if (pix) lept_stderr("pix[%d,%d] is read\n", j, i); + pixDestroy(&pix); + filedata = l_binaryRead(corruptfile, &filesize); + pix = pixReadMemBmp(filedata, filesize); + lept_free(filedata); + } else if (format == IFF_WEBP) { + /* A corrupted pix is always returned if the header is + * not damaged, so we do not display them. */ + pix = pixRead(corruptfile); + if (pix) lept_stderr("pix[%d,%d] is read\n", j, i); + pixDestroy(&pix); + filedata = l_binaryRead(corruptfile, &filesize); + pix = pixReadMemWebP(filedata, filesize); + lept_free(filedata); + } else if (format == IFF_PNM) { + /* A corrupted pix is always returned if the header is + * not damaged, so we do not display them. */ + pix = pixRead(corruptfile); + if (pix) lept_stderr("pix[%d,%d] is read\n", j, i); + pixDestroy(&pix); + filedata = l_binaryRead(corruptfile, &filesize); + pix = pixReadMemPnm(filedata, filesize); + lept_free(filedata); + } else { + lept_stderr("Format %d unknown\n", format); + continue; + } + + /* Effect of 1% byte mangling from interior of data stream */ + if (pix && j == 14 && i == 10 && deletion == FALSE) + pixDisplay(pix, 0, 0); + pixDestroy(&pix); + + /* Attempt to read the header and the resolution */ + fp = fopenReadStream(corruptfile); + if (format == IFF_JFIF_JPEG) { + freadHeaderJpeg(fp, &w, NULL, NULL, NULL, NULL); + if (fgetJpegResolution(fp, &xres, &yres) == 0) + lept_stderr("w = %d, xres = %d, yres = %d\n", + w, xres, yres); + } else if (format == IFF_PNG) { + freadHeaderPng(fp, &w, NULL, NULL, NULL, NULL); + if (fgetPngResolution(fp, &xres, &yres) == 0) + lept_stderr("w = %d, xres = %d, yres = %d\n", + w, xres, yres); + } else if (L_FORMAT_IS_TIFF(format)) { + freadHeaderTiff(fp, 0, &w, NULL, NULL, NULL, NULL, NULL, NULL); + getTiffResolution(fp, &xres, &yres); + lept_stderr("w = %d, xres = %d, yres = %d\n", + w, xres, yres); + } else if (format == IFF_WEBP) { + if (readHeaderWebP(corruptfile, &w, NULL, NULL) == 0) + lept_stderr("w = %d\n", w); + } else if (format == IFF_PNM) { + if (freadHeaderPnm(fp, &w, NULL, NULL, NULL, NULL, NULL) == 0) + lept_stderr("w = %d\n", w); + } + fclose(fp); + } + } + return 0; +} + diff --git a/leptonica/prog/crop_reg.c b/leptonica/prog/crop_reg.c new file mode 100644 index 00000000..c38f331a --- /dev/null +++ b/leptonica/prog/crop_reg.c @@ -0,0 +1,320 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * crop_reg.c + * + * Test: + * * plotting pixel profiles + * * undercropping from a box (i.e., with an added border) + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + +static const l_int32 mindif = 60; + +static l_int32 GetLeftCut(NUMA *narl, NUMA *nart, NUMA *nait, + l_int32 h, l_int32 *pleft); +static 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) +{ +l_int32 i, pageno, w, h, left, right; +BOX *box1, *box2; +NUMA *na1, *nar, *naro, *narl, *nart, *nai, *naio, *nait; +PIX *pixs, *pixr, *pixg, *pixgi, *pixd, *pix1, *pix2, *pix3, *pix4; +PIXA *pixa1, *pixa2; +L_REGPARAMS *rp; + + if (regTestSetup(argc, argv, &rp)) + return 1; + + lept_mkdir("lept/crop"); + + /* Calculate projection profiles through images/drawings. */ + pixa1 = pixaCreate(2); + for (i = 0; i < 2; i++) { + pageno = extractNumberFromFilename(fnames[i], 5, 0); + lept_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); + pix1 = gplotSimplePix1(naro, "Reversals Opened"); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 0,2 */ + narl = numaLowPassIntervals(naro, 0.1, 0.0); + nart = numaThresholdEdges(naro, 0.1, 0.5, 0.0); + 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); + pix2 = gplotSimplePix1(naio, "Intensities Opened"); + regTestWritePixAndCheck(rp, pix2, IFF_PNG); /* 1,3 */ + nait = numaThresholdEdges(naio, 0.4, 0.6, 0.0); + numaDestroy(&nai); + numaDestroy(&naio); + + /* Analyze profiles for left/right edges */ + GetLeftCut(narl, nart, nait, w, &left); + GetRightCut(narl, nart, nait, w, &right); + if (rp->display) + lept_stderr("left = %d, right = %d\n", left, right); + + /* Output visuals */ + pixa2 = pixaCreate(3); + pixaAddPix(pixa2, pixr, L_INSERT); + pixaAddPix(pixa2, pix1, L_INSERT); + pixaAddPix(pixa2, pix2, L_INSERT); + pixd = pixaDisplayTiledInColumns(pixa2, 2, 1.0, 25, 0); + pixaDestroy(&pixa2); + pixaAddPix(pixa1, pixd, L_INSERT); + pixDisplayWithTitle(pixd, 800 * i, 100, NULL, rp->display); + if (rp->display) { + lept_stderr("narl:"); + numaWriteStderr(narl); + lept_stderr("nart:"); + numaWriteStderr(nart); + lept_stderr("nait:"); + numaWriteStderr(nait); + } + pixDestroy(&pixs); + pixDestroy(&pixg); + pixDestroy(&pixgi); + numaDestroy(&narl); + numaDestroy(&nart); + numaDestroy(&nait); + } + + lept_stderr("Writing profiles to /tmp/lept/crop/croptest.pdf\n"); + pixaConvertToPdf(pixa1, 75, 1.0, L_JPEG_ENCODE, 0, "Profiles", + "/tmp/lept/crop/croptest.pdf"); + pixaDestroy(&pixa1); + + /* Calculate projection profiles from text lines */ + pixs = pixRead("1555.007.jpg"); + pixGetDimensions(pixs, &w, &h, NULL); + na1 = pixReversalProfile(pixs, 0.98, L_HORIZONTAL_LINE, + 0, h - 1, 40, 3, 3); + pix1 = gplotSimplePix1(na1, "Reversals"); + numaDestroy(&na1); + + na1 = pixAverageIntensityProfile(pixs, 0.98, L_HORIZONTAL_LINE, + 0, h - 1, 1, 1); + pix2 = gplotSimplePix1(na1, "Intensities"); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 4 */ + regTestWritePixAndCheck(rp, pix2, IFF_PNG); /* 5 */ + numaDestroy(&na1); + pixa1 = pixaCreate(3); + pixaAddPix(pixa1, pixScale(pixs, 0.5, 0.5), L_INSERT); + pixaAddPix(pixa1, pix1, L_INSERT); + pixaAddPix(pixa1, pix2, L_INSERT); + pixd = pixaDisplayTiledInRows(pixa1, 32, 1000, 1.0, 0, 30, 2); + pixWrite("/tmp/lept/crop/profiles.png", pixd, IFF_PNG); + pixDisplayWithTitle(pixd, 0, 700, NULL, rp->display); + pixDestroy(&pixs); + pixDestroy(&pixd); + pixaDestroy(&pixa1); + + /* Test rectangle clipping with border */ + pix1 = pixRead("lyra.005.jpg"); + pix2 = pixScale(pix1, 0.5, 0.5); + box1 = boxCreate(125, 50, 180, 230); /* fully contained */ + pix3 = pixClipRectangleWithBorder(pix2, box1, 30, &box2); + pixRenderBoxArb(pix2, box1, 2, 255, 0, 0); + pixRenderBoxArb(pix3, box2, 2, 255, 0, 0); + pixa1 = pixaCreate(2); + pixaAddPix(pixa1, pix2, L_INSERT); + pixaAddPix(pixa1, pix3, L_INSERT); + pix4 = pixaDisplayTiledInColumns(pixa1, 2, 1.0, 15, 2); + regTestWritePixAndCheck(rp, pix4, IFF_PNG); /* 6 */ + pixDisplayWithTitle(pix4, 325, 700, NULL, rp->display); + boxDestroy(&box1); + boxDestroy(&box2); + pixDestroy(&pix4); + pixaDestroy(&pixa1); + + pix2 = pixScale(pix1, 0.5, 0.5); + box1 = boxCreate(125, 10, 180, 270); /* not full border */ + pix3 = pixClipRectangleWithBorder(pix2, box1, 30, &box2); + pixRenderBoxArb(pix2, box1, 2, 255, 0, 0); + pixRenderBoxArb(pix3, box2, 2, 255, 0, 0); + pixa1 = pixaCreate(2); + pixaAddPix(pixa1, pix2, L_INSERT); + pixaAddPix(pixa1, pix3, L_INSERT); + pix4 = pixaDisplayTiledInColumns(pixa1, 2, 1.0, 15, 2); + regTestWritePixAndCheck(rp, pix4, IFF_PNG); /* 7 */ + pixDisplayWithTitle(pix4, 975, 700, NULL, rp->display); + boxDestroy(&box1); + boxDestroy(&box2); + pixDestroy(&pix4); + pixaDestroy(&pixa1); + + pix2 = pixScale(pix1, 0.5, 0.5); + box1 = boxCreate(125, 200, 180, 270); /* not entirely within pix2 */ + pix3 = pixClipRectangleWithBorder(pix2, box1, 30, &box2); + pixRenderBoxArb(pix2, box1, 2, 255, 0, 0); + pixRenderBoxArb(pix3, box2, 2, 255, 0, 0); + pixa1 = pixaCreate(2); + pixaAddPix(pixa1, pix2, L_INSERT); + pixaAddPix(pixa1, pix3, L_INSERT); + pix4 = pixaDisplayTiledInColumns(pixa1, 2, 1.0, 15, 2); + regTestWritePixAndCheck(rp, pix4, IFF_PNG); /* 8 */ + pixDisplayWithTitle(pix4, 1600, 700, NULL, rp->display); + boxDestroy(&box1); + boxDestroy(&box2); + pixDestroy(&pix4); + pixaDestroy(&pixa1); + pixDestroy(&pix1); + + return regTestCleanup(rp); +} + + +/* + * 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 + */ +static 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); + } + lept_stderr("txt1 = %d, pap1 = %d\n", txt1, pap1); + *pleft = pap1; + return 0; +} + + +static 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; + } + lept_stderr("txt2 = %d, pap2 = %d\n", txt2, pap2); + *pright = pap2; + return 0; +} + diff --git a/leptonica/prog/croptext.c b/leptonica/prog/croptext.c new file mode 100644 index 00000000..c1e72e5a --- /dev/null +++ b/leptonica/prog/croptext.c @@ -0,0 +1,99 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * croptext.c + * + * Simple program that crops text pages to a given border + * + * Syntax: + * croptext dirin border dirout + * where + * border = number of pixels added on each side (e.g., 50) + * + * The output file name has the same tail as the input file name. + * If dirout is the same as dirin, you overwrite the input files. + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + +int main(int argc, + char **argv) +{ +char *dirin, *dirout, *infile, *outfile, *tail; +l_int32 i, nfiles, border, x, y, w, h, xb, yb, wb, hb; +BOX *box1, *box2; +BOXA *boxa1, *boxa2; +PIX *pixs, *pixt1, *pixd; +SARRAY *safiles; +static char mainName[] = "croptext"; + + if (argc != 4) + return ERROR_INT("Syntax: croptext dirin border dirout", mainName, 1); + dirin = argv[1]; + border = atoi(argv[2]); + dirout = argv[3]; + + setLeptDebugOK(1); + safiles = getSortedPathnamesInDirectory(dirin, NULL, 0, 0); + nfiles = sarrayGetCount(safiles); + + for (i = 0; i < nfiles; i++) { + infile = sarrayGetString(safiles, i, L_NOCOPY); + splitPathAtDirectory(infile, NULL, &tail); + outfile = genPathname(dirout, tail); + pixs = pixRead(infile); + pixt1 = pixMorphSequence(pixs, "r11 + c10.40 + o5.5 + x4", 0); + boxa1 = pixConnComp(pixt1, NULL, 8); + if (boxaGetCount(boxa1) == 0) { + lept_stderr("Warning: no components on page %s\n", tail); + continue; + } + boxa2 = boxaSort(boxa1, L_SORT_BY_AREA, L_SORT_DECREASING, NULL); + box1 = boxaGetBox(boxa2, 0, L_CLONE); + boxGetGeometry(box1, &x, &y, &w, &h); + xb = L_MAX(0, x - border); + yb = L_MAX(0, y - border); + wb = w + 2 * border; + hb = h + 2 * border; + box2 = boxCreate(xb, yb, wb, hb); + pixd = pixClipRectangle(pixs, box2, NULL); + pixWrite(outfile, pixd, IFF_TIFF_G4); + + pixDestroy(&pixs); + pixDestroy(&pixt1); + pixDestroy(&pixd); + boxaDestroy(&boxa1); + boxaDestroy(&boxa2); + } + + return 0; +} + diff --git a/leptonica/prog/dave-orig.png b/leptonica/prog/dave-orig.png Binary files differnew file mode 100644 index 00000000..7948cb5a --- /dev/null +++ b/leptonica/prog/dave-orig.png diff --git a/leptonica/prog/deskew_it.c b/leptonica/prog/deskew_it.c new file mode 100644 index 00000000..db082b8d --- /dev/null +++ b/leptonica/prog/deskew_it.c @@ -0,0 +1,140 @@ +/*====================================================================* + - 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. + *====================================================================*/ + + +/* + * deskew_it.c + * + * deskew_it filein threshold sweeprange tryboth fileout + * + * where: + * threshold: for binarization, use 0 for default (130) + * sweeprange: half the sweep angle search range, in degrees; + * use 0 for default (7.0 degrees) + * tryboth: 1 to test for skew both as input and with a 90 deg rotation; + * 0 to test for skew as input only + * + * On failure to deskew, write the input image to the output (not rotated). + * + * For further information on these and other defaulted parameters, + * see skew.c. + + * For testing the deskew functions, see skewtest.c and the skew + * regression test skew_reg.c. + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + + /* Default binarization threshold */ +static const l_int32 DefaultThreshold = 130; + + /* Default half angle for searching */ +static const l_float32 DefaultSweepRange = 7.0; /* degrees */ + + +int main(int argc, + char **argv) +{ +char *filein, *fileout; +l_int32 threshold, tryboth, format; +l_float32 deg2rad, sweeprange, angle, conf; +PIX *pixs, *pix1, *pix2, *pixd; +static char mainName[] = "deskew_it"; + + if (argc != 6) + return ERROR_INT( + "\n Syntax: deskew_it filein threshold sweeprange tryboth fileout", + mainName, 1); + + filein = argv[1]; + threshold = atoi(argv[2]); + sweeprange = atof(argv[3]); + tryboth = atoi(argv[4]); + fileout = argv[5]; + + setLeptDebugOK(1); + pixd = NULL; + deg2rad = 3.1415926535 / 180.; + + if ((pixs = pixRead(filein)) == NULL) + return ERROR_INT("pixs not made", mainName, 1); + + sweeprange = (sweeprange == 0) ? DefaultSweepRange : sweeprange; + threshold = (threshold == 0) ? DefaultThreshold : threshold; + format = pixGetInputFormat(pixs); + if (format == IFF_UNKNOWN) format = IFF_PNG; + + pixd = pixDeskewGeneral(pixs, 0, sweeprange, 0.0, 0, threshold, + &angle, &conf); + if (!pixd) { + L_ERROR("deskew failed; pixd not made\n", mainName); + pixWrite(fileout, pixs, format); + pixDestroy(&pixs); + return 1; + } + lept_stderr("skew angle = %.3f, conf = %.1f\n", angle, conf); + + /* Two situations were we're finished: + * (1) conf >= 3.0 and it's good enough, so write out pixd + * (2) conf < 3.0, so pixd is a clone of pixs, and we're + * only trying once. */ + if (conf >= 3.0 || tryboth == 0) { + pixWrite(fileout, pixd, format); + pixDestroy(&pixs); + pixDestroy(&pixd); + return 0; + } + pixDestroy(&pixd); + + /* Confidence was less than the min acceptable, but we will + * try again (tryboth == 1) after a 90 degree rotation. */ + pix1 = pixRotateOrth(pixs, 1); + pix2 = pixDeskewGeneral(pix1, 0, sweeprange, 0.0, 0, threshold, + &angle, &conf); + pixDestroy(&pix1); + if (!pix2) { + L_ERROR("deskew failed at 90 deg; pixd not made\n", mainName); + pixWrite(fileout, pixs, format); + pixDestroy(&pixs); + return 1; + } + lept_stderr("90 rot: skew angle = %.3f, conf = %.1f\n", angle, conf); + + if (conf < 3.0) { + pixWrite(fileout, pixs, format); + } else { + pixd = pixRotateOrth(pix2, 3); + pixWrite(fileout, pixd, format); + pixDestroy(&pixd); + } + pixDestroy(&pixs); + pixDestroy(&pix2); + return 0; +} diff --git a/leptonica/prog/dewarp_reg.c b/leptonica/prog/dewarp_reg.c new file mode 100644 index 00000000..1e3db289 --- /dev/null +++ b/leptonica/prog/dewarp_reg.c @@ -0,0 +1,211 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * dewarp_reg.c + * + * Regression test for image dewarp based on text lines + * + * We also test some of the fpix and dpix functions (scaling, + * serialization, interconversion) + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + +l_int32 main(int argc, + char **argv) +{ +l_int32 i, n; +l_float32 a, b, c; +L_DEWARP *dew1, *dew2; +L_DEWARPA *dewa1, *dewa2; +DPIX *dpix1, *dpix2, *dpix3; +FPIX *fpix1, *fpix2, *fpix3; +NUMA *nax, *nafit; +PIX *pixs, *pixn, *pixg, *pixd, *pixb, *pix1, *pixt1, *pixt2; +PIX *pixs2, *pixn2, *pixg2, *pixb2; +PTA *pta, *ptad; +PTAA *ptaa1, *ptaa2; +L_REGPARAMS *rp; + + if (regTestSetup(argc, argv, &rp)) + return 1; + + /* Read page 7, normalize for varying background and binarize */ + pixs = pixRead("1555.007.jpg"); + pixn = pixBackgroundNormSimple(pixs, NULL, NULL); + pixg = pixConvertRGBToGray(pixn, 0.5, 0.3, 0.2); + pixb = pixThresholdToBinary(pixg, 130); + pixDestroy(&pixn); + pixDestroy(&pixg); + regTestWritePixAndCheck(rp, pixb, IFF_PNG); /* 0 */ + pixDisplayWithTitle(pixb, 0, 0, "page 7 binarized input", rp->display); + + /* Get the textline centers */ + ptaa1 = dewarpGetTextlineCenters(pixb, 0); + pixt1 = pixCreateTemplate(pixs); + pixt2 = pixDisplayPtaa(pixt1, ptaa1); + regTestWritePixAndCheck(rp, pixt2, IFF_PNG); /* 1 */ + pixDisplayWithTitle(pixt2, 0, 500, "textline centers", rp->display); + pixDestroy(&pixt1); + + /* Remove short lines */ + ptaa2 = dewarpRemoveShortLines(pixb, ptaa1, 0.8, 0); + + /* Fit to quadratic */ + n = ptaaGetCount(ptaa2); + for (i = 0; i < n; i++) { + pta = ptaaGetPta(ptaa2, i, L_CLONE); + ptaGetArrays(pta, &nax, NULL); + ptaGetQuadraticLSF(pta, &a, &b, &c, &nafit); + ptad = ptaCreateFromNuma(nax, nafit); + pixDisplayPta(pixt2, pixt2, ptad); + ptaDestroy(&pta); + ptaDestroy(&ptad); + numaDestroy(&nax); + numaDestroy(&nafit); + } + regTestWritePixAndCheck(rp, pixt2, IFF_PNG); /* 2 */ + pixDisplayWithTitle(pixt2, 300, 500, "fitted lines superimposed", + rp->display); + ptaaDestroy(&ptaa1); + ptaaDestroy(&ptaa2); + pixDestroy(&pixt2); + + /* Build the model for page 7 and dewarp */ + dewa1 = dewarpaCreate(2, 30, 1, 15, 30); + if ((dew1 = dewarpCreate(pixb, 7)) == NULL) + return ERROR_INT("\n\n\n FAILURE !!! \n\n\n", rp->testname, 1); + dewarpaUseBothArrays(dewa1, 1); + dewarpaInsertDewarp(dewa1, dew1); + dewarpBuildPageModel(dew1, NULL); + dewarpaApplyDisparity(dewa1, 7, pixb, 200, 0, 0, &pixd, NULL); + regTestWritePixAndCheck(rp, pixd, IFF_PNG); /* 3 */ + pixDisplayWithTitle(pixd, 400, 0, "page 7 dewarped", rp->display); + pixDestroy(&pixd); + + /* Read page 3, normalize background and binarize */ + pixs2 = pixRead("1555.003.jpg"); + pixn2 = pixBackgroundNormSimple(pixs2, NULL, NULL); + pixg2 = pixConvertRGBToGray(pixn2, 0.5, 0.3, 0.2); + pixb2 = pixThresholdToBinary(pixg2, 130); + pixDestroy(&pixn2); + pixDestroy(&pixg2); + regTestWritePixAndCheck(rp, pixb, IFF_PNG); /* 4 */ + pixDisplayWithTitle(pixb, 0, 400, "binarized input (2)", rp->display); + + /* Minimize and re-apply page 7 disparity to this image */ + dewarpaInsertRefModels(dewa1, 0, 0); + dewarpaApplyDisparity(dewa1, 3, pixb2, 200, 0, 0, &pixd, NULL); + regTestWritePixAndCheck(rp, pixd, IFF_PNG); /* 5 */ + pixDisplayWithTitle(pixd, 400, 400, "page 3 dewarped", rp->display); + pixDestroy(&pixd); + + /* Write and read back minimized dewarp struct */ + dewarpMinimize(dew1); + dewarpWrite("/tmp/lept/regout/dewarp.6.dew", dew1); + regTestCheckFile(rp, "/tmp/lept/regout/dewarp.6.dew"); /* 6 */ + dew2 = dewarpRead("/tmp/lept/regout/dewarp.6.dew"); + dewarpWrite("/tmp/lept/regout/dewarp.7.dew", dew2); + regTestCheckFile(rp, "/tmp/lept/regout/dewarp.7.dew"); /* 7 */ + regTestCompareFiles(rp, 6, 7); /* 8 */ + + /* Apply this minimized dew to page 3 in a new dewa */ + dewa2 = dewarpaCreate(2, 30, 1, 15, 30); + dewarpaUseBothArrays(dewa2, 1); + dewarpaInsertDewarp(dewa2, dew2); + dewarpaInsertRefModels(dewa2, 0, 0); + dewarpaListPages(dewa2); /* just for fun: should be 1, 3, 5, 7 */ + dewarpaApplyDisparity(dewa2, 3, pixb2, 200, 0, 0, &pixd, NULL); + regTestWritePixAndCheck(rp, pixd, IFF_PNG); /* 9 */ + pixDisplayWithTitle(pixd, 800, 400, "page 3 dewarped again", rp->display); + pixDestroy(&pixd); + + /* Minimize, re-populate disparity arrays, and apply again */ + dewarpMinimize(dew2); + dewarpaApplyDisparity(dewa2, 3, pixb2, 200, 0, 0, &pixd, NULL); + regTestWritePixAndCheck(rp, pixd, IFF_PNG); /* 10 */ + regTestCompareFiles(rp, 9, 10); /* 11 */ + pixDisplayWithTitle(pixd, 900, 400, "page 3 dewarped yet again", + rp->display); + pixDestroy(&pixd); + + /* Test a few of the fpix functions */ + if (!dew2) { + L_ERROR("dew2 doesn't exist !!!!\n", "dewarp_reg"); + return 1; + } + fpix1 = fpixClone(dew2->sampvdispar); + fpixWrite("/tmp/lept/regout/dewarp.12.fpix", fpix1); + regTestCheckFile(rp, "/tmp/lept/regout/dewarp.12.fpix"); /* 12 */ + + fpix2 = fpixRead("/tmp/lept/regout/dewarp.12.fpix"); + fpixWrite("/tmp/lept/regout/dewarp.13.fpix", fpix2); + regTestCheckFile(rp, "/tmp/lept/regout/dewarp.13.fpix"); /* 13 */ + regTestCompareFiles(rp, 12, 13); /* 14 */ + fpix3 = fpixScaleByInteger(fpix2, 30); + pix1 = fpixRenderContours(fpix3, 2.0, 0.2); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 15 */ + pixDisplayWithTitle(pix1, 0, 800, "v. disparity contours", rp->display); + fpixDestroy(&fpix1); + fpixDestroy(&fpix2); + fpixDestroy(&fpix3); + + /* Test a few of the dpix functions. Note that we can't compare + * 15 with 19, because of a tiny difference due to float roundoff, + * so we do an approximate comparison on the images. */ + dpix1 = fpixConvertToDPix(dew2->sampvdispar); + dpixWrite("/tmp/lept/regout/dewarp.16.dpix", dpix1); + regTestCheckFile(rp, "/tmp/lept/regout/dewarp.16.dpix"); /* 16 */ + dpix2 = dpixRead("/tmp/lept/regout/dewarp.16.dpix"); + dpixWrite("/tmp/lept/regout/dewarp.17.dpix", dpix2); + regTestCheckFile(rp, "/tmp/lept/regout/dewarp.17.dpix"); /* 17 */ + regTestCompareFiles(rp, 16, 17); /* 18 */ + dpix3 = dpixScaleByInteger(dpix2, 30); + fpix3 = dpixConvertToFPix(dpix3); + pixt1 = fpixRenderContours(fpix3, 2.0, 0.2); + regTestWritePixAndCheck(rp, pixt1, IFF_PNG); /* 19 */ + pixDisplayWithTitle(pixt1, 400, 800, "v. disparity contours", rp->display); + regTestCompareSimilarPix(rp, pix1, pixt1, 1, 0.00001, 0); /* 20 */ + dpixDestroy(&dpix1); + dpixDestroy(&dpix2); + dpixDestroy(&dpix3); + fpixDestroy(&fpix3); + pixDestroy(&pix1); + pixDestroy(&pixt1); + + dewarpaDestroy(&dewa1); + dewarpaDestroy(&dewa2); + pixDestroy(&pixs); + pixDestroy(&pixb); + pixDestroy(&pixs2); + pixDestroy(&pixb2); + return regTestCleanup(rp); +} diff --git a/leptonica/prog/dewarprules.c b/leptonica/prog/dewarprules.c new file mode 100644 index 00000000..3eab1e1f --- /dev/null +++ b/leptonica/prog/dewarprules.c @@ -0,0 +1,176 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * dewarprules.c + * + * Syntax: dewarprules select ndew + * where select = 0 (sudoku), 1 (graph paper) + * ndew = 1 (simple) or 2 (twice with rotations) + * + * There are two ways to dewarp the images: + * (1) use dewarpBuildLineModel() to correct both vertical and + * horizontal disparity with 1 dew + * (2) use dewarpBuildPageModel() twice, correcting only for + * vertical disparity, with 90 degree rotations in between + * and at the end. + * + * A challenge was presented in: + * http://stackoverflow.com/questions/10196198/how-to-remove-convexity-defects-in-sudoku-square/10226971#10226971 + * + * Solutions were given there using mathematica and opencv. + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "string.h" +#include "allheaders.h" + +l_int32 main(int argc, + char **argv) +{ +l_int32 w, h, select, ndew; +BOXA *boxa1; +L_DEWARP *dew; +L_DEWARPA *dewa; +PIX *pixs, *pixd, *pix1, *pix2, *pix3, *pix4, *pix5, *pix6, *pix7; +PIX *pix8, *pix9, *pix10; +PIXA *pixa1, *pixa2; + + if (argc != 3) { + lept_stderr(" Syntax: dewarprules select ndew\n"); + return 1; + } + select = atoi(argv[1]); + ndew = atoi(argv[2]); + + setLeptDebugOK(1); + lept_mkdir("dewarp"); + + if (select == 0) { + /* Extract the basic grid from the sudoku image */ + pixs = pixRead("warped_sudoku.jpg"); + pixGetDimensions(pixs, &w, &h, NULL); + pix1 = pixConvertTo1(pixs, 220); + boxa1 = pixConnComp(pix1, &pixa1, 8); + pixa2 = pixaSelectBySize(pixa1, 400, 400, L_SELECT_IF_BOTH, + L_SELECT_IF_GT, NULL); + pix2 = pixaDisplay(pixa2, w, h); /* grid */ + pixDisplay(pix1, 600, 300); + pixDisplay(pix2, 100, 100); + } else { /* select == 1 */ + /* Extract the grid from the graph paper image */ + pixs = pixRead("warped_paper.jpg"); + pixDisplay(pixs, 1500, 1000); + pix3 = pixConvertTo8(pixs, 0); + pix4 = pixBackgroundNormSimple(pix3, NULL, NULL); + pix5 = pixGammaTRC(NULL, pix4, 1.0, 50, 200); + pix1 = pixConvertTo1(pix5, 220); + pixGetDimensions(pix1, &w, &h, NULL); + boxa1 = pixConnComp(pix1, &pixa1, 8); + pixa2 = pixaSelectBySize(pixa1, 400, 400, L_SELECT_IF_BOTH, + L_SELECT_IF_GT, NULL); + pix2 = pixaDisplay(pixa2, w, h); /* grid */ + pixDisplay(pix1, 600, 300); + pixDisplay(pix2, 600, 400); + pixDestroy(&pix3); + pixDestroy(&pix4); + pixDestroy(&pix5); + } + + if (ndew == 1) { + /* -------------------------------------------------------------------* + * Use dewarpBuildLineModel() to correct using both horizontal + * and vertical lines with one dew. + * -------------------------------------------------------------------*/ + dewa = dewarpaCreate(1, 30, 1, 4, 50); + dewarpaSetCurvatures(dewa, 500, 0, 500, 100, 100, 200); + dewarpaUseBothArrays(dewa, 1); + dew = dewarpCreate(pix2, 0); + dewarpaInsertDewarp(dewa, dew); + dewarpBuildLineModel(dew, 10, "/tmp/dewarp/sud.pdf"); + dewarpaApplyDisparity(dewa, 0, pix1, 255, 0, 0, &pix3, NULL); + dewarpaApplyDisparity(dewa, 0, pix2, 255, 0, 0, &pix4, NULL); + pixDisplay(pix3, 500, 100); + pixDisplay(pix4, 600, 100); + pixDestroy(&pix3); + pixDestroy(&pix4); + dewarpaDestroy(&dewa); + } else { + /* -------------------------------------------------------------------* + * Hack: use dewarpBuildPageModel() twice, first straightening + * the horizontal lines, then rotating the result by 90 degrees + * and doing it again, and finally rotating back by -90 degrees. + * -------------------------------------------------------------------*/ + /* Extract the horizontal lines */ + pix3 = pixMorphSequence(pix2, "d1.3 + c6.1 + o8.1", 0); + pixDisplay(pix3, 600, 100); + + /* Correct for vertical disparity */ + dewa = dewarpaCreate(1, 30, 1, 4, 50); + dewarpaSetCurvatures(dewa, 500, 0, 500, 100, 100, 200); + dewarpaUseBothArrays(dewa, 0); + dew = dewarpCreate(pix3, 0); + dewarpaInsertDewarp(dewa, dew); + dewarpBuildPageModel(dew, "/tmp/dewarp/sud1.pdf"); + dewarpaApplyDisparity(dewa, 0, pix1, 255, 0, 0, &pix4, NULL); + dewarpaApplyDisparity(dewa, 0, pix2, 255, 0, 0, &pix5, NULL); + pixDisplay(pix4, 500, 100); + pixDisplay(pix5, 600, 100); + dewarpaDestroy(&dewa); + + /* Rotate result 90 degrees */ + pix6 = pixRotateOrth(pix4, 1); + pix7 = pixRotateOrth(pix5, 1); /* grid: vertical lines now are horiz */ + + /* Extract the vertical lines (which are now horizontal) */ + pix8 = pixMorphSequence(pix7, "d1.3 + c6.1 + o8.1", 0); + pixDisplay(pix8, 600, 500); + + /* Correct for vertical (now horizontal) disparity */ + dewa = dewarpaCreate(1, 30, 1, 4, 50); + dewarpaSetCurvatures(dewa, 500, 0, 500, 100, 100, 200); + dewarpaUseBothArrays(dewa, 0); + dew = dewarpCreate(pix8, 0); + dewarpaInsertDewarp(dewa, dew); + dewarpBuildPageModel(dew, "/tmp/dewarp/sud2.pdf"); + dewarpaApplyDisparity(dewa, 0, pix6, 255, 0, 0, &pix9, NULL); + dewarpaApplyDisparity(dewa, 0, pix8, 255, 0, 0, &pix10, NULL); + pixd = pixRotateOrth(pix9, 3); + pixDisplay(pix10, 600, 300); + pixDisplay(pixd, 600, 700); + } + + pixDestroy(&pixs); + pixDestroy(&pix1); + pixDestroy(&pix2); + boxaDestroy(&boxa1); + pixaDestroy(&pixa1); + pixaDestroy(&pixa2); + return 0; +} diff --git a/leptonica/prog/dewarptest1.c b/leptonica/prog/dewarptest1.c new file mode 100644 index 00000000..333f6b4f --- /dev/null +++ b/leptonica/prog/dewarptest1.c @@ -0,0 +1,182 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * dewarptest1.c + * + * This exercise functions in dewarp.c for dewarping based on lines + * of horizontal text. It also creates a 24-image pdf of steps + * in the process. + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + +#define DO_QUAD 1 +#define DO_CUBIC 0 +#define DO_QUARTIC 0 + + /* Default LSF is quadratic on left and right edges. + * Set to 1 for linear LSF. */ +#define LINEAR_FIT_ON_EDGES 0 + +l_int32 main(int argc, + char **argv) +{ +L_DEWARP *dew1, *dew2; +L_DEWARPA *dewa; +PIX *pixs, *pixn, *pixg, *pixb, *pixd, *pixt1, *pixt2; +PIX *pixs2, *pixn2, *pixg2, *pixb2, *pixd2; + + setLeptDebugOK(1); + lept_mkdir("lept/model"); + lept_rmdir("lept/dewmod"); + lept_mkdir("lept/dewmod"); + +/* pixs = pixRead("1555.007.jpg"); */ + pixs = pixRead("cat.035.jpg"); +/* pixs = pixRead("cat.010.jpg"); */ + + /* Normalize for varying background and binarize */ + pixn = pixBackgroundNormSimple(pixs, NULL, NULL); + pixg = pixConvertRGBToGray(pixn, 0.5, 0.3, 0.2); + pixb = pixThresholdToBinary(pixg, 130); + + /* Run the basic functions */ + dewa = dewarpaCreate(2, 30, 1, 10, 30); + if (LINEAR_FIT_ON_EDGES) + dewarpaSetCurvatures(dewa, -1, -1, -1, 0, -1, -1); + dewarpaUseBothArrays(dewa, 1); + dew1 = dewarpCreate(pixb, 35); + dewarpaInsertDewarp(dewa, dew1); + dewarpBuildPageModel(dew1, "/tmp/lept/model/dewarp_model1.pdf"); + dewarpaApplyDisparity(dewa, 35, pixg, 200, 0, 0, &pixd, + "/tmp/lept/model/dewarp_apply1.pdf"); + + /* Write out some of the files to be imaged */ + lept_rmdir("lept/dewtest"); + lept_mkdir("lept/dewtest"); + pixWrite("/tmp/lept/dewtest/001.jpg", pixs, IFF_JFIF_JPEG); + pixWrite("/tmp/lept/dewtest/002.jpg", pixn, IFF_JFIF_JPEG); + pixWrite("/tmp/lept/dewtest/003.jpg", pixg, IFF_JFIF_JPEG); + pixWrite("/tmp/lept/dewtest/004.png", pixb, IFF_TIFF_G4); + pixWrite("/tmp/lept/dewtest/005.jpg", pixd, IFF_JFIF_JPEG); + pixt1 = pixRead("/tmp/lept/dewmod/0020.png"); + pixWrite("/tmp/lept/dewtest/006.png", pixt1, IFF_PNG); + pixDestroy(&pixt1); + pixt1 = pixRead("/tmp/lept/dewmod/0030.png"); + pixWrite("/tmp/lept/dewtest/007.png", pixt1, IFF_PNG); + pixDestroy(&pixt1); + pixt1 = pixRead("/tmp/lept/dewmod/0060.png"); + pixWrite("/tmp/lept/dewtest/008.png", pixt1, IFF_PNG); + pixDestroy(&pixt1); + pixt1 = pixRead("/tmp/lept/dewmod/0070.png"); + pixWrite("/tmp/lept/dewtest/009.png", pixt1, IFF_PNG); + pixDestroy(&pixt1); + pixt1 = pixRead("/tmp/lept/dewapply/002.png"); + pixWrite("/tmp/lept/dewtest/010.png", pixt1, IFF_PNG); + pixDestroy(&pixt1); + pixt1 = pixRead("/tmp/lept/dewapply/003.png"); + pixWrite("/tmp/lept/dewtest/011.png", pixt1, IFF_PNG); + pixt2 = pixThresholdToBinary(pixt1, 130); + pixWrite("/tmp/lept/dewtest/012.png", pixt2, IFF_TIFF_G4); + pixDestroy(&pixt1); + pixDestroy(&pixt2); + pixt1 = pixRead("/tmp/lept/dewmod/0041.png"); + pixWrite("/tmp/lept/dewtest/013.png", pixt1, IFF_PNG); + pixDestroy(&pixt1); + pixt1 = pixRead("/tmp/lept/dewmod/0042.png"); + pixWrite("/tmp/lept/dewtest/014.png", pixt1, IFF_PNG); + pixDestroy(&pixt1); + pixt1 = pixRead("/tmp/lept/dewmod/0051.png"); + pixWrite("/tmp/lept/dewtest/015.png", pixt1, IFF_PNG); + pixDestroy(&pixt1); + pixt1 = pixRead("/tmp/lept/dewmod/0052.png"); + pixWrite("/tmp/lept/dewtest/016.png", pixt1, IFF_PNG); + pixDestroy(&pixt1); + + /* Normalize another image, that may not have enough textlines + * to build an accurate model */ +/* pixs2 = pixRead("1555.003.jpg"); */ + pixs2 = pixRead("cat.007.jpg"); +/* pixs2 = pixRead("cat.014.jpg"); */ + pixn2 = pixBackgroundNormSimple(pixs2, NULL, NULL); + pixg2 = pixConvertRGBToGray(pixn2, 0.5, 0.3, 0.2); + pixb2 = pixThresholdToBinary(pixg2, 130); + + /* Apply the previous disparity model to this image */ + dew2 = dewarpCreate(pixb2, 7); + dewarpaInsertDewarp(dewa, dew2); + dewarpaInsertRefModels(dewa, 0, 1); + dewarpaInfo(stderr, dewa); + dewarpaApplyDisparity(dewa, 7, pixg2, 200, 0, 0, &pixd2, + "/tmp/lept/model/dewarp_apply2.pdf"); + dewarpaDestroy(&dewa); + + /* Write out files for the second image */ + pixWrite("/tmp/lept/dewtest/017.jpg", pixs2, IFF_JFIF_JPEG); + pixWrite("/tmp/lept/dewtest/018.jpg", pixg2, IFF_JFIF_JPEG); + pixWrite("/tmp/lept/dewtest/019.png", pixb2, IFF_TIFF_G4); + pixWrite("/tmp/lept/dewtest/020.jpg", pixd2, IFF_JFIF_JPEG); + pixt1 = pixRead("/tmp/lept/dewmod/0060.png"); + pixWrite("/tmp/lept/dewtest/021.png", pixt1, IFF_PNG); + pixDestroy(&pixt1); + pixt1 = pixRead("/tmp/lept/dewapply/002.png"); + pixWrite("/tmp/lept/dewtest/022.png", pixt1, IFF_PNG); + pixt2 = pixThresholdToBinary(pixt1, 130); + pixWrite("/tmp/lept/dewtest/023.png", pixt2, IFF_TIFF_G4); + pixDestroy(&pixt1); + pixDestroy(&pixt2); + pixt1 = pixRead("/tmp/lept/dewmod/0070.png"); + pixWrite("/tmp/lept/dewtest/024.png", pixt1, IFF_PNG); + pixDestroy(&pixt1); + pixt1 = pixRead("/tmp/lept/dewapply/003.png"); + pixWrite("/tmp/lept/dewtest/025.png", pixt1, IFF_PNG); + pixt2 = pixThresholdToBinary(pixt1, 130); + pixWrite("/tmp/lept/dewtest/026.png", pixt2, IFF_TIFF_G4); + pixDestroy(&pixt1); + pixDestroy(&pixt2); + + /* Generate the big pdf file */ + convertFilesToPdf("/tmp/lept/dewtest", NULL, 135, 1.0, 0, 0, "Dewarp Test", + "/tmp/lept/dewarptest1.pdf"); + lept_stderr("pdf file made: /tmp/lept/model/dewarptest1.pdf\n"); + + pixDestroy(&pixs); + pixDestroy(&pixn); + pixDestroy(&pixg); + pixDestroy(&pixb); + pixDestroy(&pixd); + pixDestroy(&pixs2); + pixDestroy(&pixn2); + pixDestroy(&pixg2); + pixDestroy(&pixb2); + pixDestroy(&pixd2); + return 0; +} diff --git a/leptonica/prog/dewarptest2.c b/leptonica/prog/dewarptest2.c new file mode 100644 index 00000000..8042ada5 --- /dev/null +++ b/leptonica/prog/dewarptest2.c @@ -0,0 +1,123 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * dewarptest2.c + * + * This runs the basic functions for a single page. It can be used + * to debug the disparity model-building. + * + * dewarptest2 method [image pageno] + * + * where: method = 1 (use single page dewarp function) + * 2 (break down into multiple steps) + * + * Default image is cat.035.jpg. + * Others are 1555.007.jpg, shearer.148.tif, lapide.052.100.jpg, etc. + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + +#define NORMALIZE 1 + +l_int32 main(int argc, + char **argv) +{ +l_int32 d, method, pageno; +L_DEWARP *dew1; +L_DEWARPA *dewa; +PIX *pixs, *pixn, *pixg, *pixb, *pixd; +static char mainName[] = "dewarptest2"; + + if (argc != 2 && argc != 4) + return ERROR_INT("Syntax: dewarptest2 method [image pageno]", + mainName, 1); + if (argc == 2) { + pixs = pixRead("cat.035.jpg"); + pageno = 35; + } + else { + pixs = pixRead(argv[2]); + pageno = atoi(argv[3]); + } + if (!pixs) + return ERROR_INT("image not read", mainName, 1); + method = atoi(argv[1]); + + setLeptDebugOK(1); + lept_mkdir("lept/dewarp"); + + if (method == 1) { /* Use single page dewarp function */ + dewarpSinglePage(pixs, 0, 1, 1, 0, &pixd, NULL, 1); + } else { /* Break down into multiple steps; require min of only 8 lines */ + dewa = dewarpaCreate(40, 30, 1, 8, 50); + dewarpaUseBothArrays(dewa, 1); + dewarpaSetCheckColumns(dewa, 0); + d = pixGetDepth(pixs); + +#if NORMALIZE + /* Normalize for varying background and binarize */ + if (d > 1) { + pixn = pixBackgroundNormSimple(pixs, NULL, NULL); + pixg = pixConvertRGBToGray(pixn, 0.5, 0.3, 0.2); + pixb = pixThresholdToBinary(pixg, 130); + pixDestroy(&pixn); + pixDestroy(&pixg); + } else { + pixb = pixClone(pixs); + } +#else + /* Don't normalize; just threshold and clean edges */ + if (d > 1) { + pixg = pixConvertTo8(pixs, 0); + pixb = pixThresholdToBinary(pixg, 100); + pixDestroy(&pixg); + } else { + pixb = pixClone(pixs); + } + pixSetOrClearBorder(pixb, 30, 30, 40, 40, PIX_CLR); +#endif + + /* Run the basic functions */ + dew1 = dewarpCreate(pixb, pageno); + dewarpaInsertDewarp(dewa, dew1); + dewarpBuildPageModel(dew1, "/tmp/lept/dewarp/test2_model.pdf"); + dewarpaApplyDisparity(dewa, pageno, pixb, -1, 0, 0, &pixd, + "/tmp/lept/dewarp/test2_apply.pdf"); + + dewarpaInfo(stderr, dewa); + dewarpaDestroy(&dewa); + pixDestroy(&pixb); + } + + pixDestroy(&pixs); + pixDestroy(&pixd); + return 0; +} diff --git a/leptonica/prog/dewarptest3.c b/leptonica/prog/dewarptest3.c new file mode 100644 index 00000000..c6095660 --- /dev/null +++ b/leptonica/prog/dewarptest3.c @@ -0,0 +1,167 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * dewarptest3.c + * + * This exercise functions in dewarp.c for dewarping based on lines + * of horizontal text, showing results for different interpolations + * (quadratic, cubic, quartic). + * + * Inspection of the output pdf shows that using LS fitting beyond + * quadratic has a tendency to overfit. So we choose to use + * quadratic LSF for the textlines. + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + +l_int32 main(int argc, + char **argv) +{ +l_int32 i, n; +l_float32 a, b, c, d, e; +NUMA *nax, *nafit; +PIX *pixs, *pixn, *pixg, *pixb, *pixt1, *pixt2; +PIXA *pixa; +PTA *pta, *ptad; +PTAA *ptaa1, *ptaa2; + + setLeptDebugOK(1); + lept_mkdir("lept"); + + pixs = pixRead("cat.035.jpg"); +/* pixs = pixRead("zanotti-78.jpg"); */ + + /* Normalize for varying background and binarize */ + pixn = pixBackgroundNormSimple(pixs, NULL, NULL); + pixg = pixConvertRGBToGray(pixn, 0.5, 0.3, 0.2); + pixb = pixThresholdToBinary(pixg, 130); + pixDestroy(&pixn); + pixDestroy(&pixg); + + /* Get the textline centers */ + pixa = pixaCreate(6); + ptaa1 = dewarpGetTextlineCenters(pixb, 0); + pixt1 = pixCreateTemplate(pixs); + pixSetAll(pixt1); + pixt2 = pixDisplayPtaa(pixt1, ptaa1); + pixWrite("/tmp/lept/textline1.png", pixt2, IFF_PNG); + pixDisplayWithTitle(pixt2, 0, 100, "textline centers 1", 1); + pixaAddPix(pixa, pixt2, L_INSERT); + pixDestroy(&pixt1); + + /* Remove short lines */ + lept_stderr("Num all lines = %d\n", ptaaGetCount(ptaa1)); + ptaa2 = dewarpRemoveShortLines(pixb, ptaa1, 0.8, 0); + pixt1 = pixCreateTemplate(pixs); + pixSetAll(pixt1); + pixt2 = pixDisplayPtaa(pixt1, ptaa2); + pixWrite("/tmp/lept/textline2.png", pixt2, IFF_PNG); + pixDisplayWithTitle(pixt2, 300, 100, "textline centers 2", 1); + pixaAddPix(pixa, pixt2, L_INSERT); + pixDestroy(&pixt1); + n = ptaaGetCount(ptaa2); + lept_stderr("Num long lines = %d\n", n); + ptaaDestroy(&ptaa1); + pixDestroy(&pixb); + + /* Long lines over input image */ + pixt1 = pixCopy(NULL, pixs); + pixt2 = pixDisplayPtaa(pixt1, ptaa2); + pixWrite("/tmp/lept/textline3.png", pixt2, IFF_PNG); + pixDisplayWithTitle(pixt2, 600, 100, "textline centers 3", 1); + pixaAddPix(pixa, pixt2, L_INSERT); + pixDestroy(&pixt1); + + /* Quadratic fit to curve */ + pixt1 = pixCopy(NULL, pixs); + for (i = 0; i < n; i++) { + pta = ptaaGetPta(ptaa2, i, L_CLONE); + ptaGetArrays(pta, &nax, NULL); + ptaGetQuadraticLSF(pta, &a, &b, &c, &nafit); + lept_stderr("Quadratic: a = %10.6f, b = %7.3f, c = %7.3f\n", a, b, c); + ptad = ptaCreateFromNuma(nax, nafit); + pixDisplayPta(pixt1, pixt1, ptad); + ptaDestroy(&pta); + ptaDestroy(&ptad); + numaDestroy(&nax); + numaDestroy(&nafit); + } + pixWrite("/tmp/lept/textline4.png", pixt1, IFF_PNG); + pixDisplayWithTitle(pixt1, 900, 100, "textline centers 4", 1); + pixaAddPix(pixa, pixt1, L_INSERT); + + /* Cubic fit to curve */ + pixt1 = pixCopy(NULL, pixs); + for (i = 0; i < n; i++) { + pta = ptaaGetPta(ptaa2, i, L_CLONE); + ptaGetArrays(pta, &nax, NULL); + ptaGetCubicLSF(pta, &a, &b, &c, &d, &nafit); + lept_stderr("Cubic: a = %10.6f, b = %10.6f, c = %7.3f, d = %7.3f\n", + a, b, c, d); + ptad = ptaCreateFromNuma(nax, nafit); + pixDisplayPta(pixt1, pixt1, ptad); + ptaDestroy(&pta); + ptaDestroy(&ptad); + numaDestroy(&nax); + numaDestroy(&nafit); + } + pixWrite("/tmp/lept/textline5.png", pixt1, IFF_PNG); + pixDisplayWithTitle(pixt1, 1200, 100, "textline centers 5", 1); + pixaAddPix(pixa, pixt1, L_INSERT); + + /* Quartic fit to curve */ + pixt1 = pixCopy(NULL, pixs); + for (i = 0; i < n; i++) { + pta = ptaaGetPta(ptaa2, i, L_CLONE); + ptaGetArrays(pta, &nax, NULL); + ptaGetQuarticLSF(pta, &a, &b, &c, &d, &e, &nafit); + lept_stderr( + "Quartic: a = %7.3f, b = %7.3f, c = %9.5f, d = %7.3f, e = %7.3f\n", + a, b, c, d, e); + ptad = ptaCreateFromNuma(nax, nafit); + pixDisplayPta(pixt1, pixt1, ptad); + ptaDestroy(&pta); + ptaDestroy(&ptad); + numaDestroy(&nax); + numaDestroy(&nafit); + } + pixWrite("/tmp/lept/textline6.png", pixt1, IFF_PNG); + pixDisplayWithTitle(pixt1, 1500, 100, "textline centers 6", 1); + pixaAddPix(pixa, pixt1, L_INSERT); + + pixaConvertToPdf(pixa, 300, 0.5, L_JPEG_ENCODE, 75, + "LS fittings to textlines", + "/tmp/lept/dewarp_fittings.pdf"); + pixaDestroy(&pixa); + pixDestroy(&pixs); + ptaaDestroy(&ptaa2); + return 0; +} diff --git a/leptonica/prog/dewarptest4.c b/leptonica/prog/dewarptest4.c new file mode 100644 index 00000000..8e8f4c0a --- /dev/null +++ b/leptonica/prog/dewarptest4.c @@ -0,0 +1,123 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * dewarptest4.c + * + * Tests serialization functions for dewarpa and dewarp structs. + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + + +l_int32 main(int argc, + char **argv) +{ +L_DEWARP *dew1, *dew2, *dew3; +L_DEWARPA *dewa1, *dewa2, *dewa3; +PIX *pixs, *pixn, *pixg, *pixb, *pixd; +PIX *pixs2, *pixn2, *pixg2, *pixb2, *pixd2; +PIX *pixd3, *pixc1, *pixc2; + + setLeptDebugOK(1); + lept_mkdir("lept"); + +/* pixs = pixRead("1555.007.jpg"); */ + pixs = pixRead("cat.035.jpg"); + dewa1 = dewarpaCreate(40, 30, 1, 15, 10); + dewarpaUseBothArrays(dewa1, 1); + + /* Normalize for varying background and binarize */ + pixn = pixBackgroundNormSimple(pixs, NULL, NULL); + pixg = pixConvertRGBToGray(pixn, 0.5, 0.3, 0.2); + pixb = pixThresholdToBinary(pixg, 130); + + /* Run the basic functions */ + dew1 = dewarpCreate(pixb, 35); + dewarpaInsertDewarp(dewa1, dew1); + dewarpBuildPageModel(dew1, "/tmp/lept/dewarp_junk35.pdf"); + dewarpPopulateFullRes(dew1, pixg, 0, 0); + dewarpaApplyDisparity(dewa1, 35, pixg, 200, 0, 0, &pixd, + "/tmp/lept/dewarp_debug_35.pdf"); + + /* Normalize another image. */ +/* pixs2 = pixRead("1555.003.jpg"); */ + pixs2 = pixRead("cat.007.jpg"); + pixn2 = pixBackgroundNormSimple(pixs2, NULL, NULL); + pixg2 = pixConvertRGBToGray(pixn2, 0.5, 0.3, 0.2); + pixb2 = pixThresholdToBinary(pixg2, 130); + + /* Run the basic functions */ + dew2 = dewarpCreate(pixb2, 7); + dewarpaInsertDewarp(dewa1, dew2); + dewarpBuildPageModel(dew2, "/tmp/lept/dewarp_junk7.pdf"); + dewarpaApplyDisparity(dewa1, 7, pixg, 200, 0, 0, &pixd2, + "/tmp/lept/dewarp_debug_7.pdf"); + + /* Serialize and deserialize dewarpa */ + dewarpaWrite("/tmp/lept/dewarpa1.dewa", dewa1); + dewa2 = dewarpaRead("/tmp/lept/dewarpa1.dewa"); + dewarpaWrite("/tmp/lept/dewarpa2.dewa", dewa2); + dewa3 = dewarpaRead("/tmp/lept/dewarpa2.dewa"); + dewarpDebug(dewa3->dewarp[7], "dew1", 7); + dewarpaWrite("/tmp/lept/dewarpa3.dewa", dewa3); + + /* Repopulate and show the vertical disparity arrays */ + dewarpPopulateFullRes(dew1, NULL, 0, 0); + pixc1 = fpixRenderContours(dew1->fullvdispar, 2.0, 0.2); + pixDisplay(pixc1, 1400, 900); + dew3 = dewarpaGetDewarp(dewa2, 35); + dewarpPopulateFullRes(dew3, pixs, 0, 0); + pixc2 = fpixRenderContours(dew3->fullvdispar, 2.0, 0.2); + pixDisplay(pixc2, 1400, 900); + dewarpaApplyDisparity(dewa2, 35, pixb, 200, 0, 0, &pixd3, + "/tmp/lept/dewarp_debug_35b.pdf"); + pixDisplay(pixd, 0, 1000); + pixDisplay(pixd2, 600, 1000); + pixDisplay(pixd3, 1200, 1000); + pixDestroy(&pixd3); + + dewarpaDestroy(&dewa1); + dewarpaDestroy(&dewa2); + dewarpaDestroy(&dewa3); + pixDestroy(&pixs); + pixDestroy(&pixn); + pixDestroy(&pixg); + pixDestroy(&pixb); + pixDestroy(&pixd); + pixDestroy(&pixs2); + pixDestroy(&pixn2); + pixDestroy(&pixg2); + pixDestroy(&pixb2); + pixDestroy(&pixd2); + pixDestroy(&pixc1); + pixDestroy(&pixc2); + return 0; +} diff --git a/leptonica/prog/dewarptest5.c b/leptonica/prog/dewarptest5.c new file mode 100644 index 00000000..ec88a7b8 --- /dev/null +++ b/leptonica/prog/dewarptest5.c @@ -0,0 +1,140 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * dewarptest5.c + * + * Tests dewarping model applied to word bounding boxes. + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + +static l_int32 pageno = 35; +static l_int32 build_output = 0; +static l_int32 apply_output = 0; +static l_int32 map_output = 1; + +l_int32 main(int argc, + char **argv) +{ +char buf[64]; +BOXA *boxa1, *boxa2, *boxa3, *boxa4; +L_DEWARP *dew; +L_DEWARPA *dewa; +PIX *pixs, *pixn, *pixg, *pixb, *pix2, *pix3, *pix4, *pix5, *pix6; + + setLeptDebugOK(1); + lept_mkdir("lept"); + + snprintf(buf, sizeof(buf), "cat.%03d.jpg", pageno); + pixs = pixRead(buf); + dewa = dewarpaCreate(40, 30, 1, 15, 10); + dewarpaUseBothArrays(dewa, 1); + + /* Normalize for varying background and binarize */ + pixn = pixBackgroundNormSimple(pixs, NULL, NULL); + pixg = pixConvertRGBToGray(pixn, 0.5, 0.3, 0.2); + pixb = pixThresholdToBinary(pixg, 130); + pixDisplay(pixb, 0, 100); + + /* Build the model */ + dew = dewarpCreate(pixb, pageno); + dewarpaInsertDewarp(dewa, dew); + if (build_output) { + snprintf(buf, sizeof(buf), "/tmp/lept/dewarp_build_%d.pdf", pageno); + dewarpBuildPageModel(dew, buf); + } else { + dewarpBuildPageModel(dew, NULL); + } + + /* Apply the model */ + dewarpPopulateFullRes(dew, pixg, 0, 0); + if (apply_output) { + snprintf(buf, sizeof(buf), "/tmp/lept/dewarp_apply_%d.pdf", pageno); + dewarpaApplyDisparity(dewa, pageno, pixb, 200, 0, 0, &pix2, buf); + } else { + dewarpaApplyDisparity(dewa, pageno, pixb, 200, 0, 0, &pix2, NULL); + } + pixDisplay(pix2, 200, 100); + + /* Reverse direction: get the word boxes for the dewarped pix ... */ + pixGetWordBoxesInTextlines(pix2, 5, 5, 500, 100, &boxa1, NULL); + pix3 = pixConvertTo32(pix2); + pixRenderBoxaArb(pix3, boxa1, 2, 255, 0, 0); + pixDisplay(pix3, 400, 100); + + /* ... and map to the word boxes for the input image */ + if (map_output) { + snprintf(buf, sizeof(buf), "/tmp/lept/dewarp_map1_%d.pdf", pageno); + dewarpaApplyDisparityBoxa(dewa, pageno, pix2, boxa1, 0, 0, 0, &boxa2, + buf); + } else { + dewarpaApplyDisparityBoxa(dewa, pageno, pix2, boxa1, 0, 0, 0, &boxa2, + NULL); + } + pix4 = pixConvertTo32(pixb); + pixRenderBoxaArb(pix4, boxa2, 2, 0, 255, 0); + pixDisplay(pix4, 600, 100); + + /* Forward direction: get the word boxes for the input pix ... */ + pixGetWordBoxesInTextlines(pixb, 5, 5, 500, 100, &boxa3, NULL); + pix5 = pixConvertTo32(pixb); + pixRenderBoxaArb(pix5, boxa3, 2, 255, 0, 0); + pixDisplay(pix5, 800, 100); + + /* ... and map to the word boxes for the dewarped image */ + if (map_output) { + snprintf(buf, sizeof(buf), "/tmp/lept/dewarp_map2_%d.pdf", pageno); + dewarpaApplyDisparityBoxa(dewa, pageno, pixb, boxa3, 1, 0, 0, &boxa4, + buf); + } else { + dewarpaApplyDisparityBoxa(dewa, pageno, pixb, boxa3, 1, 0, 0, &boxa4, + NULL); + } + pix6 = pixConvertTo32(pix2); + pixRenderBoxaArb(pix6, boxa4, 2, 0, 255, 0); + pixDisplay(pix6, 1000, 100); + + dewarpaDestroy(&dewa); + pixDestroy(&pixs); + pixDestroy(&pixn); + pixDestroy(&pixg); + pixDestroy(&pixb); + pixDestroy(&pix2); + pixDestroy(&pix3); + pixDestroy(&pix4); + pixDestroy(&pix5); + pixDestroy(&pix6); + boxaDestroy(&boxa1); + boxaDestroy(&boxa2); + boxaDestroy(&boxa3); + boxaDestroy(&boxa4); + return 0; +} diff --git a/leptonica/prog/digitprep1.c b/leptonica/prog/digitprep1.c new file mode 100644 index 00000000..835d8015 --- /dev/null +++ b/leptonica/prog/digitprep1.c @@ -0,0 +1,106 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * digitprep1.c + * + * Extract barcode digits and put in a pixaa (a resource file for + * readnum.c). + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + +static const l_int32 HEIGHT = 32; /* pixels */ + +int main(int argc, + char **argv) +{ +char buf[16]; +l_int32 i, n, h; +l_float32 scalefact; +BOXA *boxa; +PIX *pixs, *pix1, *pix2; +PIXA *pixa, *pixas, *pixad; +PIXAA *paa; +static char mainName[] = "digitprep1"; + + if (argc != 1) { + ERROR_INT(" Syntax: digitprep1", mainName, 1); + return 1; + } + + setLeptDebugOK(1); + if ((pixs = pixRead("barcode-digits.png")) == NULL) + return ERROR_INT("pixs not read", mainName, 1); + + /* Extract the digits and scale to HEIGHT */ + boxa = pixConnComp(pixs, &pixa, 8); + pixas = pixaSort(pixa, L_SORT_BY_X, L_SORT_INCREASING, NULL, L_CLONE); + n = pixaGetCount(pixas); + + /* Move the last ("0") to the first position */ + pix1 = pixaGetPix(pixas, n - 1, L_CLONE); + pixaInsertPix(pixas, 0, pix1, NULL); + pixaRemovePix(pixas, n); + + /* Make the output scaled pixa */ + pixad = pixaCreate(n); + for (i = 0; i < n; i++) { + pix1 = pixaGetPix(pixas, i, L_CLONE); + pixGetDimensions(pix1, NULL, &h, NULL); + scalefact = HEIGHT / (l_float32)h; + pix2 = pixScale(pix1, scalefact, scalefact); + if (pixGetHeight(pix2) != 32) + return ERROR_INT("height not 32!", mainName, 1); + snprintf(buf, sizeof(buf), "%d", i); + pixSetText(pix2, buf); + pixaAddPix(pixad, pix2, L_INSERT); + pixDestroy(&pix1); + } + + /* Save in a pixaa, with 1 pix in each pixa */ + paa = pixaaCreateFromPixa(pixad, 1, L_CHOOSE_CONSECUTIVE, L_CLONE); + pixaaWrite("/tmp/lept/barcode_digits.paa", paa); + + /* Show result */ + pix1 = pixaaDisplayByPixa(paa, 50, 1.0, 20, 20, 0); + pixDisplay(pix1, 100, 100); + pixDestroy(&pix1); + + pixDestroy(&pixs); + boxaDestroy(&boxa); + pixaDestroy(&pixa); + pixaDestroy(&pixas); + pixaDestroy(&pixad); + pixaaDestroy(&paa); + return 0; +} + + diff --git a/leptonica/prog/dinos.pac b/leptonica/prog/dinos.pac Binary files differnew file mode 100644 index 00000000..42ba57d0 --- /dev/null +++ b/leptonica/prog/dinos.pac diff --git a/leptonica/prog/displayboxa.c b/leptonica/prog/displayboxa.c new file mode 100644 index 00000000..9d096486 --- /dev/null +++ b/leptonica/prog/displayboxa.c @@ -0,0 +1,91 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * displayboxa.c + * + * displayboxa filein first last width fileout + * + * This reads a boxa from file and generates a composite view of the + * boxes, one per "page", tiled in rows. + * Set last == -1 to go to the end. + * The pix that backs each box is chosen to be the minimum size that + * supports every box in the boxa. Each pix (and the box it backs) + * is scaled so that the pix width is @width in pixels. + * The number of each box is written below the box. + * + * The minimum allowed width of the backing pix is 30, and the default + * width is 100. + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + +int main(int argc, + char **argv) +{ +char *filein, *fileout; +l_int32 w, h, width, sep, first, last; +l_float32 scalefact; +BOXA *boxa1, *boxa2; +PIX *pixd; +static char mainName[] = "displayboxa"; + + if (argc != 6) { + lept_stderr("Syntax error in displayboxa:\n" + " displayboxa filein first last width fileout\n"); + return 1; + } + filein = argv[1]; + first = atoi(argv[2]); + last = atoi(argv[3]); + width = atoi(argv[4]); + fileout = argv[5]; + if (width < 30) { + L_ERROR("width too small; setting to 100\n", mainName); + width = 100; + } + setLeptDebugOK(1); + + if ((boxa1 = boxaRead(filein)) == NULL) + return ERROR_INT("boxa not made", mainName, 1); + boxaGetExtent(boxa1, &w, &h, NULL); + scalefact = (l_float32)width / (l_float32)w; + boxa2 = boxaTransform(boxa1, 0, 0, scalefact, scalefact); + sep = L_MIN(width / 5, 20); + pixd = boxaDisplayTiled(boxa2, NULL, first, last, 1500, 2, 1.0, 0, sep, 2); + pixWrite(fileout, pixd, IFF_PNG); + pixDisplay(pixd, 100, 100); + + boxaDestroy(&boxa1); + boxaDestroy(&boxa2); + pixDestroy(&pixd); + return 0; +} + diff --git a/leptonica/prog/displayboxes_on_pixa.c b/leptonica/prog/displayboxes_on_pixa.c new file mode 100644 index 00000000..db0055dd --- /dev/null +++ b/leptonica/prog/displayboxes_on_pixa.c @@ -0,0 +1,98 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * displayboxes_on_pixa.c + * + * displayboxes_on_pixa pixain boxaain type width pixaout display + * + * where 'type' follows the enum in pix.h: + * 0: draw red + * 1: draw green + * 2: draw blue + * 4: draw rgb (sequentially) + * 5: draw randomly selected colors + * and 'display' is a boolean: + * 0: no display on screen + * 1: display the resulting pixa on the screen, with the images + * tiled in rows + * + * This reads a pixa or a pixacomp from file and a boxaa file, draws + * the boxes on the appropriate images, and writes the new pixa out. + * No scaling is done. + * + * The boxa in the input boxaa should be in 1:1 correspondence with the + * pix in the input pixa. The number of boxes in each boxa is arbitrary. + * + * For example, you can call this with: + * displayboxes_on_pixa showboxes.pac showboxes2.baa 4 2 /tmp/result.pa 1 + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + +int main(int argc, + char **argv) +{ +char *fileout; +l_int32 width, type, display; +BOXAA *baa; +PIX *pix1; +PIXA *pixa1, *pixa2; + + if (argc != 7) { + lept_stderr("Syntax error:" + " displaybaa_on_pixa pixain boxaain type width pixaout display\n"); + return 1; + } + setLeptDebugOK(1); + + /* Input file can be either pixa or pixacomp */ + pixa1 = pixaReadBoth(argv[1]); + baa = boxaaRead(argv[2]); + type = atoi(argv[3]); + width = atoi(argv[4]); + fileout = argv[5]; + display = atoi(argv[6]); + + pixa2 = pixaDisplayBoxaa(pixa1, baa, type, width); + pixaWrite(fileout, pixa2); + + if (display) { + pix1 = pixaDisplayTiledInRows(pixa2, 32, 1400, 1.0, 0, 10, 0); + pixDisplay(pix1, 100, 100); + pixDestroy(&pix1); + } + + pixaDestroy(&pixa1); + pixaDestroy(&pixa2); + boxaaDestroy(&baa); + return 0; +} + diff --git a/leptonica/prog/displaypix.c b/leptonica/prog/displaypix.c new file mode 100644 index 00000000..40f8e417 --- /dev/null +++ b/leptonica/prog/displaypix.c @@ -0,0 +1,61 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * displaypix.c + * + * This calls pixDisplay(), which: + * (1) automatically downscales the image if necessary to display + * it without scrollbars, and + * (2) launches the selected viewer (default is xzgv) + * + * Downscaling uses area mapping to avoid moire. + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + +int main(int argc, + char **argv) +{ +PIX *pixs; +char *filein; +static char mainName[] = "displaypix"; + + if (argc != 2) + return ERROR_INT(" Syntax: displaypix filein", mainName, 1); + filein = argv[1]; + if ((pixs = pixRead(filein)) == NULL) + return ERROR_INT("pixs not made", mainName, 1); + + setLeptDebugOK(1); + pixDisplay(pixs, 20, 20); + pixDestroy(&pixs); + return 0; +} diff --git a/leptonica/prog/displaypixa.c b/leptonica/prog/displaypixa.c new file mode 100644 index 00000000..6638d751 --- /dev/null +++ b/leptonica/prog/displaypixa.c @@ -0,0 +1,176 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * displaypixa.c + * + * displaypixa filein fileout showtext + * displaypixa filein scalefact border lossless disp fileout showtext + * + * where: + * showtext = 1 to print text in the text field of each pix below + * the image; 0 to skip + * disp = 1 to display on the screen; 0 to skip + * lossless = 1 for tiff or png + * + * This reads a pixa or a pixacomp from file and generates a composite of the + * images tiled in rows. It also optionally displays on the screen. + * No scaling is done if @scalefact == 0.0 or @scalefact == 1.0. + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include <string.h> +#include "allheaders.h" + +int main(int argc, + char **argv) +{ +char buf[32]; +char *fileout, *textstr; +l_int32 n, i, same, maxd, ntext, border, lossless, display, showtext; +l_float32 scalefact; +L_BMF *bmf; +PIX *pix1, *pix2, *pix3, *pix4, *pixd; +PIXA *pixa, *pixad; +static char mainName[] = "displaypixa"; + + if (argc != 4 && argc != 8) { + lept_stderr("Syntax error in displaypixa:\n" + " displaypixa filein fileout showtext\n" + " displaypixa filein scalefact border" + " lossless disp fileout showtext\n"); + return 1; + } + setLeptDebugOK(1); + + /* Input file can be either pixa or pixacomp */ + pixa = pixaReadBoth(argv[1]); + pixaCountText(pixa, &ntext); + + if (argc == 4) { + fileout = argv[2]; + showtext = atoi(argv[3]); + } + + /* Simple specification; no output text */ + if (argc == 4 && (showtext == 0 || ntext == 0)) { /* no text output */ + pixaVerifyDepth(pixa, &same, &maxd); + pixd = pixaDisplayTiledInRows(pixa, maxd, 1400, 1.0, 0, 10, 0); + pixDisplay(pixd, 100, 100); + if (pixGetDepth(pixd) == 1) + pixWrite(fileout, pixd, IFF_PNG); + else + pixWrite(fileout, pixd, IFF_JFIF_JPEG); + pixDestroy(&pixd); + pixaDestroy(&pixa); + return 0; + } + + /* Simple specification with output text */ + if (argc == 4) { /* showtext == 1 && ntext > 0 */ + n = pixaGetCount(pixa); + bmf = bmfCreate(NULL, 10); + pixad = pixaCreate(n); + for (i = 0; i < n; i++) { + pix1 = pixaGetPix(pixa, i, L_CLONE); + pix2 = pixConvertTo32(pix1); + pix3 = pixAddBorderGeneral(pix2, 10, 10, 5, 5, 0xffffff00); + textstr = pixGetText(pix1); + if (textstr && strlen(textstr) > 0) { + snprintf(buf, sizeof(buf), "%s", textstr); + pix4 = pixAddSingleTextblock(pix3, bmf, buf, 0xff000000, + L_ADD_BELOW, NULL); + } else { + pix4 = pixClone(pix3); + } + pixaAddPix(pixad, pix4, L_INSERT); + pixDestroy(&pix1); + pixDestroy(&pix2); + pixDestroy(&pix3); + } + bmfDestroy(&bmf); + pixaVerifyDepth(pixad, &same, &maxd); + pixd = pixaDisplayTiledInRows(pixad, maxd, 1400, 1.0, 0, 10, 0); + pixDisplay(pixd, 100, 100); + if (pixGetDepth(pixd) == 1) + pixWrite(fileout, pixd, IFF_PNG); + else + pixWrite(fileout, pixd, IFF_JFIF_JPEG); + pixDestroy(&pixd); + pixaDestroy(&pixa); + pixaDestroy(&pixad); + return 0; + } + + /* Full specification */ + scalefact = atof(argv[2]); + border = atoi(argv[3]); + lossless = atoi(argv[4]); + display = atoi(argv[5]); + fileout = argv[6]; + showtext = atoi(argv[7]); + if (showtext && ntext == 0) + L_INFO("No text found in any of the pix\n", mainName); + bmf = (showtext && ntext > 0) ? bmfCreate(NULL, 10) : NULL; + n = pixaGetCount(pixa); + pixad = pixaCreate(n); + for (i = 0; i < n; i++) { + pix1 = pixaGetPix(pixa, i, L_CLONE); + pix2 = pixConvertTo32(pix1); + pix3 = pixAddBorderGeneral(pix2, 10, 10, 5, 5, 0xffffff00); + textstr = pixGetText(pix1); + if (bmf && textstr && strlen(textstr) > 0) { + snprintf(buf, sizeof(buf), "%s", textstr); + pix4 = pixAddSingleTextblock(pix3, bmf, buf, 0xff000000, + L_ADD_BELOW, NULL); + } else { + pix4 = pixClone(pix3); + } + pixaAddPix(pixad, pix4, L_INSERT); + pixDestroy(&pix1); + pixDestroy(&pix2); + pixDestroy(&pix3); + } + bmfDestroy(&bmf); + + pixaVerifyDepth(pixad, &same, &maxd); + pixd = pixaDisplayTiledInRows(pixad, maxd, 1400, scalefact, + 0, 10, border); + if (display) pixDisplay(pixd, 20, 20); + if (pixGetDepth(pixd) == 1 || lossless) + pixWrite(fileout, pixd, IFF_PNG); + else + pixWrite(fileout, pixd, IFF_JFIF_JPEG); + + pixDestroy(&pixd); + pixaDestroy(&pixa); + pixaDestroy(&pixad); + return 0; +} + diff --git a/leptonica/prog/distance_reg.c b/leptonica/prog/distance_reg.c new file mode 100644 index 00000000..642991e3 --- /dev/null +++ b/leptonica/prog/distance_reg.c @@ -0,0 +1,158 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * distance_reg.c + * + * This tests pixDistanceFunction for a variety of usage + * with all 8 combinations of these parameters: + * + * connectivity : 4 or 8 + * dest depth : 8 or 16 + * boundary cond : L_BOUNDARY_BG or L_BOUNDARY_FG + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + +static void TestDistance(PIXA *pixa, PIX *pixs, l_int32 conn, + l_int32 depth, l_int32 bc, L_REGPARAMS *rp); + +#define DEBUG 0 + + +int main(int argc, + char **argv) +{ +l_int32 i, j, k, index, conn, depth, bc; +BOX *box; +PIX *pix, *pixs, *pixd; +PIXA *pixa; +L_REGPARAMS *rp; + + if (regTestSetup(argc, argv, &rp)) + return 1; + + pix = pixRead("feyn.tif"); + box = boxCreate(383, 338, 1480, 1050); + pixs = pixClipRectangle(pix, box, NULL); + regTestWritePixAndCheck(rp, pixs, IFF_PNG); /* 0 */ + + for (i = 0; i < 2; i++) { + conn = 4 + 4 * i; + for (j = 0; j < 2; j++) { + depth = 8 + 8 * j; + for (k = 0; k < 2; k++) { + bc = k + 1; + index = 4 * i + 2 * j + k; + lept_stderr("Set %d\n", index); + if (DEBUG) { + lept_stderr("%d: conn = %d, depth = %d, bc = %d\n", + rp->index + 1, conn, depth, bc); + } + pixa = pixaCreate(0); + pixaAddPix(pixa, pixs, L_COPY); + TestDistance(pixa, pixs, conn, depth, bc, rp); + pixd = pixaDisplayTiledInColumns(pixa, 4, 1.0, 20, 2); + pixDisplayWithTitle(pixd, 0, 0, NULL, rp->display); + pixaDestroy(&pixa); + pixDestroy(&pixd); + } + } + } + + boxDestroy(&box); + pixDestroy(&pix); + pixDestroy(&pixs); + return regTestCleanup(rp); +} + + +static void +TestDistance(PIXA *pixa, + PIX *pixs, + l_int32 conn, + l_int32 depth, + l_int32 bc, + L_REGPARAMS *rp) +{ +PIX *pixt1, *pixt2, *pixt3, *pixt4, *pixt5; + + /* Test the distance function and display */ + pixInvert(pixs, pixs); + pixt1 = pixDistanceFunction(pixs, conn, depth, bc); + regTestWritePixAndCheck(rp, pixt1, IFF_PNG); /* a + 1 */ + pixaAddPix(pixa, pixt1, L_INSERT); + pixInvert(pixs, pixs); + pixt2 = pixMaxDynamicRange(pixt1, L_LOG_SCALE); + regTestWritePixAndCheck(rp, pixt2, IFF_JFIF_JPEG); /* a + 2 */ + pixaAddPix(pixa, pixt2, L_INSERT); + + /* Test the distance function and display with contour rendering */ + pixInvert(pixs, pixs); + pixt1 = pixDistanceFunction(pixs, conn, depth, bc); + regTestWritePixAndCheck(rp, pixt1, IFF_PNG); /* a + 3 */ + pixaAddPix(pixa, pixt1, L_INSERT); + pixInvert(pixs, pixs); + pixt2 = pixRenderContours(pixt1, 2, 4, 1); /* binary output */ + regTestWritePixAndCheck(rp, pixt2, IFF_PNG); /* a + 4 */ + pixaAddPix(pixa, pixt2, L_INSERT); + pixt3 = pixRenderContours(pixt1, 2, 4, depth); + pixt4 = pixMaxDynamicRange(pixt3, L_LINEAR_SCALE); + regTestWritePixAndCheck(rp, pixt4, IFF_JFIF_JPEG); /* a + 5 */ + pixaAddPix(pixa, pixt4, L_INSERT); + pixt5 = pixMaxDynamicRange(pixt3, L_LOG_SCALE); + regTestWritePixAndCheck(rp, pixt5, IFF_JFIF_JPEG); /* a + 6 */ + pixaAddPix(pixa, pixt5, L_INSERT); + pixDestroy(&pixt3); + + /* Label all pixels in each c.c. with a color equal to the + * max distance of any pixel within that c.c. from the bg. + * Note that we've normalized so the dynamic range extends + * to 255. For the image here, each unit of distance is + * represented by about 21 grayscale units. The largest + * distance is 12. */ + if (depth == 8) { + pixt1 = pixDistanceFunction(pixs, conn, depth, bc); + pixt4 = pixMaxDynamicRange(pixt1, L_LOG_SCALE); + regTestWritePixAndCheck(rp, pixt4, IFF_JFIF_JPEG); /* b + 1 */ + pixaAddPix(pixa, pixt4, L_INSERT); + pixt2 = pixCreateTemplate(pixt1); + pixSetMasked(pixt2, pixs, 255); + regTestWritePixAndCheck(rp, pixt2, IFF_JFIF_JPEG); /* b + 2 */ + pixaAddPix(pixa, pixt2, L_INSERT); + pixSeedfillGray(pixt1, pixt2, 4); + pixt3 = pixMaxDynamicRange(pixt1, L_LINEAR_SCALE); + regTestWritePixAndCheck(rp, pixt3, IFF_JFIF_JPEG); /* b + 3 */ + pixaAddPix(pixa, pixt3, L_INSERT); + pixDestroy(&pixt1); + } + + return; +} diff --git a/leptonica/prog/dither_reg.c b/leptonica/prog/dither_reg.c new file mode 100644 index 00000000..67eee053 --- /dev/null +++ b/leptonica/prog/dither_reg.c @@ -0,0 +1,86 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * dither_reg.c + * + * Test dithering from 8 bpp to 1 bpp and 2 bpp. + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + +int main(int argc, + char **argv) +{ +PIX *pix, *pixs, *pix1, *pix2; +L_REGPARAMS *rp; + + if (regTestSetup(argc, argv, &rp)) + return 1; + + pix = pixRead("test8.jpg"); + pixs = pixGammaTRC(NULL, pix, 1.3, 0, 255); /* gamma of 1.3, for fun */ + + /* Dither to 1 bpp */ + pix1 = pixDitherToBinary(pixs); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 0 */ + pixDisplayWithTitle(pix1, 0, 0, NULL, rp->display); + pixDestroy(&pix1); + + /* Dither to 2 bpp, with colormap */ + pix1 = pixDitherTo2bpp(pixs, 1); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 1 */ + pixDisplayWithTitle(pix1, 400, 0, NULL, rp->display); + + /* Dither to 2 bpp, without colormap */ + pix2 = pixDitherTo2bpp(pixs, 0); + regTestWritePixAndCheck(rp, pix2, IFF_PNG); /* 2 */ + pixDisplayWithTitle(pix2, 800, 0, NULL, rp->display); + regTestComparePix(rp, pix1, pix2); /* 3 */ + pixDestroy(&pix1); + pixDestroy(&pix2); + + /* Dither 2x upscale to 1 bpp */ + pix1 = pixScaleGray2xLIDither(pixs); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 4 */ + pixDisplayWithTitle(pix1, 0, 400, NULL, rp->display); + pixDestroy(&pix1); + + /* Dither 4x upscale to 1 bpp */ + pix1 = pixScaleGray4xLIDither(pixs); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 5 */ + pixDisplayWithTitle(pix1, 700, 400, NULL, rp->display); + pixDestroy(&pix1); + + pixDestroy(&pix); + pixDestroy(&pixs); + return regTestCleanup(rp); +} + diff --git a/leptonica/prog/dna_reg.c b/leptonica/prog/dna_reg.c new file mode 100644 index 00000000..fd57efd4 --- /dev/null +++ b/leptonica/prog/dna_reg.c @@ -0,0 +1,123 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * dna_reg.c + * + * Tests basic functioning of L_Dna (number array of doubles) + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include <math.h> +#include "allheaders.h" + +int main(int argc, + char **argv) +{ +l_int32 i, nbins, ival; +l_float64 pi, angle, val, sum; +L_DNA *da1, *da2, *da3, *da4, *da5; +L_DNAA *daa1, *daa2; +GPLOT *gplot; +NUMA *na, *nahisto, *nax; +L_REGPARAMS *rp; + +#if !defined(HAVE_LIBPNG) + L_ERROR("This test requires libpng to run.\n", "dna_reg"); + exit(77); +#endif + + if (regTestSetup(argc, argv, &rp)) + return 1; + + pi = 3.1415926535; + da1 = l_dnaCreate(50); + for (i = 0; i < 5000; i++) { + angle = 0.02293 * i * pi; + val = 999. * sin(angle); + l_dnaAddNumber(da1, val); + } + + /* Conversion to Numa; I/O for Dna */ + na = l_dnaConvertToNuma(da1); + da2 = numaConvertToDna(na); + l_dnaWrite("/tmp/lept/regout/dna1.da", da1); + l_dnaWrite("/tmp/lept/regout/dna2.da", da2); + da3 = l_dnaRead("/tmp/lept/regout/dna2.da"); + l_dnaWrite("/tmp/lept/regout/dna3.da", da3); + regTestCheckFile(rp, "/tmp/lept/regout/dna1.da"); /* 0 */ + regTestCheckFile(rp, "/tmp/lept/regout/dna2.da"); /* 1 */ + regTestCheckFile(rp, "/tmp/lept/regout/dna3.da"); /* 2 */ + regTestCompareFiles(rp, 1, 2); /* 3 */ + + /* I/O for Dnaa */ + daa1 = l_dnaaCreate(3); + l_dnaaAddDna(daa1, da1, L_INSERT); + l_dnaaAddDna(daa1, da2, L_INSERT); + l_dnaaAddDna(daa1, da3, L_INSERT); + l_dnaaWrite("/tmp/lept/regout/dnaa1.daa", daa1); + daa2 = l_dnaaRead("/tmp/lept/regout/dnaa1.daa"); + l_dnaaWrite("/tmp/lept/regout/dnaa2.daa", daa2); + regTestCheckFile(rp, "/tmp/lept/regout/dnaa1.daa"); /* 4 */ + regTestCheckFile(rp, "/tmp/lept/regout/dnaa2.daa"); /* 5 */ + regTestCompareFiles(rp, 4, 5); /* 6 */ + l_dnaaDestroy(&daa1); + l_dnaaDestroy(&daa2); + + /* Just for fun -- is the numa ok? */ + nahisto = numaMakeHistogramClipped(na, 12, 2000); + nbins = numaGetCount(nahisto); + nax = numaMakeSequence(0, 1, nbins); + gplot = gplotCreate("/tmp/lept/regout/historoot", GPLOT_PNG, + "Histo example", "i", "histo[i]"); + gplotAddPlot(gplot, nax, nahisto, GPLOT_LINES, "sine"); + gplotMakeOutput(gplot); + regTestCheckFile(rp, "/tmp/lept/regout/historoot.png"); /* 7 */ + gplotDestroy(&gplot); + numaDestroy(&na); + numaDestroy(&nax); + numaDestroy(&nahisto); + + /* Handling precision of int32 in double */ + da4 = l_dnaCreate(25); + for (i = 0; i < 1000; i++) + l_dnaAddNumber(da4, 1928374 * i); + l_dnaWrite("/tmp/lept/regout/dna4.da", da4); + da5 = l_dnaRead("/tmp/lept/regout/dna4.da"); + sum = 0; + for (i = 0; i < 1000; i++) { + l_dnaGetIValue(da5, i, &ival); + sum += L_ABS(ival - i * 1928374); /* we better be adding 0 each time */ + } + regTestCompareValues(rp, sum, 0.0, 0.0); /* 8 */ + l_dnaDestroy(&da4); + l_dnaDestroy(&da5); + + return regTestCleanup(rp); +} diff --git a/leptonica/prog/dreyfus1.png b/leptonica/prog/dreyfus1.png Binary files differnew file mode 100644 index 00000000..72f770af --- /dev/null +++ b/leptonica/prog/dreyfus1.png diff --git a/leptonica/prog/dreyfus2.png b/leptonica/prog/dreyfus2.png Binary files differnew file mode 100644 index 00000000..aa12421e --- /dev/null +++ b/leptonica/prog/dreyfus2.png diff --git a/leptonica/prog/dreyfus4.png b/leptonica/prog/dreyfus4.png Binary files differnew file mode 100644 index 00000000..40184316 --- /dev/null +++ b/leptonica/prog/dreyfus4.png diff --git a/leptonica/prog/dreyfus8.png b/leptonica/prog/dreyfus8.png Binary files differnew file mode 100644 index 00000000..8e7fe0af --- /dev/null +++ b/leptonica/prog/dreyfus8.png diff --git a/leptonica/prog/dwalinear.3.c b/leptonica/prog/dwalinear.3.c new file mode 100644 index 00000000..c08afe39 --- /dev/null +++ b/leptonica/prog/dwalinear.3.c @@ -0,0 +1,343 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/*! + * Top-level fast binary morphology with auto-generated sels + * + * PIX *pixMorphDwa_3() + * PIX *pixFMorphopGen_3() + */ + +#include <string.h> +#include "allheaders.h" + +PIX *pixMorphDwa_3(PIX *pixd, PIX *pixs, l_int32 operation, char *selname); +PIX *pixFMorphopGen_3(PIX *pixd, PIX *pixs, l_int32 operation, char *selname); +l_int32 fmorphopgen_low_3(l_uint32 *datad, l_int32 w, + l_int32 h, l_int32 wpld, + l_uint32 *datas, l_int32 wpls, + l_int32 index); + +static l_int32 NUM_SELS_GENERATED = 124; +static char SEL_NAMES[][80] = { + "sel_2h", + "sel_3h", + "sel_4h", + "sel_5h", + "sel_6h", + "sel_7h", + "sel_8h", + "sel_9h", + "sel_10h", + "sel_11h", + "sel_12h", + "sel_13h", + "sel_14h", + "sel_15h", + "sel_16h", + "sel_17h", + "sel_18h", + "sel_19h", + "sel_20h", + "sel_21h", + "sel_22h", + "sel_23h", + "sel_24h", + "sel_25h", + "sel_26h", + "sel_27h", + "sel_28h", + "sel_29h", + "sel_30h", + "sel_31h", + "sel_32h", + "sel_33h", + "sel_34h", + "sel_35h", + "sel_36h", + "sel_37h", + "sel_38h", + "sel_39h", + "sel_40h", + "sel_41h", + "sel_42h", + "sel_43h", + "sel_44h", + "sel_45h", + "sel_46h", + "sel_47h", + "sel_48h", + "sel_49h", + "sel_50h", + "sel_51h", + "sel_52h", + "sel_53h", + "sel_54h", + "sel_55h", + "sel_56h", + "sel_57h", + "sel_58h", + "sel_59h", + "sel_60h", + "sel_61h", + "sel_62h", + "sel_63h", + "sel_2v", + "sel_3v", + "sel_4v", + "sel_5v", + "sel_6v", + "sel_7v", + "sel_8v", + "sel_9v", + "sel_10v", + "sel_11v", + "sel_12v", + "sel_13v", + "sel_14v", + "sel_15v", + "sel_16v", + "sel_17v", + "sel_18v", + "sel_19v", + "sel_20v", + "sel_21v", + "sel_22v", + "sel_23v", + "sel_24v", + "sel_25v", + "sel_26v", + "sel_27v", + "sel_28v", + "sel_29v", + "sel_30v", + "sel_31v", + "sel_32v", + "sel_33v", + "sel_34v", + "sel_35v", + "sel_36v", + "sel_37v", + "sel_38v", + "sel_39v", + "sel_40v", + "sel_41v", + "sel_42v", + "sel_43v", + "sel_44v", + "sel_45v", + "sel_46v", + "sel_47v", + "sel_48v", + "sel_49v", + "sel_50v", + "sel_51v", + "sel_52v", + "sel_53v", + "sel_54v", + "sel_55v", + "sel_56v", + "sel_57v", + "sel_58v", + "sel_59v", + "sel_60v", + "sel_61v", + "sel_62v", + "sel_63v"}; + +/*! + * \brief pixMorphDwa_3() + * + * \param[in] pixd usual 3 choices: null, == pixs, != pixs + * \param[in] pixs 1 bpp + * \param[in] operation L_MORPH_DILATE, L_MORPH_ERODE, + * L_MORPH_OPEN, L_MORPH_CLOSE + * \param[in] sel name + * \return pixd + * + * <pre> + * Notes: + * (1) This simply adds a border, calls the appropriate + * pixFMorphopGen_*(), and removes the border. + * See the notes for that function. + * (2) The size of the border depends on the operation + * and the boundary conditions. + * </pre> + */ +PIX * +pixMorphDwa_3(PIX *pixd, + PIX *pixs, + l_int32 operation, + char *selname) +{ +l_int32 bordercolor, bordersize; +PIX *pixt1, *pixt2, *pixt3; + + PROCNAME("pixMorphDwa_3"); + + if (!pixs) + return (PIX *)ERROR_PTR("pixs not defined", procName, pixd); + if (pixGetDepth(pixs) != 1) + return (PIX *)ERROR_PTR("pixs must be 1 bpp", procName, pixd); + + /* Set the border size */ + bordercolor = getMorphBorderPixelColor(L_MORPH_ERODE, 1); + bordersize = 32; + if (bordercolor == 0 && operation == L_MORPH_CLOSE) + bordersize += 32; + + pixt1 = pixAddBorder(pixs, bordersize, 0); + pixt2 = pixFMorphopGen_3(NULL, pixt1, operation, selname); + pixt3 = pixRemoveBorder(pixt2, bordersize); + pixDestroy(&pixt1); + pixDestroy(&pixt2); + + if (!pixd) + return pixt3; + + pixCopy(pixd, pixt3); + pixDestroy(&pixt3); + return pixd; +} + + +/*! + * \brief pixFMorphopGen_3() + * + * \param[in] pixd usual 3 choices: null, == pixs, != pixs + * \param[in] pixs 1 bpp + * \param[in] operation L_MORPH_DILATE, L_MORPH_ERODE, + * L_MORPH_OPEN, L_MORPH_CLOSE + * \param[in] sel name + * \return pixd + * + * <pre> + * Notes: + * (1) This is a dwa operation, and the Sels must be limited in + * size to not more than 31 pixels about the origin. + * (2) A border of appropriate size (32 pixels, or 64 pixels + * for safe closing with asymmetric b.c.) must be added before + * this function is called. + * (3) This handles all required setting of the border pixels + * before erosion and dilation. + * (4) The closing operation is safe; no pixels can be removed + * near the boundary. + * </pre> + */ +PIX * +pixFMorphopGen_3(PIX *pixd, + PIX *pixs, + l_int32 operation, + char *selname) +{ +l_int32 i, index, found, w, h, wpls, wpld, bordercolor, erodeop, borderop; +l_uint32 *datad, *datas, *datat; +PIX *pixt; + + PROCNAME("pixFMorphopGen_3"); + + if (!pixs) + return (PIX *)ERROR_PTR("pixs not defined", procName, pixd); + if (pixGetDepth(pixs) != 1) + return (PIX *)ERROR_PTR("pixs must be 1 bpp", procName, pixd); + + /* Get boundary colors to use */ + bordercolor = getMorphBorderPixelColor(L_MORPH_ERODE, 1); + if (bordercolor == 1) + erodeop = PIX_SET; + else + erodeop = PIX_CLR; + + found = FALSE; + for (i = 0; i < NUM_SELS_GENERATED; i++) { + if (strcmp(selname, SEL_NAMES[i]) == 0) { + found = TRUE; + index = 2 * i; + break; + } + } + if (found == FALSE) + return (PIX *)ERROR_PTR("sel index not found", procName, pixd); + + if (!pixd) { + if ((pixd = pixCreateTemplate(pixs)) == NULL) + return (PIX *)ERROR_PTR("pixd not made", procName, NULL); + } + else /* for in-place or pre-allocated */ + pixResizeImageData(pixd, pixs); + wpls = pixGetWpl(pixs); + wpld = pixGetWpl(pixd); + + /* The images must be surrounded, in advance, with a border of + * size 32 pixels (or 64, for closing), that we'll read from. + * Fabricate a "proper" image as the subimage within the 32 + * pixel border, having the following parameters: */ + w = pixGetWidth(pixs) - 64; + h = pixGetHeight(pixs) - 64; + datas = pixGetData(pixs) + 32 * wpls + 1; + datad = pixGetData(pixd) + 32 * wpld + 1; + + if (operation == L_MORPH_DILATE || operation == L_MORPH_ERODE) { + borderop = PIX_CLR; + if (operation == L_MORPH_ERODE) { + borderop = erodeop; + index++; + } + if (pixd == pixs) { /* in-place; generate a temp image */ + if ((pixt = pixCopy(NULL, pixs)) == NULL) + return (PIX *)ERROR_PTR("pixt not made", procName, pixd); + datat = pixGetData(pixt) + 32 * wpls + 1; + pixSetOrClearBorder(pixt, 32, 32, 32, 32, borderop); + fmorphopgen_low_3(datad, w, h, wpld, datat, wpls, index); + pixDestroy(&pixt); + } + else { /* not in-place */ + pixSetOrClearBorder(pixs, 32, 32, 32, 32, borderop); + fmorphopgen_low_3(datad, w, h, wpld, datas, wpls, index); + } + } + else { /* opening or closing; generate a temp image */ + if ((pixt = pixCreateTemplate(pixs)) == NULL) + return (PIX *)ERROR_PTR("pixt not made", procName, pixd); + datat = pixGetData(pixt) + 32 * wpls + 1; + if (operation == L_MORPH_OPEN) { + pixSetOrClearBorder(pixs, 32, 32, 32, 32, erodeop); + fmorphopgen_low_3(datat, w, h, wpls, datas, wpls, index+1); + pixSetOrClearBorder(pixt, 32, 32, 32, 32, PIX_CLR); + fmorphopgen_low_3(datad, w, h, wpld, datat, wpls, index); + } + else { /* closing */ + pixSetOrClearBorder(pixs, 32, 32, 32, 32, PIX_CLR); + fmorphopgen_low_3(datat, w, h, wpls, datas, wpls, index); + pixSetOrClearBorder(pixt, 32, 32, 32, 32, erodeop); + fmorphopgen_low_3(datad, w, h, wpld, datat, wpls, index+1); + } + pixDestroy(&pixt); + } + + return pixd; +} + diff --git a/leptonica/prog/dwalineargen.c b/leptonica/prog/dwalineargen.c new file mode 100644 index 00000000..bb28fae9 --- /dev/null +++ b/leptonica/prog/dwalineargen.c @@ -0,0 +1,79 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * dwalineargen.c + * + * This generates the C code for the full set of linear Sels, + * for dilation, erosion, opening and closing, and for both + * horizontal and vertical operations, from length 2 to 63. + * + * These are put in files: + * dwalinear.3.c + * dwalinearlow.3.c + * + * Q. Why is this C code generated here in prog, and not placed + * in the library where it can be linked in with all programs? + * A. Because the two files it generates have 17K lines of code! + * We also make this code available here ("out of the box") so that you + * can build and run dwamorph1_reg and dwamorph2_reg, without + * first building and running dwalineargen.c + * + * Q. Why do we build code for operations up to 63 in width and height? + * A. Atomic DWA operations work on Sels that have hits and misses + * that are not larger than 31 pixel positions from the origin. + * Thus, they can implement a horizontal closing up to 63 pixels + * wide if the origin is in the center. + * + * Note the word "atomic". DWA operations can be done on arbitrarily + * large Sels using the *ExtendDwa() functions. See morphdwa.c + * for details. + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + +int main(int argc, + char **argv) +{ +SELA *sela; +static char mainName[] = "dwalineargen"; + + if (argc != 1) + return ERROR_INT(" Syntax: dwalineargen", mainName, 1); + setLeptDebugOK(1); + + /* Generate the linear sel dwa code */ + sela = selaAddDwaLinear(NULL); + if (fmorphautogen(sela, 3, "dwalinear")) + return 1; + selaDestroy(&sela); + return 0; +} + diff --git a/leptonica/prog/dwalinearlow.3.c b/leptonica/prog/dwalinearlow.3.c new file mode 100644 index 00000000..cf654e35 --- /dev/null +++ b/leptonica/prog/dwalinearlow.3.c @@ -0,0 +1,16986 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/*! + * Low-level fast binary morphology with auto-generated sels + * + * Dispatcher: + * l_int32 fmorphopgen_low_3() + * + * Static Low-level: + * void fdilate_3_*() + * void ferode_3_*() + */ + +#include "allheaders.h" + +static void fdilate_3_0(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void ferode_3_0(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void fdilate_3_1(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void ferode_3_1(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void fdilate_3_2(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void ferode_3_2(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void fdilate_3_3(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void ferode_3_3(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void fdilate_3_4(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void ferode_3_4(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void fdilate_3_5(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void ferode_3_5(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void fdilate_3_6(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void ferode_3_6(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void fdilate_3_7(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void ferode_3_7(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void fdilate_3_8(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void ferode_3_8(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void fdilate_3_9(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void ferode_3_9(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void fdilate_3_10(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void ferode_3_10(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void fdilate_3_11(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void ferode_3_11(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void fdilate_3_12(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void ferode_3_12(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void fdilate_3_13(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void ferode_3_13(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void fdilate_3_14(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void ferode_3_14(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void fdilate_3_15(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void ferode_3_15(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void fdilate_3_16(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void ferode_3_16(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void fdilate_3_17(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void ferode_3_17(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void fdilate_3_18(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void ferode_3_18(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void fdilate_3_19(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void ferode_3_19(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void fdilate_3_20(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void ferode_3_20(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void fdilate_3_21(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void ferode_3_21(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void fdilate_3_22(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void ferode_3_22(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void fdilate_3_23(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void ferode_3_23(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void fdilate_3_24(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void ferode_3_24(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void fdilate_3_25(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void ferode_3_25(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void fdilate_3_26(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void ferode_3_26(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void fdilate_3_27(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void ferode_3_27(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void fdilate_3_28(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void ferode_3_28(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void fdilate_3_29(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void ferode_3_29(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void fdilate_3_30(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void ferode_3_30(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void fdilate_3_31(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void ferode_3_31(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void fdilate_3_32(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void ferode_3_32(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void fdilate_3_33(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void ferode_3_33(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void fdilate_3_34(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void ferode_3_34(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void fdilate_3_35(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void ferode_3_35(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void fdilate_3_36(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void ferode_3_36(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void fdilate_3_37(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void ferode_3_37(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void fdilate_3_38(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void ferode_3_38(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void fdilate_3_39(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void ferode_3_39(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void fdilate_3_40(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void ferode_3_40(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void fdilate_3_41(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void ferode_3_41(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void fdilate_3_42(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void ferode_3_42(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void fdilate_3_43(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void ferode_3_43(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void fdilate_3_44(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void ferode_3_44(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void fdilate_3_45(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void ferode_3_45(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void fdilate_3_46(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void ferode_3_46(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void fdilate_3_47(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void ferode_3_47(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void fdilate_3_48(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void ferode_3_48(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void fdilate_3_49(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void ferode_3_49(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void fdilate_3_50(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void ferode_3_50(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void fdilate_3_51(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void ferode_3_51(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void fdilate_3_52(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void ferode_3_52(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void fdilate_3_53(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void ferode_3_53(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void fdilate_3_54(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void ferode_3_54(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void fdilate_3_55(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void ferode_3_55(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void fdilate_3_56(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void ferode_3_56(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void fdilate_3_57(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void ferode_3_57(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void fdilate_3_58(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void ferode_3_58(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void fdilate_3_59(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void ferode_3_59(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void fdilate_3_60(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void ferode_3_60(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void fdilate_3_61(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void ferode_3_61(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void fdilate_3_62(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void ferode_3_62(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void fdilate_3_63(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void ferode_3_63(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void fdilate_3_64(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void ferode_3_64(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void fdilate_3_65(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void ferode_3_65(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void fdilate_3_66(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void ferode_3_66(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void fdilate_3_67(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void ferode_3_67(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void fdilate_3_68(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void ferode_3_68(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void fdilate_3_69(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void ferode_3_69(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void fdilate_3_70(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void ferode_3_70(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void fdilate_3_71(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void ferode_3_71(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void fdilate_3_72(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void ferode_3_72(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void fdilate_3_73(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void ferode_3_73(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void fdilate_3_74(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void ferode_3_74(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void fdilate_3_75(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void ferode_3_75(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void fdilate_3_76(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void ferode_3_76(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void fdilate_3_77(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void ferode_3_77(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void fdilate_3_78(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void ferode_3_78(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void fdilate_3_79(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void ferode_3_79(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void fdilate_3_80(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void ferode_3_80(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void fdilate_3_81(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void ferode_3_81(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void fdilate_3_82(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void ferode_3_82(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void fdilate_3_83(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void ferode_3_83(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void fdilate_3_84(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void ferode_3_84(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void fdilate_3_85(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void ferode_3_85(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void fdilate_3_86(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void ferode_3_86(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void fdilate_3_87(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void ferode_3_87(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void fdilate_3_88(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void ferode_3_88(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void fdilate_3_89(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void ferode_3_89(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void fdilate_3_90(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void ferode_3_90(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void fdilate_3_91(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void ferode_3_91(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void fdilate_3_92(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void ferode_3_92(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void fdilate_3_93(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void ferode_3_93(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void fdilate_3_94(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void ferode_3_94(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void fdilate_3_95(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void ferode_3_95(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void fdilate_3_96(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void ferode_3_96(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void fdilate_3_97(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void ferode_3_97(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void fdilate_3_98(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void ferode_3_98(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void fdilate_3_99(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void ferode_3_99(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void fdilate_3_100(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void ferode_3_100(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void fdilate_3_101(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void ferode_3_101(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void fdilate_3_102(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void ferode_3_102(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void fdilate_3_103(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void ferode_3_103(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void fdilate_3_104(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void ferode_3_104(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void fdilate_3_105(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void ferode_3_105(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void fdilate_3_106(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void ferode_3_106(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void fdilate_3_107(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void ferode_3_107(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void fdilate_3_108(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void ferode_3_108(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void fdilate_3_109(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void ferode_3_109(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void fdilate_3_110(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void ferode_3_110(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void fdilate_3_111(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void ferode_3_111(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void fdilate_3_112(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void ferode_3_112(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void fdilate_3_113(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void ferode_3_113(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void fdilate_3_114(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void ferode_3_114(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void fdilate_3_115(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void ferode_3_115(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void fdilate_3_116(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void ferode_3_116(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void fdilate_3_117(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void ferode_3_117(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void fdilate_3_118(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void ferode_3_118(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void fdilate_3_119(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void ferode_3_119(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void fdilate_3_120(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void ferode_3_120(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void fdilate_3_121(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void ferode_3_121(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void fdilate_3_122(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void ferode_3_122(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void fdilate_3_123(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); +static void ferode_3_123(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32); + + +/*---------------------------------------------------------------------* + * Fast morph dispatcher * + *---------------------------------------------------------------------*/ +/*! + * fmorphopgen_low_3() + * + * a dispatcher to appropriate low-level code + */ +l_int32 +fmorphopgen_low_3(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls, + l_int32 index) +{ + + switch (index) + { + case 0: + fdilate_3_0(datad, w, h, wpld, datas, wpls); + break; + case 1: + ferode_3_0(datad, w, h, wpld, datas, wpls); + break; + case 2: + fdilate_3_1(datad, w, h, wpld, datas, wpls); + break; + case 3: + ferode_3_1(datad, w, h, wpld, datas, wpls); + break; + case 4: + fdilate_3_2(datad, w, h, wpld, datas, wpls); + break; + case 5: + ferode_3_2(datad, w, h, wpld, datas, wpls); + break; + case 6: + fdilate_3_3(datad, w, h, wpld, datas, wpls); + break; + case 7: + ferode_3_3(datad, w, h, wpld, datas, wpls); + break; + case 8: + fdilate_3_4(datad, w, h, wpld, datas, wpls); + break; + case 9: + ferode_3_4(datad, w, h, wpld, datas, wpls); + break; + case 10: + fdilate_3_5(datad, w, h, wpld, datas, wpls); + break; + case 11: + ferode_3_5(datad, w, h, wpld, datas, wpls); + break; + case 12: + fdilate_3_6(datad, w, h, wpld, datas, wpls); + break; + case 13: + ferode_3_6(datad, w, h, wpld, datas, wpls); + break; + case 14: + fdilate_3_7(datad, w, h, wpld, datas, wpls); + break; + case 15: + ferode_3_7(datad, w, h, wpld, datas, wpls); + break; + case 16: + fdilate_3_8(datad, w, h, wpld, datas, wpls); + break; + case 17: + ferode_3_8(datad, w, h, wpld, datas, wpls); + break; + case 18: + fdilate_3_9(datad, w, h, wpld, datas, wpls); + break; + case 19: + ferode_3_9(datad, w, h, wpld, datas, wpls); + break; + case 20: + fdilate_3_10(datad, w, h, wpld, datas, wpls); + break; + case 21: + ferode_3_10(datad, w, h, wpld, datas, wpls); + break; + case 22: + fdilate_3_11(datad, w, h, wpld, datas, wpls); + break; + case 23: + ferode_3_11(datad, w, h, wpld, datas, wpls); + break; + case 24: + fdilate_3_12(datad, w, h, wpld, datas, wpls); + break; + case 25: + ferode_3_12(datad, w, h, wpld, datas, wpls); + break; + case 26: + fdilate_3_13(datad, w, h, wpld, datas, wpls); + break; + case 27: + ferode_3_13(datad, w, h, wpld, datas, wpls); + break; + case 28: + fdilate_3_14(datad, w, h, wpld, datas, wpls); + break; + case 29: + ferode_3_14(datad, w, h, wpld, datas, wpls); + break; + case 30: + fdilate_3_15(datad, w, h, wpld, datas, wpls); + break; + case 31: + ferode_3_15(datad, w, h, wpld, datas, wpls); + break; + case 32: + fdilate_3_16(datad, w, h, wpld, datas, wpls); + break; + case 33: + ferode_3_16(datad, w, h, wpld, datas, wpls); + break; + case 34: + fdilate_3_17(datad, w, h, wpld, datas, wpls); + break; + case 35: + ferode_3_17(datad, w, h, wpld, datas, wpls); + break; + case 36: + fdilate_3_18(datad, w, h, wpld, datas, wpls); + break; + case 37: + ferode_3_18(datad, w, h, wpld, datas, wpls); + break; + case 38: + fdilate_3_19(datad, w, h, wpld, datas, wpls); + break; + case 39: + ferode_3_19(datad, w, h, wpld, datas, wpls); + break; + case 40: + fdilate_3_20(datad, w, h, wpld, datas, wpls); + break; + case 41: + ferode_3_20(datad, w, h, wpld, datas, wpls); + break; + case 42: + fdilate_3_21(datad, w, h, wpld, datas, wpls); + break; + case 43: + ferode_3_21(datad, w, h, wpld, datas, wpls); + break; + case 44: + fdilate_3_22(datad, w, h, wpld, datas, wpls); + break; + case 45: + ferode_3_22(datad, w, h, wpld, datas, wpls); + break; + case 46: + fdilate_3_23(datad, w, h, wpld, datas, wpls); + break; + case 47: + ferode_3_23(datad, w, h, wpld, datas, wpls); + break; + case 48: + fdilate_3_24(datad, w, h, wpld, datas, wpls); + break; + case 49: + ferode_3_24(datad, w, h, wpld, datas, wpls); + break; + case 50: + fdilate_3_25(datad, w, h, wpld, datas, wpls); + break; + case 51: + ferode_3_25(datad, w, h, wpld, datas, wpls); + break; + case 52: + fdilate_3_26(datad, w, h, wpld, datas, wpls); + break; + case 53: + ferode_3_26(datad, w, h, wpld, datas, wpls); + break; + case 54: + fdilate_3_27(datad, w, h, wpld, datas, wpls); + break; + case 55: + ferode_3_27(datad, w, h, wpld, datas, wpls); + break; + case 56: + fdilate_3_28(datad, w, h, wpld, datas, wpls); + break; + case 57: + ferode_3_28(datad, w, h, wpld, datas, wpls); + break; + case 58: + fdilate_3_29(datad, w, h, wpld, datas, wpls); + break; + case 59: + ferode_3_29(datad, w, h, wpld, datas, wpls); + break; + case 60: + fdilate_3_30(datad, w, h, wpld, datas, wpls); + break; + case 61: + ferode_3_30(datad, w, h, wpld, datas, wpls); + break; + case 62: + fdilate_3_31(datad, w, h, wpld, datas, wpls); + break; + case 63: + ferode_3_31(datad, w, h, wpld, datas, wpls); + break; + case 64: + fdilate_3_32(datad, w, h, wpld, datas, wpls); + break; + case 65: + ferode_3_32(datad, w, h, wpld, datas, wpls); + break; + case 66: + fdilate_3_33(datad, w, h, wpld, datas, wpls); + break; + case 67: + ferode_3_33(datad, w, h, wpld, datas, wpls); + break; + case 68: + fdilate_3_34(datad, w, h, wpld, datas, wpls); + break; + case 69: + ferode_3_34(datad, w, h, wpld, datas, wpls); + break; + case 70: + fdilate_3_35(datad, w, h, wpld, datas, wpls); + break; + case 71: + ferode_3_35(datad, w, h, wpld, datas, wpls); + break; + case 72: + fdilate_3_36(datad, w, h, wpld, datas, wpls); + break; + case 73: + ferode_3_36(datad, w, h, wpld, datas, wpls); + break; + case 74: + fdilate_3_37(datad, w, h, wpld, datas, wpls); + break; + case 75: + ferode_3_37(datad, w, h, wpld, datas, wpls); + break; + case 76: + fdilate_3_38(datad, w, h, wpld, datas, wpls); + break; + case 77: + ferode_3_38(datad, w, h, wpld, datas, wpls); + break; + case 78: + fdilate_3_39(datad, w, h, wpld, datas, wpls); + break; + case 79: + ferode_3_39(datad, w, h, wpld, datas, wpls); + break; + case 80: + fdilate_3_40(datad, w, h, wpld, datas, wpls); + break; + case 81: + ferode_3_40(datad, w, h, wpld, datas, wpls); + break; + case 82: + fdilate_3_41(datad, w, h, wpld, datas, wpls); + break; + case 83: + ferode_3_41(datad, w, h, wpld, datas, wpls); + break; + case 84: + fdilate_3_42(datad, w, h, wpld, datas, wpls); + break; + case 85: + ferode_3_42(datad, w, h, wpld, datas, wpls); + break; + case 86: + fdilate_3_43(datad, w, h, wpld, datas, wpls); + break; + case 87: + ferode_3_43(datad, w, h, wpld, datas, wpls); + break; + case 88: + fdilate_3_44(datad, w, h, wpld, datas, wpls); + break; + case 89: + ferode_3_44(datad, w, h, wpld, datas, wpls); + break; + case 90: + fdilate_3_45(datad, w, h, wpld, datas, wpls); + break; + case 91: + ferode_3_45(datad, w, h, wpld, datas, wpls); + break; + case 92: + fdilate_3_46(datad, w, h, wpld, datas, wpls); + break; + case 93: + ferode_3_46(datad, w, h, wpld, datas, wpls); + break; + case 94: + fdilate_3_47(datad, w, h, wpld, datas, wpls); + break; + case 95: + ferode_3_47(datad, w, h, wpld, datas, wpls); + break; + case 96: + fdilate_3_48(datad, w, h, wpld, datas, wpls); + break; + case 97: + ferode_3_48(datad, w, h, wpld, datas, wpls); + break; + case 98: + fdilate_3_49(datad, w, h, wpld, datas, wpls); + break; + case 99: + ferode_3_49(datad, w, h, wpld, datas, wpls); + break; + case 100: + fdilate_3_50(datad, w, h, wpld, datas, wpls); + break; + case 101: + ferode_3_50(datad, w, h, wpld, datas, wpls); + break; + case 102: + fdilate_3_51(datad, w, h, wpld, datas, wpls); + break; + case 103: + ferode_3_51(datad, w, h, wpld, datas, wpls); + break; + case 104: + fdilate_3_52(datad, w, h, wpld, datas, wpls); + break; + case 105: + ferode_3_52(datad, w, h, wpld, datas, wpls); + break; + case 106: + fdilate_3_53(datad, w, h, wpld, datas, wpls); + break; + case 107: + ferode_3_53(datad, w, h, wpld, datas, wpls); + break; + case 108: + fdilate_3_54(datad, w, h, wpld, datas, wpls); + break; + case 109: + ferode_3_54(datad, w, h, wpld, datas, wpls); + break; + case 110: + fdilate_3_55(datad, w, h, wpld, datas, wpls); + break; + case 111: + ferode_3_55(datad, w, h, wpld, datas, wpls); + break; + case 112: + fdilate_3_56(datad, w, h, wpld, datas, wpls); + break; + case 113: + ferode_3_56(datad, w, h, wpld, datas, wpls); + break; + case 114: + fdilate_3_57(datad, w, h, wpld, datas, wpls); + break; + case 115: + ferode_3_57(datad, w, h, wpld, datas, wpls); + break; + case 116: + fdilate_3_58(datad, w, h, wpld, datas, wpls); + break; + case 117: + ferode_3_58(datad, w, h, wpld, datas, wpls); + break; + case 118: + fdilate_3_59(datad, w, h, wpld, datas, wpls); + break; + case 119: + ferode_3_59(datad, w, h, wpld, datas, wpls); + break; + case 120: + fdilate_3_60(datad, w, h, wpld, datas, wpls); + break; + case 121: + ferode_3_60(datad, w, h, wpld, datas, wpls); + break; + case 122: + fdilate_3_61(datad, w, h, wpld, datas, wpls); + break; + case 123: + ferode_3_61(datad, w, h, wpld, datas, wpls); + break; + case 124: + fdilate_3_62(datad, w, h, wpld, datas, wpls); + break; + case 125: + ferode_3_62(datad, w, h, wpld, datas, wpls); + break; + case 126: + fdilate_3_63(datad, w, h, wpld, datas, wpls); + break; + case 127: + ferode_3_63(datad, w, h, wpld, datas, wpls); + break; + case 128: + fdilate_3_64(datad, w, h, wpld, datas, wpls); + break; + case 129: + ferode_3_64(datad, w, h, wpld, datas, wpls); + break; + case 130: + fdilate_3_65(datad, w, h, wpld, datas, wpls); + break; + case 131: + ferode_3_65(datad, w, h, wpld, datas, wpls); + break; + case 132: + fdilate_3_66(datad, w, h, wpld, datas, wpls); + break; + case 133: + ferode_3_66(datad, w, h, wpld, datas, wpls); + break; + case 134: + fdilate_3_67(datad, w, h, wpld, datas, wpls); + break; + case 135: + ferode_3_67(datad, w, h, wpld, datas, wpls); + break; + case 136: + fdilate_3_68(datad, w, h, wpld, datas, wpls); + break; + case 137: + ferode_3_68(datad, w, h, wpld, datas, wpls); + break; + case 138: + fdilate_3_69(datad, w, h, wpld, datas, wpls); + break; + case 139: + ferode_3_69(datad, w, h, wpld, datas, wpls); + break; + case 140: + fdilate_3_70(datad, w, h, wpld, datas, wpls); + break; + case 141: + ferode_3_70(datad, w, h, wpld, datas, wpls); + break; + case 142: + fdilate_3_71(datad, w, h, wpld, datas, wpls); + break; + case 143: + ferode_3_71(datad, w, h, wpld, datas, wpls); + break; + case 144: + fdilate_3_72(datad, w, h, wpld, datas, wpls); + break; + case 145: + ferode_3_72(datad, w, h, wpld, datas, wpls); + break; + case 146: + fdilate_3_73(datad, w, h, wpld, datas, wpls); + break; + case 147: + ferode_3_73(datad, w, h, wpld, datas, wpls); + break; + case 148: + fdilate_3_74(datad, w, h, wpld, datas, wpls); + break; + case 149: + ferode_3_74(datad, w, h, wpld, datas, wpls); + break; + case 150: + fdilate_3_75(datad, w, h, wpld, datas, wpls); + break; + case 151: + ferode_3_75(datad, w, h, wpld, datas, wpls); + break; + case 152: + fdilate_3_76(datad, w, h, wpld, datas, wpls); + break; + case 153: + ferode_3_76(datad, w, h, wpld, datas, wpls); + break; + case 154: + fdilate_3_77(datad, w, h, wpld, datas, wpls); + break; + case 155: + ferode_3_77(datad, w, h, wpld, datas, wpls); + break; + case 156: + fdilate_3_78(datad, w, h, wpld, datas, wpls); + break; + case 157: + ferode_3_78(datad, w, h, wpld, datas, wpls); + break; + case 158: + fdilate_3_79(datad, w, h, wpld, datas, wpls); + break; + case 159: + ferode_3_79(datad, w, h, wpld, datas, wpls); + break; + case 160: + fdilate_3_80(datad, w, h, wpld, datas, wpls); + break; + case 161: + ferode_3_80(datad, w, h, wpld, datas, wpls); + break; + case 162: + fdilate_3_81(datad, w, h, wpld, datas, wpls); + break; + case 163: + ferode_3_81(datad, w, h, wpld, datas, wpls); + break; + case 164: + fdilate_3_82(datad, w, h, wpld, datas, wpls); + break; + case 165: + ferode_3_82(datad, w, h, wpld, datas, wpls); + break; + case 166: + fdilate_3_83(datad, w, h, wpld, datas, wpls); + break; + case 167: + ferode_3_83(datad, w, h, wpld, datas, wpls); + break; + case 168: + fdilate_3_84(datad, w, h, wpld, datas, wpls); + break; + case 169: + ferode_3_84(datad, w, h, wpld, datas, wpls); + break; + case 170: + fdilate_3_85(datad, w, h, wpld, datas, wpls); + break; + case 171: + ferode_3_85(datad, w, h, wpld, datas, wpls); + break; + case 172: + fdilate_3_86(datad, w, h, wpld, datas, wpls); + break; + case 173: + ferode_3_86(datad, w, h, wpld, datas, wpls); + break; + case 174: + fdilate_3_87(datad, w, h, wpld, datas, wpls); + break; + case 175: + ferode_3_87(datad, w, h, wpld, datas, wpls); + break; + case 176: + fdilate_3_88(datad, w, h, wpld, datas, wpls); + break; + case 177: + ferode_3_88(datad, w, h, wpld, datas, wpls); + break; + case 178: + fdilate_3_89(datad, w, h, wpld, datas, wpls); + break; + case 179: + ferode_3_89(datad, w, h, wpld, datas, wpls); + break; + case 180: + fdilate_3_90(datad, w, h, wpld, datas, wpls); + break; + case 181: + ferode_3_90(datad, w, h, wpld, datas, wpls); + break; + case 182: + fdilate_3_91(datad, w, h, wpld, datas, wpls); + break; + case 183: + ferode_3_91(datad, w, h, wpld, datas, wpls); + break; + case 184: + fdilate_3_92(datad, w, h, wpld, datas, wpls); + break; + case 185: + ferode_3_92(datad, w, h, wpld, datas, wpls); + break; + case 186: + fdilate_3_93(datad, w, h, wpld, datas, wpls); + break; + case 187: + ferode_3_93(datad, w, h, wpld, datas, wpls); + break; + case 188: + fdilate_3_94(datad, w, h, wpld, datas, wpls); + break; + case 189: + ferode_3_94(datad, w, h, wpld, datas, wpls); + break; + case 190: + fdilate_3_95(datad, w, h, wpld, datas, wpls); + break; + case 191: + ferode_3_95(datad, w, h, wpld, datas, wpls); + break; + case 192: + fdilate_3_96(datad, w, h, wpld, datas, wpls); + break; + case 193: + ferode_3_96(datad, w, h, wpld, datas, wpls); + break; + case 194: + fdilate_3_97(datad, w, h, wpld, datas, wpls); + break; + case 195: + ferode_3_97(datad, w, h, wpld, datas, wpls); + break; + case 196: + fdilate_3_98(datad, w, h, wpld, datas, wpls); + break; + case 197: + ferode_3_98(datad, w, h, wpld, datas, wpls); + break; + case 198: + fdilate_3_99(datad, w, h, wpld, datas, wpls); + break; + case 199: + ferode_3_99(datad, w, h, wpld, datas, wpls); + break; + case 200: + fdilate_3_100(datad, w, h, wpld, datas, wpls); + break; + case 201: + ferode_3_100(datad, w, h, wpld, datas, wpls); + break; + case 202: + fdilate_3_101(datad, w, h, wpld, datas, wpls); + break; + case 203: + ferode_3_101(datad, w, h, wpld, datas, wpls); + break; + case 204: + fdilate_3_102(datad, w, h, wpld, datas, wpls); + break; + case 205: + ferode_3_102(datad, w, h, wpld, datas, wpls); + break; + case 206: + fdilate_3_103(datad, w, h, wpld, datas, wpls); + break; + case 207: + ferode_3_103(datad, w, h, wpld, datas, wpls); + break; + case 208: + fdilate_3_104(datad, w, h, wpld, datas, wpls); + break; + case 209: + ferode_3_104(datad, w, h, wpld, datas, wpls); + break; + case 210: + fdilate_3_105(datad, w, h, wpld, datas, wpls); + break; + case 211: + ferode_3_105(datad, w, h, wpld, datas, wpls); + break; + case 212: + fdilate_3_106(datad, w, h, wpld, datas, wpls); + break; + case 213: + ferode_3_106(datad, w, h, wpld, datas, wpls); + break; + case 214: + fdilate_3_107(datad, w, h, wpld, datas, wpls); + break; + case 215: + ferode_3_107(datad, w, h, wpld, datas, wpls); + break; + case 216: + fdilate_3_108(datad, w, h, wpld, datas, wpls); + break; + case 217: + ferode_3_108(datad, w, h, wpld, datas, wpls); + break; + case 218: + fdilate_3_109(datad, w, h, wpld, datas, wpls); + break; + case 219: + ferode_3_109(datad, w, h, wpld, datas, wpls); + break; + case 220: + fdilate_3_110(datad, w, h, wpld, datas, wpls); + break; + case 221: + ferode_3_110(datad, w, h, wpld, datas, wpls); + break; + case 222: + fdilate_3_111(datad, w, h, wpld, datas, wpls); + break; + case 223: + ferode_3_111(datad, w, h, wpld, datas, wpls); + break; + case 224: + fdilate_3_112(datad, w, h, wpld, datas, wpls); + break; + case 225: + ferode_3_112(datad, w, h, wpld, datas, wpls); + break; + case 226: + fdilate_3_113(datad, w, h, wpld, datas, wpls); + break; + case 227: + ferode_3_113(datad, w, h, wpld, datas, wpls); + break; + case 228: + fdilate_3_114(datad, w, h, wpld, datas, wpls); + break; + case 229: + ferode_3_114(datad, w, h, wpld, datas, wpls); + break; + case 230: + fdilate_3_115(datad, w, h, wpld, datas, wpls); + break; + case 231: + ferode_3_115(datad, w, h, wpld, datas, wpls); + break; + case 232: + fdilate_3_116(datad, w, h, wpld, datas, wpls); + break; + case 233: + ferode_3_116(datad, w, h, wpld, datas, wpls); + break; + case 234: + fdilate_3_117(datad, w, h, wpld, datas, wpls); + break; + case 235: + ferode_3_117(datad, w, h, wpld, datas, wpls); + break; + case 236: + fdilate_3_118(datad, w, h, wpld, datas, wpls); + break; + case 237: + ferode_3_118(datad, w, h, wpld, datas, wpls); + break; + case 238: + fdilate_3_119(datad, w, h, wpld, datas, wpls); + break; + case 239: + ferode_3_119(datad, w, h, wpld, datas, wpls); + break; + case 240: + fdilate_3_120(datad, w, h, wpld, datas, wpls); + break; + case 241: + ferode_3_120(datad, w, h, wpld, datas, wpls); + break; + case 242: + fdilate_3_121(datad, w, h, wpld, datas, wpls); + break; + case 243: + ferode_3_121(datad, w, h, wpld, datas, wpls); + break; + case 244: + fdilate_3_122(datad, w, h, wpld, datas, wpls); + break; + case 245: + ferode_3_122(datad, w, h, wpld, datas, wpls); + break; + case 246: + fdilate_3_123(datad, w, h, wpld, datas, wpls); + break; + case 247: + ferode_3_123(datad, w, h, wpld, datas, wpls); + break; + } + + return 0; +} + + +/*--------------------------------------------------------------------------* + * Low-level auto-generated static routines * + *--------------------------------------------------------------------------*/ +/* + * N.B. In all the low-level routines, the part of the image + * that is accessed has been clipped by 32 pixels on + * all four sides. This is done in the higher level + * code by redefining w and h smaller and by moving the + * start-of-image pointers up to the beginning of this + * interior rectangle. + */ +static void +fdilate_3_0(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; + + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = ((*(sptr) << 1) | (*(sptr + 1) >> 31)) | + (*sptr); + } + } +} + +static void +ferode_3_0(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; + + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = ((*(sptr) >> 1) | (*(sptr - 1) << 31)) & + (*sptr); + } + } +} + +static void +fdilate_3_1(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; + + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = ((*(sptr) << 1) | (*(sptr + 1) >> 31)) | + (*sptr) | + ((*(sptr) >> 1) | (*(sptr - 1) << 31)); + } + } +} + +static void +ferode_3_1(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; + + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = ((*(sptr) >> 1) | (*(sptr - 1) << 31)) & + (*sptr) & + ((*(sptr) << 1) | (*(sptr + 1) >> 31)); + } + } +} + +static void +fdilate_3_2(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; + + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = ((*(sptr) << 2) | (*(sptr + 1) >> 30)) | + ((*(sptr) << 1) | (*(sptr + 1) >> 31)) | + (*sptr) | + ((*(sptr) >> 1) | (*(sptr - 1) << 31)); + } + } +} + +static void +ferode_3_2(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; + + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = ((*(sptr) >> 2) | (*(sptr - 1) << 30)) & + ((*(sptr) >> 1) | (*(sptr - 1) << 31)) & + (*sptr) & + ((*(sptr) << 1) | (*(sptr + 1) >> 31)); + } + } +} + +static void +fdilate_3_3(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; + + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = ((*(sptr) << 2) | (*(sptr + 1) >> 30)) | + ((*(sptr) << 1) | (*(sptr + 1) >> 31)) | + (*sptr) | + ((*(sptr) >> 1) | (*(sptr - 1) << 31)) | + ((*(sptr) >> 2) | (*(sptr - 1) << 30)); + } + } +} + +static void +ferode_3_3(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; + + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = ((*(sptr) >> 2) | (*(sptr - 1) << 30)) & + ((*(sptr) >> 1) | (*(sptr - 1) << 31)) & + (*sptr) & + ((*(sptr) << 1) | (*(sptr + 1) >> 31)) & + ((*(sptr) << 2) | (*(sptr + 1) >> 30)); + } + } +} + +static void +fdilate_3_4(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; + + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = ((*(sptr) << 3) | (*(sptr + 1) >> 29)) | + ((*(sptr) << 2) | (*(sptr + 1) >> 30)) | + ((*(sptr) << 1) | (*(sptr + 1) >> 31)) | + (*sptr) | + ((*(sptr) >> 1) | (*(sptr - 1) << 31)) | + ((*(sptr) >> 2) | (*(sptr - 1) << 30)); + } + } +} + +static void +ferode_3_4(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; + + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = ((*(sptr) >> 3) | (*(sptr - 1) << 29)) & + ((*(sptr) >> 2) | (*(sptr - 1) << 30)) & + ((*(sptr) >> 1) | (*(sptr - 1) << 31)) & + (*sptr) & + ((*(sptr) << 1) | (*(sptr + 1) >> 31)) & + ((*(sptr) << 2) | (*(sptr + 1) >> 30)); + } + } +} + +static void +fdilate_3_5(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; + + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = ((*(sptr) << 3) | (*(sptr + 1) >> 29)) | + ((*(sptr) << 2) | (*(sptr + 1) >> 30)) | + ((*(sptr) << 1) | (*(sptr + 1) >> 31)) | + (*sptr) | + ((*(sptr) >> 1) | (*(sptr - 1) << 31)) | + ((*(sptr) >> 2) | (*(sptr - 1) << 30)) | + ((*(sptr) >> 3) | (*(sptr - 1) << 29)); + } + } +} + +static void +ferode_3_5(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; + + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = ((*(sptr) >> 3) | (*(sptr - 1) << 29)) & + ((*(sptr) >> 2) | (*(sptr - 1) << 30)) & + ((*(sptr) >> 1) | (*(sptr - 1) << 31)) & + (*sptr) & + ((*(sptr) << 1) | (*(sptr + 1) >> 31)) & + ((*(sptr) << 2) | (*(sptr + 1) >> 30)) & + ((*(sptr) << 3) | (*(sptr + 1) >> 29)); + } + } +} + +static void +fdilate_3_6(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; + + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = ((*(sptr) << 4) | (*(sptr + 1) >> 28)) | + ((*(sptr) << 3) | (*(sptr + 1) >> 29)) | + ((*(sptr) << 2) | (*(sptr + 1) >> 30)) | + ((*(sptr) << 1) | (*(sptr + 1) >> 31)) | + (*sptr) | + ((*(sptr) >> 1) | (*(sptr - 1) << 31)) | + ((*(sptr) >> 2) | (*(sptr - 1) << 30)) | + ((*(sptr) >> 3) | (*(sptr - 1) << 29)); + } + } +} + +static void +ferode_3_6(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; + + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = ((*(sptr) >> 4) | (*(sptr - 1) << 28)) & + ((*(sptr) >> 3) | (*(sptr - 1) << 29)) & + ((*(sptr) >> 2) | (*(sptr - 1) << 30)) & + ((*(sptr) >> 1) | (*(sptr - 1) << 31)) & + (*sptr) & + ((*(sptr) << 1) | (*(sptr + 1) >> 31)) & + ((*(sptr) << 2) | (*(sptr + 1) >> 30)) & + ((*(sptr) << 3) | (*(sptr + 1) >> 29)); + } + } +} + +static void +fdilate_3_7(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; + + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = ((*(sptr) << 4) | (*(sptr + 1) >> 28)) | + ((*(sptr) << 3) | (*(sptr + 1) >> 29)) | + ((*(sptr) << 2) | (*(sptr + 1) >> 30)) | + ((*(sptr) << 1) | (*(sptr + 1) >> 31)) | + (*sptr) | + ((*(sptr) >> 1) | (*(sptr - 1) << 31)) | + ((*(sptr) >> 2) | (*(sptr - 1) << 30)) | + ((*(sptr) >> 3) | (*(sptr - 1) << 29)) | + ((*(sptr) >> 4) | (*(sptr - 1) << 28)); + } + } +} + +static void +ferode_3_7(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; + + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = ((*(sptr) >> 4) | (*(sptr - 1) << 28)) & + ((*(sptr) >> 3) | (*(sptr - 1) << 29)) & + ((*(sptr) >> 2) | (*(sptr - 1) << 30)) & + ((*(sptr) >> 1) | (*(sptr - 1) << 31)) & + (*sptr) & + ((*(sptr) << 1) | (*(sptr + 1) >> 31)) & + ((*(sptr) << 2) | (*(sptr + 1) >> 30)) & + ((*(sptr) << 3) | (*(sptr + 1) >> 29)) & + ((*(sptr) << 4) | (*(sptr + 1) >> 28)); + } + } +} + +static void +fdilate_3_8(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; + + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = ((*(sptr) << 5) | (*(sptr + 1) >> 27)) | + ((*(sptr) << 4) | (*(sptr + 1) >> 28)) | + ((*(sptr) << 3) | (*(sptr + 1) >> 29)) | + ((*(sptr) << 2) | (*(sptr + 1) >> 30)) | + ((*(sptr) << 1) | (*(sptr + 1) >> 31)) | + (*sptr) | + ((*(sptr) >> 1) | (*(sptr - 1) << 31)) | + ((*(sptr) >> 2) | (*(sptr - 1) << 30)) | + ((*(sptr) >> 3) | (*(sptr - 1) << 29)) | + ((*(sptr) >> 4) | (*(sptr - 1) << 28)); + } + } +} + +static void +ferode_3_8(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; + + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = ((*(sptr) >> 5) | (*(sptr - 1) << 27)) & + ((*(sptr) >> 4) | (*(sptr - 1) << 28)) & + ((*(sptr) >> 3) | (*(sptr - 1) << 29)) & + ((*(sptr) >> 2) | (*(sptr - 1) << 30)) & + ((*(sptr) >> 1) | (*(sptr - 1) << 31)) & + (*sptr) & + ((*(sptr) << 1) | (*(sptr + 1) >> 31)) & + ((*(sptr) << 2) | (*(sptr + 1) >> 30)) & + ((*(sptr) << 3) | (*(sptr + 1) >> 29)) & + ((*(sptr) << 4) | (*(sptr + 1) >> 28)); + } + } +} + +static void +fdilate_3_9(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; + + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = ((*(sptr) << 5) | (*(sptr + 1) >> 27)) | + ((*(sptr) << 4) | (*(sptr + 1) >> 28)) | + ((*(sptr) << 3) | (*(sptr + 1) >> 29)) | + ((*(sptr) << 2) | (*(sptr + 1) >> 30)) | + ((*(sptr) << 1) | (*(sptr + 1) >> 31)) | + (*sptr) | + ((*(sptr) >> 1) | (*(sptr - 1) << 31)) | + ((*(sptr) >> 2) | (*(sptr - 1) << 30)) | + ((*(sptr) >> 3) | (*(sptr - 1) << 29)) | + ((*(sptr) >> 4) | (*(sptr - 1) << 28)) | + ((*(sptr) >> 5) | (*(sptr - 1) << 27)); + } + } +} + +static void +ferode_3_9(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; + + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = ((*(sptr) >> 5) | (*(sptr - 1) << 27)) & + ((*(sptr) >> 4) | (*(sptr - 1) << 28)) & + ((*(sptr) >> 3) | (*(sptr - 1) << 29)) & + ((*(sptr) >> 2) | (*(sptr - 1) << 30)) & + ((*(sptr) >> 1) | (*(sptr - 1) << 31)) & + (*sptr) & + ((*(sptr) << 1) | (*(sptr + 1) >> 31)) & + ((*(sptr) << 2) | (*(sptr + 1) >> 30)) & + ((*(sptr) << 3) | (*(sptr + 1) >> 29)) & + ((*(sptr) << 4) | (*(sptr + 1) >> 28)) & + ((*(sptr) << 5) | (*(sptr + 1) >> 27)); + } + } +} + +static void +fdilate_3_10(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; + + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = ((*(sptr) << 6) | (*(sptr + 1) >> 26)) | + ((*(sptr) << 5) | (*(sptr + 1) >> 27)) | + ((*(sptr) << 4) | (*(sptr + 1) >> 28)) | + ((*(sptr) << 3) | (*(sptr + 1) >> 29)) | + ((*(sptr) << 2) | (*(sptr + 1) >> 30)) | + ((*(sptr) << 1) | (*(sptr + 1) >> 31)) | + (*sptr) | + ((*(sptr) >> 1) | (*(sptr - 1) << 31)) | + ((*(sptr) >> 2) | (*(sptr - 1) << 30)) | + ((*(sptr) >> 3) | (*(sptr - 1) << 29)) | + ((*(sptr) >> 4) | (*(sptr - 1) << 28)) | + ((*(sptr) >> 5) | (*(sptr - 1) << 27)); + } + } +} + +static void +ferode_3_10(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; + + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = ((*(sptr) >> 6) | (*(sptr - 1) << 26)) & + ((*(sptr) >> 5) | (*(sptr - 1) << 27)) & + ((*(sptr) >> 4) | (*(sptr - 1) << 28)) & + ((*(sptr) >> 3) | (*(sptr - 1) << 29)) & + ((*(sptr) >> 2) | (*(sptr - 1) << 30)) & + ((*(sptr) >> 1) | (*(sptr - 1) << 31)) & + (*sptr) & + ((*(sptr) << 1) | (*(sptr + 1) >> 31)) & + ((*(sptr) << 2) | (*(sptr + 1) >> 30)) & + ((*(sptr) << 3) | (*(sptr + 1) >> 29)) & + ((*(sptr) << 4) | (*(sptr + 1) >> 28)) & + ((*(sptr) << 5) | (*(sptr + 1) >> 27)); + } + } +} + +static void +fdilate_3_11(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; + + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = ((*(sptr) << 6) | (*(sptr + 1) >> 26)) | + ((*(sptr) << 5) | (*(sptr + 1) >> 27)) | + ((*(sptr) << 4) | (*(sptr + 1) >> 28)) | + ((*(sptr) << 3) | (*(sptr + 1) >> 29)) | + ((*(sptr) << 2) | (*(sptr + 1) >> 30)) | + ((*(sptr) << 1) | (*(sptr + 1) >> 31)) | + (*sptr) | + ((*(sptr) >> 1) | (*(sptr - 1) << 31)) | + ((*(sptr) >> 2) | (*(sptr - 1) << 30)) | + ((*(sptr) >> 3) | (*(sptr - 1) << 29)) | + ((*(sptr) >> 4) | (*(sptr - 1) << 28)) | + ((*(sptr) >> 5) | (*(sptr - 1) << 27)) | + ((*(sptr) >> 6) | (*(sptr - 1) << 26)); + } + } +} + +static void +ferode_3_11(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; + + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = ((*(sptr) >> 6) | (*(sptr - 1) << 26)) & + ((*(sptr) >> 5) | (*(sptr - 1) << 27)) & + ((*(sptr) >> 4) | (*(sptr - 1) << 28)) & + ((*(sptr) >> 3) | (*(sptr - 1) << 29)) & + ((*(sptr) >> 2) | (*(sptr - 1) << 30)) & + ((*(sptr) >> 1) | (*(sptr - 1) << 31)) & + (*sptr) & + ((*(sptr) << 1) | (*(sptr + 1) >> 31)) & + ((*(sptr) << 2) | (*(sptr + 1) >> 30)) & + ((*(sptr) << 3) | (*(sptr + 1) >> 29)) & + ((*(sptr) << 4) | (*(sptr + 1) >> 28)) & + ((*(sptr) << 5) | (*(sptr + 1) >> 27)) & + ((*(sptr) << 6) | (*(sptr + 1) >> 26)); + } + } +} + +static void +fdilate_3_12(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; + + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = ((*(sptr) << 7) | (*(sptr + 1) >> 25)) | + ((*(sptr) << 6) | (*(sptr + 1) >> 26)) | + ((*(sptr) << 5) | (*(sptr + 1) >> 27)) | + ((*(sptr) << 4) | (*(sptr + 1) >> 28)) | + ((*(sptr) << 3) | (*(sptr + 1) >> 29)) | + ((*(sptr) << 2) | (*(sptr + 1) >> 30)) | + ((*(sptr) << 1) | (*(sptr + 1) >> 31)) | + (*sptr) | + ((*(sptr) >> 1) | (*(sptr - 1) << 31)) | + ((*(sptr) >> 2) | (*(sptr - 1) << 30)) | + ((*(sptr) >> 3) | (*(sptr - 1) << 29)) | + ((*(sptr) >> 4) | (*(sptr - 1) << 28)) | + ((*(sptr) >> 5) | (*(sptr - 1) << 27)) | + ((*(sptr) >> 6) | (*(sptr - 1) << 26)); + } + } +} + +static void +ferode_3_12(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; + + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = ((*(sptr) >> 7) | (*(sptr - 1) << 25)) & + ((*(sptr) >> 6) | (*(sptr - 1) << 26)) & + ((*(sptr) >> 5) | (*(sptr - 1) << 27)) & + ((*(sptr) >> 4) | (*(sptr - 1) << 28)) & + ((*(sptr) >> 3) | (*(sptr - 1) << 29)) & + ((*(sptr) >> 2) | (*(sptr - 1) << 30)) & + ((*(sptr) >> 1) | (*(sptr - 1) << 31)) & + (*sptr) & + ((*(sptr) << 1) | (*(sptr + 1) >> 31)) & + ((*(sptr) << 2) | (*(sptr + 1) >> 30)) & + ((*(sptr) << 3) | (*(sptr + 1) >> 29)) & + ((*(sptr) << 4) | (*(sptr + 1) >> 28)) & + ((*(sptr) << 5) | (*(sptr + 1) >> 27)) & + ((*(sptr) << 6) | (*(sptr + 1) >> 26)); + } + } +} + +static void +fdilate_3_13(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; + + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = ((*(sptr) << 7) | (*(sptr + 1) >> 25)) | + ((*(sptr) << 6) | (*(sptr + 1) >> 26)) | + ((*(sptr) << 5) | (*(sptr + 1) >> 27)) | + ((*(sptr) << 4) | (*(sptr + 1) >> 28)) | + ((*(sptr) << 3) | (*(sptr + 1) >> 29)) | + ((*(sptr) << 2) | (*(sptr + 1) >> 30)) | + ((*(sptr) << 1) | (*(sptr + 1) >> 31)) | + (*sptr) | + ((*(sptr) >> 1) | (*(sptr - 1) << 31)) | + ((*(sptr) >> 2) | (*(sptr - 1) << 30)) | + ((*(sptr) >> 3) | (*(sptr - 1) << 29)) | + ((*(sptr) >> 4) | (*(sptr - 1) << 28)) | + ((*(sptr) >> 5) | (*(sptr - 1) << 27)) | + ((*(sptr) >> 6) | (*(sptr - 1) << 26)) | + ((*(sptr) >> 7) | (*(sptr - 1) << 25)); + } + } +} + +static void +ferode_3_13(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; + + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = ((*(sptr) >> 7) | (*(sptr - 1) << 25)) & + ((*(sptr) >> 6) | (*(sptr - 1) << 26)) & + ((*(sptr) >> 5) | (*(sptr - 1) << 27)) & + ((*(sptr) >> 4) | (*(sptr - 1) << 28)) & + ((*(sptr) >> 3) | (*(sptr - 1) << 29)) & + ((*(sptr) >> 2) | (*(sptr - 1) << 30)) & + ((*(sptr) >> 1) | (*(sptr - 1) << 31)) & + (*sptr) & + ((*(sptr) << 1) | (*(sptr + 1) >> 31)) & + ((*(sptr) << 2) | (*(sptr + 1) >> 30)) & + ((*(sptr) << 3) | (*(sptr + 1) >> 29)) & + ((*(sptr) << 4) | (*(sptr + 1) >> 28)) & + ((*(sptr) << 5) | (*(sptr + 1) >> 27)) & + ((*(sptr) << 6) | (*(sptr + 1) >> 26)) & + ((*(sptr) << 7) | (*(sptr + 1) >> 25)); + } + } +} + +static void +fdilate_3_14(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; + + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = ((*(sptr) << 8) | (*(sptr + 1) >> 24)) | + ((*(sptr) << 7) | (*(sptr + 1) >> 25)) | + ((*(sptr) << 6) | (*(sptr + 1) >> 26)) | + ((*(sptr) << 5) | (*(sptr + 1) >> 27)) | + ((*(sptr) << 4) | (*(sptr + 1) >> 28)) | + ((*(sptr) << 3) | (*(sptr + 1) >> 29)) | + ((*(sptr) << 2) | (*(sptr + 1) >> 30)) | + ((*(sptr) << 1) | (*(sptr + 1) >> 31)) | + (*sptr) | + ((*(sptr) >> 1) | (*(sptr - 1) << 31)) | + ((*(sptr) >> 2) | (*(sptr - 1) << 30)) | + ((*(sptr) >> 3) | (*(sptr - 1) << 29)) | + ((*(sptr) >> 4) | (*(sptr - 1) << 28)) | + ((*(sptr) >> 5) | (*(sptr - 1) << 27)) | + ((*(sptr) >> 6) | (*(sptr - 1) << 26)) | + ((*(sptr) >> 7) | (*(sptr - 1) << 25)); + } + } +} + +static void +ferode_3_14(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; + + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = ((*(sptr) >> 8) | (*(sptr - 1) << 24)) & + ((*(sptr) >> 7) | (*(sptr - 1) << 25)) & + ((*(sptr) >> 6) | (*(sptr - 1) << 26)) & + ((*(sptr) >> 5) | (*(sptr - 1) << 27)) & + ((*(sptr) >> 4) | (*(sptr - 1) << 28)) & + ((*(sptr) >> 3) | (*(sptr - 1) << 29)) & + ((*(sptr) >> 2) | (*(sptr - 1) << 30)) & + ((*(sptr) >> 1) | (*(sptr - 1) << 31)) & + (*sptr) & + ((*(sptr) << 1) | (*(sptr + 1) >> 31)) & + ((*(sptr) << 2) | (*(sptr + 1) >> 30)) & + ((*(sptr) << 3) | (*(sptr + 1) >> 29)) & + ((*(sptr) << 4) | (*(sptr + 1) >> 28)) & + ((*(sptr) << 5) | (*(sptr + 1) >> 27)) & + ((*(sptr) << 6) | (*(sptr + 1) >> 26)) & + ((*(sptr) << 7) | (*(sptr + 1) >> 25)); + } + } +} + +static void +fdilate_3_15(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; + + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = ((*(sptr) << 8) | (*(sptr + 1) >> 24)) | + ((*(sptr) << 7) | (*(sptr + 1) >> 25)) | + ((*(sptr) << 6) | (*(sptr + 1) >> 26)) | + ((*(sptr) << 5) | (*(sptr + 1) >> 27)) | + ((*(sptr) << 4) | (*(sptr + 1) >> 28)) | + ((*(sptr) << 3) | (*(sptr + 1) >> 29)) | + ((*(sptr) << 2) | (*(sptr + 1) >> 30)) | + ((*(sptr) << 1) | (*(sptr + 1) >> 31)) | + (*sptr) | + ((*(sptr) >> 1) | (*(sptr - 1) << 31)) | + ((*(sptr) >> 2) | (*(sptr - 1) << 30)) | + ((*(sptr) >> 3) | (*(sptr - 1) << 29)) | + ((*(sptr) >> 4) | (*(sptr - 1) << 28)) | + ((*(sptr) >> 5) | (*(sptr - 1) << 27)) | + ((*(sptr) >> 6) | (*(sptr - 1) << 26)) | + ((*(sptr) >> 7) | (*(sptr - 1) << 25)) | + ((*(sptr) >> 8) | (*(sptr - 1) << 24)); + } + } +} + +static void +ferode_3_15(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; + + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = ((*(sptr) >> 8) | (*(sptr - 1) << 24)) & + ((*(sptr) >> 7) | (*(sptr - 1) << 25)) & + ((*(sptr) >> 6) | (*(sptr - 1) << 26)) & + ((*(sptr) >> 5) | (*(sptr - 1) << 27)) & + ((*(sptr) >> 4) | (*(sptr - 1) << 28)) & + ((*(sptr) >> 3) | (*(sptr - 1) << 29)) & + ((*(sptr) >> 2) | (*(sptr - 1) << 30)) & + ((*(sptr) >> 1) | (*(sptr - 1) << 31)) & + (*sptr) & + ((*(sptr) << 1) | (*(sptr + 1) >> 31)) & + ((*(sptr) << 2) | (*(sptr + 1) >> 30)) & + ((*(sptr) << 3) | (*(sptr + 1) >> 29)) & + ((*(sptr) << 4) | (*(sptr + 1) >> 28)) & + ((*(sptr) << 5) | (*(sptr + 1) >> 27)) & + ((*(sptr) << 6) | (*(sptr + 1) >> 26)) & + ((*(sptr) << 7) | (*(sptr + 1) >> 25)) & + ((*(sptr) << 8) | (*(sptr + 1) >> 24)); + } + } +} + +static void +fdilate_3_16(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; + + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = ((*(sptr) << 9) | (*(sptr + 1) >> 23)) | + ((*(sptr) << 8) | (*(sptr + 1) >> 24)) | + ((*(sptr) << 7) | (*(sptr + 1) >> 25)) | + ((*(sptr) << 6) | (*(sptr + 1) >> 26)) | + ((*(sptr) << 5) | (*(sptr + 1) >> 27)) | + ((*(sptr) << 4) | (*(sptr + 1) >> 28)) | + ((*(sptr) << 3) | (*(sptr + 1) >> 29)) | + ((*(sptr) << 2) | (*(sptr + 1) >> 30)) | + ((*(sptr) << 1) | (*(sptr + 1) >> 31)) | + (*sptr) | + ((*(sptr) >> 1) | (*(sptr - 1) << 31)) | + ((*(sptr) >> 2) | (*(sptr - 1) << 30)) | + ((*(sptr) >> 3) | (*(sptr - 1) << 29)) | + ((*(sptr) >> 4) | (*(sptr - 1) << 28)) | + ((*(sptr) >> 5) | (*(sptr - 1) << 27)) | + ((*(sptr) >> 6) | (*(sptr - 1) << 26)) | + ((*(sptr) >> 7) | (*(sptr - 1) << 25)) | + ((*(sptr) >> 8) | (*(sptr - 1) << 24)); + } + } +} + +static void +ferode_3_16(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; + + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = ((*(sptr) >> 9) | (*(sptr - 1) << 23)) & + ((*(sptr) >> 8) | (*(sptr - 1) << 24)) & + ((*(sptr) >> 7) | (*(sptr - 1) << 25)) & + ((*(sptr) >> 6) | (*(sptr - 1) << 26)) & + ((*(sptr) >> 5) | (*(sptr - 1) << 27)) & + ((*(sptr) >> 4) | (*(sptr - 1) << 28)) & + ((*(sptr) >> 3) | (*(sptr - 1) << 29)) & + ((*(sptr) >> 2) | (*(sptr - 1) << 30)) & + ((*(sptr) >> 1) | (*(sptr - 1) << 31)) & + (*sptr) & + ((*(sptr) << 1) | (*(sptr + 1) >> 31)) & + ((*(sptr) << 2) | (*(sptr + 1) >> 30)) & + ((*(sptr) << 3) | (*(sptr + 1) >> 29)) & + ((*(sptr) << 4) | (*(sptr + 1) >> 28)) & + ((*(sptr) << 5) | (*(sptr + 1) >> 27)) & + ((*(sptr) << 6) | (*(sptr + 1) >> 26)) & + ((*(sptr) << 7) | (*(sptr + 1) >> 25)) & + ((*(sptr) << 8) | (*(sptr + 1) >> 24)); + } + } +} + +static void +fdilate_3_17(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; + + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = ((*(sptr) << 9) | (*(sptr + 1) >> 23)) | + ((*(sptr) << 8) | (*(sptr + 1) >> 24)) | + ((*(sptr) << 7) | (*(sptr + 1) >> 25)) | + ((*(sptr) << 6) | (*(sptr + 1) >> 26)) | + ((*(sptr) << 5) | (*(sptr + 1) >> 27)) | + ((*(sptr) << 4) | (*(sptr + 1) >> 28)) | + ((*(sptr) << 3) | (*(sptr + 1) >> 29)) | + ((*(sptr) << 2) | (*(sptr + 1) >> 30)) | + ((*(sptr) << 1) | (*(sptr + 1) >> 31)) | + (*sptr) | + ((*(sptr) >> 1) | (*(sptr - 1) << 31)) | + ((*(sptr) >> 2) | (*(sptr - 1) << 30)) | + ((*(sptr) >> 3) | (*(sptr - 1) << 29)) | + ((*(sptr) >> 4) | (*(sptr - 1) << 28)) | + ((*(sptr) >> 5) | (*(sptr - 1) << 27)) | + ((*(sptr) >> 6) | (*(sptr - 1) << 26)) | + ((*(sptr) >> 7) | (*(sptr - 1) << 25)) | + ((*(sptr) >> 8) | (*(sptr - 1) << 24)) | + ((*(sptr) >> 9) | (*(sptr - 1) << 23)); + } + } +} + +static void +ferode_3_17(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; + + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = ((*(sptr) >> 9) | (*(sptr - 1) << 23)) & + ((*(sptr) >> 8) | (*(sptr - 1) << 24)) & + ((*(sptr) >> 7) | (*(sptr - 1) << 25)) & + ((*(sptr) >> 6) | (*(sptr - 1) << 26)) & + ((*(sptr) >> 5) | (*(sptr - 1) << 27)) & + ((*(sptr) >> 4) | (*(sptr - 1) << 28)) & + ((*(sptr) >> 3) | (*(sptr - 1) << 29)) & + ((*(sptr) >> 2) | (*(sptr - 1) << 30)) & + ((*(sptr) >> 1) | (*(sptr - 1) << 31)) & + (*sptr) & + ((*(sptr) << 1) | (*(sptr + 1) >> 31)) & + ((*(sptr) << 2) | (*(sptr + 1) >> 30)) & + ((*(sptr) << 3) | (*(sptr + 1) >> 29)) & + ((*(sptr) << 4) | (*(sptr + 1) >> 28)) & + ((*(sptr) << 5) | (*(sptr + 1) >> 27)) & + ((*(sptr) << 6) | (*(sptr + 1) >> 26)) & + ((*(sptr) << 7) | (*(sptr + 1) >> 25)) & + ((*(sptr) << 8) | (*(sptr + 1) >> 24)) & + ((*(sptr) << 9) | (*(sptr + 1) >> 23)); + } + } +} + +static void +fdilate_3_18(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; + + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = ((*(sptr) << 10) | (*(sptr + 1) >> 22)) | + ((*(sptr) << 9) | (*(sptr + 1) >> 23)) | + ((*(sptr) << 8) | (*(sptr + 1) >> 24)) | + ((*(sptr) << 7) | (*(sptr + 1) >> 25)) | + ((*(sptr) << 6) | (*(sptr + 1) >> 26)) | + ((*(sptr) << 5) | (*(sptr + 1) >> 27)) | + ((*(sptr) << 4) | (*(sptr + 1) >> 28)) | + ((*(sptr) << 3) | (*(sptr + 1) >> 29)) | + ((*(sptr) << 2) | (*(sptr + 1) >> 30)) | + ((*(sptr) << 1) | (*(sptr + 1) >> 31)) | + (*sptr) | + ((*(sptr) >> 1) | (*(sptr - 1) << 31)) | + ((*(sptr) >> 2) | (*(sptr - 1) << 30)) | + ((*(sptr) >> 3) | (*(sptr - 1) << 29)) | + ((*(sptr) >> 4) | (*(sptr - 1) << 28)) | + ((*(sptr) >> 5) | (*(sptr - 1) << 27)) | + ((*(sptr) >> 6) | (*(sptr - 1) << 26)) | + ((*(sptr) >> 7) | (*(sptr - 1) << 25)) | + ((*(sptr) >> 8) | (*(sptr - 1) << 24)) | + ((*(sptr) >> 9) | (*(sptr - 1) << 23)); + } + } +} + +static void +ferode_3_18(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; + + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = ((*(sptr) >> 10) | (*(sptr - 1) << 22)) & + ((*(sptr) >> 9) | (*(sptr - 1) << 23)) & + ((*(sptr) >> 8) | (*(sptr - 1) << 24)) & + ((*(sptr) >> 7) | (*(sptr - 1) << 25)) & + ((*(sptr) >> 6) | (*(sptr - 1) << 26)) & + ((*(sptr) >> 5) | (*(sptr - 1) << 27)) & + ((*(sptr) >> 4) | (*(sptr - 1) << 28)) & + ((*(sptr) >> 3) | (*(sptr - 1) << 29)) & + ((*(sptr) >> 2) | (*(sptr - 1) << 30)) & + ((*(sptr) >> 1) | (*(sptr - 1) << 31)) & + (*sptr) & + ((*(sptr) << 1) | (*(sptr + 1) >> 31)) & + ((*(sptr) << 2) | (*(sptr + 1) >> 30)) & + ((*(sptr) << 3) | (*(sptr + 1) >> 29)) & + ((*(sptr) << 4) | (*(sptr + 1) >> 28)) & + ((*(sptr) << 5) | (*(sptr + 1) >> 27)) & + ((*(sptr) << 6) | (*(sptr + 1) >> 26)) & + ((*(sptr) << 7) | (*(sptr + 1) >> 25)) & + ((*(sptr) << 8) | (*(sptr + 1) >> 24)) & + ((*(sptr) << 9) | (*(sptr + 1) >> 23)); + } + } +} + +static void +fdilate_3_19(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; + + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = ((*(sptr) << 10) | (*(sptr + 1) >> 22)) | + ((*(sptr) << 9) | (*(sptr + 1) >> 23)) | + ((*(sptr) << 8) | (*(sptr + 1) >> 24)) | + ((*(sptr) << 7) | (*(sptr + 1) >> 25)) | + ((*(sptr) << 6) | (*(sptr + 1) >> 26)) | + ((*(sptr) << 5) | (*(sptr + 1) >> 27)) | + ((*(sptr) << 4) | (*(sptr + 1) >> 28)) | + ((*(sptr) << 3) | (*(sptr + 1) >> 29)) | + ((*(sptr) << 2) | (*(sptr + 1) >> 30)) | + ((*(sptr) << 1) | (*(sptr + 1) >> 31)) | + (*sptr) | + ((*(sptr) >> 1) | (*(sptr - 1) << 31)) | + ((*(sptr) >> 2) | (*(sptr - 1) << 30)) | + ((*(sptr) >> 3) | (*(sptr - 1) << 29)) | + ((*(sptr) >> 4) | (*(sptr - 1) << 28)) | + ((*(sptr) >> 5) | (*(sptr - 1) << 27)) | + ((*(sptr) >> 6) | (*(sptr - 1) << 26)) | + ((*(sptr) >> 7) | (*(sptr - 1) << 25)) | + ((*(sptr) >> 8) | (*(sptr - 1) << 24)) | + ((*(sptr) >> 9) | (*(sptr - 1) << 23)) | + ((*(sptr) >> 10) | (*(sptr - 1) << 22)); + } + } +} + +static void +ferode_3_19(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; + + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = ((*(sptr) >> 10) | (*(sptr - 1) << 22)) & + ((*(sptr) >> 9) | (*(sptr - 1) << 23)) & + ((*(sptr) >> 8) | (*(sptr - 1) << 24)) & + ((*(sptr) >> 7) | (*(sptr - 1) << 25)) & + ((*(sptr) >> 6) | (*(sptr - 1) << 26)) & + ((*(sptr) >> 5) | (*(sptr - 1) << 27)) & + ((*(sptr) >> 4) | (*(sptr - 1) << 28)) & + ((*(sptr) >> 3) | (*(sptr - 1) << 29)) & + ((*(sptr) >> 2) | (*(sptr - 1) << 30)) & + ((*(sptr) >> 1) | (*(sptr - 1) << 31)) & + (*sptr) & + ((*(sptr) << 1) | (*(sptr + 1) >> 31)) & + ((*(sptr) << 2) | (*(sptr + 1) >> 30)) & + ((*(sptr) << 3) | (*(sptr + 1) >> 29)) & + ((*(sptr) << 4) | (*(sptr + 1) >> 28)) & + ((*(sptr) << 5) | (*(sptr + 1) >> 27)) & + ((*(sptr) << 6) | (*(sptr + 1) >> 26)) & + ((*(sptr) << 7) | (*(sptr + 1) >> 25)) & + ((*(sptr) << 8) | (*(sptr + 1) >> 24)) & + ((*(sptr) << 9) | (*(sptr + 1) >> 23)) & + ((*(sptr) << 10) | (*(sptr + 1) >> 22)); + } + } +} + +static void +fdilate_3_20(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; + + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = ((*(sptr) << 11) | (*(sptr + 1) >> 21)) | + ((*(sptr) << 10) | (*(sptr + 1) >> 22)) | + ((*(sptr) << 9) | (*(sptr + 1) >> 23)) | + ((*(sptr) << 8) | (*(sptr + 1) >> 24)) | + ((*(sptr) << 7) | (*(sptr + 1) >> 25)) | + ((*(sptr) << 6) | (*(sptr + 1) >> 26)) | + ((*(sptr) << 5) | (*(sptr + 1) >> 27)) | + ((*(sptr) << 4) | (*(sptr + 1) >> 28)) | + ((*(sptr) << 3) | (*(sptr + 1) >> 29)) | + ((*(sptr) << 2) | (*(sptr + 1) >> 30)) | + ((*(sptr) << 1) | (*(sptr + 1) >> 31)) | + (*sptr) | + ((*(sptr) >> 1) | (*(sptr - 1) << 31)) | + ((*(sptr) >> 2) | (*(sptr - 1) << 30)) | + ((*(sptr) >> 3) | (*(sptr - 1) << 29)) | + ((*(sptr) >> 4) | (*(sptr - 1) << 28)) | + ((*(sptr) >> 5) | (*(sptr - 1) << 27)) | + ((*(sptr) >> 6) | (*(sptr - 1) << 26)) | + ((*(sptr) >> 7) | (*(sptr - 1) << 25)) | + ((*(sptr) >> 8) | (*(sptr - 1) << 24)) | + ((*(sptr) >> 9) | (*(sptr - 1) << 23)) | + ((*(sptr) >> 10) | (*(sptr - 1) << 22)); + } + } +} + +static void +ferode_3_20(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; + + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = ((*(sptr) >> 11) | (*(sptr - 1) << 21)) & + ((*(sptr) >> 10) | (*(sptr - 1) << 22)) & + ((*(sptr) >> 9) | (*(sptr - 1) << 23)) & + ((*(sptr) >> 8) | (*(sptr - 1) << 24)) & + ((*(sptr) >> 7) | (*(sptr - 1) << 25)) & + ((*(sptr) >> 6) | (*(sptr - 1) << 26)) & + ((*(sptr) >> 5) | (*(sptr - 1) << 27)) & + ((*(sptr) >> 4) | (*(sptr - 1) << 28)) & + ((*(sptr) >> 3) | (*(sptr - 1) << 29)) & + ((*(sptr) >> 2) | (*(sptr - 1) << 30)) & + ((*(sptr) >> 1) | (*(sptr - 1) << 31)) & + (*sptr) & + ((*(sptr) << 1) | (*(sptr + 1) >> 31)) & + ((*(sptr) << 2) | (*(sptr + 1) >> 30)) & + ((*(sptr) << 3) | (*(sptr + 1) >> 29)) & + ((*(sptr) << 4) | (*(sptr + 1) >> 28)) & + ((*(sptr) << 5) | (*(sptr + 1) >> 27)) & + ((*(sptr) << 6) | (*(sptr + 1) >> 26)) & + ((*(sptr) << 7) | (*(sptr + 1) >> 25)) & + ((*(sptr) << 8) | (*(sptr + 1) >> 24)) & + ((*(sptr) << 9) | (*(sptr + 1) >> 23)) & + ((*(sptr) << 10) | (*(sptr + 1) >> 22)); + } + } +} + +static void +fdilate_3_21(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; + + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = ((*(sptr) << 11) | (*(sptr + 1) >> 21)) | + ((*(sptr) << 10) | (*(sptr + 1) >> 22)) | + ((*(sptr) << 9) | (*(sptr + 1) >> 23)) | + ((*(sptr) << 8) | (*(sptr + 1) >> 24)) | + ((*(sptr) << 7) | (*(sptr + 1) >> 25)) | + ((*(sptr) << 6) | (*(sptr + 1) >> 26)) | + ((*(sptr) << 5) | (*(sptr + 1) >> 27)) | + ((*(sptr) << 4) | (*(sptr + 1) >> 28)) | + ((*(sptr) << 3) | (*(sptr + 1) >> 29)) | + ((*(sptr) << 2) | (*(sptr + 1) >> 30)) | + ((*(sptr) << 1) | (*(sptr + 1) >> 31)) | + (*sptr) | + ((*(sptr) >> 1) | (*(sptr - 1) << 31)) | + ((*(sptr) >> 2) | (*(sptr - 1) << 30)) | + ((*(sptr) >> 3) | (*(sptr - 1) << 29)) | + ((*(sptr) >> 4) | (*(sptr - 1) << 28)) | + ((*(sptr) >> 5) | (*(sptr - 1) << 27)) | + ((*(sptr) >> 6) | (*(sptr - 1) << 26)) | + ((*(sptr) >> 7) | (*(sptr - 1) << 25)) | + ((*(sptr) >> 8) | (*(sptr - 1) << 24)) | + ((*(sptr) >> 9) | (*(sptr - 1) << 23)) | + ((*(sptr) >> 10) | (*(sptr - 1) << 22)) | + ((*(sptr) >> 11) | (*(sptr - 1) << 21)); + } + } +} + +static void +ferode_3_21(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; + + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = ((*(sptr) >> 11) | (*(sptr - 1) << 21)) & + ((*(sptr) >> 10) | (*(sptr - 1) << 22)) & + ((*(sptr) >> 9) | (*(sptr - 1) << 23)) & + ((*(sptr) >> 8) | (*(sptr - 1) << 24)) & + ((*(sptr) >> 7) | (*(sptr - 1) << 25)) & + ((*(sptr) >> 6) | (*(sptr - 1) << 26)) & + ((*(sptr) >> 5) | (*(sptr - 1) << 27)) & + ((*(sptr) >> 4) | (*(sptr - 1) << 28)) & + ((*(sptr) >> 3) | (*(sptr - 1) << 29)) & + ((*(sptr) >> 2) | (*(sptr - 1) << 30)) & + ((*(sptr) >> 1) | (*(sptr - 1) << 31)) & + (*sptr) & + ((*(sptr) << 1) | (*(sptr + 1) >> 31)) & + ((*(sptr) << 2) | (*(sptr + 1) >> 30)) & + ((*(sptr) << 3) | (*(sptr + 1) >> 29)) & + ((*(sptr) << 4) | (*(sptr + 1) >> 28)) & + ((*(sptr) << 5) | (*(sptr + 1) >> 27)) & + ((*(sptr) << 6) | (*(sptr + 1) >> 26)) & + ((*(sptr) << 7) | (*(sptr + 1) >> 25)) & + ((*(sptr) << 8) | (*(sptr + 1) >> 24)) & + ((*(sptr) << 9) | (*(sptr + 1) >> 23)) & + ((*(sptr) << 10) | (*(sptr + 1) >> 22)) & + ((*(sptr) << 11) | (*(sptr + 1) >> 21)); + } + } +} + +static void +fdilate_3_22(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; + + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = ((*(sptr) << 12) | (*(sptr + 1) >> 20)) | + ((*(sptr) << 11) | (*(sptr + 1) >> 21)) | + ((*(sptr) << 10) | (*(sptr + 1) >> 22)) | + ((*(sptr) << 9) | (*(sptr + 1) >> 23)) | + ((*(sptr) << 8) | (*(sptr + 1) >> 24)) | + ((*(sptr) << 7) | (*(sptr + 1) >> 25)) | + ((*(sptr) << 6) | (*(sptr + 1) >> 26)) | + ((*(sptr) << 5) | (*(sptr + 1) >> 27)) | + ((*(sptr) << 4) | (*(sptr + 1) >> 28)) | + ((*(sptr) << 3) | (*(sptr + 1) >> 29)) | + ((*(sptr) << 2) | (*(sptr + 1) >> 30)) | + ((*(sptr) << 1) | (*(sptr + 1) >> 31)) | + (*sptr) | + ((*(sptr) >> 1) | (*(sptr - 1) << 31)) | + ((*(sptr) >> 2) | (*(sptr - 1) << 30)) | + ((*(sptr) >> 3) | (*(sptr - 1) << 29)) | + ((*(sptr) >> 4) | (*(sptr - 1) << 28)) | + ((*(sptr) >> 5) | (*(sptr - 1) << 27)) | + ((*(sptr) >> 6) | (*(sptr - 1) << 26)) | + ((*(sptr) >> 7) | (*(sptr - 1) << 25)) | + ((*(sptr) >> 8) | (*(sptr - 1) << 24)) | + ((*(sptr) >> 9) | (*(sptr - 1) << 23)) | + ((*(sptr) >> 10) | (*(sptr - 1) << 22)) | + ((*(sptr) >> 11) | (*(sptr - 1) << 21)); + } + } +} + +static void +ferode_3_22(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; + + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = ((*(sptr) >> 12) | (*(sptr - 1) << 20)) & + ((*(sptr) >> 11) | (*(sptr - 1) << 21)) & + ((*(sptr) >> 10) | (*(sptr - 1) << 22)) & + ((*(sptr) >> 9) | (*(sptr - 1) << 23)) & + ((*(sptr) >> 8) | (*(sptr - 1) << 24)) & + ((*(sptr) >> 7) | (*(sptr - 1) << 25)) & + ((*(sptr) >> 6) | (*(sptr - 1) << 26)) & + ((*(sptr) >> 5) | (*(sptr - 1) << 27)) & + ((*(sptr) >> 4) | (*(sptr - 1) << 28)) & + ((*(sptr) >> 3) | (*(sptr - 1) << 29)) & + ((*(sptr) >> 2) | (*(sptr - 1) << 30)) & + ((*(sptr) >> 1) | (*(sptr - 1) << 31)) & + (*sptr) & + ((*(sptr) << 1) | (*(sptr + 1) >> 31)) & + ((*(sptr) << 2) | (*(sptr + 1) >> 30)) & + ((*(sptr) << 3) | (*(sptr + 1) >> 29)) & + ((*(sptr) << 4) | (*(sptr + 1) >> 28)) & + ((*(sptr) << 5) | (*(sptr + 1) >> 27)) & + ((*(sptr) << 6) | (*(sptr + 1) >> 26)) & + ((*(sptr) << 7) | (*(sptr + 1) >> 25)) & + ((*(sptr) << 8) | (*(sptr + 1) >> 24)) & + ((*(sptr) << 9) | (*(sptr + 1) >> 23)) & + ((*(sptr) << 10) | (*(sptr + 1) >> 22)) & + ((*(sptr) << 11) | (*(sptr + 1) >> 21)); + } + } +} + +static void +fdilate_3_23(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; + + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = ((*(sptr) << 12) | (*(sptr + 1) >> 20)) | + ((*(sptr) << 11) | (*(sptr + 1) >> 21)) | + ((*(sptr) << 10) | (*(sptr + 1) >> 22)) | + ((*(sptr) << 9) | (*(sptr + 1) >> 23)) | + ((*(sptr) << 8) | (*(sptr + 1) >> 24)) | + ((*(sptr) << 7) | (*(sptr + 1) >> 25)) | + ((*(sptr) << 6) | (*(sptr + 1) >> 26)) | + ((*(sptr) << 5) | (*(sptr + 1) >> 27)) | + ((*(sptr) << 4) | (*(sptr + 1) >> 28)) | + ((*(sptr) << 3) | (*(sptr + 1) >> 29)) | + ((*(sptr) << 2) | (*(sptr + 1) >> 30)) | + ((*(sptr) << 1) | (*(sptr + 1) >> 31)) | + (*sptr) | + ((*(sptr) >> 1) | (*(sptr - 1) << 31)) | + ((*(sptr) >> 2) | (*(sptr - 1) << 30)) | + ((*(sptr) >> 3) | (*(sptr - 1) << 29)) | + ((*(sptr) >> 4) | (*(sptr - 1) << 28)) | + ((*(sptr) >> 5) | (*(sptr - 1) << 27)) | + ((*(sptr) >> 6) | (*(sptr - 1) << 26)) | + ((*(sptr) >> 7) | (*(sptr - 1) << 25)) | + ((*(sptr) >> 8) | (*(sptr - 1) << 24)) | + ((*(sptr) >> 9) | (*(sptr - 1) << 23)) | + ((*(sptr) >> 10) | (*(sptr - 1) << 22)) | + ((*(sptr) >> 11) | (*(sptr - 1) << 21)) | + ((*(sptr) >> 12) | (*(sptr - 1) << 20)); + } + } +} + +static void +ferode_3_23(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; + + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = ((*(sptr) >> 12) | (*(sptr - 1) << 20)) & + ((*(sptr) >> 11) | (*(sptr - 1) << 21)) & + ((*(sptr) >> 10) | (*(sptr - 1) << 22)) & + ((*(sptr) >> 9) | (*(sptr - 1) << 23)) & + ((*(sptr) >> 8) | (*(sptr - 1) << 24)) & + ((*(sptr) >> 7) | (*(sptr - 1) << 25)) & + ((*(sptr) >> 6) | (*(sptr - 1) << 26)) & + ((*(sptr) >> 5) | (*(sptr - 1) << 27)) & + ((*(sptr) >> 4) | (*(sptr - 1) << 28)) & + ((*(sptr) >> 3) | (*(sptr - 1) << 29)) & + ((*(sptr) >> 2) | (*(sptr - 1) << 30)) & + ((*(sptr) >> 1) | (*(sptr - 1) << 31)) & + (*sptr) & + ((*(sptr) << 1) | (*(sptr + 1) >> 31)) & + ((*(sptr) << 2) | (*(sptr + 1) >> 30)) & + ((*(sptr) << 3) | (*(sptr + 1) >> 29)) & + ((*(sptr) << 4) | (*(sptr + 1) >> 28)) & + ((*(sptr) << 5) | (*(sptr + 1) >> 27)) & + ((*(sptr) << 6) | (*(sptr + 1) >> 26)) & + ((*(sptr) << 7) | (*(sptr + 1) >> 25)) & + ((*(sptr) << 8) | (*(sptr + 1) >> 24)) & + ((*(sptr) << 9) | (*(sptr + 1) >> 23)) & + ((*(sptr) << 10) | (*(sptr + 1) >> 22)) & + ((*(sptr) << 11) | (*(sptr + 1) >> 21)) & + ((*(sptr) << 12) | (*(sptr + 1) >> 20)); + } + } +} + +static void +fdilate_3_24(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; + + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = ((*(sptr) << 13) | (*(sptr + 1) >> 19)) | + ((*(sptr) << 12) | (*(sptr + 1) >> 20)) | + ((*(sptr) << 11) | (*(sptr + 1) >> 21)) | + ((*(sptr) << 10) | (*(sptr + 1) >> 22)) | + ((*(sptr) << 9) | (*(sptr + 1) >> 23)) | + ((*(sptr) << 8) | (*(sptr + 1) >> 24)) | + ((*(sptr) << 7) | (*(sptr + 1) >> 25)) | + ((*(sptr) << 6) | (*(sptr + 1) >> 26)) | + ((*(sptr) << 5) | (*(sptr + 1) >> 27)) | + ((*(sptr) << 4) | (*(sptr + 1) >> 28)) | + ((*(sptr) << 3) | (*(sptr + 1) >> 29)) | + ((*(sptr) << 2) | (*(sptr + 1) >> 30)) | + ((*(sptr) << 1) | (*(sptr + 1) >> 31)) | + (*sptr) | + ((*(sptr) >> 1) | (*(sptr - 1) << 31)) | + ((*(sptr) >> 2) | (*(sptr - 1) << 30)) | + ((*(sptr) >> 3) | (*(sptr - 1) << 29)) | + ((*(sptr) >> 4) | (*(sptr - 1) << 28)) | + ((*(sptr) >> 5) | (*(sptr - 1) << 27)) | + ((*(sptr) >> 6) | (*(sptr - 1) << 26)) | + ((*(sptr) >> 7) | (*(sptr - 1) << 25)) | + ((*(sptr) >> 8) | (*(sptr - 1) << 24)) | + ((*(sptr) >> 9) | (*(sptr - 1) << 23)) | + ((*(sptr) >> 10) | (*(sptr - 1) << 22)) | + ((*(sptr) >> 11) | (*(sptr - 1) << 21)) | + ((*(sptr) >> 12) | (*(sptr - 1) << 20)); + } + } +} + +static void +ferode_3_24(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; + + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = ((*(sptr) >> 13) | (*(sptr - 1) << 19)) & + ((*(sptr) >> 12) | (*(sptr - 1) << 20)) & + ((*(sptr) >> 11) | (*(sptr - 1) << 21)) & + ((*(sptr) >> 10) | (*(sptr - 1) << 22)) & + ((*(sptr) >> 9) | (*(sptr - 1) << 23)) & + ((*(sptr) >> 8) | (*(sptr - 1) << 24)) & + ((*(sptr) >> 7) | (*(sptr - 1) << 25)) & + ((*(sptr) >> 6) | (*(sptr - 1) << 26)) & + ((*(sptr) >> 5) | (*(sptr - 1) << 27)) & + ((*(sptr) >> 4) | (*(sptr - 1) << 28)) & + ((*(sptr) >> 3) | (*(sptr - 1) << 29)) & + ((*(sptr) >> 2) | (*(sptr - 1) << 30)) & + ((*(sptr) >> 1) | (*(sptr - 1) << 31)) & + (*sptr) & + ((*(sptr) << 1) | (*(sptr + 1) >> 31)) & + ((*(sptr) << 2) | (*(sptr + 1) >> 30)) & + ((*(sptr) << 3) | (*(sptr + 1) >> 29)) & + ((*(sptr) << 4) | (*(sptr + 1) >> 28)) & + ((*(sptr) << 5) | (*(sptr + 1) >> 27)) & + ((*(sptr) << 6) | (*(sptr + 1) >> 26)) & + ((*(sptr) << 7) | (*(sptr + 1) >> 25)) & + ((*(sptr) << 8) | (*(sptr + 1) >> 24)) & + ((*(sptr) << 9) | (*(sptr + 1) >> 23)) & + ((*(sptr) << 10) | (*(sptr + 1) >> 22)) & + ((*(sptr) << 11) | (*(sptr + 1) >> 21)) & + ((*(sptr) << 12) | (*(sptr + 1) >> 20)); + } + } +} + +static void +fdilate_3_25(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; + + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = ((*(sptr) << 13) | (*(sptr + 1) >> 19)) | + ((*(sptr) << 12) | (*(sptr + 1) >> 20)) | + ((*(sptr) << 11) | (*(sptr + 1) >> 21)) | + ((*(sptr) << 10) | (*(sptr + 1) >> 22)) | + ((*(sptr) << 9) | (*(sptr + 1) >> 23)) | + ((*(sptr) << 8) | (*(sptr + 1) >> 24)) | + ((*(sptr) << 7) | (*(sptr + 1) >> 25)) | + ((*(sptr) << 6) | (*(sptr + 1) >> 26)) | + ((*(sptr) << 5) | (*(sptr + 1) >> 27)) | + ((*(sptr) << 4) | (*(sptr + 1) >> 28)) | + ((*(sptr) << 3) | (*(sptr + 1) >> 29)) | + ((*(sptr) << 2) | (*(sptr + 1) >> 30)) | + ((*(sptr) << 1) | (*(sptr + 1) >> 31)) | + (*sptr) | + ((*(sptr) >> 1) | (*(sptr - 1) << 31)) | + ((*(sptr) >> 2) | (*(sptr - 1) << 30)) | + ((*(sptr) >> 3) | (*(sptr - 1) << 29)) | + ((*(sptr) >> 4) | (*(sptr - 1) << 28)) | + ((*(sptr) >> 5) | (*(sptr - 1) << 27)) | + ((*(sptr) >> 6) | (*(sptr - 1) << 26)) | + ((*(sptr) >> 7) | (*(sptr - 1) << 25)) | + ((*(sptr) >> 8) | (*(sptr - 1) << 24)) | + ((*(sptr) >> 9) | (*(sptr - 1) << 23)) | + ((*(sptr) >> 10) | (*(sptr - 1) << 22)) | + ((*(sptr) >> 11) | (*(sptr - 1) << 21)) | + ((*(sptr) >> 12) | (*(sptr - 1) << 20)) | + ((*(sptr) >> 13) | (*(sptr - 1) << 19)); + } + } +} + +static void +ferode_3_25(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; + + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = ((*(sptr) >> 13) | (*(sptr - 1) << 19)) & + ((*(sptr) >> 12) | (*(sptr - 1) << 20)) & + ((*(sptr) >> 11) | (*(sptr - 1) << 21)) & + ((*(sptr) >> 10) | (*(sptr - 1) << 22)) & + ((*(sptr) >> 9) | (*(sptr - 1) << 23)) & + ((*(sptr) >> 8) | (*(sptr - 1) << 24)) & + ((*(sptr) >> 7) | (*(sptr - 1) << 25)) & + ((*(sptr) >> 6) | (*(sptr - 1) << 26)) & + ((*(sptr) >> 5) | (*(sptr - 1) << 27)) & + ((*(sptr) >> 4) | (*(sptr - 1) << 28)) & + ((*(sptr) >> 3) | (*(sptr - 1) << 29)) & + ((*(sptr) >> 2) | (*(sptr - 1) << 30)) & + ((*(sptr) >> 1) | (*(sptr - 1) << 31)) & + (*sptr) & + ((*(sptr) << 1) | (*(sptr + 1) >> 31)) & + ((*(sptr) << 2) | (*(sptr + 1) >> 30)) & + ((*(sptr) << 3) | (*(sptr + 1) >> 29)) & + ((*(sptr) << 4) | (*(sptr + 1) >> 28)) & + ((*(sptr) << 5) | (*(sptr + 1) >> 27)) & + ((*(sptr) << 6) | (*(sptr + 1) >> 26)) & + ((*(sptr) << 7) | (*(sptr + 1) >> 25)) & + ((*(sptr) << 8) | (*(sptr + 1) >> 24)) & + ((*(sptr) << 9) | (*(sptr + 1) >> 23)) & + ((*(sptr) << 10) | (*(sptr + 1) >> 22)) & + ((*(sptr) << 11) | (*(sptr + 1) >> 21)) & + ((*(sptr) << 12) | (*(sptr + 1) >> 20)) & + ((*(sptr) << 13) | (*(sptr + 1) >> 19)); + } + } +} + +static void +fdilate_3_26(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; + + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = ((*(sptr) << 14) | (*(sptr + 1) >> 18)) | + ((*(sptr) << 13) | (*(sptr + 1) >> 19)) | + ((*(sptr) << 12) | (*(sptr + 1) >> 20)) | + ((*(sptr) << 11) | (*(sptr + 1) >> 21)) | + ((*(sptr) << 10) | (*(sptr + 1) >> 22)) | + ((*(sptr) << 9) | (*(sptr + 1) >> 23)) | + ((*(sptr) << 8) | (*(sptr + 1) >> 24)) | + ((*(sptr) << 7) | (*(sptr + 1) >> 25)) | + ((*(sptr) << 6) | (*(sptr + 1) >> 26)) | + ((*(sptr) << 5) | (*(sptr + 1) >> 27)) | + ((*(sptr) << 4) | (*(sptr + 1) >> 28)) | + ((*(sptr) << 3) | (*(sptr + 1) >> 29)) | + ((*(sptr) << 2) | (*(sptr + 1) >> 30)) | + ((*(sptr) << 1) | (*(sptr + 1) >> 31)) | + (*sptr) | + ((*(sptr) >> 1) | (*(sptr - 1) << 31)) | + ((*(sptr) >> 2) | (*(sptr - 1) << 30)) | + ((*(sptr) >> 3) | (*(sptr - 1) << 29)) | + ((*(sptr) >> 4) | (*(sptr - 1) << 28)) | + ((*(sptr) >> 5) | (*(sptr - 1) << 27)) | + ((*(sptr) >> 6) | (*(sptr - 1) << 26)) | + ((*(sptr) >> 7) | (*(sptr - 1) << 25)) | + ((*(sptr) >> 8) | (*(sptr - 1) << 24)) | + ((*(sptr) >> 9) | (*(sptr - 1) << 23)) | + ((*(sptr) >> 10) | (*(sptr - 1) << 22)) | + ((*(sptr) >> 11) | (*(sptr - 1) << 21)) | + ((*(sptr) >> 12) | (*(sptr - 1) << 20)) | + ((*(sptr) >> 13) | (*(sptr - 1) << 19)); + } + } +} + +static void +ferode_3_26(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; + + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = ((*(sptr) >> 14) | (*(sptr - 1) << 18)) & + ((*(sptr) >> 13) | (*(sptr - 1) << 19)) & + ((*(sptr) >> 12) | (*(sptr - 1) << 20)) & + ((*(sptr) >> 11) | (*(sptr - 1) << 21)) & + ((*(sptr) >> 10) | (*(sptr - 1) << 22)) & + ((*(sptr) >> 9) | (*(sptr - 1) << 23)) & + ((*(sptr) >> 8) | (*(sptr - 1) << 24)) & + ((*(sptr) >> 7) | (*(sptr - 1) << 25)) & + ((*(sptr) >> 6) | (*(sptr - 1) << 26)) & + ((*(sptr) >> 5) | (*(sptr - 1) << 27)) & + ((*(sptr) >> 4) | (*(sptr - 1) << 28)) & + ((*(sptr) >> 3) | (*(sptr - 1) << 29)) & + ((*(sptr) >> 2) | (*(sptr - 1) << 30)) & + ((*(sptr) >> 1) | (*(sptr - 1) << 31)) & + (*sptr) & + ((*(sptr) << 1) | (*(sptr + 1) >> 31)) & + ((*(sptr) << 2) | (*(sptr + 1) >> 30)) & + ((*(sptr) << 3) | (*(sptr + 1) >> 29)) & + ((*(sptr) << 4) | (*(sptr + 1) >> 28)) & + ((*(sptr) << 5) | (*(sptr + 1) >> 27)) & + ((*(sptr) << 6) | (*(sptr + 1) >> 26)) & + ((*(sptr) << 7) | (*(sptr + 1) >> 25)) & + ((*(sptr) << 8) | (*(sptr + 1) >> 24)) & + ((*(sptr) << 9) | (*(sptr + 1) >> 23)) & + ((*(sptr) << 10) | (*(sptr + 1) >> 22)) & + ((*(sptr) << 11) | (*(sptr + 1) >> 21)) & + ((*(sptr) << 12) | (*(sptr + 1) >> 20)) & + ((*(sptr) << 13) | (*(sptr + 1) >> 19)); + } + } +} + +static void +fdilate_3_27(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; + + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = ((*(sptr) << 14) | (*(sptr + 1) >> 18)) | + ((*(sptr) << 13) | (*(sptr + 1) >> 19)) | + ((*(sptr) << 12) | (*(sptr + 1) >> 20)) | + ((*(sptr) << 11) | (*(sptr + 1) >> 21)) | + ((*(sptr) << 10) | (*(sptr + 1) >> 22)) | + ((*(sptr) << 9) | (*(sptr + 1) >> 23)) | + ((*(sptr) << 8) | (*(sptr + 1) >> 24)) | + ((*(sptr) << 7) | (*(sptr + 1) >> 25)) | + ((*(sptr) << 6) | (*(sptr + 1) >> 26)) | + ((*(sptr) << 5) | (*(sptr + 1) >> 27)) | + ((*(sptr) << 4) | (*(sptr + 1) >> 28)) | + ((*(sptr) << 3) | (*(sptr + 1) >> 29)) | + ((*(sptr) << 2) | (*(sptr + 1) >> 30)) | + ((*(sptr) << 1) | (*(sptr + 1) >> 31)) | + (*sptr) | + ((*(sptr) >> 1) | (*(sptr - 1) << 31)) | + ((*(sptr) >> 2) | (*(sptr - 1) << 30)) | + ((*(sptr) >> 3) | (*(sptr - 1) << 29)) | + ((*(sptr) >> 4) | (*(sptr - 1) << 28)) | + ((*(sptr) >> 5) | (*(sptr - 1) << 27)) | + ((*(sptr) >> 6) | (*(sptr - 1) << 26)) | + ((*(sptr) >> 7) | (*(sptr - 1) << 25)) | + ((*(sptr) >> 8) | (*(sptr - 1) << 24)) | + ((*(sptr) >> 9) | (*(sptr - 1) << 23)) | + ((*(sptr) >> 10) | (*(sptr - 1) << 22)) | + ((*(sptr) >> 11) | (*(sptr - 1) << 21)) | + ((*(sptr) >> 12) | (*(sptr - 1) << 20)) | + ((*(sptr) >> 13) | (*(sptr - 1) << 19)) | + ((*(sptr) >> 14) | (*(sptr - 1) << 18)); + } + } +} + +static void +ferode_3_27(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; + + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = ((*(sptr) >> 14) | (*(sptr - 1) << 18)) & + ((*(sptr) >> 13) | (*(sptr - 1) << 19)) & + ((*(sptr) >> 12) | (*(sptr - 1) << 20)) & + ((*(sptr) >> 11) | (*(sptr - 1) << 21)) & + ((*(sptr) >> 10) | (*(sptr - 1) << 22)) & + ((*(sptr) >> 9) | (*(sptr - 1) << 23)) & + ((*(sptr) >> 8) | (*(sptr - 1) << 24)) & + ((*(sptr) >> 7) | (*(sptr - 1) << 25)) & + ((*(sptr) >> 6) | (*(sptr - 1) << 26)) & + ((*(sptr) >> 5) | (*(sptr - 1) << 27)) & + ((*(sptr) >> 4) | (*(sptr - 1) << 28)) & + ((*(sptr) >> 3) | (*(sptr - 1) << 29)) & + ((*(sptr) >> 2) | (*(sptr - 1) << 30)) & + ((*(sptr) >> 1) | (*(sptr - 1) << 31)) & + (*sptr) & + ((*(sptr) << 1) | (*(sptr + 1) >> 31)) & + ((*(sptr) << 2) | (*(sptr + 1) >> 30)) & + ((*(sptr) << 3) | (*(sptr + 1) >> 29)) & + ((*(sptr) << 4) | (*(sptr + 1) >> 28)) & + ((*(sptr) << 5) | (*(sptr + 1) >> 27)) & + ((*(sptr) << 6) | (*(sptr + 1) >> 26)) & + ((*(sptr) << 7) | (*(sptr + 1) >> 25)) & + ((*(sptr) << 8) | (*(sptr + 1) >> 24)) & + ((*(sptr) << 9) | (*(sptr + 1) >> 23)) & + ((*(sptr) << 10) | (*(sptr + 1) >> 22)) & + ((*(sptr) << 11) | (*(sptr + 1) >> 21)) & + ((*(sptr) << 12) | (*(sptr + 1) >> 20)) & + ((*(sptr) << 13) | (*(sptr + 1) >> 19)) & + ((*(sptr) << 14) | (*(sptr + 1) >> 18)); + } + } +} + +static void +fdilate_3_28(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; + + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = ((*(sptr) << 15) | (*(sptr + 1) >> 17)) | + ((*(sptr) << 14) | (*(sptr + 1) >> 18)) | + ((*(sptr) << 13) | (*(sptr + 1) >> 19)) | + ((*(sptr) << 12) | (*(sptr + 1) >> 20)) | + ((*(sptr) << 11) | (*(sptr + 1) >> 21)) | + ((*(sptr) << 10) | (*(sptr + 1) >> 22)) | + ((*(sptr) << 9) | (*(sptr + 1) >> 23)) | + ((*(sptr) << 8) | (*(sptr + 1) >> 24)) | + ((*(sptr) << 7) | (*(sptr + 1) >> 25)) | + ((*(sptr) << 6) | (*(sptr + 1) >> 26)) | + ((*(sptr) << 5) | (*(sptr + 1) >> 27)) | + ((*(sptr) << 4) | (*(sptr + 1) >> 28)) | + ((*(sptr) << 3) | (*(sptr + 1) >> 29)) | + ((*(sptr) << 2) | (*(sptr + 1) >> 30)) | + ((*(sptr) << 1) | (*(sptr + 1) >> 31)) | + (*sptr) | + ((*(sptr) >> 1) | (*(sptr - 1) << 31)) | + ((*(sptr) >> 2) | (*(sptr - 1) << 30)) | + ((*(sptr) >> 3) | (*(sptr - 1) << 29)) | + ((*(sptr) >> 4) | (*(sptr - 1) << 28)) | + ((*(sptr) >> 5) | (*(sptr - 1) << 27)) | + ((*(sptr) >> 6) | (*(sptr - 1) << 26)) | + ((*(sptr) >> 7) | (*(sptr - 1) << 25)) | + ((*(sptr) >> 8) | (*(sptr - 1) << 24)) | + ((*(sptr) >> 9) | (*(sptr - 1) << 23)) | + ((*(sptr) >> 10) | (*(sptr - 1) << 22)) | + ((*(sptr) >> 11) | (*(sptr - 1) << 21)) | + ((*(sptr) >> 12) | (*(sptr - 1) << 20)) | + ((*(sptr) >> 13) | (*(sptr - 1) << 19)) | + ((*(sptr) >> 14) | (*(sptr - 1) << 18)); + } + } +} + +static void +ferode_3_28(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; + + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = ((*(sptr) >> 15) | (*(sptr - 1) << 17)) & + ((*(sptr) >> 14) | (*(sptr - 1) << 18)) & + ((*(sptr) >> 13) | (*(sptr - 1) << 19)) & + ((*(sptr) >> 12) | (*(sptr - 1) << 20)) & + ((*(sptr) >> 11) | (*(sptr - 1) << 21)) & + ((*(sptr) >> 10) | (*(sptr - 1) << 22)) & + ((*(sptr) >> 9) | (*(sptr - 1) << 23)) & + ((*(sptr) >> 8) | (*(sptr - 1) << 24)) & + ((*(sptr) >> 7) | (*(sptr - 1) << 25)) & + ((*(sptr) >> 6) | (*(sptr - 1) << 26)) & + ((*(sptr) >> 5) | (*(sptr - 1) << 27)) & + ((*(sptr) >> 4) | (*(sptr - 1) << 28)) & + ((*(sptr) >> 3) | (*(sptr - 1) << 29)) & + ((*(sptr) >> 2) | (*(sptr - 1) << 30)) & + ((*(sptr) >> 1) | (*(sptr - 1) << 31)) & + (*sptr) & + ((*(sptr) << 1) | (*(sptr + 1) >> 31)) & + ((*(sptr) << 2) | (*(sptr + 1) >> 30)) & + ((*(sptr) << 3) | (*(sptr + 1) >> 29)) & + ((*(sptr) << 4) | (*(sptr + 1) >> 28)) & + ((*(sptr) << 5) | (*(sptr + 1) >> 27)) & + ((*(sptr) << 6) | (*(sptr + 1) >> 26)) & + ((*(sptr) << 7) | (*(sptr + 1) >> 25)) & + ((*(sptr) << 8) | (*(sptr + 1) >> 24)) & + ((*(sptr) << 9) | (*(sptr + 1) >> 23)) & + ((*(sptr) << 10) | (*(sptr + 1) >> 22)) & + ((*(sptr) << 11) | (*(sptr + 1) >> 21)) & + ((*(sptr) << 12) | (*(sptr + 1) >> 20)) & + ((*(sptr) << 13) | (*(sptr + 1) >> 19)) & + ((*(sptr) << 14) | (*(sptr + 1) >> 18)); + } + } +} + +static void +fdilate_3_29(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; + + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = ((*(sptr) << 15) | (*(sptr + 1) >> 17)) | + ((*(sptr) << 14) | (*(sptr + 1) >> 18)) | + ((*(sptr) << 13) | (*(sptr + 1) >> 19)) | + ((*(sptr) << 12) | (*(sptr + 1) >> 20)) | + ((*(sptr) << 11) | (*(sptr + 1) >> 21)) | + ((*(sptr) << 10) | (*(sptr + 1) >> 22)) | + ((*(sptr) << 9) | (*(sptr + 1) >> 23)) | + ((*(sptr) << 8) | (*(sptr + 1) >> 24)) | + ((*(sptr) << 7) | (*(sptr + 1) >> 25)) | + ((*(sptr) << 6) | (*(sptr + 1) >> 26)) | + ((*(sptr) << 5) | (*(sptr + 1) >> 27)) | + ((*(sptr) << 4) | (*(sptr + 1) >> 28)) | + ((*(sptr) << 3) | (*(sptr + 1) >> 29)) | + ((*(sptr) << 2) | (*(sptr + 1) >> 30)) | + ((*(sptr) << 1) | (*(sptr + 1) >> 31)) | + (*sptr) | + ((*(sptr) >> 1) | (*(sptr - 1) << 31)) | + ((*(sptr) >> 2) | (*(sptr - 1) << 30)) | + ((*(sptr) >> 3) | (*(sptr - 1) << 29)) | + ((*(sptr) >> 4) | (*(sptr - 1) << 28)) | + ((*(sptr) >> 5) | (*(sptr - 1) << 27)) | + ((*(sptr) >> 6) | (*(sptr - 1) << 26)) | + ((*(sptr) >> 7) | (*(sptr - 1) << 25)) | + ((*(sptr) >> 8) | (*(sptr - 1) << 24)) | + ((*(sptr) >> 9) | (*(sptr - 1) << 23)) | + ((*(sptr) >> 10) | (*(sptr - 1) << 22)) | + ((*(sptr) >> 11) | (*(sptr - 1) << 21)) | + ((*(sptr) >> 12) | (*(sptr - 1) << 20)) | + ((*(sptr) >> 13) | (*(sptr - 1) << 19)) | + ((*(sptr) >> 14) | (*(sptr - 1) << 18)) | + ((*(sptr) >> 15) | (*(sptr - 1) << 17)); + } + } +} + +static void +ferode_3_29(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; + + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = ((*(sptr) >> 15) | (*(sptr - 1) << 17)) & + ((*(sptr) >> 14) | (*(sptr - 1) << 18)) & + ((*(sptr) >> 13) | (*(sptr - 1) << 19)) & + ((*(sptr) >> 12) | (*(sptr - 1) << 20)) & + ((*(sptr) >> 11) | (*(sptr - 1) << 21)) & + ((*(sptr) >> 10) | (*(sptr - 1) << 22)) & + ((*(sptr) >> 9) | (*(sptr - 1) << 23)) & + ((*(sptr) >> 8) | (*(sptr - 1) << 24)) & + ((*(sptr) >> 7) | (*(sptr - 1) << 25)) & + ((*(sptr) >> 6) | (*(sptr - 1) << 26)) & + ((*(sptr) >> 5) | (*(sptr - 1) << 27)) & + ((*(sptr) >> 4) | (*(sptr - 1) << 28)) & + ((*(sptr) >> 3) | (*(sptr - 1) << 29)) & + ((*(sptr) >> 2) | (*(sptr - 1) << 30)) & + ((*(sptr) >> 1) | (*(sptr - 1) << 31)) & + (*sptr) & + ((*(sptr) << 1) | (*(sptr + 1) >> 31)) & + ((*(sptr) << 2) | (*(sptr + 1) >> 30)) & + ((*(sptr) << 3) | (*(sptr + 1) >> 29)) & + ((*(sptr) << 4) | (*(sptr + 1) >> 28)) & + ((*(sptr) << 5) | (*(sptr + 1) >> 27)) & + ((*(sptr) << 6) | (*(sptr + 1) >> 26)) & + ((*(sptr) << 7) | (*(sptr + 1) >> 25)) & + ((*(sptr) << 8) | (*(sptr + 1) >> 24)) & + ((*(sptr) << 9) | (*(sptr + 1) >> 23)) & + ((*(sptr) << 10) | (*(sptr + 1) >> 22)) & + ((*(sptr) << 11) | (*(sptr + 1) >> 21)) & + ((*(sptr) << 12) | (*(sptr + 1) >> 20)) & + ((*(sptr) << 13) | (*(sptr + 1) >> 19)) & + ((*(sptr) << 14) | (*(sptr + 1) >> 18)) & + ((*(sptr) << 15) | (*(sptr + 1) >> 17)); + } + } +} + +static void +fdilate_3_30(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; + + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = ((*(sptr) << 16) | (*(sptr + 1) >> 16)) | + ((*(sptr) << 15) | (*(sptr + 1) >> 17)) | + ((*(sptr) << 14) | (*(sptr + 1) >> 18)) | + ((*(sptr) << 13) | (*(sptr + 1) >> 19)) | + ((*(sptr) << 12) | (*(sptr + 1) >> 20)) | + ((*(sptr) << 11) | (*(sptr + 1) >> 21)) | + ((*(sptr) << 10) | (*(sptr + 1) >> 22)) | + ((*(sptr) << 9) | (*(sptr + 1) >> 23)) | + ((*(sptr) << 8) | (*(sptr + 1) >> 24)) | + ((*(sptr) << 7) | (*(sptr + 1) >> 25)) | + ((*(sptr) << 6) | (*(sptr + 1) >> 26)) | + ((*(sptr) << 5) | (*(sptr + 1) >> 27)) | + ((*(sptr) << 4) | (*(sptr + 1) >> 28)) | + ((*(sptr) << 3) | (*(sptr + 1) >> 29)) | + ((*(sptr) << 2) | (*(sptr + 1) >> 30)) | + ((*(sptr) << 1) | (*(sptr + 1) >> 31)) | + (*sptr) | + ((*(sptr) >> 1) | (*(sptr - 1) << 31)) | + ((*(sptr) >> 2) | (*(sptr - 1) << 30)) | + ((*(sptr) >> 3) | (*(sptr - 1) << 29)) | + ((*(sptr) >> 4) | (*(sptr - 1) << 28)) | + ((*(sptr) >> 5) | (*(sptr - 1) << 27)) | + ((*(sptr) >> 6) | (*(sptr - 1) << 26)) | + ((*(sptr) >> 7) | (*(sptr - 1) << 25)) | + ((*(sptr) >> 8) | (*(sptr - 1) << 24)) | + ((*(sptr) >> 9) | (*(sptr - 1) << 23)) | + ((*(sptr) >> 10) | (*(sptr - 1) << 22)) | + ((*(sptr) >> 11) | (*(sptr - 1) << 21)) | + ((*(sptr) >> 12) | (*(sptr - 1) << 20)) | + ((*(sptr) >> 13) | (*(sptr - 1) << 19)) | + ((*(sptr) >> 14) | (*(sptr - 1) << 18)) | + ((*(sptr) >> 15) | (*(sptr - 1) << 17)); + } + } +} + +static void +ferode_3_30(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; + + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = ((*(sptr) >> 16) | (*(sptr - 1) << 16)) & + ((*(sptr) >> 15) | (*(sptr - 1) << 17)) & + ((*(sptr) >> 14) | (*(sptr - 1) << 18)) & + ((*(sptr) >> 13) | (*(sptr - 1) << 19)) & + ((*(sptr) >> 12) | (*(sptr - 1) << 20)) & + ((*(sptr) >> 11) | (*(sptr - 1) << 21)) & + ((*(sptr) >> 10) | (*(sptr - 1) << 22)) & + ((*(sptr) >> 9) | (*(sptr - 1) << 23)) & + ((*(sptr) >> 8) | (*(sptr - 1) << 24)) & + ((*(sptr) >> 7) | (*(sptr - 1) << 25)) & + ((*(sptr) >> 6) | (*(sptr - 1) << 26)) & + ((*(sptr) >> 5) | (*(sptr - 1) << 27)) & + ((*(sptr) >> 4) | (*(sptr - 1) << 28)) & + ((*(sptr) >> 3) | (*(sptr - 1) << 29)) & + ((*(sptr) >> 2) | (*(sptr - 1) << 30)) & + ((*(sptr) >> 1) | (*(sptr - 1) << 31)) & + (*sptr) & + ((*(sptr) << 1) | (*(sptr + 1) >> 31)) & + ((*(sptr) << 2) | (*(sptr + 1) >> 30)) & + ((*(sptr) << 3) | (*(sptr + 1) >> 29)) & + ((*(sptr) << 4) | (*(sptr + 1) >> 28)) & + ((*(sptr) << 5) | (*(sptr + 1) >> 27)) & + ((*(sptr) << 6) | (*(sptr + 1) >> 26)) & + ((*(sptr) << 7) | (*(sptr + 1) >> 25)) & + ((*(sptr) << 8) | (*(sptr + 1) >> 24)) & + ((*(sptr) << 9) | (*(sptr + 1) >> 23)) & + ((*(sptr) << 10) | (*(sptr + 1) >> 22)) & + ((*(sptr) << 11) | (*(sptr + 1) >> 21)) & + ((*(sptr) << 12) | (*(sptr + 1) >> 20)) & + ((*(sptr) << 13) | (*(sptr + 1) >> 19)) & + ((*(sptr) << 14) | (*(sptr + 1) >> 18)) & + ((*(sptr) << 15) | (*(sptr + 1) >> 17)); + } + } +} + +static void +fdilate_3_31(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; + + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = ((*(sptr) << 16) | (*(sptr + 1) >> 16)) | + ((*(sptr) << 15) | (*(sptr + 1) >> 17)) | + ((*(sptr) << 14) | (*(sptr + 1) >> 18)) | + ((*(sptr) << 13) | (*(sptr + 1) >> 19)) | + ((*(sptr) << 12) | (*(sptr + 1) >> 20)) | + ((*(sptr) << 11) | (*(sptr + 1) >> 21)) | + ((*(sptr) << 10) | (*(sptr + 1) >> 22)) | + ((*(sptr) << 9) | (*(sptr + 1) >> 23)) | + ((*(sptr) << 8) | (*(sptr + 1) >> 24)) | + ((*(sptr) << 7) | (*(sptr + 1) >> 25)) | + ((*(sptr) << 6) | (*(sptr + 1) >> 26)) | + ((*(sptr) << 5) | (*(sptr + 1) >> 27)) | + ((*(sptr) << 4) | (*(sptr + 1) >> 28)) | + ((*(sptr) << 3) | (*(sptr + 1) >> 29)) | + ((*(sptr) << 2) | (*(sptr + 1) >> 30)) | + ((*(sptr) << 1) | (*(sptr + 1) >> 31)) | + (*sptr) | + ((*(sptr) >> 1) | (*(sptr - 1) << 31)) | + ((*(sptr) >> 2) | (*(sptr - 1) << 30)) | + ((*(sptr) >> 3) | (*(sptr - 1) << 29)) | + ((*(sptr) >> 4) | (*(sptr - 1) << 28)) | + ((*(sptr) >> 5) | (*(sptr - 1) << 27)) | + ((*(sptr) >> 6) | (*(sptr - 1) << 26)) | + ((*(sptr) >> 7) | (*(sptr - 1) << 25)) | + ((*(sptr) >> 8) | (*(sptr - 1) << 24)) | + ((*(sptr) >> 9) | (*(sptr - 1) << 23)) | + ((*(sptr) >> 10) | (*(sptr - 1) << 22)) | + ((*(sptr) >> 11) | (*(sptr - 1) << 21)) | + ((*(sptr) >> 12) | (*(sptr - 1) << 20)) | + ((*(sptr) >> 13) | (*(sptr - 1) << 19)) | + ((*(sptr) >> 14) | (*(sptr - 1) << 18)) | + ((*(sptr) >> 15) | (*(sptr - 1) << 17)) | + ((*(sptr) >> 16) | (*(sptr - 1) << 16)); + } + } +} + +static void +ferode_3_31(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; + + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = ((*(sptr) >> 16) | (*(sptr - 1) << 16)) & + ((*(sptr) >> 15) | (*(sptr - 1) << 17)) & + ((*(sptr) >> 14) | (*(sptr - 1) << 18)) & + ((*(sptr) >> 13) | (*(sptr - 1) << 19)) & + ((*(sptr) >> 12) | (*(sptr - 1) << 20)) & + ((*(sptr) >> 11) | (*(sptr - 1) << 21)) & + ((*(sptr) >> 10) | (*(sptr - 1) << 22)) & + ((*(sptr) >> 9) | (*(sptr - 1) << 23)) & + ((*(sptr) >> 8) | (*(sptr - 1) << 24)) & + ((*(sptr) >> 7) | (*(sptr - 1) << 25)) & + ((*(sptr) >> 6) | (*(sptr - 1) << 26)) & + ((*(sptr) >> 5) | (*(sptr - 1) << 27)) & + ((*(sptr) >> 4) | (*(sptr - 1) << 28)) & + ((*(sptr) >> 3) | (*(sptr - 1) << 29)) & + ((*(sptr) >> 2) | (*(sptr - 1) << 30)) & + ((*(sptr) >> 1) | (*(sptr - 1) << 31)) & + (*sptr) & + ((*(sptr) << 1) | (*(sptr + 1) >> 31)) & + ((*(sptr) << 2) | (*(sptr + 1) >> 30)) & + ((*(sptr) << 3) | (*(sptr + 1) >> 29)) & + ((*(sptr) << 4) | (*(sptr + 1) >> 28)) & + ((*(sptr) << 5) | (*(sptr + 1) >> 27)) & + ((*(sptr) << 6) | (*(sptr + 1) >> 26)) & + ((*(sptr) << 7) | (*(sptr + 1) >> 25)) & + ((*(sptr) << 8) | (*(sptr + 1) >> 24)) & + ((*(sptr) << 9) | (*(sptr + 1) >> 23)) & + ((*(sptr) << 10) | (*(sptr + 1) >> 22)) & + ((*(sptr) << 11) | (*(sptr + 1) >> 21)) & + ((*(sptr) << 12) | (*(sptr + 1) >> 20)) & + ((*(sptr) << 13) | (*(sptr + 1) >> 19)) & + ((*(sptr) << 14) | (*(sptr + 1) >> 18)) & + ((*(sptr) << 15) | (*(sptr + 1) >> 17)) & + ((*(sptr) << 16) | (*(sptr + 1) >> 16)); + } + } +} + +static void +fdilate_3_32(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; + + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = ((*(sptr) << 17) | (*(sptr + 1) >> 15)) | + ((*(sptr) << 16) | (*(sptr + 1) >> 16)) | + ((*(sptr) << 15) | (*(sptr + 1) >> 17)) | + ((*(sptr) << 14) | (*(sptr + 1) >> 18)) | + ((*(sptr) << 13) | (*(sptr + 1) >> 19)) | + ((*(sptr) << 12) | (*(sptr + 1) >> 20)) | + ((*(sptr) << 11) | (*(sptr + 1) >> 21)) | + ((*(sptr) << 10) | (*(sptr + 1) >> 22)) | + ((*(sptr) << 9) | (*(sptr + 1) >> 23)) | + ((*(sptr) << 8) | (*(sptr + 1) >> 24)) | + ((*(sptr) << 7) | (*(sptr + 1) >> 25)) | + ((*(sptr) << 6) | (*(sptr + 1) >> 26)) | + ((*(sptr) << 5) | (*(sptr + 1) >> 27)) | + ((*(sptr) << 4) | (*(sptr + 1) >> 28)) | + ((*(sptr) << 3) | (*(sptr + 1) >> 29)) | + ((*(sptr) << 2) | (*(sptr + 1) >> 30)) | + ((*(sptr) << 1) | (*(sptr + 1) >> 31)) | + (*sptr) | + ((*(sptr) >> 1) | (*(sptr - 1) << 31)) | + ((*(sptr) >> 2) | (*(sptr - 1) << 30)) | + ((*(sptr) >> 3) | (*(sptr - 1) << 29)) | + ((*(sptr) >> 4) | (*(sptr - 1) << 28)) | + ((*(sptr) >> 5) | (*(sptr - 1) << 27)) | + ((*(sptr) >> 6) | (*(sptr - 1) << 26)) | + ((*(sptr) >> 7) | (*(sptr - 1) << 25)) | + ((*(sptr) >> 8) | (*(sptr - 1) << 24)) | + ((*(sptr) >> 9) | (*(sptr - 1) << 23)) | + ((*(sptr) >> 10) | (*(sptr - 1) << 22)) | + ((*(sptr) >> 11) | (*(sptr - 1) << 21)) | + ((*(sptr) >> 12) | (*(sptr - 1) << 20)) | + ((*(sptr) >> 13) | (*(sptr - 1) << 19)) | + ((*(sptr) >> 14) | (*(sptr - 1) << 18)) | + ((*(sptr) >> 15) | (*(sptr - 1) << 17)) | + ((*(sptr) >> 16) | (*(sptr - 1) << 16)); + } + } +} + +static void +ferode_3_32(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; + + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = ((*(sptr) >> 17) | (*(sptr - 1) << 15)) & + ((*(sptr) >> 16) | (*(sptr - 1) << 16)) & + ((*(sptr) >> 15) | (*(sptr - 1) << 17)) & + ((*(sptr) >> 14) | (*(sptr - 1) << 18)) & + ((*(sptr) >> 13) | (*(sptr - 1) << 19)) & + ((*(sptr) >> 12) | (*(sptr - 1) << 20)) & + ((*(sptr) >> 11) | (*(sptr - 1) << 21)) & + ((*(sptr) >> 10) | (*(sptr - 1) << 22)) & + ((*(sptr) >> 9) | (*(sptr - 1) << 23)) & + ((*(sptr) >> 8) | (*(sptr - 1) << 24)) & + ((*(sptr) >> 7) | (*(sptr - 1) << 25)) & + ((*(sptr) >> 6) | (*(sptr - 1) << 26)) & + ((*(sptr) >> 5) | (*(sptr - 1) << 27)) & + ((*(sptr) >> 4) | (*(sptr - 1) << 28)) & + ((*(sptr) >> 3) | (*(sptr - 1) << 29)) & + ((*(sptr) >> 2) | (*(sptr - 1) << 30)) & + ((*(sptr) >> 1) | (*(sptr - 1) << 31)) & + (*sptr) & + ((*(sptr) << 1) | (*(sptr + 1) >> 31)) & + ((*(sptr) << 2) | (*(sptr + 1) >> 30)) & + ((*(sptr) << 3) | (*(sptr + 1) >> 29)) & + ((*(sptr) << 4) | (*(sptr + 1) >> 28)) & + ((*(sptr) << 5) | (*(sptr + 1) >> 27)) & + ((*(sptr) << 6) | (*(sptr + 1) >> 26)) & + ((*(sptr) << 7) | (*(sptr + 1) >> 25)) & + ((*(sptr) << 8) | (*(sptr + 1) >> 24)) & + ((*(sptr) << 9) | (*(sptr + 1) >> 23)) & + ((*(sptr) << 10) | (*(sptr + 1) >> 22)) & + ((*(sptr) << 11) | (*(sptr + 1) >> 21)) & + ((*(sptr) << 12) | (*(sptr + 1) >> 20)) & + ((*(sptr) << 13) | (*(sptr + 1) >> 19)) & + ((*(sptr) << 14) | (*(sptr + 1) >> 18)) & + ((*(sptr) << 15) | (*(sptr + 1) >> 17)) & + ((*(sptr) << 16) | (*(sptr + 1) >> 16)); + } + } +} + +static void +fdilate_3_33(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; + + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = ((*(sptr) << 17) | (*(sptr + 1) >> 15)) | + ((*(sptr) << 16) | (*(sptr + 1) >> 16)) | + ((*(sptr) << 15) | (*(sptr + 1) >> 17)) | + ((*(sptr) << 14) | (*(sptr + 1) >> 18)) | + ((*(sptr) << 13) | (*(sptr + 1) >> 19)) | + ((*(sptr) << 12) | (*(sptr + 1) >> 20)) | + ((*(sptr) << 11) | (*(sptr + 1) >> 21)) | + ((*(sptr) << 10) | (*(sptr + 1) >> 22)) | + ((*(sptr) << 9) | (*(sptr + 1) >> 23)) | + ((*(sptr) << 8) | (*(sptr + 1) >> 24)) | + ((*(sptr) << 7) | (*(sptr + 1) >> 25)) | + ((*(sptr) << 6) | (*(sptr + 1) >> 26)) | + ((*(sptr) << 5) | (*(sptr + 1) >> 27)) | + ((*(sptr) << 4) | (*(sptr + 1) >> 28)) | + ((*(sptr) << 3) | (*(sptr + 1) >> 29)) | + ((*(sptr) << 2) | (*(sptr + 1) >> 30)) | + ((*(sptr) << 1) | (*(sptr + 1) >> 31)) | + (*sptr) | + ((*(sptr) >> 1) | (*(sptr - 1) << 31)) | + ((*(sptr) >> 2) | (*(sptr - 1) << 30)) | + ((*(sptr) >> 3) | (*(sptr - 1) << 29)) | + ((*(sptr) >> 4) | (*(sptr - 1) << 28)) | + ((*(sptr) >> 5) | (*(sptr - 1) << 27)) | + ((*(sptr) >> 6) | (*(sptr - 1) << 26)) | + ((*(sptr) >> 7) | (*(sptr - 1) << 25)) | + ((*(sptr) >> 8) | (*(sptr - 1) << 24)) | + ((*(sptr) >> 9) | (*(sptr - 1) << 23)) | + ((*(sptr) >> 10) | (*(sptr - 1) << 22)) | + ((*(sptr) >> 11) | (*(sptr - 1) << 21)) | + ((*(sptr) >> 12) | (*(sptr - 1) << 20)) | + ((*(sptr) >> 13) | (*(sptr - 1) << 19)) | + ((*(sptr) >> 14) | (*(sptr - 1) << 18)) | + ((*(sptr) >> 15) | (*(sptr - 1) << 17)) | + ((*(sptr) >> 16) | (*(sptr - 1) << 16)) | + ((*(sptr) >> 17) | (*(sptr - 1) << 15)); + } + } +} + +static void +ferode_3_33(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; + + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = ((*(sptr) >> 17) | (*(sptr - 1) << 15)) & + ((*(sptr) >> 16) | (*(sptr - 1) << 16)) & + ((*(sptr) >> 15) | (*(sptr - 1) << 17)) & + ((*(sptr) >> 14) | (*(sptr - 1) << 18)) & + ((*(sptr) >> 13) | (*(sptr - 1) << 19)) & + ((*(sptr) >> 12) | (*(sptr - 1) << 20)) & + ((*(sptr) >> 11) | (*(sptr - 1) << 21)) & + ((*(sptr) >> 10) | (*(sptr - 1) << 22)) & + ((*(sptr) >> 9) | (*(sptr - 1) << 23)) & + ((*(sptr) >> 8) | (*(sptr - 1) << 24)) & + ((*(sptr) >> 7) | (*(sptr - 1) << 25)) & + ((*(sptr) >> 6) | (*(sptr - 1) << 26)) & + ((*(sptr) >> 5) | (*(sptr - 1) << 27)) & + ((*(sptr) >> 4) | (*(sptr - 1) << 28)) & + ((*(sptr) >> 3) | (*(sptr - 1) << 29)) & + ((*(sptr) >> 2) | (*(sptr - 1) << 30)) & + ((*(sptr) >> 1) | (*(sptr - 1) << 31)) & + (*sptr) & + ((*(sptr) << 1) | (*(sptr + 1) >> 31)) & + ((*(sptr) << 2) | (*(sptr + 1) >> 30)) & + ((*(sptr) << 3) | (*(sptr + 1) >> 29)) & + ((*(sptr) << 4) | (*(sptr + 1) >> 28)) & + ((*(sptr) << 5) | (*(sptr + 1) >> 27)) & + ((*(sptr) << 6) | (*(sptr + 1) >> 26)) & + ((*(sptr) << 7) | (*(sptr + 1) >> 25)) & + ((*(sptr) << 8) | (*(sptr + 1) >> 24)) & + ((*(sptr) << 9) | (*(sptr + 1) >> 23)) & + ((*(sptr) << 10) | (*(sptr + 1) >> 22)) & + ((*(sptr) << 11) | (*(sptr + 1) >> 21)) & + ((*(sptr) << 12) | (*(sptr + 1) >> 20)) & + ((*(sptr) << 13) | (*(sptr + 1) >> 19)) & + ((*(sptr) << 14) | (*(sptr + 1) >> 18)) & + ((*(sptr) << 15) | (*(sptr + 1) >> 17)) & + ((*(sptr) << 16) | (*(sptr + 1) >> 16)) & + ((*(sptr) << 17) | (*(sptr + 1) >> 15)); + } + } +} + +static void +fdilate_3_34(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; + + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = ((*(sptr) << 18) | (*(sptr + 1) >> 14)) | + ((*(sptr) << 17) | (*(sptr + 1) >> 15)) | + ((*(sptr) << 16) | (*(sptr + 1) >> 16)) | + ((*(sptr) << 15) | (*(sptr + 1) >> 17)) | + ((*(sptr) << 14) | (*(sptr + 1) >> 18)) | + ((*(sptr) << 13) | (*(sptr + 1) >> 19)) | + ((*(sptr) << 12) | (*(sptr + 1) >> 20)) | + ((*(sptr) << 11) | (*(sptr + 1) >> 21)) | + ((*(sptr) << 10) | (*(sptr + 1) >> 22)) | + ((*(sptr) << 9) | (*(sptr + 1) >> 23)) | + ((*(sptr) << 8) | (*(sptr + 1) >> 24)) | + ((*(sptr) << 7) | (*(sptr + 1) >> 25)) | + ((*(sptr) << 6) | (*(sptr + 1) >> 26)) | + ((*(sptr) << 5) | (*(sptr + 1) >> 27)) | + ((*(sptr) << 4) | (*(sptr + 1) >> 28)) | + ((*(sptr) << 3) | (*(sptr + 1) >> 29)) | + ((*(sptr) << 2) | (*(sptr + 1) >> 30)) | + ((*(sptr) << 1) | (*(sptr + 1) >> 31)) | + (*sptr) | + ((*(sptr) >> 1) | (*(sptr - 1) << 31)) | + ((*(sptr) >> 2) | (*(sptr - 1) << 30)) | + ((*(sptr) >> 3) | (*(sptr - 1) << 29)) | + ((*(sptr) >> 4) | (*(sptr - 1) << 28)) | + ((*(sptr) >> 5) | (*(sptr - 1) << 27)) | + ((*(sptr) >> 6) | (*(sptr - 1) << 26)) | + ((*(sptr) >> 7) | (*(sptr - 1) << 25)) | + ((*(sptr) >> 8) | (*(sptr - 1) << 24)) | + ((*(sptr) >> 9) | (*(sptr - 1) << 23)) | + ((*(sptr) >> 10) | (*(sptr - 1) << 22)) | + ((*(sptr) >> 11) | (*(sptr - 1) << 21)) | + ((*(sptr) >> 12) | (*(sptr - 1) << 20)) | + ((*(sptr) >> 13) | (*(sptr - 1) << 19)) | + ((*(sptr) >> 14) | (*(sptr - 1) << 18)) | + ((*(sptr) >> 15) | (*(sptr - 1) << 17)) | + ((*(sptr) >> 16) | (*(sptr - 1) << 16)) | + ((*(sptr) >> 17) | (*(sptr - 1) << 15)); + } + } +} + +static void +ferode_3_34(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; + + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = ((*(sptr) >> 18) | (*(sptr - 1) << 14)) & + ((*(sptr) >> 17) | (*(sptr - 1) << 15)) & + ((*(sptr) >> 16) | (*(sptr - 1) << 16)) & + ((*(sptr) >> 15) | (*(sptr - 1) << 17)) & + ((*(sptr) >> 14) | (*(sptr - 1) << 18)) & + ((*(sptr) >> 13) | (*(sptr - 1) << 19)) & + ((*(sptr) >> 12) | (*(sptr - 1) << 20)) & + ((*(sptr) >> 11) | (*(sptr - 1) << 21)) & + ((*(sptr) >> 10) | (*(sptr - 1) << 22)) & + ((*(sptr) >> 9) | (*(sptr - 1) << 23)) & + ((*(sptr) >> 8) | (*(sptr - 1) << 24)) & + ((*(sptr) >> 7) | (*(sptr - 1) << 25)) & + ((*(sptr) >> 6) | (*(sptr - 1) << 26)) & + ((*(sptr) >> 5) | (*(sptr - 1) << 27)) & + ((*(sptr) >> 4) | (*(sptr - 1) << 28)) & + ((*(sptr) >> 3) | (*(sptr - 1) << 29)) & + ((*(sptr) >> 2) | (*(sptr - 1) << 30)) & + ((*(sptr) >> 1) | (*(sptr - 1) << 31)) & + (*sptr) & + ((*(sptr) << 1) | (*(sptr + 1) >> 31)) & + ((*(sptr) << 2) | (*(sptr + 1) >> 30)) & + ((*(sptr) << 3) | (*(sptr + 1) >> 29)) & + ((*(sptr) << 4) | (*(sptr + 1) >> 28)) & + ((*(sptr) << 5) | (*(sptr + 1) >> 27)) & + ((*(sptr) << 6) | (*(sptr + 1) >> 26)) & + ((*(sptr) << 7) | (*(sptr + 1) >> 25)) & + ((*(sptr) << 8) | (*(sptr + 1) >> 24)) & + ((*(sptr) << 9) | (*(sptr + 1) >> 23)) & + ((*(sptr) << 10) | (*(sptr + 1) >> 22)) & + ((*(sptr) << 11) | (*(sptr + 1) >> 21)) & + ((*(sptr) << 12) | (*(sptr + 1) >> 20)) & + ((*(sptr) << 13) | (*(sptr + 1) >> 19)) & + ((*(sptr) << 14) | (*(sptr + 1) >> 18)) & + ((*(sptr) << 15) | (*(sptr + 1) >> 17)) & + ((*(sptr) << 16) | (*(sptr + 1) >> 16)) & + ((*(sptr) << 17) | (*(sptr + 1) >> 15)); + } + } +} + +static void +fdilate_3_35(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; + + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = ((*(sptr) << 18) | (*(sptr + 1) >> 14)) | + ((*(sptr) << 17) | (*(sptr + 1) >> 15)) | + ((*(sptr) << 16) | (*(sptr + 1) >> 16)) | + ((*(sptr) << 15) | (*(sptr + 1) >> 17)) | + ((*(sptr) << 14) | (*(sptr + 1) >> 18)) | + ((*(sptr) << 13) | (*(sptr + 1) >> 19)) | + ((*(sptr) << 12) | (*(sptr + 1) >> 20)) | + ((*(sptr) << 11) | (*(sptr + 1) >> 21)) | + ((*(sptr) << 10) | (*(sptr + 1) >> 22)) | + ((*(sptr) << 9) | (*(sptr + 1) >> 23)) | + ((*(sptr) << 8) | (*(sptr + 1) >> 24)) | + ((*(sptr) << 7) | (*(sptr + 1) >> 25)) | + ((*(sptr) << 6) | (*(sptr + 1) >> 26)) | + ((*(sptr) << 5) | (*(sptr + 1) >> 27)) | + ((*(sptr) << 4) | (*(sptr + 1) >> 28)) | + ((*(sptr) << 3) | (*(sptr + 1) >> 29)) | + ((*(sptr) << 2) | (*(sptr + 1) >> 30)) | + ((*(sptr) << 1) | (*(sptr + 1) >> 31)) | + (*sptr) | + ((*(sptr) >> 1) | (*(sptr - 1) << 31)) | + ((*(sptr) >> 2) | (*(sptr - 1) << 30)) | + ((*(sptr) >> 3) | (*(sptr - 1) << 29)) | + ((*(sptr) >> 4) | (*(sptr - 1) << 28)) | + ((*(sptr) >> 5) | (*(sptr - 1) << 27)) | + ((*(sptr) >> 6) | (*(sptr - 1) << 26)) | + ((*(sptr) >> 7) | (*(sptr - 1) << 25)) | + ((*(sptr) >> 8) | (*(sptr - 1) << 24)) | + ((*(sptr) >> 9) | (*(sptr - 1) << 23)) | + ((*(sptr) >> 10) | (*(sptr - 1) << 22)) | + ((*(sptr) >> 11) | (*(sptr - 1) << 21)) | + ((*(sptr) >> 12) | (*(sptr - 1) << 20)) | + ((*(sptr) >> 13) | (*(sptr - 1) << 19)) | + ((*(sptr) >> 14) | (*(sptr - 1) << 18)) | + ((*(sptr) >> 15) | (*(sptr - 1) << 17)) | + ((*(sptr) >> 16) | (*(sptr - 1) << 16)) | + ((*(sptr) >> 17) | (*(sptr - 1) << 15)) | + ((*(sptr) >> 18) | (*(sptr - 1) << 14)); + } + } +} + +static void +ferode_3_35(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; + + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = ((*(sptr) >> 18) | (*(sptr - 1) << 14)) & + ((*(sptr) >> 17) | (*(sptr - 1) << 15)) & + ((*(sptr) >> 16) | (*(sptr - 1) << 16)) & + ((*(sptr) >> 15) | (*(sptr - 1) << 17)) & + ((*(sptr) >> 14) | (*(sptr - 1) << 18)) & + ((*(sptr) >> 13) | (*(sptr - 1) << 19)) & + ((*(sptr) >> 12) | (*(sptr - 1) << 20)) & + ((*(sptr) >> 11) | (*(sptr - 1) << 21)) & + ((*(sptr) >> 10) | (*(sptr - 1) << 22)) & + ((*(sptr) >> 9) | (*(sptr - 1) << 23)) & + ((*(sptr) >> 8) | (*(sptr - 1) << 24)) & + ((*(sptr) >> 7) | (*(sptr - 1) << 25)) & + ((*(sptr) >> 6) | (*(sptr - 1) << 26)) & + ((*(sptr) >> 5) | (*(sptr - 1) << 27)) & + ((*(sptr) >> 4) | (*(sptr - 1) << 28)) & + ((*(sptr) >> 3) | (*(sptr - 1) << 29)) & + ((*(sptr) >> 2) | (*(sptr - 1) << 30)) & + ((*(sptr) >> 1) | (*(sptr - 1) << 31)) & + (*sptr) & + ((*(sptr) << 1) | (*(sptr + 1) >> 31)) & + ((*(sptr) << 2) | (*(sptr + 1) >> 30)) & + ((*(sptr) << 3) | (*(sptr + 1) >> 29)) & + ((*(sptr) << 4) | (*(sptr + 1) >> 28)) & + ((*(sptr) << 5) | (*(sptr + 1) >> 27)) & + ((*(sptr) << 6) | (*(sptr + 1) >> 26)) & + ((*(sptr) << 7) | (*(sptr + 1) >> 25)) & + ((*(sptr) << 8) | (*(sptr + 1) >> 24)) & + ((*(sptr) << 9) | (*(sptr + 1) >> 23)) & + ((*(sptr) << 10) | (*(sptr + 1) >> 22)) & + ((*(sptr) << 11) | (*(sptr + 1) >> 21)) & + ((*(sptr) << 12) | (*(sptr + 1) >> 20)) & + ((*(sptr) << 13) | (*(sptr + 1) >> 19)) & + ((*(sptr) << 14) | (*(sptr + 1) >> 18)) & + ((*(sptr) << 15) | (*(sptr + 1) >> 17)) & + ((*(sptr) << 16) | (*(sptr + 1) >> 16)) & + ((*(sptr) << 17) | (*(sptr + 1) >> 15)) & + ((*(sptr) << 18) | (*(sptr + 1) >> 14)); + } + } +} + +static void +fdilate_3_36(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; + + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = ((*(sptr) << 19) | (*(sptr + 1) >> 13)) | + ((*(sptr) << 18) | (*(sptr + 1) >> 14)) | + ((*(sptr) << 17) | (*(sptr + 1) >> 15)) | + ((*(sptr) << 16) | (*(sptr + 1) >> 16)) | + ((*(sptr) << 15) | (*(sptr + 1) >> 17)) | + ((*(sptr) << 14) | (*(sptr + 1) >> 18)) | + ((*(sptr) << 13) | (*(sptr + 1) >> 19)) | + ((*(sptr) << 12) | (*(sptr + 1) >> 20)) | + ((*(sptr) << 11) | (*(sptr + 1) >> 21)) | + ((*(sptr) << 10) | (*(sptr + 1) >> 22)) | + ((*(sptr) << 9) | (*(sptr + 1) >> 23)) | + ((*(sptr) << 8) | (*(sptr + 1) >> 24)) | + ((*(sptr) << 7) | (*(sptr + 1) >> 25)) | + ((*(sptr) << 6) | (*(sptr + 1) >> 26)) | + ((*(sptr) << 5) | (*(sptr + 1) >> 27)) | + ((*(sptr) << 4) | (*(sptr + 1) >> 28)) | + ((*(sptr) << 3) | (*(sptr + 1) >> 29)) | + ((*(sptr) << 2) | (*(sptr + 1) >> 30)) | + ((*(sptr) << 1) | (*(sptr + 1) >> 31)) | + (*sptr) | + ((*(sptr) >> 1) | (*(sptr - 1) << 31)) | + ((*(sptr) >> 2) | (*(sptr - 1) << 30)) | + ((*(sptr) >> 3) | (*(sptr - 1) << 29)) | + ((*(sptr) >> 4) | (*(sptr - 1) << 28)) | + ((*(sptr) >> 5) | (*(sptr - 1) << 27)) | + ((*(sptr) >> 6) | (*(sptr - 1) << 26)) | + ((*(sptr) >> 7) | (*(sptr - 1) << 25)) | + ((*(sptr) >> 8) | (*(sptr - 1) << 24)) | + ((*(sptr) >> 9) | (*(sptr - 1) << 23)) | + ((*(sptr) >> 10) | (*(sptr - 1) << 22)) | + ((*(sptr) >> 11) | (*(sptr - 1) << 21)) | + ((*(sptr) >> 12) | (*(sptr - 1) << 20)) | + ((*(sptr) >> 13) | (*(sptr - 1) << 19)) | + ((*(sptr) >> 14) | (*(sptr - 1) << 18)) | + ((*(sptr) >> 15) | (*(sptr - 1) << 17)) | + ((*(sptr) >> 16) | (*(sptr - 1) << 16)) | + ((*(sptr) >> 17) | (*(sptr - 1) << 15)) | + ((*(sptr) >> 18) | (*(sptr - 1) << 14)); + } + } +} + +static void +ferode_3_36(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; + + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = ((*(sptr) >> 19) | (*(sptr - 1) << 13)) & + ((*(sptr) >> 18) | (*(sptr - 1) << 14)) & + ((*(sptr) >> 17) | (*(sptr - 1) << 15)) & + ((*(sptr) >> 16) | (*(sptr - 1) << 16)) & + ((*(sptr) >> 15) | (*(sptr - 1) << 17)) & + ((*(sptr) >> 14) | (*(sptr - 1) << 18)) & + ((*(sptr) >> 13) | (*(sptr - 1) << 19)) & + ((*(sptr) >> 12) | (*(sptr - 1) << 20)) & + ((*(sptr) >> 11) | (*(sptr - 1) << 21)) & + ((*(sptr) >> 10) | (*(sptr - 1) << 22)) & + ((*(sptr) >> 9) | (*(sptr - 1) << 23)) & + ((*(sptr) >> 8) | (*(sptr - 1) << 24)) & + ((*(sptr) >> 7) | (*(sptr - 1) << 25)) & + ((*(sptr) >> 6) | (*(sptr - 1) << 26)) & + ((*(sptr) >> 5) | (*(sptr - 1) << 27)) & + ((*(sptr) >> 4) | (*(sptr - 1) << 28)) & + ((*(sptr) >> 3) | (*(sptr - 1) << 29)) & + ((*(sptr) >> 2) | (*(sptr - 1) << 30)) & + ((*(sptr) >> 1) | (*(sptr - 1) << 31)) & + (*sptr) & + ((*(sptr) << 1) | (*(sptr + 1) >> 31)) & + ((*(sptr) << 2) | (*(sptr + 1) >> 30)) & + ((*(sptr) << 3) | (*(sptr + 1) >> 29)) & + ((*(sptr) << 4) | (*(sptr + 1) >> 28)) & + ((*(sptr) << 5) | (*(sptr + 1) >> 27)) & + ((*(sptr) << 6) | (*(sptr + 1) >> 26)) & + ((*(sptr) << 7) | (*(sptr + 1) >> 25)) & + ((*(sptr) << 8) | (*(sptr + 1) >> 24)) & + ((*(sptr) << 9) | (*(sptr + 1) >> 23)) & + ((*(sptr) << 10) | (*(sptr + 1) >> 22)) & + ((*(sptr) << 11) | (*(sptr + 1) >> 21)) & + ((*(sptr) << 12) | (*(sptr + 1) >> 20)) & + ((*(sptr) << 13) | (*(sptr + 1) >> 19)) & + ((*(sptr) << 14) | (*(sptr + 1) >> 18)) & + ((*(sptr) << 15) | (*(sptr + 1) >> 17)) & + ((*(sptr) << 16) | (*(sptr + 1) >> 16)) & + ((*(sptr) << 17) | (*(sptr + 1) >> 15)) & + ((*(sptr) << 18) | (*(sptr + 1) >> 14)); + } + } +} + +static void +fdilate_3_37(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; + + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = ((*(sptr) << 19) | (*(sptr + 1) >> 13)) | + ((*(sptr) << 18) | (*(sptr + 1) >> 14)) | + ((*(sptr) << 17) | (*(sptr + 1) >> 15)) | + ((*(sptr) << 16) | (*(sptr + 1) >> 16)) | + ((*(sptr) << 15) | (*(sptr + 1) >> 17)) | + ((*(sptr) << 14) | (*(sptr + 1) >> 18)) | + ((*(sptr) << 13) | (*(sptr + 1) >> 19)) | + ((*(sptr) << 12) | (*(sptr + 1) >> 20)) | + ((*(sptr) << 11) | (*(sptr + 1) >> 21)) | + ((*(sptr) << 10) | (*(sptr + 1) >> 22)) | + ((*(sptr) << 9) | (*(sptr + 1) >> 23)) | + ((*(sptr) << 8) | (*(sptr + 1) >> 24)) | + ((*(sptr) << 7) | (*(sptr + 1) >> 25)) | + ((*(sptr) << 6) | (*(sptr + 1) >> 26)) | + ((*(sptr) << 5) | (*(sptr + 1) >> 27)) | + ((*(sptr) << 4) | (*(sptr + 1) >> 28)) | + ((*(sptr) << 3) | (*(sptr + 1) >> 29)) | + ((*(sptr) << 2) | (*(sptr + 1) >> 30)) | + ((*(sptr) << 1) | (*(sptr + 1) >> 31)) | + (*sptr) | + ((*(sptr) >> 1) | (*(sptr - 1) << 31)) | + ((*(sptr) >> 2) | (*(sptr - 1) << 30)) | + ((*(sptr) >> 3) | (*(sptr - 1) << 29)) | + ((*(sptr) >> 4) | (*(sptr - 1) << 28)) | + ((*(sptr) >> 5) | (*(sptr - 1) << 27)) | + ((*(sptr) >> 6) | (*(sptr - 1) << 26)) | + ((*(sptr) >> 7) | (*(sptr - 1) << 25)) | + ((*(sptr) >> 8) | (*(sptr - 1) << 24)) | + ((*(sptr) >> 9) | (*(sptr - 1) << 23)) | + ((*(sptr) >> 10) | (*(sptr - 1) << 22)) | + ((*(sptr) >> 11) | (*(sptr - 1) << 21)) | + ((*(sptr) >> 12) | (*(sptr - 1) << 20)) | + ((*(sptr) >> 13) | (*(sptr - 1) << 19)) | + ((*(sptr) >> 14) | (*(sptr - 1) << 18)) | + ((*(sptr) >> 15) | (*(sptr - 1) << 17)) | + ((*(sptr) >> 16) | (*(sptr - 1) << 16)) | + ((*(sptr) >> 17) | (*(sptr - 1) << 15)) | + ((*(sptr) >> 18) | (*(sptr - 1) << 14)) | + ((*(sptr) >> 19) | (*(sptr - 1) << 13)); + } + } +} + +static void +ferode_3_37(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; + + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = ((*(sptr) >> 19) | (*(sptr - 1) << 13)) & + ((*(sptr) >> 18) | (*(sptr - 1) << 14)) & + ((*(sptr) >> 17) | (*(sptr - 1) << 15)) & + ((*(sptr) >> 16) | (*(sptr - 1) << 16)) & + ((*(sptr) >> 15) | (*(sptr - 1) << 17)) & + ((*(sptr) >> 14) | (*(sptr - 1) << 18)) & + ((*(sptr) >> 13) | (*(sptr - 1) << 19)) & + ((*(sptr) >> 12) | (*(sptr - 1) << 20)) & + ((*(sptr) >> 11) | (*(sptr - 1) << 21)) & + ((*(sptr) >> 10) | (*(sptr - 1) << 22)) & + ((*(sptr) >> 9) | (*(sptr - 1) << 23)) & + ((*(sptr) >> 8) | (*(sptr - 1) << 24)) & + ((*(sptr) >> 7) | (*(sptr - 1) << 25)) & + ((*(sptr) >> 6) | (*(sptr - 1) << 26)) & + ((*(sptr) >> 5) | (*(sptr - 1) << 27)) & + ((*(sptr) >> 4) | (*(sptr - 1) << 28)) & + ((*(sptr) >> 3) | (*(sptr - 1) << 29)) & + ((*(sptr) >> 2) | (*(sptr - 1) << 30)) & + ((*(sptr) >> 1) | (*(sptr - 1) << 31)) & + (*sptr) & + ((*(sptr) << 1) | (*(sptr + 1) >> 31)) & + ((*(sptr) << 2) | (*(sptr + 1) >> 30)) & + ((*(sptr) << 3) | (*(sptr + 1) >> 29)) & + ((*(sptr) << 4) | (*(sptr + 1) >> 28)) & + ((*(sptr) << 5) | (*(sptr + 1) >> 27)) & + ((*(sptr) << 6) | (*(sptr + 1) >> 26)) & + ((*(sptr) << 7) | (*(sptr + 1) >> 25)) & + ((*(sptr) << 8) | (*(sptr + 1) >> 24)) & + ((*(sptr) << 9) | (*(sptr + 1) >> 23)) & + ((*(sptr) << 10) | (*(sptr + 1) >> 22)) & + ((*(sptr) << 11) | (*(sptr + 1) >> 21)) & + ((*(sptr) << 12) | (*(sptr + 1) >> 20)) & + ((*(sptr) << 13) | (*(sptr + 1) >> 19)) & + ((*(sptr) << 14) | (*(sptr + 1) >> 18)) & + ((*(sptr) << 15) | (*(sptr + 1) >> 17)) & + ((*(sptr) << 16) | (*(sptr + 1) >> 16)) & + ((*(sptr) << 17) | (*(sptr + 1) >> 15)) & + ((*(sptr) << 18) | (*(sptr + 1) >> 14)) & + ((*(sptr) << 19) | (*(sptr + 1) >> 13)); + } + } +} + +static void +fdilate_3_38(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; + + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = ((*(sptr) << 20) | (*(sptr + 1) >> 12)) | + ((*(sptr) << 19) | (*(sptr + 1) >> 13)) | + ((*(sptr) << 18) | (*(sptr + 1) >> 14)) | + ((*(sptr) << 17) | (*(sptr + 1) >> 15)) | + ((*(sptr) << 16) | (*(sptr + 1) >> 16)) | + ((*(sptr) << 15) | (*(sptr + 1) >> 17)) | + ((*(sptr) << 14) | (*(sptr + 1) >> 18)) | + ((*(sptr) << 13) | (*(sptr + 1) >> 19)) | + ((*(sptr) << 12) | (*(sptr + 1) >> 20)) | + ((*(sptr) << 11) | (*(sptr + 1) >> 21)) | + ((*(sptr) << 10) | (*(sptr + 1) >> 22)) | + ((*(sptr) << 9) | (*(sptr + 1) >> 23)) | + ((*(sptr) << 8) | (*(sptr + 1) >> 24)) | + ((*(sptr) << 7) | (*(sptr + 1) >> 25)) | + ((*(sptr) << 6) | (*(sptr + 1) >> 26)) | + ((*(sptr) << 5) | (*(sptr + 1) >> 27)) | + ((*(sptr) << 4) | (*(sptr + 1) >> 28)) | + ((*(sptr) << 3) | (*(sptr + 1) >> 29)) | + ((*(sptr) << 2) | (*(sptr + 1) >> 30)) | + ((*(sptr) << 1) | (*(sptr + 1) >> 31)) | + (*sptr) | + ((*(sptr) >> 1) | (*(sptr - 1) << 31)) | + ((*(sptr) >> 2) | (*(sptr - 1) << 30)) | + ((*(sptr) >> 3) | (*(sptr - 1) << 29)) | + ((*(sptr) >> 4) | (*(sptr - 1) << 28)) | + ((*(sptr) >> 5) | (*(sptr - 1) << 27)) | + ((*(sptr) >> 6) | (*(sptr - 1) << 26)) | + ((*(sptr) >> 7) | (*(sptr - 1) << 25)) | + ((*(sptr) >> 8) | (*(sptr - 1) << 24)) | + ((*(sptr) >> 9) | (*(sptr - 1) << 23)) | + ((*(sptr) >> 10) | (*(sptr - 1) << 22)) | + ((*(sptr) >> 11) | (*(sptr - 1) << 21)) | + ((*(sptr) >> 12) | (*(sptr - 1) << 20)) | + ((*(sptr) >> 13) | (*(sptr - 1) << 19)) | + ((*(sptr) >> 14) | (*(sptr - 1) << 18)) | + ((*(sptr) >> 15) | (*(sptr - 1) << 17)) | + ((*(sptr) >> 16) | (*(sptr - 1) << 16)) | + ((*(sptr) >> 17) | (*(sptr - 1) << 15)) | + ((*(sptr) >> 18) | (*(sptr - 1) << 14)) | + ((*(sptr) >> 19) | (*(sptr - 1) << 13)); + } + } +} + +static void +ferode_3_38(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; + + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = ((*(sptr) >> 20) | (*(sptr - 1) << 12)) & + ((*(sptr) >> 19) | (*(sptr - 1) << 13)) & + ((*(sptr) >> 18) | (*(sptr - 1) << 14)) & + ((*(sptr) >> 17) | (*(sptr - 1) << 15)) & + ((*(sptr) >> 16) | (*(sptr - 1) << 16)) & + ((*(sptr) >> 15) | (*(sptr - 1) << 17)) & + ((*(sptr) >> 14) | (*(sptr - 1) << 18)) & + ((*(sptr) >> 13) | (*(sptr - 1) << 19)) & + ((*(sptr) >> 12) | (*(sptr - 1) << 20)) & + ((*(sptr) >> 11) | (*(sptr - 1) << 21)) & + ((*(sptr) >> 10) | (*(sptr - 1) << 22)) & + ((*(sptr) >> 9) | (*(sptr - 1) << 23)) & + ((*(sptr) >> 8) | (*(sptr - 1) << 24)) & + ((*(sptr) >> 7) | (*(sptr - 1) << 25)) & + ((*(sptr) >> 6) | (*(sptr - 1) << 26)) & + ((*(sptr) >> 5) | (*(sptr - 1) << 27)) & + ((*(sptr) >> 4) | (*(sptr - 1) << 28)) & + ((*(sptr) >> 3) | (*(sptr - 1) << 29)) & + ((*(sptr) >> 2) | (*(sptr - 1) << 30)) & + ((*(sptr) >> 1) | (*(sptr - 1) << 31)) & + (*sptr) & + ((*(sptr) << 1) | (*(sptr + 1) >> 31)) & + ((*(sptr) << 2) | (*(sptr + 1) >> 30)) & + ((*(sptr) << 3) | (*(sptr + 1) >> 29)) & + ((*(sptr) << 4) | (*(sptr + 1) >> 28)) & + ((*(sptr) << 5) | (*(sptr + 1) >> 27)) & + ((*(sptr) << 6) | (*(sptr + 1) >> 26)) & + ((*(sptr) << 7) | (*(sptr + 1) >> 25)) & + ((*(sptr) << 8) | (*(sptr + 1) >> 24)) & + ((*(sptr) << 9) | (*(sptr + 1) >> 23)) & + ((*(sptr) << 10) | (*(sptr + 1) >> 22)) & + ((*(sptr) << 11) | (*(sptr + 1) >> 21)) & + ((*(sptr) << 12) | (*(sptr + 1) >> 20)) & + ((*(sptr) << 13) | (*(sptr + 1) >> 19)) & + ((*(sptr) << 14) | (*(sptr + 1) >> 18)) & + ((*(sptr) << 15) | (*(sptr + 1) >> 17)) & + ((*(sptr) << 16) | (*(sptr + 1) >> 16)) & + ((*(sptr) << 17) | (*(sptr + 1) >> 15)) & + ((*(sptr) << 18) | (*(sptr + 1) >> 14)) & + ((*(sptr) << 19) | (*(sptr + 1) >> 13)); + } + } +} + +static void +fdilate_3_39(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; + + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = ((*(sptr) << 20) | (*(sptr + 1) >> 12)) | + ((*(sptr) << 19) | (*(sptr + 1) >> 13)) | + ((*(sptr) << 18) | (*(sptr + 1) >> 14)) | + ((*(sptr) << 17) | (*(sptr + 1) >> 15)) | + ((*(sptr) << 16) | (*(sptr + 1) >> 16)) | + ((*(sptr) << 15) | (*(sptr + 1) >> 17)) | + ((*(sptr) << 14) | (*(sptr + 1) >> 18)) | + ((*(sptr) << 13) | (*(sptr + 1) >> 19)) | + ((*(sptr) << 12) | (*(sptr + 1) >> 20)) | + ((*(sptr) << 11) | (*(sptr + 1) >> 21)) | + ((*(sptr) << 10) | (*(sptr + 1) >> 22)) | + ((*(sptr) << 9) | (*(sptr + 1) >> 23)) | + ((*(sptr) << 8) | (*(sptr + 1) >> 24)) | + ((*(sptr) << 7) | (*(sptr + 1) >> 25)) | + ((*(sptr) << 6) | (*(sptr + 1) >> 26)) | + ((*(sptr) << 5) | (*(sptr + 1) >> 27)) | + ((*(sptr) << 4) | (*(sptr + 1) >> 28)) | + ((*(sptr) << 3) | (*(sptr + 1) >> 29)) | + ((*(sptr) << 2) | (*(sptr + 1) >> 30)) | + ((*(sptr) << 1) | (*(sptr + 1) >> 31)) | + (*sptr) | + ((*(sptr) >> 1) | (*(sptr - 1) << 31)) | + ((*(sptr) >> 2) | (*(sptr - 1) << 30)) | + ((*(sptr) >> 3) | (*(sptr - 1) << 29)) | + ((*(sptr) >> 4) | (*(sptr - 1) << 28)) | + ((*(sptr) >> 5) | (*(sptr - 1) << 27)) | + ((*(sptr) >> 6) | (*(sptr - 1) << 26)) | + ((*(sptr) >> 7) | (*(sptr - 1) << 25)) | + ((*(sptr) >> 8) | (*(sptr - 1) << 24)) | + ((*(sptr) >> 9) | (*(sptr - 1) << 23)) | + ((*(sptr) >> 10) | (*(sptr - 1) << 22)) | + ((*(sptr) >> 11) | (*(sptr - 1) << 21)) | + ((*(sptr) >> 12) | (*(sptr - 1) << 20)) | + ((*(sptr) >> 13) | (*(sptr - 1) << 19)) | + ((*(sptr) >> 14) | (*(sptr - 1) << 18)) | + ((*(sptr) >> 15) | (*(sptr - 1) << 17)) | + ((*(sptr) >> 16) | (*(sptr - 1) << 16)) | + ((*(sptr) >> 17) | (*(sptr - 1) << 15)) | + ((*(sptr) >> 18) | (*(sptr - 1) << 14)) | + ((*(sptr) >> 19) | (*(sptr - 1) << 13)) | + ((*(sptr) >> 20) | (*(sptr - 1) << 12)); + } + } +} + +static void +ferode_3_39(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; + + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = ((*(sptr) >> 20) | (*(sptr - 1) << 12)) & + ((*(sptr) >> 19) | (*(sptr - 1) << 13)) & + ((*(sptr) >> 18) | (*(sptr - 1) << 14)) & + ((*(sptr) >> 17) | (*(sptr - 1) << 15)) & + ((*(sptr) >> 16) | (*(sptr - 1) << 16)) & + ((*(sptr) >> 15) | (*(sptr - 1) << 17)) & + ((*(sptr) >> 14) | (*(sptr - 1) << 18)) & + ((*(sptr) >> 13) | (*(sptr - 1) << 19)) & + ((*(sptr) >> 12) | (*(sptr - 1) << 20)) & + ((*(sptr) >> 11) | (*(sptr - 1) << 21)) & + ((*(sptr) >> 10) | (*(sptr - 1) << 22)) & + ((*(sptr) >> 9) | (*(sptr - 1) << 23)) & + ((*(sptr) >> 8) | (*(sptr - 1) << 24)) & + ((*(sptr) >> 7) | (*(sptr - 1) << 25)) & + ((*(sptr) >> 6) | (*(sptr - 1) << 26)) & + ((*(sptr) >> 5) | (*(sptr - 1) << 27)) & + ((*(sptr) >> 4) | (*(sptr - 1) << 28)) & + ((*(sptr) >> 3) | (*(sptr - 1) << 29)) & + ((*(sptr) >> 2) | (*(sptr - 1) << 30)) & + ((*(sptr) >> 1) | (*(sptr - 1) << 31)) & + (*sptr) & + ((*(sptr) << 1) | (*(sptr + 1) >> 31)) & + ((*(sptr) << 2) | (*(sptr + 1) >> 30)) & + ((*(sptr) << 3) | (*(sptr + 1) >> 29)) & + ((*(sptr) << 4) | (*(sptr + 1) >> 28)) & + ((*(sptr) << 5) | (*(sptr + 1) >> 27)) & + ((*(sptr) << 6) | (*(sptr + 1) >> 26)) & + ((*(sptr) << 7) | (*(sptr + 1) >> 25)) & + ((*(sptr) << 8) | (*(sptr + 1) >> 24)) & + ((*(sptr) << 9) | (*(sptr + 1) >> 23)) & + ((*(sptr) << 10) | (*(sptr + 1) >> 22)) & + ((*(sptr) << 11) | (*(sptr + 1) >> 21)) & + ((*(sptr) << 12) | (*(sptr + 1) >> 20)) & + ((*(sptr) << 13) | (*(sptr + 1) >> 19)) & + ((*(sptr) << 14) | (*(sptr + 1) >> 18)) & + ((*(sptr) << 15) | (*(sptr + 1) >> 17)) & + ((*(sptr) << 16) | (*(sptr + 1) >> 16)) & + ((*(sptr) << 17) | (*(sptr + 1) >> 15)) & + ((*(sptr) << 18) | (*(sptr + 1) >> 14)) & + ((*(sptr) << 19) | (*(sptr + 1) >> 13)) & + ((*(sptr) << 20) | (*(sptr + 1) >> 12)); + } + } +} + +static void +fdilate_3_40(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; + + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = ((*(sptr) << 21) | (*(sptr + 1) >> 11)) | + ((*(sptr) << 20) | (*(sptr + 1) >> 12)) | + ((*(sptr) << 19) | (*(sptr + 1) >> 13)) | + ((*(sptr) << 18) | (*(sptr + 1) >> 14)) | + ((*(sptr) << 17) | (*(sptr + 1) >> 15)) | + ((*(sptr) << 16) | (*(sptr + 1) >> 16)) | + ((*(sptr) << 15) | (*(sptr + 1) >> 17)) | + ((*(sptr) << 14) | (*(sptr + 1) >> 18)) | + ((*(sptr) << 13) | (*(sptr + 1) >> 19)) | + ((*(sptr) << 12) | (*(sptr + 1) >> 20)) | + ((*(sptr) << 11) | (*(sptr + 1) >> 21)) | + ((*(sptr) << 10) | (*(sptr + 1) >> 22)) | + ((*(sptr) << 9) | (*(sptr + 1) >> 23)) | + ((*(sptr) << 8) | (*(sptr + 1) >> 24)) | + ((*(sptr) << 7) | (*(sptr + 1) >> 25)) | + ((*(sptr) << 6) | (*(sptr + 1) >> 26)) | + ((*(sptr) << 5) | (*(sptr + 1) >> 27)) | + ((*(sptr) << 4) | (*(sptr + 1) >> 28)) | + ((*(sptr) << 3) | (*(sptr + 1) >> 29)) | + ((*(sptr) << 2) | (*(sptr + 1) >> 30)) | + ((*(sptr) << 1) | (*(sptr + 1) >> 31)) | + (*sptr) | + ((*(sptr) >> 1) | (*(sptr - 1) << 31)) | + ((*(sptr) >> 2) | (*(sptr - 1) << 30)) | + ((*(sptr) >> 3) | (*(sptr - 1) << 29)) | + ((*(sptr) >> 4) | (*(sptr - 1) << 28)) | + ((*(sptr) >> 5) | (*(sptr - 1) << 27)) | + ((*(sptr) >> 6) | (*(sptr - 1) << 26)) | + ((*(sptr) >> 7) | (*(sptr - 1) << 25)) | + ((*(sptr) >> 8) | (*(sptr - 1) << 24)) | + ((*(sptr) >> 9) | (*(sptr - 1) << 23)) | + ((*(sptr) >> 10) | (*(sptr - 1) << 22)) | + ((*(sptr) >> 11) | (*(sptr - 1) << 21)) | + ((*(sptr) >> 12) | (*(sptr - 1) << 20)) | + ((*(sptr) >> 13) | (*(sptr - 1) << 19)) | + ((*(sptr) >> 14) | (*(sptr - 1) << 18)) | + ((*(sptr) >> 15) | (*(sptr - 1) << 17)) | + ((*(sptr) >> 16) | (*(sptr - 1) << 16)) | + ((*(sptr) >> 17) | (*(sptr - 1) << 15)) | + ((*(sptr) >> 18) | (*(sptr - 1) << 14)) | + ((*(sptr) >> 19) | (*(sptr - 1) << 13)) | + ((*(sptr) >> 20) | (*(sptr - 1) << 12)); + } + } +} + +static void +ferode_3_40(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; + + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = ((*(sptr) >> 21) | (*(sptr - 1) << 11)) & + ((*(sptr) >> 20) | (*(sptr - 1) << 12)) & + ((*(sptr) >> 19) | (*(sptr - 1) << 13)) & + ((*(sptr) >> 18) | (*(sptr - 1) << 14)) & + ((*(sptr) >> 17) | (*(sptr - 1) << 15)) & + ((*(sptr) >> 16) | (*(sptr - 1) << 16)) & + ((*(sptr) >> 15) | (*(sptr - 1) << 17)) & + ((*(sptr) >> 14) | (*(sptr - 1) << 18)) & + ((*(sptr) >> 13) | (*(sptr - 1) << 19)) & + ((*(sptr) >> 12) | (*(sptr - 1) << 20)) & + ((*(sptr) >> 11) | (*(sptr - 1) << 21)) & + ((*(sptr) >> 10) | (*(sptr - 1) << 22)) & + ((*(sptr) >> 9) | (*(sptr - 1) << 23)) & + ((*(sptr) >> 8) | (*(sptr - 1) << 24)) & + ((*(sptr) >> 7) | (*(sptr - 1) << 25)) & + ((*(sptr) >> 6) | (*(sptr - 1) << 26)) & + ((*(sptr) >> 5) | (*(sptr - 1) << 27)) & + ((*(sptr) >> 4) | (*(sptr - 1) << 28)) & + ((*(sptr) >> 3) | (*(sptr - 1) << 29)) & + ((*(sptr) >> 2) | (*(sptr - 1) << 30)) & + ((*(sptr) >> 1) | (*(sptr - 1) << 31)) & + (*sptr) & + ((*(sptr) << 1) | (*(sptr + 1) >> 31)) & + ((*(sptr) << 2) | (*(sptr + 1) >> 30)) & + ((*(sptr) << 3) | (*(sptr + 1) >> 29)) & + ((*(sptr) << 4) | (*(sptr + 1) >> 28)) & + ((*(sptr) << 5) | (*(sptr + 1) >> 27)) & + ((*(sptr) << 6) | (*(sptr + 1) >> 26)) & + ((*(sptr) << 7) | (*(sptr + 1) >> 25)) & + ((*(sptr) << 8) | (*(sptr + 1) >> 24)) & + ((*(sptr) << 9) | (*(sptr + 1) >> 23)) & + ((*(sptr) << 10) | (*(sptr + 1) >> 22)) & + ((*(sptr) << 11) | (*(sptr + 1) >> 21)) & + ((*(sptr) << 12) | (*(sptr + 1) >> 20)) & + ((*(sptr) << 13) | (*(sptr + 1) >> 19)) & + ((*(sptr) << 14) | (*(sptr + 1) >> 18)) & + ((*(sptr) << 15) | (*(sptr + 1) >> 17)) & + ((*(sptr) << 16) | (*(sptr + 1) >> 16)) & + ((*(sptr) << 17) | (*(sptr + 1) >> 15)) & + ((*(sptr) << 18) | (*(sptr + 1) >> 14)) & + ((*(sptr) << 19) | (*(sptr + 1) >> 13)) & + ((*(sptr) << 20) | (*(sptr + 1) >> 12)); + } + } +} + +static void +fdilate_3_41(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; + + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = ((*(sptr) << 21) | (*(sptr + 1) >> 11)) | + ((*(sptr) << 20) | (*(sptr + 1) >> 12)) | + ((*(sptr) << 19) | (*(sptr + 1) >> 13)) | + ((*(sptr) << 18) | (*(sptr + 1) >> 14)) | + ((*(sptr) << 17) | (*(sptr + 1) >> 15)) | + ((*(sptr) << 16) | (*(sptr + 1) >> 16)) | + ((*(sptr) << 15) | (*(sptr + 1) >> 17)) | + ((*(sptr) << 14) | (*(sptr + 1) >> 18)) | + ((*(sptr) << 13) | (*(sptr + 1) >> 19)) | + ((*(sptr) << 12) | (*(sptr + 1) >> 20)) | + ((*(sptr) << 11) | (*(sptr + 1) >> 21)) | + ((*(sptr) << 10) | (*(sptr + 1) >> 22)) | + ((*(sptr) << 9) | (*(sptr + 1) >> 23)) | + ((*(sptr) << 8) | (*(sptr + 1) >> 24)) | + ((*(sptr) << 7) | (*(sptr + 1) >> 25)) | + ((*(sptr) << 6) | (*(sptr + 1) >> 26)) | + ((*(sptr) << 5) | (*(sptr + 1) >> 27)) | + ((*(sptr) << 4) | (*(sptr + 1) >> 28)) | + ((*(sptr) << 3) | (*(sptr + 1) >> 29)) | + ((*(sptr) << 2) | (*(sptr + 1) >> 30)) | + ((*(sptr) << 1) | (*(sptr + 1) >> 31)) | + (*sptr) | + ((*(sptr) >> 1) | (*(sptr - 1) << 31)) | + ((*(sptr) >> 2) | (*(sptr - 1) << 30)) | + ((*(sptr) >> 3) | (*(sptr - 1) << 29)) | + ((*(sptr) >> 4) | (*(sptr - 1) << 28)) | + ((*(sptr) >> 5) | (*(sptr - 1) << 27)) | + ((*(sptr) >> 6) | (*(sptr - 1) << 26)) | + ((*(sptr) >> 7) | (*(sptr - 1) << 25)) | + ((*(sptr) >> 8) | (*(sptr - 1) << 24)) | + ((*(sptr) >> 9) | (*(sptr - 1) << 23)) | + ((*(sptr) >> 10) | (*(sptr - 1) << 22)) | + ((*(sptr) >> 11) | (*(sptr - 1) << 21)) | + ((*(sptr) >> 12) | (*(sptr - 1) << 20)) | + ((*(sptr) >> 13) | (*(sptr - 1) << 19)) | + ((*(sptr) >> 14) | (*(sptr - 1) << 18)) | + ((*(sptr) >> 15) | (*(sptr - 1) << 17)) | + ((*(sptr) >> 16) | (*(sptr - 1) << 16)) | + ((*(sptr) >> 17) | (*(sptr - 1) << 15)) | + ((*(sptr) >> 18) | (*(sptr - 1) << 14)) | + ((*(sptr) >> 19) | (*(sptr - 1) << 13)) | + ((*(sptr) >> 20) | (*(sptr - 1) << 12)) | + ((*(sptr) >> 21) | (*(sptr - 1) << 11)); + } + } +} + +static void +ferode_3_41(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; + + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = ((*(sptr) >> 21) | (*(sptr - 1) << 11)) & + ((*(sptr) >> 20) | (*(sptr - 1) << 12)) & + ((*(sptr) >> 19) | (*(sptr - 1) << 13)) & + ((*(sptr) >> 18) | (*(sptr - 1) << 14)) & + ((*(sptr) >> 17) | (*(sptr - 1) << 15)) & + ((*(sptr) >> 16) | (*(sptr - 1) << 16)) & + ((*(sptr) >> 15) | (*(sptr - 1) << 17)) & + ((*(sptr) >> 14) | (*(sptr - 1) << 18)) & + ((*(sptr) >> 13) | (*(sptr - 1) << 19)) & + ((*(sptr) >> 12) | (*(sptr - 1) << 20)) & + ((*(sptr) >> 11) | (*(sptr - 1) << 21)) & + ((*(sptr) >> 10) | (*(sptr - 1) << 22)) & + ((*(sptr) >> 9) | (*(sptr - 1) << 23)) & + ((*(sptr) >> 8) | (*(sptr - 1) << 24)) & + ((*(sptr) >> 7) | (*(sptr - 1) << 25)) & + ((*(sptr) >> 6) | (*(sptr - 1) << 26)) & + ((*(sptr) >> 5) | (*(sptr - 1) << 27)) & + ((*(sptr) >> 4) | (*(sptr - 1) << 28)) & + ((*(sptr) >> 3) | (*(sptr - 1) << 29)) & + ((*(sptr) >> 2) | (*(sptr - 1) << 30)) & + ((*(sptr) >> 1) | (*(sptr - 1) << 31)) & + (*sptr) & + ((*(sptr) << 1) | (*(sptr + 1) >> 31)) & + ((*(sptr) << 2) | (*(sptr + 1) >> 30)) & + ((*(sptr) << 3) | (*(sptr + 1) >> 29)) & + ((*(sptr) << 4) | (*(sptr + 1) >> 28)) & + ((*(sptr) << 5) | (*(sptr + 1) >> 27)) & + ((*(sptr) << 6) | (*(sptr + 1) >> 26)) & + ((*(sptr) << 7) | (*(sptr + 1) >> 25)) & + ((*(sptr) << 8) | (*(sptr + 1) >> 24)) & + ((*(sptr) << 9) | (*(sptr + 1) >> 23)) & + ((*(sptr) << 10) | (*(sptr + 1) >> 22)) & + ((*(sptr) << 11) | (*(sptr + 1) >> 21)) & + ((*(sptr) << 12) | (*(sptr + 1) >> 20)) & + ((*(sptr) << 13) | (*(sptr + 1) >> 19)) & + ((*(sptr) << 14) | (*(sptr + 1) >> 18)) & + ((*(sptr) << 15) | (*(sptr + 1) >> 17)) & + ((*(sptr) << 16) | (*(sptr + 1) >> 16)) & + ((*(sptr) << 17) | (*(sptr + 1) >> 15)) & + ((*(sptr) << 18) | (*(sptr + 1) >> 14)) & + ((*(sptr) << 19) | (*(sptr + 1) >> 13)) & + ((*(sptr) << 20) | (*(sptr + 1) >> 12)) & + ((*(sptr) << 21) | (*(sptr + 1) >> 11)); + } + } +} + +static void +fdilate_3_42(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; + + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = ((*(sptr) << 22) | (*(sptr + 1) >> 10)) | + ((*(sptr) << 21) | (*(sptr + 1) >> 11)) | + ((*(sptr) << 20) | (*(sptr + 1) >> 12)) | + ((*(sptr) << 19) | (*(sptr + 1) >> 13)) | + ((*(sptr) << 18) | (*(sptr + 1) >> 14)) | + ((*(sptr) << 17) | (*(sptr + 1) >> 15)) | + ((*(sptr) << 16) | (*(sptr + 1) >> 16)) | + ((*(sptr) << 15) | (*(sptr + 1) >> 17)) | + ((*(sptr) << 14) | (*(sptr + 1) >> 18)) | + ((*(sptr) << 13) | (*(sptr + 1) >> 19)) | + ((*(sptr) << 12) | (*(sptr + 1) >> 20)) | + ((*(sptr) << 11) | (*(sptr + 1) >> 21)) | + ((*(sptr) << 10) | (*(sptr + 1) >> 22)) | + ((*(sptr) << 9) | (*(sptr + 1) >> 23)) | + ((*(sptr) << 8) | (*(sptr + 1) >> 24)) | + ((*(sptr) << 7) | (*(sptr + 1) >> 25)) | + ((*(sptr) << 6) | (*(sptr + 1) >> 26)) | + ((*(sptr) << 5) | (*(sptr + 1) >> 27)) | + ((*(sptr) << 4) | (*(sptr + 1) >> 28)) | + ((*(sptr) << 3) | (*(sptr + 1) >> 29)) | + ((*(sptr) << 2) | (*(sptr + 1) >> 30)) | + ((*(sptr) << 1) | (*(sptr + 1) >> 31)) | + (*sptr) | + ((*(sptr) >> 1) | (*(sptr - 1) << 31)) | + ((*(sptr) >> 2) | (*(sptr - 1) << 30)) | + ((*(sptr) >> 3) | (*(sptr - 1) << 29)) | + ((*(sptr) >> 4) | (*(sptr - 1) << 28)) | + ((*(sptr) >> 5) | (*(sptr - 1) << 27)) | + ((*(sptr) >> 6) | (*(sptr - 1) << 26)) | + ((*(sptr) >> 7) | (*(sptr - 1) << 25)) | + ((*(sptr) >> 8) | (*(sptr - 1) << 24)) | + ((*(sptr) >> 9) | (*(sptr - 1) << 23)) | + ((*(sptr) >> 10) | (*(sptr - 1) << 22)) | + ((*(sptr) >> 11) | (*(sptr - 1) << 21)) | + ((*(sptr) >> 12) | (*(sptr - 1) << 20)) | + ((*(sptr) >> 13) | (*(sptr - 1) << 19)) | + ((*(sptr) >> 14) | (*(sptr - 1) << 18)) | + ((*(sptr) >> 15) | (*(sptr - 1) << 17)) | + ((*(sptr) >> 16) | (*(sptr - 1) << 16)) | + ((*(sptr) >> 17) | (*(sptr - 1) << 15)) | + ((*(sptr) >> 18) | (*(sptr - 1) << 14)) | + ((*(sptr) >> 19) | (*(sptr - 1) << 13)) | + ((*(sptr) >> 20) | (*(sptr - 1) << 12)) | + ((*(sptr) >> 21) | (*(sptr - 1) << 11)); + } + } +} + +static void +ferode_3_42(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; + + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = ((*(sptr) >> 22) | (*(sptr - 1) << 10)) & + ((*(sptr) >> 21) | (*(sptr - 1) << 11)) & + ((*(sptr) >> 20) | (*(sptr - 1) << 12)) & + ((*(sptr) >> 19) | (*(sptr - 1) << 13)) & + ((*(sptr) >> 18) | (*(sptr - 1) << 14)) & + ((*(sptr) >> 17) | (*(sptr - 1) << 15)) & + ((*(sptr) >> 16) | (*(sptr - 1) << 16)) & + ((*(sptr) >> 15) | (*(sptr - 1) << 17)) & + ((*(sptr) >> 14) | (*(sptr - 1) << 18)) & + ((*(sptr) >> 13) | (*(sptr - 1) << 19)) & + ((*(sptr) >> 12) | (*(sptr - 1) << 20)) & + ((*(sptr) >> 11) | (*(sptr - 1) << 21)) & + ((*(sptr) >> 10) | (*(sptr - 1) << 22)) & + ((*(sptr) >> 9) | (*(sptr - 1) << 23)) & + ((*(sptr) >> 8) | (*(sptr - 1) << 24)) & + ((*(sptr) >> 7) | (*(sptr - 1) << 25)) & + ((*(sptr) >> 6) | (*(sptr - 1) << 26)) & + ((*(sptr) >> 5) | (*(sptr - 1) << 27)) & + ((*(sptr) >> 4) | (*(sptr - 1) << 28)) & + ((*(sptr) >> 3) | (*(sptr - 1) << 29)) & + ((*(sptr) >> 2) | (*(sptr - 1) << 30)) & + ((*(sptr) >> 1) | (*(sptr - 1) << 31)) & + (*sptr) & + ((*(sptr) << 1) | (*(sptr + 1) >> 31)) & + ((*(sptr) << 2) | (*(sptr + 1) >> 30)) & + ((*(sptr) << 3) | (*(sptr + 1) >> 29)) & + ((*(sptr) << 4) | (*(sptr + 1) >> 28)) & + ((*(sptr) << 5) | (*(sptr + 1) >> 27)) & + ((*(sptr) << 6) | (*(sptr + 1) >> 26)) & + ((*(sptr) << 7) | (*(sptr + 1) >> 25)) & + ((*(sptr) << 8) | (*(sptr + 1) >> 24)) & + ((*(sptr) << 9) | (*(sptr + 1) >> 23)) & + ((*(sptr) << 10) | (*(sptr + 1) >> 22)) & + ((*(sptr) << 11) | (*(sptr + 1) >> 21)) & + ((*(sptr) << 12) | (*(sptr + 1) >> 20)) & + ((*(sptr) << 13) | (*(sptr + 1) >> 19)) & + ((*(sptr) << 14) | (*(sptr + 1) >> 18)) & + ((*(sptr) << 15) | (*(sptr + 1) >> 17)) & + ((*(sptr) << 16) | (*(sptr + 1) >> 16)) & + ((*(sptr) << 17) | (*(sptr + 1) >> 15)) & + ((*(sptr) << 18) | (*(sptr + 1) >> 14)) & + ((*(sptr) << 19) | (*(sptr + 1) >> 13)) & + ((*(sptr) << 20) | (*(sptr + 1) >> 12)) & + ((*(sptr) << 21) | (*(sptr + 1) >> 11)); + } + } +} + +static void +fdilate_3_43(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; + + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = ((*(sptr) << 22) | (*(sptr + 1) >> 10)) | + ((*(sptr) << 21) | (*(sptr + 1) >> 11)) | + ((*(sptr) << 20) | (*(sptr + 1) >> 12)) | + ((*(sptr) << 19) | (*(sptr + 1) >> 13)) | + ((*(sptr) << 18) | (*(sptr + 1) >> 14)) | + ((*(sptr) << 17) | (*(sptr + 1) >> 15)) | + ((*(sptr) << 16) | (*(sptr + 1) >> 16)) | + ((*(sptr) << 15) | (*(sptr + 1) >> 17)) | + ((*(sptr) << 14) | (*(sptr + 1) >> 18)) | + ((*(sptr) << 13) | (*(sptr + 1) >> 19)) | + ((*(sptr) << 12) | (*(sptr + 1) >> 20)) | + ((*(sptr) << 11) | (*(sptr + 1) >> 21)) | + ((*(sptr) << 10) | (*(sptr + 1) >> 22)) | + ((*(sptr) << 9) | (*(sptr + 1) >> 23)) | + ((*(sptr) << 8) | (*(sptr + 1) >> 24)) | + ((*(sptr) << 7) | (*(sptr + 1) >> 25)) | + ((*(sptr) << 6) | (*(sptr + 1) >> 26)) | + ((*(sptr) << 5) | (*(sptr + 1) >> 27)) | + ((*(sptr) << 4) | (*(sptr + 1) >> 28)) | + ((*(sptr) << 3) | (*(sptr + 1) >> 29)) | + ((*(sptr) << 2) | (*(sptr + 1) >> 30)) | + ((*(sptr) << 1) | (*(sptr + 1) >> 31)) | + (*sptr) | + ((*(sptr) >> 1) | (*(sptr - 1) << 31)) | + ((*(sptr) >> 2) | (*(sptr - 1) << 30)) | + ((*(sptr) >> 3) | (*(sptr - 1) << 29)) | + ((*(sptr) >> 4) | (*(sptr - 1) << 28)) | + ((*(sptr) >> 5) | (*(sptr - 1) << 27)) | + ((*(sptr) >> 6) | (*(sptr - 1) << 26)) | + ((*(sptr) >> 7) | (*(sptr - 1) << 25)) | + ((*(sptr) >> 8) | (*(sptr - 1) << 24)) | + ((*(sptr) >> 9) | (*(sptr - 1) << 23)) | + ((*(sptr) >> 10) | (*(sptr - 1) << 22)) | + ((*(sptr) >> 11) | (*(sptr - 1) << 21)) | + ((*(sptr) >> 12) | (*(sptr - 1) << 20)) | + ((*(sptr) >> 13) | (*(sptr - 1) << 19)) | + ((*(sptr) >> 14) | (*(sptr - 1) << 18)) | + ((*(sptr) >> 15) | (*(sptr - 1) << 17)) | + ((*(sptr) >> 16) | (*(sptr - 1) << 16)) | + ((*(sptr) >> 17) | (*(sptr - 1) << 15)) | + ((*(sptr) >> 18) | (*(sptr - 1) << 14)) | + ((*(sptr) >> 19) | (*(sptr - 1) << 13)) | + ((*(sptr) >> 20) | (*(sptr - 1) << 12)) | + ((*(sptr) >> 21) | (*(sptr - 1) << 11)) | + ((*(sptr) >> 22) | (*(sptr - 1) << 10)); + } + } +} + +static void +ferode_3_43(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; + + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = ((*(sptr) >> 22) | (*(sptr - 1) << 10)) & + ((*(sptr) >> 21) | (*(sptr - 1) << 11)) & + ((*(sptr) >> 20) | (*(sptr - 1) << 12)) & + ((*(sptr) >> 19) | (*(sptr - 1) << 13)) & + ((*(sptr) >> 18) | (*(sptr - 1) << 14)) & + ((*(sptr) >> 17) | (*(sptr - 1) << 15)) & + ((*(sptr) >> 16) | (*(sptr - 1) << 16)) & + ((*(sptr) >> 15) | (*(sptr - 1) << 17)) & + ((*(sptr) >> 14) | (*(sptr - 1) << 18)) & + ((*(sptr) >> 13) | (*(sptr - 1) << 19)) & + ((*(sptr) >> 12) | (*(sptr - 1) << 20)) & + ((*(sptr) >> 11) | (*(sptr - 1) << 21)) & + ((*(sptr) >> 10) | (*(sptr - 1) << 22)) & + ((*(sptr) >> 9) | (*(sptr - 1) << 23)) & + ((*(sptr) >> 8) | (*(sptr - 1) << 24)) & + ((*(sptr) >> 7) | (*(sptr - 1) << 25)) & + ((*(sptr) >> 6) | (*(sptr - 1) << 26)) & + ((*(sptr) >> 5) | (*(sptr - 1) << 27)) & + ((*(sptr) >> 4) | (*(sptr - 1) << 28)) & + ((*(sptr) >> 3) | (*(sptr - 1) << 29)) & + ((*(sptr) >> 2) | (*(sptr - 1) << 30)) & + ((*(sptr) >> 1) | (*(sptr - 1) << 31)) & + (*sptr) & + ((*(sptr) << 1) | (*(sptr + 1) >> 31)) & + ((*(sptr) << 2) | (*(sptr + 1) >> 30)) & + ((*(sptr) << 3) | (*(sptr + 1) >> 29)) & + ((*(sptr) << 4) | (*(sptr + 1) >> 28)) & + ((*(sptr) << 5) | (*(sptr + 1) >> 27)) & + ((*(sptr) << 6) | (*(sptr + 1) >> 26)) & + ((*(sptr) << 7) | (*(sptr + 1) >> 25)) & + ((*(sptr) << 8) | (*(sptr + 1) >> 24)) & + ((*(sptr) << 9) | (*(sptr + 1) >> 23)) & + ((*(sptr) << 10) | (*(sptr + 1) >> 22)) & + ((*(sptr) << 11) | (*(sptr + 1) >> 21)) & + ((*(sptr) << 12) | (*(sptr + 1) >> 20)) & + ((*(sptr) << 13) | (*(sptr + 1) >> 19)) & + ((*(sptr) << 14) | (*(sptr + 1) >> 18)) & + ((*(sptr) << 15) | (*(sptr + 1) >> 17)) & + ((*(sptr) << 16) | (*(sptr + 1) >> 16)) & + ((*(sptr) << 17) | (*(sptr + 1) >> 15)) & + ((*(sptr) << 18) | (*(sptr + 1) >> 14)) & + ((*(sptr) << 19) | (*(sptr + 1) >> 13)) & + ((*(sptr) << 20) | (*(sptr + 1) >> 12)) & + ((*(sptr) << 21) | (*(sptr + 1) >> 11)) & + ((*(sptr) << 22) | (*(sptr + 1) >> 10)); + } + } +} + +static void +fdilate_3_44(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; + + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = ((*(sptr) << 23) | (*(sptr + 1) >> 9)) | + ((*(sptr) << 22) | (*(sptr + 1) >> 10)) | + ((*(sptr) << 21) | (*(sptr + 1) >> 11)) | + ((*(sptr) << 20) | (*(sptr + 1) >> 12)) | + ((*(sptr) << 19) | (*(sptr + 1) >> 13)) | + ((*(sptr) << 18) | (*(sptr + 1) >> 14)) | + ((*(sptr) << 17) | (*(sptr + 1) >> 15)) | + ((*(sptr) << 16) | (*(sptr + 1) >> 16)) | + ((*(sptr) << 15) | (*(sptr + 1) >> 17)) | + ((*(sptr) << 14) | (*(sptr + 1) >> 18)) | + ((*(sptr) << 13) | (*(sptr + 1) >> 19)) | + ((*(sptr) << 12) | (*(sptr + 1) >> 20)) | + ((*(sptr) << 11) | (*(sptr + 1) >> 21)) | + ((*(sptr) << 10) | (*(sptr + 1) >> 22)) | + ((*(sptr) << 9) | (*(sptr + 1) >> 23)) | + ((*(sptr) << 8) | (*(sptr + 1) >> 24)) | + ((*(sptr) << 7) | (*(sptr + 1) >> 25)) | + ((*(sptr) << 6) | (*(sptr + 1) >> 26)) | + ((*(sptr) << 5) | (*(sptr + 1) >> 27)) | + ((*(sptr) << 4) | (*(sptr + 1) >> 28)) | + ((*(sptr) << 3) | (*(sptr + 1) >> 29)) | + ((*(sptr) << 2) | (*(sptr + 1) >> 30)) | + ((*(sptr) << 1) | (*(sptr + 1) >> 31)) | + (*sptr) | + ((*(sptr) >> 1) | (*(sptr - 1) << 31)) | + ((*(sptr) >> 2) | (*(sptr - 1) << 30)) | + ((*(sptr) >> 3) | (*(sptr - 1) << 29)) | + ((*(sptr) >> 4) | (*(sptr - 1) << 28)) | + ((*(sptr) >> 5) | (*(sptr - 1) << 27)) | + ((*(sptr) >> 6) | (*(sptr - 1) << 26)) | + ((*(sptr) >> 7) | (*(sptr - 1) << 25)) | + ((*(sptr) >> 8) | (*(sptr - 1) << 24)) | + ((*(sptr) >> 9) | (*(sptr - 1) << 23)) | + ((*(sptr) >> 10) | (*(sptr - 1) << 22)) | + ((*(sptr) >> 11) | (*(sptr - 1) << 21)) | + ((*(sptr) >> 12) | (*(sptr - 1) << 20)) | + ((*(sptr) >> 13) | (*(sptr - 1) << 19)) | + ((*(sptr) >> 14) | (*(sptr - 1) << 18)) | + ((*(sptr) >> 15) | (*(sptr - 1) << 17)) | + ((*(sptr) >> 16) | (*(sptr - 1) << 16)) | + ((*(sptr) >> 17) | (*(sptr - 1) << 15)) | + ((*(sptr) >> 18) | (*(sptr - 1) << 14)) | + ((*(sptr) >> 19) | (*(sptr - 1) << 13)) | + ((*(sptr) >> 20) | (*(sptr - 1) << 12)) | + ((*(sptr) >> 21) | (*(sptr - 1) << 11)) | + ((*(sptr) >> 22) | (*(sptr - 1) << 10)); + } + } +} + +static void +ferode_3_44(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; + + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = ((*(sptr) >> 23) | (*(sptr - 1) << 9)) & + ((*(sptr) >> 22) | (*(sptr - 1) << 10)) & + ((*(sptr) >> 21) | (*(sptr - 1) << 11)) & + ((*(sptr) >> 20) | (*(sptr - 1) << 12)) & + ((*(sptr) >> 19) | (*(sptr - 1) << 13)) & + ((*(sptr) >> 18) | (*(sptr - 1) << 14)) & + ((*(sptr) >> 17) | (*(sptr - 1) << 15)) & + ((*(sptr) >> 16) | (*(sptr - 1) << 16)) & + ((*(sptr) >> 15) | (*(sptr - 1) << 17)) & + ((*(sptr) >> 14) | (*(sptr - 1) << 18)) & + ((*(sptr) >> 13) | (*(sptr - 1) << 19)) & + ((*(sptr) >> 12) | (*(sptr - 1) << 20)) & + ((*(sptr) >> 11) | (*(sptr - 1) << 21)) & + ((*(sptr) >> 10) | (*(sptr - 1) << 22)) & + ((*(sptr) >> 9) | (*(sptr - 1) << 23)) & + ((*(sptr) >> 8) | (*(sptr - 1) << 24)) & + ((*(sptr) >> 7) | (*(sptr - 1) << 25)) & + ((*(sptr) >> 6) | (*(sptr - 1) << 26)) & + ((*(sptr) >> 5) | (*(sptr - 1) << 27)) & + ((*(sptr) >> 4) | (*(sptr - 1) << 28)) & + ((*(sptr) >> 3) | (*(sptr - 1) << 29)) & + ((*(sptr) >> 2) | (*(sptr - 1) << 30)) & + ((*(sptr) >> 1) | (*(sptr - 1) << 31)) & + (*sptr) & + ((*(sptr) << 1) | (*(sptr + 1) >> 31)) & + ((*(sptr) << 2) | (*(sptr + 1) >> 30)) & + ((*(sptr) << 3) | (*(sptr + 1) >> 29)) & + ((*(sptr) << 4) | (*(sptr + 1) >> 28)) & + ((*(sptr) << 5) | (*(sptr + 1) >> 27)) & + ((*(sptr) << 6) | (*(sptr + 1) >> 26)) & + ((*(sptr) << 7) | (*(sptr + 1) >> 25)) & + ((*(sptr) << 8) | (*(sptr + 1) >> 24)) & + ((*(sptr) << 9) | (*(sptr + 1) >> 23)) & + ((*(sptr) << 10) | (*(sptr + 1) >> 22)) & + ((*(sptr) << 11) | (*(sptr + 1) >> 21)) & + ((*(sptr) << 12) | (*(sptr + 1) >> 20)) & + ((*(sptr) << 13) | (*(sptr + 1) >> 19)) & + ((*(sptr) << 14) | (*(sptr + 1) >> 18)) & + ((*(sptr) << 15) | (*(sptr + 1) >> 17)) & + ((*(sptr) << 16) | (*(sptr + 1) >> 16)) & + ((*(sptr) << 17) | (*(sptr + 1) >> 15)) & + ((*(sptr) << 18) | (*(sptr + 1) >> 14)) & + ((*(sptr) << 19) | (*(sptr + 1) >> 13)) & + ((*(sptr) << 20) | (*(sptr + 1) >> 12)) & + ((*(sptr) << 21) | (*(sptr + 1) >> 11)) & + ((*(sptr) << 22) | (*(sptr + 1) >> 10)); + } + } +} + +static void +fdilate_3_45(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; + + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = ((*(sptr) << 23) | (*(sptr + 1) >> 9)) | + ((*(sptr) << 22) | (*(sptr + 1) >> 10)) | + ((*(sptr) << 21) | (*(sptr + 1) >> 11)) | + ((*(sptr) << 20) | (*(sptr + 1) >> 12)) | + ((*(sptr) << 19) | (*(sptr + 1) >> 13)) | + ((*(sptr) << 18) | (*(sptr + 1) >> 14)) | + ((*(sptr) << 17) | (*(sptr + 1) >> 15)) | + ((*(sptr) << 16) | (*(sptr + 1) >> 16)) | + ((*(sptr) << 15) | (*(sptr + 1) >> 17)) | + ((*(sptr) << 14) | (*(sptr + 1) >> 18)) | + ((*(sptr) << 13) | (*(sptr + 1) >> 19)) | + ((*(sptr) << 12) | (*(sptr + 1) >> 20)) | + ((*(sptr) << 11) | (*(sptr + 1) >> 21)) | + ((*(sptr) << 10) | (*(sptr + 1) >> 22)) | + ((*(sptr) << 9) | (*(sptr + 1) >> 23)) | + ((*(sptr) << 8) | (*(sptr + 1) >> 24)) | + ((*(sptr) << 7) | (*(sptr + 1) >> 25)) | + ((*(sptr) << 6) | (*(sptr + 1) >> 26)) | + ((*(sptr) << 5) | (*(sptr + 1) >> 27)) | + ((*(sptr) << 4) | (*(sptr + 1) >> 28)) | + ((*(sptr) << 3) | (*(sptr + 1) >> 29)) | + ((*(sptr) << 2) | (*(sptr + 1) >> 30)) | + ((*(sptr) << 1) | (*(sptr + 1) >> 31)) | + (*sptr) | + ((*(sptr) >> 1) | (*(sptr - 1) << 31)) | + ((*(sptr) >> 2) | (*(sptr - 1) << 30)) | + ((*(sptr) >> 3) | (*(sptr - 1) << 29)) | + ((*(sptr) >> 4) | (*(sptr - 1) << 28)) | + ((*(sptr) >> 5) | (*(sptr - 1) << 27)) | + ((*(sptr) >> 6) | (*(sptr - 1) << 26)) | + ((*(sptr) >> 7) | (*(sptr - 1) << 25)) | + ((*(sptr) >> 8) | (*(sptr - 1) << 24)) | + ((*(sptr) >> 9) | (*(sptr - 1) << 23)) | + ((*(sptr) >> 10) | (*(sptr - 1) << 22)) | + ((*(sptr) >> 11) | (*(sptr - 1) << 21)) | + ((*(sptr) >> 12) | (*(sptr - 1) << 20)) | + ((*(sptr) >> 13) | (*(sptr - 1) << 19)) | + ((*(sptr) >> 14) | (*(sptr - 1) << 18)) | + ((*(sptr) >> 15) | (*(sptr - 1) << 17)) | + ((*(sptr) >> 16) | (*(sptr - 1) << 16)) | + ((*(sptr) >> 17) | (*(sptr - 1) << 15)) | + ((*(sptr) >> 18) | (*(sptr - 1) << 14)) | + ((*(sptr) >> 19) | (*(sptr - 1) << 13)) | + ((*(sptr) >> 20) | (*(sptr - 1) << 12)) | + ((*(sptr) >> 21) | (*(sptr - 1) << 11)) | + ((*(sptr) >> 22) | (*(sptr - 1) << 10)) | + ((*(sptr) >> 23) | (*(sptr - 1) << 9)); + } + } +} + +static void +ferode_3_45(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; + + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = ((*(sptr) >> 23) | (*(sptr - 1) << 9)) & + ((*(sptr) >> 22) | (*(sptr - 1) << 10)) & + ((*(sptr) >> 21) | (*(sptr - 1) << 11)) & + ((*(sptr) >> 20) | (*(sptr - 1) << 12)) & + ((*(sptr) >> 19) | (*(sptr - 1) << 13)) & + ((*(sptr) >> 18) | (*(sptr - 1) << 14)) & + ((*(sptr) >> 17) | (*(sptr - 1) << 15)) & + ((*(sptr) >> 16) | (*(sptr - 1) << 16)) & + ((*(sptr) >> 15) | (*(sptr - 1) << 17)) & + ((*(sptr) >> 14) | (*(sptr - 1) << 18)) & + ((*(sptr) >> 13) | (*(sptr - 1) << 19)) & + ((*(sptr) >> 12) | (*(sptr - 1) << 20)) & + ((*(sptr) >> 11) | (*(sptr - 1) << 21)) & + ((*(sptr) >> 10) | (*(sptr - 1) << 22)) & + ((*(sptr) >> 9) | (*(sptr - 1) << 23)) & + ((*(sptr) >> 8) | (*(sptr - 1) << 24)) & + ((*(sptr) >> 7) | (*(sptr - 1) << 25)) & + ((*(sptr) >> 6) | (*(sptr - 1) << 26)) & + ((*(sptr) >> 5) | (*(sptr - 1) << 27)) & + ((*(sptr) >> 4) | (*(sptr - 1) << 28)) & + ((*(sptr) >> 3) | (*(sptr - 1) << 29)) & + ((*(sptr) >> 2) | (*(sptr - 1) << 30)) & + ((*(sptr) >> 1) | (*(sptr - 1) << 31)) & + (*sptr) & + ((*(sptr) << 1) | (*(sptr + 1) >> 31)) & + ((*(sptr) << 2) | (*(sptr + 1) >> 30)) & + ((*(sptr) << 3) | (*(sptr + 1) >> 29)) & + ((*(sptr) << 4) | (*(sptr + 1) >> 28)) & + ((*(sptr) << 5) | (*(sptr + 1) >> 27)) & + ((*(sptr) << 6) | (*(sptr + 1) >> 26)) & + ((*(sptr) << 7) | (*(sptr + 1) >> 25)) & + ((*(sptr) << 8) | (*(sptr + 1) >> 24)) & + ((*(sptr) << 9) | (*(sptr + 1) >> 23)) & + ((*(sptr) << 10) | (*(sptr + 1) >> 22)) & + ((*(sptr) << 11) | (*(sptr + 1) >> 21)) & + ((*(sptr) << 12) | (*(sptr + 1) >> 20)) & + ((*(sptr) << 13) | (*(sptr + 1) >> 19)) & + ((*(sptr) << 14) | (*(sptr + 1) >> 18)) & + ((*(sptr) << 15) | (*(sptr + 1) >> 17)) & + ((*(sptr) << 16) | (*(sptr + 1) >> 16)) & + ((*(sptr) << 17) | (*(sptr + 1) >> 15)) & + ((*(sptr) << 18) | (*(sptr + 1) >> 14)) & + ((*(sptr) << 19) | (*(sptr + 1) >> 13)) & + ((*(sptr) << 20) | (*(sptr + 1) >> 12)) & + ((*(sptr) << 21) | (*(sptr + 1) >> 11)) & + ((*(sptr) << 22) | (*(sptr + 1) >> 10)) & + ((*(sptr) << 23) | (*(sptr + 1) >> 9)); + } + } +} + +static void +fdilate_3_46(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; + + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = ((*(sptr) << 24) | (*(sptr + 1) >> 8)) | + ((*(sptr) << 23) | (*(sptr + 1) >> 9)) | + ((*(sptr) << 22) | (*(sptr + 1) >> 10)) | + ((*(sptr) << 21) | (*(sptr + 1) >> 11)) | + ((*(sptr) << 20) | (*(sptr + 1) >> 12)) | + ((*(sptr) << 19) | (*(sptr + 1) >> 13)) | + ((*(sptr) << 18) | (*(sptr + 1) >> 14)) | + ((*(sptr) << 17) | (*(sptr + 1) >> 15)) | + ((*(sptr) << 16) | (*(sptr + 1) >> 16)) | + ((*(sptr) << 15) | (*(sptr + 1) >> 17)) | + ((*(sptr) << 14) | (*(sptr + 1) >> 18)) | + ((*(sptr) << 13) | (*(sptr + 1) >> 19)) | + ((*(sptr) << 12) | (*(sptr + 1) >> 20)) | + ((*(sptr) << 11) | (*(sptr + 1) >> 21)) | + ((*(sptr) << 10) | (*(sptr + 1) >> 22)) | + ((*(sptr) << 9) | (*(sptr + 1) >> 23)) | + ((*(sptr) << 8) | (*(sptr + 1) >> 24)) | + ((*(sptr) << 7) | (*(sptr + 1) >> 25)) | + ((*(sptr) << 6) | (*(sptr + 1) >> 26)) | + ((*(sptr) << 5) | (*(sptr + 1) >> 27)) | + ((*(sptr) << 4) | (*(sptr + 1) >> 28)) | + ((*(sptr) << 3) | (*(sptr + 1) >> 29)) | + ((*(sptr) << 2) | (*(sptr + 1) >> 30)) | + ((*(sptr) << 1) | (*(sptr + 1) >> 31)) | + (*sptr) | + ((*(sptr) >> 1) | (*(sptr - 1) << 31)) | + ((*(sptr) >> 2) | (*(sptr - 1) << 30)) | + ((*(sptr) >> 3) | (*(sptr - 1) << 29)) | + ((*(sptr) >> 4) | (*(sptr - 1) << 28)) | + ((*(sptr) >> 5) | (*(sptr - 1) << 27)) | + ((*(sptr) >> 6) | (*(sptr - 1) << 26)) | + ((*(sptr) >> 7) | (*(sptr - 1) << 25)) | + ((*(sptr) >> 8) | (*(sptr - 1) << 24)) | + ((*(sptr) >> 9) | (*(sptr - 1) << 23)) | + ((*(sptr) >> 10) | (*(sptr - 1) << 22)) | + ((*(sptr) >> 11) | (*(sptr - 1) << 21)) | + ((*(sptr) >> 12) | (*(sptr - 1) << 20)) | + ((*(sptr) >> 13) | (*(sptr - 1) << 19)) | + ((*(sptr) >> 14) | (*(sptr - 1) << 18)) | + ((*(sptr) >> 15) | (*(sptr - 1) << 17)) | + ((*(sptr) >> 16) | (*(sptr - 1) << 16)) | + ((*(sptr) >> 17) | (*(sptr - 1) << 15)) | + ((*(sptr) >> 18) | (*(sptr - 1) << 14)) | + ((*(sptr) >> 19) | (*(sptr - 1) << 13)) | + ((*(sptr) >> 20) | (*(sptr - 1) << 12)) | + ((*(sptr) >> 21) | (*(sptr - 1) << 11)) | + ((*(sptr) >> 22) | (*(sptr - 1) << 10)) | + ((*(sptr) >> 23) | (*(sptr - 1) << 9)); + } + } +} + +static void +ferode_3_46(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; + + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = ((*(sptr) >> 24) | (*(sptr - 1) << 8)) & + ((*(sptr) >> 23) | (*(sptr - 1) << 9)) & + ((*(sptr) >> 22) | (*(sptr - 1) << 10)) & + ((*(sptr) >> 21) | (*(sptr - 1) << 11)) & + ((*(sptr) >> 20) | (*(sptr - 1) << 12)) & + ((*(sptr) >> 19) | (*(sptr - 1) << 13)) & + ((*(sptr) >> 18) | (*(sptr - 1) << 14)) & + ((*(sptr) >> 17) | (*(sptr - 1) << 15)) & + ((*(sptr) >> 16) | (*(sptr - 1) << 16)) & + ((*(sptr) >> 15) | (*(sptr - 1) << 17)) & + ((*(sptr) >> 14) | (*(sptr - 1) << 18)) & + ((*(sptr) >> 13) | (*(sptr - 1) << 19)) & + ((*(sptr) >> 12) | (*(sptr - 1) << 20)) & + ((*(sptr) >> 11) | (*(sptr - 1) << 21)) & + ((*(sptr) >> 10) | (*(sptr - 1) << 22)) & + ((*(sptr) >> 9) | (*(sptr - 1) << 23)) & + ((*(sptr) >> 8) | (*(sptr - 1) << 24)) & + ((*(sptr) >> 7) | (*(sptr - 1) << 25)) & + ((*(sptr) >> 6) | (*(sptr - 1) << 26)) & + ((*(sptr) >> 5) | (*(sptr - 1) << 27)) & + ((*(sptr) >> 4) | (*(sptr - 1) << 28)) & + ((*(sptr) >> 3) | (*(sptr - 1) << 29)) & + ((*(sptr) >> 2) | (*(sptr - 1) << 30)) & + ((*(sptr) >> 1) | (*(sptr - 1) << 31)) & + (*sptr) & + ((*(sptr) << 1) | (*(sptr + 1) >> 31)) & + ((*(sptr) << 2) | (*(sptr + 1) >> 30)) & + ((*(sptr) << 3) | (*(sptr + 1) >> 29)) & + ((*(sptr) << 4) | (*(sptr + 1) >> 28)) & + ((*(sptr) << 5) | (*(sptr + 1) >> 27)) & + ((*(sptr) << 6) | (*(sptr + 1) >> 26)) & + ((*(sptr) << 7) | (*(sptr + 1) >> 25)) & + ((*(sptr) << 8) | (*(sptr + 1) >> 24)) & + ((*(sptr) << 9) | (*(sptr + 1) >> 23)) & + ((*(sptr) << 10) | (*(sptr + 1) >> 22)) & + ((*(sptr) << 11) | (*(sptr + 1) >> 21)) & + ((*(sptr) << 12) | (*(sptr + 1) >> 20)) & + ((*(sptr) << 13) | (*(sptr + 1) >> 19)) & + ((*(sptr) << 14) | (*(sptr + 1) >> 18)) & + ((*(sptr) << 15) | (*(sptr + 1) >> 17)) & + ((*(sptr) << 16) | (*(sptr + 1) >> 16)) & + ((*(sptr) << 17) | (*(sptr + 1) >> 15)) & + ((*(sptr) << 18) | (*(sptr + 1) >> 14)) & + ((*(sptr) << 19) | (*(sptr + 1) >> 13)) & + ((*(sptr) << 20) | (*(sptr + 1) >> 12)) & + ((*(sptr) << 21) | (*(sptr + 1) >> 11)) & + ((*(sptr) << 22) | (*(sptr + 1) >> 10)) & + ((*(sptr) << 23) | (*(sptr + 1) >> 9)); + } + } +} + +static void +fdilate_3_47(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; + + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = ((*(sptr) << 24) | (*(sptr + 1) >> 8)) | + ((*(sptr) << 23) | (*(sptr + 1) >> 9)) | + ((*(sptr) << 22) | (*(sptr + 1) >> 10)) | + ((*(sptr) << 21) | (*(sptr + 1) >> 11)) | + ((*(sptr) << 20) | (*(sptr + 1) >> 12)) | + ((*(sptr) << 19) | (*(sptr + 1) >> 13)) | + ((*(sptr) << 18) | (*(sptr + 1) >> 14)) | + ((*(sptr) << 17) | (*(sptr + 1) >> 15)) | + ((*(sptr) << 16) | (*(sptr + 1) >> 16)) | + ((*(sptr) << 15) | (*(sptr + 1) >> 17)) | + ((*(sptr) << 14) | (*(sptr + 1) >> 18)) | + ((*(sptr) << 13) | (*(sptr + 1) >> 19)) | + ((*(sptr) << 12) | (*(sptr + 1) >> 20)) | + ((*(sptr) << 11) | (*(sptr + 1) >> 21)) | + ((*(sptr) << 10) | (*(sptr + 1) >> 22)) | + ((*(sptr) << 9) | (*(sptr + 1) >> 23)) | + ((*(sptr) << 8) | (*(sptr + 1) >> 24)) | + ((*(sptr) << 7) | (*(sptr + 1) >> 25)) | + ((*(sptr) << 6) | (*(sptr + 1) >> 26)) | + ((*(sptr) << 5) | (*(sptr + 1) >> 27)) | + ((*(sptr) << 4) | (*(sptr + 1) >> 28)) | + ((*(sptr) << 3) | (*(sptr + 1) >> 29)) | + ((*(sptr) << 2) | (*(sptr + 1) >> 30)) | + ((*(sptr) << 1) | (*(sptr + 1) >> 31)) | + (*sptr) | + ((*(sptr) >> 1) | (*(sptr - 1) << 31)) | + ((*(sptr) >> 2) | (*(sptr - 1) << 30)) | + ((*(sptr) >> 3) | (*(sptr - 1) << 29)) | + ((*(sptr) >> 4) | (*(sptr - 1) << 28)) | + ((*(sptr) >> 5) | (*(sptr - 1) << 27)) | + ((*(sptr) >> 6) | (*(sptr - 1) << 26)) | + ((*(sptr) >> 7) | (*(sptr - 1) << 25)) | + ((*(sptr) >> 8) | (*(sptr - 1) << 24)) | + ((*(sptr) >> 9) | (*(sptr - 1) << 23)) | + ((*(sptr) >> 10) | (*(sptr - 1) << 22)) | + ((*(sptr) >> 11) | (*(sptr - 1) << 21)) | + ((*(sptr) >> 12) | (*(sptr - 1) << 20)) | + ((*(sptr) >> 13) | (*(sptr - 1) << 19)) | + ((*(sptr) >> 14) | (*(sptr - 1) << 18)) | + ((*(sptr) >> 15) | (*(sptr - 1) << 17)) | + ((*(sptr) >> 16) | (*(sptr - 1) << 16)) | + ((*(sptr) >> 17) | (*(sptr - 1) << 15)) | + ((*(sptr) >> 18) | (*(sptr - 1) << 14)) | + ((*(sptr) >> 19) | (*(sptr - 1) << 13)) | + ((*(sptr) >> 20) | (*(sptr - 1) << 12)) | + ((*(sptr) >> 21) | (*(sptr - 1) << 11)) | + ((*(sptr) >> 22) | (*(sptr - 1) << 10)) | + ((*(sptr) >> 23) | (*(sptr - 1) << 9)) | + ((*(sptr) >> 24) | (*(sptr - 1) << 8)); + } + } +} + +static void +ferode_3_47(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; + + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = ((*(sptr) >> 24) | (*(sptr - 1) << 8)) & + ((*(sptr) >> 23) | (*(sptr - 1) << 9)) & + ((*(sptr) >> 22) | (*(sptr - 1) << 10)) & + ((*(sptr) >> 21) | (*(sptr - 1) << 11)) & + ((*(sptr) >> 20) | (*(sptr - 1) << 12)) & + ((*(sptr) >> 19) | (*(sptr - 1) << 13)) & + ((*(sptr) >> 18) | (*(sptr - 1) << 14)) & + ((*(sptr) >> 17) | (*(sptr - 1) << 15)) & + ((*(sptr) >> 16) | (*(sptr - 1) << 16)) & + ((*(sptr) >> 15) | (*(sptr - 1) << 17)) & + ((*(sptr) >> 14) | (*(sptr - 1) << 18)) & + ((*(sptr) >> 13) | (*(sptr - 1) << 19)) & + ((*(sptr) >> 12) | (*(sptr - 1) << 20)) & + ((*(sptr) >> 11) | (*(sptr - 1) << 21)) & + ((*(sptr) >> 10) | (*(sptr - 1) << 22)) & + ((*(sptr) >> 9) | (*(sptr - 1) << 23)) & + ((*(sptr) >> 8) | (*(sptr - 1) << 24)) & + ((*(sptr) >> 7) | (*(sptr - 1) << 25)) & + ((*(sptr) >> 6) | (*(sptr - 1) << 26)) & + ((*(sptr) >> 5) | (*(sptr - 1) << 27)) & + ((*(sptr) >> 4) | (*(sptr - 1) << 28)) & + ((*(sptr) >> 3) | (*(sptr - 1) << 29)) & + ((*(sptr) >> 2) | (*(sptr - 1) << 30)) & + ((*(sptr) >> 1) | (*(sptr - 1) << 31)) & + (*sptr) & + ((*(sptr) << 1) | (*(sptr + 1) >> 31)) & + ((*(sptr) << 2) | (*(sptr + 1) >> 30)) & + ((*(sptr) << 3) | (*(sptr + 1) >> 29)) & + ((*(sptr) << 4) | (*(sptr + 1) >> 28)) & + ((*(sptr) << 5) | (*(sptr + 1) >> 27)) & + ((*(sptr) << 6) | (*(sptr + 1) >> 26)) & + ((*(sptr) << 7) | (*(sptr + 1) >> 25)) & + ((*(sptr) << 8) | (*(sptr + 1) >> 24)) & + ((*(sptr) << 9) | (*(sptr + 1) >> 23)) & + ((*(sptr) << 10) | (*(sptr + 1) >> 22)) & + ((*(sptr) << 11) | (*(sptr + 1) >> 21)) & + ((*(sptr) << 12) | (*(sptr + 1) >> 20)) & + ((*(sptr) << 13) | (*(sptr + 1) >> 19)) & + ((*(sptr) << 14) | (*(sptr + 1) >> 18)) & + ((*(sptr) << 15) | (*(sptr + 1) >> 17)) & + ((*(sptr) << 16) | (*(sptr + 1) >> 16)) & + ((*(sptr) << 17) | (*(sptr + 1) >> 15)) & + ((*(sptr) << 18) | (*(sptr + 1) >> 14)) & + ((*(sptr) << 19) | (*(sptr + 1) >> 13)) & + ((*(sptr) << 20) | (*(sptr + 1) >> 12)) & + ((*(sptr) << 21) | (*(sptr + 1) >> 11)) & + ((*(sptr) << 22) | (*(sptr + 1) >> 10)) & + ((*(sptr) << 23) | (*(sptr + 1) >> 9)) & + ((*(sptr) << 24) | (*(sptr + 1) >> 8)); + } + } +} + +static void +fdilate_3_48(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; + + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = ((*(sptr) << 25) | (*(sptr + 1) >> 7)) | + ((*(sptr) << 24) | (*(sptr + 1) >> 8)) | + ((*(sptr) << 23) | (*(sptr + 1) >> 9)) | + ((*(sptr) << 22) | (*(sptr + 1) >> 10)) | + ((*(sptr) << 21) | (*(sptr + 1) >> 11)) | + ((*(sptr) << 20) | (*(sptr + 1) >> 12)) | + ((*(sptr) << 19) | (*(sptr + 1) >> 13)) | + ((*(sptr) << 18) | (*(sptr + 1) >> 14)) | + ((*(sptr) << 17) | (*(sptr + 1) >> 15)) | + ((*(sptr) << 16) | (*(sptr + 1) >> 16)) | + ((*(sptr) << 15) | (*(sptr + 1) >> 17)) | + ((*(sptr) << 14) | (*(sptr + 1) >> 18)) | + ((*(sptr) << 13) | (*(sptr + 1) >> 19)) | + ((*(sptr) << 12) | (*(sptr + 1) >> 20)) | + ((*(sptr) << 11) | (*(sptr + 1) >> 21)) | + ((*(sptr) << 10) | (*(sptr + 1) >> 22)) | + ((*(sptr) << 9) | (*(sptr + 1) >> 23)) | + ((*(sptr) << 8) | (*(sptr + 1) >> 24)) | + ((*(sptr) << 7) | (*(sptr + 1) >> 25)) | + ((*(sptr) << 6) | (*(sptr + 1) >> 26)) | + ((*(sptr) << 5) | (*(sptr + 1) >> 27)) | + ((*(sptr) << 4) | (*(sptr + 1) >> 28)) | + ((*(sptr) << 3) | (*(sptr + 1) >> 29)) | + ((*(sptr) << 2) | (*(sptr + 1) >> 30)) | + ((*(sptr) << 1) | (*(sptr + 1) >> 31)) | + (*sptr) | + ((*(sptr) >> 1) | (*(sptr - 1) << 31)) | + ((*(sptr) >> 2) | (*(sptr - 1) << 30)) | + ((*(sptr) >> 3) | (*(sptr - 1) << 29)) | + ((*(sptr) >> 4) | (*(sptr - 1) << 28)) | + ((*(sptr) >> 5) | (*(sptr - 1) << 27)) | + ((*(sptr) >> 6) | (*(sptr - 1) << 26)) | + ((*(sptr) >> 7) | (*(sptr - 1) << 25)) | + ((*(sptr) >> 8) | (*(sptr - 1) << 24)) | + ((*(sptr) >> 9) | (*(sptr - 1) << 23)) | + ((*(sptr) >> 10) | (*(sptr - 1) << 22)) | + ((*(sptr) >> 11) | (*(sptr - 1) << 21)) | + ((*(sptr) >> 12) | (*(sptr - 1) << 20)) | + ((*(sptr) >> 13) | (*(sptr - 1) << 19)) | + ((*(sptr) >> 14) | (*(sptr - 1) << 18)) | + ((*(sptr) >> 15) | (*(sptr - 1) << 17)) | + ((*(sptr) >> 16) | (*(sptr - 1) << 16)) | + ((*(sptr) >> 17) | (*(sptr - 1) << 15)) | + ((*(sptr) >> 18) | (*(sptr - 1) << 14)) | + ((*(sptr) >> 19) | (*(sptr - 1) << 13)) | + ((*(sptr) >> 20) | (*(sptr - 1) << 12)) | + ((*(sptr) >> 21) | (*(sptr - 1) << 11)) | + ((*(sptr) >> 22) | (*(sptr - 1) << 10)) | + ((*(sptr) >> 23) | (*(sptr - 1) << 9)) | + ((*(sptr) >> 24) | (*(sptr - 1) << 8)); + } + } +} + +static void +ferode_3_48(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; + + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = ((*(sptr) >> 25) | (*(sptr - 1) << 7)) & + ((*(sptr) >> 24) | (*(sptr - 1) << 8)) & + ((*(sptr) >> 23) | (*(sptr - 1) << 9)) & + ((*(sptr) >> 22) | (*(sptr - 1) << 10)) & + ((*(sptr) >> 21) | (*(sptr - 1) << 11)) & + ((*(sptr) >> 20) | (*(sptr - 1) << 12)) & + ((*(sptr) >> 19) | (*(sptr - 1) << 13)) & + ((*(sptr) >> 18) | (*(sptr - 1) << 14)) & + ((*(sptr) >> 17) | (*(sptr - 1) << 15)) & + ((*(sptr) >> 16) | (*(sptr - 1) << 16)) & + ((*(sptr) >> 15) | (*(sptr - 1) << 17)) & + ((*(sptr) >> 14) | (*(sptr - 1) << 18)) & + ((*(sptr) >> 13) | (*(sptr - 1) << 19)) & + ((*(sptr) >> 12) | (*(sptr - 1) << 20)) & + ((*(sptr) >> 11) | (*(sptr - 1) << 21)) & + ((*(sptr) >> 10) | (*(sptr - 1) << 22)) & + ((*(sptr) >> 9) | (*(sptr - 1) << 23)) & + ((*(sptr) >> 8) | (*(sptr - 1) << 24)) & + ((*(sptr) >> 7) | (*(sptr - 1) << 25)) & + ((*(sptr) >> 6) | (*(sptr - 1) << 26)) & + ((*(sptr) >> 5) | (*(sptr - 1) << 27)) & + ((*(sptr) >> 4) | (*(sptr - 1) << 28)) & + ((*(sptr) >> 3) | (*(sptr - 1) << 29)) & + ((*(sptr) >> 2) | (*(sptr - 1) << 30)) & + ((*(sptr) >> 1) | (*(sptr - 1) << 31)) & + (*sptr) & + ((*(sptr) << 1) | (*(sptr + 1) >> 31)) & + ((*(sptr) << 2) | (*(sptr + 1) >> 30)) & + ((*(sptr) << 3) | (*(sptr + 1) >> 29)) & + ((*(sptr) << 4) | (*(sptr + 1) >> 28)) & + ((*(sptr) << 5) | (*(sptr + 1) >> 27)) & + ((*(sptr) << 6) | (*(sptr + 1) >> 26)) & + ((*(sptr) << 7) | (*(sptr + 1) >> 25)) & + ((*(sptr) << 8) | (*(sptr + 1) >> 24)) & + ((*(sptr) << 9) | (*(sptr + 1) >> 23)) & + ((*(sptr) << 10) | (*(sptr + 1) >> 22)) & + ((*(sptr) << 11) | (*(sptr + 1) >> 21)) & + ((*(sptr) << 12) | (*(sptr + 1) >> 20)) & + ((*(sptr) << 13) | (*(sptr + 1) >> 19)) & + ((*(sptr) << 14) | (*(sptr + 1) >> 18)) & + ((*(sptr) << 15) | (*(sptr + 1) >> 17)) & + ((*(sptr) << 16) | (*(sptr + 1) >> 16)) & + ((*(sptr) << 17) | (*(sptr + 1) >> 15)) & + ((*(sptr) << 18) | (*(sptr + 1) >> 14)) & + ((*(sptr) << 19) | (*(sptr + 1) >> 13)) & + ((*(sptr) << 20) | (*(sptr + 1) >> 12)) & + ((*(sptr) << 21) | (*(sptr + 1) >> 11)) & + ((*(sptr) << 22) | (*(sptr + 1) >> 10)) & + ((*(sptr) << 23) | (*(sptr + 1) >> 9)) & + ((*(sptr) << 24) | (*(sptr + 1) >> 8)); + } + } +} + +static void +fdilate_3_49(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; + + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = ((*(sptr) << 25) | (*(sptr + 1) >> 7)) | + ((*(sptr) << 24) | (*(sptr + 1) >> 8)) | + ((*(sptr) << 23) | (*(sptr + 1) >> 9)) | + ((*(sptr) << 22) | (*(sptr + 1) >> 10)) | + ((*(sptr) << 21) | (*(sptr + 1) >> 11)) | + ((*(sptr) << 20) | (*(sptr + 1) >> 12)) | + ((*(sptr) << 19) | (*(sptr + 1) >> 13)) | + ((*(sptr) << 18) | (*(sptr + 1) >> 14)) | + ((*(sptr) << 17) | (*(sptr + 1) >> 15)) | + ((*(sptr) << 16) | (*(sptr + 1) >> 16)) | + ((*(sptr) << 15) | (*(sptr + 1) >> 17)) | + ((*(sptr) << 14) | (*(sptr + 1) >> 18)) | + ((*(sptr) << 13) | (*(sptr + 1) >> 19)) | + ((*(sptr) << 12) | (*(sptr + 1) >> 20)) | + ((*(sptr) << 11) | (*(sptr + 1) >> 21)) | + ((*(sptr) << 10) | (*(sptr + 1) >> 22)) | + ((*(sptr) << 9) | (*(sptr + 1) >> 23)) | + ((*(sptr) << 8) | (*(sptr + 1) >> 24)) | + ((*(sptr) << 7) | (*(sptr + 1) >> 25)) | + ((*(sptr) << 6) | (*(sptr + 1) >> 26)) | + ((*(sptr) << 5) | (*(sptr + 1) >> 27)) | + ((*(sptr) << 4) | (*(sptr + 1) >> 28)) | + ((*(sptr) << 3) | (*(sptr + 1) >> 29)) | + ((*(sptr) << 2) | (*(sptr + 1) >> 30)) | + ((*(sptr) << 1) | (*(sptr + 1) >> 31)) | + (*sptr) | + ((*(sptr) >> 1) | (*(sptr - 1) << 31)) | + ((*(sptr) >> 2) | (*(sptr - 1) << 30)) | + ((*(sptr) >> 3) | (*(sptr - 1) << 29)) | + ((*(sptr) >> 4) | (*(sptr - 1) << 28)) | + ((*(sptr) >> 5) | (*(sptr - 1) << 27)) | + ((*(sptr) >> 6) | (*(sptr - 1) << 26)) | + ((*(sptr) >> 7) | (*(sptr - 1) << 25)) | + ((*(sptr) >> 8) | (*(sptr - 1) << 24)) | + ((*(sptr) >> 9) | (*(sptr - 1) << 23)) | + ((*(sptr) >> 10) | (*(sptr - 1) << 22)) | + ((*(sptr) >> 11) | (*(sptr - 1) << 21)) | + ((*(sptr) >> 12) | (*(sptr - 1) << 20)) | + ((*(sptr) >> 13) | (*(sptr - 1) << 19)) | + ((*(sptr) >> 14) | (*(sptr - 1) << 18)) | + ((*(sptr) >> 15) | (*(sptr - 1) << 17)) | + ((*(sptr) >> 16) | (*(sptr - 1) << 16)) | + ((*(sptr) >> 17) | (*(sptr - 1) << 15)) | + ((*(sptr) >> 18) | (*(sptr - 1) << 14)) | + ((*(sptr) >> 19) | (*(sptr - 1) << 13)) | + ((*(sptr) >> 20) | (*(sptr - 1) << 12)) | + ((*(sptr) >> 21) | (*(sptr - 1) << 11)) | + ((*(sptr) >> 22) | (*(sptr - 1) << 10)) | + ((*(sptr) >> 23) | (*(sptr - 1) << 9)) | + ((*(sptr) >> 24) | (*(sptr - 1) << 8)) | + ((*(sptr) >> 25) | (*(sptr - 1) << 7)); + } + } +} + +static void +ferode_3_49(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; + + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = ((*(sptr) >> 25) | (*(sptr - 1) << 7)) & + ((*(sptr) >> 24) | (*(sptr - 1) << 8)) & + ((*(sptr) >> 23) | (*(sptr - 1) << 9)) & + ((*(sptr) >> 22) | (*(sptr - 1) << 10)) & + ((*(sptr) >> 21) | (*(sptr - 1) << 11)) & + ((*(sptr) >> 20) | (*(sptr - 1) << 12)) & + ((*(sptr) >> 19) | (*(sptr - 1) << 13)) & + ((*(sptr) >> 18) | (*(sptr - 1) << 14)) & + ((*(sptr) >> 17) | (*(sptr - 1) << 15)) & + ((*(sptr) >> 16) | (*(sptr - 1) << 16)) & + ((*(sptr) >> 15) | (*(sptr - 1) << 17)) & + ((*(sptr) >> 14) | (*(sptr - 1) << 18)) & + ((*(sptr) >> 13) | (*(sptr - 1) << 19)) & + ((*(sptr) >> 12) | (*(sptr - 1) << 20)) & + ((*(sptr) >> 11) | (*(sptr - 1) << 21)) & + ((*(sptr) >> 10) | (*(sptr - 1) << 22)) & + ((*(sptr) >> 9) | (*(sptr - 1) << 23)) & + ((*(sptr) >> 8) | (*(sptr - 1) << 24)) & + ((*(sptr) >> 7) | (*(sptr - 1) << 25)) & + ((*(sptr) >> 6) | (*(sptr - 1) << 26)) & + ((*(sptr) >> 5) | (*(sptr - 1) << 27)) & + ((*(sptr) >> 4) | (*(sptr - 1) << 28)) & + ((*(sptr) >> 3) | (*(sptr - 1) << 29)) & + ((*(sptr) >> 2) | (*(sptr - 1) << 30)) & + ((*(sptr) >> 1) | (*(sptr - 1) << 31)) & + (*sptr) & + ((*(sptr) << 1) | (*(sptr + 1) >> 31)) & + ((*(sptr) << 2) | (*(sptr + 1) >> 30)) & + ((*(sptr) << 3) | (*(sptr + 1) >> 29)) & + ((*(sptr) << 4) | (*(sptr + 1) >> 28)) & + ((*(sptr) << 5) | (*(sptr + 1) >> 27)) & + ((*(sptr) << 6) | (*(sptr + 1) >> 26)) & + ((*(sptr) << 7) | (*(sptr + 1) >> 25)) & + ((*(sptr) << 8) | (*(sptr + 1) >> 24)) & + ((*(sptr) << 9) | (*(sptr + 1) >> 23)) & + ((*(sptr) << 10) | (*(sptr + 1) >> 22)) & + ((*(sptr) << 11) | (*(sptr + 1) >> 21)) & + ((*(sptr) << 12) | (*(sptr + 1) >> 20)) & + ((*(sptr) << 13) | (*(sptr + 1) >> 19)) & + ((*(sptr) << 14) | (*(sptr + 1) >> 18)) & + ((*(sptr) << 15) | (*(sptr + 1) >> 17)) & + ((*(sptr) << 16) | (*(sptr + 1) >> 16)) & + ((*(sptr) << 17) | (*(sptr + 1) >> 15)) & + ((*(sptr) << 18) | (*(sptr + 1) >> 14)) & + ((*(sptr) << 19) | (*(sptr + 1) >> 13)) & + ((*(sptr) << 20) | (*(sptr + 1) >> 12)) & + ((*(sptr) << 21) | (*(sptr + 1) >> 11)) & + ((*(sptr) << 22) | (*(sptr + 1) >> 10)) & + ((*(sptr) << 23) | (*(sptr + 1) >> 9)) & + ((*(sptr) << 24) | (*(sptr + 1) >> 8)) & + ((*(sptr) << 25) | (*(sptr + 1) >> 7)); + } + } +} + +static void +fdilate_3_50(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; + + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = ((*(sptr) << 26) | (*(sptr + 1) >> 6)) | + ((*(sptr) << 25) | (*(sptr + 1) >> 7)) | + ((*(sptr) << 24) | (*(sptr + 1) >> 8)) | + ((*(sptr) << 23) | (*(sptr + 1) >> 9)) | + ((*(sptr) << 22) | (*(sptr + 1) >> 10)) | + ((*(sptr) << 21) | (*(sptr + 1) >> 11)) | + ((*(sptr) << 20) | (*(sptr + 1) >> 12)) | + ((*(sptr) << 19) | (*(sptr + 1) >> 13)) | + ((*(sptr) << 18) | (*(sptr + 1) >> 14)) | + ((*(sptr) << 17) | (*(sptr + 1) >> 15)) | + ((*(sptr) << 16) | (*(sptr + 1) >> 16)) | + ((*(sptr) << 15) | (*(sptr + 1) >> 17)) | + ((*(sptr) << 14) | (*(sptr + 1) >> 18)) | + ((*(sptr) << 13) | (*(sptr + 1) >> 19)) | + ((*(sptr) << 12) | (*(sptr + 1) >> 20)) | + ((*(sptr) << 11) | (*(sptr + 1) >> 21)) | + ((*(sptr) << 10) | (*(sptr + 1) >> 22)) | + ((*(sptr) << 9) | (*(sptr + 1) >> 23)) | + ((*(sptr) << 8) | (*(sptr + 1) >> 24)) | + ((*(sptr) << 7) | (*(sptr + 1) >> 25)) | + ((*(sptr) << 6) | (*(sptr + 1) >> 26)) | + ((*(sptr) << 5) | (*(sptr + 1) >> 27)) | + ((*(sptr) << 4) | (*(sptr + 1) >> 28)) | + ((*(sptr) << 3) | (*(sptr + 1) >> 29)) | + ((*(sptr) << 2) | (*(sptr + 1) >> 30)) | + ((*(sptr) << 1) | (*(sptr + 1) >> 31)) | + (*sptr) | + ((*(sptr) >> 1) | (*(sptr - 1) << 31)) | + ((*(sptr) >> 2) | (*(sptr - 1) << 30)) | + ((*(sptr) >> 3) | (*(sptr - 1) << 29)) | + ((*(sptr) >> 4) | (*(sptr - 1) << 28)) | + ((*(sptr) >> 5) | (*(sptr - 1) << 27)) | + ((*(sptr) >> 6) | (*(sptr - 1) << 26)) | + ((*(sptr) >> 7) | (*(sptr - 1) << 25)) | + ((*(sptr) >> 8) | (*(sptr - 1) << 24)) | + ((*(sptr) >> 9) | (*(sptr - 1) << 23)) | + ((*(sptr) >> 10) | (*(sptr - 1) << 22)) | + ((*(sptr) >> 11) | (*(sptr - 1) << 21)) | + ((*(sptr) >> 12) | (*(sptr - 1) << 20)) | + ((*(sptr) >> 13) | (*(sptr - 1) << 19)) | + ((*(sptr) >> 14) | (*(sptr - 1) << 18)) | + ((*(sptr) >> 15) | (*(sptr - 1) << 17)) | + ((*(sptr) >> 16) | (*(sptr - 1) << 16)) | + ((*(sptr) >> 17) | (*(sptr - 1) << 15)) | + ((*(sptr) >> 18) | (*(sptr - 1) << 14)) | + ((*(sptr) >> 19) | (*(sptr - 1) << 13)) | + ((*(sptr) >> 20) | (*(sptr - 1) << 12)) | + ((*(sptr) >> 21) | (*(sptr - 1) << 11)) | + ((*(sptr) >> 22) | (*(sptr - 1) << 10)) | + ((*(sptr) >> 23) | (*(sptr - 1) << 9)) | + ((*(sptr) >> 24) | (*(sptr - 1) << 8)) | + ((*(sptr) >> 25) | (*(sptr - 1) << 7)); + } + } +} + +static void +ferode_3_50(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; + + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = ((*(sptr) >> 26) | (*(sptr - 1) << 6)) & + ((*(sptr) >> 25) | (*(sptr - 1) << 7)) & + ((*(sptr) >> 24) | (*(sptr - 1) << 8)) & + ((*(sptr) >> 23) | (*(sptr - 1) << 9)) & + ((*(sptr) >> 22) | (*(sptr - 1) << 10)) & + ((*(sptr) >> 21) | (*(sptr - 1) << 11)) & + ((*(sptr) >> 20) | (*(sptr - 1) << 12)) & + ((*(sptr) >> 19) | (*(sptr - 1) << 13)) & + ((*(sptr) >> 18) | (*(sptr - 1) << 14)) & + ((*(sptr) >> 17) | (*(sptr - 1) << 15)) & + ((*(sptr) >> 16) | (*(sptr - 1) << 16)) & + ((*(sptr) >> 15) | (*(sptr - 1) << 17)) & + ((*(sptr) >> 14) | (*(sptr - 1) << 18)) & + ((*(sptr) >> 13) | (*(sptr - 1) << 19)) & + ((*(sptr) >> 12) | (*(sptr - 1) << 20)) & + ((*(sptr) >> 11) | (*(sptr - 1) << 21)) & + ((*(sptr) >> 10) | (*(sptr - 1) << 22)) & + ((*(sptr) >> 9) | (*(sptr - 1) << 23)) & + ((*(sptr) >> 8) | (*(sptr - 1) << 24)) & + ((*(sptr) >> 7) | (*(sptr - 1) << 25)) & + ((*(sptr) >> 6) | (*(sptr - 1) << 26)) & + ((*(sptr) >> 5) | (*(sptr - 1) << 27)) & + ((*(sptr) >> 4) | (*(sptr - 1) << 28)) & + ((*(sptr) >> 3) | (*(sptr - 1) << 29)) & + ((*(sptr) >> 2) | (*(sptr - 1) << 30)) & + ((*(sptr) >> 1) | (*(sptr - 1) << 31)) & + (*sptr) & + ((*(sptr) << 1) | (*(sptr + 1) >> 31)) & + ((*(sptr) << 2) | (*(sptr + 1) >> 30)) & + ((*(sptr) << 3) | (*(sptr + 1) >> 29)) & + ((*(sptr) << 4) | (*(sptr + 1) >> 28)) & + ((*(sptr) << 5) | (*(sptr + 1) >> 27)) & + ((*(sptr) << 6) | (*(sptr + 1) >> 26)) & + ((*(sptr) << 7) | (*(sptr + 1) >> 25)) & + ((*(sptr) << 8) | (*(sptr + 1) >> 24)) & + ((*(sptr) << 9) | (*(sptr + 1) >> 23)) & + ((*(sptr) << 10) | (*(sptr + 1) >> 22)) & + ((*(sptr) << 11) | (*(sptr + 1) >> 21)) & + ((*(sptr) << 12) | (*(sptr + 1) >> 20)) & + ((*(sptr) << 13) | (*(sptr + 1) >> 19)) & + ((*(sptr) << 14) | (*(sptr + 1) >> 18)) & + ((*(sptr) << 15) | (*(sptr + 1) >> 17)) & + ((*(sptr) << 16) | (*(sptr + 1) >> 16)) & + ((*(sptr) << 17) | (*(sptr + 1) >> 15)) & + ((*(sptr) << 18) | (*(sptr + 1) >> 14)) & + ((*(sptr) << 19) | (*(sptr + 1) >> 13)) & + ((*(sptr) << 20) | (*(sptr + 1) >> 12)) & + ((*(sptr) << 21) | (*(sptr + 1) >> 11)) & + ((*(sptr) << 22) | (*(sptr + 1) >> 10)) & + ((*(sptr) << 23) | (*(sptr + 1) >> 9)) & + ((*(sptr) << 24) | (*(sptr + 1) >> 8)) & + ((*(sptr) << 25) | (*(sptr + 1) >> 7)); + } + } +} + +static void +fdilate_3_51(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; + + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = ((*(sptr) << 26) | (*(sptr + 1) >> 6)) | + ((*(sptr) << 25) | (*(sptr + 1) >> 7)) | + ((*(sptr) << 24) | (*(sptr + 1) >> 8)) | + ((*(sptr) << 23) | (*(sptr + 1) >> 9)) | + ((*(sptr) << 22) | (*(sptr + 1) >> 10)) | + ((*(sptr) << 21) | (*(sptr + 1) >> 11)) | + ((*(sptr) << 20) | (*(sptr + 1) >> 12)) | + ((*(sptr) << 19) | (*(sptr + 1) >> 13)) | + ((*(sptr) << 18) | (*(sptr + 1) >> 14)) | + ((*(sptr) << 17) | (*(sptr + 1) >> 15)) | + ((*(sptr) << 16) | (*(sptr + 1) >> 16)) | + ((*(sptr) << 15) | (*(sptr + 1) >> 17)) | + ((*(sptr) << 14) | (*(sptr + 1) >> 18)) | + ((*(sptr) << 13) | (*(sptr + 1) >> 19)) | + ((*(sptr) << 12) | (*(sptr + 1) >> 20)) | + ((*(sptr) << 11) | (*(sptr + 1) >> 21)) | + ((*(sptr) << 10) | (*(sptr + 1) >> 22)) | + ((*(sptr) << 9) | (*(sptr + 1) >> 23)) | + ((*(sptr) << 8) | (*(sptr + 1) >> 24)) | + ((*(sptr) << 7) | (*(sptr + 1) >> 25)) | + ((*(sptr) << 6) | (*(sptr + 1) >> 26)) | + ((*(sptr) << 5) | (*(sptr + 1) >> 27)) | + ((*(sptr) << 4) | (*(sptr + 1) >> 28)) | + ((*(sptr) << 3) | (*(sptr + 1) >> 29)) | + ((*(sptr) << 2) | (*(sptr + 1) >> 30)) | + ((*(sptr) << 1) | (*(sptr + 1) >> 31)) | + (*sptr) | + ((*(sptr) >> 1) | (*(sptr - 1) << 31)) | + ((*(sptr) >> 2) | (*(sptr - 1) << 30)) | + ((*(sptr) >> 3) | (*(sptr - 1) << 29)) | + ((*(sptr) >> 4) | (*(sptr - 1) << 28)) | + ((*(sptr) >> 5) | (*(sptr - 1) << 27)) | + ((*(sptr) >> 6) | (*(sptr - 1) << 26)) | + ((*(sptr) >> 7) | (*(sptr - 1) << 25)) | + ((*(sptr) >> 8) | (*(sptr - 1) << 24)) | + ((*(sptr) >> 9) | (*(sptr - 1) << 23)) | + ((*(sptr) >> 10) | (*(sptr - 1) << 22)) | + ((*(sptr) >> 11) | (*(sptr - 1) << 21)) | + ((*(sptr) >> 12) | (*(sptr - 1) << 20)) | + ((*(sptr) >> 13) | (*(sptr - 1) << 19)) | + ((*(sptr) >> 14) | (*(sptr - 1) << 18)) | + ((*(sptr) >> 15) | (*(sptr - 1) << 17)) | + ((*(sptr) >> 16) | (*(sptr - 1) << 16)) | + ((*(sptr) >> 17) | (*(sptr - 1) << 15)) | + ((*(sptr) >> 18) | (*(sptr - 1) << 14)) | + ((*(sptr) >> 19) | (*(sptr - 1) << 13)) | + ((*(sptr) >> 20) | (*(sptr - 1) << 12)) | + ((*(sptr) >> 21) | (*(sptr - 1) << 11)) | + ((*(sptr) >> 22) | (*(sptr - 1) << 10)) | + ((*(sptr) >> 23) | (*(sptr - 1) << 9)) | + ((*(sptr) >> 24) | (*(sptr - 1) << 8)) | + ((*(sptr) >> 25) | (*(sptr - 1) << 7)) | + ((*(sptr) >> 26) | (*(sptr - 1) << 6)); + } + } +} + +static void +ferode_3_51(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; + + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = ((*(sptr) >> 26) | (*(sptr - 1) << 6)) & + ((*(sptr) >> 25) | (*(sptr - 1) << 7)) & + ((*(sptr) >> 24) | (*(sptr - 1) << 8)) & + ((*(sptr) >> 23) | (*(sptr - 1) << 9)) & + ((*(sptr) >> 22) | (*(sptr - 1) << 10)) & + ((*(sptr) >> 21) | (*(sptr - 1) << 11)) & + ((*(sptr) >> 20) | (*(sptr - 1) << 12)) & + ((*(sptr) >> 19) | (*(sptr - 1) << 13)) & + ((*(sptr) >> 18) | (*(sptr - 1) << 14)) & + ((*(sptr) >> 17) | (*(sptr - 1) << 15)) & + ((*(sptr) >> 16) | (*(sptr - 1) << 16)) & + ((*(sptr) >> 15) | (*(sptr - 1) << 17)) & + ((*(sptr) >> 14) | (*(sptr - 1) << 18)) & + ((*(sptr) >> 13) | (*(sptr - 1) << 19)) & + ((*(sptr) >> 12) | (*(sptr - 1) << 20)) & + ((*(sptr) >> 11) | (*(sptr - 1) << 21)) & + ((*(sptr) >> 10) | (*(sptr - 1) << 22)) & + ((*(sptr) >> 9) | (*(sptr - 1) << 23)) & + ((*(sptr) >> 8) | (*(sptr - 1) << 24)) & + ((*(sptr) >> 7) | (*(sptr - 1) << 25)) & + ((*(sptr) >> 6) | (*(sptr - 1) << 26)) & + ((*(sptr) >> 5) | (*(sptr - 1) << 27)) & + ((*(sptr) >> 4) | (*(sptr - 1) << 28)) & + ((*(sptr) >> 3) | (*(sptr - 1) << 29)) & + ((*(sptr) >> 2) | (*(sptr - 1) << 30)) & + ((*(sptr) >> 1) | (*(sptr - 1) << 31)) & + (*sptr) & + ((*(sptr) << 1) | (*(sptr + 1) >> 31)) & + ((*(sptr) << 2) | (*(sptr + 1) >> 30)) & + ((*(sptr) << 3) | (*(sptr + 1) >> 29)) & + ((*(sptr) << 4) | (*(sptr + 1) >> 28)) & + ((*(sptr) << 5) | (*(sptr + 1) >> 27)) & + ((*(sptr) << 6) | (*(sptr + 1) >> 26)) & + ((*(sptr) << 7) | (*(sptr + 1) >> 25)) & + ((*(sptr) << 8) | (*(sptr + 1) >> 24)) & + ((*(sptr) << 9) | (*(sptr + 1) >> 23)) & + ((*(sptr) << 10) | (*(sptr + 1) >> 22)) & + ((*(sptr) << 11) | (*(sptr + 1) >> 21)) & + ((*(sptr) << 12) | (*(sptr + 1) >> 20)) & + ((*(sptr) << 13) | (*(sptr + 1) >> 19)) & + ((*(sptr) << 14) | (*(sptr + 1) >> 18)) & + ((*(sptr) << 15) | (*(sptr + 1) >> 17)) & + ((*(sptr) << 16) | (*(sptr + 1) >> 16)) & + ((*(sptr) << 17) | (*(sptr + 1) >> 15)) & + ((*(sptr) << 18) | (*(sptr + 1) >> 14)) & + ((*(sptr) << 19) | (*(sptr + 1) >> 13)) & + ((*(sptr) << 20) | (*(sptr + 1) >> 12)) & + ((*(sptr) << 21) | (*(sptr + 1) >> 11)) & + ((*(sptr) << 22) | (*(sptr + 1) >> 10)) & + ((*(sptr) << 23) | (*(sptr + 1) >> 9)) & + ((*(sptr) << 24) | (*(sptr + 1) >> 8)) & + ((*(sptr) << 25) | (*(sptr + 1) >> 7)) & + ((*(sptr) << 26) | (*(sptr + 1) >> 6)); + } + } +} + +static void +fdilate_3_52(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; + + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = ((*(sptr) << 27) | (*(sptr + 1) >> 5)) | + ((*(sptr) << 26) | (*(sptr + 1) >> 6)) | + ((*(sptr) << 25) | (*(sptr + 1) >> 7)) | + ((*(sptr) << 24) | (*(sptr + 1) >> 8)) | + ((*(sptr) << 23) | (*(sptr + 1) >> 9)) | + ((*(sptr) << 22) | (*(sptr + 1) >> 10)) | + ((*(sptr) << 21) | (*(sptr + 1) >> 11)) | + ((*(sptr) << 20) | (*(sptr + 1) >> 12)) | + ((*(sptr) << 19) | (*(sptr + 1) >> 13)) | + ((*(sptr) << 18) | (*(sptr + 1) >> 14)) | + ((*(sptr) << 17) | (*(sptr + 1) >> 15)) | + ((*(sptr) << 16) | (*(sptr + 1) >> 16)) | + ((*(sptr) << 15) | (*(sptr + 1) >> 17)) | + ((*(sptr) << 14) | (*(sptr + 1) >> 18)) | + ((*(sptr) << 13) | (*(sptr + 1) >> 19)) | + ((*(sptr) << 12) | (*(sptr + 1) >> 20)) | + ((*(sptr) << 11) | (*(sptr + 1) >> 21)) | + ((*(sptr) << 10) | (*(sptr + 1) >> 22)) | + ((*(sptr) << 9) | (*(sptr + 1) >> 23)) | + ((*(sptr) << 8) | (*(sptr + 1) >> 24)) | + ((*(sptr) << 7) | (*(sptr + 1) >> 25)) | + ((*(sptr) << 6) | (*(sptr + 1) >> 26)) | + ((*(sptr) << 5) | (*(sptr + 1) >> 27)) | + ((*(sptr) << 4) | (*(sptr + 1) >> 28)) | + ((*(sptr) << 3) | (*(sptr + 1) >> 29)) | + ((*(sptr) << 2) | (*(sptr + 1) >> 30)) | + ((*(sptr) << 1) | (*(sptr + 1) >> 31)) | + (*sptr) | + ((*(sptr) >> 1) | (*(sptr - 1) << 31)) | + ((*(sptr) >> 2) | (*(sptr - 1) << 30)) | + ((*(sptr) >> 3) | (*(sptr - 1) << 29)) | + ((*(sptr) >> 4) | (*(sptr - 1) << 28)) | + ((*(sptr) >> 5) | (*(sptr - 1) << 27)) | + ((*(sptr) >> 6) | (*(sptr - 1) << 26)) | + ((*(sptr) >> 7) | (*(sptr - 1) << 25)) | + ((*(sptr) >> 8) | (*(sptr - 1) << 24)) | + ((*(sptr) >> 9) | (*(sptr - 1) << 23)) | + ((*(sptr) >> 10) | (*(sptr - 1) << 22)) | + ((*(sptr) >> 11) | (*(sptr - 1) << 21)) | + ((*(sptr) >> 12) | (*(sptr - 1) << 20)) | + ((*(sptr) >> 13) | (*(sptr - 1) << 19)) | + ((*(sptr) >> 14) | (*(sptr - 1) << 18)) | + ((*(sptr) >> 15) | (*(sptr - 1) << 17)) | + ((*(sptr) >> 16) | (*(sptr - 1) << 16)) | + ((*(sptr) >> 17) | (*(sptr - 1) << 15)) | + ((*(sptr) >> 18) | (*(sptr - 1) << 14)) | + ((*(sptr) >> 19) | (*(sptr - 1) << 13)) | + ((*(sptr) >> 20) | (*(sptr - 1) << 12)) | + ((*(sptr) >> 21) | (*(sptr - 1) << 11)) | + ((*(sptr) >> 22) | (*(sptr - 1) << 10)) | + ((*(sptr) >> 23) | (*(sptr - 1) << 9)) | + ((*(sptr) >> 24) | (*(sptr - 1) << 8)) | + ((*(sptr) >> 25) | (*(sptr - 1) << 7)) | + ((*(sptr) >> 26) | (*(sptr - 1) << 6)); + } + } +} + +static void +ferode_3_52(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; + + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = ((*(sptr) >> 27) | (*(sptr - 1) << 5)) & + ((*(sptr) >> 26) | (*(sptr - 1) << 6)) & + ((*(sptr) >> 25) | (*(sptr - 1) << 7)) & + ((*(sptr) >> 24) | (*(sptr - 1) << 8)) & + ((*(sptr) >> 23) | (*(sptr - 1) << 9)) & + ((*(sptr) >> 22) | (*(sptr - 1) << 10)) & + ((*(sptr) >> 21) | (*(sptr - 1) << 11)) & + ((*(sptr) >> 20) | (*(sptr - 1) << 12)) & + ((*(sptr) >> 19) | (*(sptr - 1) << 13)) & + ((*(sptr) >> 18) | (*(sptr - 1) << 14)) & + ((*(sptr) >> 17) | (*(sptr - 1) << 15)) & + ((*(sptr) >> 16) | (*(sptr - 1) << 16)) & + ((*(sptr) >> 15) | (*(sptr - 1) << 17)) & + ((*(sptr) >> 14) | (*(sptr - 1) << 18)) & + ((*(sptr) >> 13) | (*(sptr - 1) << 19)) & + ((*(sptr) >> 12) | (*(sptr - 1) << 20)) & + ((*(sptr) >> 11) | (*(sptr - 1) << 21)) & + ((*(sptr) >> 10) | (*(sptr - 1) << 22)) & + ((*(sptr) >> 9) | (*(sptr - 1) << 23)) & + ((*(sptr) >> 8) | (*(sptr - 1) << 24)) & + ((*(sptr) >> 7) | (*(sptr - 1) << 25)) & + ((*(sptr) >> 6) | (*(sptr - 1) << 26)) & + ((*(sptr) >> 5) | (*(sptr - 1) << 27)) & + ((*(sptr) >> 4) | (*(sptr - 1) << 28)) & + ((*(sptr) >> 3) | (*(sptr - 1) << 29)) & + ((*(sptr) >> 2) | (*(sptr - 1) << 30)) & + ((*(sptr) >> 1) | (*(sptr - 1) << 31)) & + (*sptr) & + ((*(sptr) << 1) | (*(sptr + 1) >> 31)) & + ((*(sptr) << 2) | (*(sptr + 1) >> 30)) & + ((*(sptr) << 3) | (*(sptr + 1) >> 29)) & + ((*(sptr) << 4) | (*(sptr + 1) >> 28)) & + ((*(sptr) << 5) | (*(sptr + 1) >> 27)) & + ((*(sptr) << 6) | (*(sptr + 1) >> 26)) & + ((*(sptr) << 7) | (*(sptr + 1) >> 25)) & + ((*(sptr) << 8) | (*(sptr + 1) >> 24)) & + ((*(sptr) << 9) | (*(sptr + 1) >> 23)) & + ((*(sptr) << 10) | (*(sptr + 1) >> 22)) & + ((*(sptr) << 11) | (*(sptr + 1) >> 21)) & + ((*(sptr) << 12) | (*(sptr + 1) >> 20)) & + ((*(sptr) << 13) | (*(sptr + 1) >> 19)) & + ((*(sptr) << 14) | (*(sptr + 1) >> 18)) & + ((*(sptr) << 15) | (*(sptr + 1) >> 17)) & + ((*(sptr) << 16) | (*(sptr + 1) >> 16)) & + ((*(sptr) << 17) | (*(sptr + 1) >> 15)) & + ((*(sptr) << 18) | (*(sptr + 1) >> 14)) & + ((*(sptr) << 19) | (*(sptr + 1) >> 13)) & + ((*(sptr) << 20) | (*(sptr + 1) >> 12)) & + ((*(sptr) << 21) | (*(sptr + 1) >> 11)) & + ((*(sptr) << 22) | (*(sptr + 1) >> 10)) & + ((*(sptr) << 23) | (*(sptr + 1) >> 9)) & + ((*(sptr) << 24) | (*(sptr + 1) >> 8)) & + ((*(sptr) << 25) | (*(sptr + 1) >> 7)) & + ((*(sptr) << 26) | (*(sptr + 1) >> 6)); + } + } +} + +static void +fdilate_3_53(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; + + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = ((*(sptr) << 27) | (*(sptr + 1) >> 5)) | + ((*(sptr) << 26) | (*(sptr + 1) >> 6)) | + ((*(sptr) << 25) | (*(sptr + 1) >> 7)) | + ((*(sptr) << 24) | (*(sptr + 1) >> 8)) | + ((*(sptr) << 23) | (*(sptr + 1) >> 9)) | + ((*(sptr) << 22) | (*(sptr + 1) >> 10)) | + ((*(sptr) << 21) | (*(sptr + 1) >> 11)) | + ((*(sptr) << 20) | (*(sptr + 1) >> 12)) | + ((*(sptr) << 19) | (*(sptr + 1) >> 13)) | + ((*(sptr) << 18) | (*(sptr + 1) >> 14)) | + ((*(sptr) << 17) | (*(sptr + 1) >> 15)) | + ((*(sptr) << 16) | (*(sptr + 1) >> 16)) | + ((*(sptr) << 15) | (*(sptr + 1) >> 17)) | + ((*(sptr) << 14) | (*(sptr + 1) >> 18)) | + ((*(sptr) << 13) | (*(sptr + 1) >> 19)) | + ((*(sptr) << 12) | (*(sptr + 1) >> 20)) | + ((*(sptr) << 11) | (*(sptr + 1) >> 21)) | + ((*(sptr) << 10) | (*(sptr + 1) >> 22)) | + ((*(sptr) << 9) | (*(sptr + 1) >> 23)) | + ((*(sptr) << 8) | (*(sptr + 1) >> 24)) | + ((*(sptr) << 7) | (*(sptr + 1) >> 25)) | + ((*(sptr) << 6) | (*(sptr + 1) >> 26)) | + ((*(sptr) << 5) | (*(sptr + 1) >> 27)) | + ((*(sptr) << 4) | (*(sptr + 1) >> 28)) | + ((*(sptr) << 3) | (*(sptr + 1) >> 29)) | + ((*(sptr) << 2) | (*(sptr + 1) >> 30)) | + ((*(sptr) << 1) | (*(sptr + 1) >> 31)) | + (*sptr) | + ((*(sptr) >> 1) | (*(sptr - 1) << 31)) | + ((*(sptr) >> 2) | (*(sptr - 1) << 30)) | + ((*(sptr) >> 3) | (*(sptr - 1) << 29)) | + ((*(sptr) >> 4) | (*(sptr - 1) << 28)) | + ((*(sptr) >> 5) | (*(sptr - 1) << 27)) | + ((*(sptr) >> 6) | (*(sptr - 1) << 26)) | + ((*(sptr) >> 7) | (*(sptr - 1) << 25)) | + ((*(sptr) >> 8) | (*(sptr - 1) << 24)) | + ((*(sptr) >> 9) | (*(sptr - 1) << 23)) | + ((*(sptr) >> 10) | (*(sptr - 1) << 22)) | + ((*(sptr) >> 11) | (*(sptr - 1) << 21)) | + ((*(sptr) >> 12) | (*(sptr - 1) << 20)) | + ((*(sptr) >> 13) | (*(sptr - 1) << 19)) | + ((*(sptr) >> 14) | (*(sptr - 1) << 18)) | + ((*(sptr) >> 15) | (*(sptr - 1) << 17)) | + ((*(sptr) >> 16) | (*(sptr - 1) << 16)) | + ((*(sptr) >> 17) | (*(sptr - 1) << 15)) | + ((*(sptr) >> 18) | (*(sptr - 1) << 14)) | + ((*(sptr) >> 19) | (*(sptr - 1) << 13)) | + ((*(sptr) >> 20) | (*(sptr - 1) << 12)) | + ((*(sptr) >> 21) | (*(sptr - 1) << 11)) | + ((*(sptr) >> 22) | (*(sptr - 1) << 10)) | + ((*(sptr) >> 23) | (*(sptr - 1) << 9)) | + ((*(sptr) >> 24) | (*(sptr - 1) << 8)) | + ((*(sptr) >> 25) | (*(sptr - 1) << 7)) | + ((*(sptr) >> 26) | (*(sptr - 1) << 6)) | + ((*(sptr) >> 27) | (*(sptr - 1) << 5)); + } + } +} + +static void +ferode_3_53(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; + + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = ((*(sptr) >> 27) | (*(sptr - 1) << 5)) & + ((*(sptr) >> 26) | (*(sptr - 1) << 6)) & + ((*(sptr) >> 25) | (*(sptr - 1) << 7)) & + ((*(sptr) >> 24) | (*(sptr - 1) << 8)) & + ((*(sptr) >> 23) | (*(sptr - 1) << 9)) & + ((*(sptr) >> 22) | (*(sptr - 1) << 10)) & + ((*(sptr) >> 21) | (*(sptr - 1) << 11)) & + ((*(sptr) >> 20) | (*(sptr - 1) << 12)) & + ((*(sptr) >> 19) | (*(sptr - 1) << 13)) & + ((*(sptr) >> 18) | (*(sptr - 1) << 14)) & + ((*(sptr) >> 17) | (*(sptr - 1) << 15)) & + ((*(sptr) >> 16) | (*(sptr - 1) << 16)) & + ((*(sptr) >> 15) | (*(sptr - 1) << 17)) & + ((*(sptr) >> 14) | (*(sptr - 1) << 18)) & + ((*(sptr) >> 13) | (*(sptr - 1) << 19)) & + ((*(sptr) >> 12) | (*(sptr - 1) << 20)) & + ((*(sptr) >> 11) | (*(sptr - 1) << 21)) & + ((*(sptr) >> 10) | (*(sptr - 1) << 22)) & + ((*(sptr) >> 9) | (*(sptr - 1) << 23)) & + ((*(sptr) >> 8) | (*(sptr - 1) << 24)) & + ((*(sptr) >> 7) | (*(sptr - 1) << 25)) & + ((*(sptr) >> 6) | (*(sptr - 1) << 26)) & + ((*(sptr) >> 5) | (*(sptr - 1) << 27)) & + ((*(sptr) >> 4) | (*(sptr - 1) << 28)) & + ((*(sptr) >> 3) | (*(sptr - 1) << 29)) & + ((*(sptr) >> 2) | (*(sptr - 1) << 30)) & + ((*(sptr) >> 1) | (*(sptr - 1) << 31)) & + (*sptr) & + ((*(sptr) << 1) | (*(sptr + 1) >> 31)) & + ((*(sptr) << 2) | (*(sptr + 1) >> 30)) & + ((*(sptr) << 3) | (*(sptr + 1) >> 29)) & + ((*(sptr) << 4) | (*(sptr + 1) >> 28)) & + ((*(sptr) << 5) | (*(sptr + 1) >> 27)) & + ((*(sptr) << 6) | (*(sptr + 1) >> 26)) & + ((*(sptr) << 7) | (*(sptr + 1) >> 25)) & + ((*(sptr) << 8) | (*(sptr + 1) >> 24)) & + ((*(sptr) << 9) | (*(sptr + 1) >> 23)) & + ((*(sptr) << 10) | (*(sptr + 1) >> 22)) & + ((*(sptr) << 11) | (*(sptr + 1) >> 21)) & + ((*(sptr) << 12) | (*(sptr + 1) >> 20)) & + ((*(sptr) << 13) | (*(sptr + 1) >> 19)) & + ((*(sptr) << 14) | (*(sptr + 1) >> 18)) & + ((*(sptr) << 15) | (*(sptr + 1) >> 17)) & + ((*(sptr) << 16) | (*(sptr + 1) >> 16)) & + ((*(sptr) << 17) | (*(sptr + 1) >> 15)) & + ((*(sptr) << 18) | (*(sptr + 1) >> 14)) & + ((*(sptr) << 19) | (*(sptr + 1) >> 13)) & + ((*(sptr) << 20) | (*(sptr + 1) >> 12)) & + ((*(sptr) << 21) | (*(sptr + 1) >> 11)) & + ((*(sptr) << 22) | (*(sptr + 1) >> 10)) & + ((*(sptr) << 23) | (*(sptr + 1) >> 9)) & + ((*(sptr) << 24) | (*(sptr + 1) >> 8)) & + ((*(sptr) << 25) | (*(sptr + 1) >> 7)) & + ((*(sptr) << 26) | (*(sptr + 1) >> 6)) & + ((*(sptr) << 27) | (*(sptr + 1) >> 5)); + } + } +} + +static void +fdilate_3_54(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; + + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = ((*(sptr) << 28) | (*(sptr + 1) >> 4)) | + ((*(sptr) << 27) | (*(sptr + 1) >> 5)) | + ((*(sptr) << 26) | (*(sptr + 1) >> 6)) | + ((*(sptr) << 25) | (*(sptr + 1) >> 7)) | + ((*(sptr) << 24) | (*(sptr + 1) >> 8)) | + ((*(sptr) << 23) | (*(sptr + 1) >> 9)) | + ((*(sptr) << 22) | (*(sptr + 1) >> 10)) | + ((*(sptr) << 21) | (*(sptr + 1) >> 11)) | + ((*(sptr) << 20) | (*(sptr + 1) >> 12)) | + ((*(sptr) << 19) | (*(sptr + 1) >> 13)) | + ((*(sptr) << 18) | (*(sptr + 1) >> 14)) | + ((*(sptr) << 17) | (*(sptr + 1) >> 15)) | + ((*(sptr) << 16) | (*(sptr + 1) >> 16)) | + ((*(sptr) << 15) | (*(sptr + 1) >> 17)) | + ((*(sptr) << 14) | (*(sptr + 1) >> 18)) | + ((*(sptr) << 13) | (*(sptr + 1) >> 19)) | + ((*(sptr) << 12) | (*(sptr + 1) >> 20)) | + ((*(sptr) << 11) | (*(sptr + 1) >> 21)) | + ((*(sptr) << 10) | (*(sptr + 1) >> 22)) | + ((*(sptr) << 9) | (*(sptr + 1) >> 23)) | + ((*(sptr) << 8) | (*(sptr + 1) >> 24)) | + ((*(sptr) << 7) | (*(sptr + 1) >> 25)) | + ((*(sptr) << 6) | (*(sptr + 1) >> 26)) | + ((*(sptr) << 5) | (*(sptr + 1) >> 27)) | + ((*(sptr) << 4) | (*(sptr + 1) >> 28)) | + ((*(sptr) << 3) | (*(sptr + 1) >> 29)) | + ((*(sptr) << 2) | (*(sptr + 1) >> 30)) | + ((*(sptr) << 1) | (*(sptr + 1) >> 31)) | + (*sptr) | + ((*(sptr) >> 1) | (*(sptr - 1) << 31)) | + ((*(sptr) >> 2) | (*(sptr - 1) << 30)) | + ((*(sptr) >> 3) | (*(sptr - 1) << 29)) | + ((*(sptr) >> 4) | (*(sptr - 1) << 28)) | + ((*(sptr) >> 5) | (*(sptr - 1) << 27)) | + ((*(sptr) >> 6) | (*(sptr - 1) << 26)) | + ((*(sptr) >> 7) | (*(sptr - 1) << 25)) | + ((*(sptr) >> 8) | (*(sptr - 1) << 24)) | + ((*(sptr) >> 9) | (*(sptr - 1) << 23)) | + ((*(sptr) >> 10) | (*(sptr - 1) << 22)) | + ((*(sptr) >> 11) | (*(sptr - 1) << 21)) | + ((*(sptr) >> 12) | (*(sptr - 1) << 20)) | + ((*(sptr) >> 13) | (*(sptr - 1) << 19)) | + ((*(sptr) >> 14) | (*(sptr - 1) << 18)) | + ((*(sptr) >> 15) | (*(sptr - 1) << 17)) | + ((*(sptr) >> 16) | (*(sptr - 1) << 16)) | + ((*(sptr) >> 17) | (*(sptr - 1) << 15)) | + ((*(sptr) >> 18) | (*(sptr - 1) << 14)) | + ((*(sptr) >> 19) | (*(sptr - 1) << 13)) | + ((*(sptr) >> 20) | (*(sptr - 1) << 12)) | + ((*(sptr) >> 21) | (*(sptr - 1) << 11)) | + ((*(sptr) >> 22) | (*(sptr - 1) << 10)) | + ((*(sptr) >> 23) | (*(sptr - 1) << 9)) | + ((*(sptr) >> 24) | (*(sptr - 1) << 8)) | + ((*(sptr) >> 25) | (*(sptr - 1) << 7)) | + ((*(sptr) >> 26) | (*(sptr - 1) << 6)) | + ((*(sptr) >> 27) | (*(sptr - 1) << 5)); + } + } +} + +static void +ferode_3_54(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; + + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = ((*(sptr) >> 28) | (*(sptr - 1) << 4)) & + ((*(sptr) >> 27) | (*(sptr - 1) << 5)) & + ((*(sptr) >> 26) | (*(sptr - 1) << 6)) & + ((*(sptr) >> 25) | (*(sptr - 1) << 7)) & + ((*(sptr) >> 24) | (*(sptr - 1) << 8)) & + ((*(sptr) >> 23) | (*(sptr - 1) << 9)) & + ((*(sptr) >> 22) | (*(sptr - 1) << 10)) & + ((*(sptr) >> 21) | (*(sptr - 1) << 11)) & + ((*(sptr) >> 20) | (*(sptr - 1) << 12)) & + ((*(sptr) >> 19) | (*(sptr - 1) << 13)) & + ((*(sptr) >> 18) | (*(sptr - 1) << 14)) & + ((*(sptr) >> 17) | (*(sptr - 1) << 15)) & + ((*(sptr) >> 16) | (*(sptr - 1) << 16)) & + ((*(sptr) >> 15) | (*(sptr - 1) << 17)) & + ((*(sptr) >> 14) | (*(sptr - 1) << 18)) & + ((*(sptr) >> 13) | (*(sptr - 1) << 19)) & + ((*(sptr) >> 12) | (*(sptr - 1) << 20)) & + ((*(sptr) >> 11) | (*(sptr - 1) << 21)) & + ((*(sptr) >> 10) | (*(sptr - 1) << 22)) & + ((*(sptr) >> 9) | (*(sptr - 1) << 23)) & + ((*(sptr) >> 8) | (*(sptr - 1) << 24)) & + ((*(sptr) >> 7) | (*(sptr - 1) << 25)) & + ((*(sptr) >> 6) | (*(sptr - 1) << 26)) & + ((*(sptr) >> 5) | (*(sptr - 1) << 27)) & + ((*(sptr) >> 4) | (*(sptr - 1) << 28)) & + ((*(sptr) >> 3) | (*(sptr - 1) << 29)) & + ((*(sptr) >> 2) | (*(sptr - 1) << 30)) & + ((*(sptr) >> 1) | (*(sptr - 1) << 31)) & + (*sptr) & + ((*(sptr) << 1) | (*(sptr + 1) >> 31)) & + ((*(sptr) << 2) | (*(sptr + 1) >> 30)) & + ((*(sptr) << 3) | (*(sptr + 1) >> 29)) & + ((*(sptr) << 4) | (*(sptr + 1) >> 28)) & + ((*(sptr) << 5) | (*(sptr + 1) >> 27)) & + ((*(sptr) << 6) | (*(sptr + 1) >> 26)) & + ((*(sptr) << 7) | (*(sptr + 1) >> 25)) & + ((*(sptr) << 8) | (*(sptr + 1) >> 24)) & + ((*(sptr) << 9) | (*(sptr + 1) >> 23)) & + ((*(sptr) << 10) | (*(sptr + 1) >> 22)) & + ((*(sptr) << 11) | (*(sptr + 1) >> 21)) & + ((*(sptr) << 12) | (*(sptr + 1) >> 20)) & + ((*(sptr) << 13) | (*(sptr + 1) >> 19)) & + ((*(sptr) << 14) | (*(sptr + 1) >> 18)) & + ((*(sptr) << 15) | (*(sptr + 1) >> 17)) & + ((*(sptr) << 16) | (*(sptr + 1) >> 16)) & + ((*(sptr) << 17) | (*(sptr + 1) >> 15)) & + ((*(sptr) << 18) | (*(sptr + 1) >> 14)) & + ((*(sptr) << 19) | (*(sptr + 1) >> 13)) & + ((*(sptr) << 20) | (*(sptr + 1) >> 12)) & + ((*(sptr) << 21) | (*(sptr + 1) >> 11)) & + ((*(sptr) << 22) | (*(sptr + 1) >> 10)) & + ((*(sptr) << 23) | (*(sptr + 1) >> 9)) & + ((*(sptr) << 24) | (*(sptr + 1) >> 8)) & + ((*(sptr) << 25) | (*(sptr + 1) >> 7)) & + ((*(sptr) << 26) | (*(sptr + 1) >> 6)) & + ((*(sptr) << 27) | (*(sptr + 1) >> 5)); + } + } +} + +static void +fdilate_3_55(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; + + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = ((*(sptr) << 28) | (*(sptr + 1) >> 4)) | + ((*(sptr) << 27) | (*(sptr + 1) >> 5)) | + ((*(sptr) << 26) | (*(sptr + 1) >> 6)) | + ((*(sptr) << 25) | (*(sptr + 1) >> 7)) | + ((*(sptr) << 24) | (*(sptr + 1) >> 8)) | + ((*(sptr) << 23) | (*(sptr + 1) >> 9)) | + ((*(sptr) << 22) | (*(sptr + 1) >> 10)) | + ((*(sptr) << 21) | (*(sptr + 1) >> 11)) | + ((*(sptr) << 20) | (*(sptr + 1) >> 12)) | + ((*(sptr) << 19) | (*(sptr + 1) >> 13)) | + ((*(sptr) << 18) | (*(sptr + 1) >> 14)) | + ((*(sptr) << 17) | (*(sptr + 1) >> 15)) | + ((*(sptr) << 16) | (*(sptr + 1) >> 16)) | + ((*(sptr) << 15) | (*(sptr + 1) >> 17)) | + ((*(sptr) << 14) | (*(sptr + 1) >> 18)) | + ((*(sptr) << 13) | (*(sptr + 1) >> 19)) | + ((*(sptr) << 12) | (*(sptr + 1) >> 20)) | + ((*(sptr) << 11) | (*(sptr + 1) >> 21)) | + ((*(sptr) << 10) | (*(sptr + 1) >> 22)) | + ((*(sptr) << 9) | (*(sptr + 1) >> 23)) | + ((*(sptr) << 8) | (*(sptr + 1) >> 24)) | + ((*(sptr) << 7) | (*(sptr + 1) >> 25)) | + ((*(sptr) << 6) | (*(sptr + 1) >> 26)) | + ((*(sptr) << 5) | (*(sptr + 1) >> 27)) | + ((*(sptr) << 4) | (*(sptr + 1) >> 28)) | + ((*(sptr) << 3) | (*(sptr + 1) >> 29)) | + ((*(sptr) << 2) | (*(sptr + 1) >> 30)) | + ((*(sptr) << 1) | (*(sptr + 1) >> 31)) | + (*sptr) | + ((*(sptr) >> 1) | (*(sptr - 1) << 31)) | + ((*(sptr) >> 2) | (*(sptr - 1) << 30)) | + ((*(sptr) >> 3) | (*(sptr - 1) << 29)) | + ((*(sptr) >> 4) | (*(sptr - 1) << 28)) | + ((*(sptr) >> 5) | (*(sptr - 1) << 27)) | + ((*(sptr) >> 6) | (*(sptr - 1) << 26)) | + ((*(sptr) >> 7) | (*(sptr - 1) << 25)) | + ((*(sptr) >> 8) | (*(sptr - 1) << 24)) | + ((*(sptr) >> 9) | (*(sptr - 1) << 23)) | + ((*(sptr) >> 10) | (*(sptr - 1) << 22)) | + ((*(sptr) >> 11) | (*(sptr - 1) << 21)) | + ((*(sptr) >> 12) | (*(sptr - 1) << 20)) | + ((*(sptr) >> 13) | (*(sptr - 1) << 19)) | + ((*(sptr) >> 14) | (*(sptr - 1) << 18)) | + ((*(sptr) >> 15) | (*(sptr - 1) << 17)) | + ((*(sptr) >> 16) | (*(sptr - 1) << 16)) | + ((*(sptr) >> 17) | (*(sptr - 1) << 15)) | + ((*(sptr) >> 18) | (*(sptr - 1) << 14)) | + ((*(sptr) >> 19) | (*(sptr - 1) << 13)) | + ((*(sptr) >> 20) | (*(sptr - 1) << 12)) | + ((*(sptr) >> 21) | (*(sptr - 1) << 11)) | + ((*(sptr) >> 22) | (*(sptr - 1) << 10)) | + ((*(sptr) >> 23) | (*(sptr - 1) << 9)) | + ((*(sptr) >> 24) | (*(sptr - 1) << 8)) | + ((*(sptr) >> 25) | (*(sptr - 1) << 7)) | + ((*(sptr) >> 26) | (*(sptr - 1) << 6)) | + ((*(sptr) >> 27) | (*(sptr - 1) << 5)) | + ((*(sptr) >> 28) | (*(sptr - 1) << 4)); + } + } +} + +static void +ferode_3_55(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; + + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = ((*(sptr) >> 28) | (*(sptr - 1) << 4)) & + ((*(sptr) >> 27) | (*(sptr - 1) << 5)) & + ((*(sptr) >> 26) | (*(sptr - 1) << 6)) & + ((*(sptr) >> 25) | (*(sptr - 1) << 7)) & + ((*(sptr) >> 24) | (*(sptr - 1) << 8)) & + ((*(sptr) >> 23) | (*(sptr - 1) << 9)) & + ((*(sptr) >> 22) | (*(sptr - 1) << 10)) & + ((*(sptr) >> 21) | (*(sptr - 1) << 11)) & + ((*(sptr) >> 20) | (*(sptr - 1) << 12)) & + ((*(sptr) >> 19) | (*(sptr - 1) << 13)) & + ((*(sptr) >> 18) | (*(sptr - 1) << 14)) & + ((*(sptr) >> 17) | (*(sptr - 1) << 15)) & + ((*(sptr) >> 16) | (*(sptr - 1) << 16)) & + ((*(sptr) >> 15) | (*(sptr - 1) << 17)) & + ((*(sptr) >> 14) | (*(sptr - 1) << 18)) & + ((*(sptr) >> 13) | (*(sptr - 1) << 19)) & + ((*(sptr) >> 12) | (*(sptr - 1) << 20)) & + ((*(sptr) >> 11) | (*(sptr - 1) << 21)) & + ((*(sptr) >> 10) | (*(sptr - 1) << 22)) & + ((*(sptr) >> 9) | (*(sptr - 1) << 23)) & + ((*(sptr) >> 8) | (*(sptr - 1) << 24)) & + ((*(sptr) >> 7) | (*(sptr - 1) << 25)) & + ((*(sptr) >> 6) | (*(sptr - 1) << 26)) & + ((*(sptr) >> 5) | (*(sptr - 1) << 27)) & + ((*(sptr) >> 4) | (*(sptr - 1) << 28)) & + ((*(sptr) >> 3) | (*(sptr - 1) << 29)) & + ((*(sptr) >> 2) | (*(sptr - 1) << 30)) & + ((*(sptr) >> 1) | (*(sptr - 1) << 31)) & + (*sptr) & + ((*(sptr) << 1) | (*(sptr + 1) >> 31)) & + ((*(sptr) << 2) | (*(sptr + 1) >> 30)) & + ((*(sptr) << 3) | (*(sptr + 1) >> 29)) & + ((*(sptr) << 4) | (*(sptr + 1) >> 28)) & + ((*(sptr) << 5) | (*(sptr + 1) >> 27)) & + ((*(sptr) << 6) | (*(sptr + 1) >> 26)) & + ((*(sptr) << 7) | (*(sptr + 1) >> 25)) & + ((*(sptr) << 8) | (*(sptr + 1) >> 24)) & + ((*(sptr) << 9) | (*(sptr + 1) >> 23)) & + ((*(sptr) << 10) | (*(sptr + 1) >> 22)) & + ((*(sptr) << 11) | (*(sptr + 1) >> 21)) & + ((*(sptr) << 12) | (*(sptr + 1) >> 20)) & + ((*(sptr) << 13) | (*(sptr + 1) >> 19)) & + ((*(sptr) << 14) | (*(sptr + 1) >> 18)) & + ((*(sptr) << 15) | (*(sptr + 1) >> 17)) & + ((*(sptr) << 16) | (*(sptr + 1) >> 16)) & + ((*(sptr) << 17) | (*(sptr + 1) >> 15)) & + ((*(sptr) << 18) | (*(sptr + 1) >> 14)) & + ((*(sptr) << 19) | (*(sptr + 1) >> 13)) & + ((*(sptr) << 20) | (*(sptr + 1) >> 12)) & + ((*(sptr) << 21) | (*(sptr + 1) >> 11)) & + ((*(sptr) << 22) | (*(sptr + 1) >> 10)) & + ((*(sptr) << 23) | (*(sptr + 1) >> 9)) & + ((*(sptr) << 24) | (*(sptr + 1) >> 8)) & + ((*(sptr) << 25) | (*(sptr + 1) >> 7)) & + ((*(sptr) << 26) | (*(sptr + 1) >> 6)) & + ((*(sptr) << 27) | (*(sptr + 1) >> 5)) & + ((*(sptr) << 28) | (*(sptr + 1) >> 4)); + } + } +} + +static void +fdilate_3_56(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; + + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = ((*(sptr) << 29) | (*(sptr + 1) >> 3)) | + ((*(sptr) << 28) | (*(sptr + 1) >> 4)) | + ((*(sptr) << 27) | (*(sptr + 1) >> 5)) | + ((*(sptr) << 26) | (*(sptr + 1) >> 6)) | + ((*(sptr) << 25) | (*(sptr + 1) >> 7)) | + ((*(sptr) << 24) | (*(sptr + 1) >> 8)) | + ((*(sptr) << 23) | (*(sptr + 1) >> 9)) | + ((*(sptr) << 22) | (*(sptr + 1) >> 10)) | + ((*(sptr) << 21) | (*(sptr + 1) >> 11)) | + ((*(sptr) << 20) | (*(sptr + 1) >> 12)) | + ((*(sptr) << 19) | (*(sptr + 1) >> 13)) | + ((*(sptr) << 18) | (*(sptr + 1) >> 14)) | + ((*(sptr) << 17) | (*(sptr + 1) >> 15)) | + ((*(sptr) << 16) | (*(sptr + 1) >> 16)) | + ((*(sptr) << 15) | (*(sptr + 1) >> 17)) | + ((*(sptr) << 14) | (*(sptr + 1) >> 18)) | + ((*(sptr) << 13) | (*(sptr + 1) >> 19)) | + ((*(sptr) << 12) | (*(sptr + 1) >> 20)) | + ((*(sptr) << 11) | (*(sptr + 1) >> 21)) | + ((*(sptr) << 10) | (*(sptr + 1) >> 22)) | + ((*(sptr) << 9) | (*(sptr + 1) >> 23)) | + ((*(sptr) << 8) | (*(sptr + 1) >> 24)) | + ((*(sptr) << 7) | (*(sptr + 1) >> 25)) | + ((*(sptr) << 6) | (*(sptr + 1) >> 26)) | + ((*(sptr) << 5) | (*(sptr + 1) >> 27)) | + ((*(sptr) << 4) | (*(sptr + 1) >> 28)) | + ((*(sptr) << 3) | (*(sptr + 1) >> 29)) | + ((*(sptr) << 2) | (*(sptr + 1) >> 30)) | + ((*(sptr) << 1) | (*(sptr + 1) >> 31)) | + (*sptr) | + ((*(sptr) >> 1) | (*(sptr - 1) << 31)) | + ((*(sptr) >> 2) | (*(sptr - 1) << 30)) | + ((*(sptr) >> 3) | (*(sptr - 1) << 29)) | + ((*(sptr) >> 4) | (*(sptr - 1) << 28)) | + ((*(sptr) >> 5) | (*(sptr - 1) << 27)) | + ((*(sptr) >> 6) | (*(sptr - 1) << 26)) | + ((*(sptr) >> 7) | (*(sptr - 1) << 25)) | + ((*(sptr) >> 8) | (*(sptr - 1) << 24)) | + ((*(sptr) >> 9) | (*(sptr - 1) << 23)) | + ((*(sptr) >> 10) | (*(sptr - 1) << 22)) | + ((*(sptr) >> 11) | (*(sptr - 1) << 21)) | + ((*(sptr) >> 12) | (*(sptr - 1) << 20)) | + ((*(sptr) >> 13) | (*(sptr - 1) << 19)) | + ((*(sptr) >> 14) | (*(sptr - 1) << 18)) | + ((*(sptr) >> 15) | (*(sptr - 1) << 17)) | + ((*(sptr) >> 16) | (*(sptr - 1) << 16)) | + ((*(sptr) >> 17) | (*(sptr - 1) << 15)) | + ((*(sptr) >> 18) | (*(sptr - 1) << 14)) | + ((*(sptr) >> 19) | (*(sptr - 1) << 13)) | + ((*(sptr) >> 20) | (*(sptr - 1) << 12)) | + ((*(sptr) >> 21) | (*(sptr - 1) << 11)) | + ((*(sptr) >> 22) | (*(sptr - 1) << 10)) | + ((*(sptr) >> 23) | (*(sptr - 1) << 9)) | + ((*(sptr) >> 24) | (*(sptr - 1) << 8)) | + ((*(sptr) >> 25) | (*(sptr - 1) << 7)) | + ((*(sptr) >> 26) | (*(sptr - 1) << 6)) | + ((*(sptr) >> 27) | (*(sptr - 1) << 5)) | + ((*(sptr) >> 28) | (*(sptr - 1) << 4)); + } + } +} + +static void +ferode_3_56(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; + + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = ((*(sptr) >> 29) | (*(sptr - 1) << 3)) & + ((*(sptr) >> 28) | (*(sptr - 1) << 4)) & + ((*(sptr) >> 27) | (*(sptr - 1) << 5)) & + ((*(sptr) >> 26) | (*(sptr - 1) << 6)) & + ((*(sptr) >> 25) | (*(sptr - 1) << 7)) & + ((*(sptr) >> 24) | (*(sptr - 1) << 8)) & + ((*(sptr) >> 23) | (*(sptr - 1) << 9)) & + ((*(sptr) >> 22) | (*(sptr - 1) << 10)) & + ((*(sptr) >> 21) | (*(sptr - 1) << 11)) & + ((*(sptr) >> 20) | (*(sptr - 1) << 12)) & + ((*(sptr) >> 19) | (*(sptr - 1) << 13)) & + ((*(sptr) >> 18) | (*(sptr - 1) << 14)) & + ((*(sptr) >> 17) | (*(sptr - 1) << 15)) & + ((*(sptr) >> 16) | (*(sptr - 1) << 16)) & + ((*(sptr) >> 15) | (*(sptr - 1) << 17)) & + ((*(sptr) >> 14) | (*(sptr - 1) << 18)) & + ((*(sptr) >> 13) | (*(sptr - 1) << 19)) & + ((*(sptr) >> 12) | (*(sptr - 1) << 20)) & + ((*(sptr) >> 11) | (*(sptr - 1) << 21)) & + ((*(sptr) >> 10) | (*(sptr - 1) << 22)) & + ((*(sptr) >> 9) | (*(sptr - 1) << 23)) & + ((*(sptr) >> 8) | (*(sptr - 1) << 24)) & + ((*(sptr) >> 7) | (*(sptr - 1) << 25)) & + ((*(sptr) >> 6) | (*(sptr - 1) << 26)) & + ((*(sptr) >> 5) | (*(sptr - 1) << 27)) & + ((*(sptr) >> 4) | (*(sptr - 1) << 28)) & + ((*(sptr) >> 3) | (*(sptr - 1) << 29)) & + ((*(sptr) >> 2) | (*(sptr - 1) << 30)) & + ((*(sptr) >> 1) | (*(sptr - 1) << 31)) & + (*sptr) & + ((*(sptr) << 1) | (*(sptr + 1) >> 31)) & + ((*(sptr) << 2) | (*(sptr + 1) >> 30)) & + ((*(sptr) << 3) | (*(sptr + 1) >> 29)) & + ((*(sptr) << 4) | (*(sptr + 1) >> 28)) & + ((*(sptr) << 5) | (*(sptr + 1) >> 27)) & + ((*(sptr) << 6) | (*(sptr + 1) >> 26)) & + ((*(sptr) << 7) | (*(sptr + 1) >> 25)) & + ((*(sptr) << 8) | (*(sptr + 1) >> 24)) & + ((*(sptr) << 9) | (*(sptr + 1) >> 23)) & + ((*(sptr) << 10) | (*(sptr + 1) >> 22)) & + ((*(sptr) << 11) | (*(sptr + 1) >> 21)) & + ((*(sptr) << 12) | (*(sptr + 1) >> 20)) & + ((*(sptr) << 13) | (*(sptr + 1) >> 19)) & + ((*(sptr) << 14) | (*(sptr + 1) >> 18)) & + ((*(sptr) << 15) | (*(sptr + 1) >> 17)) & + ((*(sptr) << 16) | (*(sptr + 1) >> 16)) & + ((*(sptr) << 17) | (*(sptr + 1) >> 15)) & + ((*(sptr) << 18) | (*(sptr + 1) >> 14)) & + ((*(sptr) << 19) | (*(sptr + 1) >> 13)) & + ((*(sptr) << 20) | (*(sptr + 1) >> 12)) & + ((*(sptr) << 21) | (*(sptr + 1) >> 11)) & + ((*(sptr) << 22) | (*(sptr + 1) >> 10)) & + ((*(sptr) << 23) | (*(sptr + 1) >> 9)) & + ((*(sptr) << 24) | (*(sptr + 1) >> 8)) & + ((*(sptr) << 25) | (*(sptr + 1) >> 7)) & + ((*(sptr) << 26) | (*(sptr + 1) >> 6)) & + ((*(sptr) << 27) | (*(sptr + 1) >> 5)) & + ((*(sptr) << 28) | (*(sptr + 1) >> 4)); + } + } +} + +static void +fdilate_3_57(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; + + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = ((*(sptr) << 29) | (*(sptr + 1) >> 3)) | + ((*(sptr) << 28) | (*(sptr + 1) >> 4)) | + ((*(sptr) << 27) | (*(sptr + 1) >> 5)) | + ((*(sptr) << 26) | (*(sptr + 1) >> 6)) | + ((*(sptr) << 25) | (*(sptr + 1) >> 7)) | + ((*(sptr) << 24) | (*(sptr + 1) >> 8)) | + ((*(sptr) << 23) | (*(sptr + 1) >> 9)) | + ((*(sptr) << 22) | (*(sptr + 1) >> 10)) | + ((*(sptr) << 21) | (*(sptr + 1) >> 11)) | + ((*(sptr) << 20) | (*(sptr + 1) >> 12)) | + ((*(sptr) << 19) | (*(sptr + 1) >> 13)) | + ((*(sptr) << 18) | (*(sptr + 1) >> 14)) | + ((*(sptr) << 17) | (*(sptr + 1) >> 15)) | + ((*(sptr) << 16) | (*(sptr + 1) >> 16)) | + ((*(sptr) << 15) | (*(sptr + 1) >> 17)) | + ((*(sptr) << 14) | (*(sptr + 1) >> 18)) | + ((*(sptr) << 13) | (*(sptr + 1) >> 19)) | + ((*(sptr) << 12) | (*(sptr + 1) >> 20)) | + ((*(sptr) << 11) | (*(sptr + 1) >> 21)) | + ((*(sptr) << 10) | (*(sptr + 1) >> 22)) | + ((*(sptr) << 9) | (*(sptr + 1) >> 23)) | + ((*(sptr) << 8) | (*(sptr + 1) >> 24)) | + ((*(sptr) << 7) | (*(sptr + 1) >> 25)) | + ((*(sptr) << 6) | (*(sptr + 1) >> 26)) | + ((*(sptr) << 5) | (*(sptr + 1) >> 27)) | + ((*(sptr) << 4) | (*(sptr + 1) >> 28)) | + ((*(sptr) << 3) | (*(sptr + 1) >> 29)) | + ((*(sptr) << 2) | (*(sptr + 1) >> 30)) | + ((*(sptr) << 1) | (*(sptr + 1) >> 31)) | + (*sptr) | + ((*(sptr) >> 1) | (*(sptr - 1) << 31)) | + ((*(sptr) >> 2) | (*(sptr - 1) << 30)) | + ((*(sptr) >> 3) | (*(sptr - 1) << 29)) | + ((*(sptr) >> 4) | (*(sptr - 1) << 28)) | + ((*(sptr) >> 5) | (*(sptr - 1) << 27)) | + ((*(sptr) >> 6) | (*(sptr - 1) << 26)) | + ((*(sptr) >> 7) | (*(sptr - 1) << 25)) | + ((*(sptr) >> 8) | (*(sptr - 1) << 24)) | + ((*(sptr) >> 9) | (*(sptr - 1) << 23)) | + ((*(sptr) >> 10) | (*(sptr - 1) << 22)) | + ((*(sptr) >> 11) | (*(sptr - 1) << 21)) | + ((*(sptr) >> 12) | (*(sptr - 1) << 20)) | + ((*(sptr) >> 13) | (*(sptr - 1) << 19)) | + ((*(sptr) >> 14) | (*(sptr - 1) << 18)) | + ((*(sptr) >> 15) | (*(sptr - 1) << 17)) | + ((*(sptr) >> 16) | (*(sptr - 1) << 16)) | + ((*(sptr) >> 17) | (*(sptr - 1) << 15)) | + ((*(sptr) >> 18) | (*(sptr - 1) << 14)) | + ((*(sptr) >> 19) | (*(sptr - 1) << 13)) | + ((*(sptr) >> 20) | (*(sptr - 1) << 12)) | + ((*(sptr) >> 21) | (*(sptr - 1) << 11)) | + ((*(sptr) >> 22) | (*(sptr - 1) << 10)) | + ((*(sptr) >> 23) | (*(sptr - 1) << 9)) | + ((*(sptr) >> 24) | (*(sptr - 1) << 8)) | + ((*(sptr) >> 25) | (*(sptr - 1) << 7)) | + ((*(sptr) >> 26) | (*(sptr - 1) << 6)) | + ((*(sptr) >> 27) | (*(sptr - 1) << 5)) | + ((*(sptr) >> 28) | (*(sptr - 1) << 4)) | + ((*(sptr) >> 29) | (*(sptr - 1) << 3)); + } + } +} + +static void +ferode_3_57(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; + + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = ((*(sptr) >> 29) | (*(sptr - 1) << 3)) & + ((*(sptr) >> 28) | (*(sptr - 1) << 4)) & + ((*(sptr) >> 27) | (*(sptr - 1) << 5)) & + ((*(sptr) >> 26) | (*(sptr - 1) << 6)) & + ((*(sptr) >> 25) | (*(sptr - 1) << 7)) & + ((*(sptr) >> 24) | (*(sptr - 1) << 8)) & + ((*(sptr) >> 23) | (*(sptr - 1) << 9)) & + ((*(sptr) >> 22) | (*(sptr - 1) << 10)) & + ((*(sptr) >> 21) | (*(sptr - 1) << 11)) & + ((*(sptr) >> 20) | (*(sptr - 1) << 12)) & + ((*(sptr) >> 19) | (*(sptr - 1) << 13)) & + ((*(sptr) >> 18) | (*(sptr - 1) << 14)) & + ((*(sptr) >> 17) | (*(sptr - 1) << 15)) & + ((*(sptr) >> 16) | (*(sptr - 1) << 16)) & + ((*(sptr) >> 15) | (*(sptr - 1) << 17)) & + ((*(sptr) >> 14) | (*(sptr - 1) << 18)) & + ((*(sptr) >> 13) | (*(sptr - 1) << 19)) & + ((*(sptr) >> 12) | (*(sptr - 1) << 20)) & + ((*(sptr) >> 11) | (*(sptr - 1) << 21)) & + ((*(sptr) >> 10) | (*(sptr - 1) << 22)) & + ((*(sptr) >> 9) | (*(sptr - 1) << 23)) & + ((*(sptr) >> 8) | (*(sptr - 1) << 24)) & + ((*(sptr) >> 7) | (*(sptr - 1) << 25)) & + ((*(sptr) >> 6) | (*(sptr - 1) << 26)) & + ((*(sptr) >> 5) | (*(sptr - 1) << 27)) & + ((*(sptr) >> 4) | (*(sptr - 1) << 28)) & + ((*(sptr) >> 3) | (*(sptr - 1) << 29)) & + ((*(sptr) >> 2) | (*(sptr - 1) << 30)) & + ((*(sptr) >> 1) | (*(sptr - 1) << 31)) & + (*sptr) & + ((*(sptr) << 1) | (*(sptr + 1) >> 31)) & + ((*(sptr) << 2) | (*(sptr + 1) >> 30)) & + ((*(sptr) << 3) | (*(sptr + 1) >> 29)) & + ((*(sptr) << 4) | (*(sptr + 1) >> 28)) & + ((*(sptr) << 5) | (*(sptr + 1) >> 27)) & + ((*(sptr) << 6) | (*(sptr + 1) >> 26)) & + ((*(sptr) << 7) | (*(sptr + 1) >> 25)) & + ((*(sptr) << 8) | (*(sptr + 1) >> 24)) & + ((*(sptr) << 9) | (*(sptr + 1) >> 23)) & + ((*(sptr) << 10) | (*(sptr + 1) >> 22)) & + ((*(sptr) << 11) | (*(sptr + 1) >> 21)) & + ((*(sptr) << 12) | (*(sptr + 1) >> 20)) & + ((*(sptr) << 13) | (*(sptr + 1) >> 19)) & + ((*(sptr) << 14) | (*(sptr + 1) >> 18)) & + ((*(sptr) << 15) | (*(sptr + 1) >> 17)) & + ((*(sptr) << 16) | (*(sptr + 1) >> 16)) & + ((*(sptr) << 17) | (*(sptr + 1) >> 15)) & + ((*(sptr) << 18) | (*(sptr + 1) >> 14)) & + ((*(sptr) << 19) | (*(sptr + 1) >> 13)) & + ((*(sptr) << 20) | (*(sptr + 1) >> 12)) & + ((*(sptr) << 21) | (*(sptr + 1) >> 11)) & + ((*(sptr) << 22) | (*(sptr + 1) >> 10)) & + ((*(sptr) << 23) | (*(sptr + 1) >> 9)) & + ((*(sptr) << 24) | (*(sptr + 1) >> 8)) & + ((*(sptr) << 25) | (*(sptr + 1) >> 7)) & + ((*(sptr) << 26) | (*(sptr + 1) >> 6)) & + ((*(sptr) << 27) | (*(sptr + 1) >> 5)) & + ((*(sptr) << 28) | (*(sptr + 1) >> 4)) & + ((*(sptr) << 29) | (*(sptr + 1) >> 3)); + } + } +} + +static void +fdilate_3_58(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; + + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = ((*(sptr) << 30) | (*(sptr + 1) >> 2)) | + ((*(sptr) << 29) | (*(sptr + 1) >> 3)) | + ((*(sptr) << 28) | (*(sptr + 1) >> 4)) | + ((*(sptr) << 27) | (*(sptr + 1) >> 5)) | + ((*(sptr) << 26) | (*(sptr + 1) >> 6)) | + ((*(sptr) << 25) | (*(sptr + 1) >> 7)) | + ((*(sptr) << 24) | (*(sptr + 1) >> 8)) | + ((*(sptr) << 23) | (*(sptr + 1) >> 9)) | + ((*(sptr) << 22) | (*(sptr + 1) >> 10)) | + ((*(sptr) << 21) | (*(sptr + 1) >> 11)) | + ((*(sptr) << 20) | (*(sptr + 1) >> 12)) | + ((*(sptr) << 19) | (*(sptr + 1) >> 13)) | + ((*(sptr) << 18) | (*(sptr + 1) >> 14)) | + ((*(sptr) << 17) | (*(sptr + 1) >> 15)) | + ((*(sptr) << 16) | (*(sptr + 1) >> 16)) | + ((*(sptr) << 15) | (*(sptr + 1) >> 17)) | + ((*(sptr) << 14) | (*(sptr + 1) >> 18)) | + ((*(sptr) << 13) | (*(sptr + 1) >> 19)) | + ((*(sptr) << 12) | (*(sptr + 1) >> 20)) | + ((*(sptr) << 11) | (*(sptr + 1) >> 21)) | + ((*(sptr) << 10) | (*(sptr + 1) >> 22)) | + ((*(sptr) << 9) | (*(sptr + 1) >> 23)) | + ((*(sptr) << 8) | (*(sptr + 1) >> 24)) | + ((*(sptr) << 7) | (*(sptr + 1) >> 25)) | + ((*(sptr) << 6) | (*(sptr + 1) >> 26)) | + ((*(sptr) << 5) | (*(sptr + 1) >> 27)) | + ((*(sptr) << 4) | (*(sptr + 1) >> 28)) | + ((*(sptr) << 3) | (*(sptr + 1) >> 29)) | + ((*(sptr) << 2) | (*(sptr + 1) >> 30)) | + ((*(sptr) << 1) | (*(sptr + 1) >> 31)) | + (*sptr) | + ((*(sptr) >> 1) | (*(sptr - 1) << 31)) | + ((*(sptr) >> 2) | (*(sptr - 1) << 30)) | + ((*(sptr) >> 3) | (*(sptr - 1) << 29)) | + ((*(sptr) >> 4) | (*(sptr - 1) << 28)) | + ((*(sptr) >> 5) | (*(sptr - 1) << 27)) | + ((*(sptr) >> 6) | (*(sptr - 1) << 26)) | + ((*(sptr) >> 7) | (*(sptr - 1) << 25)) | + ((*(sptr) >> 8) | (*(sptr - 1) << 24)) | + ((*(sptr) >> 9) | (*(sptr - 1) << 23)) | + ((*(sptr) >> 10) | (*(sptr - 1) << 22)) | + ((*(sptr) >> 11) | (*(sptr - 1) << 21)) | + ((*(sptr) >> 12) | (*(sptr - 1) << 20)) | + ((*(sptr) >> 13) | (*(sptr - 1) << 19)) | + ((*(sptr) >> 14) | (*(sptr - 1) << 18)) | + ((*(sptr) >> 15) | (*(sptr - 1) << 17)) | + ((*(sptr) >> 16) | (*(sptr - 1) << 16)) | + ((*(sptr) >> 17) | (*(sptr - 1) << 15)) | + ((*(sptr) >> 18) | (*(sptr - 1) << 14)) | + ((*(sptr) >> 19) | (*(sptr - 1) << 13)) | + ((*(sptr) >> 20) | (*(sptr - 1) << 12)) | + ((*(sptr) >> 21) | (*(sptr - 1) << 11)) | + ((*(sptr) >> 22) | (*(sptr - 1) << 10)) | + ((*(sptr) >> 23) | (*(sptr - 1) << 9)) | + ((*(sptr) >> 24) | (*(sptr - 1) << 8)) | + ((*(sptr) >> 25) | (*(sptr - 1) << 7)) | + ((*(sptr) >> 26) | (*(sptr - 1) << 6)) | + ((*(sptr) >> 27) | (*(sptr - 1) << 5)) | + ((*(sptr) >> 28) | (*(sptr - 1) << 4)) | + ((*(sptr) >> 29) | (*(sptr - 1) << 3)); + } + } +} + +static void +ferode_3_58(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; + + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = ((*(sptr) >> 30) | (*(sptr - 1) << 2)) & + ((*(sptr) >> 29) | (*(sptr - 1) << 3)) & + ((*(sptr) >> 28) | (*(sptr - 1) << 4)) & + ((*(sptr) >> 27) | (*(sptr - 1) << 5)) & + ((*(sptr) >> 26) | (*(sptr - 1) << 6)) & + ((*(sptr) >> 25) | (*(sptr - 1) << 7)) & + ((*(sptr) >> 24) | (*(sptr - 1) << 8)) & + ((*(sptr) >> 23) | (*(sptr - 1) << 9)) & + ((*(sptr) >> 22) | (*(sptr - 1) << 10)) & + ((*(sptr) >> 21) | (*(sptr - 1) << 11)) & + ((*(sptr) >> 20) | (*(sptr - 1) << 12)) & + ((*(sptr) >> 19) | (*(sptr - 1) << 13)) & + ((*(sptr) >> 18) | (*(sptr - 1) << 14)) & + ((*(sptr) >> 17) | (*(sptr - 1) << 15)) & + ((*(sptr) >> 16) | (*(sptr - 1) << 16)) & + ((*(sptr) >> 15) | (*(sptr - 1) << 17)) & + ((*(sptr) >> 14) | (*(sptr - 1) << 18)) & + ((*(sptr) >> 13) | (*(sptr - 1) << 19)) & + ((*(sptr) >> 12) | (*(sptr - 1) << 20)) & + ((*(sptr) >> 11) | (*(sptr - 1) << 21)) & + ((*(sptr) >> 10) | (*(sptr - 1) << 22)) & + ((*(sptr) >> 9) | (*(sptr - 1) << 23)) & + ((*(sptr) >> 8) | (*(sptr - 1) << 24)) & + ((*(sptr) >> 7) | (*(sptr - 1) << 25)) & + ((*(sptr) >> 6) | (*(sptr - 1) << 26)) & + ((*(sptr) >> 5) | (*(sptr - 1) << 27)) & + ((*(sptr) >> 4) | (*(sptr - 1) << 28)) & + ((*(sptr) >> 3) | (*(sptr - 1) << 29)) & + ((*(sptr) >> 2) | (*(sptr - 1) << 30)) & + ((*(sptr) >> 1) | (*(sptr - 1) << 31)) & + (*sptr) & + ((*(sptr) << 1) | (*(sptr + 1) >> 31)) & + ((*(sptr) << 2) | (*(sptr + 1) >> 30)) & + ((*(sptr) << 3) | (*(sptr + 1) >> 29)) & + ((*(sptr) << 4) | (*(sptr + 1) >> 28)) & + ((*(sptr) << 5) | (*(sptr + 1) >> 27)) & + ((*(sptr) << 6) | (*(sptr + 1) >> 26)) & + ((*(sptr) << 7) | (*(sptr + 1) >> 25)) & + ((*(sptr) << 8) | (*(sptr + 1) >> 24)) & + ((*(sptr) << 9) | (*(sptr + 1) >> 23)) & + ((*(sptr) << 10) | (*(sptr + 1) >> 22)) & + ((*(sptr) << 11) | (*(sptr + 1) >> 21)) & + ((*(sptr) << 12) | (*(sptr + 1) >> 20)) & + ((*(sptr) << 13) | (*(sptr + 1) >> 19)) & + ((*(sptr) << 14) | (*(sptr + 1) >> 18)) & + ((*(sptr) << 15) | (*(sptr + 1) >> 17)) & + ((*(sptr) << 16) | (*(sptr + 1) >> 16)) & + ((*(sptr) << 17) | (*(sptr + 1) >> 15)) & + ((*(sptr) << 18) | (*(sptr + 1) >> 14)) & + ((*(sptr) << 19) | (*(sptr + 1) >> 13)) & + ((*(sptr) << 20) | (*(sptr + 1) >> 12)) & + ((*(sptr) << 21) | (*(sptr + 1) >> 11)) & + ((*(sptr) << 22) | (*(sptr + 1) >> 10)) & + ((*(sptr) << 23) | (*(sptr + 1) >> 9)) & + ((*(sptr) << 24) | (*(sptr + 1) >> 8)) & + ((*(sptr) << 25) | (*(sptr + 1) >> 7)) & + ((*(sptr) << 26) | (*(sptr + 1) >> 6)) & + ((*(sptr) << 27) | (*(sptr + 1) >> 5)) & + ((*(sptr) << 28) | (*(sptr + 1) >> 4)) & + ((*(sptr) << 29) | (*(sptr + 1) >> 3)); + } + } +} + +static void +fdilate_3_59(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; + + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = ((*(sptr) << 30) | (*(sptr + 1) >> 2)) | + ((*(sptr) << 29) | (*(sptr + 1) >> 3)) | + ((*(sptr) << 28) | (*(sptr + 1) >> 4)) | + ((*(sptr) << 27) | (*(sptr + 1) >> 5)) | + ((*(sptr) << 26) | (*(sptr + 1) >> 6)) | + ((*(sptr) << 25) | (*(sptr + 1) >> 7)) | + ((*(sptr) << 24) | (*(sptr + 1) >> 8)) | + ((*(sptr) << 23) | (*(sptr + 1) >> 9)) | + ((*(sptr) << 22) | (*(sptr + 1) >> 10)) | + ((*(sptr) << 21) | (*(sptr + 1) >> 11)) | + ((*(sptr) << 20) | (*(sptr + 1) >> 12)) | + ((*(sptr) << 19) | (*(sptr + 1) >> 13)) | + ((*(sptr) << 18) | (*(sptr + 1) >> 14)) | + ((*(sptr) << 17) | (*(sptr + 1) >> 15)) | + ((*(sptr) << 16) | (*(sptr + 1) >> 16)) | + ((*(sptr) << 15) | (*(sptr + 1) >> 17)) | + ((*(sptr) << 14) | (*(sptr + 1) >> 18)) | + ((*(sptr) << 13) | (*(sptr + 1) >> 19)) | + ((*(sptr) << 12) | (*(sptr + 1) >> 20)) | + ((*(sptr) << 11) | (*(sptr + 1) >> 21)) | + ((*(sptr) << 10) | (*(sptr + 1) >> 22)) | + ((*(sptr) << 9) | (*(sptr + 1) >> 23)) | + ((*(sptr) << 8) | (*(sptr + 1) >> 24)) | + ((*(sptr) << 7) | (*(sptr + 1) >> 25)) | + ((*(sptr) << 6) | (*(sptr + 1) >> 26)) | + ((*(sptr) << 5) | (*(sptr + 1) >> 27)) | + ((*(sptr) << 4) | (*(sptr + 1) >> 28)) | + ((*(sptr) << 3) | (*(sptr + 1) >> 29)) | + ((*(sptr) << 2) | (*(sptr + 1) >> 30)) | + ((*(sptr) << 1) | (*(sptr + 1) >> 31)) | + (*sptr) | + ((*(sptr) >> 1) | (*(sptr - 1) << 31)) | + ((*(sptr) >> 2) | (*(sptr - 1) << 30)) | + ((*(sptr) >> 3) | (*(sptr - 1) << 29)) | + ((*(sptr) >> 4) | (*(sptr - 1) << 28)) | + ((*(sptr) >> 5) | (*(sptr - 1) << 27)) | + ((*(sptr) >> 6) | (*(sptr - 1) << 26)) | + ((*(sptr) >> 7) | (*(sptr - 1) << 25)) | + ((*(sptr) >> 8) | (*(sptr - 1) << 24)) | + ((*(sptr) >> 9) | (*(sptr - 1) << 23)) | + ((*(sptr) >> 10) | (*(sptr - 1) << 22)) | + ((*(sptr) >> 11) | (*(sptr - 1) << 21)) | + ((*(sptr) >> 12) | (*(sptr - 1) << 20)) | + ((*(sptr) >> 13) | (*(sptr - 1) << 19)) | + ((*(sptr) >> 14) | (*(sptr - 1) << 18)) | + ((*(sptr) >> 15) | (*(sptr - 1) << 17)) | + ((*(sptr) >> 16) | (*(sptr - 1) << 16)) | + ((*(sptr) >> 17) | (*(sptr - 1) << 15)) | + ((*(sptr) >> 18) | (*(sptr - 1) << 14)) | + ((*(sptr) >> 19) | (*(sptr - 1) << 13)) | + ((*(sptr) >> 20) | (*(sptr - 1) << 12)) | + ((*(sptr) >> 21) | (*(sptr - 1) << 11)) | + ((*(sptr) >> 22) | (*(sptr - 1) << 10)) | + ((*(sptr) >> 23) | (*(sptr - 1) << 9)) | + ((*(sptr) >> 24) | (*(sptr - 1) << 8)) | + ((*(sptr) >> 25) | (*(sptr - 1) << 7)) | + ((*(sptr) >> 26) | (*(sptr - 1) << 6)) | + ((*(sptr) >> 27) | (*(sptr - 1) << 5)) | + ((*(sptr) >> 28) | (*(sptr - 1) << 4)) | + ((*(sptr) >> 29) | (*(sptr - 1) << 3)) | + ((*(sptr) >> 30) | (*(sptr - 1) << 2)); + } + } +} + +static void +ferode_3_59(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; + + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = ((*(sptr) >> 30) | (*(sptr - 1) << 2)) & + ((*(sptr) >> 29) | (*(sptr - 1) << 3)) & + ((*(sptr) >> 28) | (*(sptr - 1) << 4)) & + ((*(sptr) >> 27) | (*(sptr - 1) << 5)) & + ((*(sptr) >> 26) | (*(sptr - 1) << 6)) & + ((*(sptr) >> 25) | (*(sptr - 1) << 7)) & + ((*(sptr) >> 24) | (*(sptr - 1) << 8)) & + ((*(sptr) >> 23) | (*(sptr - 1) << 9)) & + ((*(sptr) >> 22) | (*(sptr - 1) << 10)) & + ((*(sptr) >> 21) | (*(sptr - 1) << 11)) & + ((*(sptr) >> 20) | (*(sptr - 1) << 12)) & + ((*(sptr) >> 19) | (*(sptr - 1) << 13)) & + ((*(sptr) >> 18) | (*(sptr - 1) << 14)) & + ((*(sptr) >> 17) | (*(sptr - 1) << 15)) & + ((*(sptr) >> 16) | (*(sptr - 1) << 16)) & + ((*(sptr) >> 15) | (*(sptr - 1) << 17)) & + ((*(sptr) >> 14) | (*(sptr - 1) << 18)) & + ((*(sptr) >> 13) | (*(sptr - 1) << 19)) & + ((*(sptr) >> 12) | (*(sptr - 1) << 20)) & + ((*(sptr) >> 11) | (*(sptr - 1) << 21)) & + ((*(sptr) >> 10) | (*(sptr - 1) << 22)) & + ((*(sptr) >> 9) | (*(sptr - 1) << 23)) & + ((*(sptr) >> 8) | (*(sptr - 1) << 24)) & + ((*(sptr) >> 7) | (*(sptr - 1) << 25)) & + ((*(sptr) >> 6) | (*(sptr - 1) << 26)) & + ((*(sptr) >> 5) | (*(sptr - 1) << 27)) & + ((*(sptr) >> 4) | (*(sptr - 1) << 28)) & + ((*(sptr) >> 3) | (*(sptr - 1) << 29)) & + ((*(sptr) >> 2) | (*(sptr - 1) << 30)) & + ((*(sptr) >> 1) | (*(sptr - 1) << 31)) & + (*sptr) & + ((*(sptr) << 1) | (*(sptr + 1) >> 31)) & + ((*(sptr) << 2) | (*(sptr + 1) >> 30)) & + ((*(sptr) << 3) | (*(sptr + 1) >> 29)) & + ((*(sptr) << 4) | (*(sptr + 1) >> 28)) & + ((*(sptr) << 5) | (*(sptr + 1) >> 27)) & + ((*(sptr) << 6) | (*(sptr + 1) >> 26)) & + ((*(sptr) << 7) | (*(sptr + 1) >> 25)) & + ((*(sptr) << 8) | (*(sptr + 1) >> 24)) & + ((*(sptr) << 9) | (*(sptr + 1) >> 23)) & + ((*(sptr) << 10) | (*(sptr + 1) >> 22)) & + ((*(sptr) << 11) | (*(sptr + 1) >> 21)) & + ((*(sptr) << 12) | (*(sptr + 1) >> 20)) & + ((*(sptr) << 13) | (*(sptr + 1) >> 19)) & + ((*(sptr) << 14) | (*(sptr + 1) >> 18)) & + ((*(sptr) << 15) | (*(sptr + 1) >> 17)) & + ((*(sptr) << 16) | (*(sptr + 1) >> 16)) & + ((*(sptr) << 17) | (*(sptr + 1) >> 15)) & + ((*(sptr) << 18) | (*(sptr + 1) >> 14)) & + ((*(sptr) << 19) | (*(sptr + 1) >> 13)) & + ((*(sptr) << 20) | (*(sptr + 1) >> 12)) & + ((*(sptr) << 21) | (*(sptr + 1) >> 11)) & + ((*(sptr) << 22) | (*(sptr + 1) >> 10)) & + ((*(sptr) << 23) | (*(sptr + 1) >> 9)) & + ((*(sptr) << 24) | (*(sptr + 1) >> 8)) & + ((*(sptr) << 25) | (*(sptr + 1) >> 7)) & + ((*(sptr) << 26) | (*(sptr + 1) >> 6)) & + ((*(sptr) << 27) | (*(sptr + 1) >> 5)) & + ((*(sptr) << 28) | (*(sptr + 1) >> 4)) & + ((*(sptr) << 29) | (*(sptr + 1) >> 3)) & + ((*(sptr) << 30) | (*(sptr + 1) >> 2)); + } + } +} + +static void +fdilate_3_60(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; + + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = ((*(sptr) << 31) | (*(sptr + 1) >> 1)) | + ((*(sptr) << 30) | (*(sptr + 1) >> 2)) | + ((*(sptr) << 29) | (*(sptr + 1) >> 3)) | + ((*(sptr) << 28) | (*(sptr + 1) >> 4)) | + ((*(sptr) << 27) | (*(sptr + 1) >> 5)) | + ((*(sptr) << 26) | (*(sptr + 1) >> 6)) | + ((*(sptr) << 25) | (*(sptr + 1) >> 7)) | + ((*(sptr) << 24) | (*(sptr + 1) >> 8)) | + ((*(sptr) << 23) | (*(sptr + 1) >> 9)) | + ((*(sptr) << 22) | (*(sptr + 1) >> 10)) | + ((*(sptr) << 21) | (*(sptr + 1) >> 11)) | + ((*(sptr) << 20) | (*(sptr + 1) >> 12)) | + ((*(sptr) << 19) | (*(sptr + 1) >> 13)) | + ((*(sptr) << 18) | (*(sptr + 1) >> 14)) | + ((*(sptr) << 17) | (*(sptr + 1) >> 15)) | + ((*(sptr) << 16) | (*(sptr + 1) >> 16)) | + ((*(sptr) << 15) | (*(sptr + 1) >> 17)) | + ((*(sptr) << 14) | (*(sptr + 1) >> 18)) | + ((*(sptr) << 13) | (*(sptr + 1) >> 19)) | + ((*(sptr) << 12) | (*(sptr + 1) >> 20)) | + ((*(sptr) << 11) | (*(sptr + 1) >> 21)) | + ((*(sptr) << 10) | (*(sptr + 1) >> 22)) | + ((*(sptr) << 9) | (*(sptr + 1) >> 23)) | + ((*(sptr) << 8) | (*(sptr + 1) >> 24)) | + ((*(sptr) << 7) | (*(sptr + 1) >> 25)) | + ((*(sptr) << 6) | (*(sptr + 1) >> 26)) | + ((*(sptr) << 5) | (*(sptr + 1) >> 27)) | + ((*(sptr) << 4) | (*(sptr + 1) >> 28)) | + ((*(sptr) << 3) | (*(sptr + 1) >> 29)) | + ((*(sptr) << 2) | (*(sptr + 1) >> 30)) | + ((*(sptr) << 1) | (*(sptr + 1) >> 31)) | + (*sptr) | + ((*(sptr) >> 1) | (*(sptr - 1) << 31)) | + ((*(sptr) >> 2) | (*(sptr - 1) << 30)) | + ((*(sptr) >> 3) | (*(sptr - 1) << 29)) | + ((*(sptr) >> 4) | (*(sptr - 1) << 28)) | + ((*(sptr) >> 5) | (*(sptr - 1) << 27)) | + ((*(sptr) >> 6) | (*(sptr - 1) << 26)) | + ((*(sptr) >> 7) | (*(sptr - 1) << 25)) | + ((*(sptr) >> 8) | (*(sptr - 1) << 24)) | + ((*(sptr) >> 9) | (*(sptr - 1) << 23)) | + ((*(sptr) >> 10) | (*(sptr - 1) << 22)) | + ((*(sptr) >> 11) | (*(sptr - 1) << 21)) | + ((*(sptr) >> 12) | (*(sptr - 1) << 20)) | + ((*(sptr) >> 13) | (*(sptr - 1) << 19)) | + ((*(sptr) >> 14) | (*(sptr - 1) << 18)) | + ((*(sptr) >> 15) | (*(sptr - 1) << 17)) | + ((*(sptr) >> 16) | (*(sptr - 1) << 16)) | + ((*(sptr) >> 17) | (*(sptr - 1) << 15)) | + ((*(sptr) >> 18) | (*(sptr - 1) << 14)) | + ((*(sptr) >> 19) | (*(sptr - 1) << 13)) | + ((*(sptr) >> 20) | (*(sptr - 1) << 12)) | + ((*(sptr) >> 21) | (*(sptr - 1) << 11)) | + ((*(sptr) >> 22) | (*(sptr - 1) << 10)) | + ((*(sptr) >> 23) | (*(sptr - 1) << 9)) | + ((*(sptr) >> 24) | (*(sptr - 1) << 8)) | + ((*(sptr) >> 25) | (*(sptr - 1) << 7)) | + ((*(sptr) >> 26) | (*(sptr - 1) << 6)) | + ((*(sptr) >> 27) | (*(sptr - 1) << 5)) | + ((*(sptr) >> 28) | (*(sptr - 1) << 4)) | + ((*(sptr) >> 29) | (*(sptr - 1) << 3)) | + ((*(sptr) >> 30) | (*(sptr - 1) << 2)); + } + } +} + +static void +ferode_3_60(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; + + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = ((*(sptr) >> 31) | (*(sptr - 1) << 1)) & + ((*(sptr) >> 30) | (*(sptr - 1) << 2)) & + ((*(sptr) >> 29) | (*(sptr - 1) << 3)) & + ((*(sptr) >> 28) | (*(sptr - 1) << 4)) & + ((*(sptr) >> 27) | (*(sptr - 1) << 5)) & + ((*(sptr) >> 26) | (*(sptr - 1) << 6)) & + ((*(sptr) >> 25) | (*(sptr - 1) << 7)) & + ((*(sptr) >> 24) | (*(sptr - 1) << 8)) & + ((*(sptr) >> 23) | (*(sptr - 1) << 9)) & + ((*(sptr) >> 22) | (*(sptr - 1) << 10)) & + ((*(sptr) >> 21) | (*(sptr - 1) << 11)) & + ((*(sptr) >> 20) | (*(sptr - 1) << 12)) & + ((*(sptr) >> 19) | (*(sptr - 1) << 13)) & + ((*(sptr) >> 18) | (*(sptr - 1) << 14)) & + ((*(sptr) >> 17) | (*(sptr - 1) << 15)) & + ((*(sptr) >> 16) | (*(sptr - 1) << 16)) & + ((*(sptr) >> 15) | (*(sptr - 1) << 17)) & + ((*(sptr) >> 14) | (*(sptr - 1) << 18)) & + ((*(sptr) >> 13) | (*(sptr - 1) << 19)) & + ((*(sptr) >> 12) | (*(sptr - 1) << 20)) & + ((*(sptr) >> 11) | (*(sptr - 1) << 21)) & + ((*(sptr) >> 10) | (*(sptr - 1) << 22)) & + ((*(sptr) >> 9) | (*(sptr - 1) << 23)) & + ((*(sptr) >> 8) | (*(sptr - 1) << 24)) & + ((*(sptr) >> 7) | (*(sptr - 1) << 25)) & + ((*(sptr) >> 6) | (*(sptr - 1) << 26)) & + ((*(sptr) >> 5) | (*(sptr - 1) << 27)) & + ((*(sptr) >> 4) | (*(sptr - 1) << 28)) & + ((*(sptr) >> 3) | (*(sptr - 1) << 29)) & + ((*(sptr) >> 2) | (*(sptr - 1) << 30)) & + ((*(sptr) >> 1) | (*(sptr - 1) << 31)) & + (*sptr) & + ((*(sptr) << 1) | (*(sptr + 1) >> 31)) & + ((*(sptr) << 2) | (*(sptr + 1) >> 30)) & + ((*(sptr) << 3) | (*(sptr + 1) >> 29)) & + ((*(sptr) << 4) | (*(sptr + 1) >> 28)) & + ((*(sptr) << 5) | (*(sptr + 1) >> 27)) & + ((*(sptr) << 6) | (*(sptr + 1) >> 26)) & + ((*(sptr) << 7) | (*(sptr + 1) >> 25)) & + ((*(sptr) << 8) | (*(sptr + 1) >> 24)) & + ((*(sptr) << 9) | (*(sptr + 1) >> 23)) & + ((*(sptr) << 10) | (*(sptr + 1) >> 22)) & + ((*(sptr) << 11) | (*(sptr + 1) >> 21)) & + ((*(sptr) << 12) | (*(sptr + 1) >> 20)) & + ((*(sptr) << 13) | (*(sptr + 1) >> 19)) & + ((*(sptr) << 14) | (*(sptr + 1) >> 18)) & + ((*(sptr) << 15) | (*(sptr + 1) >> 17)) & + ((*(sptr) << 16) | (*(sptr + 1) >> 16)) & + ((*(sptr) << 17) | (*(sptr + 1) >> 15)) & + ((*(sptr) << 18) | (*(sptr + 1) >> 14)) & + ((*(sptr) << 19) | (*(sptr + 1) >> 13)) & + ((*(sptr) << 20) | (*(sptr + 1) >> 12)) & + ((*(sptr) << 21) | (*(sptr + 1) >> 11)) & + ((*(sptr) << 22) | (*(sptr + 1) >> 10)) & + ((*(sptr) << 23) | (*(sptr + 1) >> 9)) & + ((*(sptr) << 24) | (*(sptr + 1) >> 8)) & + ((*(sptr) << 25) | (*(sptr + 1) >> 7)) & + ((*(sptr) << 26) | (*(sptr + 1) >> 6)) & + ((*(sptr) << 27) | (*(sptr + 1) >> 5)) & + ((*(sptr) << 28) | (*(sptr + 1) >> 4)) & + ((*(sptr) << 29) | (*(sptr + 1) >> 3)) & + ((*(sptr) << 30) | (*(sptr + 1) >> 2)); + } + } +} + +static void +fdilate_3_61(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; + + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = ((*(sptr) << 31) | (*(sptr + 1) >> 1)) | + ((*(sptr) << 30) | (*(sptr + 1) >> 2)) | + ((*(sptr) << 29) | (*(sptr + 1) >> 3)) | + ((*(sptr) << 28) | (*(sptr + 1) >> 4)) | + ((*(sptr) << 27) | (*(sptr + 1) >> 5)) | + ((*(sptr) << 26) | (*(sptr + 1) >> 6)) | + ((*(sptr) << 25) | (*(sptr + 1) >> 7)) | + ((*(sptr) << 24) | (*(sptr + 1) >> 8)) | + ((*(sptr) << 23) | (*(sptr + 1) >> 9)) | + ((*(sptr) << 22) | (*(sptr + 1) >> 10)) | + ((*(sptr) << 21) | (*(sptr + 1) >> 11)) | + ((*(sptr) << 20) | (*(sptr + 1) >> 12)) | + ((*(sptr) << 19) | (*(sptr + 1) >> 13)) | + ((*(sptr) << 18) | (*(sptr + 1) >> 14)) | + ((*(sptr) << 17) | (*(sptr + 1) >> 15)) | + ((*(sptr) << 16) | (*(sptr + 1) >> 16)) | + ((*(sptr) << 15) | (*(sptr + 1) >> 17)) | + ((*(sptr) << 14) | (*(sptr + 1) >> 18)) | + ((*(sptr) << 13) | (*(sptr + 1) >> 19)) | + ((*(sptr) << 12) | (*(sptr + 1) >> 20)) | + ((*(sptr) << 11) | (*(sptr + 1) >> 21)) | + ((*(sptr) << 10) | (*(sptr + 1) >> 22)) | + ((*(sptr) << 9) | (*(sptr + 1) >> 23)) | + ((*(sptr) << 8) | (*(sptr + 1) >> 24)) | + ((*(sptr) << 7) | (*(sptr + 1) >> 25)) | + ((*(sptr) << 6) | (*(sptr + 1) >> 26)) | + ((*(sptr) << 5) | (*(sptr + 1) >> 27)) | + ((*(sptr) << 4) | (*(sptr + 1) >> 28)) | + ((*(sptr) << 3) | (*(sptr + 1) >> 29)) | + ((*(sptr) << 2) | (*(sptr + 1) >> 30)) | + ((*(sptr) << 1) | (*(sptr + 1) >> 31)) | + (*sptr) | + ((*(sptr) >> 1) | (*(sptr - 1) << 31)) | + ((*(sptr) >> 2) | (*(sptr - 1) << 30)) | + ((*(sptr) >> 3) | (*(sptr - 1) << 29)) | + ((*(sptr) >> 4) | (*(sptr - 1) << 28)) | + ((*(sptr) >> 5) | (*(sptr - 1) << 27)) | + ((*(sptr) >> 6) | (*(sptr - 1) << 26)) | + ((*(sptr) >> 7) | (*(sptr - 1) << 25)) | + ((*(sptr) >> 8) | (*(sptr - 1) << 24)) | + ((*(sptr) >> 9) | (*(sptr - 1) << 23)) | + ((*(sptr) >> 10) | (*(sptr - 1) << 22)) | + ((*(sptr) >> 11) | (*(sptr - 1) << 21)) | + ((*(sptr) >> 12) | (*(sptr - 1) << 20)) | + ((*(sptr) >> 13) | (*(sptr - 1) << 19)) | + ((*(sptr) >> 14) | (*(sptr - 1) << 18)) | + ((*(sptr) >> 15) | (*(sptr - 1) << 17)) | + ((*(sptr) >> 16) | (*(sptr - 1) << 16)) | + ((*(sptr) >> 17) | (*(sptr - 1) << 15)) | + ((*(sptr) >> 18) | (*(sptr - 1) << 14)) | + ((*(sptr) >> 19) | (*(sptr - 1) << 13)) | + ((*(sptr) >> 20) | (*(sptr - 1) << 12)) | + ((*(sptr) >> 21) | (*(sptr - 1) << 11)) | + ((*(sptr) >> 22) | (*(sptr - 1) << 10)) | + ((*(sptr) >> 23) | (*(sptr - 1) << 9)) | + ((*(sptr) >> 24) | (*(sptr - 1) << 8)) | + ((*(sptr) >> 25) | (*(sptr - 1) << 7)) | + ((*(sptr) >> 26) | (*(sptr - 1) << 6)) | + ((*(sptr) >> 27) | (*(sptr - 1) << 5)) | + ((*(sptr) >> 28) | (*(sptr - 1) << 4)) | + ((*(sptr) >> 29) | (*(sptr - 1) << 3)) | + ((*(sptr) >> 30) | (*(sptr - 1) << 2)) | + ((*(sptr) >> 31) | (*(sptr - 1) << 1)); + } + } +} + +static void +ferode_3_61(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; + + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = ((*(sptr) >> 31) | (*(sptr - 1) << 1)) & + ((*(sptr) >> 30) | (*(sptr - 1) << 2)) & + ((*(sptr) >> 29) | (*(sptr - 1) << 3)) & + ((*(sptr) >> 28) | (*(sptr - 1) << 4)) & + ((*(sptr) >> 27) | (*(sptr - 1) << 5)) & + ((*(sptr) >> 26) | (*(sptr - 1) << 6)) & + ((*(sptr) >> 25) | (*(sptr - 1) << 7)) & + ((*(sptr) >> 24) | (*(sptr - 1) << 8)) & + ((*(sptr) >> 23) | (*(sptr - 1) << 9)) & + ((*(sptr) >> 22) | (*(sptr - 1) << 10)) & + ((*(sptr) >> 21) | (*(sptr - 1) << 11)) & + ((*(sptr) >> 20) | (*(sptr - 1) << 12)) & + ((*(sptr) >> 19) | (*(sptr - 1) << 13)) & + ((*(sptr) >> 18) | (*(sptr - 1) << 14)) & + ((*(sptr) >> 17) | (*(sptr - 1) << 15)) & + ((*(sptr) >> 16) | (*(sptr - 1) << 16)) & + ((*(sptr) >> 15) | (*(sptr - 1) << 17)) & + ((*(sptr) >> 14) | (*(sptr - 1) << 18)) & + ((*(sptr) >> 13) | (*(sptr - 1) << 19)) & + ((*(sptr) >> 12) | (*(sptr - 1) << 20)) & + ((*(sptr) >> 11) | (*(sptr - 1) << 21)) & + ((*(sptr) >> 10) | (*(sptr - 1) << 22)) & + ((*(sptr) >> 9) | (*(sptr - 1) << 23)) & + ((*(sptr) >> 8) | (*(sptr - 1) << 24)) & + ((*(sptr) >> 7) | (*(sptr - 1) << 25)) & + ((*(sptr) >> 6) | (*(sptr - 1) << 26)) & + ((*(sptr) >> 5) | (*(sptr - 1) << 27)) & + ((*(sptr) >> 4) | (*(sptr - 1) << 28)) & + ((*(sptr) >> 3) | (*(sptr - 1) << 29)) & + ((*(sptr) >> 2) | (*(sptr - 1) << 30)) & + ((*(sptr) >> 1) | (*(sptr - 1) << 31)) & + (*sptr) & + ((*(sptr) << 1) | (*(sptr + 1) >> 31)) & + ((*(sptr) << 2) | (*(sptr + 1) >> 30)) & + ((*(sptr) << 3) | (*(sptr + 1) >> 29)) & + ((*(sptr) << 4) | (*(sptr + 1) >> 28)) & + ((*(sptr) << 5) | (*(sptr + 1) >> 27)) & + ((*(sptr) << 6) | (*(sptr + 1) >> 26)) & + ((*(sptr) << 7) | (*(sptr + 1) >> 25)) & + ((*(sptr) << 8) | (*(sptr + 1) >> 24)) & + ((*(sptr) << 9) | (*(sptr + 1) >> 23)) & + ((*(sptr) << 10) | (*(sptr + 1) >> 22)) & + ((*(sptr) << 11) | (*(sptr + 1) >> 21)) & + ((*(sptr) << 12) | (*(sptr + 1) >> 20)) & + ((*(sptr) << 13) | (*(sptr + 1) >> 19)) & + ((*(sptr) << 14) | (*(sptr + 1) >> 18)) & + ((*(sptr) << 15) | (*(sptr + 1) >> 17)) & + ((*(sptr) << 16) | (*(sptr + 1) >> 16)) & + ((*(sptr) << 17) | (*(sptr + 1) >> 15)) & + ((*(sptr) << 18) | (*(sptr + 1) >> 14)) & + ((*(sptr) << 19) | (*(sptr + 1) >> 13)) & + ((*(sptr) << 20) | (*(sptr + 1) >> 12)) & + ((*(sptr) << 21) | (*(sptr + 1) >> 11)) & + ((*(sptr) << 22) | (*(sptr + 1) >> 10)) & + ((*(sptr) << 23) | (*(sptr + 1) >> 9)) & + ((*(sptr) << 24) | (*(sptr + 1) >> 8)) & + ((*(sptr) << 25) | (*(sptr + 1) >> 7)) & + ((*(sptr) << 26) | (*(sptr + 1) >> 6)) & + ((*(sptr) << 27) | (*(sptr + 1) >> 5)) & + ((*(sptr) << 28) | (*(sptr + 1) >> 4)) & + ((*(sptr) << 29) | (*(sptr + 1) >> 3)) & + ((*(sptr) << 30) | (*(sptr + 1) >> 2)) & + ((*(sptr) << 31) | (*(sptr + 1) >> 1)); + } + } +} + +static void +fdilate_3_62(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; + + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = (*(sptr + wpls)) | + (*sptr); + } + } +} + +static void +ferode_3_62(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; + + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = (*(sptr - wpls)) & + (*sptr); + } + } +} + +static void +fdilate_3_63(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; + + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = (*(sptr + wpls)) | + (*sptr) | + (*(sptr - wpls)); + } + } +} + +static void +ferode_3_63(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; + + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = (*(sptr - wpls)) & + (*sptr) & + (*(sptr + wpls)); + } + } +} + +static void +fdilate_3_64(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; +l_int32 wpls2; + + wpls2 = 2 * wpls; + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = (*(sptr + wpls2)) | + (*(sptr + wpls)) | + (*sptr) | + (*(sptr - wpls)); + } + } +} + +static void +ferode_3_64(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; +l_int32 wpls2; + + wpls2 = 2 * wpls; + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = (*(sptr - wpls2)) & + (*(sptr - wpls)) & + (*sptr) & + (*(sptr + wpls)); + } + } +} + +static void +fdilate_3_65(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; +l_int32 wpls2; + + wpls2 = 2 * wpls; + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = (*(sptr + wpls2)) | + (*(sptr + wpls)) | + (*sptr) | + (*(sptr - wpls)) | + (*(sptr - wpls2)); + } + } +} + +static void +ferode_3_65(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; +l_int32 wpls2; + + wpls2 = 2 * wpls; + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = (*(sptr - wpls2)) & + (*(sptr - wpls)) & + (*sptr) & + (*(sptr + wpls)) & + (*(sptr + wpls2)); + } + } +} + +static void +fdilate_3_66(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; +l_int32 wpls2, wpls3; + + wpls2 = 2 * wpls; + wpls3 = 3 * wpls; + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = (*(sptr + wpls3)) | + (*(sptr + wpls2)) | + (*(sptr + wpls)) | + (*sptr) | + (*(sptr - wpls)) | + (*(sptr - wpls2)); + } + } +} + +static void +ferode_3_66(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; +l_int32 wpls2, wpls3; + + wpls2 = 2 * wpls; + wpls3 = 3 * wpls; + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = (*(sptr - wpls3)) & + (*(sptr - wpls2)) & + (*(sptr - wpls)) & + (*sptr) & + (*(sptr + wpls)) & + (*(sptr + wpls2)); + } + } +} + +static void +fdilate_3_67(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; +l_int32 wpls2, wpls3; + + wpls2 = 2 * wpls; + wpls3 = 3 * wpls; + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = (*(sptr + wpls3)) | + (*(sptr + wpls2)) | + (*(sptr + wpls)) | + (*sptr) | + (*(sptr - wpls)) | + (*(sptr - wpls2)) | + (*(sptr - wpls3)); + } + } +} + +static void +ferode_3_67(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; +l_int32 wpls2, wpls3; + + wpls2 = 2 * wpls; + wpls3 = 3 * wpls; + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = (*(sptr - wpls3)) & + (*(sptr - wpls2)) & + (*(sptr - wpls)) & + (*sptr) & + (*(sptr + wpls)) & + (*(sptr + wpls2)) & + (*(sptr + wpls3)); + } + } +} + +static void +fdilate_3_68(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; +l_int32 wpls2, wpls3, wpls4; + + wpls2 = 2 * wpls; + wpls3 = 3 * wpls; + wpls4 = 4 * wpls; + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = (*(sptr + wpls4)) | + (*(sptr + wpls3)) | + (*(sptr + wpls2)) | + (*(sptr + wpls)) | + (*sptr) | + (*(sptr - wpls)) | + (*(sptr - wpls2)) | + (*(sptr - wpls3)); + } + } +} + +static void +ferode_3_68(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; +l_int32 wpls2, wpls3, wpls4; + + wpls2 = 2 * wpls; + wpls3 = 3 * wpls; + wpls4 = 4 * wpls; + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = (*(sptr - wpls4)) & + (*(sptr - wpls3)) & + (*(sptr - wpls2)) & + (*(sptr - wpls)) & + (*sptr) & + (*(sptr + wpls)) & + (*(sptr + wpls2)) & + (*(sptr + wpls3)); + } + } +} + +static void +fdilate_3_69(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; +l_int32 wpls2, wpls3, wpls4; + + wpls2 = 2 * wpls; + wpls3 = 3 * wpls; + wpls4 = 4 * wpls; + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = (*(sptr + wpls4)) | + (*(sptr + wpls3)) | + (*(sptr + wpls2)) | + (*(sptr + wpls)) | + (*sptr) | + (*(sptr - wpls)) | + (*(sptr - wpls2)) | + (*(sptr - wpls3)) | + (*(sptr - wpls4)); + } + } +} + +static void +ferode_3_69(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; +l_int32 wpls2, wpls3, wpls4; + + wpls2 = 2 * wpls; + wpls3 = 3 * wpls; + wpls4 = 4 * wpls; + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = (*(sptr - wpls4)) & + (*(sptr - wpls3)) & + (*(sptr - wpls2)) & + (*(sptr - wpls)) & + (*sptr) & + (*(sptr + wpls)) & + (*(sptr + wpls2)) & + (*(sptr + wpls3)) & + (*(sptr + wpls4)); + } + } +} + +static void +fdilate_3_70(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; +l_int32 wpls2, wpls3, wpls4; +l_int32 wpls5; + + wpls2 = 2 * wpls; + wpls3 = 3 * wpls; + wpls4 = 4 * wpls; + wpls5 = 5 * wpls; + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = (*(sptr + wpls5)) | + (*(sptr + wpls4)) | + (*(sptr + wpls3)) | + (*(sptr + wpls2)) | + (*(sptr + wpls)) | + (*sptr) | + (*(sptr - wpls)) | + (*(sptr - wpls2)) | + (*(sptr - wpls3)) | + (*(sptr - wpls4)); + } + } +} + +static void +ferode_3_70(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; +l_int32 wpls2, wpls3, wpls4; +l_int32 wpls5; + + wpls2 = 2 * wpls; + wpls3 = 3 * wpls; + wpls4 = 4 * wpls; + wpls5 = 5 * wpls; + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = (*(sptr - wpls5)) & + (*(sptr - wpls4)) & + (*(sptr - wpls3)) & + (*(sptr - wpls2)) & + (*(sptr - wpls)) & + (*sptr) & + (*(sptr + wpls)) & + (*(sptr + wpls2)) & + (*(sptr + wpls3)) & + (*(sptr + wpls4)); + } + } +} + +static void +fdilate_3_71(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; +l_int32 wpls2, wpls3, wpls4; +l_int32 wpls5; + + wpls2 = 2 * wpls; + wpls3 = 3 * wpls; + wpls4 = 4 * wpls; + wpls5 = 5 * wpls; + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = (*(sptr + wpls5)) | + (*(sptr + wpls4)) | + (*(sptr + wpls3)) | + (*(sptr + wpls2)) | + (*(sptr + wpls)) | + (*sptr) | + (*(sptr - wpls)) | + (*(sptr - wpls2)) | + (*(sptr - wpls3)) | + (*(sptr - wpls4)) | + (*(sptr - wpls5)); + } + } +} + +static void +ferode_3_71(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; +l_int32 wpls2, wpls3, wpls4; +l_int32 wpls5; + + wpls2 = 2 * wpls; + wpls3 = 3 * wpls; + wpls4 = 4 * wpls; + wpls5 = 5 * wpls; + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = (*(sptr - wpls5)) & + (*(sptr - wpls4)) & + (*(sptr - wpls3)) & + (*(sptr - wpls2)) & + (*(sptr - wpls)) & + (*sptr) & + (*(sptr + wpls)) & + (*(sptr + wpls2)) & + (*(sptr + wpls3)) & + (*(sptr + wpls4)) & + (*(sptr + wpls5)); + } + } +} + +static void +fdilate_3_72(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; +l_int32 wpls2, wpls3, wpls4; +l_int32 wpls5, wpls6; + + wpls2 = 2 * wpls; + wpls3 = 3 * wpls; + wpls4 = 4 * wpls; + wpls5 = 5 * wpls; + wpls6 = 6 * wpls; + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = (*(sptr + wpls6)) | + (*(sptr + wpls5)) | + (*(sptr + wpls4)) | + (*(sptr + wpls3)) | + (*(sptr + wpls2)) | + (*(sptr + wpls)) | + (*sptr) | + (*(sptr - wpls)) | + (*(sptr - wpls2)) | + (*(sptr - wpls3)) | + (*(sptr - wpls4)) | + (*(sptr - wpls5)); + } + } +} + +static void +ferode_3_72(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; +l_int32 wpls2, wpls3, wpls4; +l_int32 wpls5, wpls6; + + wpls2 = 2 * wpls; + wpls3 = 3 * wpls; + wpls4 = 4 * wpls; + wpls5 = 5 * wpls; + wpls6 = 6 * wpls; + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = (*(sptr - wpls6)) & + (*(sptr - wpls5)) & + (*(sptr - wpls4)) & + (*(sptr - wpls3)) & + (*(sptr - wpls2)) & + (*(sptr - wpls)) & + (*sptr) & + (*(sptr + wpls)) & + (*(sptr + wpls2)) & + (*(sptr + wpls3)) & + (*(sptr + wpls4)) & + (*(sptr + wpls5)); + } + } +} + +static void +fdilate_3_73(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; +l_int32 wpls2, wpls3, wpls4; +l_int32 wpls5, wpls6; + + wpls2 = 2 * wpls; + wpls3 = 3 * wpls; + wpls4 = 4 * wpls; + wpls5 = 5 * wpls; + wpls6 = 6 * wpls; + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = (*(sptr + wpls6)) | + (*(sptr + wpls5)) | + (*(sptr + wpls4)) | + (*(sptr + wpls3)) | + (*(sptr + wpls2)) | + (*(sptr + wpls)) | + (*sptr) | + (*(sptr - wpls)) | + (*(sptr - wpls2)) | + (*(sptr - wpls3)) | + (*(sptr - wpls4)) | + (*(sptr - wpls5)) | + (*(sptr - wpls6)); + } + } +} + +static void +ferode_3_73(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; +l_int32 wpls2, wpls3, wpls4; +l_int32 wpls5, wpls6; + + wpls2 = 2 * wpls; + wpls3 = 3 * wpls; + wpls4 = 4 * wpls; + wpls5 = 5 * wpls; + wpls6 = 6 * wpls; + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = (*(sptr - wpls6)) & + (*(sptr - wpls5)) & + (*(sptr - wpls4)) & + (*(sptr - wpls3)) & + (*(sptr - wpls2)) & + (*(sptr - wpls)) & + (*sptr) & + (*(sptr + wpls)) & + (*(sptr + wpls2)) & + (*(sptr + wpls3)) & + (*(sptr + wpls4)) & + (*(sptr + wpls5)) & + (*(sptr + wpls6)); + } + } +} + +static void +fdilate_3_74(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; +l_int32 wpls2, wpls3, wpls4; +l_int32 wpls5, wpls6, wpls7; + + wpls2 = 2 * wpls; + wpls3 = 3 * wpls; + wpls4 = 4 * wpls; + wpls5 = 5 * wpls; + wpls6 = 6 * wpls; + wpls7 = 7 * wpls; + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = (*(sptr + wpls7)) | + (*(sptr + wpls6)) | + (*(sptr + wpls5)) | + (*(sptr + wpls4)) | + (*(sptr + wpls3)) | + (*(sptr + wpls2)) | + (*(sptr + wpls)) | + (*sptr) | + (*(sptr - wpls)) | + (*(sptr - wpls2)) | + (*(sptr - wpls3)) | + (*(sptr - wpls4)) | + (*(sptr - wpls5)) | + (*(sptr - wpls6)); + } + } +} + +static void +ferode_3_74(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; +l_int32 wpls2, wpls3, wpls4; +l_int32 wpls5, wpls6, wpls7; + + wpls2 = 2 * wpls; + wpls3 = 3 * wpls; + wpls4 = 4 * wpls; + wpls5 = 5 * wpls; + wpls6 = 6 * wpls; + wpls7 = 7 * wpls; + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = (*(sptr - wpls7)) & + (*(sptr - wpls6)) & + (*(sptr - wpls5)) & + (*(sptr - wpls4)) & + (*(sptr - wpls3)) & + (*(sptr - wpls2)) & + (*(sptr - wpls)) & + (*sptr) & + (*(sptr + wpls)) & + (*(sptr + wpls2)) & + (*(sptr + wpls3)) & + (*(sptr + wpls4)) & + (*(sptr + wpls5)) & + (*(sptr + wpls6)); + } + } +} + +static void +fdilate_3_75(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; +l_int32 wpls2, wpls3, wpls4; +l_int32 wpls5, wpls6, wpls7; + + wpls2 = 2 * wpls; + wpls3 = 3 * wpls; + wpls4 = 4 * wpls; + wpls5 = 5 * wpls; + wpls6 = 6 * wpls; + wpls7 = 7 * wpls; + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = (*(sptr + wpls7)) | + (*(sptr + wpls6)) | + (*(sptr + wpls5)) | + (*(sptr + wpls4)) | + (*(sptr + wpls3)) | + (*(sptr + wpls2)) | + (*(sptr + wpls)) | + (*sptr) | + (*(sptr - wpls)) | + (*(sptr - wpls2)) | + (*(sptr - wpls3)) | + (*(sptr - wpls4)) | + (*(sptr - wpls5)) | + (*(sptr - wpls6)) | + (*(sptr - wpls7)); + } + } +} + +static void +ferode_3_75(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; +l_int32 wpls2, wpls3, wpls4; +l_int32 wpls5, wpls6, wpls7; + + wpls2 = 2 * wpls; + wpls3 = 3 * wpls; + wpls4 = 4 * wpls; + wpls5 = 5 * wpls; + wpls6 = 6 * wpls; + wpls7 = 7 * wpls; + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = (*(sptr - wpls7)) & + (*(sptr - wpls6)) & + (*(sptr - wpls5)) & + (*(sptr - wpls4)) & + (*(sptr - wpls3)) & + (*(sptr - wpls2)) & + (*(sptr - wpls)) & + (*sptr) & + (*(sptr + wpls)) & + (*(sptr + wpls2)) & + (*(sptr + wpls3)) & + (*(sptr + wpls4)) & + (*(sptr + wpls5)) & + (*(sptr + wpls6)) & + (*(sptr + wpls7)); + } + } +} + +static void +fdilate_3_76(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; +l_int32 wpls2, wpls3, wpls4; +l_int32 wpls5, wpls6, wpls7, wpls8; + + wpls2 = 2 * wpls; + wpls3 = 3 * wpls; + wpls4 = 4 * wpls; + wpls5 = 5 * wpls; + wpls6 = 6 * wpls; + wpls7 = 7 * wpls; + wpls8 = 8 * wpls; + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = (*(sptr + wpls8)) | + (*(sptr + wpls7)) | + (*(sptr + wpls6)) | + (*(sptr + wpls5)) | + (*(sptr + wpls4)) | + (*(sptr + wpls3)) | + (*(sptr + wpls2)) | + (*(sptr + wpls)) | + (*sptr) | + (*(sptr - wpls)) | + (*(sptr - wpls2)) | + (*(sptr - wpls3)) | + (*(sptr - wpls4)) | + (*(sptr - wpls5)) | + (*(sptr - wpls6)) | + (*(sptr - wpls7)); + } + } +} + +static void +ferode_3_76(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; +l_int32 wpls2, wpls3, wpls4; +l_int32 wpls5, wpls6, wpls7, wpls8; + + wpls2 = 2 * wpls; + wpls3 = 3 * wpls; + wpls4 = 4 * wpls; + wpls5 = 5 * wpls; + wpls6 = 6 * wpls; + wpls7 = 7 * wpls; + wpls8 = 8 * wpls; + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = (*(sptr - wpls8)) & + (*(sptr - wpls7)) & + (*(sptr - wpls6)) & + (*(sptr - wpls5)) & + (*(sptr - wpls4)) & + (*(sptr - wpls3)) & + (*(sptr - wpls2)) & + (*(sptr - wpls)) & + (*sptr) & + (*(sptr + wpls)) & + (*(sptr + wpls2)) & + (*(sptr + wpls3)) & + (*(sptr + wpls4)) & + (*(sptr + wpls5)) & + (*(sptr + wpls6)) & + (*(sptr + wpls7)); + } + } +} + +static void +fdilate_3_77(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; +l_int32 wpls2, wpls3, wpls4; +l_int32 wpls5, wpls6, wpls7, wpls8; + + wpls2 = 2 * wpls; + wpls3 = 3 * wpls; + wpls4 = 4 * wpls; + wpls5 = 5 * wpls; + wpls6 = 6 * wpls; + wpls7 = 7 * wpls; + wpls8 = 8 * wpls; + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = (*(sptr + wpls8)) | + (*(sptr + wpls7)) | + (*(sptr + wpls6)) | + (*(sptr + wpls5)) | + (*(sptr + wpls4)) | + (*(sptr + wpls3)) | + (*(sptr + wpls2)) | + (*(sptr + wpls)) | + (*sptr) | + (*(sptr - wpls)) | + (*(sptr - wpls2)) | + (*(sptr - wpls3)) | + (*(sptr - wpls4)) | + (*(sptr - wpls5)) | + (*(sptr - wpls6)) | + (*(sptr - wpls7)) | + (*(sptr - wpls8)); + } + } +} + +static void +ferode_3_77(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; +l_int32 wpls2, wpls3, wpls4; +l_int32 wpls5, wpls6, wpls7, wpls8; + + wpls2 = 2 * wpls; + wpls3 = 3 * wpls; + wpls4 = 4 * wpls; + wpls5 = 5 * wpls; + wpls6 = 6 * wpls; + wpls7 = 7 * wpls; + wpls8 = 8 * wpls; + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = (*(sptr - wpls8)) & + (*(sptr - wpls7)) & + (*(sptr - wpls6)) & + (*(sptr - wpls5)) & + (*(sptr - wpls4)) & + (*(sptr - wpls3)) & + (*(sptr - wpls2)) & + (*(sptr - wpls)) & + (*sptr) & + (*(sptr + wpls)) & + (*(sptr + wpls2)) & + (*(sptr + wpls3)) & + (*(sptr + wpls4)) & + (*(sptr + wpls5)) & + (*(sptr + wpls6)) & + (*(sptr + wpls7)) & + (*(sptr + wpls8)); + } + } +} + +static void +fdilate_3_78(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; +l_int32 wpls2, wpls3, wpls4; +l_int32 wpls5, wpls6, wpls7, wpls8; +l_int32 wpls9; + + wpls2 = 2 * wpls; + wpls3 = 3 * wpls; + wpls4 = 4 * wpls; + wpls5 = 5 * wpls; + wpls6 = 6 * wpls; + wpls7 = 7 * wpls; + wpls8 = 8 * wpls; + wpls9 = 9 * wpls; + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = (*(sptr + wpls9)) | + (*(sptr + wpls8)) | + (*(sptr + wpls7)) | + (*(sptr + wpls6)) | + (*(sptr + wpls5)) | + (*(sptr + wpls4)) | + (*(sptr + wpls3)) | + (*(sptr + wpls2)) | + (*(sptr + wpls)) | + (*sptr) | + (*(sptr - wpls)) | + (*(sptr - wpls2)) | + (*(sptr - wpls3)) | + (*(sptr - wpls4)) | + (*(sptr - wpls5)) | + (*(sptr - wpls6)) | + (*(sptr - wpls7)) | + (*(sptr - wpls8)); + } + } +} + +static void +ferode_3_78(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; +l_int32 wpls2, wpls3, wpls4; +l_int32 wpls5, wpls6, wpls7, wpls8; +l_int32 wpls9; + + wpls2 = 2 * wpls; + wpls3 = 3 * wpls; + wpls4 = 4 * wpls; + wpls5 = 5 * wpls; + wpls6 = 6 * wpls; + wpls7 = 7 * wpls; + wpls8 = 8 * wpls; + wpls9 = 9 * wpls; + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = (*(sptr - wpls9)) & + (*(sptr - wpls8)) & + (*(sptr - wpls7)) & + (*(sptr - wpls6)) & + (*(sptr - wpls5)) & + (*(sptr - wpls4)) & + (*(sptr - wpls3)) & + (*(sptr - wpls2)) & + (*(sptr - wpls)) & + (*sptr) & + (*(sptr + wpls)) & + (*(sptr + wpls2)) & + (*(sptr + wpls3)) & + (*(sptr + wpls4)) & + (*(sptr + wpls5)) & + (*(sptr + wpls6)) & + (*(sptr + wpls7)) & + (*(sptr + wpls8)); + } + } +} + +static void +fdilate_3_79(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; +l_int32 wpls2, wpls3, wpls4; +l_int32 wpls5, wpls6, wpls7, wpls8; +l_int32 wpls9; + + wpls2 = 2 * wpls; + wpls3 = 3 * wpls; + wpls4 = 4 * wpls; + wpls5 = 5 * wpls; + wpls6 = 6 * wpls; + wpls7 = 7 * wpls; + wpls8 = 8 * wpls; + wpls9 = 9 * wpls; + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = (*(sptr + wpls9)) | + (*(sptr + wpls8)) | + (*(sptr + wpls7)) | + (*(sptr + wpls6)) | + (*(sptr + wpls5)) | + (*(sptr + wpls4)) | + (*(sptr + wpls3)) | + (*(sptr + wpls2)) | + (*(sptr + wpls)) | + (*sptr) | + (*(sptr - wpls)) | + (*(sptr - wpls2)) | + (*(sptr - wpls3)) | + (*(sptr - wpls4)) | + (*(sptr - wpls5)) | + (*(sptr - wpls6)) | + (*(sptr - wpls7)) | + (*(sptr - wpls8)) | + (*(sptr - wpls9)); + } + } +} + +static void +ferode_3_79(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; +l_int32 wpls2, wpls3, wpls4; +l_int32 wpls5, wpls6, wpls7, wpls8; +l_int32 wpls9; + + wpls2 = 2 * wpls; + wpls3 = 3 * wpls; + wpls4 = 4 * wpls; + wpls5 = 5 * wpls; + wpls6 = 6 * wpls; + wpls7 = 7 * wpls; + wpls8 = 8 * wpls; + wpls9 = 9 * wpls; + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = (*(sptr - wpls9)) & + (*(sptr - wpls8)) & + (*(sptr - wpls7)) & + (*(sptr - wpls6)) & + (*(sptr - wpls5)) & + (*(sptr - wpls4)) & + (*(sptr - wpls3)) & + (*(sptr - wpls2)) & + (*(sptr - wpls)) & + (*sptr) & + (*(sptr + wpls)) & + (*(sptr + wpls2)) & + (*(sptr + wpls3)) & + (*(sptr + wpls4)) & + (*(sptr + wpls5)) & + (*(sptr + wpls6)) & + (*(sptr + wpls7)) & + (*(sptr + wpls8)) & + (*(sptr + wpls9)); + } + } +} + +static void +fdilate_3_80(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; +l_int32 wpls2, wpls3, wpls4; +l_int32 wpls5, wpls6, wpls7, wpls8; +l_int32 wpls9, wpls10; + + wpls2 = 2 * wpls; + wpls3 = 3 * wpls; + wpls4 = 4 * wpls; + wpls5 = 5 * wpls; + wpls6 = 6 * wpls; + wpls7 = 7 * wpls; + wpls8 = 8 * wpls; + wpls9 = 9 * wpls; + wpls10 = 10 * wpls; + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = (*(sptr + wpls10)) | + (*(sptr + wpls9)) | + (*(sptr + wpls8)) | + (*(sptr + wpls7)) | + (*(sptr + wpls6)) | + (*(sptr + wpls5)) | + (*(sptr + wpls4)) | + (*(sptr + wpls3)) | + (*(sptr + wpls2)) | + (*(sptr + wpls)) | + (*sptr) | + (*(sptr - wpls)) | + (*(sptr - wpls2)) | + (*(sptr - wpls3)) | + (*(sptr - wpls4)) | + (*(sptr - wpls5)) | + (*(sptr - wpls6)) | + (*(sptr - wpls7)) | + (*(sptr - wpls8)) | + (*(sptr - wpls9)); + } + } +} + +static void +ferode_3_80(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; +l_int32 wpls2, wpls3, wpls4; +l_int32 wpls5, wpls6, wpls7, wpls8; +l_int32 wpls9, wpls10; + + wpls2 = 2 * wpls; + wpls3 = 3 * wpls; + wpls4 = 4 * wpls; + wpls5 = 5 * wpls; + wpls6 = 6 * wpls; + wpls7 = 7 * wpls; + wpls8 = 8 * wpls; + wpls9 = 9 * wpls; + wpls10 = 10 * wpls; + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = (*(sptr - wpls10)) & + (*(sptr - wpls9)) & + (*(sptr - wpls8)) & + (*(sptr - wpls7)) & + (*(sptr - wpls6)) & + (*(sptr - wpls5)) & + (*(sptr - wpls4)) & + (*(sptr - wpls3)) & + (*(sptr - wpls2)) & + (*(sptr - wpls)) & + (*sptr) & + (*(sptr + wpls)) & + (*(sptr + wpls2)) & + (*(sptr + wpls3)) & + (*(sptr + wpls4)) & + (*(sptr + wpls5)) & + (*(sptr + wpls6)) & + (*(sptr + wpls7)) & + (*(sptr + wpls8)) & + (*(sptr + wpls9)); + } + } +} + +static void +fdilate_3_81(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; +l_int32 wpls2, wpls3, wpls4; +l_int32 wpls5, wpls6, wpls7, wpls8; +l_int32 wpls9, wpls10; + + wpls2 = 2 * wpls; + wpls3 = 3 * wpls; + wpls4 = 4 * wpls; + wpls5 = 5 * wpls; + wpls6 = 6 * wpls; + wpls7 = 7 * wpls; + wpls8 = 8 * wpls; + wpls9 = 9 * wpls; + wpls10 = 10 * wpls; + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = (*(sptr + wpls10)) | + (*(sptr + wpls9)) | + (*(sptr + wpls8)) | + (*(sptr + wpls7)) | + (*(sptr + wpls6)) | + (*(sptr + wpls5)) | + (*(sptr + wpls4)) | + (*(sptr + wpls3)) | + (*(sptr + wpls2)) | + (*(sptr + wpls)) | + (*sptr) | + (*(sptr - wpls)) | + (*(sptr - wpls2)) | + (*(sptr - wpls3)) | + (*(sptr - wpls4)) | + (*(sptr - wpls5)) | + (*(sptr - wpls6)) | + (*(sptr - wpls7)) | + (*(sptr - wpls8)) | + (*(sptr - wpls9)) | + (*(sptr - wpls10)); + } + } +} + +static void +ferode_3_81(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; +l_int32 wpls2, wpls3, wpls4; +l_int32 wpls5, wpls6, wpls7, wpls8; +l_int32 wpls9, wpls10; + + wpls2 = 2 * wpls; + wpls3 = 3 * wpls; + wpls4 = 4 * wpls; + wpls5 = 5 * wpls; + wpls6 = 6 * wpls; + wpls7 = 7 * wpls; + wpls8 = 8 * wpls; + wpls9 = 9 * wpls; + wpls10 = 10 * wpls; + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = (*(sptr - wpls10)) & + (*(sptr - wpls9)) & + (*(sptr - wpls8)) & + (*(sptr - wpls7)) & + (*(sptr - wpls6)) & + (*(sptr - wpls5)) & + (*(sptr - wpls4)) & + (*(sptr - wpls3)) & + (*(sptr - wpls2)) & + (*(sptr - wpls)) & + (*sptr) & + (*(sptr + wpls)) & + (*(sptr + wpls2)) & + (*(sptr + wpls3)) & + (*(sptr + wpls4)) & + (*(sptr + wpls5)) & + (*(sptr + wpls6)) & + (*(sptr + wpls7)) & + (*(sptr + wpls8)) & + (*(sptr + wpls9)) & + (*(sptr + wpls10)); + } + } +} + +static void +fdilate_3_82(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; +l_int32 wpls2, wpls3, wpls4; +l_int32 wpls5, wpls6, wpls7, wpls8; +l_int32 wpls9, wpls10, wpls11; + + wpls2 = 2 * wpls; + wpls3 = 3 * wpls; + wpls4 = 4 * wpls; + wpls5 = 5 * wpls; + wpls6 = 6 * wpls; + wpls7 = 7 * wpls; + wpls8 = 8 * wpls; + wpls9 = 9 * wpls; + wpls10 = 10 * wpls; + wpls11 = 11 * wpls; + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = (*(sptr + wpls11)) | + (*(sptr + wpls10)) | + (*(sptr + wpls9)) | + (*(sptr + wpls8)) | + (*(sptr + wpls7)) | + (*(sptr + wpls6)) | + (*(sptr + wpls5)) | + (*(sptr + wpls4)) | + (*(sptr + wpls3)) | + (*(sptr + wpls2)) | + (*(sptr + wpls)) | + (*sptr) | + (*(sptr - wpls)) | + (*(sptr - wpls2)) | + (*(sptr - wpls3)) | + (*(sptr - wpls4)) | + (*(sptr - wpls5)) | + (*(sptr - wpls6)) | + (*(sptr - wpls7)) | + (*(sptr - wpls8)) | + (*(sptr - wpls9)) | + (*(sptr - wpls10)); + } + } +} + +static void +ferode_3_82(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; +l_int32 wpls2, wpls3, wpls4; +l_int32 wpls5, wpls6, wpls7, wpls8; +l_int32 wpls9, wpls10, wpls11; + + wpls2 = 2 * wpls; + wpls3 = 3 * wpls; + wpls4 = 4 * wpls; + wpls5 = 5 * wpls; + wpls6 = 6 * wpls; + wpls7 = 7 * wpls; + wpls8 = 8 * wpls; + wpls9 = 9 * wpls; + wpls10 = 10 * wpls; + wpls11 = 11 * wpls; + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = (*(sptr - wpls11)) & + (*(sptr - wpls10)) & + (*(sptr - wpls9)) & + (*(sptr - wpls8)) & + (*(sptr - wpls7)) & + (*(sptr - wpls6)) & + (*(sptr - wpls5)) & + (*(sptr - wpls4)) & + (*(sptr - wpls3)) & + (*(sptr - wpls2)) & + (*(sptr - wpls)) & + (*sptr) & + (*(sptr + wpls)) & + (*(sptr + wpls2)) & + (*(sptr + wpls3)) & + (*(sptr + wpls4)) & + (*(sptr + wpls5)) & + (*(sptr + wpls6)) & + (*(sptr + wpls7)) & + (*(sptr + wpls8)) & + (*(sptr + wpls9)) & + (*(sptr + wpls10)); + } + } +} + +static void +fdilate_3_83(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; +l_int32 wpls2, wpls3, wpls4; +l_int32 wpls5, wpls6, wpls7, wpls8; +l_int32 wpls9, wpls10, wpls11; + + wpls2 = 2 * wpls; + wpls3 = 3 * wpls; + wpls4 = 4 * wpls; + wpls5 = 5 * wpls; + wpls6 = 6 * wpls; + wpls7 = 7 * wpls; + wpls8 = 8 * wpls; + wpls9 = 9 * wpls; + wpls10 = 10 * wpls; + wpls11 = 11 * wpls; + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = (*(sptr + wpls11)) | + (*(sptr + wpls10)) | + (*(sptr + wpls9)) | + (*(sptr + wpls8)) | + (*(sptr + wpls7)) | + (*(sptr + wpls6)) | + (*(sptr + wpls5)) | + (*(sptr + wpls4)) | + (*(sptr + wpls3)) | + (*(sptr + wpls2)) | + (*(sptr + wpls)) | + (*sptr) | + (*(sptr - wpls)) | + (*(sptr - wpls2)) | + (*(sptr - wpls3)) | + (*(sptr - wpls4)) | + (*(sptr - wpls5)) | + (*(sptr - wpls6)) | + (*(sptr - wpls7)) | + (*(sptr - wpls8)) | + (*(sptr - wpls9)) | + (*(sptr - wpls10)) | + (*(sptr - wpls11)); + } + } +} + +static void +ferode_3_83(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; +l_int32 wpls2, wpls3, wpls4; +l_int32 wpls5, wpls6, wpls7, wpls8; +l_int32 wpls9, wpls10, wpls11; + + wpls2 = 2 * wpls; + wpls3 = 3 * wpls; + wpls4 = 4 * wpls; + wpls5 = 5 * wpls; + wpls6 = 6 * wpls; + wpls7 = 7 * wpls; + wpls8 = 8 * wpls; + wpls9 = 9 * wpls; + wpls10 = 10 * wpls; + wpls11 = 11 * wpls; + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = (*(sptr - wpls11)) & + (*(sptr - wpls10)) & + (*(sptr - wpls9)) & + (*(sptr - wpls8)) & + (*(sptr - wpls7)) & + (*(sptr - wpls6)) & + (*(sptr - wpls5)) & + (*(sptr - wpls4)) & + (*(sptr - wpls3)) & + (*(sptr - wpls2)) & + (*(sptr - wpls)) & + (*sptr) & + (*(sptr + wpls)) & + (*(sptr + wpls2)) & + (*(sptr + wpls3)) & + (*(sptr + wpls4)) & + (*(sptr + wpls5)) & + (*(sptr + wpls6)) & + (*(sptr + wpls7)) & + (*(sptr + wpls8)) & + (*(sptr + wpls9)) & + (*(sptr + wpls10)) & + (*(sptr + wpls11)); + } + } +} + +static void +fdilate_3_84(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; +l_int32 wpls2, wpls3, wpls4; +l_int32 wpls5, wpls6, wpls7, wpls8; +l_int32 wpls9, wpls10, wpls11, wpls12; + + wpls2 = 2 * wpls; + wpls3 = 3 * wpls; + wpls4 = 4 * wpls; + wpls5 = 5 * wpls; + wpls6 = 6 * wpls; + wpls7 = 7 * wpls; + wpls8 = 8 * wpls; + wpls9 = 9 * wpls; + wpls10 = 10 * wpls; + wpls11 = 11 * wpls; + wpls12 = 12 * wpls; + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = (*(sptr + wpls12)) | + (*(sptr + wpls11)) | + (*(sptr + wpls10)) | + (*(sptr + wpls9)) | + (*(sptr + wpls8)) | + (*(sptr + wpls7)) | + (*(sptr + wpls6)) | + (*(sptr + wpls5)) | + (*(sptr + wpls4)) | + (*(sptr + wpls3)) | + (*(sptr + wpls2)) | + (*(sptr + wpls)) | + (*sptr) | + (*(sptr - wpls)) | + (*(sptr - wpls2)) | + (*(sptr - wpls3)) | + (*(sptr - wpls4)) | + (*(sptr - wpls5)) | + (*(sptr - wpls6)) | + (*(sptr - wpls7)) | + (*(sptr - wpls8)) | + (*(sptr - wpls9)) | + (*(sptr - wpls10)) | + (*(sptr - wpls11)); + } + } +} + +static void +ferode_3_84(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; +l_int32 wpls2, wpls3, wpls4; +l_int32 wpls5, wpls6, wpls7, wpls8; +l_int32 wpls9, wpls10, wpls11, wpls12; + + wpls2 = 2 * wpls; + wpls3 = 3 * wpls; + wpls4 = 4 * wpls; + wpls5 = 5 * wpls; + wpls6 = 6 * wpls; + wpls7 = 7 * wpls; + wpls8 = 8 * wpls; + wpls9 = 9 * wpls; + wpls10 = 10 * wpls; + wpls11 = 11 * wpls; + wpls12 = 12 * wpls; + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = (*(sptr - wpls12)) & + (*(sptr - wpls11)) & + (*(sptr - wpls10)) & + (*(sptr - wpls9)) & + (*(sptr - wpls8)) & + (*(sptr - wpls7)) & + (*(sptr - wpls6)) & + (*(sptr - wpls5)) & + (*(sptr - wpls4)) & + (*(sptr - wpls3)) & + (*(sptr - wpls2)) & + (*(sptr - wpls)) & + (*sptr) & + (*(sptr + wpls)) & + (*(sptr + wpls2)) & + (*(sptr + wpls3)) & + (*(sptr + wpls4)) & + (*(sptr + wpls5)) & + (*(sptr + wpls6)) & + (*(sptr + wpls7)) & + (*(sptr + wpls8)) & + (*(sptr + wpls9)) & + (*(sptr + wpls10)) & + (*(sptr + wpls11)); + } + } +} + +static void +fdilate_3_85(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; +l_int32 wpls2, wpls3, wpls4; +l_int32 wpls5, wpls6, wpls7, wpls8; +l_int32 wpls9, wpls10, wpls11, wpls12; + + wpls2 = 2 * wpls; + wpls3 = 3 * wpls; + wpls4 = 4 * wpls; + wpls5 = 5 * wpls; + wpls6 = 6 * wpls; + wpls7 = 7 * wpls; + wpls8 = 8 * wpls; + wpls9 = 9 * wpls; + wpls10 = 10 * wpls; + wpls11 = 11 * wpls; + wpls12 = 12 * wpls; + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = (*(sptr + wpls12)) | + (*(sptr + wpls11)) | + (*(sptr + wpls10)) | + (*(sptr + wpls9)) | + (*(sptr + wpls8)) | + (*(sptr + wpls7)) | + (*(sptr + wpls6)) | + (*(sptr + wpls5)) | + (*(sptr + wpls4)) | + (*(sptr + wpls3)) | + (*(sptr + wpls2)) | + (*(sptr + wpls)) | + (*sptr) | + (*(sptr - wpls)) | + (*(sptr - wpls2)) | + (*(sptr - wpls3)) | + (*(sptr - wpls4)) | + (*(sptr - wpls5)) | + (*(sptr - wpls6)) | + (*(sptr - wpls7)) | + (*(sptr - wpls8)) | + (*(sptr - wpls9)) | + (*(sptr - wpls10)) | + (*(sptr - wpls11)) | + (*(sptr - wpls12)); + } + } +} + +static void +ferode_3_85(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; +l_int32 wpls2, wpls3, wpls4; +l_int32 wpls5, wpls6, wpls7, wpls8; +l_int32 wpls9, wpls10, wpls11, wpls12; + + wpls2 = 2 * wpls; + wpls3 = 3 * wpls; + wpls4 = 4 * wpls; + wpls5 = 5 * wpls; + wpls6 = 6 * wpls; + wpls7 = 7 * wpls; + wpls8 = 8 * wpls; + wpls9 = 9 * wpls; + wpls10 = 10 * wpls; + wpls11 = 11 * wpls; + wpls12 = 12 * wpls; + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = (*(sptr - wpls12)) & + (*(sptr - wpls11)) & + (*(sptr - wpls10)) & + (*(sptr - wpls9)) & + (*(sptr - wpls8)) & + (*(sptr - wpls7)) & + (*(sptr - wpls6)) & + (*(sptr - wpls5)) & + (*(sptr - wpls4)) & + (*(sptr - wpls3)) & + (*(sptr - wpls2)) & + (*(sptr - wpls)) & + (*sptr) & + (*(sptr + wpls)) & + (*(sptr + wpls2)) & + (*(sptr + wpls3)) & + (*(sptr + wpls4)) & + (*(sptr + wpls5)) & + (*(sptr + wpls6)) & + (*(sptr + wpls7)) & + (*(sptr + wpls8)) & + (*(sptr + wpls9)) & + (*(sptr + wpls10)) & + (*(sptr + wpls11)) & + (*(sptr + wpls12)); + } + } +} + +static void +fdilate_3_86(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; +l_int32 wpls2, wpls3, wpls4; +l_int32 wpls5, wpls6, wpls7, wpls8; +l_int32 wpls9, wpls10, wpls11, wpls12; +l_int32 wpls13; + + wpls2 = 2 * wpls; + wpls3 = 3 * wpls; + wpls4 = 4 * wpls; + wpls5 = 5 * wpls; + wpls6 = 6 * wpls; + wpls7 = 7 * wpls; + wpls8 = 8 * wpls; + wpls9 = 9 * wpls; + wpls10 = 10 * wpls; + wpls11 = 11 * wpls; + wpls12 = 12 * wpls; + wpls13 = 13 * wpls; + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = (*(sptr + wpls13)) | + (*(sptr + wpls12)) | + (*(sptr + wpls11)) | + (*(sptr + wpls10)) | + (*(sptr + wpls9)) | + (*(sptr + wpls8)) | + (*(sptr + wpls7)) | + (*(sptr + wpls6)) | + (*(sptr + wpls5)) | + (*(sptr + wpls4)) | + (*(sptr + wpls3)) | + (*(sptr + wpls2)) | + (*(sptr + wpls)) | + (*sptr) | + (*(sptr - wpls)) | + (*(sptr - wpls2)) | + (*(sptr - wpls3)) | + (*(sptr - wpls4)) | + (*(sptr - wpls5)) | + (*(sptr - wpls6)) | + (*(sptr - wpls7)) | + (*(sptr - wpls8)) | + (*(sptr - wpls9)) | + (*(sptr - wpls10)) | + (*(sptr - wpls11)) | + (*(sptr - wpls12)); + } + } +} + +static void +ferode_3_86(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; +l_int32 wpls2, wpls3, wpls4; +l_int32 wpls5, wpls6, wpls7, wpls8; +l_int32 wpls9, wpls10, wpls11, wpls12; +l_int32 wpls13; + + wpls2 = 2 * wpls; + wpls3 = 3 * wpls; + wpls4 = 4 * wpls; + wpls5 = 5 * wpls; + wpls6 = 6 * wpls; + wpls7 = 7 * wpls; + wpls8 = 8 * wpls; + wpls9 = 9 * wpls; + wpls10 = 10 * wpls; + wpls11 = 11 * wpls; + wpls12 = 12 * wpls; + wpls13 = 13 * wpls; + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = (*(sptr - wpls13)) & + (*(sptr - wpls12)) & + (*(sptr - wpls11)) & + (*(sptr - wpls10)) & + (*(sptr - wpls9)) & + (*(sptr - wpls8)) & + (*(sptr - wpls7)) & + (*(sptr - wpls6)) & + (*(sptr - wpls5)) & + (*(sptr - wpls4)) & + (*(sptr - wpls3)) & + (*(sptr - wpls2)) & + (*(sptr - wpls)) & + (*sptr) & + (*(sptr + wpls)) & + (*(sptr + wpls2)) & + (*(sptr + wpls3)) & + (*(sptr + wpls4)) & + (*(sptr + wpls5)) & + (*(sptr + wpls6)) & + (*(sptr + wpls7)) & + (*(sptr + wpls8)) & + (*(sptr + wpls9)) & + (*(sptr + wpls10)) & + (*(sptr + wpls11)) & + (*(sptr + wpls12)); + } + } +} + +static void +fdilate_3_87(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; +l_int32 wpls2, wpls3, wpls4; +l_int32 wpls5, wpls6, wpls7, wpls8; +l_int32 wpls9, wpls10, wpls11, wpls12; +l_int32 wpls13; + + wpls2 = 2 * wpls; + wpls3 = 3 * wpls; + wpls4 = 4 * wpls; + wpls5 = 5 * wpls; + wpls6 = 6 * wpls; + wpls7 = 7 * wpls; + wpls8 = 8 * wpls; + wpls9 = 9 * wpls; + wpls10 = 10 * wpls; + wpls11 = 11 * wpls; + wpls12 = 12 * wpls; + wpls13 = 13 * wpls; + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = (*(sptr + wpls13)) | + (*(sptr + wpls12)) | + (*(sptr + wpls11)) | + (*(sptr + wpls10)) | + (*(sptr + wpls9)) | + (*(sptr + wpls8)) | + (*(sptr + wpls7)) | + (*(sptr + wpls6)) | + (*(sptr + wpls5)) | + (*(sptr + wpls4)) | + (*(sptr + wpls3)) | + (*(sptr + wpls2)) | + (*(sptr + wpls)) | + (*sptr) | + (*(sptr - wpls)) | + (*(sptr - wpls2)) | + (*(sptr - wpls3)) | + (*(sptr - wpls4)) | + (*(sptr - wpls5)) | + (*(sptr - wpls6)) | + (*(sptr - wpls7)) | + (*(sptr - wpls8)) | + (*(sptr - wpls9)) | + (*(sptr - wpls10)) | + (*(sptr - wpls11)) | + (*(sptr - wpls12)) | + (*(sptr - wpls13)); + } + } +} + +static void +ferode_3_87(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; +l_int32 wpls2, wpls3, wpls4; +l_int32 wpls5, wpls6, wpls7, wpls8; +l_int32 wpls9, wpls10, wpls11, wpls12; +l_int32 wpls13; + + wpls2 = 2 * wpls; + wpls3 = 3 * wpls; + wpls4 = 4 * wpls; + wpls5 = 5 * wpls; + wpls6 = 6 * wpls; + wpls7 = 7 * wpls; + wpls8 = 8 * wpls; + wpls9 = 9 * wpls; + wpls10 = 10 * wpls; + wpls11 = 11 * wpls; + wpls12 = 12 * wpls; + wpls13 = 13 * wpls; + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = (*(sptr - wpls13)) & + (*(sptr - wpls12)) & + (*(sptr - wpls11)) & + (*(sptr - wpls10)) & + (*(sptr - wpls9)) & + (*(sptr - wpls8)) & + (*(sptr - wpls7)) & + (*(sptr - wpls6)) & + (*(sptr - wpls5)) & + (*(sptr - wpls4)) & + (*(sptr - wpls3)) & + (*(sptr - wpls2)) & + (*(sptr - wpls)) & + (*sptr) & + (*(sptr + wpls)) & + (*(sptr + wpls2)) & + (*(sptr + wpls3)) & + (*(sptr + wpls4)) & + (*(sptr + wpls5)) & + (*(sptr + wpls6)) & + (*(sptr + wpls7)) & + (*(sptr + wpls8)) & + (*(sptr + wpls9)) & + (*(sptr + wpls10)) & + (*(sptr + wpls11)) & + (*(sptr + wpls12)) & + (*(sptr + wpls13)); + } + } +} + +static void +fdilate_3_88(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; +l_int32 wpls2, wpls3, wpls4; +l_int32 wpls5, wpls6, wpls7, wpls8; +l_int32 wpls9, wpls10, wpls11, wpls12; +l_int32 wpls13, wpls14; + + wpls2 = 2 * wpls; + wpls3 = 3 * wpls; + wpls4 = 4 * wpls; + wpls5 = 5 * wpls; + wpls6 = 6 * wpls; + wpls7 = 7 * wpls; + wpls8 = 8 * wpls; + wpls9 = 9 * wpls; + wpls10 = 10 * wpls; + wpls11 = 11 * wpls; + wpls12 = 12 * wpls; + wpls13 = 13 * wpls; + wpls14 = 14 * wpls; + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = (*(sptr + wpls14)) | + (*(sptr + wpls13)) | + (*(sptr + wpls12)) | + (*(sptr + wpls11)) | + (*(sptr + wpls10)) | + (*(sptr + wpls9)) | + (*(sptr + wpls8)) | + (*(sptr + wpls7)) | + (*(sptr + wpls6)) | + (*(sptr + wpls5)) | + (*(sptr + wpls4)) | + (*(sptr + wpls3)) | + (*(sptr + wpls2)) | + (*(sptr + wpls)) | + (*sptr) | + (*(sptr - wpls)) | + (*(sptr - wpls2)) | + (*(sptr - wpls3)) | + (*(sptr - wpls4)) | + (*(sptr - wpls5)) | + (*(sptr - wpls6)) | + (*(sptr - wpls7)) | + (*(sptr - wpls8)) | + (*(sptr - wpls9)) | + (*(sptr - wpls10)) | + (*(sptr - wpls11)) | + (*(sptr - wpls12)) | + (*(sptr - wpls13)); + } + } +} + +static void +ferode_3_88(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; +l_int32 wpls2, wpls3, wpls4; +l_int32 wpls5, wpls6, wpls7, wpls8; +l_int32 wpls9, wpls10, wpls11, wpls12; +l_int32 wpls13, wpls14; + + wpls2 = 2 * wpls; + wpls3 = 3 * wpls; + wpls4 = 4 * wpls; + wpls5 = 5 * wpls; + wpls6 = 6 * wpls; + wpls7 = 7 * wpls; + wpls8 = 8 * wpls; + wpls9 = 9 * wpls; + wpls10 = 10 * wpls; + wpls11 = 11 * wpls; + wpls12 = 12 * wpls; + wpls13 = 13 * wpls; + wpls14 = 14 * wpls; + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = (*(sptr - wpls14)) & + (*(sptr - wpls13)) & + (*(sptr - wpls12)) & + (*(sptr - wpls11)) & + (*(sptr - wpls10)) & + (*(sptr - wpls9)) & + (*(sptr - wpls8)) & + (*(sptr - wpls7)) & + (*(sptr - wpls6)) & + (*(sptr - wpls5)) & + (*(sptr - wpls4)) & + (*(sptr - wpls3)) & + (*(sptr - wpls2)) & + (*(sptr - wpls)) & + (*sptr) & + (*(sptr + wpls)) & + (*(sptr + wpls2)) & + (*(sptr + wpls3)) & + (*(sptr + wpls4)) & + (*(sptr + wpls5)) & + (*(sptr + wpls6)) & + (*(sptr + wpls7)) & + (*(sptr + wpls8)) & + (*(sptr + wpls9)) & + (*(sptr + wpls10)) & + (*(sptr + wpls11)) & + (*(sptr + wpls12)) & + (*(sptr + wpls13)); + } + } +} + +static void +fdilate_3_89(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; +l_int32 wpls2, wpls3, wpls4; +l_int32 wpls5, wpls6, wpls7, wpls8; +l_int32 wpls9, wpls10, wpls11, wpls12; +l_int32 wpls13, wpls14; + + wpls2 = 2 * wpls; + wpls3 = 3 * wpls; + wpls4 = 4 * wpls; + wpls5 = 5 * wpls; + wpls6 = 6 * wpls; + wpls7 = 7 * wpls; + wpls8 = 8 * wpls; + wpls9 = 9 * wpls; + wpls10 = 10 * wpls; + wpls11 = 11 * wpls; + wpls12 = 12 * wpls; + wpls13 = 13 * wpls; + wpls14 = 14 * wpls; + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = (*(sptr + wpls14)) | + (*(sptr + wpls13)) | + (*(sptr + wpls12)) | + (*(sptr + wpls11)) | + (*(sptr + wpls10)) | + (*(sptr + wpls9)) | + (*(sptr + wpls8)) | + (*(sptr + wpls7)) | + (*(sptr + wpls6)) | + (*(sptr + wpls5)) | + (*(sptr + wpls4)) | + (*(sptr + wpls3)) | + (*(sptr + wpls2)) | + (*(sptr + wpls)) | + (*sptr) | + (*(sptr - wpls)) | + (*(sptr - wpls2)) | + (*(sptr - wpls3)) | + (*(sptr - wpls4)) | + (*(sptr - wpls5)) | + (*(sptr - wpls6)) | + (*(sptr - wpls7)) | + (*(sptr - wpls8)) | + (*(sptr - wpls9)) | + (*(sptr - wpls10)) | + (*(sptr - wpls11)) | + (*(sptr - wpls12)) | + (*(sptr - wpls13)) | + (*(sptr - wpls14)); + } + } +} + +static void +ferode_3_89(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; +l_int32 wpls2, wpls3, wpls4; +l_int32 wpls5, wpls6, wpls7, wpls8; +l_int32 wpls9, wpls10, wpls11, wpls12; +l_int32 wpls13, wpls14; + + wpls2 = 2 * wpls; + wpls3 = 3 * wpls; + wpls4 = 4 * wpls; + wpls5 = 5 * wpls; + wpls6 = 6 * wpls; + wpls7 = 7 * wpls; + wpls8 = 8 * wpls; + wpls9 = 9 * wpls; + wpls10 = 10 * wpls; + wpls11 = 11 * wpls; + wpls12 = 12 * wpls; + wpls13 = 13 * wpls; + wpls14 = 14 * wpls; + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = (*(sptr - wpls14)) & + (*(sptr - wpls13)) & + (*(sptr - wpls12)) & + (*(sptr - wpls11)) & + (*(sptr - wpls10)) & + (*(sptr - wpls9)) & + (*(sptr - wpls8)) & + (*(sptr - wpls7)) & + (*(sptr - wpls6)) & + (*(sptr - wpls5)) & + (*(sptr - wpls4)) & + (*(sptr - wpls3)) & + (*(sptr - wpls2)) & + (*(sptr - wpls)) & + (*sptr) & + (*(sptr + wpls)) & + (*(sptr + wpls2)) & + (*(sptr + wpls3)) & + (*(sptr + wpls4)) & + (*(sptr + wpls5)) & + (*(sptr + wpls6)) & + (*(sptr + wpls7)) & + (*(sptr + wpls8)) & + (*(sptr + wpls9)) & + (*(sptr + wpls10)) & + (*(sptr + wpls11)) & + (*(sptr + wpls12)) & + (*(sptr + wpls13)) & + (*(sptr + wpls14)); + } + } +} + +static void +fdilate_3_90(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; +l_int32 wpls2, wpls3, wpls4; +l_int32 wpls5, wpls6, wpls7, wpls8; +l_int32 wpls9, wpls10, wpls11, wpls12; +l_int32 wpls13, wpls14, wpls15; + + wpls2 = 2 * wpls; + wpls3 = 3 * wpls; + wpls4 = 4 * wpls; + wpls5 = 5 * wpls; + wpls6 = 6 * wpls; + wpls7 = 7 * wpls; + wpls8 = 8 * wpls; + wpls9 = 9 * wpls; + wpls10 = 10 * wpls; + wpls11 = 11 * wpls; + wpls12 = 12 * wpls; + wpls13 = 13 * wpls; + wpls14 = 14 * wpls; + wpls15 = 15 * wpls; + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = (*(sptr + wpls15)) | + (*(sptr + wpls14)) | + (*(sptr + wpls13)) | + (*(sptr + wpls12)) | + (*(sptr + wpls11)) | + (*(sptr + wpls10)) | + (*(sptr + wpls9)) | + (*(sptr + wpls8)) | + (*(sptr + wpls7)) | + (*(sptr + wpls6)) | + (*(sptr + wpls5)) | + (*(sptr + wpls4)) | + (*(sptr + wpls3)) | + (*(sptr + wpls2)) | + (*(sptr + wpls)) | + (*sptr) | + (*(sptr - wpls)) | + (*(sptr - wpls2)) | + (*(sptr - wpls3)) | + (*(sptr - wpls4)) | + (*(sptr - wpls5)) | + (*(sptr - wpls6)) | + (*(sptr - wpls7)) | + (*(sptr - wpls8)) | + (*(sptr - wpls9)) | + (*(sptr - wpls10)) | + (*(sptr - wpls11)) | + (*(sptr - wpls12)) | + (*(sptr - wpls13)) | + (*(sptr - wpls14)); + } + } +} + +static void +ferode_3_90(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; +l_int32 wpls2, wpls3, wpls4; +l_int32 wpls5, wpls6, wpls7, wpls8; +l_int32 wpls9, wpls10, wpls11, wpls12; +l_int32 wpls13, wpls14, wpls15; + + wpls2 = 2 * wpls; + wpls3 = 3 * wpls; + wpls4 = 4 * wpls; + wpls5 = 5 * wpls; + wpls6 = 6 * wpls; + wpls7 = 7 * wpls; + wpls8 = 8 * wpls; + wpls9 = 9 * wpls; + wpls10 = 10 * wpls; + wpls11 = 11 * wpls; + wpls12 = 12 * wpls; + wpls13 = 13 * wpls; + wpls14 = 14 * wpls; + wpls15 = 15 * wpls; + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = (*(sptr - wpls15)) & + (*(sptr - wpls14)) & + (*(sptr - wpls13)) & + (*(sptr - wpls12)) & + (*(sptr - wpls11)) & + (*(sptr - wpls10)) & + (*(sptr - wpls9)) & + (*(sptr - wpls8)) & + (*(sptr - wpls7)) & + (*(sptr - wpls6)) & + (*(sptr - wpls5)) & + (*(sptr - wpls4)) & + (*(sptr - wpls3)) & + (*(sptr - wpls2)) & + (*(sptr - wpls)) & + (*sptr) & + (*(sptr + wpls)) & + (*(sptr + wpls2)) & + (*(sptr + wpls3)) & + (*(sptr + wpls4)) & + (*(sptr + wpls5)) & + (*(sptr + wpls6)) & + (*(sptr + wpls7)) & + (*(sptr + wpls8)) & + (*(sptr + wpls9)) & + (*(sptr + wpls10)) & + (*(sptr + wpls11)) & + (*(sptr + wpls12)) & + (*(sptr + wpls13)) & + (*(sptr + wpls14)); + } + } +} + +static void +fdilate_3_91(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; +l_int32 wpls2, wpls3, wpls4; +l_int32 wpls5, wpls6, wpls7, wpls8; +l_int32 wpls9, wpls10, wpls11, wpls12; +l_int32 wpls13, wpls14, wpls15; + + wpls2 = 2 * wpls; + wpls3 = 3 * wpls; + wpls4 = 4 * wpls; + wpls5 = 5 * wpls; + wpls6 = 6 * wpls; + wpls7 = 7 * wpls; + wpls8 = 8 * wpls; + wpls9 = 9 * wpls; + wpls10 = 10 * wpls; + wpls11 = 11 * wpls; + wpls12 = 12 * wpls; + wpls13 = 13 * wpls; + wpls14 = 14 * wpls; + wpls15 = 15 * wpls; + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = (*(sptr + wpls15)) | + (*(sptr + wpls14)) | + (*(sptr + wpls13)) | + (*(sptr + wpls12)) | + (*(sptr + wpls11)) | + (*(sptr + wpls10)) | + (*(sptr + wpls9)) | + (*(sptr + wpls8)) | + (*(sptr + wpls7)) | + (*(sptr + wpls6)) | + (*(sptr + wpls5)) | + (*(sptr + wpls4)) | + (*(sptr + wpls3)) | + (*(sptr + wpls2)) | + (*(sptr + wpls)) | + (*sptr) | + (*(sptr - wpls)) | + (*(sptr - wpls2)) | + (*(sptr - wpls3)) | + (*(sptr - wpls4)) | + (*(sptr - wpls5)) | + (*(sptr - wpls6)) | + (*(sptr - wpls7)) | + (*(sptr - wpls8)) | + (*(sptr - wpls9)) | + (*(sptr - wpls10)) | + (*(sptr - wpls11)) | + (*(sptr - wpls12)) | + (*(sptr - wpls13)) | + (*(sptr - wpls14)) | + (*(sptr - wpls15)); + } + } +} + +static void +ferode_3_91(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; +l_int32 wpls2, wpls3, wpls4; +l_int32 wpls5, wpls6, wpls7, wpls8; +l_int32 wpls9, wpls10, wpls11, wpls12; +l_int32 wpls13, wpls14, wpls15; + + wpls2 = 2 * wpls; + wpls3 = 3 * wpls; + wpls4 = 4 * wpls; + wpls5 = 5 * wpls; + wpls6 = 6 * wpls; + wpls7 = 7 * wpls; + wpls8 = 8 * wpls; + wpls9 = 9 * wpls; + wpls10 = 10 * wpls; + wpls11 = 11 * wpls; + wpls12 = 12 * wpls; + wpls13 = 13 * wpls; + wpls14 = 14 * wpls; + wpls15 = 15 * wpls; + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = (*(sptr - wpls15)) & + (*(sptr - wpls14)) & + (*(sptr - wpls13)) & + (*(sptr - wpls12)) & + (*(sptr - wpls11)) & + (*(sptr - wpls10)) & + (*(sptr - wpls9)) & + (*(sptr - wpls8)) & + (*(sptr - wpls7)) & + (*(sptr - wpls6)) & + (*(sptr - wpls5)) & + (*(sptr - wpls4)) & + (*(sptr - wpls3)) & + (*(sptr - wpls2)) & + (*(sptr - wpls)) & + (*sptr) & + (*(sptr + wpls)) & + (*(sptr + wpls2)) & + (*(sptr + wpls3)) & + (*(sptr + wpls4)) & + (*(sptr + wpls5)) & + (*(sptr + wpls6)) & + (*(sptr + wpls7)) & + (*(sptr + wpls8)) & + (*(sptr + wpls9)) & + (*(sptr + wpls10)) & + (*(sptr + wpls11)) & + (*(sptr + wpls12)) & + (*(sptr + wpls13)) & + (*(sptr + wpls14)) & + (*(sptr + wpls15)); + } + } +} + +static void +fdilate_3_92(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; +l_int32 wpls2, wpls3, wpls4; +l_int32 wpls5, wpls6, wpls7, wpls8; +l_int32 wpls9, wpls10, wpls11, wpls12; +l_int32 wpls13, wpls14, wpls15, wpls16; + + wpls2 = 2 * wpls; + wpls3 = 3 * wpls; + wpls4 = 4 * wpls; + wpls5 = 5 * wpls; + wpls6 = 6 * wpls; + wpls7 = 7 * wpls; + wpls8 = 8 * wpls; + wpls9 = 9 * wpls; + wpls10 = 10 * wpls; + wpls11 = 11 * wpls; + wpls12 = 12 * wpls; + wpls13 = 13 * wpls; + wpls14 = 14 * wpls; + wpls15 = 15 * wpls; + wpls16 = 16 * wpls; + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = (*(sptr + wpls16)) | + (*(sptr + wpls15)) | + (*(sptr + wpls14)) | + (*(sptr + wpls13)) | + (*(sptr + wpls12)) | + (*(sptr + wpls11)) | + (*(sptr + wpls10)) | + (*(sptr + wpls9)) | + (*(sptr + wpls8)) | + (*(sptr + wpls7)) | + (*(sptr + wpls6)) | + (*(sptr + wpls5)) | + (*(sptr + wpls4)) | + (*(sptr + wpls3)) | + (*(sptr + wpls2)) | + (*(sptr + wpls)) | + (*sptr) | + (*(sptr - wpls)) | + (*(sptr - wpls2)) | + (*(sptr - wpls3)) | + (*(sptr - wpls4)) | + (*(sptr - wpls5)) | + (*(sptr - wpls6)) | + (*(sptr - wpls7)) | + (*(sptr - wpls8)) | + (*(sptr - wpls9)) | + (*(sptr - wpls10)) | + (*(sptr - wpls11)) | + (*(sptr - wpls12)) | + (*(sptr - wpls13)) | + (*(sptr - wpls14)) | + (*(sptr - wpls15)); + } + } +} + +static void +ferode_3_92(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; +l_int32 wpls2, wpls3, wpls4; +l_int32 wpls5, wpls6, wpls7, wpls8; +l_int32 wpls9, wpls10, wpls11, wpls12; +l_int32 wpls13, wpls14, wpls15, wpls16; + + wpls2 = 2 * wpls; + wpls3 = 3 * wpls; + wpls4 = 4 * wpls; + wpls5 = 5 * wpls; + wpls6 = 6 * wpls; + wpls7 = 7 * wpls; + wpls8 = 8 * wpls; + wpls9 = 9 * wpls; + wpls10 = 10 * wpls; + wpls11 = 11 * wpls; + wpls12 = 12 * wpls; + wpls13 = 13 * wpls; + wpls14 = 14 * wpls; + wpls15 = 15 * wpls; + wpls16 = 16 * wpls; + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = (*(sptr - wpls16)) & + (*(sptr - wpls15)) & + (*(sptr - wpls14)) & + (*(sptr - wpls13)) & + (*(sptr - wpls12)) & + (*(sptr - wpls11)) & + (*(sptr - wpls10)) & + (*(sptr - wpls9)) & + (*(sptr - wpls8)) & + (*(sptr - wpls7)) & + (*(sptr - wpls6)) & + (*(sptr - wpls5)) & + (*(sptr - wpls4)) & + (*(sptr - wpls3)) & + (*(sptr - wpls2)) & + (*(sptr - wpls)) & + (*sptr) & + (*(sptr + wpls)) & + (*(sptr + wpls2)) & + (*(sptr + wpls3)) & + (*(sptr + wpls4)) & + (*(sptr + wpls5)) & + (*(sptr + wpls6)) & + (*(sptr + wpls7)) & + (*(sptr + wpls8)) & + (*(sptr + wpls9)) & + (*(sptr + wpls10)) & + (*(sptr + wpls11)) & + (*(sptr + wpls12)) & + (*(sptr + wpls13)) & + (*(sptr + wpls14)) & + (*(sptr + wpls15)); + } + } +} + +static void +fdilate_3_93(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; +l_int32 wpls2, wpls3, wpls4; +l_int32 wpls5, wpls6, wpls7, wpls8; +l_int32 wpls9, wpls10, wpls11, wpls12; +l_int32 wpls13, wpls14, wpls15, wpls16; + + wpls2 = 2 * wpls; + wpls3 = 3 * wpls; + wpls4 = 4 * wpls; + wpls5 = 5 * wpls; + wpls6 = 6 * wpls; + wpls7 = 7 * wpls; + wpls8 = 8 * wpls; + wpls9 = 9 * wpls; + wpls10 = 10 * wpls; + wpls11 = 11 * wpls; + wpls12 = 12 * wpls; + wpls13 = 13 * wpls; + wpls14 = 14 * wpls; + wpls15 = 15 * wpls; + wpls16 = 16 * wpls; + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = (*(sptr + wpls16)) | + (*(sptr + wpls15)) | + (*(sptr + wpls14)) | + (*(sptr + wpls13)) | + (*(sptr + wpls12)) | + (*(sptr + wpls11)) | + (*(sptr + wpls10)) | + (*(sptr + wpls9)) | + (*(sptr + wpls8)) | + (*(sptr + wpls7)) | + (*(sptr + wpls6)) | + (*(sptr + wpls5)) | + (*(sptr + wpls4)) | + (*(sptr + wpls3)) | + (*(sptr + wpls2)) | + (*(sptr + wpls)) | + (*sptr) | + (*(sptr - wpls)) | + (*(sptr - wpls2)) | + (*(sptr - wpls3)) | + (*(sptr - wpls4)) | + (*(sptr - wpls5)) | + (*(sptr - wpls6)) | + (*(sptr - wpls7)) | + (*(sptr - wpls8)) | + (*(sptr - wpls9)) | + (*(sptr - wpls10)) | + (*(sptr - wpls11)) | + (*(sptr - wpls12)) | + (*(sptr - wpls13)) | + (*(sptr - wpls14)) | + (*(sptr - wpls15)) | + (*(sptr - wpls16)); + } + } +} + +static void +ferode_3_93(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; +l_int32 wpls2, wpls3, wpls4; +l_int32 wpls5, wpls6, wpls7, wpls8; +l_int32 wpls9, wpls10, wpls11, wpls12; +l_int32 wpls13, wpls14, wpls15, wpls16; + + wpls2 = 2 * wpls; + wpls3 = 3 * wpls; + wpls4 = 4 * wpls; + wpls5 = 5 * wpls; + wpls6 = 6 * wpls; + wpls7 = 7 * wpls; + wpls8 = 8 * wpls; + wpls9 = 9 * wpls; + wpls10 = 10 * wpls; + wpls11 = 11 * wpls; + wpls12 = 12 * wpls; + wpls13 = 13 * wpls; + wpls14 = 14 * wpls; + wpls15 = 15 * wpls; + wpls16 = 16 * wpls; + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = (*(sptr - wpls16)) & + (*(sptr - wpls15)) & + (*(sptr - wpls14)) & + (*(sptr - wpls13)) & + (*(sptr - wpls12)) & + (*(sptr - wpls11)) & + (*(sptr - wpls10)) & + (*(sptr - wpls9)) & + (*(sptr - wpls8)) & + (*(sptr - wpls7)) & + (*(sptr - wpls6)) & + (*(sptr - wpls5)) & + (*(sptr - wpls4)) & + (*(sptr - wpls3)) & + (*(sptr - wpls2)) & + (*(sptr - wpls)) & + (*sptr) & + (*(sptr + wpls)) & + (*(sptr + wpls2)) & + (*(sptr + wpls3)) & + (*(sptr + wpls4)) & + (*(sptr + wpls5)) & + (*(sptr + wpls6)) & + (*(sptr + wpls7)) & + (*(sptr + wpls8)) & + (*(sptr + wpls9)) & + (*(sptr + wpls10)) & + (*(sptr + wpls11)) & + (*(sptr + wpls12)) & + (*(sptr + wpls13)) & + (*(sptr + wpls14)) & + (*(sptr + wpls15)) & + (*(sptr + wpls16)); + } + } +} + +static void +fdilate_3_94(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; +l_int32 wpls2, wpls3, wpls4; +l_int32 wpls5, wpls6, wpls7, wpls8; +l_int32 wpls9, wpls10, wpls11, wpls12; +l_int32 wpls13, wpls14, wpls15, wpls16; +l_int32 wpls17; + + wpls2 = 2 * wpls; + wpls3 = 3 * wpls; + wpls4 = 4 * wpls; + wpls5 = 5 * wpls; + wpls6 = 6 * wpls; + wpls7 = 7 * wpls; + wpls8 = 8 * wpls; + wpls9 = 9 * wpls; + wpls10 = 10 * wpls; + wpls11 = 11 * wpls; + wpls12 = 12 * wpls; + wpls13 = 13 * wpls; + wpls14 = 14 * wpls; + wpls15 = 15 * wpls; + wpls16 = 16 * wpls; + wpls17 = 17 * wpls; + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = (*(sptr + wpls17)) | + (*(sptr + wpls16)) | + (*(sptr + wpls15)) | + (*(sptr + wpls14)) | + (*(sptr + wpls13)) | + (*(sptr + wpls12)) | + (*(sptr + wpls11)) | + (*(sptr + wpls10)) | + (*(sptr + wpls9)) | + (*(sptr + wpls8)) | + (*(sptr + wpls7)) | + (*(sptr + wpls6)) | + (*(sptr + wpls5)) | + (*(sptr + wpls4)) | + (*(sptr + wpls3)) | + (*(sptr + wpls2)) | + (*(sptr + wpls)) | + (*sptr) | + (*(sptr - wpls)) | + (*(sptr - wpls2)) | + (*(sptr - wpls3)) | + (*(sptr - wpls4)) | + (*(sptr - wpls5)) | + (*(sptr - wpls6)) | + (*(sptr - wpls7)) | + (*(sptr - wpls8)) | + (*(sptr - wpls9)) | + (*(sptr - wpls10)) | + (*(sptr - wpls11)) | + (*(sptr - wpls12)) | + (*(sptr - wpls13)) | + (*(sptr - wpls14)) | + (*(sptr - wpls15)) | + (*(sptr - wpls16)); + } + } +} + +static void +ferode_3_94(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; +l_int32 wpls2, wpls3, wpls4; +l_int32 wpls5, wpls6, wpls7, wpls8; +l_int32 wpls9, wpls10, wpls11, wpls12; +l_int32 wpls13, wpls14, wpls15, wpls16; +l_int32 wpls17; + + wpls2 = 2 * wpls; + wpls3 = 3 * wpls; + wpls4 = 4 * wpls; + wpls5 = 5 * wpls; + wpls6 = 6 * wpls; + wpls7 = 7 * wpls; + wpls8 = 8 * wpls; + wpls9 = 9 * wpls; + wpls10 = 10 * wpls; + wpls11 = 11 * wpls; + wpls12 = 12 * wpls; + wpls13 = 13 * wpls; + wpls14 = 14 * wpls; + wpls15 = 15 * wpls; + wpls16 = 16 * wpls; + wpls17 = 17 * wpls; + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = (*(sptr - wpls17)) & + (*(sptr - wpls16)) & + (*(sptr - wpls15)) & + (*(sptr - wpls14)) & + (*(sptr - wpls13)) & + (*(sptr - wpls12)) & + (*(sptr - wpls11)) & + (*(sptr - wpls10)) & + (*(sptr - wpls9)) & + (*(sptr - wpls8)) & + (*(sptr - wpls7)) & + (*(sptr - wpls6)) & + (*(sptr - wpls5)) & + (*(sptr - wpls4)) & + (*(sptr - wpls3)) & + (*(sptr - wpls2)) & + (*(sptr - wpls)) & + (*sptr) & + (*(sptr + wpls)) & + (*(sptr + wpls2)) & + (*(sptr + wpls3)) & + (*(sptr + wpls4)) & + (*(sptr + wpls5)) & + (*(sptr + wpls6)) & + (*(sptr + wpls7)) & + (*(sptr + wpls8)) & + (*(sptr + wpls9)) & + (*(sptr + wpls10)) & + (*(sptr + wpls11)) & + (*(sptr + wpls12)) & + (*(sptr + wpls13)) & + (*(sptr + wpls14)) & + (*(sptr + wpls15)) & + (*(sptr + wpls16)); + } + } +} + +static void +fdilate_3_95(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; +l_int32 wpls2, wpls3, wpls4; +l_int32 wpls5, wpls6, wpls7, wpls8; +l_int32 wpls9, wpls10, wpls11, wpls12; +l_int32 wpls13, wpls14, wpls15, wpls16; +l_int32 wpls17; + + wpls2 = 2 * wpls; + wpls3 = 3 * wpls; + wpls4 = 4 * wpls; + wpls5 = 5 * wpls; + wpls6 = 6 * wpls; + wpls7 = 7 * wpls; + wpls8 = 8 * wpls; + wpls9 = 9 * wpls; + wpls10 = 10 * wpls; + wpls11 = 11 * wpls; + wpls12 = 12 * wpls; + wpls13 = 13 * wpls; + wpls14 = 14 * wpls; + wpls15 = 15 * wpls; + wpls16 = 16 * wpls; + wpls17 = 17 * wpls; + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = (*(sptr + wpls17)) | + (*(sptr + wpls16)) | + (*(sptr + wpls15)) | + (*(sptr + wpls14)) | + (*(sptr + wpls13)) | + (*(sptr + wpls12)) | + (*(sptr + wpls11)) | + (*(sptr + wpls10)) | + (*(sptr + wpls9)) | + (*(sptr + wpls8)) | + (*(sptr + wpls7)) | + (*(sptr + wpls6)) | + (*(sptr + wpls5)) | + (*(sptr + wpls4)) | + (*(sptr + wpls3)) | + (*(sptr + wpls2)) | + (*(sptr + wpls)) | + (*sptr) | + (*(sptr - wpls)) | + (*(sptr - wpls2)) | + (*(sptr - wpls3)) | + (*(sptr - wpls4)) | + (*(sptr - wpls5)) | + (*(sptr - wpls6)) | + (*(sptr - wpls7)) | + (*(sptr - wpls8)) | + (*(sptr - wpls9)) | + (*(sptr - wpls10)) | + (*(sptr - wpls11)) | + (*(sptr - wpls12)) | + (*(sptr - wpls13)) | + (*(sptr - wpls14)) | + (*(sptr - wpls15)) | + (*(sptr - wpls16)) | + (*(sptr - wpls17)); + } + } +} + +static void +ferode_3_95(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; +l_int32 wpls2, wpls3, wpls4; +l_int32 wpls5, wpls6, wpls7, wpls8; +l_int32 wpls9, wpls10, wpls11, wpls12; +l_int32 wpls13, wpls14, wpls15, wpls16; +l_int32 wpls17; + + wpls2 = 2 * wpls; + wpls3 = 3 * wpls; + wpls4 = 4 * wpls; + wpls5 = 5 * wpls; + wpls6 = 6 * wpls; + wpls7 = 7 * wpls; + wpls8 = 8 * wpls; + wpls9 = 9 * wpls; + wpls10 = 10 * wpls; + wpls11 = 11 * wpls; + wpls12 = 12 * wpls; + wpls13 = 13 * wpls; + wpls14 = 14 * wpls; + wpls15 = 15 * wpls; + wpls16 = 16 * wpls; + wpls17 = 17 * wpls; + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = (*(sptr - wpls17)) & + (*(sptr - wpls16)) & + (*(sptr - wpls15)) & + (*(sptr - wpls14)) & + (*(sptr - wpls13)) & + (*(sptr - wpls12)) & + (*(sptr - wpls11)) & + (*(sptr - wpls10)) & + (*(sptr - wpls9)) & + (*(sptr - wpls8)) & + (*(sptr - wpls7)) & + (*(sptr - wpls6)) & + (*(sptr - wpls5)) & + (*(sptr - wpls4)) & + (*(sptr - wpls3)) & + (*(sptr - wpls2)) & + (*(sptr - wpls)) & + (*sptr) & + (*(sptr + wpls)) & + (*(sptr + wpls2)) & + (*(sptr + wpls3)) & + (*(sptr + wpls4)) & + (*(sptr + wpls5)) & + (*(sptr + wpls6)) & + (*(sptr + wpls7)) & + (*(sptr + wpls8)) & + (*(sptr + wpls9)) & + (*(sptr + wpls10)) & + (*(sptr + wpls11)) & + (*(sptr + wpls12)) & + (*(sptr + wpls13)) & + (*(sptr + wpls14)) & + (*(sptr + wpls15)) & + (*(sptr + wpls16)) & + (*(sptr + wpls17)); + } + } +} + +static void +fdilate_3_96(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; +l_int32 wpls2, wpls3, wpls4; +l_int32 wpls5, wpls6, wpls7, wpls8; +l_int32 wpls9, wpls10, wpls11, wpls12; +l_int32 wpls13, wpls14, wpls15, wpls16; +l_int32 wpls17, wpls18; + + wpls2 = 2 * wpls; + wpls3 = 3 * wpls; + wpls4 = 4 * wpls; + wpls5 = 5 * wpls; + wpls6 = 6 * wpls; + wpls7 = 7 * wpls; + wpls8 = 8 * wpls; + wpls9 = 9 * wpls; + wpls10 = 10 * wpls; + wpls11 = 11 * wpls; + wpls12 = 12 * wpls; + wpls13 = 13 * wpls; + wpls14 = 14 * wpls; + wpls15 = 15 * wpls; + wpls16 = 16 * wpls; + wpls17 = 17 * wpls; + wpls18 = 18 * wpls; + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = (*(sptr + wpls18)) | + (*(sptr + wpls17)) | + (*(sptr + wpls16)) | + (*(sptr + wpls15)) | + (*(sptr + wpls14)) | + (*(sptr + wpls13)) | + (*(sptr + wpls12)) | + (*(sptr + wpls11)) | + (*(sptr + wpls10)) | + (*(sptr + wpls9)) | + (*(sptr + wpls8)) | + (*(sptr + wpls7)) | + (*(sptr + wpls6)) | + (*(sptr + wpls5)) | + (*(sptr + wpls4)) | + (*(sptr + wpls3)) | + (*(sptr + wpls2)) | + (*(sptr + wpls)) | + (*sptr) | + (*(sptr - wpls)) | + (*(sptr - wpls2)) | + (*(sptr - wpls3)) | + (*(sptr - wpls4)) | + (*(sptr - wpls5)) | + (*(sptr - wpls6)) | + (*(sptr - wpls7)) | + (*(sptr - wpls8)) | + (*(sptr - wpls9)) | + (*(sptr - wpls10)) | + (*(sptr - wpls11)) | + (*(sptr - wpls12)) | + (*(sptr - wpls13)) | + (*(sptr - wpls14)) | + (*(sptr - wpls15)) | + (*(sptr - wpls16)) | + (*(sptr - wpls17)); + } + } +} + +static void +ferode_3_96(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; +l_int32 wpls2, wpls3, wpls4; +l_int32 wpls5, wpls6, wpls7, wpls8; +l_int32 wpls9, wpls10, wpls11, wpls12; +l_int32 wpls13, wpls14, wpls15, wpls16; +l_int32 wpls17, wpls18; + + wpls2 = 2 * wpls; + wpls3 = 3 * wpls; + wpls4 = 4 * wpls; + wpls5 = 5 * wpls; + wpls6 = 6 * wpls; + wpls7 = 7 * wpls; + wpls8 = 8 * wpls; + wpls9 = 9 * wpls; + wpls10 = 10 * wpls; + wpls11 = 11 * wpls; + wpls12 = 12 * wpls; + wpls13 = 13 * wpls; + wpls14 = 14 * wpls; + wpls15 = 15 * wpls; + wpls16 = 16 * wpls; + wpls17 = 17 * wpls; + wpls18 = 18 * wpls; + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = (*(sptr - wpls18)) & + (*(sptr - wpls17)) & + (*(sptr - wpls16)) & + (*(sptr - wpls15)) & + (*(sptr - wpls14)) & + (*(sptr - wpls13)) & + (*(sptr - wpls12)) & + (*(sptr - wpls11)) & + (*(sptr - wpls10)) & + (*(sptr - wpls9)) & + (*(sptr - wpls8)) & + (*(sptr - wpls7)) & + (*(sptr - wpls6)) & + (*(sptr - wpls5)) & + (*(sptr - wpls4)) & + (*(sptr - wpls3)) & + (*(sptr - wpls2)) & + (*(sptr - wpls)) & + (*sptr) & + (*(sptr + wpls)) & + (*(sptr + wpls2)) & + (*(sptr + wpls3)) & + (*(sptr + wpls4)) & + (*(sptr + wpls5)) & + (*(sptr + wpls6)) & + (*(sptr + wpls7)) & + (*(sptr + wpls8)) & + (*(sptr + wpls9)) & + (*(sptr + wpls10)) & + (*(sptr + wpls11)) & + (*(sptr + wpls12)) & + (*(sptr + wpls13)) & + (*(sptr + wpls14)) & + (*(sptr + wpls15)) & + (*(sptr + wpls16)) & + (*(sptr + wpls17)); + } + } +} + +static void +fdilate_3_97(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; +l_int32 wpls2, wpls3, wpls4; +l_int32 wpls5, wpls6, wpls7, wpls8; +l_int32 wpls9, wpls10, wpls11, wpls12; +l_int32 wpls13, wpls14, wpls15, wpls16; +l_int32 wpls17, wpls18; + + wpls2 = 2 * wpls; + wpls3 = 3 * wpls; + wpls4 = 4 * wpls; + wpls5 = 5 * wpls; + wpls6 = 6 * wpls; + wpls7 = 7 * wpls; + wpls8 = 8 * wpls; + wpls9 = 9 * wpls; + wpls10 = 10 * wpls; + wpls11 = 11 * wpls; + wpls12 = 12 * wpls; + wpls13 = 13 * wpls; + wpls14 = 14 * wpls; + wpls15 = 15 * wpls; + wpls16 = 16 * wpls; + wpls17 = 17 * wpls; + wpls18 = 18 * wpls; + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = (*(sptr + wpls18)) | + (*(sptr + wpls17)) | + (*(sptr + wpls16)) | + (*(sptr + wpls15)) | + (*(sptr + wpls14)) | + (*(sptr + wpls13)) | + (*(sptr + wpls12)) | + (*(sptr + wpls11)) | + (*(sptr + wpls10)) | + (*(sptr + wpls9)) | + (*(sptr + wpls8)) | + (*(sptr + wpls7)) | + (*(sptr + wpls6)) | + (*(sptr + wpls5)) | + (*(sptr + wpls4)) | + (*(sptr + wpls3)) | + (*(sptr + wpls2)) | + (*(sptr + wpls)) | + (*sptr) | + (*(sptr - wpls)) | + (*(sptr - wpls2)) | + (*(sptr - wpls3)) | + (*(sptr - wpls4)) | + (*(sptr - wpls5)) | + (*(sptr - wpls6)) | + (*(sptr - wpls7)) | + (*(sptr - wpls8)) | + (*(sptr - wpls9)) | + (*(sptr - wpls10)) | + (*(sptr - wpls11)) | + (*(sptr - wpls12)) | + (*(sptr - wpls13)) | + (*(sptr - wpls14)) | + (*(sptr - wpls15)) | + (*(sptr - wpls16)) | + (*(sptr - wpls17)) | + (*(sptr - wpls18)); + } + } +} + +static void +ferode_3_97(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; +l_int32 wpls2, wpls3, wpls4; +l_int32 wpls5, wpls6, wpls7, wpls8; +l_int32 wpls9, wpls10, wpls11, wpls12; +l_int32 wpls13, wpls14, wpls15, wpls16; +l_int32 wpls17, wpls18; + + wpls2 = 2 * wpls; + wpls3 = 3 * wpls; + wpls4 = 4 * wpls; + wpls5 = 5 * wpls; + wpls6 = 6 * wpls; + wpls7 = 7 * wpls; + wpls8 = 8 * wpls; + wpls9 = 9 * wpls; + wpls10 = 10 * wpls; + wpls11 = 11 * wpls; + wpls12 = 12 * wpls; + wpls13 = 13 * wpls; + wpls14 = 14 * wpls; + wpls15 = 15 * wpls; + wpls16 = 16 * wpls; + wpls17 = 17 * wpls; + wpls18 = 18 * wpls; + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = (*(sptr - wpls18)) & + (*(sptr - wpls17)) & + (*(sptr - wpls16)) & + (*(sptr - wpls15)) & + (*(sptr - wpls14)) & + (*(sptr - wpls13)) & + (*(sptr - wpls12)) & + (*(sptr - wpls11)) & + (*(sptr - wpls10)) & + (*(sptr - wpls9)) & + (*(sptr - wpls8)) & + (*(sptr - wpls7)) & + (*(sptr - wpls6)) & + (*(sptr - wpls5)) & + (*(sptr - wpls4)) & + (*(sptr - wpls3)) & + (*(sptr - wpls2)) & + (*(sptr - wpls)) & + (*sptr) & + (*(sptr + wpls)) & + (*(sptr + wpls2)) & + (*(sptr + wpls3)) & + (*(sptr + wpls4)) & + (*(sptr + wpls5)) & + (*(sptr + wpls6)) & + (*(sptr + wpls7)) & + (*(sptr + wpls8)) & + (*(sptr + wpls9)) & + (*(sptr + wpls10)) & + (*(sptr + wpls11)) & + (*(sptr + wpls12)) & + (*(sptr + wpls13)) & + (*(sptr + wpls14)) & + (*(sptr + wpls15)) & + (*(sptr + wpls16)) & + (*(sptr + wpls17)) & + (*(sptr + wpls18)); + } + } +} + +static void +fdilate_3_98(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; +l_int32 wpls2, wpls3, wpls4; +l_int32 wpls5, wpls6, wpls7, wpls8; +l_int32 wpls9, wpls10, wpls11, wpls12; +l_int32 wpls13, wpls14, wpls15, wpls16; +l_int32 wpls17, wpls18, wpls19; + + wpls2 = 2 * wpls; + wpls3 = 3 * wpls; + wpls4 = 4 * wpls; + wpls5 = 5 * wpls; + wpls6 = 6 * wpls; + wpls7 = 7 * wpls; + wpls8 = 8 * wpls; + wpls9 = 9 * wpls; + wpls10 = 10 * wpls; + wpls11 = 11 * wpls; + wpls12 = 12 * wpls; + wpls13 = 13 * wpls; + wpls14 = 14 * wpls; + wpls15 = 15 * wpls; + wpls16 = 16 * wpls; + wpls17 = 17 * wpls; + wpls18 = 18 * wpls; + wpls19 = 19 * wpls; + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = (*(sptr + wpls19)) | + (*(sptr + wpls18)) | + (*(sptr + wpls17)) | + (*(sptr + wpls16)) | + (*(sptr + wpls15)) | + (*(sptr + wpls14)) | + (*(sptr + wpls13)) | + (*(sptr + wpls12)) | + (*(sptr + wpls11)) | + (*(sptr + wpls10)) | + (*(sptr + wpls9)) | + (*(sptr + wpls8)) | + (*(sptr + wpls7)) | + (*(sptr + wpls6)) | + (*(sptr + wpls5)) | + (*(sptr + wpls4)) | + (*(sptr + wpls3)) | + (*(sptr + wpls2)) | + (*(sptr + wpls)) | + (*sptr) | + (*(sptr - wpls)) | + (*(sptr - wpls2)) | + (*(sptr - wpls3)) | + (*(sptr - wpls4)) | + (*(sptr - wpls5)) | + (*(sptr - wpls6)) | + (*(sptr - wpls7)) | + (*(sptr - wpls8)) | + (*(sptr - wpls9)) | + (*(sptr - wpls10)) | + (*(sptr - wpls11)) | + (*(sptr - wpls12)) | + (*(sptr - wpls13)) | + (*(sptr - wpls14)) | + (*(sptr - wpls15)) | + (*(sptr - wpls16)) | + (*(sptr - wpls17)) | + (*(sptr - wpls18)); + } + } +} + +static void +ferode_3_98(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; +l_int32 wpls2, wpls3, wpls4; +l_int32 wpls5, wpls6, wpls7, wpls8; +l_int32 wpls9, wpls10, wpls11, wpls12; +l_int32 wpls13, wpls14, wpls15, wpls16; +l_int32 wpls17, wpls18, wpls19; + + wpls2 = 2 * wpls; + wpls3 = 3 * wpls; + wpls4 = 4 * wpls; + wpls5 = 5 * wpls; + wpls6 = 6 * wpls; + wpls7 = 7 * wpls; + wpls8 = 8 * wpls; + wpls9 = 9 * wpls; + wpls10 = 10 * wpls; + wpls11 = 11 * wpls; + wpls12 = 12 * wpls; + wpls13 = 13 * wpls; + wpls14 = 14 * wpls; + wpls15 = 15 * wpls; + wpls16 = 16 * wpls; + wpls17 = 17 * wpls; + wpls18 = 18 * wpls; + wpls19 = 19 * wpls; + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = (*(sptr - wpls19)) & + (*(sptr - wpls18)) & + (*(sptr - wpls17)) & + (*(sptr - wpls16)) & + (*(sptr - wpls15)) & + (*(sptr - wpls14)) & + (*(sptr - wpls13)) & + (*(sptr - wpls12)) & + (*(sptr - wpls11)) & + (*(sptr - wpls10)) & + (*(sptr - wpls9)) & + (*(sptr - wpls8)) & + (*(sptr - wpls7)) & + (*(sptr - wpls6)) & + (*(sptr - wpls5)) & + (*(sptr - wpls4)) & + (*(sptr - wpls3)) & + (*(sptr - wpls2)) & + (*(sptr - wpls)) & + (*sptr) & + (*(sptr + wpls)) & + (*(sptr + wpls2)) & + (*(sptr + wpls3)) & + (*(sptr + wpls4)) & + (*(sptr + wpls5)) & + (*(sptr + wpls6)) & + (*(sptr + wpls7)) & + (*(sptr + wpls8)) & + (*(sptr + wpls9)) & + (*(sptr + wpls10)) & + (*(sptr + wpls11)) & + (*(sptr + wpls12)) & + (*(sptr + wpls13)) & + (*(sptr + wpls14)) & + (*(sptr + wpls15)) & + (*(sptr + wpls16)) & + (*(sptr + wpls17)) & + (*(sptr + wpls18)); + } + } +} + +static void +fdilate_3_99(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; +l_int32 wpls2, wpls3, wpls4; +l_int32 wpls5, wpls6, wpls7, wpls8; +l_int32 wpls9, wpls10, wpls11, wpls12; +l_int32 wpls13, wpls14, wpls15, wpls16; +l_int32 wpls17, wpls18, wpls19; + + wpls2 = 2 * wpls; + wpls3 = 3 * wpls; + wpls4 = 4 * wpls; + wpls5 = 5 * wpls; + wpls6 = 6 * wpls; + wpls7 = 7 * wpls; + wpls8 = 8 * wpls; + wpls9 = 9 * wpls; + wpls10 = 10 * wpls; + wpls11 = 11 * wpls; + wpls12 = 12 * wpls; + wpls13 = 13 * wpls; + wpls14 = 14 * wpls; + wpls15 = 15 * wpls; + wpls16 = 16 * wpls; + wpls17 = 17 * wpls; + wpls18 = 18 * wpls; + wpls19 = 19 * wpls; + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = (*(sptr + wpls19)) | + (*(sptr + wpls18)) | + (*(sptr + wpls17)) | + (*(sptr + wpls16)) | + (*(sptr + wpls15)) | + (*(sptr + wpls14)) | + (*(sptr + wpls13)) | + (*(sptr + wpls12)) | + (*(sptr + wpls11)) | + (*(sptr + wpls10)) | + (*(sptr + wpls9)) | + (*(sptr + wpls8)) | + (*(sptr + wpls7)) | + (*(sptr + wpls6)) | + (*(sptr + wpls5)) | + (*(sptr + wpls4)) | + (*(sptr + wpls3)) | + (*(sptr + wpls2)) | + (*(sptr + wpls)) | + (*sptr) | + (*(sptr - wpls)) | + (*(sptr - wpls2)) | + (*(sptr - wpls3)) | + (*(sptr - wpls4)) | + (*(sptr - wpls5)) | + (*(sptr - wpls6)) | + (*(sptr - wpls7)) | + (*(sptr - wpls8)) | + (*(sptr - wpls9)) | + (*(sptr - wpls10)) | + (*(sptr - wpls11)) | + (*(sptr - wpls12)) | + (*(sptr - wpls13)) | + (*(sptr - wpls14)) | + (*(sptr - wpls15)) | + (*(sptr - wpls16)) | + (*(sptr - wpls17)) | + (*(sptr - wpls18)) | + (*(sptr - wpls19)); + } + } +} + +static void +ferode_3_99(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; +l_int32 wpls2, wpls3, wpls4; +l_int32 wpls5, wpls6, wpls7, wpls8; +l_int32 wpls9, wpls10, wpls11, wpls12; +l_int32 wpls13, wpls14, wpls15, wpls16; +l_int32 wpls17, wpls18, wpls19; + + wpls2 = 2 * wpls; + wpls3 = 3 * wpls; + wpls4 = 4 * wpls; + wpls5 = 5 * wpls; + wpls6 = 6 * wpls; + wpls7 = 7 * wpls; + wpls8 = 8 * wpls; + wpls9 = 9 * wpls; + wpls10 = 10 * wpls; + wpls11 = 11 * wpls; + wpls12 = 12 * wpls; + wpls13 = 13 * wpls; + wpls14 = 14 * wpls; + wpls15 = 15 * wpls; + wpls16 = 16 * wpls; + wpls17 = 17 * wpls; + wpls18 = 18 * wpls; + wpls19 = 19 * wpls; + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = (*(sptr - wpls19)) & + (*(sptr - wpls18)) & + (*(sptr - wpls17)) & + (*(sptr - wpls16)) & + (*(sptr - wpls15)) & + (*(sptr - wpls14)) & + (*(sptr - wpls13)) & + (*(sptr - wpls12)) & + (*(sptr - wpls11)) & + (*(sptr - wpls10)) & + (*(sptr - wpls9)) & + (*(sptr - wpls8)) & + (*(sptr - wpls7)) & + (*(sptr - wpls6)) & + (*(sptr - wpls5)) & + (*(sptr - wpls4)) & + (*(sptr - wpls3)) & + (*(sptr - wpls2)) & + (*(sptr - wpls)) & + (*sptr) & + (*(sptr + wpls)) & + (*(sptr + wpls2)) & + (*(sptr + wpls3)) & + (*(sptr + wpls4)) & + (*(sptr + wpls5)) & + (*(sptr + wpls6)) & + (*(sptr + wpls7)) & + (*(sptr + wpls8)) & + (*(sptr + wpls9)) & + (*(sptr + wpls10)) & + (*(sptr + wpls11)) & + (*(sptr + wpls12)) & + (*(sptr + wpls13)) & + (*(sptr + wpls14)) & + (*(sptr + wpls15)) & + (*(sptr + wpls16)) & + (*(sptr + wpls17)) & + (*(sptr + wpls18)) & + (*(sptr + wpls19)); + } + } +} + +static void +fdilate_3_100(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; +l_int32 wpls2, wpls3, wpls4; +l_int32 wpls5, wpls6, wpls7, wpls8; +l_int32 wpls9, wpls10, wpls11, wpls12; +l_int32 wpls13, wpls14, wpls15, wpls16; +l_int32 wpls17, wpls18, wpls19, wpls20; + + wpls2 = 2 * wpls; + wpls3 = 3 * wpls; + wpls4 = 4 * wpls; + wpls5 = 5 * wpls; + wpls6 = 6 * wpls; + wpls7 = 7 * wpls; + wpls8 = 8 * wpls; + wpls9 = 9 * wpls; + wpls10 = 10 * wpls; + wpls11 = 11 * wpls; + wpls12 = 12 * wpls; + wpls13 = 13 * wpls; + wpls14 = 14 * wpls; + wpls15 = 15 * wpls; + wpls16 = 16 * wpls; + wpls17 = 17 * wpls; + wpls18 = 18 * wpls; + wpls19 = 19 * wpls; + wpls20 = 20 * wpls; + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = (*(sptr + wpls20)) | + (*(sptr + wpls19)) | + (*(sptr + wpls18)) | + (*(sptr + wpls17)) | + (*(sptr + wpls16)) | + (*(sptr + wpls15)) | + (*(sptr + wpls14)) | + (*(sptr + wpls13)) | + (*(sptr + wpls12)) | + (*(sptr + wpls11)) | + (*(sptr + wpls10)) | + (*(sptr + wpls9)) | + (*(sptr + wpls8)) | + (*(sptr + wpls7)) | + (*(sptr + wpls6)) | + (*(sptr + wpls5)) | + (*(sptr + wpls4)) | + (*(sptr + wpls3)) | + (*(sptr + wpls2)) | + (*(sptr + wpls)) | + (*sptr) | + (*(sptr - wpls)) | + (*(sptr - wpls2)) | + (*(sptr - wpls3)) | + (*(sptr - wpls4)) | + (*(sptr - wpls5)) | + (*(sptr - wpls6)) | + (*(sptr - wpls7)) | + (*(sptr - wpls8)) | + (*(sptr - wpls9)) | + (*(sptr - wpls10)) | + (*(sptr - wpls11)) | + (*(sptr - wpls12)) | + (*(sptr - wpls13)) | + (*(sptr - wpls14)) | + (*(sptr - wpls15)) | + (*(sptr - wpls16)) | + (*(sptr - wpls17)) | + (*(sptr - wpls18)) | + (*(sptr - wpls19)); + } + } +} + +static void +ferode_3_100(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; +l_int32 wpls2, wpls3, wpls4; +l_int32 wpls5, wpls6, wpls7, wpls8; +l_int32 wpls9, wpls10, wpls11, wpls12; +l_int32 wpls13, wpls14, wpls15, wpls16; +l_int32 wpls17, wpls18, wpls19, wpls20; + + wpls2 = 2 * wpls; + wpls3 = 3 * wpls; + wpls4 = 4 * wpls; + wpls5 = 5 * wpls; + wpls6 = 6 * wpls; + wpls7 = 7 * wpls; + wpls8 = 8 * wpls; + wpls9 = 9 * wpls; + wpls10 = 10 * wpls; + wpls11 = 11 * wpls; + wpls12 = 12 * wpls; + wpls13 = 13 * wpls; + wpls14 = 14 * wpls; + wpls15 = 15 * wpls; + wpls16 = 16 * wpls; + wpls17 = 17 * wpls; + wpls18 = 18 * wpls; + wpls19 = 19 * wpls; + wpls20 = 20 * wpls; + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = (*(sptr - wpls20)) & + (*(sptr - wpls19)) & + (*(sptr - wpls18)) & + (*(sptr - wpls17)) & + (*(sptr - wpls16)) & + (*(sptr - wpls15)) & + (*(sptr - wpls14)) & + (*(sptr - wpls13)) & + (*(sptr - wpls12)) & + (*(sptr - wpls11)) & + (*(sptr - wpls10)) & + (*(sptr - wpls9)) & + (*(sptr - wpls8)) & + (*(sptr - wpls7)) & + (*(sptr - wpls6)) & + (*(sptr - wpls5)) & + (*(sptr - wpls4)) & + (*(sptr - wpls3)) & + (*(sptr - wpls2)) & + (*(sptr - wpls)) & + (*sptr) & + (*(sptr + wpls)) & + (*(sptr + wpls2)) & + (*(sptr + wpls3)) & + (*(sptr + wpls4)) & + (*(sptr + wpls5)) & + (*(sptr + wpls6)) & + (*(sptr + wpls7)) & + (*(sptr + wpls8)) & + (*(sptr + wpls9)) & + (*(sptr + wpls10)) & + (*(sptr + wpls11)) & + (*(sptr + wpls12)) & + (*(sptr + wpls13)) & + (*(sptr + wpls14)) & + (*(sptr + wpls15)) & + (*(sptr + wpls16)) & + (*(sptr + wpls17)) & + (*(sptr + wpls18)) & + (*(sptr + wpls19)); + } + } +} + +static void +fdilate_3_101(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; +l_int32 wpls2, wpls3, wpls4; +l_int32 wpls5, wpls6, wpls7, wpls8; +l_int32 wpls9, wpls10, wpls11, wpls12; +l_int32 wpls13, wpls14, wpls15, wpls16; +l_int32 wpls17, wpls18, wpls19, wpls20; + + wpls2 = 2 * wpls; + wpls3 = 3 * wpls; + wpls4 = 4 * wpls; + wpls5 = 5 * wpls; + wpls6 = 6 * wpls; + wpls7 = 7 * wpls; + wpls8 = 8 * wpls; + wpls9 = 9 * wpls; + wpls10 = 10 * wpls; + wpls11 = 11 * wpls; + wpls12 = 12 * wpls; + wpls13 = 13 * wpls; + wpls14 = 14 * wpls; + wpls15 = 15 * wpls; + wpls16 = 16 * wpls; + wpls17 = 17 * wpls; + wpls18 = 18 * wpls; + wpls19 = 19 * wpls; + wpls20 = 20 * wpls; + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = (*(sptr + wpls20)) | + (*(sptr + wpls19)) | + (*(sptr + wpls18)) | + (*(sptr + wpls17)) | + (*(sptr + wpls16)) | + (*(sptr + wpls15)) | + (*(sptr + wpls14)) | + (*(sptr + wpls13)) | + (*(sptr + wpls12)) | + (*(sptr + wpls11)) | + (*(sptr + wpls10)) | + (*(sptr + wpls9)) | + (*(sptr + wpls8)) | + (*(sptr + wpls7)) | + (*(sptr + wpls6)) | + (*(sptr + wpls5)) | + (*(sptr + wpls4)) | + (*(sptr + wpls3)) | + (*(sptr + wpls2)) | + (*(sptr + wpls)) | + (*sptr) | + (*(sptr - wpls)) | + (*(sptr - wpls2)) | + (*(sptr - wpls3)) | + (*(sptr - wpls4)) | + (*(sptr - wpls5)) | + (*(sptr - wpls6)) | + (*(sptr - wpls7)) | + (*(sptr - wpls8)) | + (*(sptr - wpls9)) | + (*(sptr - wpls10)) | + (*(sptr - wpls11)) | + (*(sptr - wpls12)) | + (*(sptr - wpls13)) | + (*(sptr - wpls14)) | + (*(sptr - wpls15)) | + (*(sptr - wpls16)) | + (*(sptr - wpls17)) | + (*(sptr - wpls18)) | + (*(sptr - wpls19)) | + (*(sptr - wpls20)); + } + } +} + +static void +ferode_3_101(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; +l_int32 wpls2, wpls3, wpls4; +l_int32 wpls5, wpls6, wpls7, wpls8; +l_int32 wpls9, wpls10, wpls11, wpls12; +l_int32 wpls13, wpls14, wpls15, wpls16; +l_int32 wpls17, wpls18, wpls19, wpls20; + + wpls2 = 2 * wpls; + wpls3 = 3 * wpls; + wpls4 = 4 * wpls; + wpls5 = 5 * wpls; + wpls6 = 6 * wpls; + wpls7 = 7 * wpls; + wpls8 = 8 * wpls; + wpls9 = 9 * wpls; + wpls10 = 10 * wpls; + wpls11 = 11 * wpls; + wpls12 = 12 * wpls; + wpls13 = 13 * wpls; + wpls14 = 14 * wpls; + wpls15 = 15 * wpls; + wpls16 = 16 * wpls; + wpls17 = 17 * wpls; + wpls18 = 18 * wpls; + wpls19 = 19 * wpls; + wpls20 = 20 * wpls; + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = (*(sptr - wpls20)) & + (*(sptr - wpls19)) & + (*(sptr - wpls18)) & + (*(sptr - wpls17)) & + (*(sptr - wpls16)) & + (*(sptr - wpls15)) & + (*(sptr - wpls14)) & + (*(sptr - wpls13)) & + (*(sptr - wpls12)) & + (*(sptr - wpls11)) & + (*(sptr - wpls10)) & + (*(sptr - wpls9)) & + (*(sptr - wpls8)) & + (*(sptr - wpls7)) & + (*(sptr - wpls6)) & + (*(sptr - wpls5)) & + (*(sptr - wpls4)) & + (*(sptr - wpls3)) & + (*(sptr - wpls2)) & + (*(sptr - wpls)) & + (*sptr) & + (*(sptr + wpls)) & + (*(sptr + wpls2)) & + (*(sptr + wpls3)) & + (*(sptr + wpls4)) & + (*(sptr + wpls5)) & + (*(sptr + wpls6)) & + (*(sptr + wpls7)) & + (*(sptr + wpls8)) & + (*(sptr + wpls9)) & + (*(sptr + wpls10)) & + (*(sptr + wpls11)) & + (*(sptr + wpls12)) & + (*(sptr + wpls13)) & + (*(sptr + wpls14)) & + (*(sptr + wpls15)) & + (*(sptr + wpls16)) & + (*(sptr + wpls17)) & + (*(sptr + wpls18)) & + (*(sptr + wpls19)) & + (*(sptr + wpls20)); + } + } +} + +static void +fdilate_3_102(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; +l_int32 wpls2, wpls3, wpls4; +l_int32 wpls5, wpls6, wpls7, wpls8; +l_int32 wpls9, wpls10, wpls11, wpls12; +l_int32 wpls13, wpls14, wpls15, wpls16; +l_int32 wpls17, wpls18, wpls19, wpls20; +l_int32 wpls21; + + wpls2 = 2 * wpls; + wpls3 = 3 * wpls; + wpls4 = 4 * wpls; + wpls5 = 5 * wpls; + wpls6 = 6 * wpls; + wpls7 = 7 * wpls; + wpls8 = 8 * wpls; + wpls9 = 9 * wpls; + wpls10 = 10 * wpls; + wpls11 = 11 * wpls; + wpls12 = 12 * wpls; + wpls13 = 13 * wpls; + wpls14 = 14 * wpls; + wpls15 = 15 * wpls; + wpls16 = 16 * wpls; + wpls17 = 17 * wpls; + wpls18 = 18 * wpls; + wpls19 = 19 * wpls; + wpls20 = 20 * wpls; + wpls21 = 21 * wpls; + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = (*(sptr + wpls21)) | + (*(sptr + wpls20)) | + (*(sptr + wpls19)) | + (*(sptr + wpls18)) | + (*(sptr + wpls17)) | + (*(sptr + wpls16)) | + (*(sptr + wpls15)) | + (*(sptr + wpls14)) | + (*(sptr + wpls13)) | + (*(sptr + wpls12)) | + (*(sptr + wpls11)) | + (*(sptr + wpls10)) | + (*(sptr + wpls9)) | + (*(sptr + wpls8)) | + (*(sptr + wpls7)) | + (*(sptr + wpls6)) | + (*(sptr + wpls5)) | + (*(sptr + wpls4)) | + (*(sptr + wpls3)) | + (*(sptr + wpls2)) | + (*(sptr + wpls)) | + (*sptr) | + (*(sptr - wpls)) | + (*(sptr - wpls2)) | + (*(sptr - wpls3)) | + (*(sptr - wpls4)) | + (*(sptr - wpls5)) | + (*(sptr - wpls6)) | + (*(sptr - wpls7)) | + (*(sptr - wpls8)) | + (*(sptr - wpls9)) | + (*(sptr - wpls10)) | + (*(sptr - wpls11)) | + (*(sptr - wpls12)) | + (*(sptr - wpls13)) | + (*(sptr - wpls14)) | + (*(sptr - wpls15)) | + (*(sptr - wpls16)) | + (*(sptr - wpls17)) | + (*(sptr - wpls18)) | + (*(sptr - wpls19)) | + (*(sptr - wpls20)); + } + } +} + +static void +ferode_3_102(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; +l_int32 wpls2, wpls3, wpls4; +l_int32 wpls5, wpls6, wpls7, wpls8; +l_int32 wpls9, wpls10, wpls11, wpls12; +l_int32 wpls13, wpls14, wpls15, wpls16; +l_int32 wpls17, wpls18, wpls19, wpls20; +l_int32 wpls21; + + wpls2 = 2 * wpls; + wpls3 = 3 * wpls; + wpls4 = 4 * wpls; + wpls5 = 5 * wpls; + wpls6 = 6 * wpls; + wpls7 = 7 * wpls; + wpls8 = 8 * wpls; + wpls9 = 9 * wpls; + wpls10 = 10 * wpls; + wpls11 = 11 * wpls; + wpls12 = 12 * wpls; + wpls13 = 13 * wpls; + wpls14 = 14 * wpls; + wpls15 = 15 * wpls; + wpls16 = 16 * wpls; + wpls17 = 17 * wpls; + wpls18 = 18 * wpls; + wpls19 = 19 * wpls; + wpls20 = 20 * wpls; + wpls21 = 21 * wpls; + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = (*(sptr - wpls21)) & + (*(sptr - wpls20)) & + (*(sptr - wpls19)) & + (*(sptr - wpls18)) & + (*(sptr - wpls17)) & + (*(sptr - wpls16)) & + (*(sptr - wpls15)) & + (*(sptr - wpls14)) & + (*(sptr - wpls13)) & + (*(sptr - wpls12)) & + (*(sptr - wpls11)) & + (*(sptr - wpls10)) & + (*(sptr - wpls9)) & + (*(sptr - wpls8)) & + (*(sptr - wpls7)) & + (*(sptr - wpls6)) & + (*(sptr - wpls5)) & + (*(sptr - wpls4)) & + (*(sptr - wpls3)) & + (*(sptr - wpls2)) & + (*(sptr - wpls)) & + (*sptr) & + (*(sptr + wpls)) & + (*(sptr + wpls2)) & + (*(sptr + wpls3)) & + (*(sptr + wpls4)) & + (*(sptr + wpls5)) & + (*(sptr + wpls6)) & + (*(sptr + wpls7)) & + (*(sptr + wpls8)) & + (*(sptr + wpls9)) & + (*(sptr + wpls10)) & + (*(sptr + wpls11)) & + (*(sptr + wpls12)) & + (*(sptr + wpls13)) & + (*(sptr + wpls14)) & + (*(sptr + wpls15)) & + (*(sptr + wpls16)) & + (*(sptr + wpls17)) & + (*(sptr + wpls18)) & + (*(sptr + wpls19)) & + (*(sptr + wpls20)); + } + } +} + +static void +fdilate_3_103(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; +l_int32 wpls2, wpls3, wpls4; +l_int32 wpls5, wpls6, wpls7, wpls8; +l_int32 wpls9, wpls10, wpls11, wpls12; +l_int32 wpls13, wpls14, wpls15, wpls16; +l_int32 wpls17, wpls18, wpls19, wpls20; +l_int32 wpls21; + + wpls2 = 2 * wpls; + wpls3 = 3 * wpls; + wpls4 = 4 * wpls; + wpls5 = 5 * wpls; + wpls6 = 6 * wpls; + wpls7 = 7 * wpls; + wpls8 = 8 * wpls; + wpls9 = 9 * wpls; + wpls10 = 10 * wpls; + wpls11 = 11 * wpls; + wpls12 = 12 * wpls; + wpls13 = 13 * wpls; + wpls14 = 14 * wpls; + wpls15 = 15 * wpls; + wpls16 = 16 * wpls; + wpls17 = 17 * wpls; + wpls18 = 18 * wpls; + wpls19 = 19 * wpls; + wpls20 = 20 * wpls; + wpls21 = 21 * wpls; + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = (*(sptr + wpls21)) | + (*(sptr + wpls20)) | + (*(sptr + wpls19)) | + (*(sptr + wpls18)) | + (*(sptr + wpls17)) | + (*(sptr + wpls16)) | + (*(sptr + wpls15)) | + (*(sptr + wpls14)) | + (*(sptr + wpls13)) | + (*(sptr + wpls12)) | + (*(sptr + wpls11)) | + (*(sptr + wpls10)) | + (*(sptr + wpls9)) | + (*(sptr + wpls8)) | + (*(sptr + wpls7)) | + (*(sptr + wpls6)) | + (*(sptr + wpls5)) | + (*(sptr + wpls4)) | + (*(sptr + wpls3)) | + (*(sptr + wpls2)) | + (*(sptr + wpls)) | + (*sptr) | + (*(sptr - wpls)) | + (*(sptr - wpls2)) | + (*(sptr - wpls3)) | + (*(sptr - wpls4)) | + (*(sptr - wpls5)) | + (*(sptr - wpls6)) | + (*(sptr - wpls7)) | + (*(sptr - wpls8)) | + (*(sptr - wpls9)) | + (*(sptr - wpls10)) | + (*(sptr - wpls11)) | + (*(sptr - wpls12)) | + (*(sptr - wpls13)) | + (*(sptr - wpls14)) | + (*(sptr - wpls15)) | + (*(sptr - wpls16)) | + (*(sptr - wpls17)) | + (*(sptr - wpls18)) | + (*(sptr - wpls19)) | + (*(sptr - wpls20)) | + (*(sptr - wpls21)); + } + } +} + +static void +ferode_3_103(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; +l_int32 wpls2, wpls3, wpls4; +l_int32 wpls5, wpls6, wpls7, wpls8; +l_int32 wpls9, wpls10, wpls11, wpls12; +l_int32 wpls13, wpls14, wpls15, wpls16; +l_int32 wpls17, wpls18, wpls19, wpls20; +l_int32 wpls21; + + wpls2 = 2 * wpls; + wpls3 = 3 * wpls; + wpls4 = 4 * wpls; + wpls5 = 5 * wpls; + wpls6 = 6 * wpls; + wpls7 = 7 * wpls; + wpls8 = 8 * wpls; + wpls9 = 9 * wpls; + wpls10 = 10 * wpls; + wpls11 = 11 * wpls; + wpls12 = 12 * wpls; + wpls13 = 13 * wpls; + wpls14 = 14 * wpls; + wpls15 = 15 * wpls; + wpls16 = 16 * wpls; + wpls17 = 17 * wpls; + wpls18 = 18 * wpls; + wpls19 = 19 * wpls; + wpls20 = 20 * wpls; + wpls21 = 21 * wpls; + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = (*(sptr - wpls21)) & + (*(sptr - wpls20)) & + (*(sptr - wpls19)) & + (*(sptr - wpls18)) & + (*(sptr - wpls17)) & + (*(sptr - wpls16)) & + (*(sptr - wpls15)) & + (*(sptr - wpls14)) & + (*(sptr - wpls13)) & + (*(sptr - wpls12)) & + (*(sptr - wpls11)) & + (*(sptr - wpls10)) & + (*(sptr - wpls9)) & + (*(sptr - wpls8)) & + (*(sptr - wpls7)) & + (*(sptr - wpls6)) & + (*(sptr - wpls5)) & + (*(sptr - wpls4)) & + (*(sptr - wpls3)) & + (*(sptr - wpls2)) & + (*(sptr - wpls)) & + (*sptr) & + (*(sptr + wpls)) & + (*(sptr + wpls2)) & + (*(sptr + wpls3)) & + (*(sptr + wpls4)) & + (*(sptr + wpls5)) & + (*(sptr + wpls6)) & + (*(sptr + wpls7)) & + (*(sptr + wpls8)) & + (*(sptr + wpls9)) & + (*(sptr + wpls10)) & + (*(sptr + wpls11)) & + (*(sptr + wpls12)) & + (*(sptr + wpls13)) & + (*(sptr + wpls14)) & + (*(sptr + wpls15)) & + (*(sptr + wpls16)) & + (*(sptr + wpls17)) & + (*(sptr + wpls18)) & + (*(sptr + wpls19)) & + (*(sptr + wpls20)) & + (*(sptr + wpls21)); + } + } +} + +static void +fdilate_3_104(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; +l_int32 wpls2, wpls3, wpls4; +l_int32 wpls5, wpls6, wpls7, wpls8; +l_int32 wpls9, wpls10, wpls11, wpls12; +l_int32 wpls13, wpls14, wpls15, wpls16; +l_int32 wpls17, wpls18, wpls19, wpls20; +l_int32 wpls21, wpls22; + + wpls2 = 2 * wpls; + wpls3 = 3 * wpls; + wpls4 = 4 * wpls; + wpls5 = 5 * wpls; + wpls6 = 6 * wpls; + wpls7 = 7 * wpls; + wpls8 = 8 * wpls; + wpls9 = 9 * wpls; + wpls10 = 10 * wpls; + wpls11 = 11 * wpls; + wpls12 = 12 * wpls; + wpls13 = 13 * wpls; + wpls14 = 14 * wpls; + wpls15 = 15 * wpls; + wpls16 = 16 * wpls; + wpls17 = 17 * wpls; + wpls18 = 18 * wpls; + wpls19 = 19 * wpls; + wpls20 = 20 * wpls; + wpls21 = 21 * wpls; + wpls22 = 22 * wpls; + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = (*(sptr + wpls22)) | + (*(sptr + wpls21)) | + (*(sptr + wpls20)) | + (*(sptr + wpls19)) | + (*(sptr + wpls18)) | + (*(sptr + wpls17)) | + (*(sptr + wpls16)) | + (*(sptr + wpls15)) | + (*(sptr + wpls14)) | + (*(sptr + wpls13)) | + (*(sptr + wpls12)) | + (*(sptr + wpls11)) | + (*(sptr + wpls10)) | + (*(sptr + wpls9)) | + (*(sptr + wpls8)) | + (*(sptr + wpls7)) | + (*(sptr + wpls6)) | + (*(sptr + wpls5)) | + (*(sptr + wpls4)) | + (*(sptr + wpls3)) | + (*(sptr + wpls2)) | + (*(sptr + wpls)) | + (*sptr) | + (*(sptr - wpls)) | + (*(sptr - wpls2)) | + (*(sptr - wpls3)) | + (*(sptr - wpls4)) | + (*(sptr - wpls5)) | + (*(sptr - wpls6)) | + (*(sptr - wpls7)) | + (*(sptr - wpls8)) | + (*(sptr - wpls9)) | + (*(sptr - wpls10)) | + (*(sptr - wpls11)) | + (*(sptr - wpls12)) | + (*(sptr - wpls13)) | + (*(sptr - wpls14)) | + (*(sptr - wpls15)) | + (*(sptr - wpls16)) | + (*(sptr - wpls17)) | + (*(sptr - wpls18)) | + (*(sptr - wpls19)) | + (*(sptr - wpls20)) | + (*(sptr - wpls21)); + } + } +} + +static void +ferode_3_104(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; +l_int32 wpls2, wpls3, wpls4; +l_int32 wpls5, wpls6, wpls7, wpls8; +l_int32 wpls9, wpls10, wpls11, wpls12; +l_int32 wpls13, wpls14, wpls15, wpls16; +l_int32 wpls17, wpls18, wpls19, wpls20; +l_int32 wpls21, wpls22; + + wpls2 = 2 * wpls; + wpls3 = 3 * wpls; + wpls4 = 4 * wpls; + wpls5 = 5 * wpls; + wpls6 = 6 * wpls; + wpls7 = 7 * wpls; + wpls8 = 8 * wpls; + wpls9 = 9 * wpls; + wpls10 = 10 * wpls; + wpls11 = 11 * wpls; + wpls12 = 12 * wpls; + wpls13 = 13 * wpls; + wpls14 = 14 * wpls; + wpls15 = 15 * wpls; + wpls16 = 16 * wpls; + wpls17 = 17 * wpls; + wpls18 = 18 * wpls; + wpls19 = 19 * wpls; + wpls20 = 20 * wpls; + wpls21 = 21 * wpls; + wpls22 = 22 * wpls; + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = (*(sptr - wpls22)) & + (*(sptr - wpls21)) & + (*(sptr - wpls20)) & + (*(sptr - wpls19)) & + (*(sptr - wpls18)) & + (*(sptr - wpls17)) & + (*(sptr - wpls16)) & + (*(sptr - wpls15)) & + (*(sptr - wpls14)) & + (*(sptr - wpls13)) & + (*(sptr - wpls12)) & + (*(sptr - wpls11)) & + (*(sptr - wpls10)) & + (*(sptr - wpls9)) & + (*(sptr - wpls8)) & + (*(sptr - wpls7)) & + (*(sptr - wpls6)) & + (*(sptr - wpls5)) & + (*(sptr - wpls4)) & + (*(sptr - wpls3)) & + (*(sptr - wpls2)) & + (*(sptr - wpls)) & + (*sptr) & + (*(sptr + wpls)) & + (*(sptr + wpls2)) & + (*(sptr + wpls3)) & + (*(sptr + wpls4)) & + (*(sptr + wpls5)) & + (*(sptr + wpls6)) & + (*(sptr + wpls7)) & + (*(sptr + wpls8)) & + (*(sptr + wpls9)) & + (*(sptr + wpls10)) & + (*(sptr + wpls11)) & + (*(sptr + wpls12)) & + (*(sptr + wpls13)) & + (*(sptr + wpls14)) & + (*(sptr + wpls15)) & + (*(sptr + wpls16)) & + (*(sptr + wpls17)) & + (*(sptr + wpls18)) & + (*(sptr + wpls19)) & + (*(sptr + wpls20)) & + (*(sptr + wpls21)); + } + } +} + +static void +fdilate_3_105(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; +l_int32 wpls2, wpls3, wpls4; +l_int32 wpls5, wpls6, wpls7, wpls8; +l_int32 wpls9, wpls10, wpls11, wpls12; +l_int32 wpls13, wpls14, wpls15, wpls16; +l_int32 wpls17, wpls18, wpls19, wpls20; +l_int32 wpls21, wpls22; + + wpls2 = 2 * wpls; + wpls3 = 3 * wpls; + wpls4 = 4 * wpls; + wpls5 = 5 * wpls; + wpls6 = 6 * wpls; + wpls7 = 7 * wpls; + wpls8 = 8 * wpls; + wpls9 = 9 * wpls; + wpls10 = 10 * wpls; + wpls11 = 11 * wpls; + wpls12 = 12 * wpls; + wpls13 = 13 * wpls; + wpls14 = 14 * wpls; + wpls15 = 15 * wpls; + wpls16 = 16 * wpls; + wpls17 = 17 * wpls; + wpls18 = 18 * wpls; + wpls19 = 19 * wpls; + wpls20 = 20 * wpls; + wpls21 = 21 * wpls; + wpls22 = 22 * wpls; + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = (*(sptr + wpls22)) | + (*(sptr + wpls21)) | + (*(sptr + wpls20)) | + (*(sptr + wpls19)) | + (*(sptr + wpls18)) | + (*(sptr + wpls17)) | + (*(sptr + wpls16)) | + (*(sptr + wpls15)) | + (*(sptr + wpls14)) | + (*(sptr + wpls13)) | + (*(sptr + wpls12)) | + (*(sptr + wpls11)) | + (*(sptr + wpls10)) | + (*(sptr + wpls9)) | + (*(sptr + wpls8)) | + (*(sptr + wpls7)) | + (*(sptr + wpls6)) | + (*(sptr + wpls5)) | + (*(sptr + wpls4)) | + (*(sptr + wpls3)) | + (*(sptr + wpls2)) | + (*(sptr + wpls)) | + (*sptr) | + (*(sptr - wpls)) | + (*(sptr - wpls2)) | + (*(sptr - wpls3)) | + (*(sptr - wpls4)) | + (*(sptr - wpls5)) | + (*(sptr - wpls6)) | + (*(sptr - wpls7)) | + (*(sptr - wpls8)) | + (*(sptr - wpls9)) | + (*(sptr - wpls10)) | + (*(sptr - wpls11)) | + (*(sptr - wpls12)) | + (*(sptr - wpls13)) | + (*(sptr - wpls14)) | + (*(sptr - wpls15)) | + (*(sptr - wpls16)) | + (*(sptr - wpls17)) | + (*(sptr - wpls18)) | + (*(sptr - wpls19)) | + (*(sptr - wpls20)) | + (*(sptr - wpls21)) | + (*(sptr - wpls22)); + } + } +} + +static void +ferode_3_105(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; +l_int32 wpls2, wpls3, wpls4; +l_int32 wpls5, wpls6, wpls7, wpls8; +l_int32 wpls9, wpls10, wpls11, wpls12; +l_int32 wpls13, wpls14, wpls15, wpls16; +l_int32 wpls17, wpls18, wpls19, wpls20; +l_int32 wpls21, wpls22; + + wpls2 = 2 * wpls; + wpls3 = 3 * wpls; + wpls4 = 4 * wpls; + wpls5 = 5 * wpls; + wpls6 = 6 * wpls; + wpls7 = 7 * wpls; + wpls8 = 8 * wpls; + wpls9 = 9 * wpls; + wpls10 = 10 * wpls; + wpls11 = 11 * wpls; + wpls12 = 12 * wpls; + wpls13 = 13 * wpls; + wpls14 = 14 * wpls; + wpls15 = 15 * wpls; + wpls16 = 16 * wpls; + wpls17 = 17 * wpls; + wpls18 = 18 * wpls; + wpls19 = 19 * wpls; + wpls20 = 20 * wpls; + wpls21 = 21 * wpls; + wpls22 = 22 * wpls; + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = (*(sptr - wpls22)) & + (*(sptr - wpls21)) & + (*(sptr - wpls20)) & + (*(sptr - wpls19)) & + (*(sptr - wpls18)) & + (*(sptr - wpls17)) & + (*(sptr - wpls16)) & + (*(sptr - wpls15)) & + (*(sptr - wpls14)) & + (*(sptr - wpls13)) & + (*(sptr - wpls12)) & + (*(sptr - wpls11)) & + (*(sptr - wpls10)) & + (*(sptr - wpls9)) & + (*(sptr - wpls8)) & + (*(sptr - wpls7)) & + (*(sptr - wpls6)) & + (*(sptr - wpls5)) & + (*(sptr - wpls4)) & + (*(sptr - wpls3)) & + (*(sptr - wpls2)) & + (*(sptr - wpls)) & + (*sptr) & + (*(sptr + wpls)) & + (*(sptr + wpls2)) & + (*(sptr + wpls3)) & + (*(sptr + wpls4)) & + (*(sptr + wpls5)) & + (*(sptr + wpls6)) & + (*(sptr + wpls7)) & + (*(sptr + wpls8)) & + (*(sptr + wpls9)) & + (*(sptr + wpls10)) & + (*(sptr + wpls11)) & + (*(sptr + wpls12)) & + (*(sptr + wpls13)) & + (*(sptr + wpls14)) & + (*(sptr + wpls15)) & + (*(sptr + wpls16)) & + (*(sptr + wpls17)) & + (*(sptr + wpls18)) & + (*(sptr + wpls19)) & + (*(sptr + wpls20)) & + (*(sptr + wpls21)) & + (*(sptr + wpls22)); + } + } +} + +static void +fdilate_3_106(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; +l_int32 wpls2, wpls3, wpls4; +l_int32 wpls5, wpls6, wpls7, wpls8; +l_int32 wpls9, wpls10, wpls11, wpls12; +l_int32 wpls13, wpls14, wpls15, wpls16; +l_int32 wpls17, wpls18, wpls19, wpls20; +l_int32 wpls21, wpls22, wpls23; + + wpls2 = 2 * wpls; + wpls3 = 3 * wpls; + wpls4 = 4 * wpls; + wpls5 = 5 * wpls; + wpls6 = 6 * wpls; + wpls7 = 7 * wpls; + wpls8 = 8 * wpls; + wpls9 = 9 * wpls; + wpls10 = 10 * wpls; + wpls11 = 11 * wpls; + wpls12 = 12 * wpls; + wpls13 = 13 * wpls; + wpls14 = 14 * wpls; + wpls15 = 15 * wpls; + wpls16 = 16 * wpls; + wpls17 = 17 * wpls; + wpls18 = 18 * wpls; + wpls19 = 19 * wpls; + wpls20 = 20 * wpls; + wpls21 = 21 * wpls; + wpls22 = 22 * wpls; + wpls23 = 23 * wpls; + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = (*(sptr + wpls23)) | + (*(sptr + wpls22)) | + (*(sptr + wpls21)) | + (*(sptr + wpls20)) | + (*(sptr + wpls19)) | + (*(sptr + wpls18)) | + (*(sptr + wpls17)) | + (*(sptr + wpls16)) | + (*(sptr + wpls15)) | + (*(sptr + wpls14)) | + (*(sptr + wpls13)) | + (*(sptr + wpls12)) | + (*(sptr + wpls11)) | + (*(sptr + wpls10)) | + (*(sptr + wpls9)) | + (*(sptr + wpls8)) | + (*(sptr + wpls7)) | + (*(sptr + wpls6)) | + (*(sptr + wpls5)) | + (*(sptr + wpls4)) | + (*(sptr + wpls3)) | + (*(sptr + wpls2)) | + (*(sptr + wpls)) | + (*sptr) | + (*(sptr - wpls)) | + (*(sptr - wpls2)) | + (*(sptr - wpls3)) | + (*(sptr - wpls4)) | + (*(sptr - wpls5)) | + (*(sptr - wpls6)) | + (*(sptr - wpls7)) | + (*(sptr - wpls8)) | + (*(sptr - wpls9)) | + (*(sptr - wpls10)) | + (*(sptr - wpls11)) | + (*(sptr - wpls12)) | + (*(sptr - wpls13)) | + (*(sptr - wpls14)) | + (*(sptr - wpls15)) | + (*(sptr - wpls16)) | + (*(sptr - wpls17)) | + (*(sptr - wpls18)) | + (*(sptr - wpls19)) | + (*(sptr - wpls20)) | + (*(sptr - wpls21)) | + (*(sptr - wpls22)); + } + } +} + +static void +ferode_3_106(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; +l_int32 wpls2, wpls3, wpls4; +l_int32 wpls5, wpls6, wpls7, wpls8; +l_int32 wpls9, wpls10, wpls11, wpls12; +l_int32 wpls13, wpls14, wpls15, wpls16; +l_int32 wpls17, wpls18, wpls19, wpls20; +l_int32 wpls21, wpls22, wpls23; + + wpls2 = 2 * wpls; + wpls3 = 3 * wpls; + wpls4 = 4 * wpls; + wpls5 = 5 * wpls; + wpls6 = 6 * wpls; + wpls7 = 7 * wpls; + wpls8 = 8 * wpls; + wpls9 = 9 * wpls; + wpls10 = 10 * wpls; + wpls11 = 11 * wpls; + wpls12 = 12 * wpls; + wpls13 = 13 * wpls; + wpls14 = 14 * wpls; + wpls15 = 15 * wpls; + wpls16 = 16 * wpls; + wpls17 = 17 * wpls; + wpls18 = 18 * wpls; + wpls19 = 19 * wpls; + wpls20 = 20 * wpls; + wpls21 = 21 * wpls; + wpls22 = 22 * wpls; + wpls23 = 23 * wpls; + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = (*(sptr - wpls23)) & + (*(sptr - wpls22)) & + (*(sptr - wpls21)) & + (*(sptr - wpls20)) & + (*(sptr - wpls19)) & + (*(sptr - wpls18)) & + (*(sptr - wpls17)) & + (*(sptr - wpls16)) & + (*(sptr - wpls15)) & + (*(sptr - wpls14)) & + (*(sptr - wpls13)) & + (*(sptr - wpls12)) & + (*(sptr - wpls11)) & + (*(sptr - wpls10)) & + (*(sptr - wpls9)) & + (*(sptr - wpls8)) & + (*(sptr - wpls7)) & + (*(sptr - wpls6)) & + (*(sptr - wpls5)) & + (*(sptr - wpls4)) & + (*(sptr - wpls3)) & + (*(sptr - wpls2)) & + (*(sptr - wpls)) & + (*sptr) & + (*(sptr + wpls)) & + (*(sptr + wpls2)) & + (*(sptr + wpls3)) & + (*(sptr + wpls4)) & + (*(sptr + wpls5)) & + (*(sptr + wpls6)) & + (*(sptr + wpls7)) & + (*(sptr + wpls8)) & + (*(sptr + wpls9)) & + (*(sptr + wpls10)) & + (*(sptr + wpls11)) & + (*(sptr + wpls12)) & + (*(sptr + wpls13)) & + (*(sptr + wpls14)) & + (*(sptr + wpls15)) & + (*(sptr + wpls16)) & + (*(sptr + wpls17)) & + (*(sptr + wpls18)) & + (*(sptr + wpls19)) & + (*(sptr + wpls20)) & + (*(sptr + wpls21)) & + (*(sptr + wpls22)); + } + } +} + +static void +fdilate_3_107(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; +l_int32 wpls2, wpls3, wpls4; +l_int32 wpls5, wpls6, wpls7, wpls8; +l_int32 wpls9, wpls10, wpls11, wpls12; +l_int32 wpls13, wpls14, wpls15, wpls16; +l_int32 wpls17, wpls18, wpls19, wpls20; +l_int32 wpls21, wpls22, wpls23; + + wpls2 = 2 * wpls; + wpls3 = 3 * wpls; + wpls4 = 4 * wpls; + wpls5 = 5 * wpls; + wpls6 = 6 * wpls; + wpls7 = 7 * wpls; + wpls8 = 8 * wpls; + wpls9 = 9 * wpls; + wpls10 = 10 * wpls; + wpls11 = 11 * wpls; + wpls12 = 12 * wpls; + wpls13 = 13 * wpls; + wpls14 = 14 * wpls; + wpls15 = 15 * wpls; + wpls16 = 16 * wpls; + wpls17 = 17 * wpls; + wpls18 = 18 * wpls; + wpls19 = 19 * wpls; + wpls20 = 20 * wpls; + wpls21 = 21 * wpls; + wpls22 = 22 * wpls; + wpls23 = 23 * wpls; + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = (*(sptr + wpls23)) | + (*(sptr + wpls22)) | + (*(sptr + wpls21)) | + (*(sptr + wpls20)) | + (*(sptr + wpls19)) | + (*(sptr + wpls18)) | + (*(sptr + wpls17)) | + (*(sptr + wpls16)) | + (*(sptr + wpls15)) | + (*(sptr + wpls14)) | + (*(sptr + wpls13)) | + (*(sptr + wpls12)) | + (*(sptr + wpls11)) | + (*(sptr + wpls10)) | + (*(sptr + wpls9)) | + (*(sptr + wpls8)) | + (*(sptr + wpls7)) | + (*(sptr + wpls6)) | + (*(sptr + wpls5)) | + (*(sptr + wpls4)) | + (*(sptr + wpls3)) | + (*(sptr + wpls2)) | + (*(sptr + wpls)) | + (*sptr) | + (*(sptr - wpls)) | + (*(sptr - wpls2)) | + (*(sptr - wpls3)) | + (*(sptr - wpls4)) | + (*(sptr - wpls5)) | + (*(sptr - wpls6)) | + (*(sptr - wpls7)) | + (*(sptr - wpls8)) | + (*(sptr - wpls9)) | + (*(sptr - wpls10)) | + (*(sptr - wpls11)) | + (*(sptr - wpls12)) | + (*(sptr - wpls13)) | + (*(sptr - wpls14)) | + (*(sptr - wpls15)) | + (*(sptr - wpls16)) | + (*(sptr - wpls17)) | + (*(sptr - wpls18)) | + (*(sptr - wpls19)) | + (*(sptr - wpls20)) | + (*(sptr - wpls21)) | + (*(sptr - wpls22)) | + (*(sptr - wpls23)); + } + } +} + +static void +ferode_3_107(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; +l_int32 wpls2, wpls3, wpls4; +l_int32 wpls5, wpls6, wpls7, wpls8; +l_int32 wpls9, wpls10, wpls11, wpls12; +l_int32 wpls13, wpls14, wpls15, wpls16; +l_int32 wpls17, wpls18, wpls19, wpls20; +l_int32 wpls21, wpls22, wpls23; + + wpls2 = 2 * wpls; + wpls3 = 3 * wpls; + wpls4 = 4 * wpls; + wpls5 = 5 * wpls; + wpls6 = 6 * wpls; + wpls7 = 7 * wpls; + wpls8 = 8 * wpls; + wpls9 = 9 * wpls; + wpls10 = 10 * wpls; + wpls11 = 11 * wpls; + wpls12 = 12 * wpls; + wpls13 = 13 * wpls; + wpls14 = 14 * wpls; + wpls15 = 15 * wpls; + wpls16 = 16 * wpls; + wpls17 = 17 * wpls; + wpls18 = 18 * wpls; + wpls19 = 19 * wpls; + wpls20 = 20 * wpls; + wpls21 = 21 * wpls; + wpls22 = 22 * wpls; + wpls23 = 23 * wpls; + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = (*(sptr - wpls23)) & + (*(sptr - wpls22)) & + (*(sptr - wpls21)) & + (*(sptr - wpls20)) & + (*(sptr - wpls19)) & + (*(sptr - wpls18)) & + (*(sptr - wpls17)) & + (*(sptr - wpls16)) & + (*(sptr - wpls15)) & + (*(sptr - wpls14)) & + (*(sptr - wpls13)) & + (*(sptr - wpls12)) & + (*(sptr - wpls11)) & + (*(sptr - wpls10)) & + (*(sptr - wpls9)) & + (*(sptr - wpls8)) & + (*(sptr - wpls7)) & + (*(sptr - wpls6)) & + (*(sptr - wpls5)) & + (*(sptr - wpls4)) & + (*(sptr - wpls3)) & + (*(sptr - wpls2)) & + (*(sptr - wpls)) & + (*sptr) & + (*(sptr + wpls)) & + (*(sptr + wpls2)) & + (*(sptr + wpls3)) & + (*(sptr + wpls4)) & + (*(sptr + wpls5)) & + (*(sptr + wpls6)) & + (*(sptr + wpls7)) & + (*(sptr + wpls8)) & + (*(sptr + wpls9)) & + (*(sptr + wpls10)) & + (*(sptr + wpls11)) & + (*(sptr + wpls12)) & + (*(sptr + wpls13)) & + (*(sptr + wpls14)) & + (*(sptr + wpls15)) & + (*(sptr + wpls16)) & + (*(sptr + wpls17)) & + (*(sptr + wpls18)) & + (*(sptr + wpls19)) & + (*(sptr + wpls20)) & + (*(sptr + wpls21)) & + (*(sptr + wpls22)) & + (*(sptr + wpls23)); + } + } +} + +static void +fdilate_3_108(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; +l_int32 wpls2, wpls3, wpls4; +l_int32 wpls5, wpls6, wpls7, wpls8; +l_int32 wpls9, wpls10, wpls11, wpls12; +l_int32 wpls13, wpls14, wpls15, wpls16; +l_int32 wpls17, wpls18, wpls19, wpls20; +l_int32 wpls21, wpls22, wpls23, wpls24; + + wpls2 = 2 * wpls; + wpls3 = 3 * wpls; + wpls4 = 4 * wpls; + wpls5 = 5 * wpls; + wpls6 = 6 * wpls; + wpls7 = 7 * wpls; + wpls8 = 8 * wpls; + wpls9 = 9 * wpls; + wpls10 = 10 * wpls; + wpls11 = 11 * wpls; + wpls12 = 12 * wpls; + wpls13 = 13 * wpls; + wpls14 = 14 * wpls; + wpls15 = 15 * wpls; + wpls16 = 16 * wpls; + wpls17 = 17 * wpls; + wpls18 = 18 * wpls; + wpls19 = 19 * wpls; + wpls20 = 20 * wpls; + wpls21 = 21 * wpls; + wpls22 = 22 * wpls; + wpls23 = 23 * wpls; + wpls24 = 24 * wpls; + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = (*(sptr + wpls24)) | + (*(sptr + wpls23)) | + (*(sptr + wpls22)) | + (*(sptr + wpls21)) | + (*(sptr + wpls20)) | + (*(sptr + wpls19)) | + (*(sptr + wpls18)) | + (*(sptr + wpls17)) | + (*(sptr + wpls16)) | + (*(sptr + wpls15)) | + (*(sptr + wpls14)) | + (*(sptr + wpls13)) | + (*(sptr + wpls12)) | + (*(sptr + wpls11)) | + (*(sptr + wpls10)) | + (*(sptr + wpls9)) | + (*(sptr + wpls8)) | + (*(sptr + wpls7)) | + (*(sptr + wpls6)) | + (*(sptr + wpls5)) | + (*(sptr + wpls4)) | + (*(sptr + wpls3)) | + (*(sptr + wpls2)) | + (*(sptr + wpls)) | + (*sptr) | + (*(sptr - wpls)) | + (*(sptr - wpls2)) | + (*(sptr - wpls3)) | + (*(sptr - wpls4)) | + (*(sptr - wpls5)) | + (*(sptr - wpls6)) | + (*(sptr - wpls7)) | + (*(sptr - wpls8)) | + (*(sptr - wpls9)) | + (*(sptr - wpls10)) | + (*(sptr - wpls11)) | + (*(sptr - wpls12)) | + (*(sptr - wpls13)) | + (*(sptr - wpls14)) | + (*(sptr - wpls15)) | + (*(sptr - wpls16)) | + (*(sptr - wpls17)) | + (*(sptr - wpls18)) | + (*(sptr - wpls19)) | + (*(sptr - wpls20)) | + (*(sptr - wpls21)) | + (*(sptr - wpls22)) | + (*(sptr - wpls23)); + } + } +} + +static void +ferode_3_108(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; +l_int32 wpls2, wpls3, wpls4; +l_int32 wpls5, wpls6, wpls7, wpls8; +l_int32 wpls9, wpls10, wpls11, wpls12; +l_int32 wpls13, wpls14, wpls15, wpls16; +l_int32 wpls17, wpls18, wpls19, wpls20; +l_int32 wpls21, wpls22, wpls23, wpls24; + + wpls2 = 2 * wpls; + wpls3 = 3 * wpls; + wpls4 = 4 * wpls; + wpls5 = 5 * wpls; + wpls6 = 6 * wpls; + wpls7 = 7 * wpls; + wpls8 = 8 * wpls; + wpls9 = 9 * wpls; + wpls10 = 10 * wpls; + wpls11 = 11 * wpls; + wpls12 = 12 * wpls; + wpls13 = 13 * wpls; + wpls14 = 14 * wpls; + wpls15 = 15 * wpls; + wpls16 = 16 * wpls; + wpls17 = 17 * wpls; + wpls18 = 18 * wpls; + wpls19 = 19 * wpls; + wpls20 = 20 * wpls; + wpls21 = 21 * wpls; + wpls22 = 22 * wpls; + wpls23 = 23 * wpls; + wpls24 = 24 * wpls; + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = (*(sptr - wpls24)) & + (*(sptr - wpls23)) & + (*(sptr - wpls22)) & + (*(sptr - wpls21)) & + (*(sptr - wpls20)) & + (*(sptr - wpls19)) & + (*(sptr - wpls18)) & + (*(sptr - wpls17)) & + (*(sptr - wpls16)) & + (*(sptr - wpls15)) & + (*(sptr - wpls14)) & + (*(sptr - wpls13)) & + (*(sptr - wpls12)) & + (*(sptr - wpls11)) & + (*(sptr - wpls10)) & + (*(sptr - wpls9)) & + (*(sptr - wpls8)) & + (*(sptr - wpls7)) & + (*(sptr - wpls6)) & + (*(sptr - wpls5)) & + (*(sptr - wpls4)) & + (*(sptr - wpls3)) & + (*(sptr - wpls2)) & + (*(sptr - wpls)) & + (*sptr) & + (*(sptr + wpls)) & + (*(sptr + wpls2)) & + (*(sptr + wpls3)) & + (*(sptr + wpls4)) & + (*(sptr + wpls5)) & + (*(sptr + wpls6)) & + (*(sptr + wpls7)) & + (*(sptr + wpls8)) & + (*(sptr + wpls9)) & + (*(sptr + wpls10)) & + (*(sptr + wpls11)) & + (*(sptr + wpls12)) & + (*(sptr + wpls13)) & + (*(sptr + wpls14)) & + (*(sptr + wpls15)) & + (*(sptr + wpls16)) & + (*(sptr + wpls17)) & + (*(sptr + wpls18)) & + (*(sptr + wpls19)) & + (*(sptr + wpls20)) & + (*(sptr + wpls21)) & + (*(sptr + wpls22)) & + (*(sptr + wpls23)); + } + } +} + +static void +fdilate_3_109(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; +l_int32 wpls2, wpls3, wpls4; +l_int32 wpls5, wpls6, wpls7, wpls8; +l_int32 wpls9, wpls10, wpls11, wpls12; +l_int32 wpls13, wpls14, wpls15, wpls16; +l_int32 wpls17, wpls18, wpls19, wpls20; +l_int32 wpls21, wpls22, wpls23, wpls24; + + wpls2 = 2 * wpls; + wpls3 = 3 * wpls; + wpls4 = 4 * wpls; + wpls5 = 5 * wpls; + wpls6 = 6 * wpls; + wpls7 = 7 * wpls; + wpls8 = 8 * wpls; + wpls9 = 9 * wpls; + wpls10 = 10 * wpls; + wpls11 = 11 * wpls; + wpls12 = 12 * wpls; + wpls13 = 13 * wpls; + wpls14 = 14 * wpls; + wpls15 = 15 * wpls; + wpls16 = 16 * wpls; + wpls17 = 17 * wpls; + wpls18 = 18 * wpls; + wpls19 = 19 * wpls; + wpls20 = 20 * wpls; + wpls21 = 21 * wpls; + wpls22 = 22 * wpls; + wpls23 = 23 * wpls; + wpls24 = 24 * wpls; + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = (*(sptr + wpls24)) | + (*(sptr + wpls23)) | + (*(sptr + wpls22)) | + (*(sptr + wpls21)) | + (*(sptr + wpls20)) | + (*(sptr + wpls19)) | + (*(sptr + wpls18)) | + (*(sptr + wpls17)) | + (*(sptr + wpls16)) | + (*(sptr + wpls15)) | + (*(sptr + wpls14)) | + (*(sptr + wpls13)) | + (*(sptr + wpls12)) | + (*(sptr + wpls11)) | + (*(sptr + wpls10)) | + (*(sptr + wpls9)) | + (*(sptr + wpls8)) | + (*(sptr + wpls7)) | + (*(sptr + wpls6)) | + (*(sptr + wpls5)) | + (*(sptr + wpls4)) | + (*(sptr + wpls3)) | + (*(sptr + wpls2)) | + (*(sptr + wpls)) | + (*sptr) | + (*(sptr - wpls)) | + (*(sptr - wpls2)) | + (*(sptr - wpls3)) | + (*(sptr - wpls4)) | + (*(sptr - wpls5)) | + (*(sptr - wpls6)) | + (*(sptr - wpls7)) | + (*(sptr - wpls8)) | + (*(sptr - wpls9)) | + (*(sptr - wpls10)) | + (*(sptr - wpls11)) | + (*(sptr - wpls12)) | + (*(sptr - wpls13)) | + (*(sptr - wpls14)) | + (*(sptr - wpls15)) | + (*(sptr - wpls16)) | + (*(sptr - wpls17)) | + (*(sptr - wpls18)) | + (*(sptr - wpls19)) | + (*(sptr - wpls20)) | + (*(sptr - wpls21)) | + (*(sptr - wpls22)) | + (*(sptr - wpls23)) | + (*(sptr - wpls24)); + } + } +} + +static void +ferode_3_109(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; +l_int32 wpls2, wpls3, wpls4; +l_int32 wpls5, wpls6, wpls7, wpls8; +l_int32 wpls9, wpls10, wpls11, wpls12; +l_int32 wpls13, wpls14, wpls15, wpls16; +l_int32 wpls17, wpls18, wpls19, wpls20; +l_int32 wpls21, wpls22, wpls23, wpls24; + + wpls2 = 2 * wpls; + wpls3 = 3 * wpls; + wpls4 = 4 * wpls; + wpls5 = 5 * wpls; + wpls6 = 6 * wpls; + wpls7 = 7 * wpls; + wpls8 = 8 * wpls; + wpls9 = 9 * wpls; + wpls10 = 10 * wpls; + wpls11 = 11 * wpls; + wpls12 = 12 * wpls; + wpls13 = 13 * wpls; + wpls14 = 14 * wpls; + wpls15 = 15 * wpls; + wpls16 = 16 * wpls; + wpls17 = 17 * wpls; + wpls18 = 18 * wpls; + wpls19 = 19 * wpls; + wpls20 = 20 * wpls; + wpls21 = 21 * wpls; + wpls22 = 22 * wpls; + wpls23 = 23 * wpls; + wpls24 = 24 * wpls; + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = (*(sptr - wpls24)) & + (*(sptr - wpls23)) & + (*(sptr - wpls22)) & + (*(sptr - wpls21)) & + (*(sptr - wpls20)) & + (*(sptr - wpls19)) & + (*(sptr - wpls18)) & + (*(sptr - wpls17)) & + (*(sptr - wpls16)) & + (*(sptr - wpls15)) & + (*(sptr - wpls14)) & + (*(sptr - wpls13)) & + (*(sptr - wpls12)) & + (*(sptr - wpls11)) & + (*(sptr - wpls10)) & + (*(sptr - wpls9)) & + (*(sptr - wpls8)) & + (*(sptr - wpls7)) & + (*(sptr - wpls6)) & + (*(sptr - wpls5)) & + (*(sptr - wpls4)) & + (*(sptr - wpls3)) & + (*(sptr - wpls2)) & + (*(sptr - wpls)) & + (*sptr) & + (*(sptr + wpls)) & + (*(sptr + wpls2)) & + (*(sptr + wpls3)) & + (*(sptr + wpls4)) & + (*(sptr + wpls5)) & + (*(sptr + wpls6)) & + (*(sptr + wpls7)) & + (*(sptr + wpls8)) & + (*(sptr + wpls9)) & + (*(sptr + wpls10)) & + (*(sptr + wpls11)) & + (*(sptr + wpls12)) & + (*(sptr + wpls13)) & + (*(sptr + wpls14)) & + (*(sptr + wpls15)) & + (*(sptr + wpls16)) & + (*(sptr + wpls17)) & + (*(sptr + wpls18)) & + (*(sptr + wpls19)) & + (*(sptr + wpls20)) & + (*(sptr + wpls21)) & + (*(sptr + wpls22)) & + (*(sptr + wpls23)) & + (*(sptr + wpls24)); + } + } +} + +static void +fdilate_3_110(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; +l_int32 wpls2, wpls3, wpls4; +l_int32 wpls5, wpls6, wpls7, wpls8; +l_int32 wpls9, wpls10, wpls11, wpls12; +l_int32 wpls13, wpls14, wpls15, wpls16; +l_int32 wpls17, wpls18, wpls19, wpls20; +l_int32 wpls21, wpls22, wpls23, wpls24; +l_int32 wpls25; + + wpls2 = 2 * wpls; + wpls3 = 3 * wpls; + wpls4 = 4 * wpls; + wpls5 = 5 * wpls; + wpls6 = 6 * wpls; + wpls7 = 7 * wpls; + wpls8 = 8 * wpls; + wpls9 = 9 * wpls; + wpls10 = 10 * wpls; + wpls11 = 11 * wpls; + wpls12 = 12 * wpls; + wpls13 = 13 * wpls; + wpls14 = 14 * wpls; + wpls15 = 15 * wpls; + wpls16 = 16 * wpls; + wpls17 = 17 * wpls; + wpls18 = 18 * wpls; + wpls19 = 19 * wpls; + wpls20 = 20 * wpls; + wpls21 = 21 * wpls; + wpls22 = 22 * wpls; + wpls23 = 23 * wpls; + wpls24 = 24 * wpls; + wpls25 = 25 * wpls; + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = (*(sptr + wpls25)) | + (*(sptr + wpls24)) | + (*(sptr + wpls23)) | + (*(sptr + wpls22)) | + (*(sptr + wpls21)) | + (*(sptr + wpls20)) | + (*(sptr + wpls19)) | + (*(sptr + wpls18)) | + (*(sptr + wpls17)) | + (*(sptr + wpls16)) | + (*(sptr + wpls15)) | + (*(sptr + wpls14)) | + (*(sptr + wpls13)) | + (*(sptr + wpls12)) | + (*(sptr + wpls11)) | + (*(sptr + wpls10)) | + (*(sptr + wpls9)) | + (*(sptr + wpls8)) | + (*(sptr + wpls7)) | + (*(sptr + wpls6)) | + (*(sptr + wpls5)) | + (*(sptr + wpls4)) | + (*(sptr + wpls3)) | + (*(sptr + wpls2)) | + (*(sptr + wpls)) | + (*sptr) | + (*(sptr - wpls)) | + (*(sptr - wpls2)) | + (*(sptr - wpls3)) | + (*(sptr - wpls4)) | + (*(sptr - wpls5)) | + (*(sptr - wpls6)) | + (*(sptr - wpls7)) | + (*(sptr - wpls8)) | + (*(sptr - wpls9)) | + (*(sptr - wpls10)) | + (*(sptr - wpls11)) | + (*(sptr - wpls12)) | + (*(sptr - wpls13)) | + (*(sptr - wpls14)) | + (*(sptr - wpls15)) | + (*(sptr - wpls16)) | + (*(sptr - wpls17)) | + (*(sptr - wpls18)) | + (*(sptr - wpls19)) | + (*(sptr - wpls20)) | + (*(sptr - wpls21)) | + (*(sptr - wpls22)) | + (*(sptr - wpls23)) | + (*(sptr - wpls24)); + } + } +} + +static void +ferode_3_110(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; +l_int32 wpls2, wpls3, wpls4; +l_int32 wpls5, wpls6, wpls7, wpls8; +l_int32 wpls9, wpls10, wpls11, wpls12; +l_int32 wpls13, wpls14, wpls15, wpls16; +l_int32 wpls17, wpls18, wpls19, wpls20; +l_int32 wpls21, wpls22, wpls23, wpls24; +l_int32 wpls25; + + wpls2 = 2 * wpls; + wpls3 = 3 * wpls; + wpls4 = 4 * wpls; + wpls5 = 5 * wpls; + wpls6 = 6 * wpls; + wpls7 = 7 * wpls; + wpls8 = 8 * wpls; + wpls9 = 9 * wpls; + wpls10 = 10 * wpls; + wpls11 = 11 * wpls; + wpls12 = 12 * wpls; + wpls13 = 13 * wpls; + wpls14 = 14 * wpls; + wpls15 = 15 * wpls; + wpls16 = 16 * wpls; + wpls17 = 17 * wpls; + wpls18 = 18 * wpls; + wpls19 = 19 * wpls; + wpls20 = 20 * wpls; + wpls21 = 21 * wpls; + wpls22 = 22 * wpls; + wpls23 = 23 * wpls; + wpls24 = 24 * wpls; + wpls25 = 25 * wpls; + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = (*(sptr - wpls25)) & + (*(sptr - wpls24)) & + (*(sptr - wpls23)) & + (*(sptr - wpls22)) & + (*(sptr - wpls21)) & + (*(sptr - wpls20)) & + (*(sptr - wpls19)) & + (*(sptr - wpls18)) & + (*(sptr - wpls17)) & + (*(sptr - wpls16)) & + (*(sptr - wpls15)) & + (*(sptr - wpls14)) & + (*(sptr - wpls13)) & + (*(sptr - wpls12)) & + (*(sptr - wpls11)) & + (*(sptr - wpls10)) & + (*(sptr - wpls9)) & + (*(sptr - wpls8)) & + (*(sptr - wpls7)) & + (*(sptr - wpls6)) & + (*(sptr - wpls5)) & + (*(sptr - wpls4)) & + (*(sptr - wpls3)) & + (*(sptr - wpls2)) & + (*(sptr - wpls)) & + (*sptr) & + (*(sptr + wpls)) & + (*(sptr + wpls2)) & + (*(sptr + wpls3)) & + (*(sptr + wpls4)) & + (*(sptr + wpls5)) & + (*(sptr + wpls6)) & + (*(sptr + wpls7)) & + (*(sptr + wpls8)) & + (*(sptr + wpls9)) & + (*(sptr + wpls10)) & + (*(sptr + wpls11)) & + (*(sptr + wpls12)) & + (*(sptr + wpls13)) & + (*(sptr + wpls14)) & + (*(sptr + wpls15)) & + (*(sptr + wpls16)) & + (*(sptr + wpls17)) & + (*(sptr + wpls18)) & + (*(sptr + wpls19)) & + (*(sptr + wpls20)) & + (*(sptr + wpls21)) & + (*(sptr + wpls22)) & + (*(sptr + wpls23)) & + (*(sptr + wpls24)); + } + } +} + +static void +fdilate_3_111(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; +l_int32 wpls2, wpls3, wpls4; +l_int32 wpls5, wpls6, wpls7, wpls8; +l_int32 wpls9, wpls10, wpls11, wpls12; +l_int32 wpls13, wpls14, wpls15, wpls16; +l_int32 wpls17, wpls18, wpls19, wpls20; +l_int32 wpls21, wpls22, wpls23, wpls24; +l_int32 wpls25; + + wpls2 = 2 * wpls; + wpls3 = 3 * wpls; + wpls4 = 4 * wpls; + wpls5 = 5 * wpls; + wpls6 = 6 * wpls; + wpls7 = 7 * wpls; + wpls8 = 8 * wpls; + wpls9 = 9 * wpls; + wpls10 = 10 * wpls; + wpls11 = 11 * wpls; + wpls12 = 12 * wpls; + wpls13 = 13 * wpls; + wpls14 = 14 * wpls; + wpls15 = 15 * wpls; + wpls16 = 16 * wpls; + wpls17 = 17 * wpls; + wpls18 = 18 * wpls; + wpls19 = 19 * wpls; + wpls20 = 20 * wpls; + wpls21 = 21 * wpls; + wpls22 = 22 * wpls; + wpls23 = 23 * wpls; + wpls24 = 24 * wpls; + wpls25 = 25 * wpls; + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = (*(sptr + wpls25)) | + (*(sptr + wpls24)) | + (*(sptr + wpls23)) | + (*(sptr + wpls22)) | + (*(sptr + wpls21)) | + (*(sptr + wpls20)) | + (*(sptr + wpls19)) | + (*(sptr + wpls18)) | + (*(sptr + wpls17)) | + (*(sptr + wpls16)) | + (*(sptr + wpls15)) | + (*(sptr + wpls14)) | + (*(sptr + wpls13)) | + (*(sptr + wpls12)) | + (*(sptr + wpls11)) | + (*(sptr + wpls10)) | + (*(sptr + wpls9)) | + (*(sptr + wpls8)) | + (*(sptr + wpls7)) | + (*(sptr + wpls6)) | + (*(sptr + wpls5)) | + (*(sptr + wpls4)) | + (*(sptr + wpls3)) | + (*(sptr + wpls2)) | + (*(sptr + wpls)) | + (*sptr) | + (*(sptr - wpls)) | + (*(sptr - wpls2)) | + (*(sptr - wpls3)) | + (*(sptr - wpls4)) | + (*(sptr - wpls5)) | + (*(sptr - wpls6)) | + (*(sptr - wpls7)) | + (*(sptr - wpls8)) | + (*(sptr - wpls9)) | + (*(sptr - wpls10)) | + (*(sptr - wpls11)) | + (*(sptr - wpls12)) | + (*(sptr - wpls13)) | + (*(sptr - wpls14)) | + (*(sptr - wpls15)) | + (*(sptr - wpls16)) | + (*(sptr - wpls17)) | + (*(sptr - wpls18)) | + (*(sptr - wpls19)) | + (*(sptr - wpls20)) | + (*(sptr - wpls21)) | + (*(sptr - wpls22)) | + (*(sptr - wpls23)) | + (*(sptr - wpls24)) | + (*(sptr - wpls25)); + } + } +} + +static void +ferode_3_111(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; +l_int32 wpls2, wpls3, wpls4; +l_int32 wpls5, wpls6, wpls7, wpls8; +l_int32 wpls9, wpls10, wpls11, wpls12; +l_int32 wpls13, wpls14, wpls15, wpls16; +l_int32 wpls17, wpls18, wpls19, wpls20; +l_int32 wpls21, wpls22, wpls23, wpls24; +l_int32 wpls25; + + wpls2 = 2 * wpls; + wpls3 = 3 * wpls; + wpls4 = 4 * wpls; + wpls5 = 5 * wpls; + wpls6 = 6 * wpls; + wpls7 = 7 * wpls; + wpls8 = 8 * wpls; + wpls9 = 9 * wpls; + wpls10 = 10 * wpls; + wpls11 = 11 * wpls; + wpls12 = 12 * wpls; + wpls13 = 13 * wpls; + wpls14 = 14 * wpls; + wpls15 = 15 * wpls; + wpls16 = 16 * wpls; + wpls17 = 17 * wpls; + wpls18 = 18 * wpls; + wpls19 = 19 * wpls; + wpls20 = 20 * wpls; + wpls21 = 21 * wpls; + wpls22 = 22 * wpls; + wpls23 = 23 * wpls; + wpls24 = 24 * wpls; + wpls25 = 25 * wpls; + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = (*(sptr - wpls25)) & + (*(sptr - wpls24)) & + (*(sptr - wpls23)) & + (*(sptr - wpls22)) & + (*(sptr - wpls21)) & + (*(sptr - wpls20)) & + (*(sptr - wpls19)) & + (*(sptr - wpls18)) & + (*(sptr - wpls17)) & + (*(sptr - wpls16)) & + (*(sptr - wpls15)) & + (*(sptr - wpls14)) & + (*(sptr - wpls13)) & + (*(sptr - wpls12)) & + (*(sptr - wpls11)) & + (*(sptr - wpls10)) & + (*(sptr - wpls9)) & + (*(sptr - wpls8)) & + (*(sptr - wpls7)) & + (*(sptr - wpls6)) & + (*(sptr - wpls5)) & + (*(sptr - wpls4)) & + (*(sptr - wpls3)) & + (*(sptr - wpls2)) & + (*(sptr - wpls)) & + (*sptr) & + (*(sptr + wpls)) & + (*(sptr + wpls2)) & + (*(sptr + wpls3)) & + (*(sptr + wpls4)) & + (*(sptr + wpls5)) & + (*(sptr + wpls6)) & + (*(sptr + wpls7)) & + (*(sptr + wpls8)) & + (*(sptr + wpls9)) & + (*(sptr + wpls10)) & + (*(sptr + wpls11)) & + (*(sptr + wpls12)) & + (*(sptr + wpls13)) & + (*(sptr + wpls14)) & + (*(sptr + wpls15)) & + (*(sptr + wpls16)) & + (*(sptr + wpls17)) & + (*(sptr + wpls18)) & + (*(sptr + wpls19)) & + (*(sptr + wpls20)) & + (*(sptr + wpls21)) & + (*(sptr + wpls22)) & + (*(sptr + wpls23)) & + (*(sptr + wpls24)) & + (*(sptr + wpls25)); + } + } +} + +static void +fdilate_3_112(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; +l_int32 wpls2, wpls3, wpls4; +l_int32 wpls5, wpls6, wpls7, wpls8; +l_int32 wpls9, wpls10, wpls11, wpls12; +l_int32 wpls13, wpls14, wpls15, wpls16; +l_int32 wpls17, wpls18, wpls19, wpls20; +l_int32 wpls21, wpls22, wpls23, wpls24; +l_int32 wpls25, wpls26; + + wpls2 = 2 * wpls; + wpls3 = 3 * wpls; + wpls4 = 4 * wpls; + wpls5 = 5 * wpls; + wpls6 = 6 * wpls; + wpls7 = 7 * wpls; + wpls8 = 8 * wpls; + wpls9 = 9 * wpls; + wpls10 = 10 * wpls; + wpls11 = 11 * wpls; + wpls12 = 12 * wpls; + wpls13 = 13 * wpls; + wpls14 = 14 * wpls; + wpls15 = 15 * wpls; + wpls16 = 16 * wpls; + wpls17 = 17 * wpls; + wpls18 = 18 * wpls; + wpls19 = 19 * wpls; + wpls20 = 20 * wpls; + wpls21 = 21 * wpls; + wpls22 = 22 * wpls; + wpls23 = 23 * wpls; + wpls24 = 24 * wpls; + wpls25 = 25 * wpls; + wpls26 = 26 * wpls; + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = (*(sptr + wpls26)) | + (*(sptr + wpls25)) | + (*(sptr + wpls24)) | + (*(sptr + wpls23)) | + (*(sptr + wpls22)) | + (*(sptr + wpls21)) | + (*(sptr + wpls20)) | + (*(sptr + wpls19)) | + (*(sptr + wpls18)) | + (*(sptr + wpls17)) | + (*(sptr + wpls16)) | + (*(sptr + wpls15)) | + (*(sptr + wpls14)) | + (*(sptr + wpls13)) | + (*(sptr + wpls12)) | + (*(sptr + wpls11)) | + (*(sptr + wpls10)) | + (*(sptr + wpls9)) | + (*(sptr + wpls8)) | + (*(sptr + wpls7)) | + (*(sptr + wpls6)) | + (*(sptr + wpls5)) | + (*(sptr + wpls4)) | + (*(sptr + wpls3)) | + (*(sptr + wpls2)) | + (*(sptr + wpls)) | + (*sptr) | + (*(sptr - wpls)) | + (*(sptr - wpls2)) | + (*(sptr - wpls3)) | + (*(sptr - wpls4)) | + (*(sptr - wpls5)) | + (*(sptr - wpls6)) | + (*(sptr - wpls7)) | + (*(sptr - wpls8)) | + (*(sptr - wpls9)) | + (*(sptr - wpls10)) | + (*(sptr - wpls11)) | + (*(sptr - wpls12)) | + (*(sptr - wpls13)) | + (*(sptr - wpls14)) | + (*(sptr - wpls15)) | + (*(sptr - wpls16)) | + (*(sptr - wpls17)) | + (*(sptr - wpls18)) | + (*(sptr - wpls19)) | + (*(sptr - wpls20)) | + (*(sptr - wpls21)) | + (*(sptr - wpls22)) | + (*(sptr - wpls23)) | + (*(sptr - wpls24)) | + (*(sptr - wpls25)); + } + } +} + +static void +ferode_3_112(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; +l_int32 wpls2, wpls3, wpls4; +l_int32 wpls5, wpls6, wpls7, wpls8; +l_int32 wpls9, wpls10, wpls11, wpls12; +l_int32 wpls13, wpls14, wpls15, wpls16; +l_int32 wpls17, wpls18, wpls19, wpls20; +l_int32 wpls21, wpls22, wpls23, wpls24; +l_int32 wpls25, wpls26; + + wpls2 = 2 * wpls; + wpls3 = 3 * wpls; + wpls4 = 4 * wpls; + wpls5 = 5 * wpls; + wpls6 = 6 * wpls; + wpls7 = 7 * wpls; + wpls8 = 8 * wpls; + wpls9 = 9 * wpls; + wpls10 = 10 * wpls; + wpls11 = 11 * wpls; + wpls12 = 12 * wpls; + wpls13 = 13 * wpls; + wpls14 = 14 * wpls; + wpls15 = 15 * wpls; + wpls16 = 16 * wpls; + wpls17 = 17 * wpls; + wpls18 = 18 * wpls; + wpls19 = 19 * wpls; + wpls20 = 20 * wpls; + wpls21 = 21 * wpls; + wpls22 = 22 * wpls; + wpls23 = 23 * wpls; + wpls24 = 24 * wpls; + wpls25 = 25 * wpls; + wpls26 = 26 * wpls; + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = (*(sptr - wpls26)) & + (*(sptr - wpls25)) & + (*(sptr - wpls24)) & + (*(sptr - wpls23)) & + (*(sptr - wpls22)) & + (*(sptr - wpls21)) & + (*(sptr - wpls20)) & + (*(sptr - wpls19)) & + (*(sptr - wpls18)) & + (*(sptr - wpls17)) & + (*(sptr - wpls16)) & + (*(sptr - wpls15)) & + (*(sptr - wpls14)) & + (*(sptr - wpls13)) & + (*(sptr - wpls12)) & + (*(sptr - wpls11)) & + (*(sptr - wpls10)) & + (*(sptr - wpls9)) & + (*(sptr - wpls8)) & + (*(sptr - wpls7)) & + (*(sptr - wpls6)) & + (*(sptr - wpls5)) & + (*(sptr - wpls4)) & + (*(sptr - wpls3)) & + (*(sptr - wpls2)) & + (*(sptr - wpls)) & + (*sptr) & + (*(sptr + wpls)) & + (*(sptr + wpls2)) & + (*(sptr + wpls3)) & + (*(sptr + wpls4)) & + (*(sptr + wpls5)) & + (*(sptr + wpls6)) & + (*(sptr + wpls7)) & + (*(sptr + wpls8)) & + (*(sptr + wpls9)) & + (*(sptr + wpls10)) & + (*(sptr + wpls11)) & + (*(sptr + wpls12)) & + (*(sptr + wpls13)) & + (*(sptr + wpls14)) & + (*(sptr + wpls15)) & + (*(sptr + wpls16)) & + (*(sptr + wpls17)) & + (*(sptr + wpls18)) & + (*(sptr + wpls19)) & + (*(sptr + wpls20)) & + (*(sptr + wpls21)) & + (*(sptr + wpls22)) & + (*(sptr + wpls23)) & + (*(sptr + wpls24)) & + (*(sptr + wpls25)); + } + } +} + +static void +fdilate_3_113(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; +l_int32 wpls2, wpls3, wpls4; +l_int32 wpls5, wpls6, wpls7, wpls8; +l_int32 wpls9, wpls10, wpls11, wpls12; +l_int32 wpls13, wpls14, wpls15, wpls16; +l_int32 wpls17, wpls18, wpls19, wpls20; +l_int32 wpls21, wpls22, wpls23, wpls24; +l_int32 wpls25, wpls26; + + wpls2 = 2 * wpls; + wpls3 = 3 * wpls; + wpls4 = 4 * wpls; + wpls5 = 5 * wpls; + wpls6 = 6 * wpls; + wpls7 = 7 * wpls; + wpls8 = 8 * wpls; + wpls9 = 9 * wpls; + wpls10 = 10 * wpls; + wpls11 = 11 * wpls; + wpls12 = 12 * wpls; + wpls13 = 13 * wpls; + wpls14 = 14 * wpls; + wpls15 = 15 * wpls; + wpls16 = 16 * wpls; + wpls17 = 17 * wpls; + wpls18 = 18 * wpls; + wpls19 = 19 * wpls; + wpls20 = 20 * wpls; + wpls21 = 21 * wpls; + wpls22 = 22 * wpls; + wpls23 = 23 * wpls; + wpls24 = 24 * wpls; + wpls25 = 25 * wpls; + wpls26 = 26 * wpls; + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = (*(sptr + wpls26)) | + (*(sptr + wpls25)) | + (*(sptr + wpls24)) | + (*(sptr + wpls23)) | + (*(sptr + wpls22)) | + (*(sptr + wpls21)) | + (*(sptr + wpls20)) | + (*(sptr + wpls19)) | + (*(sptr + wpls18)) | + (*(sptr + wpls17)) | + (*(sptr + wpls16)) | + (*(sptr + wpls15)) | + (*(sptr + wpls14)) | + (*(sptr + wpls13)) | + (*(sptr + wpls12)) | + (*(sptr + wpls11)) | + (*(sptr + wpls10)) | + (*(sptr + wpls9)) | + (*(sptr + wpls8)) | + (*(sptr + wpls7)) | + (*(sptr + wpls6)) | + (*(sptr + wpls5)) | + (*(sptr + wpls4)) | + (*(sptr + wpls3)) | + (*(sptr + wpls2)) | + (*(sptr + wpls)) | + (*sptr) | + (*(sptr - wpls)) | + (*(sptr - wpls2)) | + (*(sptr - wpls3)) | + (*(sptr - wpls4)) | + (*(sptr - wpls5)) | + (*(sptr - wpls6)) | + (*(sptr - wpls7)) | + (*(sptr - wpls8)) | + (*(sptr - wpls9)) | + (*(sptr - wpls10)) | + (*(sptr - wpls11)) | + (*(sptr - wpls12)) | + (*(sptr - wpls13)) | + (*(sptr - wpls14)) | + (*(sptr - wpls15)) | + (*(sptr - wpls16)) | + (*(sptr - wpls17)) | + (*(sptr - wpls18)) | + (*(sptr - wpls19)) | + (*(sptr - wpls20)) | + (*(sptr - wpls21)) | + (*(sptr - wpls22)) | + (*(sptr - wpls23)) | + (*(sptr - wpls24)) | + (*(sptr - wpls25)) | + (*(sptr - wpls26)); + } + } +} + +static void +ferode_3_113(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; +l_int32 wpls2, wpls3, wpls4; +l_int32 wpls5, wpls6, wpls7, wpls8; +l_int32 wpls9, wpls10, wpls11, wpls12; +l_int32 wpls13, wpls14, wpls15, wpls16; +l_int32 wpls17, wpls18, wpls19, wpls20; +l_int32 wpls21, wpls22, wpls23, wpls24; +l_int32 wpls25, wpls26; + + wpls2 = 2 * wpls; + wpls3 = 3 * wpls; + wpls4 = 4 * wpls; + wpls5 = 5 * wpls; + wpls6 = 6 * wpls; + wpls7 = 7 * wpls; + wpls8 = 8 * wpls; + wpls9 = 9 * wpls; + wpls10 = 10 * wpls; + wpls11 = 11 * wpls; + wpls12 = 12 * wpls; + wpls13 = 13 * wpls; + wpls14 = 14 * wpls; + wpls15 = 15 * wpls; + wpls16 = 16 * wpls; + wpls17 = 17 * wpls; + wpls18 = 18 * wpls; + wpls19 = 19 * wpls; + wpls20 = 20 * wpls; + wpls21 = 21 * wpls; + wpls22 = 22 * wpls; + wpls23 = 23 * wpls; + wpls24 = 24 * wpls; + wpls25 = 25 * wpls; + wpls26 = 26 * wpls; + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = (*(sptr - wpls26)) & + (*(sptr - wpls25)) & + (*(sptr - wpls24)) & + (*(sptr - wpls23)) & + (*(sptr - wpls22)) & + (*(sptr - wpls21)) & + (*(sptr - wpls20)) & + (*(sptr - wpls19)) & + (*(sptr - wpls18)) & + (*(sptr - wpls17)) & + (*(sptr - wpls16)) & + (*(sptr - wpls15)) & + (*(sptr - wpls14)) & + (*(sptr - wpls13)) & + (*(sptr - wpls12)) & + (*(sptr - wpls11)) & + (*(sptr - wpls10)) & + (*(sptr - wpls9)) & + (*(sptr - wpls8)) & + (*(sptr - wpls7)) & + (*(sptr - wpls6)) & + (*(sptr - wpls5)) & + (*(sptr - wpls4)) & + (*(sptr - wpls3)) & + (*(sptr - wpls2)) & + (*(sptr - wpls)) & + (*sptr) & + (*(sptr + wpls)) & + (*(sptr + wpls2)) & + (*(sptr + wpls3)) & + (*(sptr + wpls4)) & + (*(sptr + wpls5)) & + (*(sptr + wpls6)) & + (*(sptr + wpls7)) & + (*(sptr + wpls8)) & + (*(sptr + wpls9)) & + (*(sptr + wpls10)) & + (*(sptr + wpls11)) & + (*(sptr + wpls12)) & + (*(sptr + wpls13)) & + (*(sptr + wpls14)) & + (*(sptr + wpls15)) & + (*(sptr + wpls16)) & + (*(sptr + wpls17)) & + (*(sptr + wpls18)) & + (*(sptr + wpls19)) & + (*(sptr + wpls20)) & + (*(sptr + wpls21)) & + (*(sptr + wpls22)) & + (*(sptr + wpls23)) & + (*(sptr + wpls24)) & + (*(sptr + wpls25)) & + (*(sptr + wpls26)); + } + } +} + +static void +fdilate_3_114(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; +l_int32 wpls2, wpls3, wpls4; +l_int32 wpls5, wpls6, wpls7, wpls8; +l_int32 wpls9, wpls10, wpls11, wpls12; +l_int32 wpls13, wpls14, wpls15, wpls16; +l_int32 wpls17, wpls18, wpls19, wpls20; +l_int32 wpls21, wpls22, wpls23, wpls24; +l_int32 wpls25, wpls26, wpls27; + + wpls2 = 2 * wpls; + wpls3 = 3 * wpls; + wpls4 = 4 * wpls; + wpls5 = 5 * wpls; + wpls6 = 6 * wpls; + wpls7 = 7 * wpls; + wpls8 = 8 * wpls; + wpls9 = 9 * wpls; + wpls10 = 10 * wpls; + wpls11 = 11 * wpls; + wpls12 = 12 * wpls; + wpls13 = 13 * wpls; + wpls14 = 14 * wpls; + wpls15 = 15 * wpls; + wpls16 = 16 * wpls; + wpls17 = 17 * wpls; + wpls18 = 18 * wpls; + wpls19 = 19 * wpls; + wpls20 = 20 * wpls; + wpls21 = 21 * wpls; + wpls22 = 22 * wpls; + wpls23 = 23 * wpls; + wpls24 = 24 * wpls; + wpls25 = 25 * wpls; + wpls26 = 26 * wpls; + wpls27 = 27 * wpls; + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = (*(sptr + wpls27)) | + (*(sptr + wpls26)) | + (*(sptr + wpls25)) | + (*(sptr + wpls24)) | + (*(sptr + wpls23)) | + (*(sptr + wpls22)) | + (*(sptr + wpls21)) | + (*(sptr + wpls20)) | + (*(sptr + wpls19)) | + (*(sptr + wpls18)) | + (*(sptr + wpls17)) | + (*(sptr + wpls16)) | + (*(sptr + wpls15)) | + (*(sptr + wpls14)) | + (*(sptr + wpls13)) | + (*(sptr + wpls12)) | + (*(sptr + wpls11)) | + (*(sptr + wpls10)) | + (*(sptr + wpls9)) | + (*(sptr + wpls8)) | + (*(sptr + wpls7)) | + (*(sptr + wpls6)) | + (*(sptr + wpls5)) | + (*(sptr + wpls4)) | + (*(sptr + wpls3)) | + (*(sptr + wpls2)) | + (*(sptr + wpls)) | + (*sptr) | + (*(sptr - wpls)) | + (*(sptr - wpls2)) | + (*(sptr - wpls3)) | + (*(sptr - wpls4)) | + (*(sptr - wpls5)) | + (*(sptr - wpls6)) | + (*(sptr - wpls7)) | + (*(sptr - wpls8)) | + (*(sptr - wpls9)) | + (*(sptr - wpls10)) | + (*(sptr - wpls11)) | + (*(sptr - wpls12)) | + (*(sptr - wpls13)) | + (*(sptr - wpls14)) | + (*(sptr - wpls15)) | + (*(sptr - wpls16)) | + (*(sptr - wpls17)) | + (*(sptr - wpls18)) | + (*(sptr - wpls19)) | + (*(sptr - wpls20)) | + (*(sptr - wpls21)) | + (*(sptr - wpls22)) | + (*(sptr - wpls23)) | + (*(sptr - wpls24)) | + (*(sptr - wpls25)) | + (*(sptr - wpls26)); + } + } +} + +static void +ferode_3_114(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; +l_int32 wpls2, wpls3, wpls4; +l_int32 wpls5, wpls6, wpls7, wpls8; +l_int32 wpls9, wpls10, wpls11, wpls12; +l_int32 wpls13, wpls14, wpls15, wpls16; +l_int32 wpls17, wpls18, wpls19, wpls20; +l_int32 wpls21, wpls22, wpls23, wpls24; +l_int32 wpls25, wpls26, wpls27; + + wpls2 = 2 * wpls; + wpls3 = 3 * wpls; + wpls4 = 4 * wpls; + wpls5 = 5 * wpls; + wpls6 = 6 * wpls; + wpls7 = 7 * wpls; + wpls8 = 8 * wpls; + wpls9 = 9 * wpls; + wpls10 = 10 * wpls; + wpls11 = 11 * wpls; + wpls12 = 12 * wpls; + wpls13 = 13 * wpls; + wpls14 = 14 * wpls; + wpls15 = 15 * wpls; + wpls16 = 16 * wpls; + wpls17 = 17 * wpls; + wpls18 = 18 * wpls; + wpls19 = 19 * wpls; + wpls20 = 20 * wpls; + wpls21 = 21 * wpls; + wpls22 = 22 * wpls; + wpls23 = 23 * wpls; + wpls24 = 24 * wpls; + wpls25 = 25 * wpls; + wpls26 = 26 * wpls; + wpls27 = 27 * wpls; + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = (*(sptr - wpls27)) & + (*(sptr - wpls26)) & + (*(sptr - wpls25)) & + (*(sptr - wpls24)) & + (*(sptr - wpls23)) & + (*(sptr - wpls22)) & + (*(sptr - wpls21)) & + (*(sptr - wpls20)) & + (*(sptr - wpls19)) & + (*(sptr - wpls18)) & + (*(sptr - wpls17)) & + (*(sptr - wpls16)) & + (*(sptr - wpls15)) & + (*(sptr - wpls14)) & + (*(sptr - wpls13)) & + (*(sptr - wpls12)) & + (*(sptr - wpls11)) & + (*(sptr - wpls10)) & + (*(sptr - wpls9)) & + (*(sptr - wpls8)) & + (*(sptr - wpls7)) & + (*(sptr - wpls6)) & + (*(sptr - wpls5)) & + (*(sptr - wpls4)) & + (*(sptr - wpls3)) & + (*(sptr - wpls2)) & + (*(sptr - wpls)) & + (*sptr) & + (*(sptr + wpls)) & + (*(sptr + wpls2)) & + (*(sptr + wpls3)) & + (*(sptr + wpls4)) & + (*(sptr + wpls5)) & + (*(sptr + wpls6)) & + (*(sptr + wpls7)) & + (*(sptr + wpls8)) & + (*(sptr + wpls9)) & + (*(sptr + wpls10)) & + (*(sptr + wpls11)) & + (*(sptr + wpls12)) & + (*(sptr + wpls13)) & + (*(sptr + wpls14)) & + (*(sptr + wpls15)) & + (*(sptr + wpls16)) & + (*(sptr + wpls17)) & + (*(sptr + wpls18)) & + (*(sptr + wpls19)) & + (*(sptr + wpls20)) & + (*(sptr + wpls21)) & + (*(sptr + wpls22)) & + (*(sptr + wpls23)) & + (*(sptr + wpls24)) & + (*(sptr + wpls25)) & + (*(sptr + wpls26)); + } + } +} + +static void +fdilate_3_115(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; +l_int32 wpls2, wpls3, wpls4; +l_int32 wpls5, wpls6, wpls7, wpls8; +l_int32 wpls9, wpls10, wpls11, wpls12; +l_int32 wpls13, wpls14, wpls15, wpls16; +l_int32 wpls17, wpls18, wpls19, wpls20; +l_int32 wpls21, wpls22, wpls23, wpls24; +l_int32 wpls25, wpls26, wpls27; + + wpls2 = 2 * wpls; + wpls3 = 3 * wpls; + wpls4 = 4 * wpls; + wpls5 = 5 * wpls; + wpls6 = 6 * wpls; + wpls7 = 7 * wpls; + wpls8 = 8 * wpls; + wpls9 = 9 * wpls; + wpls10 = 10 * wpls; + wpls11 = 11 * wpls; + wpls12 = 12 * wpls; + wpls13 = 13 * wpls; + wpls14 = 14 * wpls; + wpls15 = 15 * wpls; + wpls16 = 16 * wpls; + wpls17 = 17 * wpls; + wpls18 = 18 * wpls; + wpls19 = 19 * wpls; + wpls20 = 20 * wpls; + wpls21 = 21 * wpls; + wpls22 = 22 * wpls; + wpls23 = 23 * wpls; + wpls24 = 24 * wpls; + wpls25 = 25 * wpls; + wpls26 = 26 * wpls; + wpls27 = 27 * wpls; + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = (*(sptr + wpls27)) | + (*(sptr + wpls26)) | + (*(sptr + wpls25)) | + (*(sptr + wpls24)) | + (*(sptr + wpls23)) | + (*(sptr + wpls22)) | + (*(sptr + wpls21)) | + (*(sptr + wpls20)) | + (*(sptr + wpls19)) | + (*(sptr + wpls18)) | + (*(sptr + wpls17)) | + (*(sptr + wpls16)) | + (*(sptr + wpls15)) | + (*(sptr + wpls14)) | + (*(sptr + wpls13)) | + (*(sptr + wpls12)) | + (*(sptr + wpls11)) | + (*(sptr + wpls10)) | + (*(sptr + wpls9)) | + (*(sptr + wpls8)) | + (*(sptr + wpls7)) | + (*(sptr + wpls6)) | + (*(sptr + wpls5)) | + (*(sptr + wpls4)) | + (*(sptr + wpls3)) | + (*(sptr + wpls2)) | + (*(sptr + wpls)) | + (*sptr) | + (*(sptr - wpls)) | + (*(sptr - wpls2)) | + (*(sptr - wpls3)) | + (*(sptr - wpls4)) | + (*(sptr - wpls5)) | + (*(sptr - wpls6)) | + (*(sptr - wpls7)) | + (*(sptr - wpls8)) | + (*(sptr - wpls9)) | + (*(sptr - wpls10)) | + (*(sptr - wpls11)) | + (*(sptr - wpls12)) | + (*(sptr - wpls13)) | + (*(sptr - wpls14)) | + (*(sptr - wpls15)) | + (*(sptr - wpls16)) | + (*(sptr - wpls17)) | + (*(sptr - wpls18)) | + (*(sptr - wpls19)) | + (*(sptr - wpls20)) | + (*(sptr - wpls21)) | + (*(sptr - wpls22)) | + (*(sptr - wpls23)) | + (*(sptr - wpls24)) | + (*(sptr - wpls25)) | + (*(sptr - wpls26)) | + (*(sptr - wpls27)); + } + } +} + +static void +ferode_3_115(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; +l_int32 wpls2, wpls3, wpls4; +l_int32 wpls5, wpls6, wpls7, wpls8; +l_int32 wpls9, wpls10, wpls11, wpls12; +l_int32 wpls13, wpls14, wpls15, wpls16; +l_int32 wpls17, wpls18, wpls19, wpls20; +l_int32 wpls21, wpls22, wpls23, wpls24; +l_int32 wpls25, wpls26, wpls27; + + wpls2 = 2 * wpls; + wpls3 = 3 * wpls; + wpls4 = 4 * wpls; + wpls5 = 5 * wpls; + wpls6 = 6 * wpls; + wpls7 = 7 * wpls; + wpls8 = 8 * wpls; + wpls9 = 9 * wpls; + wpls10 = 10 * wpls; + wpls11 = 11 * wpls; + wpls12 = 12 * wpls; + wpls13 = 13 * wpls; + wpls14 = 14 * wpls; + wpls15 = 15 * wpls; + wpls16 = 16 * wpls; + wpls17 = 17 * wpls; + wpls18 = 18 * wpls; + wpls19 = 19 * wpls; + wpls20 = 20 * wpls; + wpls21 = 21 * wpls; + wpls22 = 22 * wpls; + wpls23 = 23 * wpls; + wpls24 = 24 * wpls; + wpls25 = 25 * wpls; + wpls26 = 26 * wpls; + wpls27 = 27 * wpls; + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = (*(sptr - wpls27)) & + (*(sptr - wpls26)) & + (*(sptr - wpls25)) & + (*(sptr - wpls24)) & + (*(sptr - wpls23)) & + (*(sptr - wpls22)) & + (*(sptr - wpls21)) & + (*(sptr - wpls20)) & + (*(sptr - wpls19)) & + (*(sptr - wpls18)) & + (*(sptr - wpls17)) & + (*(sptr - wpls16)) & + (*(sptr - wpls15)) & + (*(sptr - wpls14)) & + (*(sptr - wpls13)) & + (*(sptr - wpls12)) & + (*(sptr - wpls11)) & + (*(sptr - wpls10)) & + (*(sptr - wpls9)) & + (*(sptr - wpls8)) & + (*(sptr - wpls7)) & + (*(sptr - wpls6)) & + (*(sptr - wpls5)) & + (*(sptr - wpls4)) & + (*(sptr - wpls3)) & + (*(sptr - wpls2)) & + (*(sptr - wpls)) & + (*sptr) & + (*(sptr + wpls)) & + (*(sptr + wpls2)) & + (*(sptr + wpls3)) & + (*(sptr + wpls4)) & + (*(sptr + wpls5)) & + (*(sptr + wpls6)) & + (*(sptr + wpls7)) & + (*(sptr + wpls8)) & + (*(sptr + wpls9)) & + (*(sptr + wpls10)) & + (*(sptr + wpls11)) & + (*(sptr + wpls12)) & + (*(sptr + wpls13)) & + (*(sptr + wpls14)) & + (*(sptr + wpls15)) & + (*(sptr + wpls16)) & + (*(sptr + wpls17)) & + (*(sptr + wpls18)) & + (*(sptr + wpls19)) & + (*(sptr + wpls20)) & + (*(sptr + wpls21)) & + (*(sptr + wpls22)) & + (*(sptr + wpls23)) & + (*(sptr + wpls24)) & + (*(sptr + wpls25)) & + (*(sptr + wpls26)) & + (*(sptr + wpls27)); + } + } +} + +static void +fdilate_3_116(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; +l_int32 wpls2, wpls3, wpls4; +l_int32 wpls5, wpls6, wpls7, wpls8; +l_int32 wpls9, wpls10, wpls11, wpls12; +l_int32 wpls13, wpls14, wpls15, wpls16; +l_int32 wpls17, wpls18, wpls19, wpls20; +l_int32 wpls21, wpls22, wpls23, wpls24; +l_int32 wpls25, wpls26, wpls27, wpls28; + + wpls2 = 2 * wpls; + wpls3 = 3 * wpls; + wpls4 = 4 * wpls; + wpls5 = 5 * wpls; + wpls6 = 6 * wpls; + wpls7 = 7 * wpls; + wpls8 = 8 * wpls; + wpls9 = 9 * wpls; + wpls10 = 10 * wpls; + wpls11 = 11 * wpls; + wpls12 = 12 * wpls; + wpls13 = 13 * wpls; + wpls14 = 14 * wpls; + wpls15 = 15 * wpls; + wpls16 = 16 * wpls; + wpls17 = 17 * wpls; + wpls18 = 18 * wpls; + wpls19 = 19 * wpls; + wpls20 = 20 * wpls; + wpls21 = 21 * wpls; + wpls22 = 22 * wpls; + wpls23 = 23 * wpls; + wpls24 = 24 * wpls; + wpls25 = 25 * wpls; + wpls26 = 26 * wpls; + wpls27 = 27 * wpls; + wpls28 = 28 * wpls; + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = (*(sptr + wpls28)) | + (*(sptr + wpls27)) | + (*(sptr + wpls26)) | + (*(sptr + wpls25)) | + (*(sptr + wpls24)) | + (*(sptr + wpls23)) | + (*(sptr + wpls22)) | + (*(sptr + wpls21)) | + (*(sptr + wpls20)) | + (*(sptr + wpls19)) | + (*(sptr + wpls18)) | + (*(sptr + wpls17)) | + (*(sptr + wpls16)) | + (*(sptr + wpls15)) | + (*(sptr + wpls14)) | + (*(sptr + wpls13)) | + (*(sptr + wpls12)) | + (*(sptr + wpls11)) | + (*(sptr + wpls10)) | + (*(sptr + wpls9)) | + (*(sptr + wpls8)) | + (*(sptr + wpls7)) | + (*(sptr + wpls6)) | + (*(sptr + wpls5)) | + (*(sptr + wpls4)) | + (*(sptr + wpls3)) | + (*(sptr + wpls2)) | + (*(sptr + wpls)) | + (*sptr) | + (*(sptr - wpls)) | + (*(sptr - wpls2)) | + (*(sptr - wpls3)) | + (*(sptr - wpls4)) | + (*(sptr - wpls5)) | + (*(sptr - wpls6)) | + (*(sptr - wpls7)) | + (*(sptr - wpls8)) | + (*(sptr - wpls9)) | + (*(sptr - wpls10)) | + (*(sptr - wpls11)) | + (*(sptr - wpls12)) | + (*(sptr - wpls13)) | + (*(sptr - wpls14)) | + (*(sptr - wpls15)) | + (*(sptr - wpls16)) | + (*(sptr - wpls17)) | + (*(sptr - wpls18)) | + (*(sptr - wpls19)) | + (*(sptr - wpls20)) | + (*(sptr - wpls21)) | + (*(sptr - wpls22)) | + (*(sptr - wpls23)) | + (*(sptr - wpls24)) | + (*(sptr - wpls25)) | + (*(sptr - wpls26)) | + (*(sptr - wpls27)); + } + } +} + +static void +ferode_3_116(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; +l_int32 wpls2, wpls3, wpls4; +l_int32 wpls5, wpls6, wpls7, wpls8; +l_int32 wpls9, wpls10, wpls11, wpls12; +l_int32 wpls13, wpls14, wpls15, wpls16; +l_int32 wpls17, wpls18, wpls19, wpls20; +l_int32 wpls21, wpls22, wpls23, wpls24; +l_int32 wpls25, wpls26, wpls27, wpls28; + + wpls2 = 2 * wpls; + wpls3 = 3 * wpls; + wpls4 = 4 * wpls; + wpls5 = 5 * wpls; + wpls6 = 6 * wpls; + wpls7 = 7 * wpls; + wpls8 = 8 * wpls; + wpls9 = 9 * wpls; + wpls10 = 10 * wpls; + wpls11 = 11 * wpls; + wpls12 = 12 * wpls; + wpls13 = 13 * wpls; + wpls14 = 14 * wpls; + wpls15 = 15 * wpls; + wpls16 = 16 * wpls; + wpls17 = 17 * wpls; + wpls18 = 18 * wpls; + wpls19 = 19 * wpls; + wpls20 = 20 * wpls; + wpls21 = 21 * wpls; + wpls22 = 22 * wpls; + wpls23 = 23 * wpls; + wpls24 = 24 * wpls; + wpls25 = 25 * wpls; + wpls26 = 26 * wpls; + wpls27 = 27 * wpls; + wpls28 = 28 * wpls; + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = (*(sptr - wpls28)) & + (*(sptr - wpls27)) & + (*(sptr - wpls26)) & + (*(sptr - wpls25)) & + (*(sptr - wpls24)) & + (*(sptr - wpls23)) & + (*(sptr - wpls22)) & + (*(sptr - wpls21)) & + (*(sptr - wpls20)) & + (*(sptr - wpls19)) & + (*(sptr - wpls18)) & + (*(sptr - wpls17)) & + (*(sptr - wpls16)) & + (*(sptr - wpls15)) & + (*(sptr - wpls14)) & + (*(sptr - wpls13)) & + (*(sptr - wpls12)) & + (*(sptr - wpls11)) & + (*(sptr - wpls10)) & + (*(sptr - wpls9)) & + (*(sptr - wpls8)) & + (*(sptr - wpls7)) & + (*(sptr - wpls6)) & + (*(sptr - wpls5)) & + (*(sptr - wpls4)) & + (*(sptr - wpls3)) & + (*(sptr - wpls2)) & + (*(sptr - wpls)) & + (*sptr) & + (*(sptr + wpls)) & + (*(sptr + wpls2)) & + (*(sptr + wpls3)) & + (*(sptr + wpls4)) & + (*(sptr + wpls5)) & + (*(sptr + wpls6)) & + (*(sptr + wpls7)) & + (*(sptr + wpls8)) & + (*(sptr + wpls9)) & + (*(sptr + wpls10)) & + (*(sptr + wpls11)) & + (*(sptr + wpls12)) & + (*(sptr + wpls13)) & + (*(sptr + wpls14)) & + (*(sptr + wpls15)) & + (*(sptr + wpls16)) & + (*(sptr + wpls17)) & + (*(sptr + wpls18)) & + (*(sptr + wpls19)) & + (*(sptr + wpls20)) & + (*(sptr + wpls21)) & + (*(sptr + wpls22)) & + (*(sptr + wpls23)) & + (*(sptr + wpls24)) & + (*(sptr + wpls25)) & + (*(sptr + wpls26)) & + (*(sptr + wpls27)); + } + } +} + +static void +fdilate_3_117(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; +l_int32 wpls2, wpls3, wpls4; +l_int32 wpls5, wpls6, wpls7, wpls8; +l_int32 wpls9, wpls10, wpls11, wpls12; +l_int32 wpls13, wpls14, wpls15, wpls16; +l_int32 wpls17, wpls18, wpls19, wpls20; +l_int32 wpls21, wpls22, wpls23, wpls24; +l_int32 wpls25, wpls26, wpls27, wpls28; + + wpls2 = 2 * wpls; + wpls3 = 3 * wpls; + wpls4 = 4 * wpls; + wpls5 = 5 * wpls; + wpls6 = 6 * wpls; + wpls7 = 7 * wpls; + wpls8 = 8 * wpls; + wpls9 = 9 * wpls; + wpls10 = 10 * wpls; + wpls11 = 11 * wpls; + wpls12 = 12 * wpls; + wpls13 = 13 * wpls; + wpls14 = 14 * wpls; + wpls15 = 15 * wpls; + wpls16 = 16 * wpls; + wpls17 = 17 * wpls; + wpls18 = 18 * wpls; + wpls19 = 19 * wpls; + wpls20 = 20 * wpls; + wpls21 = 21 * wpls; + wpls22 = 22 * wpls; + wpls23 = 23 * wpls; + wpls24 = 24 * wpls; + wpls25 = 25 * wpls; + wpls26 = 26 * wpls; + wpls27 = 27 * wpls; + wpls28 = 28 * wpls; + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = (*(sptr + wpls28)) | + (*(sptr + wpls27)) | + (*(sptr + wpls26)) | + (*(sptr + wpls25)) | + (*(sptr + wpls24)) | + (*(sptr + wpls23)) | + (*(sptr + wpls22)) | + (*(sptr + wpls21)) | + (*(sptr + wpls20)) | + (*(sptr + wpls19)) | + (*(sptr + wpls18)) | + (*(sptr + wpls17)) | + (*(sptr + wpls16)) | + (*(sptr + wpls15)) | + (*(sptr + wpls14)) | + (*(sptr + wpls13)) | + (*(sptr + wpls12)) | + (*(sptr + wpls11)) | + (*(sptr + wpls10)) | + (*(sptr + wpls9)) | + (*(sptr + wpls8)) | + (*(sptr + wpls7)) | + (*(sptr + wpls6)) | + (*(sptr + wpls5)) | + (*(sptr + wpls4)) | + (*(sptr + wpls3)) | + (*(sptr + wpls2)) | + (*(sptr + wpls)) | + (*sptr) | + (*(sptr - wpls)) | + (*(sptr - wpls2)) | + (*(sptr - wpls3)) | + (*(sptr - wpls4)) | + (*(sptr - wpls5)) | + (*(sptr - wpls6)) | + (*(sptr - wpls7)) | + (*(sptr - wpls8)) | + (*(sptr - wpls9)) | + (*(sptr - wpls10)) | + (*(sptr - wpls11)) | + (*(sptr - wpls12)) | + (*(sptr - wpls13)) | + (*(sptr - wpls14)) | + (*(sptr - wpls15)) | + (*(sptr - wpls16)) | + (*(sptr - wpls17)) | + (*(sptr - wpls18)) | + (*(sptr - wpls19)) | + (*(sptr - wpls20)) | + (*(sptr - wpls21)) | + (*(sptr - wpls22)) | + (*(sptr - wpls23)) | + (*(sptr - wpls24)) | + (*(sptr - wpls25)) | + (*(sptr - wpls26)) | + (*(sptr - wpls27)) | + (*(sptr - wpls28)); + } + } +} + +static void +ferode_3_117(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; +l_int32 wpls2, wpls3, wpls4; +l_int32 wpls5, wpls6, wpls7, wpls8; +l_int32 wpls9, wpls10, wpls11, wpls12; +l_int32 wpls13, wpls14, wpls15, wpls16; +l_int32 wpls17, wpls18, wpls19, wpls20; +l_int32 wpls21, wpls22, wpls23, wpls24; +l_int32 wpls25, wpls26, wpls27, wpls28; + + wpls2 = 2 * wpls; + wpls3 = 3 * wpls; + wpls4 = 4 * wpls; + wpls5 = 5 * wpls; + wpls6 = 6 * wpls; + wpls7 = 7 * wpls; + wpls8 = 8 * wpls; + wpls9 = 9 * wpls; + wpls10 = 10 * wpls; + wpls11 = 11 * wpls; + wpls12 = 12 * wpls; + wpls13 = 13 * wpls; + wpls14 = 14 * wpls; + wpls15 = 15 * wpls; + wpls16 = 16 * wpls; + wpls17 = 17 * wpls; + wpls18 = 18 * wpls; + wpls19 = 19 * wpls; + wpls20 = 20 * wpls; + wpls21 = 21 * wpls; + wpls22 = 22 * wpls; + wpls23 = 23 * wpls; + wpls24 = 24 * wpls; + wpls25 = 25 * wpls; + wpls26 = 26 * wpls; + wpls27 = 27 * wpls; + wpls28 = 28 * wpls; + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = (*(sptr - wpls28)) & + (*(sptr - wpls27)) & + (*(sptr - wpls26)) & + (*(sptr - wpls25)) & + (*(sptr - wpls24)) & + (*(sptr - wpls23)) & + (*(sptr - wpls22)) & + (*(sptr - wpls21)) & + (*(sptr - wpls20)) & + (*(sptr - wpls19)) & + (*(sptr - wpls18)) & + (*(sptr - wpls17)) & + (*(sptr - wpls16)) & + (*(sptr - wpls15)) & + (*(sptr - wpls14)) & + (*(sptr - wpls13)) & + (*(sptr - wpls12)) & + (*(sptr - wpls11)) & + (*(sptr - wpls10)) & + (*(sptr - wpls9)) & + (*(sptr - wpls8)) & + (*(sptr - wpls7)) & + (*(sptr - wpls6)) & + (*(sptr - wpls5)) & + (*(sptr - wpls4)) & + (*(sptr - wpls3)) & + (*(sptr - wpls2)) & + (*(sptr - wpls)) & + (*sptr) & + (*(sptr + wpls)) & + (*(sptr + wpls2)) & + (*(sptr + wpls3)) & + (*(sptr + wpls4)) & + (*(sptr + wpls5)) & + (*(sptr + wpls6)) & + (*(sptr + wpls7)) & + (*(sptr + wpls8)) & + (*(sptr + wpls9)) & + (*(sptr + wpls10)) & + (*(sptr + wpls11)) & + (*(sptr + wpls12)) & + (*(sptr + wpls13)) & + (*(sptr + wpls14)) & + (*(sptr + wpls15)) & + (*(sptr + wpls16)) & + (*(sptr + wpls17)) & + (*(sptr + wpls18)) & + (*(sptr + wpls19)) & + (*(sptr + wpls20)) & + (*(sptr + wpls21)) & + (*(sptr + wpls22)) & + (*(sptr + wpls23)) & + (*(sptr + wpls24)) & + (*(sptr + wpls25)) & + (*(sptr + wpls26)) & + (*(sptr + wpls27)) & + (*(sptr + wpls28)); + } + } +} + +static void +fdilate_3_118(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; +l_int32 wpls2, wpls3, wpls4; +l_int32 wpls5, wpls6, wpls7, wpls8; +l_int32 wpls9, wpls10, wpls11, wpls12; +l_int32 wpls13, wpls14, wpls15, wpls16; +l_int32 wpls17, wpls18, wpls19, wpls20; +l_int32 wpls21, wpls22, wpls23, wpls24; +l_int32 wpls25, wpls26, wpls27, wpls28; +l_int32 wpls29; + + wpls2 = 2 * wpls; + wpls3 = 3 * wpls; + wpls4 = 4 * wpls; + wpls5 = 5 * wpls; + wpls6 = 6 * wpls; + wpls7 = 7 * wpls; + wpls8 = 8 * wpls; + wpls9 = 9 * wpls; + wpls10 = 10 * wpls; + wpls11 = 11 * wpls; + wpls12 = 12 * wpls; + wpls13 = 13 * wpls; + wpls14 = 14 * wpls; + wpls15 = 15 * wpls; + wpls16 = 16 * wpls; + wpls17 = 17 * wpls; + wpls18 = 18 * wpls; + wpls19 = 19 * wpls; + wpls20 = 20 * wpls; + wpls21 = 21 * wpls; + wpls22 = 22 * wpls; + wpls23 = 23 * wpls; + wpls24 = 24 * wpls; + wpls25 = 25 * wpls; + wpls26 = 26 * wpls; + wpls27 = 27 * wpls; + wpls28 = 28 * wpls; + wpls29 = 29 * wpls; + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = (*(sptr + wpls29)) | + (*(sptr + wpls28)) | + (*(sptr + wpls27)) | + (*(sptr + wpls26)) | + (*(sptr + wpls25)) | + (*(sptr + wpls24)) | + (*(sptr + wpls23)) | + (*(sptr + wpls22)) | + (*(sptr + wpls21)) | + (*(sptr + wpls20)) | + (*(sptr + wpls19)) | + (*(sptr + wpls18)) | + (*(sptr + wpls17)) | + (*(sptr + wpls16)) | + (*(sptr + wpls15)) | + (*(sptr + wpls14)) | + (*(sptr + wpls13)) | + (*(sptr + wpls12)) | + (*(sptr + wpls11)) | + (*(sptr + wpls10)) | + (*(sptr + wpls9)) | + (*(sptr + wpls8)) | + (*(sptr + wpls7)) | + (*(sptr + wpls6)) | + (*(sptr + wpls5)) | + (*(sptr + wpls4)) | + (*(sptr + wpls3)) | + (*(sptr + wpls2)) | + (*(sptr + wpls)) | + (*sptr) | + (*(sptr - wpls)) | + (*(sptr - wpls2)) | + (*(sptr - wpls3)) | + (*(sptr - wpls4)) | + (*(sptr - wpls5)) | + (*(sptr - wpls6)) | + (*(sptr - wpls7)) | + (*(sptr - wpls8)) | + (*(sptr - wpls9)) | + (*(sptr - wpls10)) | + (*(sptr - wpls11)) | + (*(sptr - wpls12)) | + (*(sptr - wpls13)) | + (*(sptr - wpls14)) | + (*(sptr - wpls15)) | + (*(sptr - wpls16)) | + (*(sptr - wpls17)) | + (*(sptr - wpls18)) | + (*(sptr - wpls19)) | + (*(sptr - wpls20)) | + (*(sptr - wpls21)) | + (*(sptr - wpls22)) | + (*(sptr - wpls23)) | + (*(sptr - wpls24)) | + (*(sptr - wpls25)) | + (*(sptr - wpls26)) | + (*(sptr - wpls27)) | + (*(sptr - wpls28)); + } + } +} + +static void +ferode_3_118(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; +l_int32 wpls2, wpls3, wpls4; +l_int32 wpls5, wpls6, wpls7, wpls8; +l_int32 wpls9, wpls10, wpls11, wpls12; +l_int32 wpls13, wpls14, wpls15, wpls16; +l_int32 wpls17, wpls18, wpls19, wpls20; +l_int32 wpls21, wpls22, wpls23, wpls24; +l_int32 wpls25, wpls26, wpls27, wpls28; +l_int32 wpls29; + + wpls2 = 2 * wpls; + wpls3 = 3 * wpls; + wpls4 = 4 * wpls; + wpls5 = 5 * wpls; + wpls6 = 6 * wpls; + wpls7 = 7 * wpls; + wpls8 = 8 * wpls; + wpls9 = 9 * wpls; + wpls10 = 10 * wpls; + wpls11 = 11 * wpls; + wpls12 = 12 * wpls; + wpls13 = 13 * wpls; + wpls14 = 14 * wpls; + wpls15 = 15 * wpls; + wpls16 = 16 * wpls; + wpls17 = 17 * wpls; + wpls18 = 18 * wpls; + wpls19 = 19 * wpls; + wpls20 = 20 * wpls; + wpls21 = 21 * wpls; + wpls22 = 22 * wpls; + wpls23 = 23 * wpls; + wpls24 = 24 * wpls; + wpls25 = 25 * wpls; + wpls26 = 26 * wpls; + wpls27 = 27 * wpls; + wpls28 = 28 * wpls; + wpls29 = 29 * wpls; + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = (*(sptr - wpls29)) & + (*(sptr - wpls28)) & + (*(sptr - wpls27)) & + (*(sptr - wpls26)) & + (*(sptr - wpls25)) & + (*(sptr - wpls24)) & + (*(sptr - wpls23)) & + (*(sptr - wpls22)) & + (*(sptr - wpls21)) & + (*(sptr - wpls20)) & + (*(sptr - wpls19)) & + (*(sptr - wpls18)) & + (*(sptr - wpls17)) & + (*(sptr - wpls16)) & + (*(sptr - wpls15)) & + (*(sptr - wpls14)) & + (*(sptr - wpls13)) & + (*(sptr - wpls12)) & + (*(sptr - wpls11)) & + (*(sptr - wpls10)) & + (*(sptr - wpls9)) & + (*(sptr - wpls8)) & + (*(sptr - wpls7)) & + (*(sptr - wpls6)) & + (*(sptr - wpls5)) & + (*(sptr - wpls4)) & + (*(sptr - wpls3)) & + (*(sptr - wpls2)) & + (*(sptr - wpls)) & + (*sptr) & + (*(sptr + wpls)) & + (*(sptr + wpls2)) & + (*(sptr + wpls3)) & + (*(sptr + wpls4)) & + (*(sptr + wpls5)) & + (*(sptr + wpls6)) & + (*(sptr + wpls7)) & + (*(sptr + wpls8)) & + (*(sptr + wpls9)) & + (*(sptr + wpls10)) & + (*(sptr + wpls11)) & + (*(sptr + wpls12)) & + (*(sptr + wpls13)) & + (*(sptr + wpls14)) & + (*(sptr + wpls15)) & + (*(sptr + wpls16)) & + (*(sptr + wpls17)) & + (*(sptr + wpls18)) & + (*(sptr + wpls19)) & + (*(sptr + wpls20)) & + (*(sptr + wpls21)) & + (*(sptr + wpls22)) & + (*(sptr + wpls23)) & + (*(sptr + wpls24)) & + (*(sptr + wpls25)) & + (*(sptr + wpls26)) & + (*(sptr + wpls27)) & + (*(sptr + wpls28)); + } + } +} + +static void +fdilate_3_119(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; +l_int32 wpls2, wpls3, wpls4; +l_int32 wpls5, wpls6, wpls7, wpls8; +l_int32 wpls9, wpls10, wpls11, wpls12; +l_int32 wpls13, wpls14, wpls15, wpls16; +l_int32 wpls17, wpls18, wpls19, wpls20; +l_int32 wpls21, wpls22, wpls23, wpls24; +l_int32 wpls25, wpls26, wpls27, wpls28; +l_int32 wpls29; + + wpls2 = 2 * wpls; + wpls3 = 3 * wpls; + wpls4 = 4 * wpls; + wpls5 = 5 * wpls; + wpls6 = 6 * wpls; + wpls7 = 7 * wpls; + wpls8 = 8 * wpls; + wpls9 = 9 * wpls; + wpls10 = 10 * wpls; + wpls11 = 11 * wpls; + wpls12 = 12 * wpls; + wpls13 = 13 * wpls; + wpls14 = 14 * wpls; + wpls15 = 15 * wpls; + wpls16 = 16 * wpls; + wpls17 = 17 * wpls; + wpls18 = 18 * wpls; + wpls19 = 19 * wpls; + wpls20 = 20 * wpls; + wpls21 = 21 * wpls; + wpls22 = 22 * wpls; + wpls23 = 23 * wpls; + wpls24 = 24 * wpls; + wpls25 = 25 * wpls; + wpls26 = 26 * wpls; + wpls27 = 27 * wpls; + wpls28 = 28 * wpls; + wpls29 = 29 * wpls; + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = (*(sptr + wpls29)) | + (*(sptr + wpls28)) | + (*(sptr + wpls27)) | + (*(sptr + wpls26)) | + (*(sptr + wpls25)) | + (*(sptr + wpls24)) | + (*(sptr + wpls23)) | + (*(sptr + wpls22)) | + (*(sptr + wpls21)) | + (*(sptr + wpls20)) | + (*(sptr + wpls19)) | + (*(sptr + wpls18)) | + (*(sptr + wpls17)) | + (*(sptr + wpls16)) | + (*(sptr + wpls15)) | + (*(sptr + wpls14)) | + (*(sptr + wpls13)) | + (*(sptr + wpls12)) | + (*(sptr + wpls11)) | + (*(sptr + wpls10)) | + (*(sptr + wpls9)) | + (*(sptr + wpls8)) | + (*(sptr + wpls7)) | + (*(sptr + wpls6)) | + (*(sptr + wpls5)) | + (*(sptr + wpls4)) | + (*(sptr + wpls3)) | + (*(sptr + wpls2)) | + (*(sptr + wpls)) | + (*sptr) | + (*(sptr - wpls)) | + (*(sptr - wpls2)) | + (*(sptr - wpls3)) | + (*(sptr - wpls4)) | + (*(sptr - wpls5)) | + (*(sptr - wpls6)) | + (*(sptr - wpls7)) | + (*(sptr - wpls8)) | + (*(sptr - wpls9)) | + (*(sptr - wpls10)) | + (*(sptr - wpls11)) | + (*(sptr - wpls12)) | + (*(sptr - wpls13)) | + (*(sptr - wpls14)) | + (*(sptr - wpls15)) | + (*(sptr - wpls16)) | + (*(sptr - wpls17)) | + (*(sptr - wpls18)) | + (*(sptr - wpls19)) | + (*(sptr - wpls20)) | + (*(sptr - wpls21)) | + (*(sptr - wpls22)) | + (*(sptr - wpls23)) | + (*(sptr - wpls24)) | + (*(sptr - wpls25)) | + (*(sptr - wpls26)) | + (*(sptr - wpls27)) | + (*(sptr - wpls28)) | + (*(sptr - wpls29)); + } + } +} + +static void +ferode_3_119(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; +l_int32 wpls2, wpls3, wpls4; +l_int32 wpls5, wpls6, wpls7, wpls8; +l_int32 wpls9, wpls10, wpls11, wpls12; +l_int32 wpls13, wpls14, wpls15, wpls16; +l_int32 wpls17, wpls18, wpls19, wpls20; +l_int32 wpls21, wpls22, wpls23, wpls24; +l_int32 wpls25, wpls26, wpls27, wpls28; +l_int32 wpls29; + + wpls2 = 2 * wpls; + wpls3 = 3 * wpls; + wpls4 = 4 * wpls; + wpls5 = 5 * wpls; + wpls6 = 6 * wpls; + wpls7 = 7 * wpls; + wpls8 = 8 * wpls; + wpls9 = 9 * wpls; + wpls10 = 10 * wpls; + wpls11 = 11 * wpls; + wpls12 = 12 * wpls; + wpls13 = 13 * wpls; + wpls14 = 14 * wpls; + wpls15 = 15 * wpls; + wpls16 = 16 * wpls; + wpls17 = 17 * wpls; + wpls18 = 18 * wpls; + wpls19 = 19 * wpls; + wpls20 = 20 * wpls; + wpls21 = 21 * wpls; + wpls22 = 22 * wpls; + wpls23 = 23 * wpls; + wpls24 = 24 * wpls; + wpls25 = 25 * wpls; + wpls26 = 26 * wpls; + wpls27 = 27 * wpls; + wpls28 = 28 * wpls; + wpls29 = 29 * wpls; + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = (*(sptr - wpls29)) & + (*(sptr - wpls28)) & + (*(sptr - wpls27)) & + (*(sptr - wpls26)) & + (*(sptr - wpls25)) & + (*(sptr - wpls24)) & + (*(sptr - wpls23)) & + (*(sptr - wpls22)) & + (*(sptr - wpls21)) & + (*(sptr - wpls20)) & + (*(sptr - wpls19)) & + (*(sptr - wpls18)) & + (*(sptr - wpls17)) & + (*(sptr - wpls16)) & + (*(sptr - wpls15)) & + (*(sptr - wpls14)) & + (*(sptr - wpls13)) & + (*(sptr - wpls12)) & + (*(sptr - wpls11)) & + (*(sptr - wpls10)) & + (*(sptr - wpls9)) & + (*(sptr - wpls8)) & + (*(sptr - wpls7)) & + (*(sptr - wpls6)) & + (*(sptr - wpls5)) & + (*(sptr - wpls4)) & + (*(sptr - wpls3)) & + (*(sptr - wpls2)) & + (*(sptr - wpls)) & + (*sptr) & + (*(sptr + wpls)) & + (*(sptr + wpls2)) & + (*(sptr + wpls3)) & + (*(sptr + wpls4)) & + (*(sptr + wpls5)) & + (*(sptr + wpls6)) & + (*(sptr + wpls7)) & + (*(sptr + wpls8)) & + (*(sptr + wpls9)) & + (*(sptr + wpls10)) & + (*(sptr + wpls11)) & + (*(sptr + wpls12)) & + (*(sptr + wpls13)) & + (*(sptr + wpls14)) & + (*(sptr + wpls15)) & + (*(sptr + wpls16)) & + (*(sptr + wpls17)) & + (*(sptr + wpls18)) & + (*(sptr + wpls19)) & + (*(sptr + wpls20)) & + (*(sptr + wpls21)) & + (*(sptr + wpls22)) & + (*(sptr + wpls23)) & + (*(sptr + wpls24)) & + (*(sptr + wpls25)) & + (*(sptr + wpls26)) & + (*(sptr + wpls27)) & + (*(sptr + wpls28)) & + (*(sptr + wpls29)); + } + } +} + +static void +fdilate_3_120(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; +l_int32 wpls2, wpls3, wpls4; +l_int32 wpls5, wpls6, wpls7, wpls8; +l_int32 wpls9, wpls10, wpls11, wpls12; +l_int32 wpls13, wpls14, wpls15, wpls16; +l_int32 wpls17, wpls18, wpls19, wpls20; +l_int32 wpls21, wpls22, wpls23, wpls24; +l_int32 wpls25, wpls26, wpls27, wpls28; +l_int32 wpls29, wpls30; + + wpls2 = 2 * wpls; + wpls3 = 3 * wpls; + wpls4 = 4 * wpls; + wpls5 = 5 * wpls; + wpls6 = 6 * wpls; + wpls7 = 7 * wpls; + wpls8 = 8 * wpls; + wpls9 = 9 * wpls; + wpls10 = 10 * wpls; + wpls11 = 11 * wpls; + wpls12 = 12 * wpls; + wpls13 = 13 * wpls; + wpls14 = 14 * wpls; + wpls15 = 15 * wpls; + wpls16 = 16 * wpls; + wpls17 = 17 * wpls; + wpls18 = 18 * wpls; + wpls19 = 19 * wpls; + wpls20 = 20 * wpls; + wpls21 = 21 * wpls; + wpls22 = 22 * wpls; + wpls23 = 23 * wpls; + wpls24 = 24 * wpls; + wpls25 = 25 * wpls; + wpls26 = 26 * wpls; + wpls27 = 27 * wpls; + wpls28 = 28 * wpls; + wpls29 = 29 * wpls; + wpls30 = 30 * wpls; + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = (*(sptr + wpls30)) | + (*(sptr + wpls29)) | + (*(sptr + wpls28)) | + (*(sptr + wpls27)) | + (*(sptr + wpls26)) | + (*(sptr + wpls25)) | + (*(sptr + wpls24)) | + (*(sptr + wpls23)) | + (*(sptr + wpls22)) | + (*(sptr + wpls21)) | + (*(sptr + wpls20)) | + (*(sptr + wpls19)) | + (*(sptr + wpls18)) | + (*(sptr + wpls17)) | + (*(sptr + wpls16)) | + (*(sptr + wpls15)) | + (*(sptr + wpls14)) | + (*(sptr + wpls13)) | + (*(sptr + wpls12)) | + (*(sptr + wpls11)) | + (*(sptr + wpls10)) | + (*(sptr + wpls9)) | + (*(sptr + wpls8)) | + (*(sptr + wpls7)) | + (*(sptr + wpls6)) | + (*(sptr + wpls5)) | + (*(sptr + wpls4)) | + (*(sptr + wpls3)) | + (*(sptr + wpls2)) | + (*(sptr + wpls)) | + (*sptr) | + (*(sptr - wpls)) | + (*(sptr - wpls2)) | + (*(sptr - wpls3)) | + (*(sptr - wpls4)) | + (*(sptr - wpls5)) | + (*(sptr - wpls6)) | + (*(sptr - wpls7)) | + (*(sptr - wpls8)) | + (*(sptr - wpls9)) | + (*(sptr - wpls10)) | + (*(sptr - wpls11)) | + (*(sptr - wpls12)) | + (*(sptr - wpls13)) | + (*(sptr - wpls14)) | + (*(sptr - wpls15)) | + (*(sptr - wpls16)) | + (*(sptr - wpls17)) | + (*(sptr - wpls18)) | + (*(sptr - wpls19)) | + (*(sptr - wpls20)) | + (*(sptr - wpls21)) | + (*(sptr - wpls22)) | + (*(sptr - wpls23)) | + (*(sptr - wpls24)) | + (*(sptr - wpls25)) | + (*(sptr - wpls26)) | + (*(sptr - wpls27)) | + (*(sptr - wpls28)) | + (*(sptr - wpls29)); + } + } +} + +static void +ferode_3_120(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; +l_int32 wpls2, wpls3, wpls4; +l_int32 wpls5, wpls6, wpls7, wpls8; +l_int32 wpls9, wpls10, wpls11, wpls12; +l_int32 wpls13, wpls14, wpls15, wpls16; +l_int32 wpls17, wpls18, wpls19, wpls20; +l_int32 wpls21, wpls22, wpls23, wpls24; +l_int32 wpls25, wpls26, wpls27, wpls28; +l_int32 wpls29, wpls30; + + wpls2 = 2 * wpls; + wpls3 = 3 * wpls; + wpls4 = 4 * wpls; + wpls5 = 5 * wpls; + wpls6 = 6 * wpls; + wpls7 = 7 * wpls; + wpls8 = 8 * wpls; + wpls9 = 9 * wpls; + wpls10 = 10 * wpls; + wpls11 = 11 * wpls; + wpls12 = 12 * wpls; + wpls13 = 13 * wpls; + wpls14 = 14 * wpls; + wpls15 = 15 * wpls; + wpls16 = 16 * wpls; + wpls17 = 17 * wpls; + wpls18 = 18 * wpls; + wpls19 = 19 * wpls; + wpls20 = 20 * wpls; + wpls21 = 21 * wpls; + wpls22 = 22 * wpls; + wpls23 = 23 * wpls; + wpls24 = 24 * wpls; + wpls25 = 25 * wpls; + wpls26 = 26 * wpls; + wpls27 = 27 * wpls; + wpls28 = 28 * wpls; + wpls29 = 29 * wpls; + wpls30 = 30 * wpls; + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = (*(sptr - wpls30)) & + (*(sptr - wpls29)) & + (*(sptr - wpls28)) & + (*(sptr - wpls27)) & + (*(sptr - wpls26)) & + (*(sptr - wpls25)) & + (*(sptr - wpls24)) & + (*(sptr - wpls23)) & + (*(sptr - wpls22)) & + (*(sptr - wpls21)) & + (*(sptr - wpls20)) & + (*(sptr - wpls19)) & + (*(sptr - wpls18)) & + (*(sptr - wpls17)) & + (*(sptr - wpls16)) & + (*(sptr - wpls15)) & + (*(sptr - wpls14)) & + (*(sptr - wpls13)) & + (*(sptr - wpls12)) & + (*(sptr - wpls11)) & + (*(sptr - wpls10)) & + (*(sptr - wpls9)) & + (*(sptr - wpls8)) & + (*(sptr - wpls7)) & + (*(sptr - wpls6)) & + (*(sptr - wpls5)) & + (*(sptr - wpls4)) & + (*(sptr - wpls3)) & + (*(sptr - wpls2)) & + (*(sptr - wpls)) & + (*sptr) & + (*(sptr + wpls)) & + (*(sptr + wpls2)) & + (*(sptr + wpls3)) & + (*(sptr + wpls4)) & + (*(sptr + wpls5)) & + (*(sptr + wpls6)) & + (*(sptr + wpls7)) & + (*(sptr + wpls8)) & + (*(sptr + wpls9)) & + (*(sptr + wpls10)) & + (*(sptr + wpls11)) & + (*(sptr + wpls12)) & + (*(sptr + wpls13)) & + (*(sptr + wpls14)) & + (*(sptr + wpls15)) & + (*(sptr + wpls16)) & + (*(sptr + wpls17)) & + (*(sptr + wpls18)) & + (*(sptr + wpls19)) & + (*(sptr + wpls20)) & + (*(sptr + wpls21)) & + (*(sptr + wpls22)) & + (*(sptr + wpls23)) & + (*(sptr + wpls24)) & + (*(sptr + wpls25)) & + (*(sptr + wpls26)) & + (*(sptr + wpls27)) & + (*(sptr + wpls28)) & + (*(sptr + wpls29)); + } + } +} + +static void +fdilate_3_121(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; +l_int32 wpls2, wpls3, wpls4; +l_int32 wpls5, wpls6, wpls7, wpls8; +l_int32 wpls9, wpls10, wpls11, wpls12; +l_int32 wpls13, wpls14, wpls15, wpls16; +l_int32 wpls17, wpls18, wpls19, wpls20; +l_int32 wpls21, wpls22, wpls23, wpls24; +l_int32 wpls25, wpls26, wpls27, wpls28; +l_int32 wpls29, wpls30; + + wpls2 = 2 * wpls; + wpls3 = 3 * wpls; + wpls4 = 4 * wpls; + wpls5 = 5 * wpls; + wpls6 = 6 * wpls; + wpls7 = 7 * wpls; + wpls8 = 8 * wpls; + wpls9 = 9 * wpls; + wpls10 = 10 * wpls; + wpls11 = 11 * wpls; + wpls12 = 12 * wpls; + wpls13 = 13 * wpls; + wpls14 = 14 * wpls; + wpls15 = 15 * wpls; + wpls16 = 16 * wpls; + wpls17 = 17 * wpls; + wpls18 = 18 * wpls; + wpls19 = 19 * wpls; + wpls20 = 20 * wpls; + wpls21 = 21 * wpls; + wpls22 = 22 * wpls; + wpls23 = 23 * wpls; + wpls24 = 24 * wpls; + wpls25 = 25 * wpls; + wpls26 = 26 * wpls; + wpls27 = 27 * wpls; + wpls28 = 28 * wpls; + wpls29 = 29 * wpls; + wpls30 = 30 * wpls; + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = (*(sptr + wpls30)) | + (*(sptr + wpls29)) | + (*(sptr + wpls28)) | + (*(sptr + wpls27)) | + (*(sptr + wpls26)) | + (*(sptr + wpls25)) | + (*(sptr + wpls24)) | + (*(sptr + wpls23)) | + (*(sptr + wpls22)) | + (*(sptr + wpls21)) | + (*(sptr + wpls20)) | + (*(sptr + wpls19)) | + (*(sptr + wpls18)) | + (*(sptr + wpls17)) | + (*(sptr + wpls16)) | + (*(sptr + wpls15)) | + (*(sptr + wpls14)) | + (*(sptr + wpls13)) | + (*(sptr + wpls12)) | + (*(sptr + wpls11)) | + (*(sptr + wpls10)) | + (*(sptr + wpls9)) | + (*(sptr + wpls8)) | + (*(sptr + wpls7)) | + (*(sptr + wpls6)) | + (*(sptr + wpls5)) | + (*(sptr + wpls4)) | + (*(sptr + wpls3)) | + (*(sptr + wpls2)) | + (*(sptr + wpls)) | + (*sptr) | + (*(sptr - wpls)) | + (*(sptr - wpls2)) | + (*(sptr - wpls3)) | + (*(sptr - wpls4)) | + (*(sptr - wpls5)) | + (*(sptr - wpls6)) | + (*(sptr - wpls7)) | + (*(sptr - wpls8)) | + (*(sptr - wpls9)) | + (*(sptr - wpls10)) | + (*(sptr - wpls11)) | + (*(sptr - wpls12)) | + (*(sptr - wpls13)) | + (*(sptr - wpls14)) | + (*(sptr - wpls15)) | + (*(sptr - wpls16)) | + (*(sptr - wpls17)) | + (*(sptr - wpls18)) | + (*(sptr - wpls19)) | + (*(sptr - wpls20)) | + (*(sptr - wpls21)) | + (*(sptr - wpls22)) | + (*(sptr - wpls23)) | + (*(sptr - wpls24)) | + (*(sptr - wpls25)) | + (*(sptr - wpls26)) | + (*(sptr - wpls27)) | + (*(sptr - wpls28)) | + (*(sptr - wpls29)) | + (*(sptr - wpls30)); + } + } +} + +static void +ferode_3_121(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; +l_int32 wpls2, wpls3, wpls4; +l_int32 wpls5, wpls6, wpls7, wpls8; +l_int32 wpls9, wpls10, wpls11, wpls12; +l_int32 wpls13, wpls14, wpls15, wpls16; +l_int32 wpls17, wpls18, wpls19, wpls20; +l_int32 wpls21, wpls22, wpls23, wpls24; +l_int32 wpls25, wpls26, wpls27, wpls28; +l_int32 wpls29, wpls30; + + wpls2 = 2 * wpls; + wpls3 = 3 * wpls; + wpls4 = 4 * wpls; + wpls5 = 5 * wpls; + wpls6 = 6 * wpls; + wpls7 = 7 * wpls; + wpls8 = 8 * wpls; + wpls9 = 9 * wpls; + wpls10 = 10 * wpls; + wpls11 = 11 * wpls; + wpls12 = 12 * wpls; + wpls13 = 13 * wpls; + wpls14 = 14 * wpls; + wpls15 = 15 * wpls; + wpls16 = 16 * wpls; + wpls17 = 17 * wpls; + wpls18 = 18 * wpls; + wpls19 = 19 * wpls; + wpls20 = 20 * wpls; + wpls21 = 21 * wpls; + wpls22 = 22 * wpls; + wpls23 = 23 * wpls; + wpls24 = 24 * wpls; + wpls25 = 25 * wpls; + wpls26 = 26 * wpls; + wpls27 = 27 * wpls; + wpls28 = 28 * wpls; + wpls29 = 29 * wpls; + wpls30 = 30 * wpls; + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = (*(sptr - wpls30)) & + (*(sptr - wpls29)) & + (*(sptr - wpls28)) & + (*(sptr - wpls27)) & + (*(sptr - wpls26)) & + (*(sptr - wpls25)) & + (*(sptr - wpls24)) & + (*(sptr - wpls23)) & + (*(sptr - wpls22)) & + (*(sptr - wpls21)) & + (*(sptr - wpls20)) & + (*(sptr - wpls19)) & + (*(sptr - wpls18)) & + (*(sptr - wpls17)) & + (*(sptr - wpls16)) & + (*(sptr - wpls15)) & + (*(sptr - wpls14)) & + (*(sptr - wpls13)) & + (*(sptr - wpls12)) & + (*(sptr - wpls11)) & + (*(sptr - wpls10)) & + (*(sptr - wpls9)) & + (*(sptr - wpls8)) & + (*(sptr - wpls7)) & + (*(sptr - wpls6)) & + (*(sptr - wpls5)) & + (*(sptr - wpls4)) & + (*(sptr - wpls3)) & + (*(sptr - wpls2)) & + (*(sptr - wpls)) & + (*sptr) & + (*(sptr + wpls)) & + (*(sptr + wpls2)) & + (*(sptr + wpls3)) & + (*(sptr + wpls4)) & + (*(sptr + wpls5)) & + (*(sptr + wpls6)) & + (*(sptr + wpls7)) & + (*(sptr + wpls8)) & + (*(sptr + wpls9)) & + (*(sptr + wpls10)) & + (*(sptr + wpls11)) & + (*(sptr + wpls12)) & + (*(sptr + wpls13)) & + (*(sptr + wpls14)) & + (*(sptr + wpls15)) & + (*(sptr + wpls16)) & + (*(sptr + wpls17)) & + (*(sptr + wpls18)) & + (*(sptr + wpls19)) & + (*(sptr + wpls20)) & + (*(sptr + wpls21)) & + (*(sptr + wpls22)) & + (*(sptr + wpls23)) & + (*(sptr + wpls24)) & + (*(sptr + wpls25)) & + (*(sptr + wpls26)) & + (*(sptr + wpls27)) & + (*(sptr + wpls28)) & + (*(sptr + wpls29)) & + (*(sptr + wpls30)); + } + } +} + +static void +fdilate_3_122(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; +l_int32 wpls2, wpls3, wpls4; +l_int32 wpls5, wpls6, wpls7, wpls8; +l_int32 wpls9, wpls10, wpls11, wpls12; +l_int32 wpls13, wpls14, wpls15, wpls16; +l_int32 wpls17, wpls18, wpls19, wpls20; +l_int32 wpls21, wpls22, wpls23, wpls24; +l_int32 wpls25, wpls26, wpls27, wpls28; +l_int32 wpls29, wpls30, wpls31; + + wpls2 = 2 * wpls; + wpls3 = 3 * wpls; + wpls4 = 4 * wpls; + wpls5 = 5 * wpls; + wpls6 = 6 * wpls; + wpls7 = 7 * wpls; + wpls8 = 8 * wpls; + wpls9 = 9 * wpls; + wpls10 = 10 * wpls; + wpls11 = 11 * wpls; + wpls12 = 12 * wpls; + wpls13 = 13 * wpls; + wpls14 = 14 * wpls; + wpls15 = 15 * wpls; + wpls16 = 16 * wpls; + wpls17 = 17 * wpls; + wpls18 = 18 * wpls; + wpls19 = 19 * wpls; + wpls20 = 20 * wpls; + wpls21 = 21 * wpls; + wpls22 = 22 * wpls; + wpls23 = 23 * wpls; + wpls24 = 24 * wpls; + wpls25 = 25 * wpls; + wpls26 = 26 * wpls; + wpls27 = 27 * wpls; + wpls28 = 28 * wpls; + wpls29 = 29 * wpls; + wpls30 = 30 * wpls; + wpls31 = 31 * wpls; + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = (*(sptr + wpls31)) | + (*(sptr + wpls30)) | + (*(sptr + wpls29)) | + (*(sptr + wpls28)) | + (*(sptr + wpls27)) | + (*(sptr + wpls26)) | + (*(sptr + wpls25)) | + (*(sptr + wpls24)) | + (*(sptr + wpls23)) | + (*(sptr + wpls22)) | + (*(sptr + wpls21)) | + (*(sptr + wpls20)) | + (*(sptr + wpls19)) | + (*(sptr + wpls18)) | + (*(sptr + wpls17)) | + (*(sptr + wpls16)) | + (*(sptr + wpls15)) | + (*(sptr + wpls14)) | + (*(sptr + wpls13)) | + (*(sptr + wpls12)) | + (*(sptr + wpls11)) | + (*(sptr + wpls10)) | + (*(sptr + wpls9)) | + (*(sptr + wpls8)) | + (*(sptr + wpls7)) | + (*(sptr + wpls6)) | + (*(sptr + wpls5)) | + (*(sptr + wpls4)) | + (*(sptr + wpls3)) | + (*(sptr + wpls2)) | + (*(sptr + wpls)) | + (*sptr) | + (*(sptr - wpls)) | + (*(sptr - wpls2)) | + (*(sptr - wpls3)) | + (*(sptr - wpls4)) | + (*(sptr - wpls5)) | + (*(sptr - wpls6)) | + (*(sptr - wpls7)) | + (*(sptr - wpls8)) | + (*(sptr - wpls9)) | + (*(sptr - wpls10)) | + (*(sptr - wpls11)) | + (*(sptr - wpls12)) | + (*(sptr - wpls13)) | + (*(sptr - wpls14)) | + (*(sptr - wpls15)) | + (*(sptr - wpls16)) | + (*(sptr - wpls17)) | + (*(sptr - wpls18)) | + (*(sptr - wpls19)) | + (*(sptr - wpls20)) | + (*(sptr - wpls21)) | + (*(sptr - wpls22)) | + (*(sptr - wpls23)) | + (*(sptr - wpls24)) | + (*(sptr - wpls25)) | + (*(sptr - wpls26)) | + (*(sptr - wpls27)) | + (*(sptr - wpls28)) | + (*(sptr - wpls29)) | + (*(sptr - wpls30)); + } + } +} + +static void +ferode_3_122(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; +l_int32 wpls2, wpls3, wpls4; +l_int32 wpls5, wpls6, wpls7, wpls8; +l_int32 wpls9, wpls10, wpls11, wpls12; +l_int32 wpls13, wpls14, wpls15, wpls16; +l_int32 wpls17, wpls18, wpls19, wpls20; +l_int32 wpls21, wpls22, wpls23, wpls24; +l_int32 wpls25, wpls26, wpls27, wpls28; +l_int32 wpls29, wpls30, wpls31; + + wpls2 = 2 * wpls; + wpls3 = 3 * wpls; + wpls4 = 4 * wpls; + wpls5 = 5 * wpls; + wpls6 = 6 * wpls; + wpls7 = 7 * wpls; + wpls8 = 8 * wpls; + wpls9 = 9 * wpls; + wpls10 = 10 * wpls; + wpls11 = 11 * wpls; + wpls12 = 12 * wpls; + wpls13 = 13 * wpls; + wpls14 = 14 * wpls; + wpls15 = 15 * wpls; + wpls16 = 16 * wpls; + wpls17 = 17 * wpls; + wpls18 = 18 * wpls; + wpls19 = 19 * wpls; + wpls20 = 20 * wpls; + wpls21 = 21 * wpls; + wpls22 = 22 * wpls; + wpls23 = 23 * wpls; + wpls24 = 24 * wpls; + wpls25 = 25 * wpls; + wpls26 = 26 * wpls; + wpls27 = 27 * wpls; + wpls28 = 28 * wpls; + wpls29 = 29 * wpls; + wpls30 = 30 * wpls; + wpls31 = 31 * wpls; + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = (*(sptr - wpls31)) & + (*(sptr - wpls30)) & + (*(sptr - wpls29)) & + (*(sptr - wpls28)) & + (*(sptr - wpls27)) & + (*(sptr - wpls26)) & + (*(sptr - wpls25)) & + (*(sptr - wpls24)) & + (*(sptr - wpls23)) & + (*(sptr - wpls22)) & + (*(sptr - wpls21)) & + (*(sptr - wpls20)) & + (*(sptr - wpls19)) & + (*(sptr - wpls18)) & + (*(sptr - wpls17)) & + (*(sptr - wpls16)) & + (*(sptr - wpls15)) & + (*(sptr - wpls14)) & + (*(sptr - wpls13)) & + (*(sptr - wpls12)) & + (*(sptr - wpls11)) & + (*(sptr - wpls10)) & + (*(sptr - wpls9)) & + (*(sptr - wpls8)) & + (*(sptr - wpls7)) & + (*(sptr - wpls6)) & + (*(sptr - wpls5)) & + (*(sptr - wpls4)) & + (*(sptr - wpls3)) & + (*(sptr - wpls2)) & + (*(sptr - wpls)) & + (*sptr) & + (*(sptr + wpls)) & + (*(sptr + wpls2)) & + (*(sptr + wpls3)) & + (*(sptr + wpls4)) & + (*(sptr + wpls5)) & + (*(sptr + wpls6)) & + (*(sptr + wpls7)) & + (*(sptr + wpls8)) & + (*(sptr + wpls9)) & + (*(sptr + wpls10)) & + (*(sptr + wpls11)) & + (*(sptr + wpls12)) & + (*(sptr + wpls13)) & + (*(sptr + wpls14)) & + (*(sptr + wpls15)) & + (*(sptr + wpls16)) & + (*(sptr + wpls17)) & + (*(sptr + wpls18)) & + (*(sptr + wpls19)) & + (*(sptr + wpls20)) & + (*(sptr + wpls21)) & + (*(sptr + wpls22)) & + (*(sptr + wpls23)) & + (*(sptr + wpls24)) & + (*(sptr + wpls25)) & + (*(sptr + wpls26)) & + (*(sptr + wpls27)) & + (*(sptr + wpls28)) & + (*(sptr + wpls29)) & + (*(sptr + wpls30)); + } + } +} + +static void +fdilate_3_123(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; +l_int32 wpls2, wpls3, wpls4; +l_int32 wpls5, wpls6, wpls7, wpls8; +l_int32 wpls9, wpls10, wpls11, wpls12; +l_int32 wpls13, wpls14, wpls15, wpls16; +l_int32 wpls17, wpls18, wpls19, wpls20; +l_int32 wpls21, wpls22, wpls23, wpls24; +l_int32 wpls25, wpls26, wpls27, wpls28; +l_int32 wpls29, wpls30, wpls31; + + wpls2 = 2 * wpls; + wpls3 = 3 * wpls; + wpls4 = 4 * wpls; + wpls5 = 5 * wpls; + wpls6 = 6 * wpls; + wpls7 = 7 * wpls; + wpls8 = 8 * wpls; + wpls9 = 9 * wpls; + wpls10 = 10 * wpls; + wpls11 = 11 * wpls; + wpls12 = 12 * wpls; + wpls13 = 13 * wpls; + wpls14 = 14 * wpls; + wpls15 = 15 * wpls; + wpls16 = 16 * wpls; + wpls17 = 17 * wpls; + wpls18 = 18 * wpls; + wpls19 = 19 * wpls; + wpls20 = 20 * wpls; + wpls21 = 21 * wpls; + wpls22 = 22 * wpls; + wpls23 = 23 * wpls; + wpls24 = 24 * wpls; + wpls25 = 25 * wpls; + wpls26 = 26 * wpls; + wpls27 = 27 * wpls; + wpls28 = 28 * wpls; + wpls29 = 29 * wpls; + wpls30 = 30 * wpls; + wpls31 = 31 * wpls; + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = (*(sptr + wpls31)) | + (*(sptr + wpls30)) | + (*(sptr + wpls29)) | + (*(sptr + wpls28)) | + (*(sptr + wpls27)) | + (*(sptr + wpls26)) | + (*(sptr + wpls25)) | + (*(sptr + wpls24)) | + (*(sptr + wpls23)) | + (*(sptr + wpls22)) | + (*(sptr + wpls21)) | + (*(sptr + wpls20)) | + (*(sptr + wpls19)) | + (*(sptr + wpls18)) | + (*(sptr + wpls17)) | + (*(sptr + wpls16)) | + (*(sptr + wpls15)) | + (*(sptr + wpls14)) | + (*(sptr + wpls13)) | + (*(sptr + wpls12)) | + (*(sptr + wpls11)) | + (*(sptr + wpls10)) | + (*(sptr + wpls9)) | + (*(sptr + wpls8)) | + (*(sptr + wpls7)) | + (*(sptr + wpls6)) | + (*(sptr + wpls5)) | + (*(sptr + wpls4)) | + (*(sptr + wpls3)) | + (*(sptr + wpls2)) | + (*(sptr + wpls)) | + (*sptr) | + (*(sptr - wpls)) | + (*(sptr - wpls2)) | + (*(sptr - wpls3)) | + (*(sptr - wpls4)) | + (*(sptr - wpls5)) | + (*(sptr - wpls6)) | + (*(sptr - wpls7)) | + (*(sptr - wpls8)) | + (*(sptr - wpls9)) | + (*(sptr - wpls10)) | + (*(sptr - wpls11)) | + (*(sptr - wpls12)) | + (*(sptr - wpls13)) | + (*(sptr - wpls14)) | + (*(sptr - wpls15)) | + (*(sptr - wpls16)) | + (*(sptr - wpls17)) | + (*(sptr - wpls18)) | + (*(sptr - wpls19)) | + (*(sptr - wpls20)) | + (*(sptr - wpls21)) | + (*(sptr - wpls22)) | + (*(sptr - wpls23)) | + (*(sptr - wpls24)) | + (*(sptr - wpls25)) | + (*(sptr - wpls26)) | + (*(sptr - wpls27)) | + (*(sptr - wpls28)) | + (*(sptr - wpls29)) | + (*(sptr - wpls30)) | + (*(sptr - wpls31)); + } + } +} + +static void +ferode_3_123(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; +l_int32 wpls2, wpls3, wpls4; +l_int32 wpls5, wpls6, wpls7, wpls8; +l_int32 wpls9, wpls10, wpls11, wpls12; +l_int32 wpls13, wpls14, wpls15, wpls16; +l_int32 wpls17, wpls18, wpls19, wpls20; +l_int32 wpls21, wpls22, wpls23, wpls24; +l_int32 wpls25, wpls26, wpls27, wpls28; +l_int32 wpls29, wpls30, wpls31; + + wpls2 = 2 * wpls; + wpls3 = 3 * wpls; + wpls4 = 4 * wpls; + wpls5 = 5 * wpls; + wpls6 = 6 * wpls; + wpls7 = 7 * wpls; + wpls8 = 8 * wpls; + wpls9 = 9 * wpls; + wpls10 = 10 * wpls; + wpls11 = 11 * wpls; + wpls12 = 12 * wpls; + wpls13 = 13 * wpls; + wpls14 = 14 * wpls; + wpls15 = 15 * wpls; + wpls16 = 16 * wpls; + wpls17 = 17 * wpls; + wpls18 = 18 * wpls; + wpls19 = 19 * wpls; + wpls20 = 20 * wpls; + wpls21 = 21 * wpls; + wpls22 = 22 * wpls; + wpls23 = 23 * wpls; + wpls24 = 24 * wpls; + wpls25 = 25 * wpls; + wpls26 = 26 * wpls; + wpls27 = 27 * wpls; + wpls28 = 28 * wpls; + wpls29 = 29 * wpls; + wpls30 = 30 * wpls; + wpls31 = 31 * wpls; + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = (*(sptr - wpls31)) & + (*(sptr - wpls30)) & + (*(sptr - wpls29)) & + (*(sptr - wpls28)) & + (*(sptr - wpls27)) & + (*(sptr - wpls26)) & + (*(sptr - wpls25)) & + (*(sptr - wpls24)) & + (*(sptr - wpls23)) & + (*(sptr - wpls22)) & + (*(sptr - wpls21)) & + (*(sptr - wpls20)) & + (*(sptr - wpls19)) & + (*(sptr - wpls18)) & + (*(sptr - wpls17)) & + (*(sptr - wpls16)) & + (*(sptr - wpls15)) & + (*(sptr - wpls14)) & + (*(sptr - wpls13)) & + (*(sptr - wpls12)) & + (*(sptr - wpls11)) & + (*(sptr - wpls10)) & + (*(sptr - wpls9)) & + (*(sptr - wpls8)) & + (*(sptr - wpls7)) & + (*(sptr - wpls6)) & + (*(sptr - wpls5)) & + (*(sptr - wpls4)) & + (*(sptr - wpls3)) & + (*(sptr - wpls2)) & + (*(sptr - wpls)) & + (*sptr) & + (*(sptr + wpls)) & + (*(sptr + wpls2)) & + (*(sptr + wpls3)) & + (*(sptr + wpls4)) & + (*(sptr + wpls5)) & + (*(sptr + wpls6)) & + (*(sptr + wpls7)) & + (*(sptr + wpls8)) & + (*(sptr + wpls9)) & + (*(sptr + wpls10)) & + (*(sptr + wpls11)) & + (*(sptr + wpls12)) & + (*(sptr + wpls13)) & + (*(sptr + wpls14)) & + (*(sptr + wpls15)) & + (*(sptr + wpls16)) & + (*(sptr + wpls17)) & + (*(sptr + wpls18)) & + (*(sptr + wpls19)) & + (*(sptr + wpls20)) & + (*(sptr + wpls21)) & + (*(sptr + wpls22)) & + (*(sptr + wpls23)) & + (*(sptr + wpls24)) & + (*(sptr + wpls25)) & + (*(sptr + wpls26)) & + (*(sptr + wpls27)) & + (*(sptr + wpls28)) & + (*(sptr + wpls29)) & + (*(sptr + wpls30)) & + (*(sptr + wpls31)); + } + } +} + diff --git a/leptonica/prog/dwamorph1_reg.c b/leptonica/prog/dwamorph1_reg.c new file mode 100644 index 00000000..bc08f5ef --- /dev/null +++ b/leptonica/prog/dwamorph1_reg.c @@ -0,0 +1,244 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * dwamorph1_reg.c + * + * Fairly thorough regression test for autogen'd dwa. + * + * The dwa code always implements safe closing. With asymmetric + * b.c., the rasterop function must be pixCloseSafe(). + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + + /* defined in morph.c */ +LEPT_DLL extern l_int32 MORPH_BC; + + /* Complete set of linear brick dwa operations */ +PIX *pixMorphDwa_3(PIX *pixd, PIX *pixs, l_int32 operation, char *selname); +PIX *pixFMorphopGen_3(PIX *pixd, PIX *pixs, l_int32 operation, char *selname); + + +int main(int argc, + char **argv) +{ +l_int32 i, nsels, same, xorcount; +char *selname; +PIX *pixs, *pixt1, *pixt2, *pixt3; +SEL *sel; +SELA *sela; +L_REGPARAMS *rp; + + if (regTestSetup(argc, argv, &rp)) + return 1; + + if ((pixs = pixRead("feyn-fract.tif")) == NULL) { + rp->success = FALSE; + return regTestCleanup(rp); + } + sela = selaAddDwaLinear(NULL); + nsels = selaGetCount(sela); + + for (i = 0; i < nsels; i++) + { + sel = selaGetSel(sela, i); + selname = selGetName(sel); + + /* --------- dilation ----------*/ + + pixt1 = pixDilate(NULL, pixs, sel); + pixt2 = pixMorphDwa_3(NULL, pixs, L_MORPH_DILATE, selname); + pixEqual(pixt1, pixt2, &same); + + if (same == 1) { + if (rp->display) + lept_stderr("dilations are identical for sel %d (%s)\n", + i, selname); + } else { + rp->success = FALSE; + fprintf(rp->fp, "dilations differ for sel %d (%s)\n", i, selname); + pixt3 = pixXor(NULL, pixt1, pixt2); + pixCountPixels(pixt3, &xorcount, NULL); + fprintf(rp->fp, "Number of pixels in XOR: %d\n", xorcount); + pixDestroy(&pixt3); + } + pixDestroy(&pixt1); + pixDestroy(&pixt2); + + /* --------- erosion with asymmetric b.c ----------*/ + + resetMorphBoundaryCondition(ASYMMETRIC_MORPH_BC); + if (rp->display) lept_stderr("MORPH_BC = %d ... ", MORPH_BC); + + pixt1 = pixErode(NULL, pixs, sel); + pixt2 = pixMorphDwa_3(NULL, pixs, L_MORPH_ERODE, selname); + pixEqual(pixt1, pixt2, &same); + + if (same == 1) { + if (rp->display) + lept_stderr("erosions are identical for sel %d (%s)\n", + i, selname); + } else { + rp->success = FALSE; + fprintf(rp->fp, "erosions differ for sel %d (%s)\n", i, selname); + pixt3 = pixXor(NULL, pixt1, pixt2); + pixCountPixels(pixt3, &xorcount, NULL); + fprintf(rp->fp, "Number of pixels in XOR: %d\n", xorcount); + pixDestroy(&pixt3); + } + pixDestroy(&pixt1); + pixDestroy(&pixt2); + + /* --------- erosion with symmetric b.c ----------*/ + + resetMorphBoundaryCondition(SYMMETRIC_MORPH_BC); + if (rp->display) lept_stderr("MORPH_BC = %d ... ", MORPH_BC); + + pixt1 = pixErode(NULL, pixs, sel); + pixt2 = pixMorphDwa_3(NULL, pixs, L_MORPH_ERODE, selname); + pixEqual(pixt1, pixt2, &same); + + if (same == 1) { + if (rp->display) + lept_stderr("erosions are identical for sel %d (%s)\n", + i, selname); + } else { + rp->success = FALSE; + fprintf(rp->fp, "erosions differ for sel %d (%s)\n", i, selname); + pixt3 = pixXor(NULL, pixt1, pixt2); + pixCountPixels(pixt3, &xorcount, NULL); + fprintf(rp->fp, "Number of pixels in XOR: %d\n", xorcount); + pixDestroy(&pixt3); + } + pixDestroy(&pixt1); + pixDestroy(&pixt2); + + /* --------- opening with asymmetric b.c ----------*/ + + resetMorphBoundaryCondition(ASYMMETRIC_MORPH_BC); + if (rp->display) lept_stderr("MORPH_BC = %d ... ", MORPH_BC); + + pixt1 = pixOpen(NULL, pixs, sel); + pixt2 = pixMorphDwa_3(NULL, pixs, L_MORPH_OPEN, selname); + pixEqual(pixt1, pixt2, &same); + + if (same == 1) { + if (rp->display) + lept_stderr("openings are identical for sel %d (%s)\n", + i, selname); + } else { + rp->success = FALSE; + fprintf(rp->fp, "openings differ for sel %d (%s)\n", i, selname); + pixt3 = pixXor(NULL, pixt1, pixt2); + pixCountPixels(pixt3, &xorcount, NULL); + fprintf(rp->fp, "Number of pixels in XOR: %d\n", xorcount); + pixDestroy(&pixt3); + } + pixDestroy(&pixt1); + pixDestroy(&pixt2); + + /* --------- opening with symmetric b.c ----------*/ + + resetMorphBoundaryCondition(SYMMETRIC_MORPH_BC); + if (rp->display) lept_stderr("MORPH_BC = %d ... ", MORPH_BC); + + pixt1 = pixOpen(NULL, pixs, sel); + pixt2 = pixMorphDwa_3(NULL, pixs, L_MORPH_OPEN, selname); + pixEqual(pixt1, pixt2, &same); + + if (same == 1) { + if (rp->display) + lept_stderr("openings are identical for sel %d (%s)\n", + i, selname); + } else { + rp->success = FALSE; + fprintf(rp->fp, "openings differ for sel %d (%s)\n", i, selname); + pixt3 = pixXor(NULL, pixt1, pixt2); + pixCountPixels(pixt3, &xorcount, NULL); + fprintf(rp->fp, "Number of pixels in XOR: %d\n", xorcount); + pixDestroy(&pixt3); + } + pixDestroy(&pixt1); + pixDestroy(&pixt2); + + /* --------- safe closing with asymmetric b.c ----------*/ + + resetMorphBoundaryCondition(ASYMMETRIC_MORPH_BC); + if (rp->display) lept_stderr("MORPH_BC = %d ... ", MORPH_BC); + + pixt1 = pixCloseSafe(NULL, pixs, sel); /* must use safe version */ + pixt2 = pixMorphDwa_3(NULL, pixs, L_MORPH_CLOSE, selname); + pixEqual(pixt1, pixt2, &same); + + if (same == 1) { + if (rp->display) + lept_stderr("closings are identical for sel %d (%s)\n", + i, selname); + } else { + rp->success = FALSE; + fprintf(rp->fp, "closings differ for sel %d (%s)\n", i, selname); + pixt3 = pixXor(NULL, pixt1, pixt2); + pixCountPixels(pixt3, &xorcount, NULL); + fprintf(rp->fp, "Number of pixels in XOR: %d\n", xorcount); + pixDestroy(&pixt3); + } + pixDestroy(&pixt1); + pixDestroy(&pixt2); + + /* --------- safe closing with symmetric b.c ----------*/ + + resetMorphBoundaryCondition(SYMMETRIC_MORPH_BC); + if (rp->display) lept_stderr("MORPH_BC = %d ... ", MORPH_BC); + + pixt1 = pixClose(NULL, pixs, sel); /* safe version not required */ + pixt2 = pixMorphDwa_3(NULL, pixs, L_MORPH_CLOSE, selname); + pixEqual(pixt1, pixt2, &same); + + if (same == 1) { + if (rp->display) + lept_stderr("closings are identical for sel %d (%s)\n", + i, selname); + } else { + rp->success = FALSE; + fprintf(rp->fp, "closings differ for sel %d (%s)\n", i, selname); + pixt3 = pixXor(NULL, pixt1, pixt2); + pixCountPixels(pixt3, &xorcount, NULL); + fprintf(rp->fp, "Number of pixels in XOR: %d\n", xorcount); + pixDestroy(&pixt3); + } + pixDestroy(&pixt1); + pixDestroy(&pixt2); + } + + selaDestroy(&sela); + pixDestroy(&pixs); + return regTestCleanup(rp); +} diff --git a/leptonica/prog/dwamorph2_reg.c b/leptonica/prog/dwamorph2_reg.c new file mode 100644 index 00000000..8e2a2aea --- /dev/null +++ b/leptonica/prog/dwamorph2_reg.c @@ -0,0 +1,321 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * dwamorph2_reg.c + * + * Compare the timings of various binary morphological implementations. + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + +#define HALFWIDTH 3 + + /* Complete set of linear brick dwa operations */ +PIX *pixMorphDwa_3(PIX *pixd, PIX *pixs, l_int32 operation, char *selname); + +static const l_int32 NTIMES = 20; + +int main(int argc, + char **argv) +{ +char *selname; +l_int32 i, j, nsels, sx, sy; +l_float32 fact, time; +GPLOT *gplot; +NUMA *na1, *na2, *na3, *na4, *nac1, *nac2, *nac3, *nac4, *nax; +PIX *pixs, *pixt; +PIXA *pixa; +SEL *sel; +SELA *selalinear; +static char mainName[] = "dwamorph2_reg"; + + if (argc != 1) + return ERROR_INT(" Syntax: dwamorph2_reg", mainName, 1); + setLeptDebugOK(1); + + pixs = pixRead("feyn-fract.tif"); + pixt = pixCreateTemplate(pixs); + selalinear = selaAddDwaLinear(NULL); + nsels = selaGetCount(selalinear); + + fact = 1000. / (l_float32)NTIMES; /* converts to time in msec */ + na1 = numaCreate(64); + na2 = numaCreate(64); + na3 = numaCreate(64); + na4 = numaCreate(64); + + lept_mkdir("lept/morph"); + + /* --------- dilation ----------*/ + + for (i = 0; i < nsels / 2; i++) + { + sel = selaGetSel(selalinear, i); + selGetParameters(sel, &sy, &sx, NULL, NULL); + selname = selGetName(sel); + lept_stderr(" %d .", i); + + startTimer(); + for (j = 0; j < NTIMES; j++) + pixDilate(pixt, pixs, sel); + time = fact * stopTimer(); + numaAddNumber(na1, time); + + startTimer(); + for (j = 0; j < NTIMES; j++) + pixDilateCompBrick(pixt, pixs, sx, sy); + time = fact * stopTimer(); + numaAddNumber(na2, time); + + startTimer(); + for (j = 0; j < NTIMES; j++) + pixMorphDwa_3(pixt, pixs, L_MORPH_DILATE, selname); + time = fact * stopTimer(); + numaAddNumber(na3, time); + + startTimer(); + for (j = 0; j < NTIMES; j++) + pixDilateCompBrickDwa(pixt, pixs, sx, sy); + time = fact * stopTimer(); + numaAddNumber(na4, time); + } + + nax = numaMakeSequence(2, 1, nsels / 2); + nac1 = numaWindowedMean(na1, HALFWIDTH); + nac2 = numaWindowedMean(na2, HALFWIDTH); + nac3 = numaWindowedMean(na3, HALFWIDTH); + nac4 = numaWindowedMean(na4, HALFWIDTH); + gplot = gplotCreate("/tmp/lept/morph/dilate", GPLOT_PNG, + "Dilation time vs sel size", "size", "time (ms)"); + gplotAddPlot(gplot, nax, nac1, GPLOT_LINES, "linear rasterop"); + gplotAddPlot(gplot, nax, nac2, GPLOT_LINES, "composite rasterop"); + gplotAddPlot(gplot, nax, nac3, GPLOT_LINES, "linear dwa"); + gplotAddPlot(gplot, nax, nac4, GPLOT_LINES, "composite dwa"); + gplotMakeOutput(gplot); + gplotDestroy(&gplot); + numaDestroy(&nac1); + numaDestroy(&nac2); + numaDestroy(&nac3); + numaDestroy(&nac4); + + /* --------- erosion ----------*/ + + numaEmpty(na1); + numaEmpty(na2); + numaEmpty(na3); + numaEmpty(na4); + for (i = 0; i < nsels / 2; i++) + { + sel = selaGetSel(selalinear, i); + selGetParameters(sel, &sy, &sx, NULL, NULL); + selname = selGetName(sel); + lept_stderr(" %d .", i); + + startTimer(); + for (j = 0; j < NTIMES; j++) + pixErode(pixt, pixs, sel); + time = fact * stopTimer(); + numaAddNumber(na1, time); + + startTimer(); + for (j = 0; j < NTIMES; j++) + pixErodeCompBrick(pixt, pixs, sx, sy); + time = fact * stopTimer(); + numaAddNumber(na2, time); + + startTimer(); + for (j = 0; j < NTIMES; j++) + pixMorphDwa_3(pixt, pixs, L_MORPH_ERODE, selname); + time = fact * stopTimer(); + numaAddNumber(na3, time); + + startTimer(); + for (j = 0; j < NTIMES; j++) + pixErodeCompBrickDwa(pixt, pixs, sx, sy); + time = fact * stopTimer(); + numaAddNumber(na4, time); + } + + nac1 = numaWindowedMean(na1, HALFWIDTH); + nac2 = numaWindowedMean(na2, HALFWIDTH); + nac3 = numaWindowedMean(na3, HALFWIDTH); + nac4 = numaWindowedMean(na4, HALFWIDTH); + gplot = gplotCreate("/tmp/lept/morph/erode", GPLOT_PNG, + "Erosion time vs sel size", "size", "time (ms)"); + gplotAddPlot(gplot, nax, nac1, GPLOT_LINES, "linear rasterop"); + gplotAddPlot(gplot, nax, nac2, GPLOT_LINES, "composite rasterop"); + gplotAddPlot(gplot, nax, nac3, GPLOT_LINES, "linear dwa"); + gplotAddPlot(gplot, nax, nac4, GPLOT_LINES, "composite dwa"); + gplotMakeOutput(gplot); + gplotDestroy(&gplot); + numaDestroy(&nac1); + numaDestroy(&nac2); + numaDestroy(&nac3); + numaDestroy(&nac4); + + /* --------- opening ----------*/ + + numaEmpty(na1); + numaEmpty(na2); + numaEmpty(na3); + numaEmpty(na4); + for (i = 0; i < nsels / 2; i++) + { + sel = selaGetSel(selalinear, i); + selGetParameters(sel, &sy, &sx, NULL, NULL); + selname = selGetName(sel); + lept_stderr(" %d .", i); + + startTimer(); + for (j = 0; j < NTIMES; j++) + pixOpen(pixt, pixs, sel); + time = fact * stopTimer(); + numaAddNumber(na1, time); + + startTimer(); + for (j = 0; j < NTIMES; j++) + pixOpenCompBrick(pixt, pixs, sx, sy); + time = fact * stopTimer(); + numaAddNumber(na2, time); + + startTimer(); + for (j = 0; j < NTIMES; j++) + pixMorphDwa_3(pixt, pixs, L_MORPH_OPEN, selname); + time = fact * stopTimer(); + numaAddNumber(na3, time); + + startTimer(); + for (j = 0; j < NTIMES; j++) + pixOpenCompBrickDwa(pixt, pixs, sx, sy); + time = fact * stopTimer(); + numaAddNumber(na4, time); + } + + nac1 = numaWindowedMean(na1, HALFWIDTH); + nac2 = numaWindowedMean(na2, HALFWIDTH); + nac3 = numaWindowedMean(na3, HALFWIDTH); + nac4 = numaWindowedMean(na4, HALFWIDTH); + gplot = gplotCreate("/tmp/lept/morph/open", GPLOT_PNG, + "Opening time vs sel size", "size", "time (ms)"); + gplotAddPlot(gplot, nax, nac1, GPLOT_LINES, "linear rasterop"); + gplotAddPlot(gplot, nax, nac2, GPLOT_LINES, "composite rasterop"); + gplotAddPlot(gplot, nax, nac3, GPLOT_LINES, "linear dwa"); + gplotAddPlot(gplot, nax, nac4, GPLOT_LINES, "composite dwa"); + gplotMakeOutput(gplot); + gplotDestroy(&gplot); + numaDestroy(&nac1); + numaDestroy(&nac2); + numaDestroy(&nac3); + numaDestroy(&nac4); + + /* --------- closing ----------*/ + + numaEmpty(na1); + numaEmpty(na2); + numaEmpty(na3); + numaEmpty(na4); + for (i = 0; i < nsels / 2; i++) + { + sel = selaGetSel(selalinear, i); + selGetParameters(sel, &sy, &sx, NULL, NULL); + selname = selGetName(sel); + lept_stderr(" %d .", i); + + startTimer(); + for (j = 0; j < NTIMES; j++) + pixClose(pixt, pixs, sel); + time = fact * stopTimer(); + numaAddNumber(na1, time); + + startTimer(); + for (j = 0; j < NTIMES; j++) + pixCloseCompBrick(pixt, pixs, sx, sy); + time = fact * stopTimer(); + numaAddNumber(na2, time); + + startTimer(); + for (j = 0; j < NTIMES; j++) + pixMorphDwa_3(pixt, pixs, L_MORPH_CLOSE, selname); + time = fact * stopTimer(); + numaAddNumber(na3, time); + + startTimer(); + for (j = 0; j < NTIMES; j++) + pixCloseCompBrickDwa(pixt, pixs, sx, sy); + time = fact * stopTimer(); + numaAddNumber(na4, time); + } + + nac1 = numaWindowedMean(na1, HALFWIDTH); + nac2 = numaWindowedMean(na2, HALFWIDTH); + nac3 = numaWindowedMean(na3, HALFWIDTH); + nac4 = numaWindowedMean(na4, HALFWIDTH); + gplot = gplotCreate("/tmp/lept/morph/close", GPLOT_PNG, + "Closing time vs sel size", "size", "time (ms)"); + gplotAddPlot(gplot, nax, nac1, GPLOT_LINES, "linear rasterop"); + gplotAddPlot(gplot, nax, nac2, GPLOT_LINES, "composite rasterop"); + gplotAddPlot(gplot, nax, nac3, GPLOT_LINES, "linear dwa"); + gplotAddPlot(gplot, nax, nac4, GPLOT_LINES, "composite dwa"); + gplotMakeOutput(gplot); + gplotDestroy(&gplot); + numaDestroy(&nac1); + numaDestroy(&nac2); + numaDestroy(&nac3); + numaDestroy(&nac4); + + + numaDestroy(&na1); + numaDestroy(&na2); + numaDestroy(&na3); + numaDestroy(&na4); + numaDestroy(&nax); + selaDestroy(&selalinear); + pixDestroy(&pixt); + pixDestroy(&pixs); + + /* Display the results together */ + pixa = pixaCreate(0); + pixs = pixRead("/tmp/lept/morph/dilate.png"); + pixaAddPix(pixa, pixs, L_INSERT); + pixs = pixRead("/tmp/lept/morph/erode.png"); + pixaAddPix(pixa, pixs, L_INSERT); + pixs = pixRead("/tmp/lept/morph/open.png"); + pixaAddPix(pixa, pixs, L_INSERT); + pixs = pixRead("/tmp/lept/morph/close.png"); + pixaAddPix(pixa, pixs, L_INSERT); + pixt = pixaDisplayTiledInRows(pixa, 32, 1500, 1.0, 0, 40, 3); + pixWrite("/tmp/lept/morph/timings.png", pixt, IFF_PNG); + pixDisplay(pixt, 100, 100); + pixDestroy(&pixt); + pixaDestroy(&pixa); + return 0; +} + diff --git a/leptonica/prog/edge_reg.c b/leptonica/prog/edge_reg.c new file mode 100644 index 00000000..ba0a7932 --- /dev/null +++ b/leptonica/prog/edge_reg.c @@ -0,0 +1,90 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * edgetest.c + * + * Regression test for sobel edge filter. + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + +int main(int argc, + char **argv) +{ +l_int32 i, w, h; +PIX *pixs, *pix1, *pix2, *pix3, *pix4; +L_REGPARAMS *rp; + + if (regTestSetup(argc, argv, &rp)) + return 1; + + pixs = pixRead("test8.jpg"); + + /* Test speed: about 60 Mpix/sec/GHz */ + startTimer(); + for (i = 0; i < 100; i++) { + pix1 = pixSobelEdgeFilter(pixs, L_HORIZONTAL_EDGES); + pix2 = pixThresholdToBinary(pix1, 60); + pixInvert(pix2, pix2); + pixDestroy(&pix1); + pixDestroy(&pix2); + } + pixGetDimensions(pixs, &w, &h, NULL); + lept_stderr("Sobel edge MPix/sec: %7.3f\n", 0.0001 * w * h / stopTimer()); + + /* Horiz and vert sobel edges (1 bpp) */ + pix1 = pixSobelEdgeFilter(pixs, L_HORIZONTAL_EDGES); + pix2 = pixThresholdToBinary(pix1, 60); + pixInvert(pix2, pix2); + regTestWritePixAndCheck(rp, pix2, IFF_PNG); /* 0 */ + pixDisplayWithTitle(pix2, 0, 50, "Horizontal edges", rp->display); + pix3 = pixSobelEdgeFilter(pixs, L_VERTICAL_EDGES); + pix4 = pixThresholdToBinary(pix3, 60); + pixInvert(pix4, pix4); + regTestWritePixAndCheck(rp, pix4, IFF_PNG); /* 1 */ + pixDisplayWithTitle(pix4, 625, 50, "Vertical edges", rp->display); + pixOr(pix4, pix4, pix2); + regTestWritePixAndCheck(rp, pix4, IFF_PNG); /* 2 */ + pixDisplayWithTitle(pix4, 1200, 50, "Horiz and vert edges", rp->display); + pixDestroy(&pix2); + pixDestroy(&pix4); + + /* Horizontal and vertical sobel edges (8 bpp) */ + pixMinOrMax(pix1, pix1, pix3, L_CHOOSE_MAX); + pixInvert(pix1, pix1); + regTestWritePixAndCheck(rp, pix1, IFF_JFIF_JPEG); /* 3 */ + pixDisplayWithTitle(pix1, 0, 525, "8bpp Horiz and vert edges", rp->display); + pixDestroy(&pix1); + pixDestroy(&pix3); + pixDestroy(&pixs); + return regTestCleanup(rp); +} + diff --git a/leptonica/prog/encoding_reg.c b/leptonica/prog/encoding_reg.c new file mode 100644 index 00000000..412c05c9 --- /dev/null +++ b/leptonica/prog/encoding_reg.c @@ -0,0 +1,107 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * encoding_reg.c + * + * Regression test for encoding/decoding of binary data + * + * Ascii85 encoding/decoding Works properly with 0, 1, 2 or 3 extra + * bytes after the final full word. + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + +int main(int argc, + char **argv) +{ +size_t nbytes1, nbytes2, nbytes3, nbytes4, nbytes5, nbytes6, fbytes; +char *a85a, *a85c, *a85c2; +l_uint8 *bina, *bina2, *bin85c, *bin85c2; +PIX *pix1; +L_REGPARAMS *rp; + + if (regTestSetup(argc, argv, &rp)) + return 1; + + lept_mkdir("lept/encode"); + + /* Test ascii85 encoding */ + bina = l_binaryRead("karen8.jpg", &fbytes); + a85a = encodeAscii85(bina, fbytes, &nbytes1); + bina2 = decodeAscii85(a85a, nbytes1, &nbytes2); + regTestCompareValues(rp, fbytes, nbytes2, 0.0); /* 0 */ + + if (rp->display) { + lept_stderr("file bytes = %zu, a85 bytes = %zu, bina2 bytes = %zu\n", + fbytes, nbytes1, nbytes2); + } + l_binaryWrite("/tmp/lept/encode/ascii85", "w", a85a, nbytes1); + l_binaryWrite("/tmp/lept/encode/bina2", "w", bina2, nbytes2); + + /* Test the reconstructed image */ + pix1 = pixReadMem(bina2, nbytes2); + regTestWritePixAndCheck(rp, pix1, IFF_JFIF_JPEG); /* 1 */ + pixDisplayWithTitle(pix1, 100, 100, NULL, rp->display); + pixDestroy(&pix1); + + /* Test with compression, starting with ascii data */ + a85c = encodeAscii85WithComp((l_uint8 *)a85a, nbytes1, &nbytes3); + bin85c = decodeAscii85WithComp(a85c, nbytes3, &nbytes4); + regTestCompareStrings(rp, (l_uint8 *)a85a, nbytes1, + bin85c, nbytes4); /* 2 */ + + /* Test with compression, starting with binary data */ + a85c2 = encodeAscii85WithComp(bin85c, nbytes4, &nbytes5); + bin85c2 = decodeAscii85WithComp(a85c2, nbytes5, &nbytes6); + regTestCompareStrings(rp, bin85c, nbytes4, + bin85c2, nbytes6); /* 3 */ + lept_free(bina); + lept_free(bina2); + lept_free(a85a); + lept_free(a85c); + lept_free(bin85c); + lept_free(a85c2); + lept_free(bin85c2); + + /* Test storing and retrieving compressed text from pix */ + bina = l_binaryRead("weasel32.png", &nbytes1); + pix1 = pixRead("rabi.png"); + pixSetTextCompNew(pix1, bina, nbytes1); + bina2 = pixGetTextCompNew(pix1, &nbytes2); + if (rp->display) + lept_stderr("nbytes1 = %zu, nbytes2 = %zu\n", nbytes1, nbytes2); + regTestCompareStrings(rp, bina, nbytes1, bina2, nbytes2); /* 4 */ + pixDestroy(&pix1); + lept_free(bina); + lept_free(bina2); + + return regTestCleanup(rp); +} diff --git a/leptonica/prog/enhance_reg.c b/leptonica/prog/enhance_reg.c new file mode 100644 index 00000000..addb15f6 --- /dev/null +++ b/leptonica/prog/enhance_reg.c @@ -0,0 +1,298 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * enhance_reg.c + * + * This tests the following global "enhancement" functions: + * * TRC transforms with variation of gamma and black point + * * HSV transforms with variation of hue, saturation and intensity + * * Contrast variation + * * Sharpening + * * Color mapping to lighten background with constant hue + * * Linear color transform without mixing (diagonal) + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + + +int main(int argc, + char **argv) +{ +char textstr[256]; +l_int32 i, k, w, h; +l_uint32 srcval; +l_float32 scalefact, sat, fract; +L_BMF *bmf10; +L_KERNEL *kel; +NUMA *na1, *na2, *na3; +PIX *pix, *pixs, *pixs1, *pixs2, *pixd; +PIX *pix0, *pix1, *pix2, *pix3, *pix4; +PIXA *pixa1, *pixa2, *pixaf; +L_REGPARAMS *rp; + +#if !defined(HAVE_LIBPNG) + L_ERROR("This test requires libpng to run.\n", "enhance_reg"); + exit(77); +#endif + + if (regTestSetup(argc, argv, &rp)) + return 1; + + lept_mkdir("lept/enhance"); + pix = pixRead("test24.jpg"); /* rgb */ + w = pixGetWidth(pix); + scalefact = 150.0 / (l_float32)w; /* scale to w = 150 */ + pixs = pixScale(pix, scalefact, scalefact); + w = pixGetWidth(pixs); + pixaf = pixaCreate(5); + pixDestroy(&pix); + + /* TRC: vary gamma */ + pixa1 = pixaCreate(20); + for (i = 0; i < 20; i++) { + pix0 = pixGammaTRC(NULL, pixs, 0.3 + 0.15 * i, 0, 255); + pixaAddPix(pixa1, pix0, L_INSERT); + } + pix1 = pixaDisplayTiledAndScaled(pixa1, 32, w, 5, 0, 10, 2); + pixaAddPix(pixaf, pix1, L_INSERT); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 0 */ + pixDisplayWithTitle(pix1, 0, 100, "TRC Gamma", rp->display); + pixaDestroy(&pixa1); + + /* TRC: vary black point */ + pixa1 = pixaCreate(20); + for (i = 0; i < 20; i++) { + pix0 = pixGammaTRC(NULL, pixs, 1.0, 5 * i, 255); + pixaAddPix(pixa1, pix0, L_INSERT); + } + pix1 = pixaDisplayTiledAndScaled(pixa1, 32, w, 5, 0, 10, 2); + pixaAddPix(pixaf, pix1, L_INSERT); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 1 */ + pixDisplayWithTitle(pix1, 300, 100, "TRC", rp->display); + pixaDestroy(&pixa1); + + /* Vary hue */ + pixa1 = pixaCreate(20); + for (i = 0; i < 20; i++) { + pix0 = pixModifyHue(NULL, pixs, 0.01 + 0.05 * i); + pixaAddPix(pixa1, pix0, L_INSERT); + } + pix1 = pixaDisplayTiledAndScaled(pixa1, 32, w, 5, 0, 10, 2); + pixaAddPix(pixaf, pix1, L_INSERT); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 2 */ + pixDisplayWithTitle(pix1, 600, 100, "Hue", rp->display); + pixaDestroy(&pixa1); + + /* Vary saturation */ + pixa1 = pixaCreate(20); + na1 = numaCreate(20); + for (i = 0; i < 20; i++) { + pix0 = pixModifySaturation(NULL, pixs, -0.9 + 0.1 * i); + pixMeasureSaturation(pix0, 1, &sat); + pixaAddPix(pixa1, pix0, L_INSERT); + numaAddNumber(na1, sat); + } + pix1 = pixaDisplayTiledAndScaled(pixa1, 32, w, 5, 0, 10, 2); + pixaAddPix(pixaf, pix1, L_INSERT); + gplotSimple1(na1, GPLOT_PNG, "/tmp/lept/regout/enhance.7", + "Average Saturation"); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 3 */ + pixDisplayWithTitle(pix1, 900, 100, "Saturation", rp->display); + numaDestroy(&na1); + pixaDestroy(&pixa1); + + /* Vary contrast */ + pixa1 = pixaCreate(20); + for (i = 0; i < 20; i++) { + pix0 = pixContrastTRC(NULL, pixs, 0.1 * i); + pixaAddPix(pixa1, pix0, L_INSERT); + } + pix1 = pixaDisplayTiledAndScaled(pixa1, 32, w, 5, 0, 10, 2); + pixaAddPix(pixaf, pix1, L_INSERT); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 4 */ + pixDisplayWithTitle(pix1, 0, 400, "Contrast", rp->display); + pixaDestroy(&pixa1); + + /* Vary sharpening */ + pixa1 = pixaCreate(20); + for (i = 0; i < 20; i++) { + pix0 = pixUnsharpMasking(pixs, 3, 0.01 + 0.15 * i); + pixaAddPix(pixa1, pix0, L_INSERT); + } + pix1 = pixaDisplayTiledAndScaled(pixa1, 32, w, 5, 0, 10, 2); + pixaAddPix(pixaf, pix1, L_INSERT); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 5 */ + pixDisplayWithTitle(pix1, 300, 400, "Sharp", rp->display); + pixaDestroy(&pixa1); + + /* Hue constant mapping to lighter background */ + pixa2 = pixaCreate(2); + bmf10 = bmfCreate("fonts", 10); + pix0 = pixRead("candelabrum.011.jpg"); + composeRGBPixel(230, 185, 144, &srcval); /* select typical bg pixel */ + for (k = 1; k > -2; k -= 2) { + pixa1 = pixaCreate(11); + for (i = 0; i <= 10; i++) { + fract = k * 0.10 * i; + pix1 = pixMapWithInvariantHue(NULL, pix0, srcval, fract); + snprintf(textstr, 50, "Fract = %5.1f", fract); + pix2 = pixAddSingleTextblock(pix1, bmf10, textstr, 0xff000000, + L_ADD_BELOW, NULL); + pixaAddPix(pixa1, pix2, L_INSERT); + pixDestroy(&pix1); + } + pix3 = pixaDisplayTiledInColumns(pixa1, 4, 1.0, 30, 2); + pixaAddPix(pixa2, pix3, L_INSERT); + pixaDestroy(&pixa1); + } + pixd = pixaDisplayTiledInColumns(pixa2, 2, 0.5, 30, 2); + regTestWritePixAndCheck(rp, pixd, IFF_JFIF_JPEG); /* 6 */ + pixDisplayWithTitle(pixd, 600, 400, "Constant hue", rp->display); + pixaDestroy(&pixa2); + bmfDestroy(&bmf10); + pixDestroy(&pix0); + pixDestroy(&pixd); + + /* Delayed testing of saturation plot */ + regTestCheckFile(rp, "/tmp/lept/regout/enhance.7.png"); /* 7 */ + + /* Display results */ + pixd = pixaDisplayTiledInColumns(pixaf, 1, 1.0, 20, 2); + regTestWritePixAndCheck(rp, pixd, IFF_JFIF_JPEG); /* 8 */ + pixDisplayWithTitle(pixd, 100, 100, "All", rp->display); + pixDestroy(&pixd); + pixaDestroy(&pixaf); + + /* Test color shifts */ + pixd = pixMosaicColorShiftRGB(pixs, -0.1, 0.0, 0.0, 0.0999, 1); + regTestWritePixAndCheck(rp, pixd, IFF_JFIF_JPEG); /* 9 */ + pixDisplayWithTitle(pixd, 1000, 100, "Color shift", rp->display); + pixDestroy(&pixd); + pixDestroy(&pixs); + + /* More trc testing */ + pix = pixRead("test24.jpg"); /* rgb */ + pixs = pixScale(pix, 0.3, 0.3); + pixDestroy(&pix); + pixa1 = pixaCreate(5); + pixaAddPix(pixa1, pixs, L_COPY); + + na1 = numaGammaTRC(0.6, 40, 200); + na2 = numaGammaTRC(1.2, 40, 225); + na3 = numaGammaTRC(0.6, 40, 255); + pixGetDimensions(pixs, &w, &h, NULL); + pix1 = pixCopy(NULL, pixs); + pix2 = pixMakeSymmetricMask(w, h, 0.5, 0.5, L_USE_INNER); + pixaAddPix(pixa1, pix2, L_COPY); + pixTRCMapGeneral(pix1, pix2, na1, na2, na3); + pixaAddPix(pixa1, pix1, L_COPY); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 10 */ + numaDestroy(&na1); + numaDestroy(&na2); + numaDestroy(&na3); + pixDestroy(&pix1); + pixDestroy(&pix2); + + na1 = numaGammaTRC(1.0, 0, 255); + na2 = numaGammaTRC(1.0, 0, 255); + na3 = numaGammaTRC(1.0, 0, 255); + pix1 = pixCopy(NULL, pixs); + pixTRCMapGeneral(pix1, NULL, na1, na2, na3); + regTestComparePix(rp, pixs, pix1); /* 11 */ + numaDestroy(&na1); + numaDestroy(&na2); + numaDestroy(&na3); + pixDestroy(&pix1); + + na1 = numaGammaTRC(1.7, 150, 255); + na2 = numaGammaTRC(0.7, 0, 150); + na3 = numaGammaTRC(1.2, 80, 200); + pixTRCMapGeneral(pixs, NULL, na1, na2, na3); + regTestWritePixAndCheck(rp, pixs, IFF_PNG); /* 12 */ + pixaAddPix(pixa1, pixs, L_COPY); + numaDestroy(&na1); + numaDestroy(&na2); + numaDestroy(&na3); + pixDestroy(&pixs); + + na1 = numaGammaTRC(0.8, 0, 220); + na2 = numaGammaTRC(1.0, 40, 220); + gplotSimple2(na1, na2, GPLOT_PNG, "/tmp/lept/enhance/junkp", NULL); + pix1 = pixRead("/tmp/lept/enhance/junkp.png"); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 13 */ + pixaAddPix(pixa1, pix1, L_COPY); + numaDestroy(&na1); + numaDestroy(&na2); + pixDestroy(&pix1); + + pixd = pixaDisplayTiledInColumns(pixa1, 4, 1.0, 30, 2); + regTestWritePixAndCheck(rp, pixd, IFF_PNG); /* 14 */ + pixDisplayWithTitle(pixd, 100, 800, NULL, rp->display); + pixDestroy(&pixd); + pixaDestroy(&pixa1); + + /* -----------------------------------------------* + * Test global color transforms * + * -----------------------------------------------*/ + /* Make identical cmap and rgb images */ + pix = pixRead("wet-day.jpg"); + pixs1 = pixOctreeColorQuant(pix, 200, 0); + pixs2 = pixRemoveColormap(pixs1, REMOVE_CMAP_TO_FULL_COLOR); + regTestComparePix(rp, pixs1, pixs2); /* 15 */ + + /* Make a diagonal color transform matrix */ + kel = kernelCreate(3, 3); + kernelSetElement(kel, 0, 0, 0.7); + kernelSetElement(kel, 1, 1, 0.4); + kernelSetElement(kel, 2, 2, 1.3); + + /* Apply to both cmap and rgb images. */ + pix1 = pixMultMatrixColor(pixs1, kel); + pix2 = pixMultMatrixColor(pixs2, kel); + regTestComparePix(rp, pix1, pix2); /* 16 */ + kernelDestroy(&kel); + + /* Apply the same transform in the simpler interface */ + pix3 = pixMultConstantColor(pixs1, 0.7, 0.4, 1.3); + pix4 = pixMultConstantColor(pixs2, 0.7, 0.4, 1.3); + regTestComparePix(rp, pix3, pix4); /* 17 */ + regTestComparePix(rp, pix1, pix3); /* 18 */ + regTestWritePixAndCheck(rp, pix1, IFF_JFIF_JPEG); /* 19 */ + + pixDestroy(&pix); + pixDestroy(&pixs1); + pixDestroy(&pixs2); + pixDestroy(&pix1); + pixDestroy(&pix2); + pixDestroy(&pix3); + pixDestroy(&pix4); + return regTestCleanup(rp); +} diff --git a/leptonica/prog/equal_reg.c b/leptonica/prog/equal_reg.c new file mode 100644 index 00000000..2433b9ee --- /dev/null +++ b/leptonica/prog/equal_reg.c @@ -0,0 +1,139 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * equal_reg.c + * + * Tests the pixEqual() function in many situations. + * + * This also tests the quantization of grayscale and color + * images (to generate a colormapped image), and removal of + * the colormap to either RGB or grayscale. + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + + /* use this set */ +#define FEYN1 "feyn.tif" /* 1 bpp */ +#define DREYFUS2 "dreyfus2.png" /* 2 bpp cmapped */ +#define DREYFUS4 "dreyfus4.png" /* 4 bpp cmapped */ +#define DREYFUS8 "dreyfus8.png" /* 8 bpp cmapped */ +#define KAREN8 "karen8.jpg" /* 8 bpp, not cmapped */ +#define MARGE32 "marge.jpg" /* rgb */ + +int main(int argc, + char **argv) +{ +PIX *pixs, *pix1, *pix2, *pix3, *pix4; +L_REGPARAMS *rp; + + if (regTestSetup(argc, argv, &rp)) + return 1; + + lept_mkdir("lept/equal"); + + pixs = pixRead(FEYN1); + pixWrite("/tmp/lept/equal/junkfeyn.png", pixs, IFF_PNG); + pix1 = pixRead("/tmp/lept/equal/junkfeyn.png"); + regTestComparePix(rp, pixs, pix1); /* 0 */ + pixDestroy(&pixs); + pixDestroy(&pix1); + + pixs = pixRead(DREYFUS2); + pix1 = pixRemoveColormap(pixs, REMOVE_CMAP_BASED_ON_SRC); + pix2 = pixRemoveColormap(pixs, REMOVE_CMAP_TO_FULL_COLOR); + pix3 = pixOctreeQuantNumColors(pix2, 64, 1); + pix4 = pixConvertRGBToColormap(pix2, 1); + regTestComparePix(rp, pixs, pix1); /* 1 */ + regTestComparePix(rp, pixs, pix2); /* 2 */ + regTestComparePix(rp, pixs, pix3); /* 3 */ + regTestComparePix(rp, pixs, pix4); /* 4 */ + pixDestroy(&pixs); + pixDestroy(&pix1); + pixDestroy(&pix2); + pixDestroy(&pix3); + pixDestroy(&pix4); + + pixs = pixRead(DREYFUS4); + pix1 = pixRemoveColormap(pixs, REMOVE_CMAP_BASED_ON_SRC); + pix2 = pixRemoveColormap(pixs, REMOVE_CMAP_TO_FULL_COLOR); + pix3 = pixOctreeQuantNumColors(pix2, 256, 1); + pix4 = pixConvertRGBToColormap(pix2, 1); + regTestComparePix(rp, pixs, pix1); /* 5 */ + regTestComparePix(rp, pixs, pix2); /* 6 */ + regTestComparePix(rp, pixs, pix3); /* 7 */ + regTestComparePix(rp, pixs, pix4); /* 8 */ + pixDestroy(&pixs); + pixDestroy(&pix1); + pixDestroy(&pix2); + pixDestroy(&pix3); + pixDestroy(&pix4); + + pixs = pixRead(DREYFUS8); + pix1 = pixRemoveColormap(pixs, REMOVE_CMAP_BASED_ON_SRC); + pix2 = pixRemoveColormap(pixs, REMOVE_CMAP_TO_FULL_COLOR); + pix3 = pixConvertRGBToColormap(pix2, 1); + regTestComparePix(rp, pixs, pix1); /* 9 */ + regTestComparePix(rp, pixs, pix2); /* 10 */ + pixDestroy(&pixs); + pixDestroy(&pix1); + pixDestroy(&pix2); + pixDestroy(&pix3); + + pixs = pixRead(KAREN8); + pix1 = pixThresholdTo4bpp(pixs, 16, 1); + pix2 = pixRemoveColormap(pix1, REMOVE_CMAP_BASED_ON_SRC); + pix3 = pixRemoveColormap(pix1, REMOVE_CMAP_TO_FULL_COLOR); + pix4 = pixConvertRGBToColormap(pix3, 1); + regTestComparePix(rp, pix1, pix2); /* 11 */ + regTestComparePix(rp, pix1, pix3); /* 12 */ + regTestComparePix(rp, pix1, pix4); /* 13 */ + pixDestroy(&pixs); + pixDestroy(&pix1); + pixDestroy(&pix2); + pixDestroy(&pix3); + pixDestroy(&pix4); + + pixs = pixRead(MARGE32); + pix1 = pixOctreeQuantNumColors(pixs, 32, 0); + pix2 = pixRemoveColormap(pix1, REMOVE_CMAP_TO_FULL_COLOR); + pix3 = pixConvertRGBToColormap(pix2, 1); + pix4 = pixOctreeQuantNumColors(pix2, 64, 0); + regTestComparePix(rp, pix1, pix2); /* 14 */ + regTestComparePix(rp, pix1, pix3); /* 15 */ + regTestComparePix(rp, pix1, pix4); /* 16 */ + pixDestroy(&pixs); + pixDestroy(&pix1); + pixDestroy(&pix2); + pixDestroy(&pix3); + pixDestroy(&pix4); + return regTestCleanup(rp); +} + diff --git a/leptonica/prog/expand_reg.c b/leptonica/prog/expand_reg.c new file mode 100644 index 00000000..3e99af17 --- /dev/null +++ b/leptonica/prog/expand_reg.c @@ -0,0 +1,165 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * expand_reg.c + * + * Regression test for replicative and power-of-2 expansion (and + * corresponding reductions) + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + +#define BINARY_IMAGE "test1.png" +#define TWO_BPP_IMAGE_NO_CMAP "weasel2.4g.png" +#define TWO_BPP_IMAGE_CMAP "weasel2.4c.png" +#define FOUR_BPP_IMAGE_NO_CMAP "weasel4.16g.png" +#define FOUR_BPP_IMAGE_CMAP "weasel4.16c.png" +#define EIGHT_BPP_IMAGE_NO_CMAP "weasel8.149g.png" +#define EIGHT_BPP_IMAGE_CMAP "weasel8.240c.png" +#define RGB_IMAGE "marge.jpg" + + +int main(int argc, + char **argv) +{ +l_int32 i, w, h, format; +char filename[][64] = {BINARY_IMAGE, + TWO_BPP_IMAGE_NO_CMAP, TWO_BPP_IMAGE_CMAP, + FOUR_BPP_IMAGE_NO_CMAP, FOUR_BPP_IMAGE_CMAP, + EIGHT_BPP_IMAGE_NO_CMAP, EIGHT_BPP_IMAGE_CMAP, + RGB_IMAGE}; +BOX *box; +PIX *pixs, *pix1, *pix2, *pix3, *pix4, *pix5, *pix6; +PIXA *pixa; +L_REGPARAMS *rp; + + if (regTestSetup(argc, argv, &rp)) + return 1; + + pixa = pixaCreate(0); + for (i = 0; i < 8; i++) { + pixs = pixRead(filename[i]); + pix1 = pixExpandReplicate(pixs, 2); + format = (i == 7) ? IFF_JFIF_JPEG : IFF_PNG; + regTestWritePixAndCheck(rp, pix1, format); /* 0 - 7 */ + pixaAddPix(pixa, pix1, L_INSERT); + pixDestroy(&pixs); + } + for (i = 0; i < 8; i++) { + pixs = pixRead(filename[i]); + pix1 = pixExpandReplicate(pixs, 3); + format = (i == 7) ? IFF_JFIF_JPEG : IFF_PNG; + regTestWritePixAndCheck(rp, pix1, format); /* 8 - 15 */ + pixaAddPix(pixa, pix1, L_INSERT); + pixDestroy(&pixs); + } + + pixs = pixRead("test1.png"); + pixGetDimensions(pixs, &w, &h, NULL); + for (i = 1; i <= 15; i++) { + box = boxCreate(13 * i, 13 * i, w - 13 * i, h - 13 * i); + pix1 = pixClipRectangle(pixs, box, NULL); + pix2 = pixExpandReplicate(pix1, 3); + regTestWritePixAndCheck(rp, pix2, IFF_PNG); /* 16 - 30 */ + pixaAddPix(pixa, pix2, L_INSERT); + boxDestroy(&box); + pixDestroy(&pix1); + } + pixDestroy(&pixs); + + /* --------- Power of 2 expansion and reduction -------- */ + pixs = pixRead("speckle.png"); + + /* Test 2x expansion of 1 bpp */ + pix1 = pixExpandBinaryPower2(pixs, 2); + pix2 = pixReduceRankBinary2(pix1, 4, NULL); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 31 */ + regTestComparePix(rp, pixs, pix2); /* 32 */ + pixDestroy(&pix1); + pixDestroy(&pix2); + + /* Test 2x expansion of 2 bpp */ + pix1 = pixConvert1To2(NULL, pixs, 3, 0); + pix2 = pixExpandReplicate(pix1, 2); + pix3 = pixConvertTo8(pix2, FALSE); + pix4 = pixThresholdToBinary(pix3, 250); + regTestWritePixAndCheck(rp, pix4, IFF_PNG); /* 33 */ + pix5 = pixReduceRankBinary2(pix4, 4, NULL); + regTestWritePixAndCheck(rp, pix5, IFF_PNG); /* 34 */ + regTestComparePix(rp, pixs, pix5); /* 35 */ + pixaAddPix(pixa, pix5, L_INSERT); + pix6 = pixExpandBinaryPower2(pix5, 2); + regTestWritePixAndCheck(rp, pix6, IFF_PNG); /* 36 */ + pixaAddPix(pixa, pix6, L_INSERT); + pixDestroy(&pix1); + pixDestroy(&pix2); + pixDestroy(&pix3); + pixDestroy(&pix4); + + /* Test 4x expansion of 4 bpp */ + pix1 = pixConvert1To4(NULL, pixs, 15, 0); + pix2 = pixExpandReplicate(pix1, 4); + pix3 = pixConvertTo8(pix2, FALSE); + pix4 = pixThresholdToBinary(pix3, 250); + regTestWritePixAndCheck(rp, pix4, IFF_PNG); /* 37 */ + pixaAddPix(pixa, pix4, L_INSERT); + pix5 = pixReduceRankBinaryCascade(pix4, 4, 4, 0, 0); + regTestWritePixAndCheck(rp, pix5, IFF_PNG); /* 38 */ + regTestComparePix(rp, pixs, pix5); /* 39 */ + pixaAddPix(pixa, pix5, L_INSERT); + pixDestroy(&pix1); + pixDestroy(&pix2); + pixDestroy(&pix3); + + /* Test 8x expansion of 8 bpp */ + pix1 = pixConvertTo8(pixs, FALSE); + pix2 = pixExpandReplicate(pix1, 8); + pix3 = pixThresholdToBinary(pix2, 250); + regTestWritePixAndCheck(rp, pix3, IFF_PNG); /* 40 */ + pixaAddPix(pixa, pix3, L_INSERT); + pix4 = pixReduceRankBinaryCascade(pix3, 4, 4, 4, 0); + regTestWritePixAndCheck(rp, pix4, IFF_PNG); /* 41 */ + regTestComparePix(rp, pixs, pix4); /* 42 */ + pixaAddPix(pixa, pix4, L_INSERT); + pixDestroy(&pix1); + pixDestroy(&pix2); + pixDestroy(&pixs); + + if (rp->display) { + lept_stderr("Writing to: /tmp/lept/expand/test.pdf\n"); + pixaConvertToPdf(pixa, 0, 1.0, 0, 0, "Replicative expansion", + "/tmp/lept/expand/test.pdf"); + } + pixaDestroy(&pixa); + + return regTestCleanup(rp); +} + diff --git a/leptonica/prog/extrema_reg.c b/leptonica/prog/extrema_reg.c new file mode 100644 index 00000000..ce653432 --- /dev/null +++ b/leptonica/prog/extrema_reg.c @@ -0,0 +1,102 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * extrema_reg.c + * + * Tests procedure for locating extrema (minima and maxima) + * of a sampled function. + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include <math.h> +#include "allheaders.h" + +int main(int argc, + char **argv) +{ +l_uint8 *data; +size_t size; +l_int32 i, ival, n; +l_float32 f, val; +GPLOT *gplot; +NUMA *na1, *na2, *na3; +PIX *pix1; +L_REGPARAMS *rp; + +#if !defined(HAVE_LIBPNG) + L_ERROR("This test requires libpng to run.\n", "extrema_reg"); + exit(77); +#endif + + if (regTestSetup(argc, argv, &rp)) + return 1; + + lept_mkdir("lept/extrema"); + + /* Generate a 1D signal and plot it */ + na1 = numaCreate(500); + for (i = 0; i < 500; i++) { + f = 48.3 * sin(0.13 * (l_float32)i); + f += 63.4 * cos(0.21 * (l_float32)i); + numaAddNumber(na1, f); + } + gplot = gplotCreate("/tmp/lept/extrema/plot", GPLOT_PNG, + "Extrema test", "x", "y"); + gplotAddPlot(gplot, NULL, na1, GPLOT_LINES, "plot 1"); + + /* Find the local min and max and plot them */ + na2 = numaFindExtrema(na1, 38.3, NULL); + n = numaGetCount(na2); + na3 = numaCreate(n); + for (i = 0; i < n; i++) { + numaGetIValue(na2, i, &ival); + numaGetFValue(na1, ival, &val); + numaAddNumber(na3, val); + } + gplotAddPlot(gplot, na2, na3, GPLOT_POINTS, "plot 2"); + gplotMakeOutput(gplot); + + numaWriteMem(&data, &size, na2); + regTestWriteDataAndCheck(rp, data, size, "na"); /* 0 */ + lept_free(data); + + regTestCheckFile(rp, "/tmp/lept/extrema/plot.png"); /* 1 */ + if (rp->display) { + pix1 = pixRead("/tmp/lept/extrema/plot.png"); + pixDisplay(pix1, 100, 100); + pixDestroy(&pix1); + } + + gplotDestroy(&gplot); + numaDestroy(&na1); + numaDestroy(&na2); + numaDestroy(&na3); + return regTestCleanup(rp); +} diff --git a/leptonica/prog/falsecolor_reg.c b/leptonica/prog/falsecolor_reg.c new file mode 100644 index 00000000..d0f1ef79 --- /dev/null +++ b/leptonica/prog/falsecolor_reg.c @@ -0,0 +1,93 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * falsecolor_reg.c + * + * Test false color generation from 8 and 16 bpp gray + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + +static const l_float32 gamma[] = {1.0, 2.0, 3.0}; + +int main(int argc, + char **argv) +{ +l_int32 i, j, val8, val16; +NUMA *na; +PIX *pix1, *pix8, *pix16, *pix8f, *pix16f; +PIXA *pixa; +L_REGPARAMS *rp; + + if (regTestSetup(argc, argv, &rp)) + return 1; + + pix8 = pixCreate(768, 100, 8); + pix16 = pixCreate(768, 100, 16); + for (i = 0; i < 100; i++) { + for (j = 0; j < 768; j++) { + val16 = 0xffff * j / 768; + pixSetPixel(pix16, j, i, val16); + val8 = 0xff * j / 768; + pixSetPixel(pix8, j, i, val8); + } + } + regTestWritePixAndCheck(rp, pix8, IFF_PNG); /* 0 */ + regTestWritePixAndCheck(rp, pix16, IFF_PNG); /* 1 */ + + pixa = pixaCreate(8); + pixaAddPix(pixa, pix8, L_INSERT); + for (i = 0; i < 3; i++) { + pix8f = pixConvertGrayToFalseColor(pix8, gamma[i]); + regTestWritePixAndCheck(rp, pix8f, IFF_PNG); /* 2 - 4 */ + pixaAddPix(pixa, pix8f, L_INSERT); + } + pixaAddPix(pixa, pix16, L_INSERT); + for (i = 0; i < 3; i++) { + pix16f = pixConvertGrayToFalseColor(pix16, gamma[i]); + regTestWritePixAndCheck(rp, pix16f, IFF_PNG); /* 5 - 7 */ + pixaAddPix(pixa, pix16f, L_INSERT); + } + + if (rp->display) { + /* Use na to display them in column major order with 4 rows */ + na = numaCreate(8); + for (i = 0; i < 8; i++) + numaAddNumber(na, i / 4); + pix1 = pixaDisplayTiledByIndex(pixa, na, 768, 20, 2, 6, 0xff000000); + pixDisplay(pix1, 100, 100); + numaDestroy(&na); + pixDestroy(&pix1); + } + pixaDestroy(&pixa); + return regTestCleanup(rp); +} + diff --git a/leptonica/prog/fcombautogen.c b/leptonica/prog/fcombautogen.c new file mode 100644 index 00000000..31018269 --- /dev/null +++ b/leptonica/prog/fcombautogen.c @@ -0,0 +1,80 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * fcombautogen.c + * + * This program is used to generate the two files of dwa code for combs, + * that are used in linear composite dwa operations for brick Sels. + * If filename is not given, the files are: + * dwacomb.<n>.c + * dwacomblow.<n>.c + * Otherwise they are: + * <filename>.<n>.c + * <filename>low.<n>.c + * where <n> is the input index. + * These two files, when compiled, are used to implement all + * the composite dwa operations for brick Sels, that are + * generated by selaAddDwaCombs(). + * + * The library files dwacomp.2.c and dwacomblow.2.c were made + * using <n> = 2. + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + +int main(int argc, + char **argv) +{ +char *filename; +l_int32 index, ret; +SELA *sela; +static char mainName[] = "fcombautogen"; + + if (argc != 2 && argc != 3) + return ERROR_INT(" Syntax: fcombautogen index <filename>", + mainName, 1); + + setLeptDebugOK(1); + index = atoi(argv[1]); + sela = selaAddDwaCombs(NULL); + + if (argc == 2) + filename = stringNew("dwacomb"); + else + filename = argv[2]; + ret = fmorphautogen(sela, index, filename); + + if (argc == 2) + lept_free(filename); + selaDestroy(&sela); + return ret; +} + diff --git a/leptonica/prog/feyn-fract.tif b/leptonica/prog/feyn-fract.tif Binary files differnew file mode 100644 index 00000000..25f140a4 --- /dev/null +++ b/leptonica/prog/feyn-fract.tif diff --git a/leptonica/prog/feyn-fract2.tif b/leptonica/prog/feyn-fract2.tif Binary files differnew file mode 100644 index 00000000..4f92259f --- /dev/null +++ b/leptonica/prog/feyn-fract2.tif diff --git a/leptonica/prog/feyn-word.tif b/leptonica/prog/feyn-word.tif Binary files differnew file mode 100644 index 00000000..f1be2a97 --- /dev/null +++ b/leptonica/prog/feyn-word.tif diff --git a/leptonica/prog/feyn.tif b/leptonica/prog/feyn.tif Binary files differnew file mode 100644 index 00000000..6fd17e40 --- /dev/null +++ b/leptonica/prog/feyn.tif diff --git a/leptonica/prog/feynman-stamp.jpg b/leptonica/prog/feynman-stamp.jpg Binary files differnew file mode 100644 index 00000000..4a9c22b6 --- /dev/null +++ b/leptonica/prog/feynman-stamp.jpg diff --git a/leptonica/prog/fhmtauto_reg.c b/leptonica/prog/fhmtauto_reg.c new file mode 100644 index 00000000..7d7331e1 --- /dev/null +++ b/leptonica/prog/fhmtauto_reg.c @@ -0,0 +1,90 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * fhmtauto_reg.c + * + * Basic regression test for hit-miss transform: rasterops & dwa. + * + * Tests hmt from a set of hmt structuring elements + * by comparing the full image rasterop results with the + * automatically generated dwa results. + * + * Results must be identical for all operations. + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + +int main(int argc, + char **argv) +{ +l_int32 i, nsels, same1, same2; +char *selname; +PIX *pixs, *pixref, *pix1, *pix2, *pix3, *pix4; +SEL *sel; +SELA *sela; +L_REGPARAMS *rp; + + if (regTestSetup(argc, argv, &rp)) + return 1; + + pixs = pixRead("feyn.tif"); + sela = selaAddHitMiss(NULL); + nsels = selaGetCount(sela); + + for (i = 0; i < nsels; i++) + { + sel = selaGetSel(sela, i); + selname = selGetName(sel); + + pixref = pixHMT(NULL, pixs, sel); + pix1 = pixAddBorder(pixs, 32, 0); + pix2 = pixFHMTGen_1(NULL, pix1, selname); + pix3 = pixRemoveBorder(pix2, 32); + pix4 = pixHMTDwa_1(NULL, pixs, selname); + regTestComparePix(rp, pixref, pix3); /* 0, 2, ... 18 */ + regTestComparePix(rp, pixref, pix4); /* 1, 3, ... 19 */ + pixEqual(pixref, pix3, &same1); + pixEqual(pixref, pix4, &same2); + if (!same1 || !same2) + lept_stderr("hmt differ for sel %d (%s)\n", i, selname); + if (rp->display && same1 && same2) + lept_stderr("hmt are identical for sel %d (%s)\n", i, selname); + pixDestroy(&pixref); + pixDestroy(&pix1); + pixDestroy(&pix2); + pixDestroy(&pix3); + pixDestroy(&pix4); + } + + pixDestroy(&pixs); + selaDestroy(&sela); + return regTestCleanup(rp); +} diff --git a/leptonica/prog/fhmtautogen.c b/leptonica/prog/fhmtautogen.c new file mode 100644 index 00000000..ac3bfb98 --- /dev/null +++ b/leptonica/prog/fhmtautogen.c @@ -0,0 +1,74 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * fhmtautogen.c + * + * This program is used to generate the two files. + * If filename is not given, the files are: + * fhmtgen.<n>.c + * fhmtgenlow.<n>.c + * where <n> is the input index. Otherwise they are: + * <filename>.<n>.c + * <filename>low.<n>.c + * These two files, when compiled, implement hit-miss dwa + * operations for all sels generated by selaAddHitMiss(). + * + * The library files fhmtgen.1.c and fhmtgenlow.1.c + * were made using index = 1. + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + +int main(int argc, + char **argv) +{ +char *filename; +l_int32 index; +SELA *sela; +static char mainName[] = "fhmtautogen"; + + if (argc != 2 && argc != 3) + return ERROR_INT(" Syntax: fhmtautogen index <filename>", mainName, 1); + + setLeptDebugOK(1); + index = atoi(argv[1]); + filename = NULL; + if (argc == 3) + filename = argv[2]; + + sela = selaAddHitMiss(NULL); + if (fhmtautogen(sela, index, filename)) + return 1; + + selaDestroy(&sela); + return 0; +} + diff --git a/leptonica/prog/fileinfo.c b/leptonica/prog/fileinfo.c new file mode 100644 index 00000000..05f50593 --- /dev/null +++ b/leptonica/prog/fileinfo.c @@ -0,0 +1,52 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * fileinfo.c + * + * Returns information about the image data file + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + +int main(int argc, + char **argv) +{ +char *filein; +static char mainName[] = "fileinfo"; + + if (argc != 2) + return ERROR_INT(" Syntax: fileinfo filein", mainName, 1); + filein = argv[1]; + + setLeptDebugOK(1); + writeImageFileInfo(filein, stderr, 0); + return 0; +} diff --git a/leptonica/prog/files_reg.c b/leptonica/prog/files_reg.c new file mode 100644 index 00000000..49bea4c4 --- /dev/null +++ b/leptonica/prog/files_reg.c @@ -0,0 +1,290 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * files_reg.c + * + * Regression test for lept_*() and other path utilities in utils.h + * + * Some of these only work properly on unix because they explicitly + * use "/tmp" for string compares. + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" +#include <string.h> +#ifndef _MSC_VER +#include <unistd.h> +#else +#include <direct.h> +#define getcwd _getcwd /* fix MSVC warning */ +#endif /* !_MSC_VER */ + +void TestPathJoin(L_REGPARAMS *rp, const char *first, const char *second, + const char *result); +void TestLeptCpRm(L_REGPARAMS *rp, const char *srctail, const char *newdir, + const char *newtail); +void TestGenPathname(L_REGPARAMS *rp, const char *dir, const char *fname, + const char *result); + +l_int32 main(int argc, + char **argv) +{ +l_int32 exists; +L_REGPARAMS *rp; + + if (regTestSetup(argc, argv, &rp)) + return 1; + + lept_stderr(" ===================================================\n"); + lept_stderr(" =================== Test pathJoin() ===============\n"); + lept_stderr(" ===================================================\n"); + TestPathJoin(rp, "/a/b//c///d//", "//e//f//g//", "/a/b/c/d/e/f/g"); /* 0 */ + TestPathJoin(rp, "/tmp/", "junk//", "/tmp/junk"); /* 1 */ + TestPathJoin(rp, "//tmp/", "junk//", "/tmp/junk"); /* 2 */ + TestPathJoin(rp, "tmp/", "//junk//", "tmp/junk"); /* 3 */ + TestPathJoin(rp, "tmp/", "junk/////", "tmp/junk"); /* 4 */ + TestPathJoin(rp, "/tmp/", "///", "/tmp"); /* 5 */ + TestPathJoin(rp, "////", NULL, "/"); /* 6 */ + TestPathJoin(rp, "//", "/junk//", "/junk"); /* 7 */ + TestPathJoin(rp, NULL, "/junk//", "/junk"); /* 8 */ + TestPathJoin(rp, NULL, "//junk//", "/junk"); /* 9 */ + TestPathJoin(rp, NULL, "junk//", "junk"); /* 10 */ + TestPathJoin(rp, NULL, "//", "/"); /* 11 */ + TestPathJoin(rp, NULL, NULL, ""); /* 12 */ + TestPathJoin(rp, "", "", ""); /* 13 */ + TestPathJoin(rp, "/", "", "/"); /* 14 */ + TestPathJoin(rp, "", "//", "/"); /* 15 */ + TestPathJoin(rp, "", "a", "a"); /* 16 */ + + lept_stderr("The next 3 joins properly give error messages:\n"); + lept_stderr("join: .. + a --> NULL\n"); + pathJoin("..", "a"); /* returns NULL */ + lept_stderr("join: %s + .. --> NULL\n", "/tmp"); + pathJoin("/tmp", ".."); /* returns NULL */ + lept_stderr("join: ./ + .. --> NULL\n"); + pathJoin("./", ".."); /* returns NULL */ + + lept_stderr("\n ===================================================\n"); + lept_stderr(" ======= Test lept_rmdir() and lept_mkdir()) =======\n"); + lept_stderr(" ===================================================\n"); + lept_rmdir("junkfiles"); + lept_direxists("/tmp/junkfiles", &exists); + if (rp->display) lept_stderr("directory removed?: %d\n", !exists); + regTestCompareValues(rp, 0, exists, 0.0); /* 17 */ + + lept_mkdir("junkfiles"); + lept_direxists("/tmp/junkfiles", &exists); + if (rp->display) lept_stderr("directory made?: %d\n", exists); + regTestCompareValues(rp, 1, exists, 0.0); /* 18 */ + + lept_stderr("\n ===================================================\n"); + lept_stderr(" ======= Test lept_mv(), lept_cp(), lept_rm() ======\n"); + lept_stderr(" ===================================================\n"); + TestLeptCpRm(rp, "weasel2.png", NULL, NULL); /* 19 - 22 */ + TestLeptCpRm(rp, "weasel2.png", "junkfiles", NULL); /* 23 - 26 */ + TestLeptCpRm(rp, "weasel2.png", NULL, "new_weasel2.png"); /* 27 - 30 */ + TestLeptCpRm(rp, "weasel2.png", "junkfiles", "new_weasel2.png"); /* 31-34 */ + + lept_stderr("\n ===================================================\n"); + lept_stderr(" =============== Test genPathname() ================\n"); + lept_stderr(" ===================================================\n"); + TestGenPathname(rp, "what/", NULL, "what"); /* 35 */ + TestGenPathname(rp, "what", "abc", "what/abc"); /* 36 */ + TestGenPathname(rp, NULL, "abc/def", "abc/def"); /* 37 */ + TestGenPathname(rp, "", "abc/def", "abc/def"); /* 38 */ +#ifndef _WIN32 /* unix only */ + if (getenv("TMPDIR") == NULL) { + TestGenPathname(rp, "/tmp", NULL, "/tmp"); /* 39 */ + TestGenPathname(rp, "/tmp/", NULL, "/tmp"); /* 40 */ + TestGenPathname(rp, "/tmp/junk", NULL, "/tmp/junk"); /* 41 */ + TestGenPathname(rp, "/tmp/junk/abc", NULL, "/tmp/junk/abc"); /* 42 */ + TestGenPathname(rp, "/tmp/junk/", NULL, "/tmp/junk"); /* 43 */ + TestGenPathname(rp, "/tmp/junk", "abc", "/tmp/junk/abc"); /* 44 */ + } +#endif /* !_WIN32 */ + + return regTestCleanup(rp); +} + + +void TestPathJoin(L_REGPARAMS *rp, + const char *first, + const char *second, + const char *result) +{ +char *newfirst = NULL; +char *newsecond = NULL; +char *newpath = NULL; +char *path = NULL; + + if ((path = pathJoin(first, second)) == NULL) return; + regTestCompareStrings(rp, (l_uint8 *)result, strlen(result), + (l_uint8 *)path, strlen(path)); + + if (first && first[0] == '\0') + newfirst = stringNew("\"\""); + else if (first) + newfirst = stringNew(first); + if (second && second[0] == '\0') + newsecond = stringNew("\"\""); + else if (second) + newsecond = stringNew(second); + if (path && path[0] == '\0') + newpath = stringNew("\"\""); + else if (path) + newpath = stringNew(path); + if (rp->display) + lept_stderr("join: %s + %s --> %s\n", newfirst, newsecond, newpath); + lept_free(path); + lept_free(newfirst); + lept_free(newsecond); + lept_free(newpath); + return; +} + +void TestLeptCpRm(L_REGPARAMS *rp, + const char *srctail, + const char *newdir, + const char *newtail) +{ +char realnewdir[256], newnewdir[256]; +char *realtail, *newsrc, *fname; +l_int32 nfiles1, nfiles2, nfiles3; +SARRAY *sa; + + /* Remove old version if it exists */ + realtail = (newtail) ? stringNew(newtail) : stringNew(srctail); + lept_rm(newdir, realtail); + makeTempDirname(realnewdir, 256, newdir); + if (rp->display) { + lept_stderr("\nInput: srctail = %s, newdir = %s, newtail = %s\n", + srctail, newdir, newtail); + lept_stderr(" realnewdir = %s, realtail = %s\n", realnewdir, realtail); + } + sa = getFilenamesInDirectory(realnewdir); + nfiles1 = sarrayGetCount(sa); + sarrayDestroy(&sa); + + /* Copy */ + lept_cp(srctail, newdir, newtail, &fname); + sa = getFilenamesInDirectory(realnewdir); + nfiles2 = sarrayGetCount(sa); + if (rp->display) { + lept_stderr(" File copied to directory: %s\n", realnewdir); + lept_stderr(" ... with this filename: %s\n", fname); + lept_stderr(" delta files should be 1: %d\n", nfiles2 - nfiles1); + } + regTestCompareValues(rp, 1, nfiles2 - nfiles1, 0.0); /* '1' */ + sarrayDestroy(&sa); + lept_free(fname); + + /* Remove it */ + lept_rm(newdir, realtail); + sa = getFilenamesInDirectory(realnewdir); + nfiles2 = sarrayGetCount(sa); + if (rp->display) { + lept_stderr(" File removed from directory: %s\n", realnewdir); + lept_stderr(" delta files should be 0: %d\n", nfiles2 - nfiles1); + } + regTestCompareValues(rp, 0, nfiles2 - nfiles1, 0.0); /* '2' */ + sarrayDestroy(&sa); + + /* Copy it again ... */ + lept_cp(srctail, newdir, newtail, &fname); + if (rp->display) + lept_stderr(" File copied to: %s\n", fname); + lept_free(fname); + + /* move it elsewhere ... */ + lept_rmdir("junko"); /* clear out this directory */ + lept_mkdir("junko"); + newsrc = pathJoin(realnewdir, realtail); + lept_mv(newsrc, "junko", NULL, &fname); + if (rp->display) { + lept_stderr(" Move file at: %s\n", newsrc); + lept_stderr(" ... to: %s\n", fname); + } + lept_free(fname); + lept_free(newsrc); + makeTempDirname(newnewdir, 256, "junko"); + if (rp->display) lept_stderr(" In this directory: %s\n", newnewdir); + sa = getFilenamesInDirectory(newnewdir); /* check if it landed ok */ + nfiles3 = sarrayGetCount(sa); + if (rp->display) lept_stderr(" num files should be 1: %d\n", nfiles3); + regTestCompareValues(rp, 1, nfiles3, 0.0); /* '3' */ + sarrayDestroy(&sa); + + /* and verify it was removed from the original location */ + sa = getFilenamesInDirectory(realnewdir); /* check if it was removed */ + nfiles2 = sarrayGetCount(sa); + if (rp->display) { + lept_stderr(" In this directory: %s\n", realnewdir); + lept_stderr(" delta files should be 0: %d\n", nfiles2 - nfiles1); + } + regTestCompareValues(rp, 0, nfiles2 - nfiles1, 0.0); /* '4' */ + sarrayDestroy(&sa); + lept_free(realtail); +} + +void TestGenPathname(L_REGPARAMS *rp, + const char *dir, + const char *fname, + const char *result) +{ +char expect[512], localdir[256]; + + char *path = genPathname(dir, fname); + if (!dir || dir[0] == '\0') { + if (!getcwd(localdir, sizeof(localdir))) + lept_stderr("bad bad bad -- no local directory!\n"); + snprintf(expect, sizeof(expect), "%s/%s", localdir, result); +#ifdef _WIN32 + convertSepCharsInPath(expect, UNIX_PATH_SEPCHAR); +#endif /* _WIN32 */ + regTestCompareStrings(rp, (l_uint8 *)expect, strlen(expect), + (l_uint8 *)path, strlen(path)); + } else { + regTestCompareStrings(rp, (l_uint8 *)result, strlen(result), + (l_uint8 *)path, strlen(path)); + } + if (rp->display) { + char *newdir = NULL; + if (dir && dir[0] == '\0') + newdir = stringNew("\"\""); + else if (dir) + newdir = stringNew(dir); + lept_stderr("genPathname(%s, %s) --> %s\n", newdir, fname, path); + lept_free(newdir); + } + lept_free(path); + return; +} + + diff --git a/leptonica/prog/find_colorregions.c b/leptonica/prog/find_colorregions.c new file mode 100644 index 00000000..d5980724 --- /dev/null +++ b/leptonica/prog/find_colorregions.c @@ -0,0 +1,343 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * find_colorregions.c + * + * This shows the output of pixHasColorRegions(), which attempts to locate + * colored regions on scanned images. The difficulty arises when the + * scanned images are oxidized, dark and reddish. + * + * It also shows output from pixFindColorRegionsLight(), which is an + * inferior implementation that does not work on images with a dark + * background. + * + * The input image should be RGB at 75 ppi resolution. + * + * Use, e.g. these 75 ppi images: + * map.057.jpg + * colorpage.030.jpg + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + + /* Implementation is in this file */ +static l_int32 +pixFindColorRegionsLight(PIX *pixs, PIX *pixm, l_int32 factor, + l_int32 darkthresh, l_int32 lightthresh, l_int32 mindiff, + l_int32 colordiff, l_float32 *pcolorfract, + PIX **pcolormask1, PIX **pcolormask2, PIXA *pixadb); + +int main(int argc, + char **argv) +{ +l_float32 fcolor; +PIX *pix1, *pix2, *pix3, *pix4; +PIXA *pixadb; + + setLeptDebugOK(1); + lept_mkdir("lept/color"); + pix1 = pixRead("colorpage.030.jpg"); +/* pix1 = pixRead("map.057.jpg"); */ + + /* More general method */ + pixadb = pixaCreate(0); + pixFindColorRegions(pix1, NULL, 4, 200, 60, 10, 90, 0.05, + &fcolor, &pix3, &pix4, pixadb); + lept_stderr("ncolor = %f\n", fcolor); + if (pix3) pixDisplay(pix3, 0, 800); + if (pix4) pixDisplay(pix4, 600, 800); + + pix2 = pixaDisplayTiledInColumns(pixadb, 5, 0.3, 20, 2); + pixDisplay(pix2, 0, 0); + pixWrite("/tmp/lept/color/result1.png", pix2, IFF_PNG); + pixDestroy(&pix2); + pixDestroy(&pix3); + pixDestroy(&pix4); + pixaDestroy(&pixadb); + + /* Method for pages with very light background */ + pixadb = pixaCreate(0); + pixFindColorRegionsLight(pix1, NULL, 4, 60, 230, 40, 20, + &fcolor, &pix3, &pix4, pixadb); + lept_stderr("ncolor = %f\n", fcolor); + if (pix3) pixDisplay(pix3, 1100, 800); + if (pix4) pixDisplay(pix4, 1700, 800); + + pix2 = pixaDisplayTiledInColumns(pixadb, 5, 0.3, 20, 2); + pixDisplay(pix2, 1100, 0); + pixWrite("/tmp/lept/color/result2.png", pix2, IFF_PNG); + pixDestroy(&pix2); + pixDestroy(&pix3); + pixDestroy(&pix4); + pixaDestroy(&pixadb); + + pixDestroy(&pix1); + return 0; +} + + +/*! + * Note: this method is generally inferior to pixHasColorRegions(); it + * is retained as a reference only + * + * \brief pixFindColorRegionsLight() + * + * \param[in] pixs 32 bpp rgb + * \param[in] pixm [optional] 1 bpp mask image + * \param[in] factor subsample factor; integer >= 1 + * \param[in] darkthresh threshold to eliminate dark pixels (e.g., text) + * from consideration; typ. 70; -1 for default. + * \param[in] lightthresh threshold for minimum gray value at 95% rank + * near white; typ. 220; -1 for default + * \param[in] mindiff minimum difference from 95% rank value, used + * to count darker pixels; typ. 50; -1 for default + * \param[in] colordiff minimum difference in (max - min) component to + * qualify as a color pixel; typ. 40; -1 for default + * \param[out] pcolorfract fraction of 'color' pixels found + * \param[out] pcolormask1 [optional] mask over background color, if any + * \param[out] pcolormask2 [optional] filtered mask over background color + * \param[out] pixadb [optional] debug intermediate results + * \return 0 if OK, 1 on error + * + * <pre> + * Notes: + * (1) This function tries to determine if there is a significant + * color or darker region on a scanned page image where part + * of the image is very close to "white". It will also allow + * extraction of small regions of lightly colored pixels. + * If the background is darker (and reddish), use instead + * pixHasColorRegions2(). + * (2) If %pixm exists, only pixels under fg are considered. Typically, + * the inverse of %pixm would have fg pixels over a photograph. + * (3) There are four thresholds. + * * %darkthresh: ignore pixels darker than this (typ. fg text). + * We make a 1 bpp mask of these pixels, and then dilate it to + * remove all vestiges of fg from their vicinity. + * * %lightthresh: let val95 be the pixel value for which 95% + * of the non-masked pixels have a lower value (darker) of + * their min component. Then if val95 is darker than + * %lightthresh, the image is not considered to have a + * light bg, and this returns 0.0 for %colorfract. + * * %mindiff: we are interested in the fraction of pixels that + * have two conditions. The first is that their min component + * is at least %mindiff darker than val95. + * * %colordiff: the second condition is that the max-min diff + * of the pixel components exceeds %colordiff. + * (4) This returns in %pcolorfract the fraction of pixels that have + * both a min component that is at least %mindiff below that at the + * 95% rank value (where 100% rank is the lightest value), and + * a max-min diff that is at least %colordiff. Without the + * %colordiff constraint, gray pixels of intermediate value + * could get flagged by this function. + * (5) No masks are returned unless light color pixels are found. + * If colorfract > 0.0 and %pcolormask1 is defined, this returns + * a 1 bpp mask with fg pixels over the color background. + * This mask may have some holes in it. + * (6) If colorfract > 0.0 and %pcolormask2 is defined, this returns + * a filtered version of colormask1. The two changes are + * (a) small holes have been filled + * (b) components near the border have been removed. + * The latter insures that dark pixels near the edge of the + * image are not included. + * (7) To generate a boxa of rectangular regions from the overlap + * of components in the filtered mask: + * boxa1 = pixConnCompBB(colormask2, 8); + * boxa2 = boxaCombineOverlaps(boxa1); + * This is done here in debug mode. + * </pre> + */ +static l_int32 +pixFindColorRegionsLight(PIX *pixs, + PIX *pixm, + l_int32 factor, + l_int32 darkthresh, + l_int32 lightthresh, + l_int32 mindiff, + l_int32 colordiff, + l_float32 *pcolorfract, + PIX **pcolormask1, + PIX **pcolormask2, + PIXA *pixadb) +{ +l_int32 lightbg, w, h, count; +l_float32 ratio, val95; +BOXA *boxa1, *boxa2; +NUMA *nah; +PIX *pix1, *pix2, *pix3, *pix4, *pix5, *pixm1, *pixm2, *pixm3; + + PROCNAME("pixFindColorRegionsLight"); + + if (pcolormask1) *pcolormask1 = NULL; + if (pcolormask2) *pcolormask2 = NULL; + if (!pcolorfract) + return ERROR_INT("&colorfract not defined", procName, 1); + *pcolorfract = 0.0; + if (!pixs || pixGetDepth(pixs) != 32) + return ERROR_INT("pixs not defined or not 32 bpp", procName, 1); + if (factor < 1) factor = 1; + if (darkthresh < 0) darkthresh = 70; /* defaults */ + if (lightthresh < 0) lightthresh = 220; + if (mindiff < 0) mindiff = 50; + if (colordiff < 0) colordiff = 40; + + /* Check if pixm covers most of the image. If so, just return. */ + pixGetDimensions(pixs, &w, &h, NULL); + if (pixm) { + pixCountPixels(pixm, &count, NULL); + ratio = (l_float32)count / ((l_float32)(w) * h); + if (ratio > 0.7) { + if (pixadb) L_INFO("pixm has big fg: %f5.2\n", procName, ratio); + return 0; + } + } + + /* Make a mask pixm1 over the dark pixels in the image: + * convert to gray using the average of the components; + * threshold using %darkthresh; do a small dilation; + * combine with pixm. */ + pix1 = pixConvertRGBToGray(pixs, 0.33, 0.34, 0.33); + if (pixadb) pixaAddPix(pixadb, pixs, L_COPY); + if (pixadb) pixaAddPix(pixadb, pix1, L_COPY); + pixm1 = pixThresholdToBinary(pix1, darkthresh); + pixDilateBrick(pixm1, pixm1, 7, 7); + if (pixadb) pixaAddPix(pixadb, pixm1, L_COPY); + if (pixm) { + pixOr(pixm1, pixm1, pixm); + if (pixadb) pixaAddPix(pixadb, pixm1, L_COPY); + } + pixDestroy(&pix1); + + /* Convert to gray using the minimum component value and + * find the gray value at rank 0.95, that represents the light + * pixels in the image. If it is too dark, quit. */ + pix1 = pixConvertRGBToGrayMinMax(pixs, L_SELECT_MIN); + pix2 = pixInvert(NULL, pixm1); /* pixels that are not dark */ + pixGetRankValueMasked(pix1, pix2, 0, 0, factor, 0.95, &val95, &nah); + pixDestroy(&pix2); + if (pixadb) { + L_INFO("val at 0.95 rank = %5.1f\n", procName, val95); + gplotSimple1(nah, GPLOT_PNG, "/tmp/lept/histo1", "gray histo"); + pix3 = pixRead("/tmp/lept/histo1.png"); + pix4 = pixExpandReplicate(pix3, 2); + pixaAddPix(pixadb, pix4, L_INSERT); + pixDestroy(&pix3); + } + lightbg = (l_int32)val95 >= lightthresh; + numaDestroy(&nah); + if (!lightbg) { + pixDestroy(&pix1); + pixDestroy(&pixm1); + return 0; + } + + /* Make mask pixm2 over pixels that are darker than val95 - mindiff. */ + pixm2 = pixThresholdToBinary(pix1, val95 - mindiff); + if (pixadb) pixaAddPix(pixadb, pixm2, L_COPY); + pixDestroy(&pix1); + + /* Make a mask pixm3 over pixels that have some color saturation, + * with a (max - min) component difference >= %colordiff, + * and combine using AND with pixm2. */ + pix2 = pixConvertRGBToGrayMinMax(pixs, L_CHOOSE_MAXDIFF); + pixm3 = pixThresholdToBinary(pix2, colordiff); + pixDestroy(&pix2); + pixInvert(pixm3, pixm3); /* need pixels above threshold */ + if (pixadb) pixaAddPix(pixadb, pixm3, L_COPY); + pixAnd(pixm2, pixm2, pixm3); + if (pixadb) pixaAddPix(pixadb, pixm2, L_COPY); + pixDestroy(&pixm3); + + /* Subtract the dark pixels represented by pixm1. + * pixm2 now holds all the color pixels of interest */ + pixSubtract(pixm2, pixm2, pixm1); + pixDestroy(&pixm1); + if (pixadb) pixaAddPix(pixadb, pixm2, L_COPY); + + /* But we're not quite finished. Remove pixels from any component + * that is touching the image border. False color pixels can + * sometimes be found there if the image is much darker near + * the border, due to oxidation or reduced illumination. */ + pixm3 = pixRemoveBorderConnComps(pixm2, 8); + pixDestroy(&pixm2); + if (pixadb) pixaAddPix(pixadb, pixm3, L_COPY); + + /* Get the fraction of light color pixels */ + pixCountPixels(pixm3, &count, NULL); + *pcolorfract = (l_float32)count / (w * h); + if (pixadb) { + if (count == 0) + L_INFO("no light color pixels found\n", procName); + else + L_INFO("fraction of light color pixels = %5.3f\n", procName, + *pcolorfract); + } + + /* Debug: extract the color pixels from pixs */ + if (pixadb && count > 0) { + /* Use pixm3 to extract the color pixels */ + pix3 = pixCreateTemplate(pixs); + pixSetAll(pix3); + pixCombineMasked(pix3, pixs, pixm3); + pixaAddPix(pixadb, pix3, L_INSERT); + + /* Use additional filtering to extract the color pixels */ + pix3 = pixCloseSafeBrick(NULL, pixm3, 15, 15); + pixaAddPix(pixadb, pix3, L_INSERT); + pix5 = pixCreateTemplate(pixs); + pixSetAll(pix5); + pixCombineMasked(pix5, pixs, pix3); + pixaAddPix(pixadb, pix5, L_INSERT); + + /* Get the combined bounding boxes of the mask components + * in pix3, and extract those pixels from pixs. */ + boxa1 = pixConnCompBB(pix3, 8); + boxa2 = boxaCombineOverlaps(boxa1, NULL); + pix4 = pixCreateTemplate(pix3); + pixMaskBoxa(pix4, pix4, boxa2, L_SET_PIXELS); + pixaAddPix(pixadb, pix4, L_INSERT); + pix5 = pixCreateTemplate(pixs); + pixSetAll(pix5); + pixCombineMasked(pix5, pixs, pix4); + pixaAddPix(pixadb, pix5, L_INSERT); + boxaDestroy(&boxa1); + boxaDestroy(&boxa2); + pixaAddPix(pixadb, pixs, L_COPY); + } + + /* Optional colormask returns */ + if (pcolormask2 && count > 0) + *pcolormask2 = pixCloseSafeBrick(NULL, pixm3, 15, 15); + if (pcolormask1 && count > 0) + *pcolormask1 = pixm3; + else + pixDestroy(&pixm3); + return 0; +} diff --git a/leptonica/prog/findbinding.c b/leptonica/prog/findbinding.c new file mode 100644 index 00000000..2d1ead8f --- /dev/null +++ b/leptonica/prog/findbinding.c @@ -0,0 +1,164 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * findbinding.c + * + * Here is a simple approach to find the location of the binding + * in an open book that is photographed. It relies on the typical + * condition that the background pixels near the binding are + * darker than those on the rest of the page, and further, that + * the lightest pixels in each column parallel to the binding + * exhibit a large variance by column near the binding. This is + * because the pixels at the binding are typically even darker + * than the pixels near the binding. + * + * Accurate results are obtained in this example at the very low + * resolution of 45 ppi. Better results can be expected at higher + * resolution. + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + +int main(int argc, + char **argv) +{ +l_int32 w, h, ystart, yend, y, ymax, ymid, i, window, sum1, sum2, rankx; +l_uint32 uval; +l_float32 ave, rankval, maxvar, variance, norm, conf, angle, radangle; +NUMA *na1; +PIX *pix1, *pix2, *pix3, *pix4, *pix5, *pix6, *pix7; +PIXA *pixa; +static char mainName[] = "findbinding"; + + if (argc != 1) + return ERROR_INT(" Syntax: findbinding", mainName, 1); + + setLeptDebugOK(1); + lept_mkdir("lept/binding"); + pixa = pixaCreate(0); + + pix1 = pixRead("binding-example.45.jpg"); + pix2 = pixConvertTo8(pix1, 0); + + /* Find the skew angle */ + pix3 = pixConvertTo1(pix2, 150); + pixFindSkewSweepAndSearch(pix3, &angle, &conf, 2, 2, 7.0, 1.0, 0.01); + lept_stderr("angle = %f, conf = %f\n", angle, conf); + + /* Deskew, bringing in black pixels at the edges */ + if (L_ABS(angle) < 0.1 || conf < 1.5) { + pix4 = pixClone(pix2); + } else { + radangle = 3.1416 * angle / 180.0; + pix4 = pixRotate(pix2, radangle, L_ROTATE_AREA_MAP, + L_BRING_IN_BLACK, 0, 0); + } + + /* Rotate 90 degrees to make binding horizontal */ + pix5 = pixRotateOrth(pix4, 1); + + /* Sort pixels in each row by their gray value. + * Dark pixels on the left, light ones on the right. */ + pix6 = pixRankRowTransform(pix5); + pixDisplay(pix5, 0, 0); + pixDisplay(pix6, 550, 0); + pixaAddPix(pixa, pix4, L_COPY); + pixaAddPix(pixa, pix5, L_COPY); + pixaAddPix(pixa, pix6, L_COPY); + + /* Make an a priori estimate of the y-interval within which the + * binding will be found. The search will be done in this interval. */ + pixGetDimensions(pix6, &w, &h, NULL); + ystart = 0.25 * h; + yend = 0.75 * h; + + /* Choose a very light rank value; close to white, which + * corresponds to a column in pix6 near the right side. */ + rankval = 0.98; + rankx = (l_int32)(w * rankval); + + /* Investigate variance in a small window (vertical, size = 5) + * of the pixels in that column. These are the %rankval + * pixels in each raster of pix6. Find the y-location of + * maximum variance. */ + window = 5; + norm = 1.0 / window; + maxvar = 0.0; + na1 = numaCreate(0); + numaSetParameters(na1, ystart, 1); + for (y = ystart; y <= yend; y++) { + sum1 = sum2 = 0; + for (i = 0; i < window; i++) { + pixGetPixel(pix6, rankx, y + i, &uval); + sum1 += uval; + sum2 += uval * uval; + } + ave = norm * sum1; + variance = norm * sum2 - ave * ave; + numaAddNumber(na1, variance); + ymid = y + window / 2; + if (variance > maxvar) { + maxvar = variance; + ymax = ymid; + } + } + + /* Plot the windowed variance as a function of the y-value + * of the window location */ + lept_stderr("maxvar = %f, ymax = %d\n", maxvar, ymax); + gplotSimple1(na1, GPLOT_PNG, "/tmp/lept/binding/root", NULL); + pix7 = pixRead("/tmp/lept/binding/root.png"); + pixDisplay(pix7, 0, 800); + pixaAddPix(pixa, pix7, L_COPY); + + /* Superimpose the variance plot over the image. + * The variance peak is at the binding. */ + pixRenderPlotFromNumaGen(&pix5, na1, L_VERTICAL_LINE, 3, w - 120, 100, 1, + 0x0000ff00); + pixDisplay(pix5, 1050, 0); + pixaAddPix(pixa, pix5, L_COPY); + + /* Bundle the results up in a pdf */ + lept_stderr("Writing pdf output file: /tmp/lept/binding/binding.pdf\n"); + pixaConvertToPdf(pixa, 45, 1.0, 0, 0, "Binding locator", + "/tmp/lept/binding/binding.pdf"); + + pixDestroy(&pix1); + pixDestroy(&pix2); + pixDestroy(&pix3); + pixDestroy(&pix4); + pixDestroy(&pix5); + pixDestroy(&pix6); + pixDestroy(&pix7); + pixaDestroy(&pixa); + numaDestroy(&na1); + return 0; +} diff --git a/leptonica/prog/findcorners_reg.c b/leptonica/prog/findcorners_reg.c new file mode 100644 index 00000000..c5e74a92 --- /dev/null +++ b/leptonica/prog/findcorners_reg.c @@ -0,0 +1,210 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * findcorners_reg.c + * + * This reg test demonstrates extraction of deskewed objects (tickets + * in this case) using morphological operations to identify the + * barcodes on each object. The objects are separately deskewed, + * the barcodes are again located, and the objects are extracted. + * + * We also show how to generate the HMT sela for detecting corners, + * and how to use it (with pixUnionOfMorphOps()) to find all the + * corners. The corner Sels were constructed to find significant + * corners in the presence of the type of noise expected from + * scanned images. The located corners are displayed by xor-ing + * a pattern (sel_cross) on each one. + * + * When this function is called with the display argument + * findcorners_reg display + * we display some results and additionally generate the following pdfs: + * /tmp/lept/regout/seq_output_1.pdf (morphological operations of + * first call to locate barcodes) + * /tmp/lept/regout/tickets.pdf (deskewed result for the set of tickets) + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + +static BOXA *LocateBarcodes(PIX *pixs, PIX **ppixd, l_int32 flag); +static SELA *GetCornerSela(L_REGPARAMS *rp); + +static const char *sel_cross = " xxx " + " xxx " + " xxx " + " xxx " + " xxx " + "xxxxxxxxxxxxx" + "xxxxxxXxxxxxx" + "xxxxxxxxxxxxx" + " xxx " + " xxx " + " xxx " + " xxx " + " xxx "; + +l_int32 main(int argc, + char **argv) +{ +l_int32 i, n, flag; +l_float32 angle, conf, deg2rad; +BOX *box1, *box2, *box3, *box4; +BOXA *boxa, *boxa2; +PIX *pixs, *pixd, *pix1, *pix2, *pix3; +PIXA *pixa; +SEL *sel; +SELA *sela; +L_REGPARAMS *rp; + + if (regTestSetup(argc, argv, &rp)) + return 1; + + pixs = pixRead("tickets.tif"); + flag = (rp->display) ? -1 : 0; + boxa = LocateBarcodes(pixs, &pixd, flag); + regTestWritePixAndCheck(rp, pixd, IFF_TIFF_G4); /* 0 */ + if (rp->display) boxaWriteStream(stderr, boxa); + n = boxaGetCount(boxa); + deg2rad = 3.14159265 / 180.; + pixa = pixaCreate(9); + for (i = 0; i < n; i++) { + box1 = boxaGetBox(boxa, i, L_CLONE); + /* Use a larger adjustment to get entire skewed ticket */ + box2 = boxAdjustSides(NULL, box1, -266, 346, -1560, 182); + pix1 = pixClipRectangle(pixs, box2, NULL); + /* Deskew */ + pixFindSkew(pix1, &angle, &conf); + pix2 = pixRotate(pix1, deg2rad * angle, L_ROTATE_SAMPLING, + L_BRING_IN_WHITE, 0, 0); + /* Find the barcode again ... */ + boxa2 = LocateBarcodes(pix2, NULL, 0); + box3 = boxaGetBox(boxa2, 0, L_CLONE); + /* ... and adjust crop box exactly for ticket size */ + box4 = boxAdjustSides(NULL, box3, -141, 221, -1535, 157); + pix3 = pixClipRectangle(pix2, box4, NULL); + regTestWritePixAndCheck(rp, pix3, IFF_TIFF_G4); /* 1 - 9 */ + if (rp->display) + pixaAddPix(pixa, pix3, L_INSERT); + else + pixDestroy(&pix3); + boxDestroy(&box1); + boxDestroy(&box2); + boxDestroy(&box3); + boxDestroy(&box4); + boxaDestroy(&boxa2); + pixDestroy(&pix1); + pixDestroy(&pix2); + } + if (rp->display) { + pixaConvertToPdf(pixa, 0, 1.0, 0, 0, "tickets", + "/tmp/lept/regout/tickets.pdf"); + L_INFO("Output pdf: /tmp/lept/regout/tickets.pdf\n", rp->testname); + } + pixaDestroy(&pixa); + + /* Downscale by 2x and locate corners */ + pix1 = pixScale(pixd, 0.5, 0.5); + regTestWritePixAndCheck(rp, pix1, IFF_TIFF_G4); /* 10 */ + pixDisplayWithTitle(pix1, 100, 200, NULL, rp->display); + /* Find corners and blit a cross onto each (4 to each barcode) */ + sela = GetCornerSela(rp); + pix2 = pixUnionOfMorphOps(pix1, sela, L_MORPH_HMT); + sel = selCreateFromString(sel_cross, 13, 13, "sel_cross"); + pix3 = pixDilate(NULL, pix2, sel); + pixXor(pix3, pix3, pix1); + regTestWritePixAndCheck(rp, pix3, IFF_TIFF_G4); /* 11 */ + pixDisplayWithTitle(pix3, 800, 200, NULL, rp->display); + + boxaDestroy(&boxa); + pixDestroy(&pixs); + pixDestroy(&pix1); + pixDestroy(&pix2); + pixDestroy(&pix3); + pixDestroy(&pixd); + selDestroy(&sel); + selaDestroy(&sela); + return regTestCleanup(rp); +} + + +static BOXA * +LocateBarcodes(PIX *pixs, + PIX **ppixd, + l_int32 flag) +{ +BOXA *boxa1, *boxa2, *boxad; +PIX *pix1, *pix2, *pix3; + + pix1 = pixScale(pixs, 0.5, 0.5); + pix2 = pixMorphSequence(pix1, "o1.5 + c15.1 + o10.15 + c20.20", flag); + boxa1 = pixConnComp(pix2, NULL, 8); + boxa2 = boxaSelectBySize(boxa1, 300, 0, L_SELECT_WIDTH, + L_SELECT_IF_GT, NULL); + boxad = boxaTransform(boxa2, 0, 0, 2.0, 2.0); + if (ppixd) { + pix3 = pixSelectBySize(pix2, 300, 0, 8, L_SELECT_WIDTH, + L_SELECT_IF_GT, NULL); + *ppixd = pixScale(pix3, 2.0, 2.0); + pixDestroy(&pix3); + } + + pixDestroy(&pix1); + pixDestroy(&pix2); + boxaDestroy(&boxa1); + boxaDestroy(&boxa2); + return boxad; +} + + +static SELA * +GetCornerSela(L_REGPARAMS *rp) +{ +PIX *pix; +SEL *sel; +SELA *sela1, *sela2; + + sela1 = selaAddHitMiss(NULL); + sela2 = selaCreate(4); + selaFindSelByName(sela1, "sel_ulc", NULL, &sel); + selaAddSel(sela2, sel, NULL, 1); + selaFindSelByName(sela1, "sel_urc", NULL, &sel); + selaAddSel(sela2, sel, NULL, 1); + selaFindSelByName(sela1, "sel_llc", NULL, &sel); + selaAddSel(sela2, sel, NULL, 1); + selaFindSelByName(sela1, "sel_lrc", NULL, &sel); + selaAddSel(sela2, sel, NULL, 1); + selaDestroy(&sela1); + if (rp->display) { + pix = selaDisplayInPix(sela2, 21, 3, 10, 4); + pixDisplay(pix, 0, 0); + pixDestroy(&pix); + } + return sela2; +} diff --git a/leptonica/prog/findpattern1.c b/leptonica/prog/findpattern1.c new file mode 100644 index 00000000..42395db7 --- /dev/null +++ b/leptonica/prog/findpattern1.c @@ -0,0 +1,145 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * findpattern1.c + * + * findpattern1 filein patternfile fileout + * + * This is setup with input parameters to generate a hit-miss + * Sel from 'patternfile' and use it on 'filein' at 300 ppi. + * For example, use char.tif of a "c" bitmap, taken from the + * the page image feyn.tif: + * + * findpattern1 feyn.tif char.tif /tmp/result.tif + * + * This shows a number of different outputs, including a magnified + * image of the Sel superimposed on the "c" bitmap. + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + + /* for pixGenerateSelWithRuns() */ +static const l_int32 NumHorLines = 11; +static const l_int32 NumVertLines = 8; +static const l_int32 MinRunlength = 1; + + /* for pixDisplayHitMissSel() */ +static const l_uint32 HitColor = 0xff880000; +static const l_uint32 MissColor = 0x00ff8800; + + +int main(int argc, + char **argv) +{ +char *filein, *fileout, *patternfile; +l_int32 w, h, i, n; +BOX *box, *boxe; +BOXA *boxa1, *boxa2; +PIX *pixs, *pixp, *pixpe, *pix1, *pix2, *pix3, *pix4, *pixhmt; +PIXCMAP *cmap; +SEL *sel_2h, *sel; +static char mainName[] = "findpattern1"; + + if (argc != 4) + return ERROR_INT(" Syntax: findpattern1 filein patternfile fileout", + mainName, 1); + filein = argv[1]; + patternfile = argv[2]; + fileout = argv[3]; + + setLeptDebugOK(1); + lept_mkdir("lept/hmt"); + + if ((pixs = pixRead(filein)) == NULL) + return ERROR_INT("pixs not made", mainName, 1); + if ((pixp = pixRead(patternfile)) == NULL) + return ERROR_INT("pixp not made", mainName, 1); + pixGetDimensions(pixp, &w, &h, NULL); + + /* Generate the hit-miss Sel with runs */ + sel = pixGenerateSelWithRuns(pixp, NumHorLines, NumVertLines, 0, + MinRunlength, 7, 7, 0, 0, &pixpe); + + /* Display the Sel two ways */ + selWriteStream(stderr, sel); + pix1 = pixDisplayHitMissSel(pixpe, sel, 9, HitColor, MissColor); + pixDisplay(pix1, 200, 200); + pixWrite("/tmp/lept/hmt/pix1.png", pix1, IFF_PNG); + + /* Use the Sel to find all instances in the page */ + startTimer(); + pixhmt = pixHMT(NULL, pixs, sel); + lept_stderr("Time to find patterns = %7.3f\n", stopTimer()); + + /* Small erosion to remove noise; typically not necessary if + * there are enough elements in the Sel */ + sel_2h = selCreateBrick(1, 2, 0, 0, SEL_HIT); + pix2 = pixErode(NULL, pixhmt, sel_2h); + + /* Display the result visually by placing the Sel at each + * location found */ + pix3 = pixDilate(NULL, pix2, sel); + cmap = pixcmapCreate(1); + pixcmapAddColor(cmap, 255, 255, 255); + pixcmapAddColor(cmap, 255, 0, 0); + pixSetColormap(pix3, cmap); + pixWrite(fileout, pix3, IFF_PNG); + + /* Display output with a red outline around each located pattern */ + boxa1 = pixConnCompBB(pix2, 8); + n = boxaGetCount(boxa1); + boxa2 = boxaCreate(n); + pix4 = pixConvert1To2Cmap(pixs); + for (i = 0; i < n; i++) { + box = boxaGetBox(boxa1, i, L_COPY); + boxe = boxCreate(box->x - w / 2, box->y - h / 2, w + 4, h + 4); + boxaAddBox(boxa2, boxe, L_INSERT); + pixRenderBoxArb(pix4, boxe, 2, 255, 0, 0); + boxDestroy(&box); + } + pixWrite("/tmp/lept/hmt/outline.png", pix4, IFF_PNG); + boxaWriteStream(stderr, boxa2); + + pixDestroy(&pixs); + pixDestroy(&pixp); + pixDestroy(&pixpe); + pixDestroy(&pix1); + pixDestroy(&pix2); + pixDestroy(&pix3); + pixDestroy(&pix4); + pixDestroy(&pixhmt); + selDestroy(&sel); + selDestroy(&sel_2h); + boxaDestroy(&boxa1); + boxaDestroy(&boxa2); + return 0; +} + diff --git a/leptonica/prog/findpattern2.c b/leptonica/prog/findpattern2.c new file mode 100644 index 00000000..26c400bd --- /dev/null +++ b/leptonica/prog/findpattern2.c @@ -0,0 +1,161 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * findpattern2.c + * + * We use pixGenerateSelRandom() to generate the sels. + * + * This is set up with input parameters to work on feyn.tif. + * + * (1) We extract a "e" bitmap, generate a hit-miss sel, and + * then produce several 4 bpp colormapped renditions, + * with the pattern either removed or highlighted. + * + * (2) We do the same with the word "Caltech". + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + + /* for pixDisplayHitMissSel() */ +static const l_uint32 HitColor = 0x33aa4400; +static const l_uint32 MissColor = 0xaa44bb00; + + +int main(int argc, + char **argv) +{ +BOX *box; +PIX *pixs, *pixc, *pixp, *pixsel, *pixhmt; +PIX *pixd1, *pixd2, *pixd3; +SEL *selhm; +static char mainName[] = "findpattern2"; + + if (argc != 1) + return ERROR_INT(" Syntax: findpattern2", mainName, 1); + + setLeptDebugOK(1); + lept_mkdir("lept/hmt"); + + /* -------------------------------------------- * + * Extract the pattern for a single character * + * ---------------------------------------------*/ + pixs = pixRead("feyn.tif"); + box = boxCreate(599, 1055, 18, 23); + pixc = pixClipRectangle(pixs, box, NULL); + + /* Make a hit-miss sel */ + selhm = pixGenerateSelRandom(pixc, 0.3, 0.2, 1, 6, 6, 0, 0, &pixp); + + /* Display the sel */ + pixsel = pixDisplayHitMissSel(pixp, selhm, 7, HitColor, MissColor); + pixDisplay(pixsel, 200, 200); + pixWrite("/tmp/lept/hmt/pixsel1.png", pixsel, IFF_PNG); + + /* Use the Sel to find all instances in the page */ + startTimer(); + pixhmt = pixHMT(NULL, pixs, selhm); + lept_stderr("Time to find patterns = %7.3f\n", stopTimer()); + + /* Color each instance at full res */ + pixd1 = pixDisplayMatchedPattern(pixs, pixp, pixhmt, selhm->cx, + selhm->cy, 0x0000ff00, 1.0, 5); + pixWrite("/tmp/lept/hmt/pixd11.png", pixd1, IFF_PNG); + + /* Color each instance at 0.3 scale */ + pixd2 = pixDisplayMatchedPattern(pixs, pixp, pixhmt, selhm->cx, + selhm->cy, 0x0000ff00, 0.5, 5); + pixWrite("/tmp/lept/hmt/junkpixd12.png", pixd2, IFF_PNG); + + /* Remove each instance from the input image */ + pixd3 = pixCopy(NULL, pixs); + pixRemoveMatchedPattern(pixd3, pixp, pixhmt, selhm->cx, + selhm->cy, 1); + pixWrite("/tmp/lept/hmt/pixr1.png", pixd3, IFF_PNG); + + boxDestroy(&box); + selDestroy(&selhm); + pixDestroy(&pixc); + pixDestroy(&pixp); + pixDestroy(&pixsel); + pixDestroy(&pixhmt); + pixDestroy(&pixd1); + pixDestroy(&pixd2); + pixDestroy(&pixd3); + + + /* -------------------------------------------- * + * Extract the pattern for a word * + * ---------------------------------------------*/ + box = boxCreate(208, 872, 130, 35); + pixc = pixClipRectangle(pixs, box, NULL); + + /* Make a hit-miss sel */ + selhm = pixGenerateSelRandom(pixc, 1.0, 0.05, 2, 6, 6, 0, 0, &pixp); + + /* Display the sel */ + pixsel = pixDisplayHitMissSel(pixp, selhm, 7, HitColor, MissColor); + pixDisplay(pixsel, 200, 200); + pixWrite("/tmp/lept/hmt/pixsel2.png", pixsel, IFF_PNG); + + /* Use the Sel to find all instances in the page */ + startTimer(); + pixhmt = pixHMT(NULL, pixs, selhm); + lept_stderr("Time to find word patterns = %7.3f\n", stopTimer()); + + /* Color each instance at full res */ + pixd1 = pixDisplayMatchedPattern(pixs, pixp, pixhmt, selhm->cx, + selhm->cy, 0x0000ff00, 1.0, 5); + pixWrite("/tmp/lept/hmt/pixd21.png", pixd1, IFF_PNG); + + /* Color each instance at 0.3 scale */ + pixd2 = pixDisplayMatchedPattern(pixs, pixp, pixhmt, selhm->cx, + selhm->cy, 0x0000ff00, 0.5, 5); + pixWrite("/tmp/lept/hmt/pixd22.png", pixd2, IFF_PNG); + + /* Remove each instance from the input image */ + pixd3 = pixCopy(NULL, pixs); + pixRemoveMatchedPattern(pixd3, pixp, pixhmt, selhm->cx, + selhm->cy, 1); + pixWrite("/tmp/lept/hmt/pixr2.png", pixd3, IFF_PNG); + + selDestroy(&selhm); + boxDestroy(&box); + pixDestroy(&pixc); + pixDestroy(&pixp); + pixDestroy(&pixsel); + pixDestroy(&pixhmt); + pixDestroy(&pixd1); + pixDestroy(&pixd2); + pixDestroy(&pixd3); + pixDestroy(&pixs); + return 0; +} + diff --git a/leptonica/prog/findpattern3.c b/leptonica/prog/findpattern3.c new file mode 100644 index 00000000..cc641cfe --- /dev/null +++ b/leptonica/prog/findpattern3.c @@ -0,0 +1,160 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * findpattern3.c + * + * We use pixGenerateSelBoundary() to generate the sels. + * + * This is set up with input parameters to work on feyn.tif. + * + * (1) We extract an "e" bitmap, generate a hit-miss sel, and + * then produce several 4 bpp colormapped renditions, + * with the pattern either removed or highlighted. + * + * (2) We do the same with the word "Caltech". + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + + /* for pixDisplayHitMissSel() */ +static const l_uint32 HitColor = 0x33aa4400; +static const l_uint32 MissColor = 0xaa44bb00; + +int main(int argc, + char **argv) +{ +BOX *box; +PIX *pixs, *pixc, *pixp, *pixsel, *pixhmt; +PIX *pixd1, *pixd2, *pixd3; +SEL *selhm; +static char mainName[] = "findpattern3"; + + if (argc != 1) + return ERROR_INT(" Syntax: findpattern3", mainName, 1); + + setLeptDebugOK(1); + lept_mkdir("lept/hmt"); + + /* -------------------------------------------- * + * Extract the pattern for a single character * + * ---------------------------------------------*/ + pixs = pixRead("feyn.tif"); + box = boxCreate(599, 1055, 18, 23); + pixc = pixClipRectangle(pixs, box, NULL); + + /* Make a hit-miss sel */ + selhm = pixGenerateSelBoundary(pixc, 1, 2, 2, 2, 1, 1, 0, 0, &pixp); + + /* Display the sel */ + pixsel = pixDisplayHitMissSel(pixp, selhm, 7, HitColor, MissColor); + pixDisplay(pixsel, 200, 200); + pixWrite("/tmp/lept/hmt/pixsel1.png", pixsel, IFF_PNG); + + /* Use the Sel to find all instances in the page */ + startTimer(); + pixhmt = pixHMT(NULL, pixs, selhm); + lept_stderr("Time to find patterns = %7.3f\n", stopTimer()); + + /* Color each instance at full res */ + pixd1 = pixDisplayMatchedPattern(pixs, pixp, pixhmt, selhm->cx, + selhm->cy, 0x0000ff00, 1.0, 5); + pixWrite("/tmp/lept/hmt/pixd11.png", pixd1, IFF_PNG); + + /* Color each instance at 0.3 scale */ + pixd2 = pixDisplayMatchedPattern(pixs, pixp, pixhmt, selhm->cx, + selhm->cy, 0x0000ff00, 0.5, 5); + pixWrite("/tmp/lept/hmt/pixd12.png", pixd2, IFF_PNG); + + /* Remove each instance from the input image */ + pixd3 = pixCopy(NULL, pixs); + pixRemoveMatchedPattern(pixd3, pixp, pixhmt, selhm->cx, + selhm->cy, 1); + pixWrite("/tmp/lept/hmt/pixr1.png", pixd3, IFF_PNG); + + boxDestroy(&box); + selDestroy(&selhm); + pixDestroy(&pixc); + pixDestroy(&pixp); + pixDestroy(&pixsel); + pixDestroy(&pixhmt); + pixDestroy(&pixd1); + pixDestroy(&pixd2); + pixDestroy(&pixd3); + + + /* -------------------------------------------- * + * Extract the pattern for a word * + * ---------------------------------------------*/ + box = boxCreate(208, 872, 130, 35); + pixc = pixClipRectangle(pixs, box, NULL); + + /* Make a hit-miss sel */ + selhm = pixGenerateSelBoundary(pixc, 2, 2, 1, 4, 1, 1, 0, 0, &pixp); + + /* Display the sel */ + pixsel = pixDisplayHitMissSel(pixp, selhm, 7, HitColor, MissColor); + pixDisplay(pixsel, 200, 200); + pixWrite("/tmp/lept/hmt/pixsel2.png", pixsel, IFF_PNG); + + /* Use the Sel to find all instances in the page */ + startTimer(); + pixhmt = pixHMT(NULL, pixs, selhm); + lept_stderr("Time to find word patterns = %7.3f\n", stopTimer()); + + /* Color each instance at full res */ + pixd1 = pixDisplayMatchedPattern(pixs, pixp, pixhmt, selhm->cx, + selhm->cy, 0x0000ff00, 1.0, 5); + pixWrite("/tmp/lept/hmt/pixd21.png", pixd1, IFF_PNG); + + /* Color each instance at 0.3 scale */ + pixd2 = pixDisplayMatchedPattern(pixs, pixp, pixhmt, selhm->cx, + selhm->cy, 0x0000ff00, 0.5, 5); + pixWrite("/tmp/lept/hmt/pixd22.png", pixd2, IFF_PNG); + + /* Remove each instance from the input image */ + pixd3 = pixCopy(NULL, pixs); + pixRemoveMatchedPattern(pixd3, pixp, pixhmt, selhm->cx, + selhm->cy, 1); + pixWrite("/tmp/lept/hmt/pixr2.png", pixd3, IFF_PNG); + + selDestroy(&selhm); + boxDestroy(&box); + pixDestroy(&pixc); + pixDestroy(&pixp); + pixDestroy(&pixsel); + pixDestroy(&pixhmt); + pixDestroy(&pixd1); + pixDestroy(&pixd2); + pixDestroy(&pixd3); + pixDestroy(&pixs); + return 0; +} + diff --git a/leptonica/prog/findpattern_reg.c b/leptonica/prog/findpattern_reg.c new file mode 100644 index 00000000..7b86bfe2 --- /dev/null +++ b/leptonica/prog/findpattern_reg.c @@ -0,0 +1,173 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * findpattern_reg.c + * + * This uses pixGenerateSelBoundary() to generate hit-miss Sels + * that are a good fit for two 1 bpp patterns: + * * a "T" in the banner name + * * the banner name ("Tribune") + * The sels are first displayed, showing the hit and miss elements + * in color. + * + * The sels are then used to identify and remove the components + * in a page image in which thay are found. We demonstrate + * the ability to find these components are reductions from 4 to 16x. + * (16x is extreme -- don't do this at home!) The results are displayed + * with the matched pattern either highlighted or removed. + * + * Some of these Sels are also made by livre_hmt.c for figures + * in the Document Image Applications chapter. + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + + /* for pixDisplayHitMissSel() */ +static const l_uint32 HitColor = 0x33aa4400; +static const l_uint32 MissColor = 0xaa44bb00; + + /* Patterns at full resolution */ +static const char *patname[2] = { + "tribune-word.png", /* patno = 0 */ + "tribune-t.png"}; /* patno = 1 */ + +l_int32 GeneratePattern(l_int32 patno, l_int32 red, L_REGPARAMS *rp); + + +int main(int argc, + char **argv) +{ +l_int32 patno, red; +L_REGPARAMS *rp; + + if (regTestSetup(argc, argv, &rp)) + return 1; + + for (patno = 0; patno < 2; patno++) { + for (red = 4; red <= 16; red *= 2) { + if (patno == 1 && red == 16) continue; + GeneratePattern(patno, red, rp); + } + } + + return regTestCleanup(rp); +} + + +l_int32 +GeneratePattern(l_int32 patno, + l_int32 red, + L_REGPARAMS *rp) +{ +l_int32 width, cx, cy; +PIX *pixs, *pixt, *pix, *pixr, *pixp, *pixsel, *pixhmt; +PIX *pixc1, *pixc2, *pixc3, *pixd; +PIXA *pixa; +SEL *selhm; + + PROCNAME("GeneratePattern"); + + if ((pixs = pixRead(patname[patno])) == NULL) { + rp->success = FALSE; + return ERROR_INT("pixs not made", procName, 1); + } + + /* Make a hit-miss sel at specified reduction factor */ + if (red == 4) { + pixt = pixReduceRankBinaryCascade(pixs, 4, 4, 0, 0); + selhm = pixGenerateSelBoundary(pixt, 2, 2, 20, 30, 1, 1, 0, 0, &pixp); + } + else if (red == 8) { + pixt = pixReduceRankBinaryCascade(pixs, 4, 4, 2, 0); + selhm = pixGenerateSelBoundary(pixt, 1, 2, 6, 12, 1, 1, 0, 0, &pixp); + } + else { /* red == 16 */ + pixt = pixReduceRankBinaryCascade(pixs, 4, 4, 2, 2); + selhm = pixGenerateSelBoundary(pixt, 1, 1, 4, 8, 0, 0, 0, 0, &pixp); + } + pixDestroy(&pixt); + + /* Display the sel */ + pixsel = pixDisplayHitMissSel(pixp, selhm, 7, HitColor, MissColor); + pixa = pixaCreate(2); + pixaAddPix(pixa, pixs, L_CLONE); + pixaAddPix(pixa, pixsel, L_CLONE); + width = (patno == 0) ? 1200 : 400; + pixd = pixaDisplayTiledAndScaled(pixa, 32, width, 2, 0, 30, 2); + regTestWritePixAndCheck(rp, pixd, IFF_PNG); + pixDisplayWithTitle(pixd, 100, 100 + 100 * (3 * patno + red / 4), + NULL, rp->display); + pixaDestroy(&pixa); + pixDestroy(&pixd); + + /* Use the sel to find all instances in the page */ + pix = pixRead("tribune-page-4x.png"); /* 4x reduced */ + if (red == 4) + pixr = pixClone(pix); + else if (red == 8) + pixr = pixReduceRankBinaryCascade(pix, 2, 0, 0, 0); + else /* red == 16 */ + pixr = pixReduceRankBinaryCascade(pix, 2, 2, 0, 0); + pixDestroy(&pix); + + startTimer(); + pixhmt = pixHMT(NULL, pixr, selhm); + lept_stderr("Time to find patterns = %7.3f\n", stopTimer()); + + /* Color each instance at full res */ + selGetParameters(selhm, NULL, NULL, &cy, &cx); + pixc1 = pixDisplayMatchedPattern(pixr, pixp, pixhmt, + cx, cy, 0x0000ff00, 1.0, 5); + regTestWritePixAndCheck(rp, pixc1, IFF_PNG); + pixDisplayWithTitle(pixc1, 500, 100, NULL, rp->display); + + /* Color each instance at 0.5 scale */ + pixc2 = pixDisplayMatchedPattern(pixr, pixp, pixhmt, + cx, cy, 0x0000ff00, 0.5, 5); + regTestWritePixAndCheck(rp, pixc2, IFF_PNG); + + /* Remove each instance from the input image */ + pixc3 = pixCopy(NULL, pixr); + pixRemoveMatchedPattern(pixc3, pixp, pixhmt, cx, cy, 1); + regTestWritePixAndCheck(rp, pixc3, IFF_PNG); + + selDestroy(&selhm); + pixDestroy(&pixp); + pixDestroy(&pixsel); + pixDestroy(&pixhmt); + pixDestroy(&pixc1); + pixDestroy(&pixc2); + pixDestroy(&pixc3); + pixDestroy(&pixd); + pixDestroy(&pixr); + pixDestroy(&pixs); + return 0; +} diff --git a/leptonica/prog/fish24.jpg b/leptonica/prog/fish24.jpg Binary files differnew file mode 100644 index 00000000..eba97436 --- /dev/null +++ b/leptonica/prog/fish24.jpg diff --git a/leptonica/prog/flipdetect_reg.c b/leptonica/prog/flipdetect_reg.c new file mode 100644 index 00000000..226224a3 --- /dev/null +++ b/leptonica/prog/flipdetect_reg.c @@ -0,0 +1,119 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * flipdetect_reg.c + * + * flipdetect_reg + * + * - Tests the high-level text orientation interface + * - Tests 90 degree orientation of text and whether the text is + * mirror reversed. + * - Shows the typical 'confidence' outputs from functions in flipdetect.c. + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + +int main(int argc, + char **argv) +{ +l_int32 i, orient, rotation; +l_float32 upconf, leftconf, conf; +PIX *pix, *pixs, *pix1, *pix2; +PIXA *pixa; +L_REGPARAMS *rp; + + if (regTestSetup(argc, argv, &rp)) + return 1; + + pix = pixRead("feyn.tif"); + pixs = pixScale(pix, 0.5, 0.5); + pixDestroy(&pix); + + /* Test high-level interface */ + lept_stderr("\nTest high-level detection/rotation\n"); + pix1 = pixRotateOrth(pixs, 3); + pix2 = pixOrientCorrect(pix1, 0.0, 0.0, &upconf, &leftconf, + &rotation, 0); + if (rp->display) + lept_stderr("upconf = %7.3f, leftconf = %7.3f, rotation = %d\n", + upconf, leftconf, rotation); + regTestCompareValues(rp, upconf, 2.543, 0.1); /* 0 */ + regTestCompareValues(rp, leftconf, 15.431, 0.1); /* 1 */ + regTestCompareValues(rp, rotation, 90, 0.0); /* 2 */ + regTestComparePix(rp, pixs, pix2); /* 3 */ + pixDestroy(&pix1); + pixDestroy(&pix2); + + /* Test orientation detection */ + pixa = pixaCreate(4); + pix1 = pixCopy(NULL, pixs); + lept_stderr("\nTest orient detection for 4 orientations\n"); + pixOrientDetect(pix1, &upconf, &leftconf, 0, 0); + makeOrientDecision(upconf, leftconf, 0, 0, &orient, 1); + regTestCompareValues(rp, upconf, 15.431, 0.1); /* 4 */ + regTestCompareValues(rp, orient, 1, 0.0); /* 5 */ + pixaAddPix(pixa, pix1, L_INSERT); + pix2 = pixRotate90(pix1, 1); + pix1 = pix2; + pixOrientDetect(pix1, &upconf, &leftconf, 0, 0); + makeOrientDecision(upconf, leftconf, 0, 0, &orient, 1); + regTestCompareValues(rp, leftconf, -15.702, 0.1); /* 6 */ + regTestCompareValues(rp, orient, 4, 0.0); /* 7 */ + pixaAddPix(pixa, pix1, L_INSERT); + pix2 = pixRotate90(pix1, 1); + pix1 = pix2; + pixOrientDetect(pix1, &upconf, &leftconf, 0, 0); + makeOrientDecision(upconf, leftconf, 0, 0, &orient, 1); + regTestCompareValues(rp, upconf, -15.702, 0.1); /* 8 */ + regTestCompareValues(rp, orient, 3, 0.0); /* 9 */ + pixaAddPix(pixa, pix1, L_INSERT); + pix2 = pixRotate90(pix1, 1); + pix1 = pix2; + pixOrientDetect(pix1, &upconf, &leftconf, 0, 0); + makeOrientDecision(upconf, leftconf, 0, 0, &orient, 1); + regTestCompareValues(rp, leftconf, 15.431, 0.1); /* 10 */ + regTestCompareValues(rp, orient, 2, 0.0); /* 11 */ + pixaAddPix(pixa, pix1, L_INSERT); + + pix2 = pixaDisplayTiledInColumns(pixa, 2, 0.25, 20, 2); + regTestWritePixAndCheck(rp, pix2, IFF_PNG); /* 12 */ + pixDisplayWithTitle(pix2, 100, 100, NULL, rp->display); + pixDestroy(&pix2); + pixaDestroy(&pixa); + + lept_stderr("\nTest mirror reverse detection\n"); + pixMirrorDetect(pixs, &conf, 0, rp->display); + lept_stderr("conf = %5.3f; not mirror reversed\n", conf); + regTestCompareValues(rp, conf, 4.128, 0.1); /* 13 */ + + pixDestroy(&pixs); + return regTestCleanup(rp); +} diff --git a/leptonica/prog/flipselgen.c.notused b/leptonica/prog/flipselgen.c.notused new file mode 100644 index 00000000..f8a76774 --- /dev/null +++ b/leptonica/prog/flipselgen.c.notused @@ -0,0 +1,124 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * flipselgen.c + * + * NOTE + * ================================================================ + * This code has been retired from the library, along with the code + * in flipdetectdwa.c that it generates. It is no longer compiled. + * ================================================================ + * + * Results are two files: + * fmorphgen.3.c + * fmorphgenlow.3.c + * using INDEX = 3. + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + +#define INDEX 3 +#define DFLAG 1 + + /* Sels for pixPageFlipDetectDWA() */ +static const char *textsel1 = "x oo " + "x oOo " + "x o " + "x " + "xxxxxx"; + +static const char *textsel2 = " oo x" + " oOo x" + " o x" + " x" + "xxxxxx"; + +static const char *textsel3 = "xxxxxx" + "x " + "x o " + "x oOo " + "x oo "; + +static const char *textsel4 = "xxxxxx" + " x" + " o x" + " oOo x" + " oo x"; + +int main(int argc, + char **argv) +{ +SEL *sel1, *sel2, *sel3, *sel4; +SELA *sela; +PIX *pix, *pixd; +PIXA *pixa; +static char mainName[] = "flipselgen"; + + if (argc != 1) + return ERROR_INT(" Syntax: flipselgen", mainName, 1); + + setLeptDebugOK(1); + sela = selaCreate(0); + sel1 = selCreateFromString(textsel1, 5, 6, "flipsel1"); + sel2 = selCreateFromString(textsel2, 5, 6, "flipsel2"); + sel3 = selCreateFromString(textsel3, 5, 6, "flipsel3"); + sel4 = selCreateFromString(textsel4, 5, 6, "flipsel4"); + selaAddSel(sela, sel1, NULL, 0); + selaAddSel(sela, sel2, NULL, 0); + selaAddSel(sela, sel3, NULL, 0); + selaAddSel(sela, sel4, NULL, 0); + + pixa = pixaCreate(4); + pix = selDisplayInPix(sel1, 23, 2); + pixDisplayWithTitle(pix, 100, 100, "sel1", DFLAG); + pixaAddPix(pixa, pix, L_INSERT); + pix = selDisplayInPix(sel2, 23, 2); + pixDisplayWithTitle(pix, 275, 100, "sel2", DFLAG); + pixaAddPix(pixa, pix, L_INSERT); + pix = selDisplayInPix(sel3, 23, 2); + pixDisplayWithTitle(pix, 450, 100, "sel3", DFLAG); + pixaAddPix(pixa, pix, L_INSERT); + pix = selDisplayInPix(sel4, 23, 2); + pixDisplayWithTitle(pix, 625, 100, "sel4", DFLAG); + pixaAddPix(pixa, pix, L_INSERT); + + pixd = pixaDisplayTiled(pixa, 800, 0, 15); + pixDisplayWithTitle(pixd, 100, 300, "allsels", DFLAG); + pixDestroy(&pixd); + pixaDestroy(&pixa); + + if (fhmtautogen(sela, INDEX, NULL)) + return ERROR_INT(" Generation failed", mainName, 1); + + selaDestroy(&sela); + return 0; +} + diff --git a/leptonica/prog/flipsels.txt b/leptonica/prog/flipsels.txt new file mode 100644 index 00000000..eb71128c --- /dev/null +++ b/leptonica/prog/flipsels.txt @@ -0,0 +1,35 @@ +# flipsels.txt +# +# Example file for reading Sels from file in +# a simple format. These Sels are also defined +# in flipdetect.c and compiled into strings there. +# + +textsel1 +"x oo " +"x oOo " +"x o " +"x " +"xxxxxx" + +textsel2 +" oo x" +" oOo x" +" o x" +" x" +"xxxxxx" + +textsel3 +"xxxxxx" +"x " +"x o " +"x oOo " +"x oo " + +textsel4 +"xxxxxx" +" x" +" o x" +" oOo x" +" oo x" + diff --git a/leptonica/prog/fmorphauto_reg.c b/leptonica/prog/fmorphauto_reg.c new file mode 100644 index 00000000..36d5967e --- /dev/null +++ b/leptonica/prog/fmorphauto_reg.c @@ -0,0 +1,163 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * fmorphauto_reg.c + * + * Basic regression test for erosion & dilation: rasterops & dwa. + * + * Tests erosion and dilation from 58 structuring elements + * by comparing the full image rasterop results with the + * automatically generated dwa results. + * + * Results must be identical for all operations. + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + + /* defined in morph.c */ +LEPT_DLL extern l_int32 MORPH_BC; + + +int main(int argc, + char **argv) +{ +l_int32 i, nsels, same, xorcount; +char *filein, *selname; +PIX *pixs, *pixs1, *pixt1, *pixt2, *pixt3, *pixt4; +SEL *sel; +SELA *sela; +static char mainName[] = "fmorphauto_reg"; + + if (argc != 2) + return ERROR_INT(" Syntax: fmorphauto_reg filein", mainName, 1); + filein = argv[1]; + setLeptDebugOK(1); + + if ((pixs = pixRead(filein)) == NULL) + return ERROR_INT("pix not made", mainName, 1); + + sela = selaAddBasic(NULL); + nsels = selaGetCount(sela); + for (i = 0; i < nsels; i++) + { + sel = selaGetSel(sela, i); + selname = selGetName(sel); + + /* --------- dilation ----------*/ + + pixt1 = pixDilate(NULL, pixs, sel); + + pixs1 = pixAddBorder(pixs, 32, 0); + pixt2 = pixFMorphopGen_1(NULL, pixs1, L_MORPH_DILATE, selname); + pixt3 = pixRemoveBorder(pixt2, 32); + + pixt4 = pixXor(NULL, pixt1, pixt3); + pixZero(pixt4, &same); + + if (same == 1) { + lept_stderr("dilations are identical for sel %d (%s)\n", + i, selname); + } else { + lept_stderr("dilations differ for sel %d (%s)\n", i, selname); + pixCountPixels(pixt4, &xorcount, NULL); + lept_stderr("Number of pixels in XOR: %d\n", xorcount); + } + + pixDestroy(&pixt1); + pixDestroy(&pixt2); + pixDestroy(&pixt3); + pixDestroy(&pixt4); + pixDestroy(&pixs1); + + /* --------- erosion with asymmetric b.c ----------*/ + + resetMorphBoundaryCondition(ASYMMETRIC_MORPH_BC); + lept_stderr("MORPH_BC = %d ... ", MORPH_BC); + pixt1 = pixErode(NULL, pixs, sel); + + if (MORPH_BC == ASYMMETRIC_MORPH_BC) + pixs1 = pixAddBorder(pixs, 32, 0); /* OFF border pixels */ + else + pixs1 = pixAddBorder(pixs, 32, 1); /* ON border pixels */ + pixt2 = pixFMorphopGen_1(NULL, pixs1, L_MORPH_ERODE, selname); + pixt3 = pixRemoveBorder(pixt2, 32); + + pixt4 = pixXor(NULL, pixt1, pixt3); + pixZero(pixt4, &same); + + if (same == 1) { + lept_stderr("erosions are identical for sel %d (%s)\n", i, selname); + } else { + lept_stderr("erosions differ for sel %d (%s)\n", i, selname); + pixCountPixels(pixt4, &xorcount, NULL); + lept_stderr("Number of pixels in XOR: %d\n", xorcount); + } + + pixDestroy(&pixt1); + pixDestroy(&pixt2); + pixDestroy(&pixt3); + pixDestroy(&pixt4); + pixDestroy(&pixs1); + + /* --------- erosion with symmetric b.c ----------*/ + + resetMorphBoundaryCondition(SYMMETRIC_MORPH_BC); + lept_stderr("MORPH_BC = %d ... ", MORPH_BC); + pixt1 = pixErode(NULL, pixs, sel); + + if (MORPH_BC == ASYMMETRIC_MORPH_BC) + pixs1 = pixAddBorder(pixs, 32, 0); /* OFF border pixels */ + else + pixs1 = pixAddBorder(pixs, 32, 1); /* ON border pixels */ + pixt2 = pixFMorphopGen_1(NULL, pixs1, L_MORPH_ERODE, selname); + pixt3 = pixRemoveBorder(pixt2, 32); + + pixt4 = pixXor(NULL, pixt1, pixt3); + pixZero(pixt4, &same); + + if (same == 1) { + lept_stderr("erosions are identical for sel %d (%s)\n", i, selname); + } else { + lept_stderr("erosions differ for sel %d (%s)\n", i, selname); + pixCountPixels(pixt4, &xorcount, NULL); + lept_stderr("Number of pixels in XOR: %d\n", xorcount); + } + + pixDestroy(&pixt1); + pixDestroy(&pixt2); + pixDestroy(&pixt3); + pixDestroy(&pixt4); + pixDestroy(&pixs1); + } + + return 0; +} + diff --git a/leptonica/prog/fmorphautogen.c b/leptonica/prog/fmorphautogen.c new file mode 100644 index 00000000..9564f770 --- /dev/null +++ b/leptonica/prog/fmorphautogen.c @@ -0,0 +1,74 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * fmorphautogen.c + * + * This program is used to generate the two files. + * If filename is not given, the files are: + * fmorphgen.<n>.c + * fmorphgenlow.<n>.c + * where <n> is the input index. Otherwise they are: + * <filename>.<n>.c + * <filename>low.<n>.c + * These two files, when compiled, implement dwa operations for + * all sels generated by selaAddBasic(). + * + * The library files fmorphgen.1.c and fmorphgenlow.1.c + * were made using index = 1. + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + +int main(int argc, + char **argv) +{ +char *filename; +l_int32 index; +SELA *sela; +static char mainName[] = "fmorphautogen"; + + if (argc != 2 && argc != 3) + return ERROR_INT(" Syntax: fmorphautogen index <filename>", + mainName, 1); + index = atoi(argv[1]); + filename = NULL; + if (argc == 3) + filename = argv[2]; + + setLeptDebugOK(1); + sela = selaAddBasic(NULL); + if (fmorphautogen(sela, index, filename)) + return 1; + + selaDestroy(&sela); + return 0; +} + diff --git a/leptonica/prog/fonts/chars-10.pa b/leptonica/prog/fonts/chars-10.pa Binary files differnew file mode 100644 index 00000000..fd3d93a7 --- /dev/null +++ b/leptonica/prog/fonts/chars-10.pa diff --git a/leptonica/prog/fonts/chars-10.ps b/leptonica/prog/fonts/chars-10.ps new file mode 100644 index 00000000..cee09b2a --- /dev/null +++ b/leptonica/prog/fonts/chars-10.ps @@ -0,0 +1,21 @@ +%!PS +% chars-10.ps + +/inch {72 mul} def +/Palatino-Roman +10 72 div inch +selectfont + +% 25 chars in first row: 33-57 +0.3 inch 2.0 inch moveto +3. 0. (!"#$%&'()*+,-./0123456789) ashow + +% 34 chars in second row: 58-91 +0.3 inch 1.4 inch moveto +3. 0. (:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[) ashow + +% 34 chars in third row: 93-126 +0.3 inch 0.8 inch moveto +3. 0. (]^_`abcdefghijklmnopqrstuvwxyz{|}~) ashow + +showpage diff --git a/leptonica/prog/fonts/chars-10.tif b/leptonica/prog/fonts/chars-10.tif Binary files differnew file mode 100644 index 00000000..a6e36520 --- /dev/null +++ b/leptonica/prog/fonts/chars-10.tif diff --git a/leptonica/prog/fonts/chars-12.pa b/leptonica/prog/fonts/chars-12.pa Binary files differnew file mode 100644 index 00000000..f7159865 --- /dev/null +++ b/leptonica/prog/fonts/chars-12.pa diff --git a/leptonica/prog/fonts/chars-12.ps b/leptonica/prog/fonts/chars-12.ps new file mode 100644 index 00000000..87b03b76 --- /dev/null +++ b/leptonica/prog/fonts/chars-12.ps @@ -0,0 +1,21 @@ +%!PS +% chars-12.ps + +/inch {72 mul} def +/Palatino-Roman +12 72 div inch +selectfont + +% 25 chars in first row: 33-57 +0.3 inch 2.0 inch moveto +3. 0. (!"#$%&'()*+,-./0123456789) ashow + +% 34 chars in second row: 58-91 +0.3 inch 1.4 inch moveto +3. 0. (:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[) ashow + +% 34 chars in third row: 93-126 +0.3 inch 0.8 inch moveto +3. 0. (]^_`abcdefghijklmnopqrstuvwxyz{|}~) ashow + +showpage diff --git a/leptonica/prog/fonts/chars-12.tif b/leptonica/prog/fonts/chars-12.tif Binary files differnew file mode 100644 index 00000000..f53304f4 --- /dev/null +++ b/leptonica/prog/fonts/chars-12.tif diff --git a/leptonica/prog/fonts/chars-14.pa b/leptonica/prog/fonts/chars-14.pa Binary files differnew file mode 100644 index 00000000..1b0ede1e --- /dev/null +++ b/leptonica/prog/fonts/chars-14.pa diff --git a/leptonica/prog/fonts/chars-14.ps b/leptonica/prog/fonts/chars-14.ps new file mode 100644 index 00000000..364fee0f --- /dev/null +++ b/leptonica/prog/fonts/chars-14.ps @@ -0,0 +1,21 @@ +%!PS +% chars-14.ps + +/inch {72 mul} def +/Palatino-Roman +14 72 div inch +selectfont + +% 25 chars in first row: 33-57 +0.3 inch 2.0 inch moveto +3. 0. (!"#$%&'()*+,-./0123456789) ashow + +% 34 chars in second row: 58-91 +0.3 inch 1.4 inch moveto +3. 0. (:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[) ashow + +% 34 chars in third row: 93-126 +0.3 inch 0.8 inch moveto +3. 0. (]^_`abcdefghijklmnopqrstuvwxyz{|}~) ashow + +showpage diff --git a/leptonica/prog/fonts/chars-14.tif b/leptonica/prog/fonts/chars-14.tif Binary files differnew file mode 100644 index 00000000..ff47cb5b --- /dev/null +++ b/leptonica/prog/fonts/chars-14.tif diff --git a/leptonica/prog/fonts/chars-16.pa b/leptonica/prog/fonts/chars-16.pa Binary files differnew file mode 100644 index 00000000..32c9bd2f --- /dev/null +++ b/leptonica/prog/fonts/chars-16.pa diff --git a/leptonica/prog/fonts/chars-16.ps b/leptonica/prog/fonts/chars-16.ps new file mode 100644 index 00000000..a2390247 --- /dev/null +++ b/leptonica/prog/fonts/chars-16.ps @@ -0,0 +1,21 @@ +%!PS +% chars-16.ps + +/inch {72 mul} def +/Palatino-Roman +16 72 div inch +selectfont + +% 25 chars in first row: 33-57 +0.3 inch 2.0 inch moveto +3. 0. (!"#$%&'()*+,-./0123456789) ashow + +% 34 chars in second row: 58-91 +0.3 inch 1.4 inch moveto +3. 0. (:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[) ashow + +% 34 chars in third row: 93-126 +0.3 inch 0.8 inch moveto +3. 0. (]^_`abcdefghijklmnopqrstuvwxyz{|}~) ashow + +showpage diff --git a/leptonica/prog/fonts/chars-16.tif b/leptonica/prog/fonts/chars-16.tif Binary files differnew file mode 100644 index 00000000..4d6a5d2f --- /dev/null +++ b/leptonica/prog/fonts/chars-16.tif diff --git a/leptonica/prog/fonts/chars-18.pa b/leptonica/prog/fonts/chars-18.pa Binary files differnew file mode 100644 index 00000000..c1941d4d --- /dev/null +++ b/leptonica/prog/fonts/chars-18.pa diff --git a/leptonica/prog/fonts/chars-18.ps b/leptonica/prog/fonts/chars-18.ps new file mode 100644 index 00000000..1a6be2c6 --- /dev/null +++ b/leptonica/prog/fonts/chars-18.ps @@ -0,0 +1,21 @@ +%!PS +% chars-18.ps + +/inch {72 mul} def +/Palatino-Roman +18 72 div inch +selectfont + +% 25 chars in first row: 33-57 +0.3 inch 2.0 inch moveto +3. 0. (!"#$%&'()*+,-./0123456789) ashow + +% 34 chars in second row: 58-91 +0.3 inch 1.4 inch moveto +3. 0. (:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[) ashow + +% 34 chars in third row: 93-126 +0.3 inch 0.8 inch moveto +3. 0. (]^_`abcdefghijklmnopqrstuvwxyz{|}~) ashow + +showpage diff --git a/leptonica/prog/fonts/chars-18.tif b/leptonica/prog/fonts/chars-18.tif Binary files differnew file mode 100644 index 00000000..3eb9d9d5 --- /dev/null +++ b/leptonica/prog/fonts/chars-18.tif diff --git a/leptonica/prog/fonts/chars-20.pa b/leptonica/prog/fonts/chars-20.pa Binary files differnew file mode 100644 index 00000000..63244baa --- /dev/null +++ b/leptonica/prog/fonts/chars-20.pa diff --git a/leptonica/prog/fonts/chars-20.ps b/leptonica/prog/fonts/chars-20.ps new file mode 100644 index 00000000..926cd718 --- /dev/null +++ b/leptonica/prog/fonts/chars-20.ps @@ -0,0 +1,21 @@ +%!PS +% chars-20.ps + +/inch {72 mul} def +/Palatino-Roman +20 72 div inch +selectfont + +% 25 chars in first row: 33-57 +0.3 inch 2.0 inch moveto +3. 0. (!"#$%&'()*+,-./0123456789) ashow + +% 34 chars in second row: 58-91 +0.3 inch 1.4 inch moveto +3. 0. (:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[) ashow + +% 34 chars in third row: 93-126 +0.3 inch 0.8 inch moveto +3. 0. (]^_`abcdefghijklmnopqrstuvwxyz{|}~) ashow + +showpage diff --git a/leptonica/prog/fonts/chars-20.tif b/leptonica/prog/fonts/chars-20.tif Binary files differnew file mode 100644 index 00000000..53841dd5 --- /dev/null +++ b/leptonica/prog/fonts/chars-20.tif diff --git a/leptonica/prog/fonts/chars-4.pa b/leptonica/prog/fonts/chars-4.pa Binary files differnew file mode 100644 index 00000000..e347faaa --- /dev/null +++ b/leptonica/prog/fonts/chars-4.pa diff --git a/leptonica/prog/fonts/chars-4.ps b/leptonica/prog/fonts/chars-4.ps new file mode 100644 index 00000000..fe8ea03b --- /dev/null +++ b/leptonica/prog/fonts/chars-4.ps @@ -0,0 +1,21 @@ +%!PS +% chars-4.ps + +/inch {72 mul} def +/Palatino-Roman +4 72 div inch +selectfont + +% 25 chars in first row: 33-57 +0.3 inch 2.0 inch moveto +3. 0. (!"#$%&'()*+,-./0123456789) ashow + +% 34 chars in second row: 58-91 +0.3 inch 1.4 inch moveto +3. 0. (:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[) ashow + +% 34 chars in third row: 93-126 +0.3 inch 0.8 inch moveto +3. 0. (]^_`abcdefghijklmnopqrstuvwxyz{|}~) ashow + +showpage diff --git a/leptonica/prog/fonts/chars-4.tif b/leptonica/prog/fonts/chars-4.tif Binary files differnew file mode 100644 index 00000000..096caa61 --- /dev/null +++ b/leptonica/prog/fonts/chars-4.tif diff --git a/leptonica/prog/fonts/chars-6.pa b/leptonica/prog/fonts/chars-6.pa Binary files differnew file mode 100644 index 00000000..d720f517 --- /dev/null +++ b/leptonica/prog/fonts/chars-6.pa diff --git a/leptonica/prog/fonts/chars-6.ps b/leptonica/prog/fonts/chars-6.ps new file mode 100644 index 00000000..91d170a5 --- /dev/null +++ b/leptonica/prog/fonts/chars-6.ps @@ -0,0 +1,21 @@ +%!PS +% chars-6.ps + +/inch {72 mul} def +/Palatino-Roman +6 72 div inch +selectfont + +% 25 chars in first row: 33-57 +0.3 inch 2.0 inch moveto +3. 0. (!"#$%&'()*+,-./0123456789) ashow + +% 34 chars in second row: 58-91 +0.3 inch 1.4 inch moveto +3. 0. (:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[) ashow + +% 34 chars in third row: 93-126 +0.3 inch 0.8 inch moveto +3. 0. (]^_`abcdefghijklmnopqrstuvwxyz{|}~) ashow + +showpage diff --git a/leptonica/prog/fonts/chars-6.tif b/leptonica/prog/fonts/chars-6.tif Binary files differnew file mode 100644 index 00000000..2839a445 --- /dev/null +++ b/leptonica/prog/fonts/chars-6.tif diff --git a/leptonica/prog/fonts/chars-8.pa b/leptonica/prog/fonts/chars-8.pa Binary files differnew file mode 100644 index 00000000..fee467f6 --- /dev/null +++ b/leptonica/prog/fonts/chars-8.pa diff --git a/leptonica/prog/fonts/chars-8.ps b/leptonica/prog/fonts/chars-8.ps new file mode 100644 index 00000000..a6a83b98 --- /dev/null +++ b/leptonica/prog/fonts/chars-8.ps @@ -0,0 +1,21 @@ +%!PS +% chars-8.ps + +/inch {72 mul} def +/Palatino-Roman +8 72 div inch +selectfont + +% 25 chars in first row: 33-57 +0.3 inch 2.0 inch moveto +3. 0. (!"#$%&'()*+,-./0123456789) ashow + +% 34 chars in second row: 58-91 +0.3 inch 1.4 inch moveto +3. 0. (:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[) ashow + +% 34 chars in third row: 93-126 +0.3 inch 0.8 inch moveto +3. 0. (]^_`abcdefghijklmnopqrstuvwxyz{|}~) ashow + +showpage diff --git a/leptonica/prog/fonts/chars-8.tif b/leptonica/prog/fonts/chars-8.tif Binary files differnew file mode 100644 index 00000000..74f35f59 --- /dev/null +++ b/leptonica/prog/fonts/chars-8.tif diff --git a/leptonica/prog/form1.tif b/leptonica/prog/form1.tif Binary files differnew file mode 100644 index 00000000..0a98e205 --- /dev/null +++ b/leptonica/prog/form1.tif diff --git a/leptonica/prog/form2.tif b/leptonica/prog/form2.tif Binary files differnew file mode 100644 index 00000000..32893cc5 --- /dev/null +++ b/leptonica/prog/form2.tif diff --git a/leptonica/prog/fpix1_reg.c b/leptonica/prog/fpix1_reg.c new file mode 100644 index 00000000..1d106a8f --- /dev/null +++ b/leptonica/prog/fpix1_reg.c @@ -0,0 +1,364 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * fpix1_reg.c + * + * Regression test for a number of functions in the FPix utility. + * FPix allows you to do floating point operations such as + * convolution, with conversions to and from Pix. + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include <math.h> +#include "allheaders.h" + +static void MakePtasAffine(l_int32 i, PTA **pptas, PTA **pptad); +static void MakePtas(l_int32 i, PTA **pptas, PTA **pptad); + +static const l_int32 xs1[] = { 300, 300, 1100, 300, 32}; +static const l_int32 ys1[] = {1200, 1200, 1200, 1250, 934}; +static const l_int32 xs2[] = {1200, 1200, 325, 1300, 487}; +static const l_int32 ys2[] = {1100, 1100, 1200, 1250, 934}; +static const l_int32 xs3[] = { 200, 200, 1200, 250, 32}; +static const l_int32 ys3[] = { 200, 200, 200, 300, 67}; +static const l_int32 xs4[] = {1200, 1200, 1100, 1250, 332}; +static const l_int32 ys4[] = { 400, 200, 200, 300, 57}; + +static const l_int32 xd1[] = { 300, 300, 1150, 300, 32}; +static const l_int32 yd1[] = {1200, 1400, 1150, 1350, 934}; +static const l_int32 xd2[] = {1100, 1400, 320, 1300, 487}; +static const l_int32 yd2[] = {1000, 1500, 1300, 1200, 904}; +static const l_int32 xd3[] = { 250, 200, 1310, 300, 61}; +static const l_int32 yd3[] = { 200, 300, 250, 325, 83}; +static const l_int32 xd4[] = {1250, 1200, 1140, 1250, 412}; +static const l_int32 yd4[] = { 300, 300, 250, 350, 83}; + + +int main(int argc, + char **argv) +{ +l_float32 sum, sumx, sumy, diff; +L_DEWARP *dew; +L_DEWARPA *dewa; +FPIX *fpixs, *fpixs2, *fpixs3, *fpixs4, *fpixg, *fpixd; +FPIX *fpix1, *fpix2; +DPIX *dpix, *dpix2; +L_KERNEL *kel, *kelx, *kely; +PIX *pixs, *pixs2, *pixs3, *pixd, *pixg, *pixb, *pixn; +PIX *pix0, *pix1, *pix2, *pix3, *pix4, *pix5, *pix6; +PIXA *pixa; +PTA *ptas, *ptad; +L_REGPARAMS *rp; + +#if !defined(HAVE_LIBPNG) + L_ERROR("This test requires libpng to run.\n", "fpix1_reg"); + exit(77); +#endif + + if (regTestSetup(argc, argv, &rp)) + return 1; + + /* Gaussian kernel */ + pixa = pixaCreate(0); + kel = makeGaussianKernel(5, 5, 3.0, 4.0); + kernelGetSum(kel, &sum); + if (rp->display) lept_stderr("Sum for 2d gaussian kernel = %f\n", sum); + pix0 = kernelDisplayInPix(kel, 41, 2); + regTestWritePixAndCheck(rp, pix0, IFF_PNG); /* 0 */ + pixaAddPix(pixa, pix0, L_INSERT); + + /* Separable gaussian kernel */ + makeGaussianKernelSep(5, 5, 3.0, 4.0, &kelx, &kely); + kernelGetSum(kelx, &sumx); + if (rp->display) lept_stderr("Sum for x gaussian kernel = %f\n", sumx); + kernelGetSum(kely, &sumy); + if (rp->display) lept_stderr("Sum for y gaussian kernel = %f\n", sumy); + if (rp->display) lept_stderr("Sum for x * y gaussian kernel = %f\n", + sumx * sumy); + pix0 = kernelDisplayInPix(kelx, 41, 2); + regTestWritePixAndCheck(rp, pix0, IFF_PNG); /* 1 */ + pixaAddPix(pixa, pix0, L_INSERT); + pix0 = kernelDisplayInPix(kely, 41, 2); + regTestWritePixAndCheck(rp, pix0, IFF_PNG); /* 2 */ + pixaAddPix(pixa, pix0, L_INSERT); + pix0 = pixaDisplayTiledInColumns(pixa, 4, 1.0, 20, 2); + regTestWritePixAndCheck(rp, pix0, IFF_PNG); /* 3 */ + pixaDestroy(&pixa); + pixDestroy(&pix0); + + /* Use pixRasterop() to generate source image */ + pixa = pixaCreate(0); + pixs = pixRead("test8.jpg"); + pixs2 = pixRead("karen8.jpg"); + pixRasterop(pixs, 150, 125, 150, 100, PIX_SRC, pixs2, 75, 100); + regTestWritePixAndCheck(rp, pixs, IFF_JFIF_JPEG); /* 4 */ + + /* Convolution directly with pix */ + pix1 = pixConvolve(pixs, kel, 8, 1); + regTestWritePixAndCheck(rp, pix1, IFF_JFIF_JPEG); /* 5 */ + pixaAddPix(pixa, pix1, L_INSERT); + pix2 = pixConvolveSep(pixs, kelx, kely, 8, 1); + regTestWritePixAndCheck(rp, pix2, IFF_JFIF_JPEG); /* 6 */ + pixaAddPix(pixa, pix2, L_INSERT); + + /* Convolution indirectly with fpix, using fpixRasterop() + * to generate the source image. */ + fpixs = pixConvertToFPix(pixs, 3); + fpixs2 = pixConvertToFPix(pixs2, 3); + fpixRasterop(fpixs, 150, 125, 150, 100, fpixs2, 75, 100); + fpix1 = fpixConvolve(fpixs, kel, 1); + pix3 = fpixConvertToPix(fpix1, 8, L_CLIP_TO_ZERO, 1); + regTestWritePixAndCheck(rp, pix3, IFF_JFIF_JPEG); /* 7 */ + pixaAddPix(pixa, pix3, L_INSERT); + fpix2 = fpixConvolveSep(fpixs, kelx, kely, 1); + pix4 = fpixConvertToPix(fpix2, 8, L_CLIP_TO_ZERO, 1); + regTestWritePixAndCheck(rp, pix4, IFF_JFIF_JPEG); /* 8 */ + pixaAddPix(pixa, pix4, L_INSERT); + pixDestroy(&pixs2); + fpixDestroy(&fpixs2); + fpixDestroy(&fpix1); + fpixDestroy(&fpix2); + + /* Comparison of results */ + if (rp->display) { + pixCompareGray(pix1, pix2, L_COMPARE_ABS_DIFF, 0, NULL, + &diff, NULL, NULL); + lept_stderr("Ave diff of pixConvolve and pixConvolveSep: %f\n", diff); + pixCompareGray(pix3, pix4, L_COMPARE_ABS_DIFF, 0, NULL, + &diff, NULL, NULL); + lept_stderr("Ave diff of fpixConvolve and fpixConvolveSep: %f\n", diff); + pixCompareGray(pix1, pix3, L_COMPARE_ABS_DIFF, 0, NULL, + &diff, NULL, NULL); + lept_stderr("Ave diff of pixConvolve and fpixConvolve: %f\n", diff); + } + pixCompareGray(pix2, pix4, L_COMPARE_ABS_DIFF, GPLOT_PNG, NULL, + &diff, NULL, NULL); + lept_stderr("Ave diff of pixConvolveSep and fpixConvolveSep: %f\n", diff); + pix5 = pixRead("/tmp/lept/comp/compare_gray0.png"); + regTestWritePixAndCheck(rp, pix5, IFF_PNG); /* 9 */ + pixaAddPix(pixa, pix5, L_INSERT); + pix1 = pixaDisplayTiledInColumns(pixa, 2, 1.0, 20, 2); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 10 */ + pixaDestroy(&pixa); + pixDestroy(&pix1); + + /* Test arithmetic operations; add in a fraction rotated by 180 */ + pixa = pixaCreate(0); + pixs3 = pixRotate180(NULL, pixs); + regTestWritePixAndCheck(rp, pixs3, IFF_JFIF_JPEG); /* 11 */ + pixaAddPix(pixa, pixs3, L_INSERT); + fpixs3 = pixConvertToFPix(pixs3, 3); + fpixd = fpixLinearCombination(NULL, fpixs, fpixs3, 20.0, 5.0); + fpixAddMultConstant(fpixd, 0.0, 23.174); /* multiply up in magnitude */ + pixd = fpixDisplayMaxDynamicRange(fpixd); /* bring back to 8 bpp */ + regTestWritePixAndCheck(rp, pixd, IFF_JFIF_JPEG); /* 12 */ + pixaAddPix(pixa, pixd, L_INSERT); + fpixDestroy(&fpixs3); + fpixDestroy(&fpixd); + pixDestroy(&pixs); + fpixDestroy(&fpixs); + + /* Display results */ + pixd = pixaDisplayTiledInColumns(pixa, 2, 1.0, 20, 2); + regTestWritePixAndCheck(rp, pixd, IFF_JFIF_JPEG); /* 13 */ + pixDisplayWithTitle(pixd, 100, 100, NULL, rp->display); + pixDestroy(&pixd); + pixaDestroy(&pixa); + + /* Test some more convolutions, with sampled output. First on pix */ + pixa = pixaCreate(0); + pixs = pixRead("1555.007.jpg"); + pixg = pixConvertTo8(pixs, 0); + l_setConvolveSampling(5, 5); + pix1 = pixConvolve(pixg, kel, 8, 1); + regTestWritePixAndCheck(rp, pix1, IFF_JFIF_JPEG); /* 14 */ + pixaAddPix(pixa, pix1, L_INSERT); + pix2 = pixConvolveSep(pixg, kelx, kely, 8, 1); + regTestWritePixAndCheck(rp, pix2, IFF_JFIF_JPEG); /* 15 */ + pixaAddPix(pixa, pix2, L_INSERT); + pix3 = pixConvolveRGB(pixs, kel); + regTestWritePixAndCheck(rp, pix3, IFF_JFIF_JPEG); /* 16 */ + pixaAddPix(pixa, pix3, L_INSERT); + pix4 = pixConvolveRGBSep(pixs, kelx, kely); + regTestWritePixAndCheck(rp, pix4, IFF_JFIF_JPEG); /* 17 */ + pixaAddPix(pixa, pix4, L_INSERT); + + /* Then on fpix */ + fpixg = pixConvertToFPix(pixg, 1); + fpix1 = fpixConvolve(fpixg, kel, 1); + pix5 = fpixConvertToPix(fpix1, 8, L_CLIP_TO_ZERO, 0); + regTestWritePixAndCheck(rp, pix5, IFF_JFIF_JPEG); /* 18 */ + pixaAddPix(pixa, pix5, L_INSERT); + fpix2 = fpixConvolveSep(fpixg, kelx, kely, 1); + pix6 = fpixConvertToPix(fpix2, 8, L_CLIP_TO_ZERO, 0); + regTestWritePixAndCheck(rp, pix6, IFF_JFIF_JPEG); /* 19 */ + pixaAddPix(pixa, pix6, L_INSERT); + regTestCompareSimilarPix(rp, pix1, pix5, 2, 0.00, 0); /* 20 */ + regTestCompareSimilarPix(rp, pix2, pix6, 2, 0.00, 0); /* 21 */ + fpixDestroy(&fpixg); + fpixDestroy(&fpix1); + fpixDestroy(&fpix2); + + pixd = pixaDisplayTiledInColumns(pixa, 2, 1.0, 20, 2); + regTestWritePixAndCheck(rp, pixd, IFF_JFIF_JPEG); /* 22 */ + pixDisplayWithTitle(pixd, 600, 100, NULL, rp->display); + pixDestroy(&pixs); + pixDestroy(&pixg); + pixDestroy(&pixd); + pixaDestroy(&pixa); + + /* Test extension (continued and slope). + * First, build a smooth vertical disparity array; + * then extend and show the contours. */ + pixs = pixRead("cat.035.jpg"); + pixn = pixBackgroundNormSimple(pixs, NULL, NULL); + pixg = pixConvertRGBToGray(pixn, 0.5, 0.3, 0.2); + pixb = pixThresholdToBinary(pixg, 130); + dewa = dewarpaCreate(1, 30, 1, 15, 0); + if ((dew = dewarpCreate(pixb, 35)) == NULL) { + rp->success = FALSE; + L_ERROR("dew not made; tests 21-28 skipped (failed)\n", "fpix1_reg"); + return regTestCleanup(rp); + } + dewarpaInsertDewarp(dewa, dew); + dewarpBuildPageModel(dew, NULL); /* two invalid indices in ptaGetPt() */ + dewarpPopulateFullRes(dew, NULL, 0, 0); + fpixs = dew->fullvdispar; + fpixs2 = fpixAddContinuedBorder(fpixs, 200, 200, 100, 300); + fpixs3 = fpixAddSlopeBorder(fpixs, 200, 200, 100, 300); + dpix = fpixConvertToDPix(fpixs3); + fpixs4 = dpixConvertToFPix(dpix); + pix1 = fpixRenderContours(fpixs, 2.0, 0.2); + pix2 = fpixRenderContours(fpixs2, 2.0, 0.2); + pix3 = fpixRenderContours(fpixs3, 2.0, 0.2); + pix4 = fpixRenderContours(fpixs4, 2.0, 0.2); + pix5 = pixRead("karen8.jpg"); + dpix2 = pixConvertToDPix(pix5, 1); + pix6 = dpixConvertToPix(dpix2, 8, L_CLIP_TO_ZERO, 0); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 23 */ + pixDisplayWithTitle(pix1, 0, 100, NULL, rp->display); + regTestWritePixAndCheck(rp, pix2, IFF_PNG); /* 24 */ + pixDisplayWithTitle(pix2, 470, 100, NULL, rp->display); + regTestWritePixAndCheck(rp, pix3, IFF_PNG); /* 25 */ + pixDisplayWithTitle(pix3, 1035, 100, NULL, rp->display); + regTestComparePix(rp, pix3, pix4); /* 26 */ + regTestComparePix(rp, pix5, pix6); /* 27 */ + pixDestroy(&pixs); + pixDestroy(&pixn); + pixDestroy(&pixg); + pixDestroy(&pixb); + pixDestroy(&pix1); + pixDestroy(&pix2); + pixDestroy(&pix3); + pixDestroy(&pix4); + pixDestroy(&pix5); + pixDestroy(&pix6); + fpixDestroy(&fpixs2); + fpixDestroy(&fpixs3); + fpixDestroy(&fpixs4); + dpixDestroy(&dpix); + dpixDestroy(&dpix2); + + /* Test affine and projective transforms on fpix */ + fpixWrite("/tmp/lept/regout/fpix1.fp", dew->fullvdispar); + fpix1 = fpixRead("/tmp/lept/regout/fpix1.fp"); + pix1 = fpixAutoRenderContours(fpix1, 40); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 28 */ + pixDisplayWithTitle(pix1, 0, 500, NULL, rp->display); + pixDestroy(&pix1); + + MakePtasAffine(1, &ptas, &ptad); + fpix2 = fpixAffinePta(fpix1, ptad, ptas, 200, 0.0); + pix2 = fpixAutoRenderContours(fpix2, 40); + regTestWritePixAndCheck(rp, pix2, IFF_PNG); /* 29 */ + pixDisplayWithTitle(pix2, 400, 500, NULL, rp->display); + fpixDestroy(&fpix2); + pixDestroy(&pix2); + ptaDestroy(&ptas); + ptaDestroy(&ptad); + + MakePtas(1, &ptas, &ptad); + fpix2 = fpixProjectivePta(fpix1, ptad, ptas, 200, 0.0); + pix3 = fpixAutoRenderContours(fpix2, 40); + regTestWritePixAndCheck(rp, pix3, IFF_PNG); /* 30 */ + pixDisplayWithTitle(pix3, 400, 500, NULL, rp->display); + fpixDestroy(&fpix1); + fpixDestroy(&fpix2); + pixDestroy(&pix3); + ptaDestroy(&ptas); + ptaDestroy(&ptad); + dewarpaDestroy(&dewa); + + kernelDestroy(&kel); + kernelDestroy(&kelx); + kernelDestroy(&kely); + return regTestCleanup(rp); +} + + +static void +MakePtas(l_int32 i, + PTA **pptas, + PTA **pptad) +{ +PTA *ptas, *ptad; + ptas = ptaCreate(4); + ptaAddPt(ptas, xs1[i], ys1[i]); + ptaAddPt(ptas, xs2[i], ys2[i]); + ptaAddPt(ptas, xs3[i], ys3[i]); + ptaAddPt(ptas, xs4[i], ys4[i]); + ptad = ptaCreate(4); + ptaAddPt(ptad, xd1[i], yd1[i]); + ptaAddPt(ptad, xd2[i], yd2[i]); + ptaAddPt(ptad, xd3[i], yd3[i]); + ptaAddPt(ptad, xd4[i], yd4[i]); + *pptas = ptas; + *pptad = ptad; + return; +} + +static void +MakePtasAffine(l_int32 i, + PTA **pptas, + PTA **pptad) +{ +PTA *ptas, *ptad; + ptas = ptaCreate(3); + ptaAddPt(ptas, xs1[i], ys1[i]); + ptaAddPt(ptas, xs2[i], ys2[i]); + ptaAddPt(ptas, xs3[i], ys3[i]); + ptad = ptaCreate(3); + ptaAddPt(ptad, xd1[i], yd1[i]); + ptaAddPt(ptad, xd2[i], yd2[i]); + ptaAddPt(ptad, xd3[i], yd3[i]); + *pptas = ptas; + *pptad = ptad; + return; +} diff --git a/leptonica/prog/fpix2_reg.c b/leptonica/prog/fpix2_reg.c new file mode 100644 index 00000000..5ceafbcb --- /dev/null +++ b/leptonica/prog/fpix2_reg.c @@ -0,0 +1,116 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * fpix2_reg.c + * + * Regression test for FPix: + * - rotation by multiples of 90 degrees + * - adding borders of various types + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + +int main(int argc, + char **argv) +{ +FPIX *fpix1, *fpix2, *fpix3, *fpix4; +PIX *pix1, *pix2, *pix3, *pix4, *pix5, *pix6, *pix7, *pix8; +L_REGPARAMS *rp; + + if (regTestSetup(argc, argv, &rp)) + return 1; + + /* Test orthogonal rotations */ + pix1 = pixRead("marge.jpg"); + pix2 = pixConvertTo8(pix1, 0); + fpix1 = pixConvertToFPix(pix2, 1); + + fpix2 = fpixRotateOrth(fpix1, 1); + pix3 = fpixConvertToPix(fpix2, 8, L_CLIP_TO_ZERO, 0); + pix4 = pixRotateOrth(pix2, 1); + regTestComparePix(rp, pix3, pix4); /* 0 */ + pixDisplayWithTitle(pix3, 100, 100, NULL, rp->display); + + fpix3 = fpixRotateOrth(fpix1, 2); + pix5 = fpixConvertToPix(fpix3, 8, L_CLIP_TO_ZERO, 0); + pix6 = pixRotateOrth(pix2, 2); + regTestComparePix(rp, pix5, pix6); /* 1 */ + pixDisplayWithTitle(pix5, 560, 100, NULL, rp->display); + + fpix4 = fpixRotateOrth(fpix1, 3); + pix7 = fpixConvertToPix(fpix4, 8, L_CLIP_TO_ZERO, 0); + pix8 = pixRotateOrth(pix2, 3); + regTestComparePix(rp, pix7, pix8); /* 2 */ + pixDisplayWithTitle(pix7, 1170, 100, NULL, rp->display); + pixDisplayWithTitle(pix2, 560, 580, NULL, rp->display); + + pixDestroy(&pix1); + pixDestroy(&pix2); + pixDestroy(&pix3); + pixDestroy(&pix4); + pixDestroy(&pix5); + pixDestroy(&pix6); + pixDestroy(&pix7); + pixDestroy(&pix8); + fpixDestroy(&fpix1); + fpixDestroy(&fpix2); + fpixDestroy(&fpix3); + fpixDestroy(&fpix4); + + /* Test adding various borders */ + pix1 = pixRead("marge.jpg"); + pix2 = pixConvertTo8(pix1, 0); + fpix1 = pixConvertToFPix(pix2, 1); + + fpix2 = fpixAddMirroredBorder(fpix1, 21, 21, 25, 25); + pix3 = fpixConvertToPix(fpix2, 8, L_CLIP_TO_ZERO, 0); + pix4 = pixAddMirroredBorder(pix2, 21, 21, 25, 25); + regTestComparePix(rp, pix3, pix4); /* 3 */ + pixDisplayWithTitle(pix3, 100, 1000, NULL, rp->display); + + fpix3 = fpixAddContinuedBorder(fpix1, 21, 21, 25, 25); + pix5 = fpixConvertToPix(fpix3, 8, L_CLIP_TO_ZERO, 0); + pix6 = pixAddContinuedBorder(pix2, 21, 21, 25, 25); + regTestComparePix(rp, pix5, pix6); /* 4 */ + pixDisplayWithTitle(pix5, 750, 1000, NULL, rp->display); + + pixDestroy(&pix1); + pixDestroy(&pix2); + pixDestroy(&pix3); + pixDestroy(&pix4); + pixDestroy(&pix5); + pixDestroy(&pix6); + fpixDestroy(&fpix1); + fpixDestroy(&fpix2); + fpixDestroy(&fpix3); + return regTestCleanup(rp); +} + diff --git a/leptonica/prog/fpixcontours.c b/leptonica/prog/fpixcontours.c new file mode 100644 index 00000000..9bac599a --- /dev/null +++ b/leptonica/prog/fpixcontours.c @@ -0,0 +1,76 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * fpixcontours.c + * + * Generates and displays an fpix as a set of contours + * + * Syntax: fpixcontours filein [ncontours] + * Default for ncontours is 40. + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include <string.h> +#include "allheaders.h" + +static const char *fileout = "/tmp/lept/fpix/fpixcontours.png"; + +int main(int argc, + char **argv) +{ +char *filein; +l_int32 ncontours; +FPIX *fpix; +PIX *pix; +static char mainName[] = "fpixcontours"; + + if (argc != 2 && argc != 3) { + lept_stderr("Syntax: fpixcontours filein [ncontours]\n"); + return 1; + } + filein = argv[1]; + if (argc == 2) + ncontours = 40; + else /* argc == 3 */ + ncontours = atoi(argv[2]); + + setLeptDebugOK(1); + lept_mkdir("lept/fpix"); + + if ((fpix = fpixRead(filein)) == NULL) + return ERROR_INT(mainName, "fpix not read", 1); + pix = fpixAutoRenderContours(fpix, ncontours); + pixWrite(fileout, pix, IFF_PNG); + pixDisplay(pix, 100, 100); + + pixDestroy(&pix); + fpixDestroy(&fpix); + return 0; +} diff --git a/leptonica/prog/fuzzing/README.md b/leptonica/prog/fuzzing/README.md new file mode 100644 index 00000000..4dcddee8 --- /dev/null +++ b/leptonica/prog/fuzzing/README.md @@ -0,0 +1,25 @@ +# Leptonica fuzzing + +This directory contains fuzzing tests for Leptonica. +Each test is in a separate source file *_fuzzer.cc. + +Normally these fuzzing tests are run by [OSS-Fuzz](https://oss-fuzz.com/), +but can also be run locally. + +## Local build instructions + +Local builds require the clang compiler. +The example was tested with clang-6.0 on Debian GNU Linux. + + ./configure CC=clang-6.0 CXX=clang++-6.0 + make fuzzers CXX=clang++-6.0 + +## Running local fuzzers + +Each local fuzzer can be run like in the following example. + + # Show command line syntax. + ./barcode_fuzzer -help=1 + + # Run the fuzzer. + ./barcode_fuzzer diff --git a/leptonica/prog/fuzzing/adaptmap_fuzzer.cc b/leptonica/prog/fuzzing/adaptmap_fuzzer.cc new file mode 100644 index 00000000..29df2e5b --- /dev/null +++ b/leptonica/prog/fuzzing/adaptmap_fuzzer.cc @@ -0,0 +1,75 @@ +#include "leptfuzz.h" + +extern "C" int +LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { + if(size<3) return 0; + + leptSetStdNullHandler(); + + PIX *pixs_payload = pixReadMemSpix(data, size); + if(pixs_payload == NULL) return 0; + + PIX *pix1, *pix2, *pix3, *pix4, *pix5, *return_pix1, *payload_copy; + + pix1 = pixRead("../test8.jpg"); + payload_copy = pixCopy(NULL, pixs_payload); + pixBackgroundNormGrayArray(payload_copy, pix1, 10, 10, 10, 10, 256, 10, 10, &pix2); + pixDestroy(&pix1); + pixDestroy(&pix2); + pixDestroy(&payload_copy); + + pix1 = pixRead("../test8.jpg"); + payload_copy = pixCopy(NULL, pixs_payload); + pixBackgroundNormGrayArrayMorph(payload_copy, pix1, 6, 5, 256, &pix2); + pixDestroy(&pix1); + pixDestroy(&pix2); + pixDestroy(&payload_copy); + + pix1 = pixRead("../test8.jpg"); + payload_copy = pixCopy(NULL, pixs_payload); + return_pix1 = pixBackgroundNormMorph(payload_copy, pix1, 6, 5, 256); + pixDestroy(&pix1); + pixDestroy(&payload_copy); + pixDestroy(&return_pix1); + + pix1 = pixRead("../test8.jpg"); + pix2 = pixRead("../test8.jpg"); + payload_copy = pixCopy(NULL, pixs_payload); + pixBackgroundNormRGBArrays(payload_copy, pix1, pix2, 10, 10, 10, 10, 130, 10, 10, &pix3, &pix4, &pix5); + pixDestroy(&pix1); + pixDestroy(&pix2); + pixDestroy(&pix3); + pixDestroy(&pix4); + pixDestroy(&pix5); + pixDestroy(&payload_copy); + + pix1 = pixRead("../test8.jpg"); + payload_copy = pixCopy(NULL, pixs_payload); + pixBackgroundNormRGBArraysMorph(payload_copy, pix1, 6, 33, 130, &pix2, &pix3, &pix4); + pixDestroy(&pix1); + pixDestroy(&pix2); + pixDestroy(&pix3); + pixDestroy(&pix4); + pixDestroy(&payload_copy); + + payload_copy = pixCopy(NULL, pixs_payload); + pixContrastNorm(payload_copy, payload_copy, 10, 10, 3, 0, 0); + pixDestroy(&payload_copy); + + pix1 = pixRead("../test8.jpg"); + payload_copy = pixCopy(NULL, pixs_payload); + return_pix1 = pixGlobalNormNoSatRGB(payload_copy, pix1, 3, 3, 3, 2, 0.9); + pixDestroy(&pix1); + pixDestroy(&payload_copy); + pixDestroy(&return_pix1); + + payload_copy = pixCopy(NULL, pixs_payload); + pixThresholdSpreadNorm(payload_copy, L_SOBEL_EDGE, 10, 0, 0, 0.7, -25, 255, 10, &pix1, &pix2, &pix3); + pixDestroy(&pix1); + pixDestroy(&pix2); + pixDestroy(&pix3); + pixDestroy(&payload_copy); + + pixDestroy(&pixs_payload); + return 0; +} diff --git a/leptonica/prog/fuzzing/affine_fuzzer.cc b/leptonica/prog/fuzzing/affine_fuzzer.cc new file mode 100644 index 00000000..ab57c3e1 --- /dev/null +++ b/leptonica/prog/fuzzing/affine_fuzzer.cc @@ -0,0 +1,40 @@ +#include "leptfuzz.h" + +extern "C" int +LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { + if(size<3) return 0; + + leptSetStdNullHandler(); + + PIX *pixs_payload = pixReadMemSpix(data, size); + if(pixs_payload == NULL) return 0; + + PIX *pix1, *return_pix1; + PTA *ptas, *ptad; + + ptas = ptaCreate(0); + ptad = ptaCreate(0); + return_pix1 = pixAffinePta(pixs_payload, ptad, ptas, L_BRING_IN_WHITE); + ptaDestroy(&ptas); + ptaDestroy(&ptad); + pixDestroy(&return_pix1); + + pix1 = pixRead("../test8.jpg"); + ptas = ptaCreate(0); + ptad = ptaCreate(0); + return_pix1 = pixAffinePtaWithAlpha(pixs_payload, ptad, ptas, pix1, 0.9, 1); + pixDestroy(&pix1); + ptaDestroy(&ptas); + ptaDestroy(&ptad); + pixDestroy(&return_pix1); + + ptas = ptaCreate(0); + ptad = ptaCreate(0); + return_pix1 = pixAffineSequential(pixs_payload, ptad, ptas, 3, 3); + ptaDestroy(&ptas); + ptaDestroy(&ptad); + pixDestroy(&return_pix1); + + pixDestroy(&pixs_payload); + return 0; +} diff --git a/leptonica/prog/fuzzing/barcode_fuzzer.cc b/leptonica/prog/fuzzing/barcode_fuzzer.cc new file mode 100644 index 00000000..d4dc01ec --- /dev/null +++ b/leptonica/prog/fuzzing/barcode_fuzzer.cc @@ -0,0 +1,22 @@ +#include "leptfuzz.h" +#include "readbarcode.h" + +extern "C" int +LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + if(size<3) return 0; + PIX *pixs; + SARRAY *saw1, *sad1; + + leptSetStdNullHandler(); + + pixs = pixReadMemSpix(data, size); + if(pixs == NULL) return 0; + + sad1 = pixProcessBarcodes(pixs, L_BF_ANY, L_USE_WIDTHS, &saw1, 1); + + pixDestroy(&pixs); + sarrayDestroy(&saw1); + sarrayDestroy(&sad1); + return 0; +} diff --git a/leptonica/prog/fuzzing/barcode_fuzzer_seed_corpus.zip b/leptonica/prog/fuzzing/barcode_fuzzer_seed_corpus.zip Binary files differnew file mode 100644 index 00000000..81199be2 --- /dev/null +++ b/leptonica/prog/fuzzing/barcode_fuzzer_seed_corpus.zip diff --git a/leptonica/prog/fuzzing/baseline_fuzzer.cc b/leptonica/prog/fuzzing/baseline_fuzzer.cc new file mode 100644 index 00000000..429f8bff --- /dev/null +++ b/leptonica/prog/fuzzing/baseline_fuzzer.cc @@ -0,0 +1,24 @@ +#include "leptfuzz.h" + +extern "C" int +LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { + if(size<3) return 0; + + leptSetStdNullHandler(); + + PIX *pixs_payload = pixReadMemSpix(data, size); + if(pixs_payload == NULL) return 0; + + PIX *pix1 = pixDeskewLocal(pixs_payload, 10, 0, 0, 0.0, 0.0, 0.0); + pixDestroy(&pix1); + + PTA *pta; + PIXA *pixadb = pixaCreate(6); + NUMA *na = pixFindBaselines(pixs_payload, &pta, pixadb); + numaDestroy(&na); + ptaDestroy(&pta); + pixaDestroy(&pixadb); + + pixDestroy(&pixs_payload); + return 0; +} diff --git a/leptonica/prog/fuzzing/bilateral_fuzzer.cc b/leptonica/prog/fuzzing/bilateral_fuzzer.cc new file mode 100644 index 00000000..66d535b0 --- /dev/null +++ b/leptonica/prog/fuzzing/bilateral_fuzzer.cc @@ -0,0 +1,25 @@ +#include "leptfuzz.h" + +extern "C" int +LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { + if(size<3) return 0; + + leptSetStdNullHandler(); + + PIX *pixs_payload = pixReadMemSpix(data, size); + if(pixs_payload == NULL) return 0; + PIX *return_pix1, *pix_copy; + + pix_copy = pixCopy(NULL, pixs_payload); + return_pix1 = pixBilateral(pix_copy, 5.0, 10.0, 10, 1); + pixDestroy(&pix_copy); + pixDestroy(&return_pix1); + + pix_copy = pixCopy(NULL, pixs_payload); + return_pix1 = pixBlockBilateralExact(pixs_payload, 10.0, 1.0); + pixDestroy(&pix_copy); + pixDestroy(&return_pix1); + + pixDestroy(&pixs_payload); + return 0; +} diff --git a/leptonica/prog/fuzzing/bilinear_fuzzer.cc b/leptonica/prog/fuzzing/bilinear_fuzzer.cc new file mode 100644 index 00000000..f4fc4269 --- /dev/null +++ b/leptonica/prog/fuzzing/bilinear_fuzzer.cc @@ -0,0 +1,37 @@ +#include "leptfuzz.h" + +extern "C" int +LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { + if(size<3) return 0; + + leptSetStdNullHandler(); + + PIX *pixs_payload = pixReadMemSpix(data, size); + if(pixs_payload == NULL) return 0; + + PIX *pix1, *return_pix1, *pix_copy; + PTA *ptas, *ptad; + + ptas = ptaCreate(0); + ptad = ptaCreate(0); + pix_copy = pixCopy(NULL, pixs_payload); + return_pix1 = pixBilinearPta(pix_copy, ptad, ptas, L_BRING_IN_WHITE); + pixDestroy(&pix_copy); + pixDestroy(&return_pix1); + ptaDestroy(&ptas); + ptaDestroy(&ptad); + + pix1 = pixRead("../test8.jpg"); + ptas = ptaCreate(0); + ptad = ptaCreate(0); + pix_copy = pixCopy(NULL, pixs_payload); + return_pix1 = pixBilinearPtaWithAlpha(pix_copy, ptad, ptas, pix1, 0.5, 2); + pixDestroy(&pix_copy); + pixDestroy(&pix1); + pixDestroy(&return_pix1); + ptaDestroy(&ptas); + ptaDestroy(&ptad); + + pixDestroy(&pixs_payload); + return 0; +} diff --git a/leptonica/prog/fuzzing/binarize_fuzzer.cc b/leptonica/prog/fuzzing/binarize_fuzzer.cc new file mode 100644 index 00000000..50d5b04e --- /dev/null +++ b/leptonica/prog/fuzzing/binarize_fuzzer.cc @@ -0,0 +1,55 @@ +#include "leptfuzz.h" + +extern "C" int +LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { + if(size<3) return 0; + + leptSetStdNullHandler(); + + PIX *pixs_payload = pixReadMemSpix(data, size); + if(pixs_payload == NULL) return 0; + + PIX *pix1, *pix2, *return_pix, *pix_copy1; + l_int32 l_i; + + pix1 = pixRead("../test8.jpg"); + pix_copy1 = pixCopy(NULL, pixs_payload); + return_pix = pixMaskedThreshOnBackgroundNorm(pix_copy1, pix1, + 100, 100, 10, 10, + 10, 10, 0.1, &l_i); + pixDestroy(&pix1); + pixDestroy(&pix_copy1); + pixDestroy(&return_pix); + + pix1 = pixRead("../test8.jpg"); + pix_copy1 = pixCopy(NULL, pixs_payload); + return_pix = pixOtsuThreshOnBackgroundNorm(pix_copy1, pix1, + 100, 100, 10, 10, + 130, 30, 30, 0.1, + &l_i); + pixDestroy(&pix1); + pixDestroy(&pix_copy1); + pixDestroy(&return_pix); + + pix_copy1 = pixCopy(NULL, pixs_payload); + pixSauvolaBinarizeTiled(pix_copy1, 8, 0.34, 1, 1, NULL, &pix1); + pixDestroy(&pix1); + pixDestroy(&pix_copy1); + + pix1 = pixRead("../test8.jpg"); + pix_copy1 = pixCopy(NULL, pixs_payload); + pixThresholdByConnComp(pix_copy1, pix1, 10, 10, 10, 5.5, 5.5, + &l_i, &pix2, 1); + pixDestroy(&pix1); + pixDestroy(&pix2); + pixDestroy(&pix_copy1); + + pix_copy1 = pixCopy(NULL, pixs_payload); + pixThresholdByHisto(pix_copy1, 2, 0, 0, &l_i, &pix1, &pix2); + pixDestroy(&pix1); + pixDestroy(&pix2); + pixDestroy(&pix_copy1); + + pixDestroy(&pixs_payload); + return 0; +} diff --git a/leptonica/prog/fuzzing/blend_fuzzer.cc b/leptonica/prog/fuzzing/blend_fuzzer.cc new file mode 100644 index 00000000..17b1af7d --- /dev/null +++ b/leptonica/prog/fuzzing/blend_fuzzer.cc @@ -0,0 +1,93 @@ +#include "leptfuzz.h" + +extern "C" int +LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { + if(size<3) return 0; + + leptSetStdNullHandler(); + + PIX *pixs_payload = pixReadMemSpix(data, size); + if(pixs_payload == NULL) return 0; + + PIX *pix1, *pix2, *return_pix, *pix_copy; + + for(int i=0; i<10; i++) { + pix1 = pixRead("../test8.jpg"); + pix_copy = pixCopy(NULL, pixs_payload); + return_pix = pixBlend(pix_copy, pix1, i, i, i); + pixDestroy(&pix_copy); + pixDestroy(&pix1); + pixDestroy(&return_pix); + + pix_copy = pixCopy(NULL, pixs_payload); + return_pix = pixBlend(pix_copy, pix_copy, i, i, i); + pixDestroy(&pix_copy); + pixDestroy(&return_pix); + } + + pix_copy = pixCopy(NULL, pixs_payload); + return_pix = pixAddAlphaToBlend(pix_copy, 1.2, 1); + pixDestroy(&pix_copy); + pixDestroy(&return_pix); + + pix1 = pixRead("../test8.jpg"); + BOX *box1 = boxCreate(150, 130, 1500, 355); + pix_copy = pixCopy(NULL, pixs_payload); + pixBlendBackgroundToColor(pix_copy, pix1, box1, 123, 1.0, 5, 12); + pixDestroy(&pix1); + boxDestroy(&box1); + pixDestroy(&pix_copy); + + pix1 = pixRead("../test8.jpg"); + pix_copy = pixCopy(NULL, pixs_payload); + pixBlendCmap(pix_copy, pix1, 2, 3, 4); + pixDestroy(&pix1); + pixDestroy(&pix_copy); + + pix1 = pixRead("../test8.jpg"); + pix_copy = pixCopy(NULL, pixs_payload); + pixBlendColorByChannel(pix_copy, pix_copy, pix1, 200, 200, 0.7, 0.8, 0.9, 1, 5); + pixDestroy(&pix1); + pixDestroy(&pix_copy); + + pix1 = pixRead("../test8.jpg"); + pix_copy = pixCopy(NULL, pixs_payload); + pixBlendGrayAdapt(pix_copy, pix_copy, pix1, 2, 3, 0.8, 1); + pixDestroy(&pix1); + pixDestroy(&pix_copy); + + pix1 = pixRead("../test8.jpg"); + pix_copy = pixCopy(NULL, pixs_payload); + pixBlendGrayInverse(pix_copy, pix_copy, pix1, 1, 2, 0.7); + pixDestroy(&pix1); + pixDestroy(&pix_copy); + + pix1 = pixRead("../test8.jpg"); + pix_copy = pixCopy(NULL, pixs_payload); + pixBlendHardLight(pix_copy, pix_copy, pix1, 1, 2, 0.8); + pixDestroy(&pix1); + pixDestroy(&pix_copy); + + pix1 = pixRead("../test8.jpg"); + pix_copy = pixCopy(NULL, pixs_payload); + return_pix = pixFadeWithGray(pix_copy, pix1, 1.0, L_BLEND_TO_WHITE); + pixDestroy(&pix1); + pixDestroy(&pix_copy); + pixDestroy(&return_pix); + + pix_copy = pixCopy(NULL, pixs_payload); + pixLinearEdgeFade(pix_copy, L_FROM_LEFT, L_BLEND_TO_WHITE, 1.0, 0.8); + pixDestroy(&pix_copy); + + pix_copy = pixCopy(NULL, pixs_payload); + pixMultiplyByColor(pix_copy, pix_copy, NULL, 2); + pixDestroy(&pix_copy); + + pix_copy = pixCopy(NULL, pixs_payload); + return_pix = pixSetAlphaOverWhite(pix_copy); + pixDestroy(&pix_copy); + pixDestroy(&return_pix); + + pixDestroy(&pixs_payload); + return 0; +} diff --git a/leptonica/prog/fuzzing/boxfunc3_fuzzer.cc b/leptonica/prog/fuzzing/boxfunc3_fuzzer.cc new file mode 100644 index 00000000..c43a2de0 --- /dev/null +++ b/leptonica/prog/fuzzing/boxfunc3_fuzzer.cc @@ -0,0 +1,107 @@ +#include "leptfuzz.h" + +extern "C" int +LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { + if(size<3) return 0; + + leptSetStdNullHandler(); + + BOXA *boxa_payload, *boxa1; + boxa_payload = boxaReadMem(data, size); + if(boxa_payload == NULL) return 0; + + PIX *pixc, *pixd, *pix, *pixs; + PIX *pix1, *pix2, *pix3, *pix4, *pix5, *pix6, *pix7; + BOXAA *baa; + static const l_int32 WIDTH = 800; + + //boxaaDisplay() + pix1 = pixRead("../test8.jpg"); + if(pix1!=NULL) { + baa = boxaSort2d(boxa_payload, NULL, 6, 6, 5); + pix2 = boxaaDisplay(pix1, baa, 3, 1, 0xff000000, + 0x00ff0000, 0, 0); + boxaaDestroy(&baa); + pixDestroy(&pix1); + pixDestroy(&pix2); + } + + //pixBlendBoxaRandom(); + pixc = pixRead("../test8.jpg"); + if(pixc!=NULL) { + pixd = pixBlendBoxaRandom(pixc, boxa_payload, 0.4); + pixDestroy(&pixc); + pixDestroy(&pixd); + } + + //pixDrawBoxa(); + pixc = pixRead("../test8.jpg"); + if(pixc!=NULL) { + pixd = pixConvertTo1(pixc, 128); + pix1 = pixConvertTo8(pixd, FALSE); + pix2 = pixDrawBoxa(pix1, boxa_payload, 7, 0x40a0c000); + pixDestroy(&pix1); + pixDestroy(&pix2); + pixDestroy(&pixc); + pixDestroy(&pixd); + } + + //pixMaskConnComp(); + pix1 = pixRead("../test8.jpg"); + if(pix1!=NULL) { + boxa1 = boxaReadMem(data, size); + if(boxa1==NULL) { + pixDestroy(&pix1); + }else{ + pix2 = pixScaleToSize(pix1, WIDTH, 0); + pix3 = pixConvertTo1(pix2, 100); + pix4 = pixExpandBinaryPower2(pix3, 2); + pix5 = pixGenerateHalftoneMask(pix4, NULL, NULL, NULL); + pix6 = pixMorphSequence(pix5, "c20.1 + c1.20", 0); + pix7 = pixMaskConnComp(pix6, 8, &boxa1); + boxaDestroy(&boxa1); + pixDestroy(&pix1); + pixDestroy(&pix2); + pixDestroy(&pix3); + pixDestroy(&pix4); + pixDestroy(&pix5); + pixDestroy(&pix6); + pixDestroy(&pix7); + } + } + + //pixPaintBoxa(); + pix = pixRead("../test8.jpg"); + if(pix!=NULL) { + boxa1 = boxaReadMem(data, size); + if(boxa1==NULL) { + pixDestroy(&pix); + }else{ + pix1 = pixPaintBoxa(pix, boxa1, 0x60e0a000); + pixDestroy(&pix); + pixDestroy(&pix1); + boxaDestroy(&boxa1); + }; + + } + + + //pixPaintBoxaRandom(); + pix = pixRead("../test8.jpg"); + if(pix!=NULL) { + boxa1 = boxaReadMem(data, size); + if(boxa1==NULL) { + pixDestroy(&pix); + }else{ + pixs = pixConvertTo1(pix, 128); + pix1 = pixPaintBoxaRandom(pixs, boxa1); + pixDestroy(&pix); + pixDestroy(&pixs); + pixDestroy(&pix1); + boxaDestroy(&boxa1); + } + } + + boxaDestroy(&boxa_payload); + return 0; +} diff --git a/leptonica/prog/fuzzing/boxfunc4_fuzzer.cc b/leptonica/prog/fuzzing/boxfunc4_fuzzer.cc new file mode 100644 index 00000000..796ad93d --- /dev/null +++ b/leptonica/prog/fuzzing/boxfunc4_fuzzer.cc @@ -0,0 +1,39 @@ +#include "leptfuzz.h" + +extern "C" int +LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { + if(size<3) return 0; + + leptSetStdNullHandler(); + + BOXA *boxa_payload, *boxa1; + boxa_payload = boxaReadMem(data, size); + if(boxa_payload == NULL) return 0; + + PIX *pix1; + l_float32 fract; + l_int32 minx, miny, maxx, maxy, changed; + + pix1 = boxaDisplayTiled(boxa_payload, NULL, 0, -1, 1500, + 2, 1.0, 0, 3, 2); + pixDestroy(&pix1); + + boxaGetCoverage(boxa_payload, 0, 0, 0, &fract); + + boxaLocationRange(boxa_payload, &minx, &miny, &maxx, &maxy); + + boxa1 = boxaPermutePseudorandom(boxa_payload); + boxaDestroy(&boxa1); + + boxaPermuteRandom(boxa_payload, boxa_payload); + + boxa1 = boxaSelectByWHRatio(boxa_payload, 1, + L_SELECT_IF_LT, &changed); + boxaDestroy(&boxa1); + + boxa1 = boxaSelectRange(boxa_payload, 0, -1, L_COPY); + boxaDestroy(&boxa1); + + boxaDestroy(&boxa_payload); + return 0; +} diff --git a/leptonica/prog/fuzzing/boxfunc5_fuzzer.cc b/leptonica/prog/fuzzing/boxfunc5_fuzzer.cc new file mode 100644 index 00000000..e85f306d --- /dev/null +++ b/leptonica/prog/fuzzing/boxfunc5_fuzzer.cc @@ -0,0 +1,51 @@ +#include "leptfuzz.h" + +extern "C" int +LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { + if(size<3) return 0; + + leptSetStdNullHandler(); + + BOXA *boxa_payload, *boxa1; + boxa_payload = boxaReadMem(data, size); + if(boxa_payload == NULL) return 0; + + l_float32 fvarp, fvarm, devw, devh; + l_float32 del_evenodd, rms_even, rms_odd, rms_all; + l_int32 isame; + + boxa1 = boxaConstrainSize(boxa_payload, 0, + L_ADJUST_LEFT_AND_RIGHT, + 0, L_ADJUST_TOP_AND_BOT); + boxaDestroy(&boxa1); + + boxa1 = boxaReconcileAllByMedian(boxa_payload, + L_ADJUST_LEFT_AND_RIGHT, + L_ADJUST_TOP_AND_BOT, 50, + 0, NULL); + boxaDestroy(&boxa1); + + boxa1 = boxaReconcileEvenOddHeight(boxa_payload, L_ADJUST_TOP, 80, + L_ADJUST_CHOOSE_MIN, 1.05, 1); + boxaDestroy(&boxa1); + + boxa1 = boxaReconcilePairWidth(boxa_payload, 2, + L_ADJUST_CHOOSE_MIN, + 0.5, NULL); + boxaDestroy(&boxa1); + + boxaSizeConsistency1(boxa_payload, L_CHECK_HEIGHT, + 0.0, 0.0, &fvarp, &fvarm, &isame); + + boxaSizeConsistency2(boxa_payload, &devw, &devh, 0); + + boxaSizeVariation(boxa_payload, L_SELECT_WIDTH, &del_evenodd, + &rms_even, &rms_odd, &rms_all); + + boxa1 = boxaSmoothSequenceMedian(boxa_payload, 10, + L_SUB_ON_LOC_DIFF, + 80, 20, 1); + boxaDestroy(&boxa1); + boxaDestroy(&boxa_payload); + return 0; +} diff --git a/leptonica/prog/fuzzing/boxfunc_fuzzer.cc b/leptonica/prog/fuzzing/boxfunc_fuzzer.cc new file mode 100644 index 00000000..7c3d1c11 --- /dev/null +++ b/leptonica/prog/fuzzing/boxfunc_fuzzer.cc @@ -0,0 +1,23 @@ +#include "leptfuzz.h" + +extern "C" int +LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + + if(size<3) return 0; + + leptSetStdNullHandler(); + BOXA *boxa1, *boxa2; + boxa1 = boxaReadMem(data, size); + if(boxa1==NULL) return 0; + + boxa2 = boxaReconcileAllByMedian(boxa1, L_ADJUST_LEFT_AND_RIGHT, + L_ADJUST_TOP_AND_BOT, 50, 0, NULL); + if(boxa2!=NULL) boxaDestroy(&boxa2); + + boxa2 = boxaReconcileAllByMedian(boxa1, L_ADJUST_SKIP, + L_ADJUST_TOP_AND_BOT, 50, 0, NULL); + if(boxa2!=NULL) boxaDestroy(&boxa2); + boxaDestroy(&boxa1); + return 0; +} diff --git a/leptonica/prog/fuzzing/ccbord_fuzzer.cc b/leptonica/prog/fuzzing/ccbord_fuzzer.cc new file mode 100644 index 00000000..f1b0e19a --- /dev/null +++ b/leptonica/prog/fuzzing/ccbord_fuzzer.cc @@ -0,0 +1,27 @@ +#include "leptfuzz.h" + +extern "C" int +LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + + if(size<3) return 0; + + leptSetStdNullHandler(); + + PIX *pixs, *pixc; + CCBORDA *ccba; + + pixs = pixReadMemSpix(data, size); + if(pixs==NULL) return 0; + + ccba = pixGetAllCCBorders(pixs); + + ccbaStepChainsToPixCoords(ccba, CCB_GLOBAL_COORDS); + ccbaGenerateSPGlobalLocs(ccba, CCB_SAVE_TURNING_PTS); + pixc = ccbaDisplayImage2(ccba); + + pixDestroy(&pixs); + pixDestroy(&pixc); + ccbaDestroy(&ccba); + return 0; +} diff --git a/leptonica/prog/fuzzing/ccthin_fuzzer.cc b/leptonica/prog/fuzzing/ccthin_fuzzer.cc new file mode 100644 index 00000000..08eb7e0a --- /dev/null +++ b/leptonica/prog/fuzzing/ccthin_fuzzer.cc @@ -0,0 +1,28 @@ +#include "leptfuzz.h" + +extern "C" int +LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + PIXA *pixa, *return_pixa; + PIX *pixs; + + leptSetStdNullHandler(); + pixs = pixReadMemSpix(data, size); + if(pixs==NULL) return 0; + + for(int i=0; i<10; i++) { + pixa = pixaReadMem(data, size); + return_pixa = pixaThinConnected(pixa, L_THIN_FG, i, i); + pixaDestroy(&pixa); + pixaDestroy(&return_pixa); + + pixa = pixaReadMem(data, size); + return_pixa = pixaThinConnected(pixa, L_THIN_BG, i, i); + pixaDestroy(&pixa); + pixaDestroy(&return_pixa); + } + + pixaDestroy(&return_pixa); + pixDestroy(&pixs); + return 0; +}
\ No newline at end of file diff --git a/leptonica/prog/fuzzing/checkerboard_fuzzer.cc b/leptonica/prog/fuzzing/checkerboard_fuzzer.cc new file mode 100644 index 00000000..468363af --- /dev/null +++ b/leptonica/prog/fuzzing/checkerboard_fuzzer.cc @@ -0,0 +1,25 @@ +#include "leptfuzz.h" + +extern "C" int +LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { + if(size<3) return 0; + + leptSetStdNullHandler(); + + PIX *pixs_payload = pixReadMemSpix(data, size); + if(pixs_payload == NULL) return 0; + PIX *pix1, *pix_copy; + PIXA *pixa1; + PTA *pta1; + + pixa1 = pixaCreate(0); + pix_copy = pixCopy(NULL, pixs_payload); + pixFindCheckerboardCorners(pix_copy, 15, 3, 2, &pix1, &pta1, pixa1); + pixDestroy(&pix_copy); + pixaDestroy(&pixa1); + ptaDestroy(&pta1); + pixDestroy(&pix1); + + pixDestroy(&pixs_payload); + return 0; +} diff --git a/leptonica/prog/fuzzing/classapp_fuzzer.cc b/leptonica/prog/fuzzing/classapp_fuzzer.cc new file mode 100644 index 00000000..61e8dc3e --- /dev/null +++ b/leptonica/prog/fuzzing/classapp_fuzzer.cc @@ -0,0 +1,24 @@ +#include "leptfuzz.h" + +extern "C" int +LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { + if(size<3) return 0; + + leptSetStdNullHandler(); + + PIX *pixs_payload = pixReadMemSpix(data, size); + if(pixs_payload == NULL) return 0; + + BOX *box1 = boxCreate(150, 130, 1500, 355); + BOXA *boxa1; + BOXAA *boxaa1; + PIX *pix_copy = pixCopy(NULL, pixs_payload); + pixFindWordAndCharacterBoxes(pix_copy, box1, 120, &boxa1, &boxaa1, NULL); + boxDestroy(&box1); + boxaDestroy(&boxa1); + boxaaDestroy(&boxaa1); + pixDestroy(&pix_copy); + + pixDestroy(&pixs_payload); + return 0; +} diff --git a/leptonica/prog/fuzzing/colorfill_fuzzer.cc b/leptonica/prog/fuzzing/colorfill_fuzzer.cc new file mode 100644 index 00000000..9218e5ca --- /dev/null +++ b/leptonica/prog/fuzzing/colorfill_fuzzer.cc @@ -0,0 +1,17 @@ +#include "leptfuzz.h" + +extern "C" int +LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { + if(size<3) return 0; + + leptSetStdNullHandler(); + + PIX *pixs_payload = pixReadMemSpix(data, size); + if(pixs_payload == NULL) return 0; + + L_COLORFILL *cf = l_colorfillCreate(pixs_payload, 1, 1); + l_colorfillDestroy(&cf); + + pixDestroy(&pixs_payload); + return 0; +} diff --git a/leptonica/prog/fuzzing/colorquant_fuzzer.cc b/leptonica/prog/fuzzing/colorquant_fuzzer.cc new file mode 100644 index 00000000..410ffa56 --- /dev/null +++ b/leptonica/prog/fuzzing/colorquant_fuzzer.cc @@ -0,0 +1,83 @@ +#include "leptfuzz.h" + +extern "C" int +LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + BOX *box; + PIX *pixs; + PIX *pix1, *pix2, *pix3, *pix4; + PIX *pix5, *pix52, *pix53, *pix54; + PIX *pix6, *pix7, *pix8, *pix9; + PIX *pix10, *pix11, *pix12; + PIX *return_pix; + PIXCMAP *cmap; + + leptSetStdNullHandler(); + pixs = pixReadMemSpix(data, size); + if(pixs==NULL) return 0; + + pix1 = pixThresholdTo4bpp(pixs, 6, 1); + box = boxCreate(120, 30, 200, 200); + pixColorGray(pix1, box, L_PAINT_DARK, 220, 0, 0, 255); + boxDestroy(&box); + + pix2 = pixScale(pix1, 1.5, 1.5); + cmap = pixGetColormap(pix1); + pix3 = pixOctcubeQuantFromCmap(pix2, cmap, 4, + 3, L_EUCLIDEAN_DISTANCE); + + pix4 = pixConvertTo32(pix3); + pix5 = pixMedianCutQuant(pix4, 0); + pix52 = pixMedianCutQuant(pix4, 1); + pix53 = pixMedianCutQuant(pixs, 0); + pix54 = pixMedianCutQuant(pixs, 1); + + pix6 = pixFewColorsMedianCutQuantMixed(pix4, 30, 30, 100, 0, 0, 0); + + pix7 = pixDeskew(pixs, 0); + pixWriteImpliedFormat("/tmp/fuzzfile1", pix7, 0, 0); + + pix8 = pixOctreeQuantByPopulation(pixs, 0, 0); + pix9 = pixFewColorsOctcubeQuantMixed(pix4, 3, 20, 244, 20, 0.05, 15); + pix10 = pixColorSegment(pixs, 50, 6, 6, 6, 0); + + for(int i=128; i<257; i++){ + pix11 = pixOctreeColorQuant(pixs, i, 0); + pixDestroy(&pix11); + pix11 = pixOctreeColorQuant(pixs, i, 1); + pixDestroy(&pix11); + } + + pix12 = pixFixedOctcubeQuant256(pixs, 0); + pixDestroy(&pix12); + pix12 = pixFixedOctcubeQuant256(pixs, 1); + pixDestroy(&pix12); + + for(int i1=0; i1<10; i1++){ + for(int i2=0; i2<10; i2++){ + return_pix = pixQuantFromCmap(pixs, pixGetColormap(pixs), + i1, i2, L_MANHATTAN_DISTANCE); + pixDestroy(&return_pix); + + return_pix = pixQuantFromCmap(pixs, pixGetColormap(pixs), + i1, i2, L_EUCLIDEAN_DISTANCE); + pixDestroy(&return_pix); + } + } + + pixDestroy(&pix1); + pixDestroy(&pix2); + pixDestroy(&pix3); + pixDestroy(&pix4); + pixDestroy(&pix5); + pixDestroy(&pix52); + pixDestroy(&pix53); + pixDestroy(&pix54); + pixDestroy(&pix6); + pixDestroy(&pix7); + pixDestroy(&pix8); + pixDestroy(&pix9); + pixDestroy(&pix10); + pixDestroy(&pixs); + return 0; +} diff --git a/leptonica/prog/fuzzing/compare_fuzzer.cc b/leptonica/prog/fuzzing/compare_fuzzer.cc new file mode 100644 index 00000000..acc6a99d --- /dev/null +++ b/leptonica/prog/fuzzing/compare_fuzzer.cc @@ -0,0 +1,49 @@ +#include "leptfuzz.h" + +extern "C" int +LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + if(size<3) return 0; + + leptSetStdNullHandler(); + + l_float32 fract; + l_int32 psame, comptype; + PIX *pixs1, *pixs2, *pixs3, *pixs4, *pixs5, *pixs6, *pixs7, *pixs8; + PIX *pixd1, *pixd2; + + pixs1 = pixReadMemSpix(data, size); + if(pixs1==NULL) return 0; + + pixs2 = pixCopy(NULL, pixs1); + if(pixs2==NULL) { + pixDestroy(&pixs1); + return 0; + } + + pixs3 = pixConvertTo8(pixs1, 0); + pixs4 = pixConvertTo8(pixs2, 0); + + pixGetPerceptualDiff(pixs1, pixs2, 1, 3, 20, &fract, &pixs5, &pixs6); + pixGetPerceptualDiff(pixs3, pixs4, 1, 3, 20, &fract, &pixs7, &pixs8); + + pixEqualWithAlpha(pixs1, pixs2, 1, &psame); + pixEqualWithAlpha(pixs3, pixs4, 1, &psame); + + pixd1 = NULL; + pixCompareBinary(pixs1, pixs2, L_COMPARE_XOR, &fract, &pixd1); + pixDestroy(&pixd1); + pixd2 = NULL; + pixCompareBinary(pixs1, pixs2, L_COMPARE_SUBTRACT, &fract, &pixd2); + pixDestroy(&pixd2); + + pixDestroy(&pixs1); + pixDestroy(&pixs2); + pixDestroy(&pixs3); + pixDestroy(&pixs4); + pixDestroy(&pixs5); + pixDestroy(&pixs6); + pixDestroy(&pixs7); + pixDestroy(&pixs8); + return 0; +} diff --git a/leptonica/prog/fuzzing/dewarp_fuzzer.cc b/leptonica/prog/fuzzing/dewarp_fuzzer.cc new file mode 100644 index 00000000..37098a9f --- /dev/null +++ b/leptonica/prog/fuzzing/dewarp_fuzzer.cc @@ -0,0 +1,29 @@ +#include "leptfuzz.h" + +extern "C" int +LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + if(size<3) return 0; + + PIX *pixs, *pixd; + L_DEWARPA *dewa1; + PIXAC *pixac; + SARRAY *sa; + + leptSetStdNullHandler(); + + pixs = pixReadMemSpix(data, size); + if(pixs==NULL) return 0; + + // Don't use debug, because it requires writing to /tmp + dewarpSinglePage(pixs, 0, 1, 1, 0, &pixd, NULL, 0); + + pixac = pixacompReadMem(data, size); + dewa1 = dewarpaCreateFromPixacomp(pixac, 1, 0, 10, -1); + + dewarpaDestroy(&dewa1); + pixacompDestroy(&pixac); + pixDestroy(&pixs); + pixDestroy(&pixd); + return 0; +} diff --git a/leptonica/prog/fuzzing/edge_fuzzer.cc b/leptonica/prog/fuzzing/edge_fuzzer.cc new file mode 100644 index 00000000..4e4c0944 --- /dev/null +++ b/leptonica/prog/fuzzing/edge_fuzzer.cc @@ -0,0 +1,18 @@ +#include "leptfuzz.h" + +extern "C" int +LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { + if(size<3) return 0; + + leptSetStdNullHandler(); + + PIX *pixs_payload = pixReadMemSpix(data, size); + if(pixs_payload == NULL) return 0; + + l_float32 l_f1; + l_float32 l_f2; + l_float32 l_f3; + pixMeasureEdgeSmoothness(pixs_payload, 1, 1, 1, &l_f1, &l_f2, &l_f3, NULL); + pixDestroy(&pixs_payload); + return 0; +} diff --git a/leptonica/prog/fuzzing/enhance_fuzzer.cc b/leptonica/prog/fuzzing/enhance_fuzzer.cc new file mode 100644 index 00000000..4fa7ce76 --- /dev/null +++ b/leptonica/prog/fuzzing/enhance_fuzzer.cc @@ -0,0 +1,101 @@ +#include "leptfuzz.h" + +extern "C" int +LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { + if (size<3) return 0; + + leptSetStdNullHandler(); + + PIX *pixs_payload = pixReadMemSpix(data, size); + if (pixs_payload == NULL) return 0; + + PIX *pix_pointer_payload, *return_pix, *pix2; + L_KERNEL *kel; + NUMA *na1, *na2, *na3; + + pix_pointer_payload = pixCopy(NULL, pixs_payload); + return_pix = pixContrastTRCMasked(NULL, pix_pointer_payload, NULL, 0.5); + pixDestroy(&pix_pointer_payload); + pixDestroy(&return_pix); + + pix_pointer_payload = pixCopy(NULL, pixs_payload); + return_pix = pixDarkenGray(NULL, pix_pointer_payload, 220, 10); + pixDestroy(&pix_pointer_payload); + pixDestroy(&return_pix); + + pix_pointer_payload = pixCopy(NULL, pixs_payload); + return_pix = pixEqualizeTRC(NULL, pix_pointer_payload, 220, 10); + pixDestroy(&pix_pointer_payload); + pixDestroy(&return_pix); + + pix_pointer_payload = pixCopy(NULL, pixs_payload); + return_pix = pixGammaTRCMasked(NULL, pix_pointer_payload, NULL, + 1.0, 100, 175); + pixDestroy(&pix_pointer_payload); + pixDestroy(&return_pix); + + pix_pointer_payload = pixCopy(NULL, pixs_payload); + return_pix = pixGammaTRCWithAlpha(NULL, pix_pointer_payload, + 0.5, 1.0, 100); + pixDestroy(&pix_pointer_payload); + pixDestroy(&return_pix); + + pix_pointer_payload = pixCopy(NULL, pixs_payload); + return_pix = pixHalfEdgeByBandpass(pix_pointer_payload, 2, 2, 4, 4); + pixDestroy(&pix_pointer_payload); + pixDestroy(&return_pix); + + l_float32 sat; + pix_pointer_payload = pixCopy(NULL, pixs_payload); + pixMeasureSaturation(pix_pointer_payload, 1, &sat); + pixDestroy(&pix_pointer_payload); + + pix_pointer_payload = pixCopy(NULL, pixs_payload); + return_pix = pixModifyBrightness(NULL, pix_pointer_payload, 0.5); + pixDestroy(&pix_pointer_payload); + pixDestroy(&return_pix); + + pix_pointer_payload = pixCopy(NULL, pixs_payload); + return_pix = pixModifyHue(NULL, pix_pointer_payload, 0.01 + 0.05 * 1); + pixDestroy(&pix_pointer_payload); + pixDestroy(&return_pix); + + pix_pointer_payload = pixCopy(NULL, pixs_payload); + return_pix = pixModifySaturation(NULL, pix_pointer_payload, + -0.9 + 0.1 * 1); + pixDestroy(&pix_pointer_payload); + pixDestroy(&return_pix); + + pix_pointer_payload = pixCopy(NULL, pixs_payload); + return_pix = pixMosaicColorShiftRGB(pix_pointer_payload, + -0.1, 0.0, 0.0, 0.0999, 1); + pixDestroy(&pix_pointer_payload); + pixDestroy(&return_pix); + + pix_pointer_payload = pixCopy(NULL, pixs_payload); + return_pix = pixMultConstantColor(pix_pointer_payload, 0.7, 0.4, 1.3); + pixDestroy(&pix_pointer_payload); + pixDestroy(&return_pix); + + kel = kernelCreate(3, 3); + pix_pointer_payload = pixCopy(NULL, pixs_payload); + return_pix = pixMultMatrixColor( pix_pointer_payload, kel); + pixDestroy(&pix_pointer_payload); + pixDestroy(&return_pix); + kernelDestroy(&kel); + + na1 = numaGammaTRC(1.0, 0, 255); + na2 = numaGammaTRC(1.0, 0, 255); + na3 = numaGammaTRC(1.0, 0, 255); + pix_pointer_payload = pixCopy(NULL, pixs_payload); + pix2 = pixMakeSymmetricMask(10, 10, 0.5, 0.5, L_USE_INNER); + pixTRCMapGeneral(pix_pointer_payload, pix2, na1, na2, na3); + numaDestroy(&na1); + numaDestroy(&na2); + numaDestroy(&na3); + pixDestroy(&pix_pointer_payload); + pixDestroy(&pix2); + + pixDestroy(&pixs_payload); + return 0; +} diff --git a/leptonica/prog/fuzzing/fhmtgen_fuzzer.cc b/leptonica/prog/fuzzing/fhmtgen_fuzzer.cc new file mode 100644 index 00000000..16cef24a --- /dev/null +++ b/leptonica/prog/fuzzing/fhmtgen_fuzzer.cc @@ -0,0 +1,33 @@ +#include "leptfuzz.h" + +extern "C" int +LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { + if(size<3) return 0; + + leptSetStdNullHandler(); + + PIX *pixs_payload = pixReadMemSpix(data, size); + if(pixs_payload == NULL) return 0; + + l_int32 i, nsels; + char *selname; + SEL *sel; + SELA *sela; + PIX *pix_pointer_payload, *return_pix; + + sela = selaAddHitMiss(NULL); + nsels = selaGetCount(sela); + pix_pointer_payload = pixCopy(NULL, pixs_payload); + + for (i = 0; i < nsels; i++) { + sel = selaGetSel(sela, i); + selname = selGetName(sel); + return_pix = pixHMTDwa_1(NULL, pix_pointer_payload, selname); + pixDestroy(&return_pix); + } + + pixDestroy(&pix_pointer_payload); + pixDestroy(&pixs_payload); + selaDestroy(&sela); + return 0; +} diff --git a/leptonica/prog/fuzzing/finditalic_fuzzer.cc b/leptonica/prog/fuzzing/finditalic_fuzzer.cc new file mode 100644 index 00000000..5a46572c --- /dev/null +++ b/leptonica/prog/fuzzing/finditalic_fuzzer.cc @@ -0,0 +1,18 @@ +#include "leptfuzz.h" + +extern "C" int +LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { + if(size<3) return 0; + + leptSetStdNullHandler(); + + PIX *pixs_payload = pixReadMemSpix(data, size); + if(pixs_payload == NULL) return 0; + + BOXA *boxa1; + pixItalicWords(pixs_payload, NULL, NULL, &boxa1, 1); + + pixDestroy(&pixs_payload); + boxaDestroy(&boxa1); + return 0; +} diff --git a/leptonica/prog/fuzzing/flipdetect_fuzzer.cc b/leptonica/prog/fuzzing/flipdetect_fuzzer.cc new file mode 100644 index 00000000..e1bafeb2 --- /dev/null +++ b/leptonica/prog/fuzzing/flipdetect_fuzzer.cc @@ -0,0 +1,31 @@ +#include "leptfuzz.h" + +extern "C" int +LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { + if(size<3) return 0; + + leptSetStdNullHandler(); + + PIX *pixs_payload = pixReadMemSpix(data, size); + if(pixs_payload == NULL) return 0; + + l_float32 minupconf, minratio, conf1, upconf1, leftconf1; + PIX *pix_pointer_payload, *return_pix; + + pix_pointer_payload = pixCopy(NULL, pixs_payload); + pixMirrorDetect(pix_pointer_payload, &conf1, 0, 1); + pixDestroy(&pix_pointer_payload); + + pix_pointer_payload = pixCopy(NULL, pixs_payload); + return_pix = pixOrientCorrect(pix_pointer_payload, minupconf, + minratio, NULL, NULL, NULL, 1); + pixDestroy(&pix_pointer_payload); + pixDestroy(&return_pix); + + pix_pointer_payload = pixCopy(NULL, pixs_payload); + pixOrientDetect(pix_pointer_payload, &upconf1, &leftconf1, 0, 0); + pixDestroy(&pix_pointer_payload); + + pixDestroy(&pixs_payload); + return 0; +} diff --git a/leptonica/prog/fuzzing/fpix2_fuzzer.cc b/leptonica/prog/fuzzing/fpix2_fuzzer.cc new file mode 100644 index 00000000..e666c589 --- /dev/null +++ b/leptonica/prog/fuzzing/fpix2_fuzzer.cc @@ -0,0 +1,111 @@ +#include "leptfuzz.h" + +//static void MakePtas(l_int32 i, PTA **pptas, PTA **pptad); + +extern "C" int +LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { + if(size<3) return 0; + + leptSetStdNullHandler(); + + PIX *tmp_pixs = pixReadMemSpix(data, size); + if(tmp_pixs == NULL) return 0; + + DPIX *dpix_payload = pixConvertToDPix(tmp_pixs, 1); + if(dpix_payload == NULL) { + pixDestroy(&tmp_pixs); + return 0; + } + + FPIX *fpix_payload = dpixConvertToFPix(dpix_payload); + if(fpix_payload == NULL) { + pixDestroy(&tmp_pixs); + dpixDestroy(&dpix_payload); + return 0; + } + + DPIX *dpix_copy1 = dpixCopy(dpix_payload); + dpixAddMultConstant(dpix_copy1, 1.0, 1.2); + dpixDestroy(&dpix_copy1); + + DPIX *dpix_copy2 = dpixCopy(dpix_payload); + FPIX *fpixs1 = dpixConvertToFPix(dpix_copy2); + fpixDestroy(&fpixs1); + dpixDestroy(&dpix_copy2); + + DPIX *dpix_copy3 = dpixCopy(dpix_payload); + PIX *pix1 = dpixConvertToPix(dpix_copy3, 8, L_CLIP_TO_ZERO, 0); + pixDestroy(&pix1); + dpixDestroy(&dpix_copy3); + + l_float64 l_f1; + l_int32 l_i1; + l_int32 l_i2; + DPIX *dpix_copy4 = dpixCopy(dpix_payload); + dpixGetMax(dpix_copy4, &l_f1, &l_i1, &l_i2); + dpixDestroy(&dpix_copy4); + + l_float64 l_f2; + l_int32 l_i3; + l_int32 l_i4; + DPIX *dpix_copy5 = dpixCopy(dpix_payload); + dpixGetMin(dpix_copy5, &l_f2, &l_i3, &l_i4); + dpixDestroy(&dpix_copy5); + + DPIX *dpix1 = dpixCreate(300, 300); + DPIX *dpix2 = dpixCreate(300, 300); + DPIX *dpix_copy6 = dpixCopy(dpix_payload); + dpixLinearCombination(dpix_copy6, dpix_copy6, dpix2, 1.1, 1.2); + dpixDestroy(&dpix1); + dpixDestroy(&dpix2); + dpixDestroy(&dpix_copy6); + + DPIX *dpix_copy7 = dpixCopy(dpix_payload); + DPIX *dpix3 = dpixScaleByInteger(dpix_copy7, 1); + dpixDestroy(&dpix3); + dpixDestroy(&dpix_copy7); + + DPIX *dpix_copy8 = dpixCopy(dpix_payload); + dpixSetAllArbitrary(dpix_copy8, 1.1); + dpixDestroy(&dpix_copy8); + + FPIX *fpix_copy1 = fpixCopy(fpix_payload); + FPIX *fpix2 = fpixAddContinuedBorder(fpix_copy1, 1, 1, 1, 1); + fpixDestroy(&fpix_copy1); + fpixDestroy(&fpix2); + + PTA *pta1 = ptaCreate(0); + PTA *pta2 = ptaCreate(0); + FPIX *fpix_copy92 = fpixCopy(fpix_payload); + FPIX *fpix3 = fpixAffinePta(fpix_copy92, pta1, pta2, 1, 0); + fpixDestroy(&fpix3); + fpixDestroy(&fpix_copy92); + ptaDestroy(&pta1); + ptaDestroy(&pta2); + + FPIX *fpix_copy2 = fpixCopy(fpix_payload); + DPIX *dpix_return1 = fpixConvertToDPix(fpix_copy2); + fpixDestroy(&fpix_copy2); + dpixDestroy(&dpix_return1); + + FPIX *fpix5 = fpixCreate(300, 300); + FPIX *fpix_copy3 = fpixCopy(fpix_payload); + fpixLinearCombination(fpix_copy3, fpix_copy3, fpix5, 1.1, 1.1); + fpixDestroy(&fpix_copy3); + fpixDestroy(&fpix5); + + PTA *ptas, *ptad; + ptas = ptaCreate(0); + ptad = ptaCreate(0); + FPIX *fpix_copy4 = fpixCopy(fpix_payload); + FPIX *fpix_return2 = fpixProjectivePta(fpix_copy4, ptas, ptad, 200, 0.0); + fpixDestroy(&fpix_return2); + fpixDestroy(&fpix_copy4); + ptaDestroy(&ptas); + ptaDestroy(&ptad); + + pixDestroy(&tmp_pixs); + dpixDestroy(&dpix_payload); + fpixDestroy(&fpix_payload); + return 0; +} diff --git a/leptonica/prog/fuzzing/general_corpus.zip b/leptonica/prog/fuzzing/general_corpus.zip Binary files differnew file mode 100644 index 00000000..61a08f0d --- /dev/null +++ b/leptonica/prog/fuzzing/general_corpus.zip diff --git a/leptonica/prog/fuzzing/graphics_fuzzer.cc b/leptonica/prog/fuzzing/graphics_fuzzer.cc new file mode 100644 index 00000000..6ca746c6 --- /dev/null +++ b/leptonica/prog/fuzzing/graphics_fuzzer.cc @@ -0,0 +1,81 @@ +#include "leptfuzz.h" + +extern "C" int +LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { + if(size<3) return 0; + + leptSetStdNullHandler(); + + PIX *pixs_payload = pixReadMemSpix(data, size); + if(pixs_payload == NULL) return 0; + + PTA *pta1 = ptaCreate(0); + PIX *pix_return1 = pixFillPolygon(pixs_payload, pta1, 2, 2); + ptaDestroy(&pta1); + pixDestroy(&pix_return1); + + PTA *pta_return1 =pixGeneratePtaBoundary(pixs_payload, 1); + ptaDestroy(&pta_return1); + + BOX *box1 = boxCreate(150, 130, 1500, 355); + pixRenderBox(pixs_payload, box1, 3, 200); + boxDestroy(&box1); + + BOXA *boxa1; + boxa1 = boxaCreate(0); + pixRenderBoxa(pixs_payload, boxa1, 17, 200); + boxaDestroy(&boxa1); + + boxa1 = boxaCreate(0); + pixRenderBoxaBlend(pixs_payload, boxa1, 17, 200, 1, 25, 0.4, 1); + boxaDestroy(&boxa1); + + PIX *pix_return12 = pixRenderContours(pixs_payload, 2, 4, 1); + pixDestroy(&pix_return12); + + pixRenderGridArb(pixs_payload, 1, 1, 1, 1, 1, 1); + + BOX *box2 = boxCreate(150, 130, 1500, 355); + pixRenderHashBox(pixs_payload, box2, 2, 1, 1, 0, L_SET_PIXELS); + boxDestroy(&box2); + + BOX *box3 = boxCreate(150, 130, 1500, 355); + pixRenderHashBoxBlend(pixs_payload, box3, 2, 1, L_HORIZONTAL_LINE, 0, 1, 1, 1, 1.0); + boxDestroy(&box3); + + BOXA *boxa2; + boxa2 = boxaCreate(1); + pixRenderHashBoxa(pixs_payload, boxa2, 2, 1, L_HORIZONTAL_LINE, 0, L_SET_PIXELS); + boxaDestroy(&boxa2); + + boxa1 = boxaCreate(1); + pixRenderHashBoxaArb(pixs_payload, boxa1, 2, 1, L_HORIZONTAL_LINE, 0, 1, 1, 1); + boxaDestroy(&boxa1); + + PIX *pixs = pixRead("../test8.jpg"); + pixRenderHashMaskArb(pixs_payload, pixs, 2, 2, 2, 1, L_HORIZONTAL_LINE, 0, 1, 1, 1); + pixDestroy(&pixs); + + pixRenderLineBlend(pixs_payload, 30, 60, 440, 70, 5, 115, 200, 120, 0.3); + + PIX *pixs_payload2 = pixCopy(NULL, pixs_payload); + NUMA *na2 = numaGammaTRC(1.7, 150, 255); + pixRenderPlotFromNumaGen(&pixs_payload2, na2, L_HORIZONTAL_LINE, 3, 1, 80, 1, 1); + numaDestroy(&na2); + pixDestroy(&pixs_payload2); + + PTA *pta2 = ptaCreate(0); + pixRenderPolylineArb(pixs_payload, pta2, 1, 1, 1, 1, 0); + ptaDestroy(&pta2); + + PTA *pta3 = ptaCreate(0); + pixRenderPolylineBlend(pixs_payload, pta3, 17, 25, 200, 1, 0.5, 1, 1); + ptaDestroy(&pta3); + + NUMA *na1 = numaGammaTRC(1.7, 150, 255); + pixRenderPlotFromNuma(&pixs_payload, na1, L_HORIZONTAL_LINE, 3, 1, 80); + numaDestroy(&na1); + + pixDestroy(&pixs_payload); + return 0; +} diff --git a/leptonica/prog/fuzzing/graymorph_fuzzer.cc b/leptonica/prog/fuzzing/graymorph_fuzzer.cc new file mode 100644 index 00000000..3115e956 --- /dev/null +++ b/leptonica/prog/fuzzing/graymorph_fuzzer.cc @@ -0,0 +1,36 @@ +#include "leptfuzz.h" + +extern "C" int +LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { + if(size<3) return 0; + + leptSetStdNullHandler(); + + PIX *pixs_payload = pixReadMemSpix(data, size); + if(pixs_payload == NULL) return 0; + + PIX *pix_pointer_payload, *return_pix; + + pix_pointer_payload = pixCopy(NULL, pixs_payload); + return_pix = pixCloseGray3(pix_pointer_payload, 3, 1); + pixDestroy(&pix_pointer_payload); + pixDestroy(&return_pix); + + pix_pointer_payload = pixCopy(NULL, pixs_payload); + return_pix = pixDilateGray3(pix_pointer_payload, 3, 1); + pixDestroy(&pix_pointer_payload); + pixDestroy(&return_pix); + + pix_pointer_payload = pixCopy(NULL, pixs_payload); + return_pix = pixErodeGray3(pix_pointer_payload, 3, 1); + pixDestroy(&pix_pointer_payload); + pixDestroy(&return_pix); + + pix_pointer_payload = pixCopy(NULL, pixs_payload); + return_pix = pixOpenGray3(pix_pointer_payload, 3, 1); + pixDestroy(&pix_pointer_payload); + pixDestroy(&return_pix); + + pixDestroy(&pixs_payload); + return 0; +} diff --git a/leptonica/prog/fuzzing/grayquant_fuzzer.cc b/leptonica/prog/fuzzing/grayquant_fuzzer.cc new file mode 100644 index 00000000..90cc8d17 --- /dev/null +++ b/leptonica/prog/fuzzing/grayquant_fuzzer.cc @@ -0,0 +1,47 @@ +#include "leptfuzz.h" + +extern "C" int +LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { + if(size<3) return 0; + + leptSetStdNullHandler(); + + PIX *pixs_payload = pixReadMemSpix(data, size); + if(pixs_payload == NULL) return 0; + + PIX *pix_pointer_payload, *return_pix; + + pix_pointer_payload = pixCopy(NULL, pixs_payload); + return_pix = pixDitherTo2bpp(pix_pointer_payload, 1); + pixDestroy(&pix_pointer_payload); + pixDestroy(&return_pix); + + pix_pointer_payload = pixCopy(NULL, pixs_payload); + return_pix = pixDitherToBinary(pix_pointer_payload); + pixDestroy(&pix_pointer_payload); + pixDestroy(&return_pix); + + pix_pointer_payload = pixCopy(NULL, pixs_payload); + return_pix = pixGenerateMaskByBand(pix_pointer_payload, 1, 2, 1, 1); + pixDestroy(&pix_pointer_payload); + pixDestroy(&return_pix); + + pix_pointer_payload = pixCopy(NULL, pixs_payload); + return_pix = pixGenerateMaskByBand32(pix_pointer_payload, 1, 1, 1, 0.0, 0.0); + pixDestroy(&pix_pointer_payload); + pixDestroy(&return_pix); + + pix_pointer_payload = pixCopy(NULL, pixs_payload); + return_pix = pixGenerateMaskByDiscr32(pix_pointer_payload, 10, 10, L_MANHATTAN_DISTANCE); + pixDestroy(&pix_pointer_payload); + pixDestroy(&return_pix); + + const char *str = "45 75 115 185"; + pix_pointer_payload = pixCopy(NULL, pixs_payload); + return_pix = pixThresholdGrayArb(pix_pointer_payload, str, 8, 0, 0, 0); + pixDestroy(&pix_pointer_payload); + pixDestroy(&return_pix); + + pixDestroy(&pixs_payload); + return 0; +} diff --git a/leptonica/prog/fuzzing/jpegiostub_fuzzer.cc b/leptonica/prog/fuzzing/jpegiostub_fuzzer.cc new file mode 100644 index 00000000..08e05a2f --- /dev/null +++ b/leptonica/prog/fuzzing/jpegiostub_fuzzer.cc @@ -0,0 +1,15 @@ +#include "leptfuzz.h" + +extern "C" int +LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { + if(size<3) return 0; + + leptSetStdNullHandler(); + + PIX *pixs_payload = pixReadMemSpix(data, size); + if(pixs_payload == NULL) return 0; + + pixSetChromaSampling(pixs_payload, 0); + pixDestroy(&pixs_payload); + return 0; +} diff --git a/leptonica/prog/fuzzing/kernel_fuzzer.cc b/leptonica/prog/fuzzing/kernel_fuzzer.cc new file mode 100644 index 00000000..127f834b --- /dev/null +++ b/leptonica/prog/fuzzing/kernel_fuzzer.cc @@ -0,0 +1,16 @@ +#include "leptfuzz.h" + +extern "C" int +LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { + if(size<3) return 0; + + leptSetStdNullHandler(); + + PIX *pixs_payload = pixReadMemSpix(data, size); + if(pixs_payload == NULL) return 0; + + L_KERNEL *kel1 = kernelCreateFromPix(pixs_payload, 2, 2); + pixDestroy(&pixs_payload); + kernelDestroy(&kel1); + return 0; +} diff --git a/leptonica/prog/fuzzing/leptfuzz.h b/leptonica/prog/fuzzing/leptfuzz.h new file mode 100644 index 00000000..c8f8de12 --- /dev/null +++ b/leptonica/prog/fuzzing/leptfuzz.h @@ -0,0 +1,16 @@ +/* Common include file for Leptonica fuzzers. */ + +#ifndef LEPTFUZZ_H +#define LEPTFUZZ_H + +#include "allheaders.h" + +static void send_to_devnull(const char *) {} + +/* Suppress Leptonica error messages during fuzzing. */ +static void leptSetStdNullHandler() +{ + leptSetStderrHandler(send_to_devnull); +} + +#endif /* LEPTFUZZ_H */ diff --git a/leptonica/prog/fuzzing/mask_fuzzer.cc b/leptonica/prog/fuzzing/mask_fuzzer.cc new file mode 100644 index 00000000..dc665a9d --- /dev/null +++ b/leptonica/prog/fuzzing/mask_fuzzer.cc @@ -0,0 +1,42 @@ +#include "leptfuzz.h" + +PIX * +MakeReplacementMask(PIX *pixs) +{ +PIX *pix1, *pix2, *pix3, *pix4; + + pix1 = pixMaskOverColorPixels(pixs, 95, 3); + pix2 = pixMorphSequence(pix1, "o15.15", 0); + pixSeedfillBinary(pix2, pix2, pix1, 8); + pix3 = pixMorphSequence(pix2, "c15.15 + d61.31", 0); + pix4 = pixRemoveBorderConnComps(pix3, 8); + pixXor(pix4, pix4, pix3); + pixDestroy(&pix1); + pixDestroy(&pix2); + pixDestroy(&pix3); + return pix4; +} + + +extern "C" int +LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + if(size<3) return 0; + + leptSetStdNullHandler(); + + PIX *pixs, *pix1, *pix2; + + pixs = pixReadMemSpix(data, size); + if(pixs==NULL) return 0; + + pix1 = MakeReplacementMask(pixs); + pix2 = pixConvertTo8(pix1, FALSE); + + pixPaintSelfThroughMask(pix2, pix1, 0, 0, L_HORIZ, 30, 50, 5, 10); + + pixDestroy(&pixs); + pixDestroy(&pix1); + pixDestroy(&pix2); + return 0; +} diff --git a/leptonica/prog/fuzzing/maze_fuzzer.cc b/leptonica/prog/fuzzing/maze_fuzzer.cc new file mode 100644 index 00000000..b3116ae2 --- /dev/null +++ b/leptonica/prog/fuzzing/maze_fuzzer.cc @@ -0,0 +1,24 @@ +#include "leptfuzz.h" + +extern "C" int +LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { + if(size<3) return 0; + + leptSetStdNullHandler(); + + PIX *pixs_payload = pixReadMemSpix(data, size); + if(pixs_payload == NULL) return 0; + + PIX *ppixd; + + PTA *pta = pixSearchBinaryMaze(pixs_payload, 1, 2, 3, 4, &ppixd); + pixDestroy(&ppixd); + ptaDestroy(&pta); + + PTA *pta2 = pixSearchGrayMaze(pixs_payload, 1, 2, 3, 4, &ppixd); + pixDestroy(&ppixd); + ptaDestroy(&pta2); + + pixDestroy(&pixs_payload); + return 0; +} diff --git a/leptonica/prog/fuzzing/morph_fuzzer.cc b/leptonica/prog/fuzzing/morph_fuzzer.cc new file mode 100644 index 00000000..f4055550 --- /dev/null +++ b/leptonica/prog/fuzzing/morph_fuzzer.cc @@ -0,0 +1,48 @@ +#include "leptfuzz.h" + +extern "C" int +LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { + if(size<3) return 0; + + leptSetStdNullHandler(); + + PIX *pixs_payload = pixReadMemSpix(data, size); + if(pixs_payload == NULL) return 0; + + PIX *pix, *pix1, *pix_copy1, *pix_copy2, *pix_copy3, *pix_copy4; + BOX *box1; + SEL *sel; + + pix = pixRead("../feyn-fract.tif"); + box1 = boxCreate(507, 65, 60, 36); + pix1 = pixClipRectangle(pix, box1, NULL); + sel = selCreateFromPix(pix1, 6, 6, "plus_sign"); + pix_copy1 = pixCopy(NULL, pixs_payload); + pixCloseGeneralized(pix_copy1, pix, sel); + boxDestroy(&box1); + pixDestroy(&pix_copy1); + pixDestroy(&pix1); + + pix_copy2 = pixCopy(NULL, pixs_payload); + pixCloseSafe(pix_copy2, pix, sel); + pixDestroy(&pix_copy2); + + pix_copy3 = pixCopy(NULL, pixs_payload); + pixOpenGeneralized(pix_copy3, pix, sel); + pixDestroy(&pix_copy3); + pixDestroy(&pix); + selDestroy(&sel); + + for (l_int32 i = 0; i < 5; i++) { + if ((sel = selCreate (i, i, "sel_5dp")) == NULL) + continue; + char *selname = selGetName(sel); + pix_copy4 = pixCopy(NULL, pixs_payload); + pixMorphDwa_1(pix_copy4, pix_copy4, i, selname); + pixDestroy(&pix_copy4); + selDestroy(&sel); + } + + pixDestroy(&pixs_payload); + return 0; +} diff --git a/leptonica/prog/fuzzing/morphapp_fuzzer.cc b/leptonica/prog/fuzzing/morphapp_fuzzer.cc new file mode 100644 index 00000000..ec4cf2ff --- /dev/null +++ b/leptonica/prog/fuzzing/morphapp_fuzzer.cc @@ -0,0 +1,65 @@ +#include "leptfuzz.h" + +extern "C" int +LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { + if(size<3) return 0; + + leptSetStdNullHandler(); + + Pix *pixs_payload = pixReadMemSpix(data, size); + if(pixs_payload == NULL) return 0; + + Pix *pix1 = pixRead("../test8.jpg"); + Pix *pix2 = pixRead("../test8.jpg"); + Pix *pix_return1 = pixDisplayMatchedPattern(pixs_payload, pix1, pix2, + 1, 2, 3, 0.5, 1); + pixDestroy(&pix1); + pixDestroy(&pix_return1); + pixDestroy(&pix2); + + Pix *pix_return2 = pixFastTophat(pixs_payload, 2, 2, L_TOPHAT_WHITE); + pixDestroy(&pix_return2); + + Pix *pix_return3 = pixHDome(pixs_payload, 1, 4); + pixDestroy(&pix_return3); + + Sela *sela1 = selaCreate(0); + Pix *pix_return4 = pixIntersectionOfMorphOps(pixs_payload, + sela1, L_MORPH_DILATE); + selaDestroy(&sela1); + pixDestroy(&pix_return4); + + Pix *pix_return5 = pixMorphGradient(pixs_payload, 5, 5, 1); + pixDestroy(&pix_return5); + + pix1 = pixRead("../test8.jpg"); + Boxa *boxa1; + const char *sequence = "sequence"; + Pix *pix_return6 = pixMorphSequenceByRegion(pixs_payload, pix1, + sequence, 4, 1, 1, &boxa1); + boxaDestroy(&boxa1); + pixDestroy(&pix1); + pixDestroy(&pix_return6); + + pix1 = pixRead("../test8.jpg"); + Pix *pix_return7 = pixMorphSequenceMasked(pixs_payload, pix1, sequence, 0); + pixDestroy(&pix1); + pixDestroy(&pix_return7); + + pix1 = pixCreate(300, 300, 32); + pix2 = pixCreate(300, 300, 32); + pixRemoveMatchedPattern(pixs_payload, pix1, pix2, 2, 2, 2); + pixDestroy(&pix1); + pixDestroy(&pix2); + + Pix *pix = pixCreate(300, 300, 32); + Pix *pix_return8 = pixSeedfillMorph(pixs_payload, pix, 0, 4); + pixDestroy(&pix_return8); + pixDestroy(&pix); + + Pix *pix_return9 = pixSelectiveConnCompFill(pixs_payload, 4, 1, 1); + pixDestroy(&pix_return9); + + pixDestroy(&pixs_payload); + return 0; +} diff --git a/leptonica/prog/fuzzing/oss-fuzz-build.sh b/leptonica/prog/fuzzing/oss-fuzz-build.sh new file mode 100755 index 00000000..ef248627 --- /dev/null +++ b/leptonica/prog/fuzzing/oss-fuzz-build.sh @@ -0,0 +1,128 @@ +# libz +pushd $SRC/zlib +./configure --static --prefix="$WORK" +make -j$(nproc) all +make install +popd + +# libzstd +pushd $SRC/zstd +make -j$(nproc) install PREFIX="$WORK" +popd + +# libjbig +pushd "$SRC/jbigkit" +make clean +make -j$(nproc) lib +cp "$SRC"/jbigkit/libjbig/*.a "$WORK/lib/" +cp "$SRC"/jbigkit/libjbig/*.h "$WORK/include/" +popd + +# libjpeg-turbo +pushd $SRC/libjpeg-turbo +cmake . -DCMAKE_INSTALL_PREFIX="$WORK" -DENABLE_STATIC:bool=on +make -j$(nproc) +make install +popd + +# libpng +pushd $SRC/libpng +cat scripts/pnglibconf.dfa | \ + sed -e "s/option WARNING /option WARNING disabled/" \ +> scripts/pnglibconf.dfa.temp +mv scripts/pnglibconf.dfa.temp scripts/pnglibconf.dfa +autoreconf -f -i +./configure \ + --prefix="$WORK" \ + --disable-shared \ + --enable-static \ + LDFLAGS="-L$WORK/lib" \ + CPPFLAGS="-I$WORK/include" +make -j$(nproc) +make install +popd + +# libwebp +pushd $SRC/libwebp +export WEBP_CFLAGS="$CFLAGS -DWEBP_MAX_IMAGE_SIZE=838860800" # 800MiB +./autogen.sh +./configure \ + --enable-libwebpdemux \ + --enable-libwebpmux \ + --disable-shared \ + --disable-jpeg \ + --disable-tiff \ + --disable-gif \ + --disable-wic \ + --disable-threading \ + --prefix="$WORK" \ + CFLAGS="$WEBP_CFLAGS" +make clean +make -j$(nproc) +make install +popd + +# libtiff +pushd "$SRC/libtiff" +cmake . -DCMAKE_INSTALL_PREFIX="$WORK" -DBUILD_SHARED_LIBS=off +make clean +make -j$(nproc) +make install +popd + +# leptonica +export LEPTONICA_LIBS="$WORK/lib/libjbig.a $WORK/lib/libzstd.a $WORK/lib/libwebp.a $WORK/lib/libpng.a" +./autogen.sh +./configure \ + --enable-static \ + --disable-shared \ + --with-libpng \ + --with-zlib \ + --with-jpeg \ + --with-libwebp \ + --with-libtiff \ + --prefix="$WORK" \ + LIBS="$LEPTONICA_LIBS" \ + LDFLAGS="-L$WORK/lib" \ + CPPFLAGS="-I$WORK/include -DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION" +make -j$(nproc) +make install + +for f in $SRC/leptonica/prog/fuzzing/*_fuzzer.cc; do + fuzzer=$(basename "$f" _fuzzer.cc) + $CXX $CXXFLAGS -std=c++11 -I"$WORK/include" \ + $SRC/leptonica/prog/fuzzing/${fuzzer}_fuzzer.cc -o $OUT/${fuzzer}_fuzzer \ + -Isrc/ \ + "$WORK/lib/liblept.a" \ + "$WORK/lib/libtiff.a" \ + "$WORK/lib/libwebp.a" \ + "$WORK/lib/libpng.a" \ + "$WORK/lib/libjpeg.a" \ + "$WORK/lib/libjbig.a" \ + "$WORK/lib/libzstd.a" \ + "$WORK/lib/libz.a" \ + $LIB_FUZZING_ENGINE +done + + +cp $SRC/leptonica/prog/fuzzing/general_corpus.zip $OUT/adaptmap_fuzzer_seed_corpus.zip +cp $SRC/leptonica/prog/fuzzing/general_corpus.zip $OUT/affine_fuzzer_seed_corpus.zip +cp $SRC/leptonica/prog/fuzzing/general_corpus.zip $OUT/baseline_fuzzer_seed_corpus.zip +cp $SRC/leptonica/prog/fuzzing/general_corpus.zip $OUT/bilateral_fuzzer_seed_corpus.zip +cp $SRC/leptonica/prog/fuzzing/general_corpus.zip $OUT/bilinear_fuzzer_seed_corpus.zip +cp $SRC/leptonica/prog/fuzzing/general_corpus.zip $OUT/binarize_fuzzer_seed_corpus.zip +cp $SRC/leptonica/prog/fuzzing/general_corpus.zip $OUT/blend_fuzzer_seed_corpus.zip +cp $SRC/leptonica/prog/fuzzing/general_corpus.zip $OUT/checkerboard_fuzzer_seed_corpus.zip +cp $SRC/leptonica/prog/fuzzing/general_corpus.zip $OUT/classapp_fuzzer_seed_corpus.zip + +cp $SRC/leptonica/prog/fuzzing/general_corpus.zip $OUT/pix_rotate_shear_fuzzer_seed_corpus.zip +cp $SRC/leptonica/prog/fuzzing/general_corpus.zip $OUT/enhance_fuzzer_seed_corpus.zip +cp $SRC/leptonica/prog/fuzzing/general_corpus.zip $OUT/colorquant_fuzzer_seed_corpus.zip +cp $SRC/leptonica/prog/fuzzing/general_corpus.zip $OUT/dewarp_fuzzer_seed_corpus.zip +cp $SRC/leptonica/prog/fuzzing/general_corpus.zip $OUT/pix_orient_fuzzer_seed_corpus.zip +cp $SRC/leptonica/prog/fuzzing/general_corpus.zip $OUT/pixconv_fuzzer_seed_corpus.zip +cp $SRC/leptonica/prog/fuzzing/general_corpus.zip $OUT/blend_fuzzer_seed_corpus.zip +cp $SRC/leptonica/prog/fuzzing/general_corpus.zip $OUT/pixMirrorDetectDwa_fuzzer_seed_corpus.zip + +cp $SRC/leptonica/prog/fuzzing/pixa_recog_fuzzer_seed_corpus.zip $OUT/ +cp $SRC/leptonica/prog/fuzzing/barcode_fuzzer_seed_corpus.zip $OUT/ diff --git a/leptonica/prog/fuzzing/pageseg_fuzzer.cc b/leptonica/prog/fuzzing/pageseg_fuzzer.cc new file mode 100644 index 00000000..93ccbefc --- /dev/null +++ b/leptonica/prog/fuzzing/pageseg_fuzzer.cc @@ -0,0 +1,42 @@ +#include "leptfuzz.h" + +extern "C" int +LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + leptSetStdNullHandler(); + + l_int32 score; + PIX *pixs; + PIX *pix1, *pix2, *pix3, *pix4; + PIXA *pixa1, *pixa2; + PIXAC *pixac; + BOX *box; + BOXA *boxa; + + pixs = pixReadMemSpix(data, size); + if(pixs==NULL) return 0; + + pixa1 = pixaCreate(0); + pixDecideIfTable(pixs, NULL, L_PORTRAIT_MODE, &score, pixa1); + pixaDestroy(&pixa1); + + pixa1 = pixaCreate(0); + pixGetRegionsBinary(pixs, &pix1, &pix2, &pix3, pixa1); + pixDestroy(&pix1); + pixDestroy(&pix2); + pixDestroy(&pix3); + pixaDestroy(&pixa1); + + pixac = pixacompReadMem(data, size); + box = pixFindPageForeground(pixs, 170, 70, 30, 0, pixac); + boxDestroy(&box); + pixacompDestroy(&pixac); + + pixSplitIntoCharacters(pixs, 4, 4, &boxa, &pixa2, &pix4); + boxaDestroy(&boxa); + pixaDestroy(&pixa2); + pixDestroy(&pix4); + + pixDestroy(&pixs); + return 0; +} diff --git a/leptonica/prog/fuzzing/paintcmap_fuzzer.cc b/leptonica/prog/fuzzing/paintcmap_fuzzer.cc new file mode 100644 index 00000000..54f9c62b --- /dev/null +++ b/leptonica/prog/fuzzing/paintcmap_fuzzer.cc @@ -0,0 +1,27 @@ +#include "leptfuzz.h" + +extern "C" int +LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { + if(size<3) return 0; + + leptSetStdNullHandler(); + + PIX *pixs_payload = pixReadMemSpix(data, size); + if(pixs_payload == NULL) return 0; + + BOX *box1; + PIX *pix_pointer_payload; + + box1 = boxCreate(278, 35, 122, 50); + pix_pointer_payload = pixCopy(NULL, pixs_payload); + pixSetSelectCmap(pix_pointer_payload, box1, 2, 255, 255, 100); + boxDestroy(&box1); + pixDestroy(&pix_pointer_payload); + + pix_pointer_payload = pixCopy(NULL, pixs_payload); + pixSetSelectMaskedCmap(pix_pointer_payload, NULL, 1, 50, 0, 250, 249, 248); + pixDestroy(&pix_pointer_payload); + + pixDestroy(&pixs_payload); + return 0; +} diff --git a/leptonica/prog/fuzzing/pix1_fuzzer.cc b/leptonica/prog/fuzzing/pix1_fuzzer.cc new file mode 100644 index 00000000..f987e3f8 --- /dev/null +++ b/leptonica/prog/fuzzing/pix1_fuzzer.cc @@ -0,0 +1,19 @@ +#include "leptfuzz.h" + +extern "C" int +LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + leptSetStdNullHandler(); + + l_uint32 *data2; + PIX *pixs; + + pixs = pixReadMemSpix(data, size); + if(pixs==NULL) return 0; + + data2 = pixExtractData(pixs); + + lept_free(data2); + pixDestroy(&pixs); + return 0; +} diff --git a/leptonica/prog/fuzzing/pix3_fuzzer.cc b/leptonica/prog/fuzzing/pix3_fuzzer.cc new file mode 100644 index 00000000..fd4c6cbf --- /dev/null +++ b/leptonica/prog/fuzzing/pix3_fuzzer.cc @@ -0,0 +1,133 @@ +#include "leptfuzz.h" + +extern "C" int +LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { + if(size<3) return 0; + + leptSetStdNullHandler(); + + PIX *pixs_payload = pixReadMemSpix(data, size); + if(pixs_payload == NULL) return 0; + + BOX *box1; + PIX *pix_pointer_payload, *return_pix, *pix2; + NUMA *return_numa; + l_float32 l_f; + l_int32 l_i, l_i2; + l_uint32 l_ui; + BOXA *boxa1; + + box1 = boxCreate(150, 130, 1500, 355); + pix_pointer_payload = pixCopy(NULL, pixs_payload); + return_numa = pixAbsDiffByColumn(pix_pointer_payload, box1); + pixDestroy(&pix_pointer_payload); + boxDestroy(&box1); + numaDestroy(&return_numa); + + box1 = boxCreate(150, 130, 1500, 355); + pix_pointer_payload = pixCopy(NULL, pixs_payload); + return_numa = pixAbsDiffByRow(pix_pointer_payload, box1); + pixDestroy(&pix_pointer_payload); + boxDestroy(&box1); + numaDestroy(&return_numa); + + box1 = boxCreate(150, 130, 1500, 355); + pix_pointer_payload = pixCopy(NULL, pixs_payload); + pixAbsDiffInRect(pix_pointer_payload, box1, L_HORIZONTAL_LINE, &l_f); + pixDestroy(&pix_pointer_payload); + boxDestroy(&box1); + + pix_pointer_payload = pixCopy(NULL, pixs_payload); + pixAbsDiffOnLine(pix_pointer_payload, 2, 2, 3, 3, &l_f); + pixDestroy(&pix_pointer_payload); + + box1 = boxCreate(150, 130, 1500, 355); + pix_pointer_payload = pixCopy(NULL, pixs_payload); + return_numa = pixAverageByColumn(pix_pointer_payload, box1, L_BLACK_IS_MAX); + boxDestroy(&box1); + pixDestroy(&pix_pointer_payload); + numaDestroy(&return_numa); + + box1 = boxCreate(150, 130, 1500, 355); + return_numa = pixAverageByRow(pix_pointer_payload, box1, L_WHITE_IS_MAX); + boxDestroy(&box1); + pixDestroy(&pix_pointer_payload); + numaDestroy(&return_numa); + + pix_pointer_payload = pixCopy(NULL, pixs_payload); + pixAverageInRect(pix_pointer_payload, NULL, NULL, 0, 255, 1, &l_f); + pixDestroy(&pix_pointer_payload); + + pix_pointer_payload = pixCopy(NULL, pixs_payload); + pixAverageInRectRGB(pix_pointer_payload, NULL, NULL, 10, &l_ui); + pixDestroy(&pix_pointer_payload); + + boxa1 = boxaCreate(0); + pix_pointer_payload = pixCopy(NULL, pixs_payload); + return_pix = pixCopyWithBoxa(pix_pointer_payload, boxa1, L_SET_WHITE); + pixDestroy(&pix_pointer_payload); + boxaDestroy(&boxa1); + pixDestroy(&return_pix); + + for (int i = 0; i < 5; i++) { + box1 = boxCreate(150, 130, 1500, 355); + pix_pointer_payload = pixCopy(NULL, pixs_payload); + pixCountArbInRect(pix_pointer_payload, box1, L_SET_WHITE, 2, &l_i); + pixDestroy(&pix_pointer_payload); + boxDestroy(&box1); + } + + box1 = boxCreate(150, 130, 1500, 355); + pix_pointer_payload = pixCopy(NULL, pixs_payload); + return_numa = pixCountByRow(pix_pointer_payload, box1); + pixDestroy(&pix_pointer_payload); + boxDestroy(&box1); + numaDestroy(&return_numa); + + box1 = boxCreate(150, 130, 1500, 355); + pix_pointer_payload = pixCopy(NULL, pixs_payload); + pixCountPixelsInRect(pix_pointer_payload, box1, &l_i, &l_i2); + boxDestroy(&box1); + pixDestroy(&pix_pointer_payload); + + pix_pointer_payload = pixCopy(NULL, pixs_payload); + return_pix = pixMakeArbMaskFromRGB(pix_pointer_payload, -0.5, -0.5, 1.0, 20); + pixDestroy(&pix_pointer_payload); + pixDestroy(&return_pix); + + pix_pointer_payload = pixCopy(NULL, pixs_payload); + for (int i = 0; i < 5; i++) { + return_pix = pixMakeMaskFromVal(pix_pointer_payload, i); + pixDestroy(&pix_pointer_payload); + pixDestroy(&return_pix); + } + + pix2 = pixRead("../test8.jpg"); + pix_pointer_payload = pixCopy(NULL, pixs_payload); + pixPaintSelfThroughMask(pix_pointer_payload, pix2, 0, 0, L_HORIZ, 30, 50, 5, 10); + pixDestroy(&pix2); + pixDestroy(&pix_pointer_payload); + + pix_pointer_payload = pixCopy(NULL, pixs_payload); + return_pix = pixSetUnderTransparency(pix_pointer_payload, 0, 0); + pixDestroy(&pix_pointer_payload); + pixDestroy(&return_pix); + + pix_pointer_payload = pixCopy(NULL, pixs_payload); + return_numa = pixVarianceByColumn(pix2, NULL); + pixDestroy(&pix_pointer_payload); + numaDestroy(&return_numa); + + pix_pointer_payload = pixCopy(NULL, pixs_payload); + return_numa = pixVarianceByRow(pix_pointer_payload, NULL); + pixDestroy(&pix_pointer_payload); + numaDestroy(&return_numa); + + box1 = boxCreate(150, 130, 1500, 355); + pixVarianceInRect(pix_pointer_payload, box1, &l_f); + boxDestroy(&box1); + pixDestroy(&pix_pointer_payload); + + pixDestroy(&pixs_payload); + return 0; +} diff --git a/leptonica/prog/fuzzing/pix4_fuzzer.cc b/leptonica/prog/fuzzing/pix4_fuzzer.cc new file mode 100644 index 00000000..c8d23259 --- /dev/null +++ b/leptonica/prog/fuzzing/pix4_fuzzer.cc @@ -0,0 +1,109 @@ +#include "leptfuzz.h" + +extern "C" int +LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + leptSetStdNullHandler(); + + PIX *pixs; + BOX *box; + + pixs = pixReadMemSpix(data, size); + if(pixs==NULL) return 0; + + PIX *pix1, *pix2, *pix3, *pix4, *pix5, *pix6; + NUMA *na1, *na2, *na3, *na4, *na5, *na6; + NUMAA *naa1; + + pix1 = pixConvertTo8(pixs, FALSE); + box = boxCreate(120, 30, 200, 200); + na1 = pixGetGrayHistogramInRect(pix1, box, 1); + numaDestroy(&na1); + boxDestroy(&box); + pixDestroy(&pix1); + + naa1 = pixGetGrayHistogramTiled(pixs, 1, 1, 1); + numaaDestroy(&naa1); + + pix1 = pixConvertTo8(pixs, FALSE); + na1 = pixGetCmapHistogramMasked(pix1, NULL, 1, 1, 1); + numaDestroy(&na1); + pixDestroy(&pix1); + + pix1 = pixConvertTo8(pixs, FALSE); + box = boxCreate(120, 30, 200, 200); + na1 = pixGetCmapHistogramInRect(pix1, box, 1); + numaDestroy(&na1); + boxDestroy(&box); + pixDestroy(&pix1); + + l_int32 ncolors; + pixCountRGBColors(pixs, 1, &ncolors); + + l_uint32 pval; + pix1 = pixConvertTo8(pixs, FALSE); + pixGetPixelAverage(pix1, NULL, 10, 10, 1, &pval); + pixDestroy(&pix1); + + pix1 = pixConvertTo8(pixs, FALSE); + l_uint32 pval2; + pixGetPixelStats(pix1, 1, L_STANDARD_DEVIATION, &pval2); + pixDestroy(&pix1); + + pix1 = pixConvertTo8(pixs, FALSE); + if(pix1!=NULL){ + pix2 = pixConvert8To32(pix1); + pixGetAverageTiledRGB(pix2, 2, 2, L_MEAN_ABSVAL, &pix3, &pix4, &pix5); + pixDestroy(&pix1); + pixDestroy(&pix2); + pixDestroy(&pix3); + pixDestroy(&pix4); + pixDestroy(&pix5); + } + + pixRowStats(pixs, NULL, &na1, &na2, &na3, &na4, &na5, &na6); + numaDestroy(&na1); + numaDestroy(&na2); + numaDestroy(&na3); + numaDestroy(&na4); + numaDestroy(&na5); + numaDestroy(&na6); + + pixColumnStats(pixs, NULL, &na1, &na2, &na3, &na4, &na5, &na6); + numaDestroy(&na1); + numaDestroy(&na2); + numaDestroy(&na3); + numaDestroy(&na4); + numaDestroy(&na5); + numaDestroy(&na6); + + static const l_int32 nbins = 10; + l_int32 minval, maxval; + l_uint32 *gau32; + pix1 = pixScaleBySampling(pixs, 0.2, 0.2); + pixGetBinnedComponentRange(pix1, nbins, 2, L_SELECT_GREEN, + &minval, &maxval, &gau32, 0); + pixDestroy(&pix1); + lept_free(gau32); + + PIX *pixd = pixSeedspread(pixs, 4); + PIX *pixc = pixConvertTo32(pixd); + PIX *pixr = pixRankBinByStrip(pixc, L_SCAN_HORIZONTAL, 1, + 10, L_SELECT_MAX); + pixDestroy(&pixd); + pixDestroy(&pixc); + pixDestroy(&pixr); + + PIXA *pixa = pixaReadMem(data, size); + pix1 = pixaGetAlignedStats(pixa, L_MEAN_ABSVAL, 2, 2); + pixaDestroy(&pixa); + pixDestroy(&pix1); + + l_int32 thresh, fgval, bgval; + pix1 = pixConvertTo8(pixs, 0); + pixSplitDistributionFgBg(pix1, 1.5, 1, &thresh, &fgval, &bgval, &pix2); + pixDestroy(&pix1); + pixDestroy(&pix2); + pixDestroy(&pixs); + return 0; +} diff --git a/leptonica/prog/fuzzing/pixMirrorDetectDwa_fuzzer.cc b/leptonica/prog/fuzzing/pixMirrorDetectDwa_fuzzer.cc new file mode 100644 index 00000000..83c6ce73 --- /dev/null +++ b/leptonica/prog/fuzzing/pixMirrorDetectDwa_fuzzer.cc @@ -0,0 +1,20 @@ +#include "leptfuzz.h" + +extern "C" int +LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + if(size<3) return 0; + + leptSetStdNullHandler(); + + l_float32 conf; + PIX *pixs; + + pixs = pixReadMemSpix(data, size); + if(pixs==NULL) return 0; + + pixMirrorDetectDwa(pixs, &conf, 0, 0); + + pixDestroy(&pixs); + return 0; +} diff --git a/leptonica/prog/fuzzing/pix_orient_fuzzer.cc b/leptonica/prog/fuzzing/pix_orient_fuzzer.cc new file mode 100644 index 00000000..13adeffc --- /dev/null +++ b/leptonica/prog/fuzzing/pix_orient_fuzzer.cc @@ -0,0 +1,19 @@ +#include "leptfuzz.h" + +extern "C" int +LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + if(size<3) return 0; + l_int32 rotation; + l_float32 upconf1, leftconf1; + PIX *pix1, *pix2; + + leptSetStdNullHandler(); + + pix1 = pixReadMemSpix(data,size); + if(pix1==NULL) return 0; + pix2 = pixOrientCorrect(pix1, 1.0, 1.0, &upconf1, &leftconf1, &rotation, 0); + pixDestroy(&pix1); + pixDestroy(&pix2); + return 0; +} diff --git a/leptonica/prog/fuzzing/pix_rotate_shear_fuzzer.cc b/leptonica/prog/fuzzing/pix_rotate_shear_fuzzer.cc new file mode 100644 index 00000000..9ae2569c --- /dev/null +++ b/leptonica/prog/fuzzing/pix_rotate_shear_fuzzer.cc @@ -0,0 +1,67 @@ +// The fuzzer takes as input a buffer of bytes. The buffer is read in as: +// <angle>, <x_center>, <y_center>, and the remaining bytes will be read +// in as a <pix>. The image is then rotated by angle around the center. All +// inputs should not result in undefined behavior. +#include <cmath> +#include <cstddef> +#include <cstdint> +#include <cstdlib> +#include <cstring> +#include "leptfuzz.h" + +// Set to true only for debugging; always false for production +static const bool DebugOutput = false; + +namespace { + +// Reads the front bytes of a data buffer containing `size` bytes as an int16_t, +// and advances the buffer forward [if there is sufficient capacity]. If there +// is insufficient capacity, this returns 0 and does not modify size or data. +int16_t ReadInt16(const uint8_t** data, size_t* size) { + int16_t result = 0; + if (*size >= sizeof(result)) { + memcpy(&result, *data, sizeof(result)); + *data += sizeof(result); + *size -= sizeof(result); + } + return result; +} + +} // namespace + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { + const int16_t angle = ReadInt16(&data, &size); + const int16_t x_center = ReadInt16(&data, &size); + const int16_t y_center = ReadInt16(&data, &size); + + leptSetStdNullHandler(); + + // Don't do pnm format (which can cause timeouts) or + // jpeg format (which can have uninitialized variables. + // The format checker requires at least 12 bytes. + if (size < 12) return EXIT_SUCCESS; + int format; + findFileFormatBuffer(data, &format); + if (format == IFF_PNM || format == IFF_JFIF_JPEG) return EXIT_SUCCESS; + + Pix* pix = pixReadMem(reinterpret_cast<const unsigned char*>(data), size); + if (pix == nullptr) { + return EXIT_SUCCESS; + } + + // Never in production + if (DebugOutput) { + L_INFO("w = %d, h = %d, d = %d\n", "fuzzer", + pixGetWidth(pix), pixGetHeight(pix), pixGetDepth(pix)); + } + + constexpr float deg2rad = M_PI / 180.; + Pix* pix_rotated = pixRotateShear(pix, x_center, y_center, deg2rad * angle, + L_BRING_IN_WHITE); + if (pix_rotated) { + pixDestroy(&pix_rotated); + } + + pixDestroy(&pix); + return EXIT_SUCCESS; +} diff --git a/leptonica/prog/fuzzing/pixa_recog_fuzzer.cc b/leptonica/prog/fuzzing/pixa_recog_fuzzer.cc new file mode 100644 index 00000000..7ca69369 --- /dev/null +++ b/leptonica/prog/fuzzing/pixa_recog_fuzzer.cc @@ -0,0 +1,49 @@ +#include "leptfuzz.h" +#include <sys/types.h> +#include <unistd.h> + + +extern "C" int +LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + if(size<10) return 0; + + leptSetStdNullHandler(); + + char filename[256]; + sprintf(filename, "/tmp/libfuzzer.pa"); + FILE *fp = fopen(filename, "wb"); + if (!fp) return 0; + fwrite(data, size, 1, fp); + fclose(fp); + + PIXA *pixa1, *pixa2, *pixa3, *pixa4, *pixa5; + L_RECOG *recog1, *recog2; + PIX *pix1, *pix2, *pix3, *pix4; + + pixa1 = pixaRead(filename); + + recog1 = recogCreateFromPixa(pixa1, 0, 40, 1, 128, 1); + + pixa2 = recogTrainFromBoot(recog1, pixa1, 0.75, 128, 1); + + pixa3 = pixaRemoveOutliers1(pixa1, 0.8, 4, 3, &pix1, &pix2); + pixa4 = pixaRemoveOutliers2(pixa1, 0.8, 4, &pix3, &pix4); + + recog2 = recogCreateFromPixa(pixa1, 4, 40, 1, 128, 1); + recogIdentifyMultiple(recog2, pix2, 0, 0, NULL, &pixa5, NULL, 1); + + pixDestroy(&pix1); + pixDestroy(&pix2); + pixDestroy(&pix3); + pixDestroy(&pix4); + recogDestroy(&recog1); + recogDestroy(&recog2); + pixaDestroy(&pixa1); + pixaDestroy(&pixa2); + pixaDestroy(&pixa3); + pixaDestroy(&pixa4); + pixaDestroy(&pixa5); + unlink(filename); + return 0; +} diff --git a/leptonica/prog/fuzzing/pixa_recog_fuzzer_seed_corpus.zip b/leptonica/prog/fuzzing/pixa_recog_fuzzer_seed_corpus.zip Binary files differnew file mode 100644 index 00000000..b3eabdd8 --- /dev/null +++ b/leptonica/prog/fuzzing/pixa_recog_fuzzer_seed_corpus.zip diff --git a/leptonica/prog/fuzzing/pixconv_fuzzer.cc b/leptonica/prog/fuzzing/pixconv_fuzzer.cc new file mode 100644 index 00000000..0dc21491 --- /dev/null +++ b/leptonica/prog/fuzzing/pixconv_fuzzer.cc @@ -0,0 +1,23 @@ +#include "leptfuzz.h" + +extern "C" int +LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + if(size<5) return 0; + PIX *pixs, *pix1, *pix2, *pix3; + + leptSetStdNullHandler(); + + pixs = pixReadMemSpix(data, size); + if(pixs==NULL) return 0; + + pix1 = pixConvertGrayToFalseColor(pixs, 1.0); + pix2 = pixThreshold8(pixs, 1, 0, 0); + pixQuantizeIfFewColors(pixs, 8, 0, 1, &pix3); + + pixDestroy(&pixs); + if (pix1!=NULL) pixDestroy(&pix1); + if (pix2!=NULL) pixDestroy(&pix2); + if (pix3!=NULL) pixDestroy(&pix3); + return 0; +} diff --git a/leptonica/prog/fuzzing/recog_basic_fuzzer.cc b/leptonica/prog/fuzzing/recog_basic_fuzzer.cc new file mode 100644 index 00000000..78fcbca7 --- /dev/null +++ b/leptonica/prog/fuzzing/recog_basic_fuzzer.cc @@ -0,0 +1,25 @@ +#include "leptfuzz.h" +#include <sys/types.h> +#include <unistd.h> + +extern "C" int +LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + leptSetStdNullHandler(); + + L_RECOG *recog; + char filename[256]; + sprintf(filename, "/tmp/libfuzzer.%d", getppid()); + + FILE *fp = fopen(filename, "wb"); + if (!fp) + return 0; + fwrite(data, size, 1, fp); + fclose(fp); + + recog = recogRead(filename); + + recogDestroy(&recog); + unlink(filename); + return 0; +} diff --git a/leptonica/prog/gammatest.c b/leptonica/prog/gammatest.c new file mode 100644 index 00000000..7c8e2ec6 --- /dev/null +++ b/leptonica/prog/gammatest.c @@ -0,0 +1,98 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * gammatest.c + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include <math.h> +#include "allheaders.h" + +#define MINVAL 30 +#define MAXVAL 210 + +int main(int argc, + char **argv) +{ +char *filein, *fileout; +char buf[512]; +l_int32 iplot, same; +l_float32 gam; +l_float64 gamma[] = {.5, 1.0, 1.5, 2.0, 2.5, -1.0}; +GPLOT *gplot; +NUMA *na, *nax; +PIX *pixs, *pixd; +static char mainName[] = "gammatest"; + + if (argc != 4) + return ERROR_INT(" Syntax: gammatest filein gam fileout", mainName, 1); + filein = argv[1]; + gam = atof(argv[2]); + fileout = argv[3]; + + setLeptDebugOK(1); + lept_mkdir("lept/gamma"); + + if ((pixs = pixRead(filein)) == NULL) + return ERROR_INT("pixs not made", mainName, 1); + + startTimer(); + pixd = pixGammaTRC(NULL, pixs, gam, MINVAL, MAXVAL); + lept_stderr("Time for gamma: %7.3f sec\n", stopTimer()); + pixGammaTRC(pixs, pixs, gam, MINVAL, MAXVAL); + pixEqual(pixs, pixd, &same); + if (!same) + lept_stderr("Error in pixGammaTRC!\n"); + pixWrite(fileout, pixs, IFF_JFIF_JPEG); + pixDestroy(&pixs); + + na = numaGammaTRC(gam, MINVAL, MAXVAL); + gplotSimple1(na, GPLOT_PNG, "/tmp/lept/gamma/trc", "gamma trc"); + l_fileDisplay("/tmp/lept/gamma/trc.png", 100, 100, 1.0); + numaDestroy(&na); + + /* Plot gamma TRC maps */ + gplot = gplotCreate("/tmp/lept/gamma/corr", GPLOT_PNG, + "Mapping function for gamma correction", + "value in", "value out"); + nax = numaMakeSequence(0.0, 1.0, 256); + for (iplot = 0; gamma[iplot] >= 0.0; iplot++) { + na = numaGammaTRC(gamma[iplot], 30, 215); + snprintf(buf, sizeof(buf), "gamma = %3.1f", gamma[iplot]); + gplotAddPlot(gplot, nax, na, GPLOT_LINES, buf); + numaDestroy(&na); + } + gplotMakeOutput(gplot); + gplotDestroy(&gplot); + l_fileDisplay("/tmp/lept/gamma/corr.png", 100, 100, 1.0); + numaDestroy(&nax); + return 0; +} + diff --git a/leptonica/prog/genfonts_reg.c b/leptonica/prog/genfonts_reg.c new file mode 100644 index 00000000..8b5b7cb5 --- /dev/null +++ b/leptonica/prog/genfonts_reg.c @@ -0,0 +1,173 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * genfonts_reg.c + * + * This regtest is for the generation of bitmap font characters that + * are presently used for annotating images. + * + * The tiff images of bitmaps fonts, which are used as input + * to this generator, are supplied in Leptonica in the prog/fonts + * directory. The tiff images were generated from the PostScript files + * in that directory, using the shell script prog/ps2tiff. If you + * want to generate other fonts, modify the PostScript files + * and use ps2tiff. ps2tiff uses GhostScript. + * + * The input tiff images are stored either as files in prog/fonts/, + * or as compiled C strings in bmfdata.h. Each image stores 94 of the + * 95 printable characters, all in one of 9 sizes (ranging from 4 to 20 + * points). These are programmatically split into individual characters, + * and the baselines are computed for each character. Baselines are + * required to properly render them. + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" +#include "bmfdata.h" + +#define NFONTS 9 + +const l_int32 sizes[] = {4, 6, 8, 10, 12, 14, 16, 18, 20}; + +int main(int argc, + char **argv) +{ +char buf[512]; +char *pathname, *datastr, *formstr; +l_uint8 *data1, *data2; +l_int32 i, bl1, bl2, bl3, sbytes, formbytes, fontsize, rbytes; +size_t nbytes; +PIX *pix1, *pix2, *pixd; +PIXA *pixa; +L_REGPARAMS *rp; + +#if !defined(HAVE_LIBPNG) + L_ERROR("This test requires libpng to run.\n", "genfonts_reg"); + exit(77); +#endif + + if (regTestSetup(argc, argv, &rp)) + return 1; + + /* ------------ Generate pixa char bitmap files from file ----------- */ + lept_rmdir("lept/filefonts"); + lept_mkdir("lept/filefonts"); + for (i = 0; i < 9; i++) { + pixaSaveFont("fonts", "/tmp/lept/filefonts", sizes[i]); + pathname = pathJoin("/tmp/lept/filefonts", outputfonts[i]); + pixa = pixaRead(pathname); + if (rp->display) { + lept_stderr("Found %d chars in font size %d\n", + pixaGetCount(pixa), sizes[i]); + } + pixd = pixaDisplayTiled(pixa, 1500, 0, 15); + regTestWritePixAndCheck(rp, pixd, IFF_PNG); /* 0 - 8 */ + if (i == 2) pixDisplayWithTitle(pixd, 100, 0, NULL, rp->display); + pixDestroy(&pixd); + pixaDestroy(&pixa); + lept_free(pathname); + } + lept_rmdir("lept/filefonts"); + + /* ---------- Generate pixa char bitmap files from string --------- */ + lept_rmdir("lept/strfonts"); + lept_mkdir("lept/strfonts"); + for (i = 0; i < 9; i++) { + pixaSaveFont(NULL, "/tmp/lept/strfonts", sizes[i]); + pathname = pathJoin("/tmp/lept/strfonts", outputfonts[i]); + pixa = pixaRead(pathname); + if (rp->display) { + lept_stderr("Found %d chars in font size %d\n", + pixaGetCount(pixa), sizes[i]); + } + pixd = pixaDisplayTiled(pixa, 1500, 0, 15); + regTestWritePixAndCheck(rp, pixd, IFF_PNG); /* 9 - 17 */ + if (i == 2) pixDisplayWithTitle(pixd, 100, 150, NULL, rp->display); + pixDestroy(&pixd); + pixaDestroy(&pixa); + lept_free(pathname); + } + + /* ----- Use pixaGetFont() and write the result out -----*/ + lept_rmdir("lept/pafonts"); + lept_mkdir("lept/pafonts"); + for (i = 0; i < 9; i++) { + pixa = pixaGetFont("/tmp/lept/strfonts", sizes[i], &bl1, &bl2, &bl3); + lept_stderr("Baselines are at: %d, %d, %d\n", bl1, bl2, bl3); + snprintf(buf, sizeof(buf), "/tmp/lept/pafonts/chars-%d.pa", sizes[i]); + pixaWrite(buf, pixa); + if (i == 2) { + pixd = pixaDisplayTiled(pixa, 1500, 0, 15); + pixDisplayWithTitle(pixd, 100, 300, NULL, rp->display); + pixDestroy(&pixd); + } + pixaDestroy(&pixa); + } + lept_rmdir("lept/pafonts"); + + /* ------- Generate 4/3 encoded ascii strings from tiff files ------ */ + lept_rmdir("lept/encfonts"); + lept_mkdir("lept/encfonts"); + for (i = 0; i < 9; i++) { + fontsize = 2 * i + 4; + pathname = pathJoin("fonts", inputfonts[i]); + data1 = l_binaryRead(pathname, &nbytes); + datastr = encodeBase64(data1, nbytes, &sbytes); + if (rp->display) + lept_stderr("nbytes = %lu, sbytes = %d\n", + (unsigned long)nbytes, sbytes); + formstr = reformatPacked64(datastr, sbytes, 4, 72, 1, &formbytes); + snprintf(buf, sizeof(buf), "/tmp/lept/encfonts/formstr_%d.txt", + fontsize); + l_binaryWrite(buf, "w", formstr, formbytes); + regTestCheckFile(rp, buf); /* 18-26 */ + if (i == 8) + pix1 = pixReadMem(data1, nbytes); /* original */ + lept_free(data1); + + data2 = decodeBase64(datastr, sbytes, &rbytes); + snprintf(buf, sizeof(buf), "/tmp/lept/encfonts/image_%d.tif", fontsize); + l_binaryWrite(buf, "w", data2, rbytes); + if (i == 8) { + pix2 = pixReadMem(data2, rbytes); /* encode/decode */ + regTestComparePix(rp, pix1, pix2); /* 27 */ + pixDestroy(&pix1); + pixDestroy(&pix2); + } + lept_free(data2); + + lept_free(pathname); + lept_free(datastr); + lept_free(formstr); + } + + return regTestCleanup(rp); +} + diff --git a/leptonica/prog/german.png b/leptonica/prog/german.png Binary files differnew file mode 100644 index 00000000..ad1c1c5b --- /dev/null +++ b/leptonica/prog/german.png diff --git a/leptonica/prog/gifio_reg.c b/leptonica/prog/gifio_reg.c new file mode 100644 index 00000000..768bafcb --- /dev/null +++ b/leptonica/prog/gifio_reg.c @@ -0,0 +1,232 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * gifio_reg.c + * + * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + * This is the Leptonica regression test for lossless read/write + * I/O in gif format. + * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + * + * This tests reading and writing of images in gif format for + * varioius depths. + * + * The relative times for writing of gif and png are interesting. + * + * For 1 bpp: + * + * png writing is about 2x faster than gif writing, using giflib. + * + * For 32 bpp, using a 1 Mpix rgb image: + * + * png: Lossless: 1.16 sec (2.0 MB output file) + * Lossy: 0.43 sec, composed of: + * 0.22 sec (octree quant with dithering) + * 0.21 sec (to compress and write out) + * + * gif: Lossy: 0.34 sec, composed of: + * 0.22 sec (octree quant with dithering) + * 0.12 sec (to compress and write out) + * (note: no lossless mode; gif can't write out rgb) + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include <math.h> +#include "allheaders.h" + +#if HAVE_LIBGIF || HAVE_LIBUNGIF +#include "gif_lib.h" +#endif /* HAVE_LIBGIF || HAVE_LIBUNGIF */ + +#define FILE_1BPP "feyn.tif" +#define FILE_2BPP "weasel2.4g.png" +#define FILE_4BPP "weasel4.16c.png" +#define FILE_8BPP_1 "dreyfus8.png" +#define FILE_8BPP_2 "weasel8.240c.png" +#define FILE_8BPP_3 "test8.jpg" +#define FILE_16BPP "test16.tif" +#define FILE_32BPP "marge.jpg" + +static void test_gif(const char *fname, PIXA *pixa, L_REGPARAMS *rp); +static l_int32 test_mem_gif(const char *fname, l_int32 index); + +int main(int argc, + char **argv) +{ +char buf[64]; +l_int32 success; +PIX *pix; +PIXA *pixa; +L_REGPARAMS *rp; + + if (regTestSetup(argc, argv, &rp)) + return 1; + +#if !HAVE_LIBGIF && !HAVE_LIBUNGIF + lept_stderr("gifio is not enabled\n" + "libgif or libungif are required for gifio_reg\n" + "See environ.h: #define HAVE_LIBGIF or HAVE_LIBUNGIF 1\n" + "See prog/Makefile: link in -lgif or -lungif\n\n"); + regTestCleanup(rp); + return 0; +#endif /* abort */ + + /* 5.1+ and not 5.1.2 */ + snprintf(buf, sizeof(buf), "%s_reg", rp->testname); +#if (GIFLIB_MAJOR < 5 || (GIFLIB_MAJOR == 5 && GIFLIB_MINOR == 0)) + L_ERROR("Require giflib-5.1 or later.\n", buf); + return 1; +#endif /* < 5.1 */ +#if GIFLIB_MAJOR == 5 && GIFLIB_MINOR == 1 && GIFLIB_RELEASE == 2 /* 5.1.2 */ + L_ERROR("Can't use giflib-5.1.2; suggest 5.1.3 or later.\n", buf); + return 1; +#endif /* 5.1.2 */ + + /* Set up for display output */ + pixa = (rp->display) ? pixaCreate(0) : NULL; + + lept_rmdir("lept/gif"); + lept_mkdir("lept/gif"); + + /* ------------ Part 1: Test lossless r/w to file ------------*/ + test_gif(FILE_1BPP, pixa, rp); + test_gif(FILE_2BPP, pixa, rp); + test_gif(FILE_4BPP, pixa, rp); + test_gif(FILE_8BPP_1, pixa, rp); + test_gif(FILE_8BPP_2, pixa, rp); + test_gif(FILE_8BPP_3, pixa, rp); + test_gif(FILE_16BPP, pixa, rp); + test_gif(FILE_32BPP, pixa, rp); + if (rp->success) + lept_stderr("\n ****** Success on lossless r/w to file *****\n\n"); + else + lept_stderr("\n ***** Failure on at least one r/w to file ****\n\n"); + + if (rp->display) { + pix = pixaDisplayTiledAndScaled(pixa, 32, 450, 3, 0, 20, 2); + pixWrite("/tmp/lept/gif/giftest.jpg", pix, IFF_JFIF_JPEG); + pixDisplay(pix, 100, 100); + pixDestroy(&pix); + pixaDestroy(&pixa); + } + + /* ------------ Part 2: Test lossless r/w to memory ------------ */ + success = TRUE; + if (test_mem_gif(FILE_1BPP, 0)) success = FALSE; + if (test_mem_gif(FILE_2BPP, 1)) success = FALSE; + if (test_mem_gif(FILE_4BPP, 2)) success = FALSE; + if (test_mem_gif(FILE_8BPP_1, 3)) success = FALSE; + if (test_mem_gif(FILE_8BPP_2, 4)) success = FALSE; + if (test_mem_gif(FILE_8BPP_3, 5)) success = FALSE; + if (test_mem_gif(FILE_16BPP, 6)) success = FALSE; + if (test_mem_gif(FILE_32BPP, 7)) success = FALSE; + if (success) + lept_stderr("\n ****** Success on lossless r/w to memory *****\n\n"); + else + lept_stderr("\n **** Failure on at least one r/w to memory ****\n\n"); + + /* Success only if all tests are passed */ + if (rp->success == TRUE) rp->success = success; + + return regTestCleanup(rp); +} + + +static void +test_gif(const char *fname, + PIXA *pixa, + L_REGPARAMS *rp) +{ +char buf[256]; +l_int32 same; +PIX *pixs, *pix1, *pix2; + + pixs = pixRead(fname); + snprintf(buf, sizeof(buf), "/tmp/lept/gif/gifio-a.%d.gif", rp->index + 1); + pixWrite(buf, pixs, IFF_GIF); + pix1 = pixRead(buf); + snprintf(buf, sizeof(buf), "/tmp/lept/gif/gifio-b.%d.gif", rp->index + 1); + pixWrite(buf, pix1, IFF_GIF); + pix2 = pixRead(buf); + regTestWritePixAndCheck(rp, pix2, IFF_GIF); + pixEqual(pixs, pix2, &same); + + if (!same && rp->index < 6) { + lept_stderr("Error for %s\n", fname); + rp->success = FALSE; + } + if (rp->display) { + lept_stderr(" depth: pixs = %d, pix1 = %d\n", pixGetDepth(pixs), + pixGetDepth(pix1)); + pixaAddPix(pixa, pix2, L_CLONE); + } + pixDestroy(&pixs); + pixDestroy(&pix1); + pixDestroy(&pix2); + return; +} + + + /* Returns 1 on error */ +static l_int32 +test_mem_gif(const char *fname, + l_int32 index) +{ +l_uint8 *data = NULL; +l_int32 same; +size_t size = 0; +PIX *pixs; +PIX *pixd = NULL; + + if ((pixs = pixRead(fname)) == NULL) { + lept_stderr("Failure to read gif file: %s\n", fname); + return 1; + } + if (pixWriteMem(&data, &size, pixs, IFF_GIF)) { + lept_stderr("Mem gif write fail on image %d\n", index); + return 1; + } + if ((pixd = pixReadMem(data, size)) == NULL) { + lept_stderr("Mem gif read fail on image %d\n", index); + lept_free(data); + return 1; + } + + pixEqual(pixs, pixd, &same); + pixDestroy(&pixs); + pixDestroy(&pixd); + lept_free(data); + if (!same && index < 6) { + lept_stderr("Mem gif write/read fail for file %s\n", fname); + return 1; + } + else + return 0; +} diff --git a/leptonica/prog/google-searchbox.png b/leptonica/prog/google-searchbox.png Binary files differnew file mode 100644 index 00000000..c9c549c4 --- /dev/null +++ b/leptonica/prog/google-searchbox.png diff --git a/leptonica/prog/gplotdata.example b/leptonica/prog/gplotdata.example new file mode 100644 index 00000000..4e477b7a --- /dev/null +++ b/leptonica/prog/gplotdata.example @@ -0,0 +1,82 @@ +% +% gplotdata.example +% +% This is an example data file to be used as input for gplot +% from file. +% +% All lines starting with '%' are comments and are ignored +% All blank lines are ignored +% Use '&' at beginning of a line as a control character: +% The first '&' signals that the data is to start +% Subsequent '&' are separators between data for different plots; +% this way, we can have multiple plots on the same output graph +% +% All plot info lines before the "&" that signals start of +% data are optional +% +% If they exist, the first three must be: +% title +% xaxis label +% yaxis label +% These default to null strings. +% +% Optionally after that, the individual plots can +% be labeled and the drawing method specified. +% This is done by specifying: +% number of plots +% title for plot 1 +% drawing style for plot 1 +% title for plot 2 +% drawing style for plot 2 +% ... +% +% The defaults are to have the plots untitled and to +% use LINES for the plot. The drawing styles allowed +% are in the set {LINES, POINTS, IMPULSES, LINESPOINTS, DOTS}. +% + +this is the title +this is the xaxis label +this is the yaxis label +4 +% (this is a comment line) +plotto uno +LINES +% (this is a comment line) +plotto due +POINTS +% (this is a comment line) +plotto tre +LINESPOINTS +% (this is a comment line) +plotto quattro +DOTS +&&&&&&&& +1. 4 +2,7 +3 11 +b(4) = 19 +(5., 31) +6.2 40 +7.3 , 70 +&&&&&&&& +&&&&&&&& oops, I put in an extra one +1 7 +2.1 15 +3.3 22 +4.5, 36 +5.9 62 +&&&&&&&& +0.5 4 +1.5 10 +2.5 25 +3.5 35 +4.5 47.2 +5.5, 68 +&&&&&&&& +0.2 5 +1.2 12.3 +2.3 27.9 +3.6 42.8 +4.8 61.9 +5.1 68.3 diff --git a/leptonica/prog/graphicstest.c b/leptonica/prog/graphicstest.c new file mode 100644 index 00000000..7ac6349d --- /dev/null +++ b/leptonica/prog/graphicstest.c @@ -0,0 +1,100 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * graphicstest.c + * + * e.g.: graphicstest fish24.jpg junkout + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + +int main(int argc, + char **argv) +{ +char *filein, *fileout; +l_int32 d; +BOX *box1, *box2, *box3, *box4; +BOXA *boxa; +PIX *pixs, *pix1; +PTA *pta; +static char mainName[] = "graphicstest"; + + if (argc != 3) + return ERROR_INT(" Syntax: graphicstest filein fileout", mainName, 1); + filein = argv[1]; + fileout = argv[2]; + setLeptDebugOK(1); + + if ((pixs = pixRead(filein)) == NULL) + return ERROR_INT(" Syntax: pixs not made", mainName, 1); + d = pixGetDepth(pixs); + if (d <= 8) + pix1 = pixConvertTo32(pixs); + else + pix1 = pixClone(pixs); + + /* Paint on RGB */ + pixRenderLineArb(pix1, 450, 20, 850, 320, 5, 200, 50, 125); + pixRenderLineArb(pix1, 30, 40, 440, 40, 5, 100, 200, 25); + pixRenderLineBlend(pix1, 30, 60, 440, 70, 5, 115, 200, 120, 0.3); + pixRenderLineBlend(pix1, 30, 600, 440, 670, 9, 215, 115, 30, 0.5); + pixRenderLineBlend(pix1, 130, 700, 540, 770, 9, 255, 255, 250, 0.4); + pixRenderLineBlend(pix1, 130, 800, 540, 870, 9, 0, 0, 0, 0.4); + box1 = boxCreate(70, 80, 300, 245); + box2 = boxCreate(470, 180, 150, 205); + box3 = boxCreate(520, 220, 160, 220); + box4 = boxCreate(570, 260, 160, 220); + boxa = boxaCreate(3); + boxaAddBox(boxa, box2, L_INSERT); + boxaAddBox(boxa, box3, L_INSERT); + boxaAddBox(boxa, box4, L_INSERT); + pixRenderBoxArb(pix1, box1, 3, 200, 200, 25); + pixRenderBoxaBlend(pix1, boxa, 17, 200, 200, 25, 0.4, 1); + pta = ptaCreate(5); + ptaAddPt(pta, 250, 300); + ptaAddPt(pta, 350, 450); + ptaAddPt(pta, 400, 600); + ptaAddPt(pta, 212, 512); + ptaAddPt(pta, 180, 375); + pixRenderPolylineBlend(pix1, pta, 17, 25, 200, 200, 0.5, 1, 1); + pixWrite(fileout, pix1, IFF_JFIF_JPEG); + pixDisplay(pix1, 200, 200); + + pixDestroy(&pixs); + pixDestroy(&pix1); + boxDestroy(&box1); + boxaDestroy(&boxa); + ptaDestroy(&pta); + pixDestroy(&pixs); + return 0; +} + + diff --git a/leptonica/prog/gray-alpha.tif b/leptonica/prog/gray-alpha.tif Binary files differnew file mode 100644 index 00000000..199d30a0 --- /dev/null +++ b/leptonica/prog/gray-alpha.tif diff --git a/leptonica/prog/grayfill_reg.c b/leptonica/prog/grayfill_reg.c new file mode 100644 index 00000000..a8a99b94 --- /dev/null +++ b/leptonica/prog/grayfill_reg.c @@ -0,0 +1,207 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * grayfill_reg.c + * + * Regression test for gray filling operations + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + +void PixTestEqual(L_REGPARAMS *rp, PIX *pixs1, PIX *pixs2, PIX *pixm, + l_int32 set, l_int32 connectivity); + +int main(int argc, + char **argv) +{ +l_int32 i, j; +PIX *pixm, *pixmi, *pixs1, *pixs1_8, *pix1; +PIX *pixs2, *pixs2_8, *pixs3, *pixs3_8; +PIX *pixb1, *pixb2, *pixb3, *pixmin, *pixd; +PIXA *pixa; +L_REGPARAMS *rp; + + if (regTestSetup(argc, argv, &rp)) + return 1; + + /* Mask */ + pixm = pixCreate(200, 200, 8); + for (i = 0; i < 200; i++) + for (j = 0; j < 200; j++) + pixSetPixel(pixm, j, i, 20 + L_ABS((100 - i) * (100 - j)) / 50); + pixmi = pixInvert(NULL, pixm); + + /* Seed1 */ + pixs1 = pixCreate(200, 200, 8); + for (i = 99; i <= 101; i++) + for (j = 99; j <= 101; j++) + pixSetPixel(pixs1, j, i, 50 - i/100 - j/100); + pixs1_8 = pixCopy(NULL, pixs1); + + /* Seed2 */ + pixs2 = pixCreate(200, 200, 8); + for (i = 99; i <= 101; i++) + for (j = 99; j <= 101; j++) + pixSetPixel(pixs2, j, i, 205 - i/100 - j/100); + pixs2_8 = pixCopy(NULL, pixs2); + + /* Inverse grayscale fill */ + pixa = pixaCreate(0); + pixaAddPix(pixa, pixm, L_COPY); + regTestWritePixAndCheck(rp, pixm, IFF_PNG); /* 0 */ + pixaAddPix(pixa, pixs1, L_COPY); + regTestWritePixAndCheck(rp, pixs1, IFF_PNG); /* 1 */ + pixSeedfillGrayInv(pixs1, pixm, 4); + pixSeedfillGrayInv(pixs1_8, pixm, 8); + pixaAddPix(pixa, pixs1, L_COPY); + regTestWritePixAndCheck(rp, pixs1, IFF_PNG); /* 2 */ + pixaAddPix(pixa, pixs1_8, L_COPY); + regTestWritePixAndCheck(rp, pixs1_8, IFF_PNG); /* 3 */ + pixb1 = pixThresholdToBinary(pixs1, 20); + pixaAddPix(pixa, pixb1, L_COPY); + regTestWritePixAndCheck(rp, pixb1, IFF_PNG); /* 4 */ + pixCombineMasked(pixs1, pixm, pixb1); + pixaAddPix(pixa, pixs1, L_COPY); + regTestWritePixAndCheck(rp, pixs1, IFF_PNG); /* 5 */ + pix1 = pixaDisplayTiledInColumns(pixa, 6, 1.0, 15, 2); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 6 */ + pixDisplayWithTitle(pix1, 100, 0, "inverse gray fill", rp->display); + pixDestroy(&pixs1); + pixDestroy(&pixs1_8); + pixDestroy(&pixb1); + pixDestroy(&pix1); + pixaDestroy(&pixa); + + /* Standard grayscale fill */ + pixa = pixaCreate(0); + pixaAddPix(pixa, pixmi, L_COPY); + regTestWritePixAndCheck(rp, pixmi, IFF_PNG); /* 7 */ + pixaAddPix(pixa, pixs2, L_COPY); + regTestWritePixAndCheck(rp, pixs2, IFF_PNG); /* 8 */ + pixSeedfillGray(pixs2, pixmi, 4); + pixSeedfillGray(pixs2_8, pixmi, 8); + pixaAddPix(pixa, pixs2, L_COPY); + regTestWritePixAndCheck(rp, pixs2, IFF_PNG); /* 9 */ + pixaAddPix(pixa, pixs2_8, L_COPY); + regTestWritePixAndCheck(rp, pixs2_8, IFF_PNG); /* 10 */ + pixb2 = pixThresholdToBinary(pixs2, 205); + regTestWritePixAndCheck(rp, pixb2, IFF_PNG); /* 11 */ + pixaAddPix(pixa, pixb2, L_INSERT); + pix1 = pixaDisplayTiledInColumns(pixa, 5, 1.0, 15, 2); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 12 */ + pixDisplayWithTitle(pix1, 100, 200, "standard gray fill", rp->display); + pixDestroy(&pixs2); + pixDestroy(&pixs2_8); + pixDestroy(&pix1); + pixaDestroy(&pixa); + + /* Basin fill from minima as seed */ + pixa = pixaCreate(0); + pixaAddPix(pixa, pixm, L_COPY); + regTestWritePixAndCheck(rp, pixm, IFF_PNG); /* 13 */ + pixLocalExtrema(pixm, 0, 0, &pixmin, NULL); + pixaAddPix(pixa, pixmin, L_COPY); + regTestWritePixAndCheck(rp, pixmin, IFF_PNG); /* 14 */ + pixs3 = pixSeedfillGrayBasin(pixmin, pixm, 30, 4); + pixs3_8 = pixSeedfillGrayBasin(pixmin, pixm, 30, 8); + pixaAddPix(pixa, pixs3, L_INSERT); + regTestWritePixAndCheck(rp, pixs3, IFF_PNG); /* 15 */ + pixaAddPix(pixa, pixs3_8, L_INSERT); + regTestWritePixAndCheck(rp, pixs3_8, IFF_PNG); /* 15 */ + pixb3 = pixThresholdToBinary(pixs3, 60); + regTestWritePixAndCheck(rp, pixb3, IFF_PNG); /* 17 */ + pixaAddPix(pixa, pixb3, L_INSERT); + pix1 = pixaDisplayTiledInColumns(pixa, 5, 1.0, 15, 2); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 18 */ + pixDisplayWithTitle(pix1, 100, 400, "gray fill form seed", rp->display); + pixDestroy(&pix1); + pixaDestroy(&pixa); + + /* Compare hybrid and iterative gray seedfills */ + pixs1 = pixCopy(NULL, pixm); + pixs2 = pixCopy(NULL, pixm); + pixAddConstantGray(pixs1, -30); + pixAddConstantGray(pixs2, 60); + + PixTestEqual(rp, pixs1, pixs2, pixm, 1, 4); /* 19 - 22 */ + PixTestEqual(rp, pixs1, pixs2, pixm, 2, 8); /* 23 - 26 */ + PixTestEqual(rp, pixs2, pixs1, pixm, 3, 4); /* 27 - 30 */ + PixTestEqual(rp, pixs2, pixs1, pixm, 4, 8); /* 31 - 34 */ + pixDestroy(&pixs1); + pixDestroy(&pixs2); + + pixDestroy(&pixm); + pixDestroy(&pixmi); + pixDestroy(&pixmin); + return regTestCleanup(rp);; +} + +void +PixTestEqual(L_REGPARAMS *rp, + PIX *pixs1, + PIX *pixs2, + PIX *pixm, + l_int32 set, + l_int32 connectivity) +{ +PIX *pixc11, *pixc12, *pixc21, *pixc22, *pixmi; + + pixmi = pixInvert(NULL, pixm); + pixc11 = pixCopy(NULL, pixs1); + pixc12 = pixCopy(NULL, pixs1); + pixc21 = pixCopy(NULL, pixs2); + pixc22 = pixCopy(NULL, pixs2); + + /* Test inverse seed filling */ + pixSeedfillGrayInv(pixc11, pixm, connectivity); + regTestWritePixAndCheck(rp, pixc11, IFF_PNG); /* '1' */ + pixSeedfillGrayInvSimple(pixc12, pixm, connectivity); + regTestComparePix(rp, pixc11, pixc12); /* '2' */ + + /* Test seed filling */ + pixSeedfillGray(pixc21, pixm, connectivity); + regTestWritePixAndCheck(rp, pixc21, IFF_PNG); /* '3' */ + pixSeedfillGraySimple(pixc22, pixm, connectivity); + regTestComparePix(rp, pixc21, pixc22); /* '4' */ + + /* Display the filling results */ +/* pixDisplay(pixc11, 220 * (set - 1), 100); + pixDisplay(pixc21, 220 * (set - 1), 320); */ + + pixDestroy(&pixmi); + pixDestroy(&pixc11); + pixDestroy(&pixc12); + pixDestroy(&pixc21); + pixDestroy(&pixc22); + return; +} + + diff --git a/leptonica/prog/graymorph1_reg.c b/leptonica/prog/graymorph1_reg.c new file mode 100644 index 00000000..8d50f5d7 --- /dev/null +++ b/leptonica/prog/graymorph1_reg.c @@ -0,0 +1,332 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * graymorph1_reg.c + * + * (1) Tests the interpreter for grayscale morphology, as + * given in morphseq.c + * + * (2) Tests composite operations: tophat and hdome + * + * (3) Tests duality for grayscale erode/dilate, open/close, + * and black/white tophat + * + * (4) Demonstrates closing plus white tophat. Note that this + * combination of operations can be quite useful. + * + * (5) Demonstrates a method of doing contrast enhancement + * by taking 3 * pixs and subtracting from this the + * closing and opening of pixs. Do this both with the + * basic pix accumulation functions and with the cleaner + * Pixacc wrapper. Verify the results are equivalent. + * + * (6) Playing around: extract the feynman diagrams from + * the stamp, using the tophat. + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + +#define WSIZE 7 +#define HSIZE 7 + +int main(int argc, + char **argv) +{ +char seq[512]; +l_int32 w, h; +PIX *pixs, *pix1, *pix2, *pix3, *pix4, *pix5; +PIXA *pixa; +PIXACC *pacc; +PIXCMAP *cmap; +L_REGPARAMS *rp; + + if (regTestSetup(argc, argv, &rp)) + return 1; + + pixs = pixRead("aneurisms8.jpg"); + pixa = pixaCreate(0); + + /* =========================================================== */ + + /* -------- Test gray morph, including interpreter ------------ */ + pix1 = pixDilateGray(pixs, WSIZE, HSIZE); + snprintf(seq, sizeof(seq), "D%d.%d", WSIZE, HSIZE); + pix2 = pixGrayMorphSequence(pixs, seq, 0, 0); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 0 */ + regTestComparePix(rp, pix1, pix2); /* 1 */ + pixaAddPix(pixa, pix1, L_INSERT); + pixDestroy(&pix2); + + pix1 = pixErodeGray(pixs, WSIZE, HSIZE); + snprintf(seq, sizeof(seq), "E%d.%d", WSIZE, HSIZE); + pix2 = pixGrayMorphSequence(pixs, seq, 0, 100); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 2 */ + regTestComparePix(rp, pix1, pix2); /* 3 */ + pixaAddPix(pixa, pix1, L_INSERT); + pixDestroy(&pix2); + + pix1 = pixOpenGray(pixs, WSIZE, HSIZE); + snprintf(seq, sizeof(seq), "O%d.%d", WSIZE, HSIZE); + pix2 = pixGrayMorphSequence(pixs, seq, 0, 200); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 4 */ + regTestComparePix(rp, pix1, pix2); /* 5 */ + pixaAddPix(pixa, pix1, L_INSERT); + pixDestroy(&pix2); + + pix1 = pixCloseGray(pixs, WSIZE, HSIZE); + snprintf(seq, sizeof(seq), "C%d.%d", WSIZE, HSIZE); + pix2 = pixGrayMorphSequence(pixs, seq, 0, 300); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 6 */ + regTestComparePix(rp, pix1, pix2); /* 7 */ + pixaAddPix(pixa, pix1, L_INSERT); + pixDestroy(&pix2); + + pix1 = pixTophat(pixs, WSIZE, HSIZE, L_TOPHAT_WHITE); + snprintf(seq, sizeof(seq), "Tw%d.%d", WSIZE, HSIZE); + pix2 = pixGrayMorphSequence(pixs, seq, 0, 400); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 8 */ + regTestComparePix(rp, pix1, pix2); /* 9 */ + pixaAddPix(pixa, pix1, L_INSERT); + pixDestroy(&pix2); + + pix1 = pixTophat(pixs, WSIZE, HSIZE, L_TOPHAT_BLACK); + snprintf(seq, sizeof(seq), "Tb%d.%d", WSIZE, HSIZE); + pix2 = pixGrayMorphSequence(pixs, seq, 0, 500); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 10 */ + regTestComparePix(rp, pix1, pix2); /* 11 */ + pixaAddPix(pixa, pix1, L_INSERT); + pixDestroy(&pix2); + + /* ------------- Test erode/dilate duality -------------- */ + pix1 = pixDilateGray(pixs, WSIZE, HSIZE); + pix2 = pixInvert(NULL, pixs); + pix3 = pixErodeGray(pix2, WSIZE, HSIZE); + pixInvert(pix3, pix3); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 12 */ + regTestComparePix(rp, pix1, pix3); /* 13 */ + pixaAddPix(pixa, pix1, L_INSERT); + pixDestroy(&pix2); + pixDestroy(&pix3); + + /* ------------- Test open/close duality -------------- */ + pix1 = pixOpenGray(pixs, WSIZE, HSIZE); + pix2 = pixInvert(NULL, pixs); + pix3 = pixCloseGray(pix2, WSIZE, HSIZE); + pixInvert(pix3, pix3); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 14 */ + regTestComparePix(rp, pix1, pix3); /* 15 */ + pixaAddPix(pixa, pix1, L_INSERT); + pixDestroy(&pix2); + pixDestroy(&pix3); + + /* ------------- Test tophat duality -------------- */ + pix1 = pixTophat(pixs, WSIZE, HSIZE, L_TOPHAT_WHITE); + pix2 = pixInvert(NULL, pixs); + pix3 = pixTophat(pix2, WSIZE, HSIZE, L_TOPHAT_BLACK); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 16 */ + regTestComparePix(rp, pix1, pix3); /* 17 */ + pixaAddPix(pixa, pix1, L_INSERT); + pixDestroy(&pix2); + pixDestroy(&pix3); + + pix1 = pixGrayMorphSequence(pixs, "Tw9.5", 0, 100); + pix2 = pixInvert(NULL, pixs); + pix3 = pixGrayMorphSequence(pix2, "Tb9.5", 0, 300); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 18 */ + regTestComparePix(rp, pix1, pix3); /* 19 */ + pixaAddPix(pixa, pix1, L_INSERT); + pixDestroy(&pix2); + pixDestroy(&pix3); + + + /* ------------- Test opening/closing for large sels -------------- */ + pix1 = pixGrayMorphSequence(pixs, + "C9.9 + C19.19 + C29.29 + C39.39 + C49.49", 0, 100); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 20 */ + pixaAddPix(pixa, pix1, L_INSERT); + pix1 = pixGrayMorphSequence(pixs, + "O9.9 + O19.19 + O29.29 + O39.39 + O49.49", 0, 400); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 21 */ + pixaAddPix(pixa, pix1, L_INSERT); + + pix1 = pixaDisplayTiledInColumns(pixa, 4, 1.0, 20, 2); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 22 */ + pixDisplayWithTitle(pix1, 0, 0, NULL, rp->display); + pixaDestroy(&pixa); + pixDestroy(&pix1); + + /* =========================================================== */ + + pixa = pixaCreate(0); + /* ---------- Closing plus white tophat result ------------ * + * Parameters: wsize, hsize = 9, 29 * + * ---------------------------------------------------------*/ + pix1 = pixCloseGray(pixs, 9, 9); + pix2 = pixTophat(pix1, 9, 9, L_TOPHAT_WHITE); + pix3 = pixGrayMorphSequence(pixs, "C9.9 + TW9.9", 0, 0); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 23 */ + regTestComparePix(rp, pix2, pix3); /* 24 */ + pixaAddPix(pixa, pix1, L_INSERT); + pix1 = pixMaxDynamicRange(pix2, L_LINEAR_SCALE); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 25 */ + pixaAddPix(pixa, pix1, L_INSERT); + pixDestroy(&pix2); + pixDestroy(&pix3); + + pix1 = pixCloseGray(pixs, 29, 29); + pix2 = pixTophat(pix1, 29, 29, L_TOPHAT_WHITE); + pix3 = pixGrayMorphSequence(pixs, "C29.29 + Tw29.29", 0, 0); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 26 */ + regTestComparePix(rp, pix2, pix3); /* 27 */ + pixaAddPix(pixa, pix1, L_INSERT); + pix1 = pixMaxDynamicRange(pix2, L_LINEAR_SCALE); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 28 */ + pixaAddPix(pixa, pix1, L_INSERT); + pixDestroy(&pix2); + pixDestroy(&pix3); + + /* --------- hdome with parameter height = 100 ------------*/ + pix1 = pixHDome(pixs, 100, 4); + pix2 = pixMaxDynamicRange(pix1, L_LINEAR_SCALE); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 29 */ + regTestWritePixAndCheck(rp, pix2, IFF_PNG); /* 30 */ + pixaAddPix(pixa, pix1, L_INSERT); + pixaAddPix(pixa, pix2, L_INSERT); + + /* ----- Contrast enhancement with morph parameters 9, 9 -------*/ + pixGetDimensions(pixs, &w, &h, NULL); + pix1 = pixInitAccumulate(w, h, 0x8000); + pixAccumulate(pix1, pixs, L_ARITH_ADD); + pixMultConstAccumulate(pix1, 3., 0x8000); + pix2 = pixOpenGray(pixs, 9, 9); + regTestWritePixAndCheck(rp, pix2, IFF_PNG); /* 31 */ + pixaAddPix(pixa, pix2, L_INSERT); + pixAccumulate(pix1, pix2, L_ARITH_SUBTRACT); + + pix2 = pixCloseGray(pixs, 9, 9); + regTestWritePixAndCheck(rp, pix2, IFF_PNG); /* 32 */ + pixaAddPix(pixa, pix2, L_INSERT); + pixAccumulate(pix1, pix2, L_ARITH_SUBTRACT); + pix2 = pixFinalAccumulate(pix1, 0x8000, 8); + regTestWritePixAndCheck(rp, pix2, IFF_PNG); /* 33 */ + pixaAddPix(pixa, pix2, L_INSERT); + pixDestroy(&pix1); + + /* Do the same thing with the Pixacc */ + pacc = pixaccCreate(w, h, 1); + pixaccAdd(pacc, pixs); + pixaccMultConst(pacc, 3.); + pix1 = pixOpenGray(pixs, 9, 9); + pixaccSubtract(pacc, pix1); + pixDestroy(&pix1); + pix1 = pixCloseGray(pixs, 9, 9); + pixaccSubtract(pacc, pix1); + pixDestroy(&pix1); + pix1 = pixaccFinal(pacc, 8); + pixaccDestroy(&pacc); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 34 */ + pixaAddPix(pixa, pix1, L_INSERT); + regTestComparePix(rp, pix1, pix2); /* 35 */ + + pix1 = pixaDisplayTiledInColumns(pixa, 4, 1.0, 20, 2); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 36 */ + pixDisplayWithTitle(pix1, 1100, 0, NULL, rp->display); + pixaDestroy(&pixa); + pixDestroy(&pix1); + pixDestroy(&pixs); + + /* =========================================================== */ + + pixa = pixaCreate(0); + + /* ---- Tophat result on feynman stamp, to extract diagrams ----- */ + pixs = pixRead("feynman-stamp.jpg"); + pixGetDimensions(pixs, &w, &h, NULL); + + /* Make output image to hold five intermediate images */ + pix1 = pixCreate(5 * w + 18, h + 6, 32); /* composite output image */ + pixSetAllArbitrary(pix1, 0x0000ff00); /* set to blue */ + + /* Paste in the input image */ + pix2 = pixRemoveColormap(pixs, REMOVE_CMAP_TO_FULL_COLOR); + pixRasterop(pix1, 3, 3, w, h, PIX_SRC, pix2, 0, 0); /* 1st one */ + regTestWritePixAndCheck(rp, pix2, IFF_PNG); /* 37 */ + pixaAddPix(pixa, pix2, L_INSERT); + + /* Paste in the grayscale version */ + cmap = pixGetColormap(pixs); + if (cmap) + pix2 = pixRemoveColormap(pixs, REMOVE_CMAP_TO_GRAYSCALE); + else + pix2 = pixConvertRGBToGray(pixs, 0.33, 0.34, 0.33); + pix3 = pixConvertTo32(pix2); /* 8 --> 32 bpp */ + pixRasterop(pix1, w + 6, 3, w, h, PIX_SRC, pix3, 0, 0); /* 2nd one */ + regTestWritePixAndCheck(rp, pix3, IFF_PNG); /* 38 */ + pixaAddPix(pixa, pix3, L_INSERT); + + /* Paste in a log dynamic range scaled version of the white tophat */ + pix3 = pixTophat(pix2, 3, 3, L_TOPHAT_WHITE); + pix4 = pixMaxDynamicRange(pix3, L_LOG_SCALE); + pix5 = pixConvertTo32(pix4); + pixRasterop(pix1, 2 * w + 9, 3, w, h, PIX_SRC, pix5, 0, 0); /* 3rd */ + regTestWritePixAndCheck(rp, pix5, IFF_PNG); /* 39 */ + pixaAddPix(pixa, pix5, L_INSERT); + pixDestroy(&pix2); + pixDestroy(&pix4); + + /* Stretch the range and threshold to binary; paste it in */ + pix2 = pixGammaTRC(NULL, pix3, 1.0, 0, 80); + pix4 = pixThresholdToBinary(pix2, 70); + pix5 = pixConvertTo32(pix4); + pixRasterop(pix1, 3 * w + 12, 3, w, h, PIX_SRC, pix5, 0, 0); /* 4th */ + regTestWritePixAndCheck(rp, pix5, IFF_PNG); /* 40 */ + pixaAddPix(pixa, pix5, L_INSERT); + pixDestroy(&pix2); + pixDestroy(&pix3); + + /* Invert; this is the final result */ + pixInvert(pix4, pix4); + pix5 = pixConvertTo32(pix4); + pixRasterop(pix1, 4 * w + 15, 3, w, h, PIX_SRC, pix5, 0, 0); /* 5th */ + regTestWritePixAndCheck(rp, pix5, IFF_PNG); /* 41 */ + pixaAddPix(pixa, pix5, L_INSERT); + pixDestroy(&pix1); + pixDestroy(&pix4); + + pix1 = pixaDisplayTiledInRows(pixa, 32, 1700, 1.0, 0, 20, 2); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 42 */ + pixDisplayWithTitle(pix1, 0, 800, NULL, rp->display); + pixaDestroy(&pixa); + pixDestroy(&pix1); + pixDestroy(&pixs); + + return regTestCleanup(rp); +} diff --git a/leptonica/prog/graymorph2_reg.c b/leptonica/prog/graymorph2_reg.c new file mode 100644 index 00000000..3748a508 --- /dev/null +++ b/leptonica/prog/graymorph2_reg.c @@ -0,0 +1,153 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * graymorph2_reg.c + * + * Compares graymorph results with special (3x1, 1x3, 3x3) cases + * against the general case. Require exact equality. + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + +int main(int argc, + char **argv) +{ +PIX *pixs, *pix1, *pix2, *pixd; +PIXA *pixa; +L_REGPARAMS *rp; + + if (regTestSetup(argc, argv, &rp)) + return 1; + + pixs = pixRead("test8.jpg"); + + /* Dilation */ + pixa = pixaCreate(0); + pix1 = pixDilateGray3(pixs, 3, 1); + pixaAddPix(pixa, pix1, L_INSERT); + pix2 = pixDilateGray(pixs, 3, 1); + pixaAddPix(pixa, pix2, L_INSERT); + regTestComparePix(rp, pix1, pix2); /* 0 */ + + pix1 = pixDilateGray3(pixs, 1, 3); + pixaAddPix(pixa, pix1, L_INSERT); + pix2 = pixDilateGray(pixs, 1, 3); + pixaAddPix(pixa, pix2, L_INSERT); + regTestComparePix(rp, pix1, pix2); /* 1 */ + + pix1 = pixDilateGray3(pixs, 3, 3); + pixaAddPix(pixa, pix1, L_INSERT); + pix2 = pixDilateGray(pixs, 3, 3); + pixaAddPix(pixa, pix2, L_INSERT); + regTestComparePix(rp, pix1, pix2); /* 2 */ + + pixd = pixaDisplayTiledInColumns(pixa, 2, 1.0, 20, 2); + pixDisplayWithTitle(pixd, 0, 100, "Dilation", rp->display); + pixDestroy(&pixd); + pixaDestroy(&pixa); + + /* Erosion */ + pixa = pixaCreate(0); + pix1 = pixErodeGray3(pixs, 3, 1); + pixaAddPix(pixa, pix1, L_INSERT); + pix2 = pixErodeGray(pixs, 3, 1); + pixaAddPix(pixa, pix2, L_INSERT); + regTestComparePix(rp, pix1, pix2); /* 3 */ + + pix1 = pixErodeGray3(pixs, 1, 3); + pixaAddPix(pixa, pix1, L_INSERT); + pix2 = pixErodeGray(pixs, 1, 3); + pixaAddPix(pixa, pix2, L_INSERT); + regTestComparePix(rp, pix1, pix2); /* 4 */ + + pix1 = pixErodeGray3(pixs, 3, 3); + pixaAddPix(pixa, pix1, L_INSERT); + pix2 = pixErodeGray(pixs, 3, 3); + pixaAddPix(pixa, pix2, L_INSERT); + regTestComparePix(rp, pix1, pix2); /* 5 */ + + pixd = pixaDisplayTiledInColumns(pixa, 2, 1.0, 20, 2); + pixDisplayWithTitle(pixd, 250, 100, "Erosion", rp->display); + pixDestroy(&pixd); + pixaDestroy(&pixa); + + /* Opening */ + pixa = pixaCreate(0); + pix1 = pixOpenGray3(pixs, 3, 1); + pixaAddPix(pixa, pix1, L_INSERT); + pix2 = pixOpenGray(pixs, 3, 1); + pixaAddPix(pixa, pix2, L_INSERT); + regTestComparePix(rp, pix1, pix2); /* 6 */ + + pix1 = pixOpenGray3(pixs, 1, 3); + pixaAddPix(pixa, pix1, L_INSERT); + pix2 = pixOpenGray(pixs, 1, 3); + pixaAddPix(pixa, pix2, L_INSERT); + regTestComparePix(rp, pix1, pix2); /* 7 */ + + pix1 = pixOpenGray3(pixs, 3, 3); + pixaAddPix(pixa, pix1, L_INSERT); + pix2 = pixOpenGray(pixs, 3, 3); + pixaAddPix(pixa, pix2, L_INSERT); + regTestComparePix(rp, pix1, pix2); /* 8 */ + + pixd = pixaDisplayTiledInColumns(pixa, 2, 1.0, 20, 2); + pixDisplayWithTitle(pixd, 500, 100, "Opening", rp->display); + pixDestroy(&pixd); + pixaDestroy(&pixa); + + /* Closing */ + pixa = pixaCreate(0); + pix1 = pixCloseGray3(pixs, 3, 1); + pixaAddPix(pixa, pix1, L_INSERT); + pix2 = pixCloseGray(pixs, 3, 1); + pixaAddPix(pixa, pix2, L_INSERT); + regTestComparePix(rp, pix1, pix2); /* 9 */ + + pix1 = pixCloseGray3(pixs, 1, 3); + pixaAddPix(pixa, pix1, L_INSERT); + pix2 = pixCloseGray(pixs, 1, 3); + pixaAddPix(pixa, pix2, L_INSERT); + regTestComparePix(rp, pix1, pix2); /* 10 */ + + pix1 = pixCloseGray3(pixs, 3, 3); + pixaAddPix(pixa, pix1, L_INSERT); + pix2 = pixCloseGray(pixs, 3, 3); + pixaAddPix(pixa, pix2, L_INSERT); + regTestComparePix(rp, pix1, pix2); /* 11 */ + + pixd = pixaDisplayTiledInColumns(pixa, 2, 1.0, 20, 2); + pixDisplayWithTitle(pixd, 750, 100, "Closing", rp->display); + pixDestroy(&pixd); + pixaDestroy(&pixa); + pixDestroy(&pixs); + return regTestCleanup(rp); +} diff --git a/leptonica/prog/graymorphtest.c b/leptonica/prog/graymorphtest.c new file mode 100644 index 00000000..9ad3b84d --- /dev/null +++ b/leptonica/prog/graymorphtest.c @@ -0,0 +1,103 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * graymorphtest.c + * + * Implements basic grayscale morphology; tests speed + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + +int main(int argc, + char **argv) +{ +char *filein, *fileout; +l_int32 wsize, hsize, w, h, d; +PIX *pixs, *pixd; +static char mainName[] = "graymorphtest"; + + if (argc != 5) + return ERROR_INT(" Syntax: graymorphtest filein wsize hsize fileout", + mainName, 1); + filein = argv[1]; + wsize = atoi(argv[2]); + hsize = atoi(argv[3]); + fileout = argv[4]; + setLeptDebugOK(1); + + if ((pixs = pixRead(filein)) == NULL) + return ERROR_INT("pix not made", mainName, 1); + pixGetDimensions(pixs, &w, &h, &d); + if (d != 8) + return ERROR_INT("pix not 8 bpp", mainName, 1); + + /* ---------- Choose an operation ---------- */ +#if 1 + pixd = pixDilateGray(pixs, wsize, hsize); + pixWrite(fileout, pixd, IFF_JFIF_JPEG); + pixDestroy(&pixd); +#elif 0 + pixd = pixErodeGray(pixs, wsize, hsize); + pixWrite(fileout, pixd, IFF_JFIF_JPEG); + pixDestroy(&pixd); +#elif 0 + pixd = pixOpenGray(pixs, wsize, hsize); + pixWrite(fileout, pixd, IFF_JFIF_JPEG); + pixDestroy(&pixd); +#elif 0 + pixd = pixCloseGray(pixs, wsize, hsize); + pixWrite(fileout, pixd, IFF_JFIF_JPEG); + pixDestroy(&pixd); +#elif 0 + pixd = pixTophat(pixs, wsize, hsize, TOPHAT_WHITE); + pixWrite(fileout, pixd, IFF_JFIF_JPEG); + pixDestroy(&pixd); +#elif 0 + pixd = pixTophat(pixs, wsize, hsize, TOPHAT_BLACK); + pixWrite(fileout, pixd, IFF_JFIF_JPEG); + pixDestroy(&pixd); +#endif + + + /* ---------- Speed ---------- */ +#if 0 + startTimer(); + pixd = pixCloseGray(pixs, wsize, hsize); + lept_stderr(" Speed is %6.2f MPix/sec\n", + (l_float32)(4 * w * h) / (1000000. * stopTimer())); + pixWrite(fileout, pixd, IFF_PNG); +#endif + + pixDestroy(&pixs); + return 0; +} + + diff --git a/leptonica/prog/grayquant_reg.c b/leptonica/prog/grayquant_reg.c new file mode 100644 index 00000000..85c79ed7 --- /dev/null +++ b/leptonica/prog/grayquant_reg.c @@ -0,0 +1,398 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * grayquant_reg.c + * + * Tests gray thresholding to 1, 2 and 4 bpp, with and without colormaps + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + +static const l_int32 THRESHOLD = 130; + /* nlevels for 4 bpp output; anything between 2 and 16 is allowed */ +static const l_int32 NLEVELS = 4; + + +int main(int argc, + char **argv) +{ +const char *str; +l_int32 index, w, h; +BOX *box; +PIX *pixs, *pix1, *pix2, *pix3, *pix4, *pix5, *pix6; +PIXA *pixa; +PIXCMAP *cmap; +L_REGPARAMS *rp; + + if (regTestSetup(argc, argv, &rp)) + return 1; + + /* ------------------------------------------------------------- */ + + pixs = pixRead("test8.jpg"); + pixa = pixaCreate(0); + pixaAddPix(pixa, pixs, L_INSERT); + + /* threshold to 1 bpp */ + pix1 = pixThresholdToBinary(pixs, THRESHOLD); + pixaAddPix(pixa, pix1, L_INSERT); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 0 */ + + /* dither to 2 bpp, with and without colormap */ + pix1 = pixDitherTo2bpp(pixs, 1); + pix2 = pixDitherTo2bpp(pixs, 0); + pix3 = pixConvertGrayToColormap(pix2); + pixaAddPix(pixa, pix1, L_INSERT); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 1 */ + pixaAddPix(pixa, pix2, L_INSERT); + regTestWritePixAndCheck(rp, pix2, IFF_PNG); /* 2 */ + pixaAddPix(pixa, pix3, L_INSERT); + regTestWritePixAndCheck(rp, pix3, IFF_PNG); /* 3 */ + if (rp->display) pixcmapWriteStream(stderr, pixGetColormap(pix3)); + regTestComparePix(rp, pix1, pix3); /* 4 */ + + /* threshold to 2 bpp, with and without colormap */ + pix1 = pixThresholdTo2bpp(pixs, 4, 1); + pix2 = pixThresholdTo2bpp(pixs, 4, 0); + pix3 = pixConvertGrayToColormap(pix2); + pixaAddPix(pixa, pix1, L_INSERT); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 5 */ + pixaAddPix(pixa, pix2, L_INSERT); + regTestWritePixAndCheck(rp, pix2, IFF_PNG); /* 6 */ + pixaAddPix(pixa, pix3, L_INSERT); + regTestWritePixAndCheck(rp, pix3, IFF_PNG); /* 7 */ + if (rp->display) pixcmapWriteStream(stderr, pixGetColormap(pix3)); + regTestComparePix(rp, pix1, pix3); /* 8 */ + + pix1 = pixThresholdTo2bpp(pixs, 3, 1); + pix2 = pixThresholdTo2bpp(pixs, 3, 0); + pixaAddPix(pixa, pix1, L_INSERT); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 9 */ + pixaAddPix(pixa, pix2, L_INSERT); + regTestWritePixAndCheck(rp, pix2, IFF_PNG); /* 10 */ + + /* threshold to 4 bpp, with and without colormap */ + pix1 = pixThresholdTo4bpp(pixs, 9, 1); + pix2 = pixThresholdTo4bpp(pixs, 9, 0); + pix3 = pixConvertGrayToColormap(pix2); + pixaAddPix(pixa, pix1, L_INSERT); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 11 */ + pixaAddPix(pixa, pix2, L_INSERT); + regTestWritePixAndCheck(rp, pix2, IFF_PNG); /* 12 */ + pixaAddPix(pixa, pix3, L_INSERT); + regTestWritePixAndCheck(rp, pix3, IFF_PNG); /* 13 */ + if (rp->display) pixcmapWriteStream(stderr, pixGetColormap(pix3)); + + /* threshold on 8 bpp, with and without colormap */ + pix1 = pixThresholdOn8bpp(pixs, 9, 1); + pix2 = pixThresholdOn8bpp(pixs, 9, 0); + pix3 = pixConvertGrayToColormap(pix2); + pixaAddPix(pixa, pix1, L_INSERT); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 14 */ + pixaAddPix(pixa, pix2, L_INSERT); + regTestWritePixAndCheck(rp, pix2, IFF_PNG); /* 15 */ + pixaAddPix(pixa, pix3, L_INSERT); + regTestWritePixAndCheck(rp, pix3, IFF_PNG); /* 16 */ + if (rp->display) pixcmapWriteStream(stderr, pixGetColormap(pix3)); + regTestComparePix(rp, pix1, pix3); /* 17 */ + + /* Optional display */ + if (rp->display) { + lept_mkdir("lept/gquant"); + pix1 = pixaDisplayTiled(pixa, 2000, 0, 20); + pixDisplay(pix1, 100, 100); + pixWrite("/tmp/lept/gquant/mosaic1.png", pix1, IFF_PNG); + pixDestroy(&pix1); + } + pixaDestroy(&pixa); + + /* ------------------------------------------------------------- */ + + pixs = pixRead("test8.jpg"); + pixa = pixaCreate(0); + pixaAddPix(pixa, pixs, L_INSERT); + + /* Highlight 2 bpp with colormap */ + pix1 = pixThresholdTo2bpp(pixs, 3, 1); + pixaAddPix(pixa, pix1, L_COPY); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 18 */ + cmap = pixGetColormap(pix1); + if (rp->display) pixcmapWriteStream(stderr, cmap); + box = boxCreate(278, 35, 122, 50); + pixSetSelectCmap(pix1, box, 2, 255, 255, 100); + boxDestroy(&box); + pixaAddPix(pixa, pix1, L_INSERT); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 19 */ + if (rp->display) pixcmapWriteStream(stderr, cmap); + + /* Test pixThreshold8() */ + pix1 = pixThreshold8(pixs, 1, 2, 1); /* cmap */ + pixaAddPix(pixa, pix1, L_INSERT); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 20 */ + + pix1 = pixThreshold8(pixs, 1, 2, 0); /* no cmap */ + pixaAddPix(pixa, pix1, L_INSERT); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 21 */ + + pix1 = pixThreshold8(pixs, 2, 3, 1); /* highlight one box */ + box = boxCreate(278, 35, 122, 50); + pixSetSelectCmap(pix1, box, 2, 255, 255, 100); + pixaAddPix(pixa, pix1, L_INSERT); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 22 */ + cmap = pixGetColormap(pix1); + if (rp->display) pixcmapWriteStream(stderr, cmap); + boxDestroy(&box); + + + pix1 = pixThreshold8(pixs, 2, 4, 0); /* no cmap */ + pixaAddPix(pixa, pix1, L_INSERT); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 23 */ + + pix1 = pixThreshold8(pixs, 4, 6, 1); /* highlight one box */ + box = boxCreate(278, 35, 122, 50); + pixSetSelectCmap(pix1, box, 5, 255, 255, 100); + pixaAddPix(pixa, pix1, L_INSERT); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 24 */ + cmap = pixGetColormap(pix1); + if (rp->display) pixcmapWriteStream(stderr, cmap); + boxDestroy(&box); + + pix1 = pixThreshold8(pixs, 4, 6, 0); /* no cmap */ + pixaAddPix(pixa, pix1, L_INSERT); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 25 */ + + /* Highlight 4 bpp with 2 colormap entries */ + /* Note: We use 5 levels (0-4) for gray. */ + /* 5 & 6 are used for highlight color. */ + pix1 = pixThresholdTo4bpp(pixs, 5, 1); + cmap = pixGetColormap(pix1); + pixcmapGetIndex(cmap, 255, 255, 255, &index); + box = boxCreate(278, 35, 122, 50); + pixSetSelectCmap(pix1, box, index, 255, 255, 100); /* use index 5 */ + pixaAddPix(pixa, pix1, L_COPY); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 26 */ + boxDestroy(&box); + box = boxCreate(4, 6, 157, 33); + pixSetSelectCmap(pix1, box, index, 100, 255, 255); /* use index 6 */ + pixaAddPix(pixa, pix1, L_INSERT); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 27 */ + boxDestroy(&box); + if (rp->display) pixcmapWriteStream(stderr, cmap); + + /* Optional display */ + if (rp->display) { + pix1 = pixaDisplayTiled(pixa, 2000, 0, 20); + pixDisplay(pix1, 200, 100); + pixWrite("/tmp/lept/gquant/mosaic2.png", pix1, IFF_PNG); + pixDestroy(&pix1); + } + pixaDestroy(&pixa); + + /* ------------------------------------------------------------- */ + + pixs = pixRead("feyn.tif"); + pixa = pixaCreate(0); + + /* Comparison 8 bpp jpeg with 2 bpp (highlight) */ + pix1 = pixScaleToGray4(pixs); + pix2 = pixReduceRankBinaryCascade(pixs, 2, 2, 0, 0); + pix3 = pixThresholdTo2bpp(pix1, 3, 1); + box = boxCreate(175, 208, 228, 88); + pixaAddPix(pixa, pix1, L_INSERT); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 28 */ + pixaAddPix(pixa, pix2, L_INSERT); + regTestWritePixAndCheck(rp, pix2, IFF_PNG); /* 29 */ + pixSetSelectCmap(pix3, box, 2, 255, 255, 100); + pixaAddPix(pixa, pix3, L_INSERT); + regTestWritePixAndCheck(rp, pix3, IFF_PNG); /* 30 */ + cmap = pixGetColormap(pix3); + if (rp->display) pixcmapWriteStream(stderr, cmap); + boxDestroy(&box); + + /* Thresholding to 4 bpp (highlight); use pix1 from above */ + pix2 = pixThresholdTo4bpp(pix1, NLEVELS, 1); + box = boxCreate(175, 208, 228, 83); + pixSetSelectCmap(pix2, box, NLEVELS - 1, 255, 255, 100); + boxDestroy(&box); + box = boxCreate(232, 298, 110, 25); + pixSetSelectCmap(pix2, box, NLEVELS - 1, 100, 255, 255); + boxDestroy(&box); + box = boxCreate(21, 698, 246, 82); + pixSetSelectCmap(pix2, box, NLEVELS - 1, 225, 100, 255); + boxDestroy(&box); + pixaAddPix(pixa, pix2, L_INSERT); + regTestWritePixAndCheck(rp, pix2, IFF_PNG); /* 31 */ + cmap = pixGetColormap(pix2); + if (rp->display) pixcmapWriteStream(stderr, cmap); + pix3 = pixReduceRankBinaryCascade(pixs, 2, 2, 0, 0); + pixaAddPix(pixa, pix3, L_INSERT); + regTestWritePixAndCheck(rp, pix3, IFF_PNG); /* 32 */ + + /* Thresholding to 4 bpp at 2, 3, 4, 5 and 6 levels */ + box = boxCreate(25, 202, 136, 37); + pix2 = pixClipRectangle(pix1, box, NULL); + pix3 = pixScale(pix2, 6., 6.); + pixaAddPix(pixa, pix3, L_INSERT); + regTestWritePixAndCheck(rp, pix3, IFF_PNG); /* 33 */ + pixGetDimensions(pix3, &w, &h, NULL); + pix4 = pixCreate(w, 6 * h, 8); + pixRasterop(pix4, 0, 0, w, h, PIX_SRC, pix3, 0, 0); + pixDestroy(&pix2); + boxDestroy(&box); + + pix5 = pixThresholdTo4bpp(pix3, 6, 1); + pix6 = pixRemoveColormap(pix5, REMOVE_CMAP_TO_GRAYSCALE); + pixRasterop(pix4, 0, h, w, h, PIX_SRC, pix6, 0, 0); + pixaAddPix(pixa, pix5, L_INSERT); + regTestWritePixAndCheck(rp, pix5, IFF_PNG); /* 34 */ + pixDestroy(&pix6); + + pix5 = pixThresholdTo4bpp(pix3, 5, 1); + pix6 = pixRemoveColormap(pix5, REMOVE_CMAP_TO_GRAYSCALE); + pixRasterop(pix4, 0, 2 * h, w, h, PIX_SRC, pix6, 0, 0); + pixaAddPix(pixa, pix5, L_INSERT); + regTestWritePixAndCheck(rp, pix5, IFF_PNG); /* 35 */ + pixDestroy(&pix6); + + pix5 = pixThresholdTo4bpp(pix3, 4, 1); + pix6 = pixRemoveColormap(pix5, REMOVE_CMAP_TO_GRAYSCALE); + pixRasterop(pix4, 0, 3 * h, w, h, PIX_SRC, pix6, 0, 0); + pixaAddPix(pixa, pix5, L_INSERT); + regTestWritePixAndCheck(rp, pix5, IFF_PNG); /* 36 */ + pixDestroy(&pix6); + + pix5 = pixThresholdTo4bpp(pix3, 3, 1); + pix6 = pixRemoveColormap(pix5, REMOVE_CMAP_TO_GRAYSCALE); + pixRasterop(pix4, 0, 4 * h, w, h, PIX_SRC, pix6, 0, 0); + pixaAddPix(pixa, pix5, L_INSERT); + regTestWritePixAndCheck(rp, pix5, IFF_PNG); /* 37 */ + pixDestroy(&pix6); + + pix5 = pixThresholdTo4bpp(pix3, 2, 1); + pix6 = pixRemoveColormap(pix5, REMOVE_CMAP_TO_GRAYSCALE); + pixRasterop(pix4, 0, 5 * h, w, h, PIX_SRC, pix6, 0, 0); + pixaAddPix(pixa, pix5, L_INSERT); + regTestWritePixAndCheck(rp, pix5, IFF_PNG); /* 38 */ + pixDestroy(&pix6); + pixaAddPix(pixa, pix4, L_INSERT); + regTestWritePixAndCheck(rp, pix4, IFF_PNG); /* 39 */ + + /* Optional display */ + if (rp->display) { + pix1 = pixaDisplayTiled(pixa, 2000, 0, 20); + pixDisplay(pix1, 300, 100); + pixWrite("/tmp/lept/gquant/mosaic3.png", pix1, IFF_PNG); + pixDestroy(&pix1); + } + pixaDestroy(&pixa); + pixDestroy(&pixs); + + /* ------------------------------------------------------------- */ + + /* Thresholding with fixed and arbitrary bin boundaries */ + pixs = pixRead("stampede2.jpg"); + pixa = pixaCreate(0); + + pixaAddPix(pixa, pixs, L_INSERT); + regTestWritePixAndCheck(rp, pixs, IFF_PNG); /* 40 */ + pix1 = pixThresholdTo4bpp(pixs, 5, 1); + pixaAddPix(pixa, pix1, L_INSERT); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 41 */ + pix1 = pixThresholdTo4bpp(pixs, 7, 1); + pixaAddPix(pixa, pix1, L_INSERT); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 42 */ + cmap = pixGetColormap(pix1); + if (rp->display) pixcmapWriteStream(stderr, cmap); + pix1 = pixThresholdTo4bpp(pixs, 11, 1); + pixaAddPix(pixa, pix1, L_INSERT); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 43 */ + + str = "45 75 115 185"; + pix1 = pixThresholdGrayArb(pixs, str, 8, 0, 0, 0); + pixaAddPix(pixa, pix1, L_INSERT); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 44 */ + str = "38 65 85 115 160 210"; + pix1 = pixThresholdGrayArb(pixs, str, 8, 0, 1, 1); + pixaAddPix(pixa, pix1, L_INSERT); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 45 */ + cmap = pixGetColormap(pix1); + if (rp->display) pixcmapWriteStream(stderr, cmap); + str = "38 60 75 90 110 130 155 185 208 239"; + pix1 = pixThresholdGrayArb(pixs, str, 8, 0, 0, 0); + pixaAddPix(pixa, pix1, L_INSERT); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 46 */ + str = "45 75 115 185"; + pix1 = pixThresholdGrayArb(pixs, str, 0, 1, 0, 1); + pixaAddPix(pixa, pix1, L_INSERT); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 47 */ + str = "38 65 85 115 160 210"; + pix1 = pixThresholdGrayArb(pixs, str, 0, 1, 0, 1); + pixaAddPix(pixa, pix1, L_INSERT); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 48 */ + cmap = pixGetColormap(pix1); + if (rp->display) pixcmapWriteStream(stderr, cmap); + str = "38 60 75 90 110 130 155 185 208 239"; + pix1 = pixThresholdGrayArb(pixs, str, 4, 1, 0, 1); + pixaAddPix(pixa, pix1, L_INSERT); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 49 */ + + /* Optional display */ + if (rp->display) { + pix1 = pixaDisplayTiled(pixa, 2000, 0, 20); + pixDisplay(pix1, 400, 100); + pixWrite("/tmp/lept/gquant/mosaic4.png", pix1, IFF_PNG); + pixDestroy(&pix1); + } + pixaDestroy(&pixa); + + if (rp->display) { + /* Upscale 2x and threshold to 1 bpp */ + pixs = pixRead("test8.jpg"); + startTimer(); + pix1 = pixScaleGray2xLIThresh(pixs, THRESHOLD); + lept_stderr(" time for scale/dither = %7.3f sec\n", stopTimer()); + pixWrite("/tmp/lept/gquant/upscale1.png", pix1, IFF_PNG); + pixDisplay(pix1, 0, 500); + pixDestroy(&pix1); + + /* Upscale 4x and threshold to 1 bpp */ + startTimer(); + pix1 = pixScaleGray4xLIThresh(pixs, THRESHOLD); + lept_stderr(" time for scale/dither = %7.3f sec\n", stopTimer()); + pixWrite("/tmp/lept/gquant/upscale2.png", pix1, IFF_PNG); + pixDisplay(pix1, 700, 500); + pixDestroy(&pix1); + pixDestroy(&pixs); + } + + return regTestCleanup(rp); +} + diff --git a/leptonica/prog/graytext.png b/leptonica/prog/graytext.png Binary files differnew file mode 100644 index 00000000..0839d7c9 --- /dev/null +++ b/leptonica/prog/graytext.png diff --git a/leptonica/prog/greencover.jpg b/leptonica/prog/greencover.jpg Binary files differnew file mode 100644 index 00000000..dd320d48 --- /dev/null +++ b/leptonica/prog/greencover.jpg diff --git a/leptonica/prog/hardlight1_1.jpg b/leptonica/prog/hardlight1_1.jpg Binary files differnew file mode 100644 index 00000000..8c355404 --- /dev/null +++ b/leptonica/prog/hardlight1_1.jpg diff --git a/leptonica/prog/hardlight1_2.jpg b/leptonica/prog/hardlight1_2.jpg Binary files differnew file mode 100644 index 00000000..68086611 --- /dev/null +++ b/leptonica/prog/hardlight1_2.jpg diff --git a/leptonica/prog/hardlight2_1.jpg b/leptonica/prog/hardlight2_1.jpg Binary files differnew file mode 100644 index 00000000..8692dcbc --- /dev/null +++ b/leptonica/prog/hardlight2_1.jpg diff --git a/leptonica/prog/hardlight2_2.jpg b/leptonica/prog/hardlight2_2.jpg Binary files differnew file mode 100644 index 00000000..41dabea6 --- /dev/null +++ b/leptonica/prog/hardlight2_2.jpg diff --git a/leptonica/prog/hardlight_reg.c b/leptonica/prog/hardlight_reg.c new file mode 100644 index 00000000..6b48e900 --- /dev/null +++ b/leptonica/prog/hardlight_reg.c @@ -0,0 +1,140 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * hardlight_reg.c + * + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + +static void TestHardlight(const char *file1, const char *file2, + L_REGPARAMS *rp); + +int main(int argc, + char **argv) +{ +L_REGPARAMS *rp; + + if (regTestSetup(argc, argv, &rp)) + return 1; + + TestHardlight("hardlight1_1.jpg", "hardlight1_2.jpg", rp); + TestHardlight("hardlight2_1.jpg", "hardlight2_2.jpg", rp); + return regTestCleanup(rp); +} + +void +TestHardlight(const char *file1, + const char *file2, + L_REGPARAMS *rp) +{ +PIX *pixs1, *pixs2, *pix1, *pix2, *pixd; +PIXA *pixa; +PIXAA *paa; + + /* Read in images */ + pixs1 = pixRead(file1); + pixs2 = pixRead(file2); + paa = pixaaCreate(0); + + /* ---------- Test not-in-place; no colormaps ----------- */ + pixa = pixaCreate(0); + pixaAddPix(pixa, pixs1, L_COPY); + pixaAddPix(pixa, pixs2, L_COPY); + pixaaAddPixa(paa, pixa, L_INSERT); + pixd = pixBlendHardLight(NULL, pixs1, pixs2, 0, 0, 1.0); + regTestWritePixAndCheck(rp, pixd, IFF_PNG); + pixa = pixaCreate(0); + pixaAddPix(pixa, pixd, L_INSERT); + + pix2 = pixConvertTo32(pixs2); + pixd = pixBlendHardLight(NULL, pixs1, pix2, 0, 0, 1.0); + regTestWritePixAndCheck(rp, pixd, IFF_PNG); + pixaAddPix(pixa, pixd, L_INSERT); + pixDestroy(&pix2); + + pixd = pixBlendHardLight(NULL, pixs2, pixs1, 0, 0, 1.0); + pixaAddPix(pixa, pixd, L_INSERT); + pixaaAddPixa(paa, pixa, L_INSERT); + + /* ---------- Test not-in-place; colormaps ----------- */ + pixa = pixaCreate(0); + pix1 = pixMedianCutQuant(pixs1, 0); + if (pixGetDepth(pixs2) == 8) + pix2 = pixConvertGrayToColormap8(pixs2, 8); + else + pix2 = pixMedianCutQuant(pixs2, 0); + pixaAddPix(pixa, pix1, L_COPY); + pixaAddPix(pixa, pix2, L_COPY); + pixaaAddPixa(paa, pixa, L_INSERT); + + pixa = pixaCreate(0); + pixd = pixBlendHardLight(NULL, pix1, pixs2, 0, 0, 1.0); + regTestWritePixAndCheck(rp, pixd, IFF_PNG); + pixaAddPix(pixa, pixd, L_INSERT); + + pixd = pixBlendHardLight(NULL, pix1, pix2, 0, 0, 1.0); + regTestWritePixAndCheck(rp, pixd, IFF_PNG); + pixaAddPix(pixa, pixd, L_INSERT); + + pixd = pixBlendHardLight(NULL, pix2, pix1, 0, 0, 1.0); + regTestWritePixAndCheck(rp, pixd, IFF_PNG); + pixaAddPix(pixa, pixd, L_INSERT); + pixaaAddPixa(paa, pixa, L_INSERT); + pixDestroy(&pix1); + pixDestroy(&pix2); + + /* ---------- Test in-place; no colormaps ----------- */ + pixa = pixaCreate(0); + pixBlendHardLight(pixs1, pixs1, pixs2, 0, 0, 1.0); + regTestWritePixAndCheck(rp, pixs1, IFF_PNG); + pixaAddPix(pixa, pixs1, L_INSERT); + + pixs1 = pixRead(file1); + pix2 = pixConvertTo32(pixs2); + pixBlendHardLight(pixs1, pixs1, pix2, 0, 0, 1.0); + regTestWritePixAndCheck(rp, pixs1, IFF_PNG); + pixaAddPix(pixa, pixs1, L_INSERT); + pixDestroy(&pix2); + + pixs1 = pixRead(file1); + pixBlendHardLight(pixs2, pixs2, pixs1, 0, 0, 1.0); + regTestWritePixAndCheck(rp, pixs2, IFF_PNG); + pixaAddPix(pixa, pixs2, L_INSERT); + pixaaAddPixa(paa, pixa, L_INSERT); + pixDestroy(&pixs1); + + pixd = pixaaDisplayByPixa(paa, 4, 1.0, 20, 20, 0); + regTestWritePixAndCheck(rp, pixd, IFF_PNG); + pixDisplayWithTitle(pixd, 100, 100, NULL, rp->display); + pixDestroy(&pixd); + pixaaDestroy(&paa); +} diff --git a/leptonica/prog/harmoniam-11.tif b/leptonica/prog/harmoniam-11.tif Binary files differnew file mode 100644 index 00000000..427f1360 --- /dev/null +++ b/leptonica/prog/harmoniam-11.tif diff --git a/leptonica/prog/harmoniam100-11.png b/leptonica/prog/harmoniam100-11.png Binary files differnew file mode 100644 index 00000000..ba3f575e --- /dev/null +++ b/leptonica/prog/harmoniam100-11.png diff --git a/leptonica/prog/hash_reg.c b/leptonica/prog/hash_reg.c new file mode 100644 index 00000000..589bb561 --- /dev/null +++ b/leptonica/prog/hash_reg.c @@ -0,0 +1,471 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * hash_reg.c + * + * Tests hashing functions for strings and points, and the use of them with: + * * sets (underlying rbtree implementation for sorting) + * * hash maps (underlying dnaHash implementation for accessing) + * + * For sets, it's important to use good 64-bit hashes to ensure that + * collisions are very rare. With solid randomization, you expect + * that a collision is likely with 2^32 or more hashed entities. + * The probability of a collision goes as n^2, so with 10M entities, + * the collision probabililty is about 10^-5. + * + * For the dna hashing, a faster but weaker hash function is used. + * The hash should do a reasonable job of randomizing the lower order + * bits corresponding to the prime number used with the mod function + * for assigning to buckets. (To the extent that those bits are not + * randomized, the calculation will run slower because bucket + * occupancy will not be random, but the result will still be exact.) + * Hash collisions in the key are allowed because the dna in + * the selected bucket stores integers into arrays (of pts or strings, + * for example), and not keys. The input point or string is hashed to + * a bucket (a dna), which is then traversed, and each stored value + * (an index) is used check if the point or string is in the associated + * array at that location. + * + * Also tests similar functions directly (without hashing the number) for dna. + * This will allow handling of both float64 and large integers that are + * accurately represented by float64. + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + +static SARRAY *BuildShortStrings(l_int32 nchars, l_int32 add_dups); +static PTA *BuildPointSet(l_int32 w, l_int32 h, l_int32 add_dups); + + +l_int32 main(int argc, + char **argv) +{ +l_int32 ncolors, c1, c2, c3, s1; +L_ASET *set; +L_DNA *da1, *da2, *da3, *da4, *da5, *da6, *da7, *da8, *dav, *dac; +L_DNAHASH *dahash; +GPLOT *gplot; +NUMA *nav, *nac; +PTA *pta1, *pta2, *pta3; +SARRAY *sa1, *sa2, *sa3, *sa4; +PIX *pix1; +L_REGPARAMS *rp; + + if (regTestSetup(argc, argv, &rp)) + return 1; + + lept_mkdir("lept/hash"); + + /* Test string hashing with aset */ + sa1 = BuildShortStrings(3, 0); + sa2 = BuildShortStrings(3, 1); + c1 = sarrayGetCount(sa1); + c2 = sarrayGetCount(sa2); + regTestCompareValues(rp, 18278, c1, 0); /* 0 */ + regTestCompareValues(rp, 20982, c2, 0); /* 1 */ + if (rp->display) { + lept_stderr("Set results with string hashing:\n"); + lept_stderr(" size with unique strings: %d\n", c1); + lept_stderr(" size with dups: %d\n", c2); + } + startTimer(); + set = l_asetCreateFromSarray(sa2); + s1 = l_asetSize(set); + regTestCompareValues(rp, 18278, s1, 0); /* 2 */ + if (rp->display) { + lept_stderr(" time to make set: %5.3f sec\n", stopTimer()); + lept_stderr(" size of set without dups: %d\n", s1); + } + l_asetDestroy(&set); + startTimer(); + sa3 = sarrayRemoveDupsByAset(sa2); + c1 = sarrayGetCount(sa3); + regTestCompareValues(rp, 18278, c1, 0); /* 3 */ + if (rp->display) { + lept_stderr(" time to remove dups: %5.3f sec\n", stopTimer()); + lept_stderr(" size without dups = %d\n", c1); + } + startTimer(); + sa4 = sarrayIntersectionByAset(sa1, sa2); + c1 = sarrayGetCount(sa4); + regTestCompareValues(rp, 18278, c1, 0); /* 4 */ + if (rp->display) { + lept_stderr(" time to intersect: %5.3f sec\n", stopTimer()); + lept_stderr(" intersection size = %d\n", c1); + } + sarrayDestroy(&sa3); + sarrayDestroy(&sa4); + + /* Test sarray set operations with dna hash. + * We use the same hash function as is used with aset. */ + if (rp->display) { + lept_stderr("\nDna hash results for sarray:\n"); + lept_stderr(" size with unique strings: %d\n", sarrayGetCount(sa1)); + lept_stderr(" size with dups: %d\n", sarrayGetCount(sa2)); + } + startTimer(); + dahash = l_dnaHashCreateFromSarray(sa2); + s1 = l_dnaHashGetTotalCount(dahash); + regTestCompareValues(rp, 20982, s1, 0); /* 5 */ + if (rp->display) { + lept_stderr(" time to make hashmap: %5.3f sec\n", stopTimer()); + lept_stderr(" entries in hashmap with dups: %d\n", s1); + } + l_dnaHashDestroy(&dahash); + startTimer(); + sarrayRemoveDupsByHash(sa2, &sa3, NULL); + c1 = sarrayGetCount(sa3); + regTestCompareValues(rp, 18278, c1, 0); /* 6 */ + if (rp->display) { + lept_stderr(" time to remove dups: %5.3f sec\n", stopTimer()); + lept_stderr(" size without dups = %d\n", c1); + } + startTimer(); + sa4 = sarrayIntersectionByHash(sa1, sa2); + c1 = sarrayGetCount(sa4); + regTestCompareValues(rp, 18278, c1, 0); /* 7 */ + if (rp->display) { + lept_stderr(" time to intersect: %5.3f sec\n", stopTimer()); + lept_stderr(" intersection size = %d\n", c1); + } + sarrayDestroy(&sa3); + sarrayDestroy(&sa4); + sarrayDestroy(&sa1); + sarrayDestroy(&sa2); + + /* Test point hashing with aset. + * Enter all points within a 300 x 300 image in pta1, and include + * 18,000 duplicates in pta2. With this pt hashing function, + * there are no hash collisions among any of the 400 million pixel + * locations in a 20000 x 20000 image. */ + pta1 = BuildPointSet(300, 300, 0); + pta2 = BuildPointSet(300, 300, 1); + c1 = ptaGetCount(pta1); + c2 = ptaGetCount(pta2); + regTestCompareValues(rp, 90000, c1, 0); /* 8 */ + regTestCompareValues(rp, 108000, c2, 0); /* 9 */ + if (rp->display) { + lept_stderr("\nSet results for pta:\n"); + lept_stderr(" pta1 size with unique points: %d\n", c1); + lept_stderr(" pta2 size with dups: %d\n", c2); + } + startTimer(); + pta3 = ptaRemoveDupsByAset(pta2); + c1 = ptaGetCount(pta3); + regTestCompareValues(rp, 90000, c1, 0); /* 10 */ + if (rp->display) { + lept_stderr(" Time to remove dups: %5.3f sec\n", stopTimer()); + lept_stderr(" size without dups = %d\n", ptaGetCount(pta3)); + } + ptaDestroy(&pta3); + + startTimer(); + pta3 = ptaIntersectionByAset(pta1, pta2); + c1 = ptaGetCount(pta3); + regTestCompareValues(rp, 90000, c1, 0); /* 11 */ + if (rp->display) { + lept_stderr(" Time to intersect: %5.3f sec\n", stopTimer()); + lept_stderr(" intersection size = %d\n", c1); + } + ptaDestroy(&pta1); + ptaDestroy(&pta2); + ptaDestroy(&pta3); + + /* Test pta set operations with dna hash, using the same pt hashing + * function. Although there are no collisions in 20K x 20K images, + * the dna hash implementation works properly even if there are some. */ + pta1 = BuildPointSet(400, 400, 0); + pta2 = BuildPointSet(400, 400, 1); + c1 = ptaGetCount(pta1); + c2 = ptaGetCount(pta2); + regTestCompareValues(rp, 160000, c1, 0); /* 12 */ + regTestCompareValues(rp, 192000, c2, 0); /* 13 */ + if (rp->display) { + lept_stderr("\nDna hash results for pta:\n"); + lept_stderr(" pta1 size with unique points: %d\n", c1); + lept_stderr(" pta2 size with dups: %d\n", c2); + } + startTimer(); + ptaRemoveDupsByHash(pta2, &pta3, NULL); + c1 = ptaGetCount(pta3); + regTestCompareValues(rp, 160000, c1, 0); /* 14 */ + if (rp->display) { + lept_stderr(" Time to remove dups: %5.3f sec\n", stopTimer()); + lept_stderr(" size without dups = %d\n", c1); + } + ptaDestroy(&pta3); + + startTimer(); + pta3 = ptaIntersectionByHash(pta1, pta2); + c1 = ptaGetCount(pta3); + regTestCompareValues(rp, 160000, c1, 0); /* 15 */ + if (rp->display) { + lept_stderr(" Time to intersect: %5.3f sec\n", stopTimer()); + lept_stderr(" intersection size = %d\n", c1); + } + ptaDestroy(&pta1); + ptaDestroy(&pta2); + ptaDestroy(&pta3); + + /* Test dna set and histo operations using dna hash */ + da1 = l_dnaMakeSequence(0.0, 0.125, 8000); + da2 = l_dnaMakeSequence(300.0, 0.125, 8000); + da3 = l_dnaMakeSequence(600.0, 0.125, 8000); + da4 = l_dnaMakeSequence(900.0, 0.125, 8000); + da5 = l_dnaMakeSequence(1200.0, 0.125, 8000); + l_dnaJoin(da1, da2, 0, -1); + l_dnaJoin(da1, da3, 0, -1); + l_dnaJoin(da1, da4, 0, -1); + l_dnaJoin(da1, da5, 0, -1); + l_dnaRemoveDupsByHash(da1, &da6, &dahash); + l_dnaHashDestroy(&dahash); + c1 = l_dnaGetCount(da1); + c2 = l_dnaGetCount(da6); + regTestCompareValues(rp, 40000, c1, 0); /* 16 */ + regTestCompareValues(rp, 17600, c2, 0); /* 17 */ + if (rp->display) { + lept_stderr("\nDna hash results for dna:\n"); + lept_stderr(" dna size with dups = %d\n", c1); + lept_stderr(" dna size of unique numbers = %d\n", c2); + } + l_dnaMakeHistoByHash(da1, &dahash, &dav, &dac); + nav = l_dnaConvertToNuma(dav); + nac = l_dnaConvertToNuma(dac); + c1 = l_dnaGetCount(dac); + regTestCompareValues(rp, 17600, c1, 0); /* 18 */ + if (rp->display) + lept_stderr(" dna number of histo points = %d\n", c1); + + /* Plot it twice */ + pix1 = gplotGeneralPix2(nav, nac, GPLOT_IMPULSES, "/tmp/lept/hash/histo", + "Histo", NULL, NULL); + gplot = gplotSimpleXY1(nav, nac, GPLOT_IMPULSES, GPLOT_PNG, + "/tmp/lept/hash/histo", "Histo"); + if (rp->display) { + pixDisplay(pix1, 700, 100); + l_fileDisplay("/tmp/lept/hash/histo.png", 700, 600, 1.0); + } + pixDestroy(&pix1); + gplotDestroy(&gplot); + + da7 = l_dnaIntersectionByHash(da2, da3); + c1 = l_dnaGetCount(da2); + c2 = l_dnaGetCount(da3); + c3 = l_dnaGetCount(da7); + regTestCompareValues(rp, 8000, c1, 0); /* 19 */ + regTestCompareValues(rp, 8000, c2, 0); /* 20 */ + regTestCompareValues(rp, 5600, c3, 0); /* 21 */ + if (rp->display) { + lept_stderr(" dna num points: da2 = %d, da3 = %d\n", c1, c2); + lept_stderr(" dna num da2/da3 intersection points = %d\n", c3); + } + l_dnaDestroy(&da1); + l_dnaDestroy(&da2); + l_dnaDestroy(&da3); + l_dnaDestroy(&da4); + l_dnaDestroy(&da5); + l_dnaDestroy(&da6); + l_dnaDestroy(&da7); + l_dnaDestroy(&dac); + l_dnaDestroy(&dav); + l_dnaHashDestroy(&dahash); + numaDestroy(&nav); + numaDestroy(&nac); + + /* Test pixel counting operations with hashmap and ordered map */ + pix1 = pixRead("wet-day.jpg"); + pixCountRGBColorsByHash(pix1, &c1); + pixCountRGBColors(pix1, 1, &c2); + regTestCompareValues(rp, 42427, c1, 0); /* 22 */ + regTestCompareValues(rp, 42427, c2, 0); /* 23 */ + if (rp->display) { + lept_stderr("\nColor count using dna hash: %d\n", c1); + lept_stderr("Color count using amap: %d\n", c2); + } + pixDestroy(&pix1); + + /* Test aset operations on dna. */ + da1 = l_dnaMakeSequence(0, 3, 10000); + da2 = l_dnaMakeSequence(0, 5, 10000); + da3 = l_dnaMakeSequence(0, 7, 10000); + l_dnaJoin(da1, da2, 0, -1); + l_dnaJoin(da1, da3, 0, -1); + set = l_asetCreateFromDna(da1); + c1 = l_dnaGetCount(da1); + c2 = l_asetSize(set); + regTestCompareValues(rp, 30000, c1, 0); /* 24 */ + regTestCompareValues(rp, 25428, c2, 0); /* 25 */ + if (rp->display) { + lept_stderr("\nDna results using set:\n"); + lept_stderr(" da1 count: %d\n", c1); + lept_stderr(" da1 set size: %d\n\n", c2); + } + l_asetDestroy(&set); + + da4 = l_dnaUnionByAset(da2, da3); + set = l_asetCreateFromDna(da4); + c1 = l_dnaGetCount(da4); + c2 = l_asetSize(set); + regTestCompareValues(rp, 18571, c1, 0); /* 26 */ + regTestCompareValues(rp, 18571, c2, 0); /* 27 */ + if (rp->display) { + lept_stderr(" da4 count: %d\n", c1); + lept_stderr(" da4 set size: %d\n\n", c2); + } + l_asetDestroy(&set); + + da5 = l_dnaIntersectionByAset(da1, da2); + set = l_asetCreateFromDna(da5); + c1 = l_dnaGetCount(da5); + c2 = l_asetSize(set); + regTestCompareValues(rp, 10000, c1, 0); /* 28 */ + regTestCompareValues(rp, 10000, c2, 0); /* 29 */ + if (rp->display) { + lept_stderr(" da5 count: %d\n", c1); + lept_stderr(" da5 set size: %d\n\n", c2); + } + l_asetDestroy(&set); + + da6 = l_dnaMakeSequence(100000, 11, 5000); + l_dnaJoin(da6, da1, 0, -1); + set = l_asetCreateFromDna(da6); + c1 = l_dnaGetCount(da6); + c2 = l_asetSize(set); + regTestCompareValues(rp, 35000, c1, 0); /* 30 */ + regTestCompareValues(rp, 30428, c2, 0); /* 31 */ + if (rp->display) { + lept_stderr(" da6 count: %d\n", c1); + lept_stderr(" da6 set size: %d\n\n", c2); + } + l_asetDestroy(&set); + + da7 = l_dnaIntersectionByAset(da6, da3); + set = l_asetCreateFromDna(da7); + c1 = l_dnaGetCount(da7); + c2 = l_asetSize(set); + regTestCompareValues(rp, 10000, c1, 0); /* 32 */ + regTestCompareValues(rp, 10000, c2, 0); /* 33 */ + if (rp->display) { + lept_stderr(" da7 count: %d\n", c1); + lept_stderr(" da7 set size: %d\n\n", c2); + } + l_asetDestroy(&set); + + da8 = l_dnaRemoveDupsByAset(da1); + c1 = l_dnaGetCount(da8); + regTestCompareValues(rp, 25428, c1, 0); /* 34 */ + if (rp->display) + lept_stderr(" da8 count: %d\n\n", c1); + l_dnaDestroy(&da1); + l_dnaDestroy(&da2); + l_dnaDestroy(&da3); + l_dnaDestroy(&da4); + l_dnaDestroy(&da5); + l_dnaDestroy(&da6); + l_dnaDestroy(&da7); + l_dnaDestroy(&da8); + + return regTestCleanup(rp); +} + + + /* Build all possible strings, up to a max of 5 roman alphabet characters */ +static SARRAY * +BuildShortStrings(l_int32 nchars, /* 3, 4 or 5 */ + l_int32 add_dups) +{ +char buf[64]; +l_int32 i, j, k, l, m; +l_uint64 hash; +SARRAY *sa; + + sa = sarrayCreate(1000); + for (i = 0; i < 26; i++) { + snprintf(buf, sizeof(buf), "%c", i + 0x61); + sarrayAddString(sa, buf, L_COPY); + for (j = 0; j < 26; j++) { + snprintf(buf, sizeof(buf), "%c%c", i + 0x61, j + 0x61); + sarrayAddString(sa, buf, L_COPY); + for (k = 0; k < 26; k++) { + snprintf(buf, sizeof(buf), "%c%c%c", i + 0x61, j + 0x61, + k + 0x61); + sarrayAddString(sa, buf, L_COPY); + if (add_dups && k < 4) /* add redundant strings */ + sarrayAddString(sa, buf, L_COPY); + if (nchars > 3) { + for (l = 0; l < 26; l++) { + snprintf(buf, sizeof(buf), "%c%c%c%c", i + 0x61, + j + 0x61, k + 0x61, l + 0x61); + sarrayAddString(sa, buf, L_COPY); + if (add_dups && l < 4) /* add redundant strings */ + sarrayAddString(sa, buf, L_COPY); + if (nchars > 4) { + for (m = 0; m < 26; m++) { + snprintf(buf, sizeof(buf), "%c%c%c%c%c", + i + 0x61, j + 0x61, k + 0x61, + l + 0x61, m + 0x61); + sarrayAddString(sa, buf, L_COPY); + if (!add_dups && i == 17 && j == 12 && + k == 4 && l == 21) { + l_hashStringToUint64(buf, &hash); + lept_stderr(" %llx\n", hash); + } + if (add_dups && m < 4) /* add redundant */ + sarrayAddString(sa, buf, L_COPY); + } + } + } + } + } + } + } + + return sa; +} + +static PTA * +BuildPointSet(l_int32 w, l_int32 h, l_int32 add_dups) +{ +l_int32 i, j; +PTA *pta; + + pta = ptaCreate(w * h); + for (i = 0; i < h; i++) { + for (j = 0; j < w; j++) + ptaAddPt(pta, j, i); + if (add_dups) { /* extra (0.2 * w * h) points */ + for (j = 0.4 * w; j < 0.6 * w; j++) + ptaAddPt(pta, j, i); + } + } + + return pta; +} diff --git a/leptonica/prog/heap_reg.c b/leptonica/prog/heap_reg.c new file mode 100644 index 00000000..0ef077e9 --- /dev/null +++ b/leptonica/prog/heap_reg.c @@ -0,0 +1,155 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * heap_reg.c + * + * Tests the heap utility. + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + +struct HeapElement { + l_float32 distance; + l_int32 x; + l_int32 y; +}; +typedef struct HeapElement HEAPEL; + +static const l_int32 NELEM = 50; + +NUMA *ExtractNumaFromHeap(L_HEAP *lh); + + +int main(int argc, + char **argv) +{ +l_uint8 *data; +l_int32 i; +size_t size; +l_float32 frand, fval; +HEAPEL *item; +NUMA *na1, *na2, *na3, *na4, *na5; +L_HEAP *lh; +L_REGPARAMS *rp; + + if (regTestSetup(argc, argv, &rp)) + return 1; + + lept_mkdir("lept/heap"); + + /* Make a numa of random numbers */ + na1 = numaCreate(5); + for (i = 0; i < NELEM; i++) { + frand = (l_float32)rand() / (l_float32)RAND_MAX; + numaAddNumber(na1, frand); + } + numaWriteMem(&data, &size, na1); + regTestWriteDataAndCheck(rp, data, size, "na"); /* 0 */ + lept_free(data); + + /* Make an array of HEAPELs with the same numbers */ + lh = lheapCreate(5, L_SORT_INCREASING); + for (i = 0; i < NELEM; i++) { + numaGetFValue(na1, i, &fval); + item = (HEAPEL *)lept_calloc(1, sizeof(HEAPEL)); + item->distance = fval; + lheapAdd(lh, item); + } + + /* Re-sort for strict order */ + lheapSortStrictOrder(lh); + na2 = ExtractNumaFromHeap(lh); + numaWriteMem(&data, &size, na2); + regTestWriteDataAndCheck(rp, data, size, "na"); /* 1 */ + lept_free(data); + + /* Switch the direction and re-sort strict order */ + lh->direction = L_SORT_DECREASING; + lheapSortStrictOrder(lh); + na3 = ExtractNumaFromHeap(lh); + numaWriteMem(&data, &size, na3); + regTestWriteDataAndCheck(rp, data, size, "na"); /* 2 */ + lept_free(data); + + /* Switch direction again and re-sort strict sort */ + lh->direction = L_SORT_INCREASING; + lheapSortStrictOrder(lh); + na4 = ExtractNumaFromHeap(lh); + numaWriteMem(&data, &size, na4); + regTestWriteDataAndCheck(rp, data, size, "na"); /* 3 */ + lept_free(data); + + /* Switch direction again and re-sort strict sort */ + lh->direction = L_SORT_DECREASING; + lheapSortStrictOrder(lh); + na5 = ExtractNumaFromHeap(lh); + numaWriteMem(&data, &size, na5); + regTestWriteDataAndCheck(rp, data, size, "na"); /* 4 */ + lept_free(data); + + regTestCompareFiles(rp, 1, 3); /* 5 */ + regTestCompareFiles(rp, 2, 4); /* 6 */ + + /* Remove the elements, one at a time */ + for (i = 0; lheapGetCount(lh) > 0; i++) { + item = (HEAPEL *)lheapRemove(lh); + if (rp->display) + lept_stderr("item %d: %f\n", i, item->distance); + lept_free(item); + } + + lheapDestroy(&lh, 1); + numaDestroy(&na1); + numaDestroy(&na2); + numaDestroy(&na3); + numaDestroy(&na4); + numaDestroy(&na5); + return regTestCleanup(rp); +} + + + /* This just uses the heap array. It will only be + ordered if the heap is in strict ordering. */ +NUMA * +ExtractNumaFromHeap(L_HEAP *lh) +{ +l_int32 i, n; +HEAPEL *item; +NUMA *na; + + n = lheapGetCount(lh); + na = numaCreate(0); + for (i = 0; i < n; i++) { + item = (HEAPEL *)lh->array[i]; + numaAddNumber(na, item->distance); + } + return na; +} diff --git a/leptonica/prog/histoduptest.c b/leptonica/prog/histoduptest.c new file mode 100644 index 00000000..db3ad1de --- /dev/null +++ b/leptonica/prog/histoduptest.c @@ -0,0 +1,267 @@ +/*====================================================================* + - 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. + *====================================================================*/ +/* + * histoduptest.c + * + * This demonstrates two things: + * (1) Histogram method of comparing two grayscale images for similarity. + * High score (> 0.5) means they're likely to be the same image + * (2) The morphological method, based on horizontal lines, for + * deciding if a grayscale image is text or non-text. + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "string.h" +#include "allheaders.h" + + +#define TEST1 1 +#define TEST2 1 +#define TEST3 1 +#define TEST4 1 +#define TEST5 1 + +l_int32 main(int argc, + char **argv) +{ +l_uint8 *bytea1, *bytea2; +l_int32 i, j, n, maxi, maxj, istext, w1, h1, w2, h2; +l_int32 debug; +size_t size1, size2; +l_float32 score, maxscore; +l_float32 *scores; +BOX *box1, *box2; +NUMA *nai; +NUMAA *naa1, *naa2, *naa3, *naa4; +PIX *pix1, *pix2; +PIXA *pixa1, *pixa2, *pixa3; +PIXAC *pac; + + if (argc != 1) { + lept_stderr("Syntax: histoduptest\n"); + return 1; + } + + /* Set to 1 for more output from tests 1 and 2 */ + debug = 0; + + setLeptDebugOK(1); + lept_mkdir("lept/comp"); + pac = pixacompRead("dinos.pac"); /* resolution = 75 ppi */ + +#if TEST1 + /* -------------------------------------------------------------- * + * Test comparison with rotation * + * -------------------------------------------------------------- */ + /* Make a second set that is rotated; combine with the input set. */ + pixa1 = pixaCreateFromPixacomp(pac, L_COPY); + pixa2 = pixaScaleBySampling(pixa1, 2.0, 2.0); /* to resolution 150 ppi */ + n = pixaGetCount(pixa2); + for (i = 0; i < n; i++) { + pix1 = pixaGetPix(pixa2, i, L_CLONE); + pix2 = pixRotate(pix1, 0.06, L_ROTATE_SAMPLING, L_BRING_IN_WHITE, + 0, 0); + pixaAddPix(pixa2, pix2, L_INSERT); + pixDestroy(&pix1); + } + + /* Compare between every pair of images; + * can also use n = 2, simthresh = 0.50. */ + pixaComparePhotoRegionsByHisto(pixa2, 0.85, 1.3, 1, 3, 0.20, + &nai, &scores, &pix1, debug); + lept_free(scores); + + /* Show the similarity classes. */ + numaWriteStream(stderr, nai); + pixWrite("/tmp/lept/comp/photoclass1.jpg", pix1, IFF_JFIF_JPEG); + lept_stderr("Writing photo classes: /tmp/lept/comp/photoclass1.jpg\n"); + numaDestroy(&nai); + pixDestroy(&pix1); + + /* Show the scores between images as a 2d array */ + pix2 = pixRead("/tmp/lept/comp/scorearray.png"); + pixDisplay(pix2, 100, 100); + pixDestroy(&pix2); + pixaDestroy(&pixa1); + pixaDestroy(&pixa2); +#endif + +#if TEST2 + /* -------------------------------------------------------------- * + * Test translation * + * -------------------------------------------------------------- */ + /* Make a second set that is translated; combine with the input set. */ + pixa1 = pixaCreateFromPixacomp(pac, L_COPY); + pixa2 = pixaScaleBySampling(pixa1, 2.0, 2.0); /* to resolution 150 ppi */ + pixa3 = pixaTranslate(pixa2, 15, -21, L_BRING_IN_WHITE); + pixaJoin(pixa2, pixa3, 0, -1); + + /* Compare between every pair of images. */ + pixaComparePhotoRegionsByHisto(pixa2, 0.85, 1.3, 1, 3, 0.20, + &nai, &scores, &pix1, debug); + lept_free(scores); + + /* Show the similarity classes. */ + numaWriteStream(stderr, nai); + pixWrite("/tmp/lept/comp/photoclass2.jpg", pix1, IFF_JFIF_JPEG); + lept_stderr("Writing photo classes: /tmp/lept/comp/photoclass2.jpg\n"); + numaDestroy(&nai); + pixDestroy(&pix1); + + /* Show the scores between images as a 2d array */ + pix2 = pixRead("/tmp/lept/comp/scorearray.png"); + pixDisplay(pix2, 100, 100); + pixDestroy(&pix2); + pixaDestroy(&pixa1); + pixaDestroy(&pixa2); + pixaDestroy(&pixa3); +#endif + +#if TEST3 + /* -------------------------------------------------------------- * + * Compare two image regions * + * -------------------------------------------------------------- */ + /* Do a comparison on a pair: dinos has (5,7) and (4,10) being + * superficially similar. But they are far apart by this test. */ + pixa1 = pixaCreateFromPixacomp(pac, L_COPY); + pixa2 = pixaScaleBySampling(pixa1, 2.0, 2.0); /* to resolution 150 ppi */ + pix1 = pixaGetPix(pixa2, 5, L_CLONE); + box1 = pixaGetBox(pixa2, 5, L_COPY); + pix2 = pixaGetPix(pixa2, 7, L_CLONE); + box2 = pixaGetBox(pixa2, 7, L_COPY); + pixGenPhotoHistos(pix1, box1, 1, 1.2, 3, &naa1, &w1, &h1, 5); + pixGenPhotoHistos(pix2, box2, 1, 1.2, 3, &naa2, &w2, &h2, 7); + pixaDestroy(&pixa1); + pixaDestroy(&pixa2); + if (!naa1 || !naa2) { + lept_stderr("Not both image; exiting\n"); + return 0; + } + bytea1 = l_compressGrayHistograms(naa1, w1, h1, &size1); + bytea2 = l_compressGrayHistograms(naa2, w2, h2, &size2); + naa3 = l_uncompressGrayHistograms(bytea1, size1, &w1, &h1); + naa4 = l_uncompressGrayHistograms(bytea2, size2, &w2, &h2); + lept_stderr("******* (%d, %d), (%d, %d) *******\n", w1, h1, w2, h2); + pixa1 = pixaCreate(0); + /* Set @minratio very small to allow comparison for all pairs */ + compareTilesByHisto(naa3, naa4, 0.1, w1, h1, w2, h2, &score, pixa1); + pixaDestroy(&pixa1); + lept_stderr("score = %5.3f\n", score); + pixaDestroy(&pixa1); + pixDestroy(&pix1); + pixDestroy(&pix2); + boxDestroy(&box1); + boxDestroy(&box2); + numaaDestroy(&naa1); + numaaDestroy(&naa2); + numaaDestroy(&naa3); + numaaDestroy(&naa4); + lept_free(bytea1); + lept_free(bytea2); +#endif + +#if TEST4 + /* -------------------------------------------------------------- * + * Test comparison in detail * + * -------------------------------------------------------------- */ + pixa1 = pixaCreateFromPixacomp(pac, L_COPY); + n = pixaGetCount(pixa1); + maxscore = 0.0; + maxi = 0; + maxj = 0; + for (i = 0; i < n; i++) { + lept_stderr("i = %d\n", i); + pix1 = pixaGetPix(pixa1, i, L_CLONE); + box1 = pixaGetBox(pixa1, i, L_COPY); + for (j = 0; j <= i; j++) { + pix2 = pixaGetPix(pixa1, j, L_CLONE); + box2 = pixaGetBox(pixa1, j, L_COPY); + pixCompareGrayByHisto(pix1, pix2, box1, box2, 0.85, 230, 1, 3, + &score, 0); + lept_stderr("Score[%d,%d] = %5.3f\n", i, j, score); + if (i != j && score > maxscore) { + maxscore = score; + maxi = i; + maxj = j; + } + pixDestroy(&pix2); + boxDestroy(&box2); + } + pixDestroy(&pix1); + boxDestroy(&box1); + } + pixaDestroy(&pixa1); + lept_stderr("max score [%d,%d] = %5.3f\n", maxi, maxj, maxscore); +#endif + +#if TEST5 + /* -------------------------------------------------------------- * + * Text or photo determination in detail * + * -------------------------------------------------------------- */ + /* Are the images photo or text? This is the morphological + * method, which is more accurate than the variance of gray + * histo method. Output to /tmp/lept/comp/isphoto1.pdf. */ + pixa1 = pixaCreateFromPixacomp(pac, L_COPY); + n = pixaGetCount(pixa1); + pixa2 = pixaCreate(n); + for (i = 0; i < n; i++) { + pixa3 = pixaCreate(0); + lept_stderr("i = %d\n", i); + pix1 = pixaGetPix(pixa1, i, L_CLONE); + box1 = pixaGetBox(pixa1, i, L_COPY); + lept_stderr("w = %d, h = %d\n", pixGetWidth(pix1), + pixGetHeight(pix1)); + pixDecideIfText(pix1, box1, &istext, pixa3); + if (istext == 1) { + lept_stderr("This is text\n\n"); + } else if (istext == 0) { + lept_stderr("This is a photo\n\n"); + } else { /* istext == -1 */ + lept_stderr("Not determined if text or photo\n\n"); + } + if (istext == 0) { + pix2 = pixaDisplayTiledInRows(pixa3, 32, 1000, 1.0, 0, 50, 2); + pixDisplay(pix2, 100, 100); + pixaAddPix(pixa2, pix2, L_INSERT); + pixaDestroy(&pixa3); + } + pixDestroy(&pix1); + boxDestroy(&box1); + } + lept_stderr("Writing to: /tmp/lept/comp/isphoto1.pdf\n"); + pixaConvertToPdf(pixa2, 300, 1.0, L_FLATE_ENCODE, 0, NULL, + "/tmp/lept/comp/isphoto1.pdf"); + pixaDestroy(&pixa1); + pixaDestroy(&pixa2); +#endif + + pixacompDestroy(&pac); + return 0; +} + diff --git a/leptonica/prog/histotest.c b/leptonica/prog/histotest.c new file mode 100644 index 00000000..72b56327 --- /dev/null +++ b/leptonica/prog/histotest.c @@ -0,0 +1,102 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * histotest.c + * + * Makes histograms of grayscale and color pixels + * from a pix. For RGB color, this uses + * rgb --> octcube indexing. + * + * histotest filein sigbits + * + * where the number of octcubes is 8^(sigbits) + * + * For gray, sigbits is ignored. + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + +int main(int argc, + char **argv) +{ +char *filein; +l_int32 d, sigbits; +GPLOT *gplot; +NUMA *na; +PIX *pixs; +static char mainName[] = "histotest"; + + if (argc != 3) + return ERROR_INT(" Syntax: histotest filein sigbits", mainName, 1); + filein = argv[1]; + sigbits = atoi(argv[2]); + + setLeptDebugOK(1); + lept_mkdir("lept/histo"); + + if ((pixs = pixRead(filein)) == NULL) + return ERROR_INT("pixs not made", mainName, 1); + d = pixGetDepth(pixs); + if (d != 8 && d != 32) + return ERROR_INT("depth not 8 or 32 bpp", mainName, 1); + + if (d == 32) { + startTimer(); + if ((na = pixOctcubeHistogram(pixs, sigbits, NULL)) == NULL) + return ERROR_INT("na not made", mainName, 1); + lept_stderr("histo time = %7.3f sec\n", stopTimer()); + gplot = gplotCreate("/tmp/lept/histo/color", GPLOT_PNG, + "color histogram with octcube indexing", + "octcube index", "number of pixels in cube"); + gplotAddPlot(gplot, NULL, na, GPLOT_LINES, "input pix"); + gplotMakeOutput(gplot); + gplotDestroy(&gplot); + l_fileDisplay("/tmp/lept/histo/color.png", 100, 100, 1.0); + } + else { + if ((na = pixGetGrayHistogram(pixs, 1)) == NULL) + return ERROR_INT("na not made", mainName, 1); + numaWrite("/tmp/junkna", na); + gplot = gplotCreate("/tmp/lept/histo/gray", GPLOT_PNG, + "grayscale histogram", "gray value", + "number of pixels"); + gplotSetScaling(gplot, GPLOT_LOG_SCALE_Y); + gplotAddPlot(gplot, NULL, na, GPLOT_LINES, "input pix"); + gplotMakeOutput(gplot); + gplotDestroy(&gplot); + l_fileDisplay("/tmp/lept/histo/gray.png", 100, 100, 1.0); + } + + pixDestroy(&pixs); + numaDestroy(&na); + return 0; +} + diff --git a/leptonica/prog/hmttemplate1.txt b/leptonica/prog/hmttemplate1.txt new file mode 100644 index 00000000..cf1e0f84 --- /dev/null +++ b/leptonica/prog/hmttemplate1.txt @@ -0,0 +1,170 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/*! + * Top-level fast hit-miss transform with auto-generated sels + * +--- * PIX *pixHMTDwa_*() +--- * PIX *pixFHMTGen_*() + */ + +#include <string.h> +#include "allheaders.h" + +--- This file is: hmttemplate1.txt +--- +--- We need to include these prototypes: +--- PIX *pixHMTDwa_*(PIX *pixd, PIX *pixs, l_int32 operation); +--- PIX *pixFHMTGen_*(PIX *pixd, PIX *pixs, l_int32 operation); +--- l_int32 fhmtgen_low_*(l_uint32 *datad, l_int32 w, l_int32 h, +--- l_int32 wpld, l_uint32 *datas, +--- l_int32 wpls, l_int32 index); +--- +--- We need to input two static globals here: +--- static l_int32 NUM_SELS_GENERATED = <some number>; +--- static char SEL_NAMES[][80] = {"<string1>", "<string2>", ...}; + +/*! +--- * \brief pixHMTDwa_*() + * + * \param[in] pixd usual 3 choices: null, == pixs, != pixs + * \param[in] pixs 1 bpp + * \param[in] sel name + * \return pixd + * + * <pre> + * Notes: + * (1) This simply adds a 32 pixel border, calls the appropriate + * pixFHMTGen_*(), and removes the border. + * See notes below for that function. + * </pre> + */ +PIX * +--- pixHMTDwa_*(PIX *pixd, + PIX *pixs, + const char *selname) +{ +PIX *pixt1, *pixt2, *pixt3; + +--- PROCNAME("pixHMTDwa_*"); + + if (!pixs) + return (PIX *)ERROR_PTR("pixs not defined", procName, pixd); + if (pixGetDepth(pixs) != 1) + return (PIX *)ERROR_PTR("pixs must be 1 bpp", procName, pixd); + + pixt1 = pixAddBorder(pixs, 32, 0); +--- pixt2 = pixFHMTGen_*(NULL, pixt1, selname); + pixt3 = pixRemoveBorder(pixt2, 32); + pixDestroy(&pixt1); + pixDestroy(&pixt2); + + if (!pixd) + return pixt3; + + pixCopy(pixd, pixt3); + pixDestroy(&pixt3); + return pixd; +} + + +/*! +--- * \brief pixFHMTGen_*() + * + * \param[in] pixd usual 3 choices: null, == pixs, != pixs + * \param[in] pixs 1 bpp + * \param[in] sel name + * \return pixd + * + * <pre> + * Notes: + * (1) This is a dwa implementation of the hit-miss transform + * on pixs by the sel. + * (2) The sel must be limited in size to not more than 31 pixels + * about the origin. It must have at least one hit, and it + * can have any number of misses. + * (3) This handles all required setting of the border pixels + * before erosion and dilation. + * </pre> + */ +PIX * +--- pixFHMTGen_*(PIX *pixd, + PIX *pixs, + const char *selname) +{ +l_int32 i, index, found, w, h, wpls, wpld; +l_uint32 *datad, *datas, *datat; +PIX *pixt; + +--- PROCNAME("pixFHMTGen_*"); + + if (!pixs) + return (PIX *)ERROR_PTR("pixs not defined", procName, pixd); + if (pixGetDepth(pixs) != 1) + return (PIX *)ERROR_PTR("pixs must be 1 bpp", procName, pixd); + + found = FALSE; + for (i = 0; i < NUM_SELS_GENERATED; i++) { + if (strcmp(selname, SEL_NAMES[i]) == 0) { + found = TRUE; + index = i; + break; + } + } + if (found == FALSE) + return (PIX *)ERROR_PTR("sel index not found", procName, pixd); + + if (!pixd) { + if ((pixd = pixCreateTemplate(pixs)) == NULL) + return (PIX *)ERROR_PTR("pixd not made", procName, NULL); + } + else /* for in-place or pre-allocated */ + pixResizeImageData(pixd, pixs); + wpls = pixGetWpl(pixs); + wpld = pixGetWpl(pixd); + + /* The images must be surrounded with 32 additional border + * pixels, that we'll read from. We fabricate a "proper" + * image as the subimage within the border, having the + * following parameters: */ + w = pixGetWidth(pixs) - 64; + h = pixGetHeight(pixs) - 64; + datas = pixGetData(pixs) + 32 * wpls + 1; + datad = pixGetData(pixd) + 32 * wpld + 1; + + if (pixd == pixs) { /* need temp image if in-place */ + if ((pixt = pixCopy(NULL, pixs)) == NULL) + return (PIX *)ERROR_PTR("pixt not made", procName, pixd); + datat = pixGetData(pixt) + 32 * wpls + 1; +--- fhmtgen_low_*(datad, w, h, wpld, datat, wpls, index); + pixDestroy(&pixt); + } + else { /* not in-place */ +--- fhmtgen_low_*(datad, w, h, wpld, datas, wpls, index); + } + + return pixd; +} diff --git a/leptonica/prog/hmttemplate2.txt b/leptonica/prog/hmttemplate2.txt new file mode 100644 index 00000000..cd4da0bf --- /dev/null +++ b/leptonica/prog/hmttemplate2.txt @@ -0,0 +1,103 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/*! + * Low-level fast hit-miss transform with auto-generated sels + * + * Dispatcher: +--- * l_int32 fhmtgen_low_*() + * + * Static Low-level: +--- * void fhmt_*_*() + */ + +#include "allheaders.h" + +--- This file is: hmttemplate2.txt +--- +--- insert static protos here + + +/*---------------------------------------------------------------------* + * Fast hmt dispatcher * + *---------------------------------------------------------------------*/ +/*! +--- * fhmtgen_low_*() + * + * a dispatcher to appropriate low-level code + */ +l_int32 +--- fhmtgen_low_*(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls, + l_int32 index) +{ + + switch (index) + { +--- insert dispatcher code for fhmt* routines + } + + return 0; +} + + +/*--------------------------------------------------------------------------* + * Low-level auto-generated static routines * + *--------------------------------------------------------------------------*/ +/* + * N.B. In all the low-level routines, the part of the image + * that is accessed has been clipped by 32 pixels on + * all four sides. This is done in the higher level + * code by redefining w and h smaller and by moving the + * start-of-image pointers up to the beginning of this + * interior rectangle. + */ +--- static void fhmt_*_*(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; +--- declare wplsN args as necessary ---------------------- + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { +--- insert barrel-op code for *dptr here ... + } + } +} + diff --git a/leptonica/prog/hole-filler.png b/leptonica/prog/hole-filler.png Binary files differnew file mode 100644 index 00000000..e5e5532b --- /dev/null +++ b/leptonica/prog/hole-filler.png diff --git a/leptonica/prog/htmlviewer.c b/leptonica/prog/htmlviewer.c new file mode 100644 index 00000000..617dd708 --- /dev/null +++ b/leptonica/prog/htmlviewer.c @@ -0,0 +1,286 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * htmlviewer.c + * + * This takes a directory of image files, optionally scales them, + * and generates html files to view the scaled images (and thumbnails). + * + * Input: dirin: directory of input image files + * dirout: directory for output files + * rootname: root name for output files + * thumbwidth: width of thumb images, in pixels; use 0 for default + * viewwidth: max width of view images, in pixels; use 0 for default + * + * Example: + * mkdir /tmp/lept/lion-in + * mkdir /tmp/lept/lion-out + * cp lion-page* /tmp/lept/lion-in + * htmlviewer /tmp/lept/lion-in /tmp/lept/lion-out lion 200 600 + * ==> output: + * /tmp/lept/lion-out/lion.html (main html file) + * /tmp/lept/lion-out/lion-links.html (html file of links) + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include <string.h> +#include "allheaders.h" + +#ifdef _WIN32 +#include <windows.h> /* for CreateDirectory() */ +#endif + +static const l_int32 DEFAULT_THUMB_WIDTH = 120; +static const l_int32 DEFAULT_VIEW_WIDTH = 800; +static const l_int32 MIN_THUMB_WIDTH = 50; +static const l_int32 MIN_VIEW_WIDTH = 300; + +static l_int32 pixHtmlViewer(const char *dirin, const char *dirout, + const char *rootname, l_int32 thumbwidth, + l_int32 viewwidth); +static void WriteFormattedPix(const char *fname, PIX *pix); + + +int main(int argc, + char **argv) +{ +char *dirin, *dirout, *rootname; +l_int32 thumbwidth, viewwidth; +static char mainName[] = "htmlviewer"; + + if (argc != 6) + return ERROR_INT( + " Syntax: htmlviewer dirin dirout rootname thumbwidth viewwidth", + mainName, 1); + dirin = argv[1]; + dirout = argv[2]; + rootname = argv[3]; + thumbwidth = atoi(argv[4]); + viewwidth = atoi(argv[5]); + setLeptDebugOK(1); + + pixHtmlViewer(dirin, dirout, rootname, thumbwidth, viewwidth); + return 0; +} + + +/*---------------------------------------------------------------------* + * Generate smaller images for viewing and write html * + *---------------------------------------------------------------------*/ +/*! + * \brief pixHtmlViewer() + * + * \param[in] dirin directory of input image files + * \param[in] dirout directory for output files + * \param[in] rootname root name for output files + * \param[in] thumbwidth width of thumb images in pixels; use 0 for default + * \param[in] viewwidth maximum width of view images no up-scaling + * in pixels; use 0 for default + * \return 0 if OK; 1 on error + * + * <pre> + * Notes: + * (1) The thumb and view reduced images are generated, + * along with two html files: + * <rootname>.html and <rootname>-links.html + * (2) The thumb and view files are named + * <rootname>_thumb_xxx.jpg + * <rootname>_view_xxx.jpg + * With this naming scheme, any number of input directories + * of images can be processed into views and thumbs + * and placed in the same output directory. + * </pre> + */ +static l_int32 +pixHtmlViewer(const char *dirin, + const char *dirout, + const char *rootname, + l_int32 thumbwidth, + l_int32 viewwidth) +{ +char *fname, *fullname, *outname; +char *mainname, *linkname, *linknameshort; +char *viewfile, *thumbfile; +char *shtml, *slink; +char buf[512]; +char htmlstring[] = "<html>"; +char framestring[] = "</frameset></html>"; +l_int32 i, nfiles, index, w, d, nimages, ret; +l_float32 factor; +PIX *pix, *pixthumb, *pixview; +SARRAY *safiles, *sathumbs, *saviews, *sahtml, *salink; + + PROCNAME("pixHtmlViewer"); + + if (!dirin) + return ERROR_INT("dirin not defined", procName, 1); + if (!dirout) + return ERROR_INT("dirout not defined", procName, 1); + if (!rootname) + return ERROR_INT("rootname not defined", procName, 1); + + if (thumbwidth == 0) + thumbwidth = DEFAULT_THUMB_WIDTH; + if (thumbwidth < MIN_THUMB_WIDTH) { + L_WARNING("thumbwidth too small; using min value\n", procName); + thumbwidth = MIN_THUMB_WIDTH; + } + if (viewwidth == 0) + viewwidth = DEFAULT_VIEW_WIDTH; + if (viewwidth < MIN_VIEW_WIDTH) { + L_WARNING("viewwidth too small; using min value\n", procName); + viewwidth = MIN_VIEW_WIDTH; + } + + /* Make the output directory if it doesn't already exist */ +#ifndef _WIN32 + snprintf(buf, sizeof(buf), "mkdir -p %s", dirout); + ret = system(buf); +#else + ret = CreateDirectory(dirout, NULL) ? 0 : 1; +#endif /* !_WIN32 */ + if (ret) { + L_ERROR("output directory %s not made\n", procName, dirout); + return 1; + } + + /* Capture the filenames in the input directory */ + if ((safiles = getFilenamesInDirectory(dirin)) == NULL) + return ERROR_INT("safiles not made", procName, 1); + + /* Generate output text file names */ + snprintf(buf, sizeof(buf), "%s/%s.html", dirout, rootname); + mainname = stringNew(buf); + snprintf(buf, sizeof(buf), "%s/%s-links.html", dirout, rootname); + linkname = stringNew(buf); + linknameshort = stringJoin(rootname, "-links.html"); + + /* Generate the thumbs and views */ + sathumbs = sarrayCreate(0); + saviews = sarrayCreate(0); + nfiles = sarrayGetCount(safiles); + index = 0; + for (i = 0; i < nfiles; i++) { + fname = sarrayGetString(safiles, i, L_NOCOPY); + fullname = genPathname(dirin, fname); + lept_stderr("name: %s\n", fullname); + if ((pix = pixRead(fullname)) == NULL) { + lept_stderr("file %s not a readable image\n", fullname); + lept_free(fullname); + continue; + } + lept_free(fullname); + + /* Make and store the thumbnail images */ + pixGetDimensions(pix, &w, NULL, &d); + factor = (l_float32)thumbwidth / (l_float32)w; + pixthumb = pixScale(pix, factor, factor); + snprintf(buf, sizeof(buf), "%s_thumb_%03d", rootname, index); + sarrayAddString(sathumbs, buf, L_COPY); + outname = genPathname(dirout, buf); + WriteFormattedPix(outname, pixthumb); + lept_free(outname); + pixDestroy(&pixthumb); + + /* Make and store the view images */ + factor = (l_float32)viewwidth / (l_float32)w; + if (factor >= 1.0) + pixview = pixClone(pix); /* no upscaling */ + else + pixview = pixScale(pix, factor, factor); + snprintf(buf, sizeof(buf), "%s_view_%03d", rootname, index); + sarrayAddString(saviews, buf, L_COPY); + outname = genPathname(dirout, buf); + WriteFormattedPix(outname, pixview); + lept_free(outname); + pixDestroy(&pixview); + pixDestroy(&pix); + index++; + } + + /* Generate the main html file */ + sahtml = sarrayCreate(0); + sarrayAddString(sahtml, htmlstring, L_COPY); + snprintf(buf, sizeof(buf), "<frameset cols=\"%d, *\">", thumbwidth + 30); + sarrayAddString(sahtml, buf, L_COPY); + snprintf(buf, sizeof(buf), "<frame name=\"thumbs\" src=\"%s\">", + linknameshort); + sarrayAddString(sahtml, buf, L_COPY); + snprintf(buf, sizeof(buf), "<frame name=\"views\" src=\"%s\">", + sarrayGetString(saviews, 0, L_NOCOPY)); + sarrayAddString(sahtml, buf, L_COPY); + sarrayAddString(sahtml, framestring, L_COPY); + shtml = sarrayToString(sahtml, 1); + l_binaryWrite(mainname, "w", shtml, strlen(shtml)); + lept_stderr("******************************************\n" + "Writing html file: %s\n" + "******************************************\n", mainname); + lept_free(shtml); + lept_free(mainname); + + /* Generate the link html file */ + nimages = sarrayGetCount(saviews); + lept_stderr("num. images = %d\n", nimages); + salink = sarrayCreate(0); + for (i = 0; i < nimages; i++) { + viewfile = sarrayGetString(saviews, i, L_NOCOPY); + thumbfile = sarrayGetString(sathumbs, i, L_NOCOPY); + snprintf(buf, sizeof(buf), + "<a href=\"%s\" TARGET=views><img src=\"%s\"></a>", + viewfile, thumbfile); + sarrayAddString(salink, buf, L_COPY); + } + slink = sarrayToString(salink, 1); + l_binaryWrite(linkname, "w", slink, strlen(slink)); + lept_free(slink); + lept_free(linkname); + lept_free(linknameshort); + sarrayDestroy(&safiles); + sarrayDestroy(&sathumbs); + sarrayDestroy(&saviews); + sarrayDestroy(&sahtml); + sarrayDestroy(&salink); + return 0; +} + +static void +WriteFormattedPix(const char *fname, + PIX *pix) +{ +l_int32 d; + + d = pixGetDepth(pix); + if (d == 1 || pixGetColormap(pix)) + pixWrite(fname, pix, IFF_PNG); + else + pixWrite(fname, pix, IFF_JFIF_JPEG); + return; +} + diff --git a/leptonica/prog/imagetops.c b/leptonica/prog/imagetops.c new file mode 100644 index 00000000..66fe8496 --- /dev/null +++ b/leptonica/prog/imagetops.c @@ -0,0 +1,101 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * imagetops.c + * + * This generates a PostScript image, optionally rotating and setting + * a scaling factor for printing with maximum size on 8.5 x 11 + * paper at 300 ppi. + * + * Syntax: imagetops <filein> <level> <fileout> + * + * level (corresponding to PostScript compression level): + * 1 for uncompressed + * 2 for compression with g4 for 1 bpp and dct for everything else + * 3 for compression with flate + * + * The output PostScript file can be printed with lpr or lp. + * Examples of the invocation for lp are: + * lp -d <printer> <ps-file> + * lp -d <printer> -o ColorModel=Color <ps-file> + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + +static const l_float32 FILL_FACTOR = 0.95; /* fill factor on 8.5 x 11 page */ + +int main(int argc, + char **argv) +{ +char *filein, *fileout; +l_int32 w, h, index, level; +l_float32 scale; +FILE *fp; +PIX *pixs, *pix1; +static char mainName[] = "imagetops"; + + if (argc != 4) + return ERROR_INT( + " Syntax: imagetops <filein> <compression level> <fileout>", + mainName, 1); + filein = argv[1]; + level = atoi(argv[2]); + fileout = argv[3]; + + if ((pixs = pixRead(filein)) == NULL) + return ERROR_INT("pixs not made", mainName, 1); + if (level < 1 || level > 3) + return ERROR_INT("valid levels are: 1, 2, 3", mainName, 1); + + pixGetDimensions(pixs, &w, &h, NULL); + if (w > h) { + pix1 = pixRotate90(pixs, 1); + pixGetDimensions(pix1, &w, &h, NULL); + } + else { + pix1 = pixClone(pixs); + } + + scale = L_MIN(FILL_FACTOR * 2550 / w, FILL_FACTOR * 3300 / h); + if (level == 1) { + fp = lept_fopen(fileout, "wb+"); + pixWriteStreamPS(fp, pix1, NULL, 300, scale); + lept_fclose(fp); + } else { /* levels 2 and 3 */ + index = 0; + pixWriteCompressedToPS(pix1, fileout, (l_int32)(300. / scale), + level, &index); + } + + pixDestroy(&pixs); + pixDestroy(&pix1); + return 0; +} diff --git a/leptonica/prog/insert_reg.c b/leptonica/prog/insert_reg.c new file mode 100644 index 00000000..a3183f1e --- /dev/null +++ b/leptonica/prog/insert_reg.c @@ -0,0 +1,163 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * insert_reg.c + * + * This tests removal and insertion operations in numa, boxa and pixa. + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include <math.h> +#include "allheaders.h" + +int main(int argc, + char **argv) +{ +l_int32 i, n; +l_float32 pi, angle, val; +BOX *box; +BOXA *boxa, *boxa1, *boxa2; +NUMA *na1, *na2; +PIX *pix, *pix1, *pix2; +PIXA *pixa1, *pixa2, *pixa3, *pixa4; +L_REGPARAMS *rp; + +#if !defined(HAVE_LIBPNG) + L_ERROR("This test requires libpng to run.\n", "insert_reg"); + exit(77); +#endif + + if (regTestSetup(argc, argv, &rp)) + return 1; + + lept_rmfile("/tmp/lept/regout/insert3.ba"); + lept_rmfile("/tmp/lept/regout/insert4.ba"); + lept_rmfile("/tmp/lept/regout/insert6.pa"); + lept_rmfile("/tmp/lept/regout/insert7.pa"); + lept_rmfile("/tmp/lept/regout/insert9.pa"); + lept_rmfile("/tmp/lept/regout/insert10.pa"); + + /* ----------------- Test numa operations -------------------- */ + pi = 3.1415926535; + na1 = numaCreate(500); + for (i = 0; i < 500; i++) { + angle = 0.02293 * i * pi; + val = (l_float32)sin(angle); + numaAddNumber(na1, val); + } + numaWrite("/tmp/lept/regout/insert0.na", na1); + na2 = numaCopy(na1); + n = numaGetCount(na2); + for (i = 0; i < n; i++) { + numaGetFValue(na2, i, &val); + numaRemoveNumber(na2, i); + numaInsertNumber(na2, i, val); + } + numaWrite("/tmp/lept/regout/insert1.na", na2); + regTestCheckFile(rp, "/tmp/lept/regout/insert0.na"); /* 0 */ + regTestCheckFile(rp, "/tmp/lept/regout/insert1.na"); /* 1 */ + regTestCompareFiles(rp, 0, 1); /* 2 */ + numaDestroy(&na1); + numaDestroy(&na2); + + /* ----------------- Test boxa operations -------------------- */ + pix1 = pixRead("feyn.tif"); + box = boxCreate(1138, 1666, 1070, 380); + pix2 = pixClipRectangle(pix1, box, NULL); + boxDestroy(&box); + boxa1 = pixConnComp(pix2, NULL, 8); + boxaWrite("/tmp/lept/regout/insert3.ba", boxa1); + boxa2 = boxaCopy(boxa1, L_COPY); + n = boxaGetCount(boxa2); + for (i = 0; i < n; i++) { + boxaRemoveBoxAndSave(boxa2, i, &box); + boxaInsertBox(boxa2, i, box); + } + boxaWrite("/tmp/lept/regout/insert4.ba", boxa2); + regTestCheckFile(rp, "/tmp/lept/regout/insert3.ba"); /* 3 */ + regTestCheckFile(rp, "/tmp/lept/regout/insert4.ba"); /* 4 */ + regTestCompareFiles(rp, 3, 4); /* 5 */ + pixDestroy(&pix1); + pixDestroy(&pix2); + boxaDestroy(&boxa1); + boxaDestroy(&boxa2); + + /* ----------------- Test pixa operations -------------------- */ + pix1 = pixRead("feyn.tif"); + box = boxCreate(1138, 1666, 1070, 380); + pix2 = pixClipRectangle(pix1, box, NULL); + boxDestroy(&box); + boxa = pixConnComp(pix2, &pixa1, 8); + boxaDestroy(&boxa); + pixaWrite("/tmp/lept/regout/insert6.pa", pixa1); + regTestCheckFile(rp, "/tmp/lept/regout/insert6.pa"); /* 6 */ + pixDestroy(&pix1); + pixDestroy(&pix2); + + /* Remove and insert each one */ + pixa2 = pixaCopy(pixa1, L_COPY); + n = pixaGetCount(pixa2); + for (i = 0; i < n; i++) { + pixaRemovePixAndSave(pixa2, i, &pix, &box); + pixaInsertPix(pixa2, i, pix, box); + } + pixaWrite("/tmp/lept/regout/insert7.pa", pixa2); + regTestCheckFile(rp, "/tmp/lept/regout/insert7.pa"); /* 7 */ + regTestCompareFiles(rp, 6, 7); /* 8 */ + + /* Move the last to the beginning; do it n times */ + pixa3 = pixaCopy(pixa2, L_COPY); + for (i = 0; i < n; i++) { + pix = pixaGetPix(pixa3, n - 1, L_CLONE); + box = pixaGetBox(pixa3, n - 1, L_CLONE); + pixaInsertPix(pixa3, 0, pix, box); + pixaRemovePix(pixa3, n); + } + pixaWrite("/tmp/lept/regout/insert9.pa", pixa3); + regTestCheckFile(rp, "/tmp/lept/regout/insert9.pa"); /* 9 */ + + /* Move the first one to the end; do it n times */ + pixa4 = pixaCopy(pixa3, L_COPY); + for (i = 0; i < n; i++) { + pix = pixaGetPix(pixa4, 0, L_CLONE); + box = pixaGetBox(pixa4, 0, L_CLONE); + pixaInsertPix(pixa4, n, pix, box); /* make sure insert works at end */ + pixaRemovePix(pixa4, 0); + } + pixaWrite("/tmp/lept/regout/insert10.pa", pixa4); + regTestCheckFile(rp, "/tmp/lept/regout/insert10.pa"); /* 10 */ + regTestCompareFiles(rp, 9, 10); /* 11 */ + pixaDestroy(&pixa1); + pixaDestroy(&pixa2); + pixaDestroy(&pixa3); + pixaDestroy(&pixa4); + + return regTestCleanup(rp); +} diff --git a/leptonica/prog/invertedtext.tif b/leptonica/prog/invertedtext.tif Binary files differnew file mode 100644 index 00000000..3861864f --- /dev/null +++ b/leptonica/prog/invertedtext.tif diff --git a/leptonica/prog/ioformats_reg.c b/leptonica/prog/ioformats_reg.c new file mode 100644 index 00000000..5f703513 --- /dev/null +++ b/leptonica/prog/ioformats_reg.c @@ -0,0 +1,921 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * ioformats_reg.c + * + * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + * This is the primary Leptonica regression test for lossless + * read/write I/O to standard image files (png, tiff, bmp, etc.) + * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + * + * This tests reading and writing of images in different formats + * It should work properly on input images of any depth, with + * and without colormaps. There are 7 sections. + * + * Section 1. Test write/read with lossless and lossy compression, with + * and without colormaps. The lossless results are tested for equality. + * + * Section 2. Test read/write to file with different tiff compressions. + * + * Section 3. Test read/write to memory with different tiff compressions. + * + * Section 4. Test read/write to memory with other compression formats. + * + * Section 5. Test multippage tiff read/write to file and memory. + * + * Section 6. Test writing 24 bpp (not 32 bpp) pix + * + * Section 7. Test header reading + * + * This test requires the following external I/O libraries + * libjpeg, libtiff, libpng, libz + * and optionally tests these: + * libwebp, libopenjp2, libgif + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + +#define BMP_FILE "test1.bmp" +#define FILE_1BPP "feyn.tif" +#define FILE_2BPP "speckle2.png" +#define FILE_2BPP_C "weasel2.4g.png" +#define FILE_4BPP "speckle4.png" +#define FILE_4BPP_C "weasel4.16c.png" +#define FILE_8BPP_1 "dreyfus8.png" +#define FILE_8BPP_2 "weasel8.240c.png" +#define FILE_8BPP_3 "test8.jpg" +#define FILE_16BPP "test16.tif" +#define FILE_32BPP "marge.jpg" +#define FILE_32BPP_ALPHA "test32-alpha.png" +#define FILE_1BIT_ALPHA "test-1bit-alpha.png" +#define FILE_CMAP_ALPHA "test-cmap-alpha.png" +#define FILE_TRANS_ALPHA "test-fulltrans-alpha.png" +#define FILE_GRAY_ALPHA "test-gray-alpha.png" +#define FILE_GRAY_ALPHA_TIF "gray-alpha.tif" +#define FILE_RGB16_TIF "rgb16.tif" + +static l_int32 testcomp(const char *filename, PIX *pix, l_int32 comptype); +static l_int32 testcomp_mem(PIX *pixs, PIX **ppixt, l_int32 index, + l_int32 format); +static l_int32 test_writemem(PIX *pixs, l_int32 format, char *psfile); +static PIX *make_24_bpp_pix(PIX *pixs); +static l_int32 get_header_data(const char *filename, l_int32 true_format); +static const char *get_tiff_compression_name(l_int32 format); + +LEPT_DLL extern const char *ImageFileFormatExtensions[]; + +int main(int argc, + char **argv) +{ +char psname[256]; +char *tempname; +l_uint8 *data; +l_int32 i, d, n, success, failure, same; +l_int32 w, h, bps, spp, iscmap, res; +size_t size, nbytes; +PIX *pix1, *pix2, *pix3, *pix4, *pix8, *pix16, *pix32; +PIX *pix, *pixt, *pixd; +PIXA *pixa; +PIXCMAP *cmap; +L_REGPARAMS *rp; + +#if !HAVE_LIBJPEG + lept_stderr("Omitting libjpeg tests in ioformats_reg\n"); +#endif /* !HAVE_LIBJPEG */ + +#if !HAVE_LIBTIFF + lept_stderr("Omitting libtiff tests in ioformats_reg\n"); +#endif /* !HAVE_LIBTIFF */ + +#if !HAVE_LIBPNG || !HAVE_LIBZ + lept_stderr("Omitting libpng tests in ioformats_reg\n"); +#endif /* !HAVE_LIBPNG || !HAVE_LIBZ */ + +#if !HAVE_LIBWEBP + lept_stderr("Omitting libwebp tests in ioformats_reg\n"); +#endif /* !HAVE_LIBWEBP */ + +#if !HAVE_LIBJP2K + lept_stderr("Omitting libopenjp2 tests in ioformats_reg\n"); +#endif /* !HAVE_LIBJP2K */ + +#if !HAVE_LIBGIF + lept_stderr("Omitting libgif tests in ioformats_reg\n"); +#endif /* !HAVE_LIBGIF */ + + if (regTestSetup(argc, argv, &rp)) + return 1; + + /* --------- Part 1: Test all formats for r/w to file ---------*/ + + failure = FALSE; + success = TRUE; + lept_stderr("Test bmp 1 bpp file:\n"); + if (ioFormatTest(BMP_FILE)) success = FALSE; + +#if HAVE_LIBTIFF + lept_stderr("\nTest other 1 bpp file:\n"); + if (ioFormatTest(FILE_1BPP)) success = FALSE; +#endif /* HAVE_LIBTIFF */ + +#if HAVE_LIBPNG + lept_stderr("\nTest 2 bpp file:\n"); + if (ioFormatTest(FILE_2BPP)) success = FALSE; + lept_stderr("\nTest 2 bpp file with cmap:\n"); + if (ioFormatTest(FILE_2BPP_C)) success = FALSE; + lept_stderr("\nTest 4 bpp file:\n"); + if (ioFormatTest(FILE_4BPP)) success = FALSE; + lept_stderr("\nTest 4 bpp file with cmap:\n"); + if (ioFormatTest(FILE_4BPP_C)) success = FALSE; + lept_stderr("\nTest 8 bpp grayscale file with cmap:\n"); + if (ioFormatTest(FILE_8BPP_1)) success = FALSE; + lept_stderr("\nTest 8 bpp color file with cmap:\n"); + if (ioFormatTest(FILE_8BPP_2)) success = FALSE; +#endif /* HAVE_LIBPNG */ + +#if HAVE_LIBJPEG + lept_stderr("\nTest 8 bpp file without cmap:\n"); + if (ioFormatTest(FILE_8BPP_3)) success = FALSE; +#endif /* HAVE_LIBJPEG */ + +#if HAVE_LIBTIFF + lept_stderr("\nTest 16 bpp file:\n"); + if (ioFormatTest(FILE_16BPP)) success = FALSE; +#endif /* HAVE_LIBTIFF */ + +#if HAVE_LIBJPEG + lept_stderr("\nTest 32 bpp files:\n"); + if (ioFormatTest(FILE_32BPP)) success = FALSE; + if (ioFormatTest(FILE_32BPP_ALPHA)) success = FALSE; +#endif /* HAVE_LIBJPEG */ + +#if HAVE_LIBPNG && HAVE_LIBJPEG + lept_stderr("\nTest spp = 1, bpp = 1, cmap with alpha file:\n"); + if (ioFormatTest(FILE_1BIT_ALPHA)) success = FALSE; + lept_stderr("\nTest spp = 1, bpp = 8, cmap with alpha file:\n"); + if (ioFormatTest(FILE_CMAP_ALPHA)) success = FALSE; + lept_stderr("\nTest spp = 1, fully transparent with alpha file:\n"); + if (ioFormatTest(FILE_TRANS_ALPHA)) success = FALSE; + lept_stderr("\nTest spp = 2, gray with alpha file:\n"); + if (ioFormatTest(FILE_GRAY_ALPHA)) success = FALSE; +#endif /* HAVE_LIBJPEG */ + + if (success) + lept_stderr( + "\n ********** Success on all i/o format tests *********\n"); + else + lept_stderr( + "\n ******* Failure on at least one i/o format test ******\n"); + if (!success) failure = TRUE; + + + /* ------------------ Part 2: Test tiff r/w to file ------------------- */ +#if !HAVE_LIBTIFF + lept_stderr("\nNo libtiff. Skipping:\n" + " part 2 (tiff r/w)\n" + " part 3 (tiff r/w to memory)\n" + " part 4 (non-tiff r/w to memory)\n" + " part 5 (multipage tiff r/w to memory)\n\n"); + goto part6; +#endif /* !HAVE_LIBTIFF */ + + lept_stderr("\nTest tiff r/w and format extraction\n"); + pixa = pixaCreate(6); + pix1 = pixRead(BMP_FILE); + pix2 = pixConvert1To2(NULL, pix1, 3, 0); + pix4 = pixConvert1To4(NULL, pix1, 15, 0); + pix16 = pixRead(FILE_16BPP); + lept_stderr("Input format: %d\n", pixGetInputFormat(pix16)); + pix8 = pixConvert16To8(pix16, 1); + pix32 = pixRead(FILE_32BPP); + pixaAddPix(pixa, pix1, L_INSERT); + pixaAddPix(pixa, pix2, L_INSERT); + pixaAddPix(pixa, pix4, L_INSERT); + pixaAddPix(pixa, pix8, L_INSERT); + pixaAddPix(pixa, pix16, L_INSERT); + pixaAddPix(pixa, pix32, L_INSERT); + n = pixaGetCount(pixa); + + success = (n < 6) ? FALSE : TRUE; + if (!success) + lept_stderr("Error: only %d / 6 images loaded\n", n); + for (i = 0; i < n; i++) { + if ((pix = pixaGetPix(pixa, i, L_CLONE)) == NULL) { + success = FALSE; + continue; + } + d = pixGetDepth(pix); + lept_stderr("%d bpp\n", d); + if (i == 0) { /* 1 bpp */ + pixWrite("/tmp/lept/regout/junkg3.tif", pix, IFF_TIFF_G3); + pixWrite("/tmp/lept/regout/junkg4.tif", pix, IFF_TIFF_G4); + pixWrite("/tmp/lept/regout/junkrle.tif", pix, IFF_TIFF_RLE); + pixWrite("/tmp/lept/regout/junkpb.tif", pix, IFF_TIFF_PACKBITS); + if (testcomp("/tmp/lept/regout/junkg3.tif", pix, IFF_TIFF_G3)) + success = FALSE; + if (testcomp("/tmp/lept/regout/junkg4.tif", pix, IFF_TIFF_G4)) + success = FALSE; + if (testcomp("/tmp/lept/regout/junkrle.tif", pix, IFF_TIFF_RLE)) + success = FALSE; + if (testcomp("/tmp/lept/regout/junkpb.tif", pix, IFF_TIFF_PACKBITS)) + success = FALSE; + } + pixWrite("/tmp/lept/regout/junklzw.tif", pix, IFF_TIFF_LZW); + pixWrite("/tmp/lept/regout/junkzip.tif", pix, IFF_TIFF_ZIP); + pixWrite("/tmp/lept/regout/junknon.tif", pix, IFF_TIFF); + if (testcomp("/tmp/lept/regout/junklzw.tif", pix, IFF_TIFF_LZW)) + success = FALSE; + if (testcomp("/tmp/lept/regout/junkzip.tif", pix, IFF_TIFF_ZIP)) + success = FALSE; + if (testcomp("/tmp/lept/regout/junknon.tif", pix, IFF_TIFF)) + success = FALSE; + pixDestroy(&pix); + } + + /* Test writing and reading tiff colormaps */ + lept_stderr("Tiff read/write 8 bpp with cmap\n"); + pix1 = pixRead(FILE_8BPP_2); + pixWrite("/tmp/lept/regout/weas8.tif", pix1, IFF_TIFF); + readHeaderTiff("/tmp/lept/regout/weas8.tif", 0, &w, &h, &bps, &spp, + NULL, &iscmap, NULL); + if (w != 82 || h != 73 || bps != 8 || spp != 1 || iscmap != 1) { + lept_stderr("Header error testing tiff cmaps\n"); + success = FALSE; + } + pix2 = pixRead("/tmp/lept/regout/weas8.tif"); + pixWrite("/tmp/lept/regout/weas8a.tif", pix2, IFF_TIFF); + pix3 = pixRead("/tmp/lept/regout/weas8a.tif"); + pixEqual(pix1, pix3, &same); + if (!same) { + lept_stderr("Tiff read/write failed for cmaps\n"); + success = FALSE; + } + pixDestroy(&pix1); + pixDestroy(&pix2); + pixDestroy(&pix3); + + /* Test writing and reading 1 bpp tiff with colormap */ + lept_stderr("Tiff read/write 1 bpp with cmap\n"); + pix1 = pixRead("feyn-fract2.tif"); + cmap = pixcmapCreate(1); + pixcmapAddColor(cmap, 0, 0, 0); /* inverted b/w */ + pixcmapAddColor(cmap, 255, 255, 255); + pixSetColormap(pix1, cmap); + pixWrite("/tmp/lept/regout/fract1.tif", pix1, IFF_TIFF_ZIP); + pix2 = pixRead("/tmp/lept/regout/fract1.tif"); + pixEqual(pix1, pix2, &same); + if (!same) { + lept_stderr("Tiff read/write failed for 1 bpp cmap\n"); + success = FALSE; + } + cmap = pixcmapCreate(1); + pixcmapAddColor(cmap, 255, 255, 255); + pixcmapAddColor(cmap, 100, 200, 50); /* with color */ + pixSetColormap(pix1, cmap); /* replace the colormap */ + pixWrite("/tmp/lept/regout/fract2.tif", pix1, IFF_TIFF_ZIP); + pix3 = pixRead("/tmp/lept/regout/fract2.tif"); + pixEqual(pix1, pix3, &same); + if (!same) { + lept_stderr("Tiff read/write failed for 1 bpp color cmap\n"); + success = FALSE; + } + pixDestroy(&pix1); + pixDestroy(&pix2); + pixDestroy(&pix3); + + /* Test writing and reading tiff with alpha */ + lept_stderr("Tiff read/write gray plus alpha\n"); + pix1 = pixRead(FILE_GRAY_ALPHA_TIF); /* converts to RGBA */ + pixWrite("/tmp/lept/regout/graya.tif", pix1, IFF_TIFF); + readHeaderTiff("/tmp/lept/regout/graya.tif", 0, &w, &h, &bps, &spp, + NULL, &iscmap, NULL); + if (w != 100 || h != 100 || bps != 8 || spp != 4 || iscmap != 0) { + lept_stderr("Header error testing tiff with alpha\n"); + success = FALSE; + } + pix2 = pixRead("/tmp/lept/regout/graya.tif"); + pixEqual(pix1, pix2, &same); + if (!same) { + lept_stderr("Tiff read/write failed for graya.tif\n"); + success = FALSE; + } + pixDestroy(&pix1); + pixDestroy(&pix2); + pix1 = pixRead(FILE_GRAY_ALPHA); /* converts to RGBA */ + pixWriteTiff("/tmp/lept/regout/graya2.tif", pix1, IFF_TIFF_ZIP, "w"); + pix2 = pixRead("/tmp/lept/regout/graya2.tif"); + pixEqual(pix1, pix2, &same); + if (!same) { + lept_stderr("Tiff read/write failed for graya2.tif\n"); + success = FALSE; + } + pixDestroy(&pix1); + pixDestroy(&pix2); + + /* Test reading 16 bit sampled rgb tiff */ + lept_stderr("Tiff read/write 16 bit sampled rgb\n"); + pix1 = pixRead(FILE_RGB16_TIF); /* converts 16 to 8 bits RGB */ + pixWrite("/tmp/lept/regout/rgb16.tif", pix1, IFF_TIFF_ZIP); + readHeaderTiff("/tmp/lept/regout/rgb16.tif", 0, &w, &h, &bps, &spp, + NULL, &iscmap, NULL); + if (w != 129 || h != 90 || bps != 8 || spp != 3 || iscmap != 0) { + lept_stderr("Header error testing tiff with alpha\n"); + success = FALSE; + } + pix2 = pixRead("/tmp/lept/regout/rgb16.tif"); + pixEqual(pix1, pix2, &same); + if (!same) { + lept_stderr("Tiff read/write failed for rgb16.tif\n"); + success = FALSE; + } + pixDestroy(&pix1); + pixDestroy(&pix2); + + /* Test reading 32 bit rgb with approx half-sized tiff buffer */ + lept_stderr("Tiff read/write rgb with half-sized tiff buffer\n"); + pix1 = pixRead("testbuffer.tif"); + pixWrite("/tmp/lept/regout/testbuffer.tif", pix1, IFF_TIFF_ZIP); + readHeaderTiff("/tmp/lept/regout/testbuffer.tif", 0, &w, &h, &bps, &spp, + &res, &iscmap, NULL); + if (w != 659 || h != 799 || bps != 8 || spp != 3 || res != 96) { + lept_stderr("Header error testing rgb tiff with small tif buffer\n"); + success = FALSE; + } + pix2 = pixRead("/tmp/lept/regout/testbuffer.tif"); + pixEqual(pix1, pix2, &same); + if (!same) { + lept_stderr("Tiff read/write failed for testbuffer.tif\n"); + success = FALSE; + } + pixDestroy(&pix1); + pixDestroy(&pix2); + + if (success) + lept_stderr( + "\n ********** Success on tiff r/w to file *********\n\n"); + else + lept_stderr( + "\n ******* Failure on at least one tiff r/w to file ******\n\n"); + if (!success) failure = TRUE; + + /* ------------------ Part 3: Test tiff r/w to memory ----------------- */ + + success = (n < 6) ? FALSE : TRUE; + for (i = 0; i < n; i++) { + if ((pix = pixaGetPix(pixa, i, L_CLONE)) == NULL) { + success = FALSE; + continue; + } + d = pixGetDepth(pix); + lept_stderr("%d bpp\n", d); + if (i == 0) { /* 1 bpp */ + pixWriteMemTiff(&data, &size, pix, IFF_TIFF_G3); + nbytes = nbytesInFile("/tmp/lept/regout/junkg3.tif"); + lept_stderr("nbytes = %lu, size = %lu\n", + (unsigned long)nbytes, (unsigned long)size); + pixt = pixReadMemTiff(data, size, 0); + if (testcomp_mem(pix, &pixt, i, IFF_TIFF_G3)) success = FALSE; + lept_free(data); + pixWriteMemTiff(&data, &size, pix, IFF_TIFF_G4); + nbytes = nbytesInFile("/tmp/lept/regout/junkg4.tif"); + lept_stderr("nbytes = %lu, size = %lu\n", + (unsigned long)nbytes, (unsigned long)size); + pixt = pixReadMemTiff(data, size, 0); + if (testcomp_mem(pix, &pixt, i, IFF_TIFF_G4)) success = FALSE; + readHeaderMemTiff(data, size, 0, &w, &h, &bps, &spp, + NULL, NULL, NULL); + lept_stderr("(w,h,bps,spp) = (%d,%d,%d,%d)\n", w, h, bps, spp); + lept_free(data); + pixWriteMemTiff(&data, &size, pix, IFF_TIFF_RLE); + nbytes = nbytesInFile("/tmp/lept/regout/junkrle.tif"); + lept_stderr("nbytes = %lu, size = %lu\n", + (unsigned long)nbytes, (unsigned long)size); + pixt = pixReadMemTiff(data, size, 0); + if (testcomp_mem(pix, &pixt, i, IFF_TIFF_RLE)) success = FALSE; + lept_free(data); + pixWriteMemTiff(&data, &size, pix, IFF_TIFF_PACKBITS); + nbytes = nbytesInFile("/tmp/lept/regout/junkpb.tif"); + lept_stderr("nbytes = %lu, size = %lu\n", + (unsigned long)nbytes, (unsigned long)size); + pixt = pixReadMemTiff(data, size, 0); + if (testcomp_mem(pix, &pixt, i, IFF_TIFF_PACKBITS)) success = FALSE; + lept_free(data); + } + pixWriteMemTiff(&data, &size, pix, IFF_TIFF_LZW); + pixt = pixReadMemTiff(data, size, 0); + if (testcomp_mem(pix, &pixt, i, IFF_TIFF_LZW)) success = FALSE; + lept_free(data); + pixWriteMemTiff(&data, &size, pix, IFF_TIFF_ZIP); + pixt = pixReadMemTiff(data, size, 0); + if (testcomp_mem(pix, &pixt, i, IFF_TIFF_ZIP)) success = FALSE; + readHeaderMemTiff(data, size, 0, &w, &h, &bps, &spp, NULL, NULL, NULL); + lept_stderr("(w,h,bps,spp) = (%d,%d,%d,%d)\n", w, h, bps, spp); + lept_free(data); + pixWriteMemTiff(&data, &size, pix, IFF_TIFF); + pixt = pixReadMemTiff(data, size, 0); + if (testcomp_mem(pix, &pixt, i, IFF_TIFF)) success = FALSE; + lept_free(data); + pixDestroy(&pix); + } + if (success) + lept_stderr( + "\n ********** Success on tiff r/w to memory *********\n\n"); + else + lept_stderr( + "\n ******* Failure on at least one tiff r/w to memory ******\n\n"); + if (!success) failure = TRUE; + + /* ---------------- Part 4: Test non-tiff r/w to memory ---------------- */ + + success = (n < 6) ? FALSE : TRUE; + for (i = 0; i < n; i++) { + if ((pix = pixaGetPix(pixa, i, L_CLONE)) == NULL) { + success = FALSE; + continue; + } + d = pixGetDepth(pix); + snprintf(psname, sizeof(psname), "/tmp/lept/regout/junkps.%d", d); + lept_stderr("%d bpp\n", d); + if (test_writemem(pix, IFF_PNM, NULL)) success = FALSE; + if (test_writemem(pix, IFF_PS, psname)) success = FALSE; + if (d == 16) { + pixDestroy(&pix); + continue; + } + if (test_writemem(pix, IFF_PNG, NULL)) success = FALSE; + if (test_writemem(pix, IFF_BMP, NULL)) success = FALSE; + if (d != 32) + if (test_writemem(pix, IFF_GIF, NULL)) success = FALSE; + if (d == 8 || d == 32) { + if (test_writemem(pix, IFF_JFIF_JPEG, NULL)) success = FALSE; + if (test_writemem(pix, IFF_JP2, NULL)) success = FALSE; + if (test_writemem(pix, IFF_WEBP, NULL)) success = FALSE; + } + pixDestroy(&pix); + } + if (success) + lept_stderr( + "\n ********** Success on non-tiff r/w to memory *********\n\n"); + else + lept_stderr( + "\n **** Failure on at least one non-tiff r/w to memory *****\n\n"); + if (!success) failure = TRUE; + pixaDestroy(&pixa); + + /* ------------ Part 5: Test multipage tiff r/w to memory ------------ */ + + /* Make a multipage tiff file, and read it back into memory */ + pix = pixRead("feyn.tif"); + pixa = pixaSplitPix(pix, 3, 3, 0, 0); + for (i = 0; i < 9; i++) { + if ((pixt = pixaGetPix(pixa, i, L_CLONE)) == NULL) + continue; + if (i == 0) + pixWriteTiff("/tmp/lept/regout/junktiffmpage.tif", pixt, + IFF_TIFF_G4, "w"); + else + pixWriteTiff("/tmp/lept/regout/junktiffmpage.tif", pixt, + IFF_TIFF_G4, "a"); + pixDestroy(&pixt); + } + data = l_binaryRead("/tmp/lept/regout/junktiffmpage.tif", &nbytes); + pixaDestroy(&pixa); + + /* Read the individual pages from memory to a pix */ + pixa = pixaCreate(9); + for (i = 0; i < 9; i++) { + pixt = pixReadMemTiff(data, nbytes, i); + pixaAddPix(pixa, pixt, L_INSERT); + } + lept_free(data); + + /* Un-tile the pix in the pixa back to the original image */ + pixt = pixaDisplayUnsplit(pixa, 3, 3, 0, 0); + pixaDestroy(&pixa); + + /* Clip to foreground to remove any extra rows or columns */ + pixClipToForeground(pix, &pix1, NULL); + pixClipToForeground(pixt, &pix2, NULL); + pixEqual(pix1, pix2, &same); + if (same) + lept_stderr( + "\n ******* Success on tiff multipage read from memory ******\n\n"); + else + lept_stderr( + "\n ******* Failure on tiff multipage read from memory ******\n\n"); + if (!same) failure = TRUE; + + pixDestroy(&pix); + pixDestroy(&pixt); + pixDestroy(&pix1); + pixDestroy(&pix2); + + /* ------------ Part 6: Test 24 bpp writing ------------ */ +#if !HAVE_LIBTIFF +part6: +#endif /* !HAVE_LIBTIFF */ + +#if !HAVE_LIBPNG || !HAVE_LIBJPEG || !HAVE_LIBTIFF + lept_stderr("Missing libpng, libjpeg or libtiff. Skipping:\n" + " part 6 (24 bpp r/w)\n" + " part 7 (header read)\n\n"); + goto finish; +#endif /* !HAVE_LIBPNG || !HAVE_LIBJPEG || !HAVE_LIBTIFF */ + + /* Generate a 24 bpp (not 32 bpp !!) rgb pix and write it out */ + success = TRUE; + if ((pix = pixRead("marge.jpg")) == NULL) + success = FALSE; + pixt = make_24_bpp_pix(pix); + pixWrite("/tmp/lept/regout/junk24.png", pixt, IFF_PNG); + pixWrite("/tmp/lept/regout/junk24.jpg", pixt, IFF_JFIF_JPEG); + pixWrite("/tmp/lept/regout/junk24.tif", pixt, IFF_TIFF); + pixd = pixRead("/tmp/lept/regout/junk24.png"); + pixEqual(pix, pixd, &same); + if (same) { + lept_stderr(" **** success writing 24 bpp png ****\n"); + } else { + lept_stderr(" **** failure writing 24 bpp png ****\n"); + success = FALSE; + } + pixDestroy(&pixd); + pixd = pixRead("/tmp/lept/regout/junk24.jpg"); + regTestCompareSimilarPix(rp, pix, pixd, 10, 0.0002, 0); + pixDestroy(&pixd); + pixd = pixRead("/tmp/lept/regout/junk24.tif"); + pixEqual(pix, pixd, &same); + if (same) { + lept_stderr(" **** success writing 24 bpp tif ****\n"); + } else { + lept_stderr(" **** failure writing 24 bpp tif ****\n"); + success = FALSE; + } + pixDestroy(&pixd); + if (success) + lept_stderr("\n ******* Success on 24 bpp rgb writing *******\n\n"); + else + lept_stderr("\n ******* Failure on 24 bpp rgb writing *******\n\n"); + if (!success) failure = TRUE; + pixDestroy(&pix); + pixDestroy(&pixt); + + /* -------------- Part 7: Read header information -------------- */ + success = TRUE; + if (get_header_data(FILE_1BPP, IFF_TIFF_G4)) success = FALSE; + if (get_header_data(FILE_2BPP, IFF_PNG)) success = FALSE; + if (get_header_data(FILE_2BPP_C, IFF_PNG)) success = FALSE; + if (get_header_data(FILE_4BPP, IFF_PNG)) success = FALSE; + if (get_header_data(FILE_4BPP_C, IFF_PNG)) success = FALSE; + if (get_header_data(FILE_8BPP_1, IFF_PNG)) success = FALSE; + if (get_header_data(FILE_8BPP_2, IFF_PNG)) success = FALSE; + if (get_header_data(FILE_8BPP_3, IFF_JFIF_JPEG)) success = FALSE; + if (get_header_data(FILE_GRAY_ALPHA, IFF_PNG)) success = FALSE; + if (get_header_data(FILE_16BPP, IFF_TIFF_ZIP)) success = FALSE; + if (get_header_data(FILE_32BPP, IFF_JFIF_JPEG)) success = FALSE; + if (get_header_data(FILE_32BPP_ALPHA, IFF_PNG)) success = FALSE; + + pix = pixRead(FILE_8BPP_1); + tempname = l_makeTempFilename(); + pixWrite(tempname, pix, IFF_PNM); + if (get_header_data(tempname, IFF_PNM)) success = FALSE; + pixDestroy(&pix); + + /* These tiff formats work on 1 bpp images */ + pix = pixRead(FILE_1BPP); + pixWrite(tempname, pix, IFF_TIFF_G3); + if (get_header_data(tempname, IFF_TIFF_G3)) success = FALSE; + pixWrite(tempname, pix, IFF_TIFF_G4); + if (get_header_data(tempname, IFF_TIFF_G4)) success = FALSE; + pixWrite(tempname, pix, IFF_TIFF_PACKBITS); + if (get_header_data(tempname, IFF_TIFF_PACKBITS)) success = FALSE; + pixWrite(tempname, pix, IFF_TIFF_RLE); + if (get_header_data(tempname, IFF_TIFF_RLE)) success = FALSE; + pixWrite(tempname, pix, IFF_TIFF_LZW); + if (get_header_data(tempname, IFF_TIFF_LZW)) success = FALSE; + pixWrite(tempname, pix, IFF_TIFF_ZIP); + if (get_header_data(tempname, IFF_TIFF_ZIP)) success = FALSE; + pixWrite(tempname, pix, IFF_TIFF); + if (get_header_data(tempname, IFF_TIFF)) success = FALSE; + pixDestroy(&pix); + lept_rmfile(tempname); + lept_free(tempname); + + if (success) + lept_stderr( "\n ******* Success on reading headers *******\n\n"); + else + lept_stderr( "\n ******* Failure on reading headers *******\n\n"); + if (!success) failure = TRUE; + +#if !HAVE_LIBPNG || !HAVE_LIBJPEG || !HAVE_LIBTIFF +finish: +#endif /* !HAVE_LIBPNG || !HAVE_LIBJPEG || !HAVE_LIBTIFF */ + + if (!failure) + lept_stderr(" ******* Success on all tests *******\n\n"); + else + lept_stderr(" ******* Failure on at least one test *******\n\n"); + + return regTestCleanup(rp); +} + + + /* Returns 1 on error */ +static l_int32 +testcomp(const char *filename, + PIX *pix, + l_int32 comptype) +{ +l_int32 format, sameformat, sameimage; +FILE *fp; +PIX *pixt; + + fp = lept_fopen(filename, "rb"); + findFileFormatStream(fp, &format); + sameformat = TRUE; + if (format != comptype) { + lept_stderr("File %s has format %d, not comptype %d\n", + filename, format, comptype); + sameformat = FALSE; + } + lept_fclose(fp); + pixt = pixRead(filename); + pixEqual(pix, pixt, &sameimage); + pixDestroy(&pixt); + if (!sameimage) + lept_stderr("Write/read fail for file %s with format %d\n", + filename, format); + return (!sameformat || !sameimage); +} + + + /* Returns 1 on error */ +static l_int32 +testcomp_mem(PIX *pixs, + PIX **ppixt, /* input; nulled on return */ + l_int32 index, + l_int32 format) +{ +l_int32 sameimage; +PIX *pixt; + + pixt = *ppixt; + pixEqual(pixs, pixt, &sameimage); + if (!sameimage) + lept_stderr("Mem Write/read fail for file %d with format %d\n", + index, format); + pixDestroy(&pixt); + *ppixt = NULL; + return (!sameimage); +} + + + /* Returns 1 on error */ +static l_int32 +test_writemem(PIX *pixs, + l_int32 format, + char *psfile) +{ +l_uint8 *data = NULL; +l_int32 same = TRUE; +l_int32 ds, dd; +l_float32 diff; +size_t size = 0; +PIX *pixd = NULL; + + if (format == IFF_PS) { + pixWriteMemPS(&data, &size, pixs, NULL, 0, 1.0); + l_binaryWrite(psfile, "w", data, size); + lept_free(data); + return 0; + } + + /* Fail silently if library is not available */ +#if !HAVE_LIBJPEG + if (format == IFF_JFIF_JPEG) + return 0; +#endif /* !HAVE_LIBJPEG */ +#if !HAVE_LIBPNG + if (format == IFF_PNG) + return 0; +#endif /* !HAVE_LIBPNG */ +#if !HAVE_LIBTIFF + if (format == IFF_TIFF) + return 0; +#endif /* !HAVE_LIBTIFF */ +#if !HAVE_LIBWEBP + if (format == IFF_WEBP) + return 0; +#endif /* !HAVE_LIBWEBP */ +#if !HAVE_LIBJP2K + if (format == IFF_JP2) + return 0; +#endif /* !HAVE_LIBJP2K */ +#if !HAVE_LIBGIF + if (format == IFF_GIF) + return 0; +#endif /* !HAVE_LIBGIF */ + + if (pixWriteMem(&data, &size, pixs, format)) { + lept_stderr("Mem write fail for format %d\n", format); + return 1; + } + if ((pixd = pixReadMem(data, size)) == NULL) { + lept_stderr("Mem read fail for format %d\n", format); + lept_free(data); + return 1; + } + + if (format == IFF_JFIF_JPEG || format == IFF_JP2 || + format == IFF_WEBP || format == IFF_TIFF_JPEG) { + ds = pixGetDepth(pixs); + dd = pixGetDepth(pixd); + if (dd == 8) { + pixCompareGray(pixs, pixd, L_COMPARE_ABS_DIFF, 0, NULL, &diff, + NULL, NULL); + } else if (ds == 32 && dd == 32) { + pixCompareRGB(pixs, pixd, L_COMPARE_ABS_DIFF, 0, NULL, &diff, + NULL, NULL); + } else { + lept_stderr("skipping: ds = %d, dd = %d, format = %d\n", + ds, dd, format); + lept_free(data); + pixDestroy(&pixd); + return 0; + } + +/* lept_stderr(" size = %lu bytes; diff = %5.2f, format = %d\n", + (unsigned long)size, diff, format); */ + if (diff > 8.0) { + same = FALSE; + lept_stderr("Mem write/read fail for format %d, diff = %5.2f\n", + format, diff); + } + } else { + pixEqual(pixs, pixd, &same); + if (!same) + lept_stderr("Mem write/read fail for format %d\n", format); + } + pixDestroy(&pixd); + lept_free(data); + return (!same); +} + + + /* Composes 24 bpp rgb pix */ +static PIX * +make_24_bpp_pix(PIX *pixs) +{ +l_int32 i, j, w, h, wpls, wpld, rval, gval, bval; +l_uint32 *lines, *lined, *datas, *datad; +PIX *pixd; + + pixGetDimensions(pixs, &w, &h, NULL); + pixd = pixCreate(w, h, 24); + datas = pixGetData(pixs); + wpls = pixGetWpl(pixs); + datad = pixGetData(pixd); + wpld = pixGetWpl(pixd); + for (i = 0; i < h; i++) { + lines = datas + i * wpls; + lined = datad + i * wpld; + for (j = 0; j < w; j++) { + extractRGBValues(lines[j], &rval, &gval, &bval); + *((l_uint8 *)lined + 3 * j) = rval; + *((l_uint8 *)lined + 3 * j + 1) = gval; + *((l_uint8 *)lined + 3 * j + 2) = bval; + } + } + + return pixd; +} + + + /* Retrieve header data from file */ +static l_int32 +get_header_data(const char *filename, + l_int32 true_format) +{ +const char *tiff_compression_name = "undefined"; +l_uint8 *data; +l_int32 ret1, ret2, format1, format2; +l_int32 w1, w2, h1, h2, d1, d2, bps1, bps2, spp1, spp2, iscmap1, iscmap2; +size_t size1, size2; + + /* Fail silently if library is not available */ +#if !HAVE_LIBJPEG + if (true_format == IFF_JFIF_JPEG) + return 0; +#endif /* !HAVE_LIBJPEG */ +#if !HAVE_LIBPNG + if (true_format == IFF_PNG) + return 0; +#endif /* !HAVE_LIBPNG */ +#if !HAVE_LIBTIFF + if (L_FORMAT_IS_TIFF(true_format)) + return 0; +#endif /* !HAVE_LIBTIFF */ + + /* Read header from file */ + size1 = nbytesInFile(filename); + ret1 = pixReadHeader(filename, &format1, &w1, &h1, &bps1, &spp1, &iscmap1); + d1 = bps1 * spp1; + if (d1 == 24) d1 = 32; + if (ret1) + lept_stderr("Error: couldn't read header data: %s\n", filename); + else { + if (L_FORMAT_IS_TIFF(format1)) { + tiff_compression_name = get_tiff_compression_name(format1); + lept_stderr("Format data for image %s with format %s:\n" + " nbytes = %lu, size (w, h, d) = (%d, %d, %d)\n" + " bps = %d, spp = %d, iscmap = %d\n", + filename, tiff_compression_name, + (unsigned long)size1, w1, h1, d1, + bps1, spp1, iscmap1); + } else { + lept_stderr("Format data for image %s with format %s:\n" + " nbytes = %lu, size (w, h, d) = (%d, %d, %d)\n" + " bps = %d, spp = %d, iscmap = %d\n", + filename, ImageFileFormatExtensions[format1], + (unsigned long)size1, w1, h1, d1, bps1, spp1, iscmap1); + } + if (format1 != true_format) { + lept_stderr("Error: format is %d; should be %d\n", + format1, true_format); + ret1 = 1; + } + } + + /* Read header from array in memory */ + data = l_binaryRead(filename, &size2); + ret2 = pixReadHeaderMem(data, size2, &format2, &w2, &h2, &bps2, + &spp2, &iscmap2); + lept_free(data); + d2 = bps2 * spp2; + if (d2 == 24) d2 = 32; + if (ret2) { + lept_stderr("Error: couldn't mem-read header data: %s\n", filename); + } else { + if (size1 != size2 || format1 != format2 || w1 != w2 || + h1 != h2 || d1 != d2 || bps1 != bps2 || spp1 != spp2 || + iscmap1 != iscmap2) { + lept_stderr("Inconsistency reading image %s with format %s\n", + filename, tiff_compression_name); + ret2 = 1; + } + } + return ret1 || ret2; +} + + +static const char * +get_tiff_compression_name(l_int32 format) +{ + const char *tiff_compression_name = "unknown"; + if (format == IFF_TIFF_G4) + tiff_compression_name = "tiff_g4"; + else if (format == IFF_TIFF_G3) + tiff_compression_name = "tiff_g3"; + else if (format == IFF_TIFF_ZIP) + tiff_compression_name = "tiff_zip"; + else if (format == IFF_TIFF_LZW) + tiff_compression_name = "tiff_lzw"; + else if (format == IFF_TIFF_RLE) + tiff_compression_name = "tiff_rle"; + else if (format == IFF_TIFF_PACKBITS) + tiff_compression_name = "tiff_packbits"; + else if (format == IFF_TIFF_JPEG) + tiff_compression_name = "tiff_jpeg"; + else if (format == IFF_TIFF) + tiff_compression_name = "tiff_uncompressed"; + else + lept_stderr("format %d: not tiff\n", format); + return tiff_compression_name; +} diff --git a/leptonica/prog/iomisc_reg.c b/leptonica/prog/iomisc_reg.c new file mode 100644 index 00000000..eb8d94bd --- /dev/null +++ b/leptonica/prog/iomisc_reg.c @@ -0,0 +1,300 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * iomisc_reg.c + * + * Tests several special I/O operations: + * * special operations for handling 16 bpp png input + * * zlib compression quality in png + * * chroma sampling options in jpeg + * * read/write of alpha with png + * * i/o with colormaps + * * removal and regeneration of rgb and gray colormaps + * * tiff compression + * + * This does not test these exotic formats: + * * multipage/custom tiff (tested by mtiff_reg) + * * pdf (tested by pdfiotest and pdfseg_reg) + * * PostScript (tested by psio_reg and psioseg_reg) + * + * The large error values that are being used for tests 3-7 and 36 + * are only required for older versions of tifflib (e.g., libtiff 4.0.7). + * For libtiff 4.0.11, small values like 10 will pass tests 6, 7 and 36. + * The issue was initially found on the AArch64 (ARM) processor. + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "string.h" +#include "allheaders.h" + +LEPT_DLL extern const char *ImageFileFormatExtensions[]; + +static const size_t zlibsize[5] = {1047873, 215039, 195778, 189709, 180987}; +static const size_t tiffsize[8] = {65674, 34872, 20482, 20998, 11178, + 21500, 18472, 151885}; + +int main(int argc, + char **argv) +{ +char *text; +l_int32 w, h, d, level, wpl, format, xres, yres; +l_int32 bps, spp, res, iscmap; +size_t size; +FILE *fp; +PIX *pixs, *pixg, *pix1, *pix2, *pix3, *pix4; +PIXA *pixa; +PIXCMAP *cmap; +L_REGPARAMS *rp; + + if (regTestSetup(argc, argv, &rp)) + return 1; + + lept_mkdir("lept/io"); + + /* Test 16 to 8 stripping */ + pixs = pixRead("test16.tif"); + pixWrite("/tmp/lept/io/test16.png", pixs, IFF_PNG); + regTestCheckFile(rp, "/tmp/lept/io/test16.png"); /* 0 */ + pix1 = pixRead("/tmp/lept/io/test16.png"); + d = pixGetDepth(pix1); + regTestCompareValues(rp, 8, d, 0.0); /* 1 */ + pixDestroy(&pix1); + l_pngSetReadStrip16To8(0); + pix1 = pixRead("/tmp/lept/io/test16.png"); + d = pixGetDepth(pix1); + regTestCompareValues(rp, 16, d, 0.0); /* 2 */ + pixDestroy(&pix1); + pixDestroy(&pixs); + + /* Test zlib compression in png */ + pixs = pixRead("feyn.tif"); + for (level = 0; level < 5; level += 1) { + pixSetZlibCompression(pixs, 2 * level); + pixWrite("/tmp/lept/io/zlibtest.png", pixs, IFF_PNG); + size = nbytesInFile("/tmp/lept/io/zlibtest.png"); + regTestCompareValues(rp, zlibsize[level], size, 3000.0); /* 3 - 7 */ + if (rp->display) + lept_stderr("zlib level = %d, file size = %ld\n", + level, (unsigned long)size); + } + pixDestroy(&pixs); + + /* Test chroma sampling options in jpeg */ + pixs = pixRead("marge.jpg"); + pixWrite("/tmp/lept/io/chromatest1.jpg", pixs, IFF_JFIF_JPEG); + regTestCheckFile(rp, "/tmp/lept/io/chromatest1.jpg"); /* 8 */ + if (rp->display) { + size = nbytesInFile("/tmp/lept/io/chromatest1.jpg"); + lept_stderr("chroma default: file size = %ld\n", (unsigned long)size); + } + pixSetChromaSampling(pixs, 0); + pixWrite("/tmp/lept/io/chromatest2.jpg", pixs, IFF_JFIF_JPEG); + regTestCheckFile(rp, "/tmp/lept/io/chromatest2.jpg"); /* 9 */ + if (rp->display) { + size = nbytesInFile("/tmp/lept/io/chromatest2.jpg"); + lept_stderr("no ch. sampling: file size = %ld\n", (unsigned long)size); + } + pixSetChromaSampling(pixs, 1); + pixWrite("/tmp/lept/io/chromatest3.jpg", pixs, IFF_JFIF_JPEG); + regTestCheckFile(rp, "/tmp/lept/io/chromatest3.jpg"); /* 10 */ + if (rp->display) { + size = nbytesInFile("/tmp/lept/io/chromatest3.jpg"); + lept_stderr("chroma default: file size = %ld\n", (unsigned long)size); + } + pixDestroy(&pixs); + + /* Test read/write of alpha with png */ + pixs = pixRead("books_logo.png"); + pixDisplayWithTitle(pixs, 0, 100, NULL, rp->display); + pixg = pixGetRGBComponent(pixs, L_ALPHA_CHANNEL); + regTestWritePixAndCheck(rp, pixg, IFF_PNG); /* 11 */ + pixDisplayWithTitle(pixg, 300, 100, NULL, rp->display); + pixDestroy(&pixg); + pix1 = pixAlphaBlendUniform(pixs, 0xffffff00); /* render rgb over white */ + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 12 */ + pixDisplayWithTitle(pix1, 0, 250, NULL, rp->display); + pix2 = pixSetAlphaOverWhite(pix1); /* regenerate alpha from white */ + pixWrite("/tmp/lept/io/logo2.png", pix2, IFF_PNG); + regTestCheckFile(rp, "/tmp/lept/io/logo2.png"); /* 13 */ + pixDisplayWithTitle(pix2, 0, 400, NULL, rp->display); + pixg = pixGetRGBComponent(pix2, L_ALPHA_CHANNEL); + regTestWritePixAndCheck(rp, pixg, IFF_PNG); /* 14 */ + pixDisplayWithTitle(pixg, 300, 400, NULL, rp->display); + pixDestroy(&pixg); + pix3 = pixRead("/tmp/lept/io/logo2.png"); + pix4 = pixAlphaBlendUniform(pix3, 0x00ffff00); /* render rgb over cyan */ + regTestWritePixAndCheck(rp, pix4, IFF_PNG); /* 15 */ + pixDisplayWithTitle(pix3, 0, 550, NULL, rp->display); + pixDestroy(&pix1); + pixDestroy(&pix2); + pixDestroy(&pix3); + pixDestroy(&pix4); + pixDestroy(&pixs); + + /* A little fun with rgb colormaps */ + pixs = pixRead("weasel4.11c.png"); + pixa = pixaCreate(6); + pixaAddPix(pixa, pixs, L_CLONE); + pixGetDimensions(pixs, &w, &h, &d); + wpl = pixGetWpl(pixs); + if (rp->display) + lept_stderr("w = %d, h = %d, d = %d, wpl = %d\n", w, h, d, wpl); + pixGetResolution(pixs, &xres, &yres); + if (rp->display && xres != 0 && yres != 0) + lept_stderr("xres = %d, yres = %d\n", xres, yres); + cmap = pixGetColormap(pixs); + /* Write and read back the colormap */ + if (rp->display) pixcmapWriteStream(stderr, pixGetColormap(pixs)); + fp = lept_fopen("/tmp/lept/io/cmap1", "wb"); + pixcmapWriteStream(fp, pixGetColormap(pixs)); + lept_fclose(fp); + regTestCheckFile(rp, "/tmp/lept/io/cmap1"); /* 16 */ + fp = lept_fopen("/tmp/lept/io/cmap1", "rb"); + cmap = pixcmapReadStream(fp); + lept_fclose(fp); + fp = lept_fopen("/tmp/lept/io/cmap2", "wb"); + pixcmapWriteStream(fp, cmap); + lept_fclose(fp); + regTestCheckFile(rp, "/tmp/lept/io/cmap2"); /* 17 */ + pixcmapDestroy(&cmap); + + /* Remove and regenerate colormap */ + pix1 = pixRemoveColormap(pixs, REMOVE_CMAP_BASED_ON_SRC); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 18 */ + pixaAddPix(pixa, pix1, L_CLONE); + pix2 = pixConvertRGBToColormap(pix1, 1); + regTestWritePixAndCheck(rp, pix2, IFF_PNG); /* 19 */ + pixaAddPix(pixa, pix2, L_CLONE); + pixDestroy(&pixs); + pixDestroy(&pix1); + pixDestroy(&pix2); + + /* Remove and regnerate gray colormap */ + pixs = pixRead("weasel4.5g.png"); + pixaAddPix(pixa, pixs, L_CLONE); + pix1 = pixRemoveColormap(pixs, REMOVE_CMAP_BASED_ON_SRC); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 20 */ + pixaAddPix(pixa, pix1, L_CLONE); + pix2 = pixConvertGrayToColormap(pix1); + regTestWritePixAndCheck(rp, pix2, IFF_PNG); /* 21 */ + pixaAddPix(pixa, pix2, L_CLONE); + pixDestroy(&pix1); + pixDestroy(&pix2); + pix3 = pixaDisplayTiled(pixa, 400, 0, 20); + pixDisplayWithTitle(pix3, 0, 750, NULL, rp->display); + pixDestroy(&pix3); + pixaDestroy(&pixa); + + /* Other fields in the pix */ + format = pixGetInputFormat(pixs); + regTestCompareValues(rp, format, IFF_PNG, 0.0); /* 22 */ + if (rp->display) + lept_stderr("Input format extension: %s\n", + ImageFileFormatExtensions[format]); + pixSetText(pixs, "reconstituted 4-bit weasel"); + text = pixGetText(pixs); + if (rp->display && text && strlen(text) != 0) + lept_stderr("Text: %s\n", text); + pixDestroy(&pixs); + + /* Some tiff compression and headers */ + readHeaderTiff("feyn-fract.tif", 0, &w, &h, &bps, &spp, + &res, &iscmap, &format); + if (rp->display) { + lept_stderr("w = %d, h = %d, bps = %d, spp = %d, res = %d, cmap = %d\n", + w, h, bps, spp, res, iscmap); + lept_stderr("Input format extension: %s\n", + ImageFileFormatExtensions[format]); + } + pixs = pixRead("feyn-fract.tif"); + pixWrite("/tmp/lept/io/fract1.tif", pixs, IFF_TIFF); + regTestCheckFile(rp, "/tmp/lept/io/fract1.tif"); /* 23 */ + size = nbytesInFile("/tmp/lept/io/fract1.tif"); + regTestCompareValues(rp, tiffsize[0], size, 0.0); /* 24 */ + if (rp->display) + lept_stderr("uncompressed: %ld\n", (unsigned long)size); + pixWrite("/tmp/lept/io/fract2.tif", pixs, IFF_TIFF_PACKBITS); + regTestCheckFile(rp, "/tmp/lept/io/fract2.tif"); /* 25 */ + size = nbytesInFile("/tmp/lept/io/fract2.tif"); + regTestCompareValues(rp, tiffsize[1], size, 0.0); /* 26 */ + if (rp->display) + lept_stderr("packbits: %ld\n", (unsigned long)size); + pixWrite("/tmp/lept/io/fract3.tif", pixs, IFF_TIFF_RLE); + regTestCheckFile(rp, "/tmp/lept/io/fract3.tif"); /* 27 */ + size = nbytesInFile("/tmp/lept/io/fract3.tif"); + regTestCompareValues(rp, tiffsize[2], size, 0.0); /* 28 */ + if (rp->display) + lept_stderr("rle: %ld\n", (unsigned long)size); + pixWrite("/tmp/lept/io/fract4.tif", pixs, IFF_TIFF_G3); + regTestCheckFile(rp, "/tmp/lept/io/fract4.tif"); /* 29 */ + size = nbytesInFile("/tmp/lept/io/fract4.tif"); + regTestCompareValues(rp, tiffsize[3], size, 0.0); /* 30 */ + if (rp->display) + lept_stderr("g3: %ld\n", (unsigned long)size); + pixWrite("/tmp/lept/io/fract5.tif", pixs, IFF_TIFF_G4); + regTestCheckFile(rp, "/tmp/lept/io/fract5.tif"); /* 31 */ + size = nbytesInFile("/tmp/lept/io/fract5.tif"); + regTestCompareValues(rp, tiffsize[4], size, 0.0); /* 32 */ + if (rp->display) + lept_stderr("g4: %ld\n", (unsigned long)size); + pixWrite("/tmp/lept/io/fract6.tif", pixs, IFF_TIFF_LZW); + regTestCheckFile(rp, "/tmp/lept/io/fract6.tif"); /* 33 */ + size = nbytesInFile("/tmp/lept/io/fract6.tif"); + regTestCompareValues(rp, tiffsize[5], size, 0.0); /* 34 */ + if (rp->display) + lept_stderr("lzw: %ld\n", (unsigned long)size); + pixWrite("/tmp/lept/io/fract7.tif", pixs, IFF_TIFF_ZIP); + regTestCheckFile(rp, "/tmp/lept/io/fract7.tif"); /* 35 */ + size = nbytesInFile("/tmp/lept/io/fract7.tif"); + regTestCompareValues(rp, tiffsize[6], size, 200.0); /* 36 */ + if (rp->display) + lept_stderr("zip: %ld\n", (unsigned long)size); + pixg = pixConvertTo8(pixs, 0); + pixWrite("/tmp/lept/io/fract8.tif", pixg, IFF_TIFF_JPEG); + regTestCheckFile(rp, "/tmp/lept/io/fract8.tif"); /* 37 */ + size = nbytesInFile("/tmp/lept/io/fract8.tif"); + regTestCompareValues(rp, tiffsize[7], size, 100.0); /* 38 */ + if (rp->display) + lept_stderr("jpeg: %ld\n", (unsigned long)size); + pixDestroy(&pixs); + pixDestroy(&pixg); + + /* Test read/write of alpha with pnm */ + pixs = pixRead("books_logo.png"); + pixWrite("/tmp/lept/io/alpha1.pnm", pixs, IFF_PNM); + regTestCheckFile(rp, "/tmp/lept/io/alpha1.pnm"); /* 39 */ + pix1 = pixRead("/tmp/lept/io/alpha1.pnm"); + regTestComparePix(rp, pixs, pix1); /* 40 */ + pixDisplayWithTitle(pix1, 600, 100, NULL, rp->display); + pixDestroy(&pixs); + pixDestroy(&pix1); + + return regTestCleanup(rp); +} diff --git a/leptonica/prog/italic.png b/leptonica/prog/italic.png Binary files differnew file mode 100644 index 00000000..7fdc9fc2 --- /dev/null +++ b/leptonica/prog/italic.png diff --git a/leptonica/prog/italic_reg.c b/leptonica/prog/italic_reg.c new file mode 100644 index 00000000..0bb04dc1 --- /dev/null +++ b/leptonica/prog/italic_reg.c @@ -0,0 +1,116 @@ +/*====================================================================* + - 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. + *====================================================================*/ + + +/* + * italic_reg.c + * + * This demonstrates binary reconstruction for finding italic text. + * It also tests debug output of word masking. + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + +int main(int argc, + char **argv) +{ +char opstring[32]; +l_int32 size; +BOXA *boxa1, *boxa2, *boxa3, *boxa4; +PIX *pixs, *pixm, *pix1; +PIXA *pixadb; +L_REGPARAMS *rp; + +#if !defined(HAVE_LIBPNG) + L_ERROR("This test requires libpng to run.\n", "italic_reg"); + exit(77); +#endif + + if (regTestSetup(argc, argv, &rp)) + return 1; + + lept_mkdir("lept/ital"); + pixs = pixRead("italic.png"); + + /* Basic functionality with debug flag */ + pixItalicWords(pixs, NULL, NULL, &boxa1, 1); + boxaWrite("/tmp/lept/ital/ital1.ba", boxa1); + regTestCheckFile(rp, "/tmp/lept/ital/ital1.ba"); /* 0 */ + regTestCheckFile(rp, "/tmp/lept/ital/ital.pdf"); /* 1 */ + pix1 = pixRead("/tmp/lept/ital/ital.png"); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 2 */ + pixDisplayWithTitle(pix1, 0, 0, "Intermediate steps", rp->display); + pixDestroy(&pix1); + pix1 = pixRead("/tmp/lept/ital/runhisto.png"); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 3 */ + pixDisplayWithTitle(pix1, 400, 0, "Histogram of white runs", rp->display); + pixDestroy(&pix1); + + /* Generate word mask */ + pixadb = pixaCreate(5); + pixWordMaskByDilation(pixs, NULL, &size, pixadb); + l_pdfSetDateAndVersion(0); + pixaConvertToPdf(pixadb, 100, 1.0, L_FLATE_ENCODE, 0, "Word Mask", + "/tmp/lept/ital/wordmask.pdf"); + regTestCheckFile(rp, "/tmp/lept/ital/wordmask.pdf"); /* 4 */ + pix1 = pixaDisplayTiledInColumns(pixadb, 1, 1.0, 25, 2); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 5 */ + pixDisplayWithTitle(pix1, 1400, 0, "Intermediate mask step", rp->display); + pixDestroy(&pix1); + pixaDestroy(&pixadb); + L_INFO("dilation size = %d\n", rp->testname, size); + snprintf(opstring, sizeof(opstring), "d1.5 + c%d.1", size); + pixm = pixMorphSequence(pixs, opstring, 0); + regTestWritePixAndCheck(rp, pixm, IFF_PNG); /* 6 */ + pixDisplayWithTitle(pixm, 400, 550, "Word mask", rp->display); + + /* Re-run italic finder using the word mask */ + pixItalicWords(pixs, NULL, pixm, &boxa2, 1); + boxaWrite("/tmp/lept/ital/ital2.ba", boxa2); + regTestCheckFile(rp, "/tmp/lept/ital/ital2.ba"); /* 7 */ + + /* Re-run italic finder using word mask bounding boxes */ + boxa3 = pixConnComp(pixm, NULL, 8); + pixItalicWords(pixs, boxa3, NULL, &boxa4, 1); + boxaWrite("/tmp/lept/ital/ital3.ba", boxa3); + regTestCheckFile(rp, "/tmp/lept/ital/ital3.ba"); /* 8 */ + boxaWrite("/tmp/lept/ital/ital4.ba", boxa4); + regTestCheckFile(rp, "/tmp/lept/ital/ital4.ba"); /* 9 */ + regTestCompareFiles(rp, 7, 9); /* 10 */ + + boxaDestroy(&boxa1); + boxaDestroy(&boxa2); + boxaDestroy(&boxa3); + boxaDestroy(&boxa4); + pixDestroy(&pixs); + pixDestroy(&pixm); + return regTestCleanup(rp); +} + diff --git a/leptonica/prog/jbclass_reg.c b/leptonica/prog/jbclass_reg.c new file mode 100644 index 00000000..fd220d0c --- /dev/null +++ b/leptonica/prog/jbclass_reg.c @@ -0,0 +1,211 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * jbclass_reg.c + * + * Regression test for + * jbCorrelation + * jbRankhaus + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + + /* Choose one of these */ +#define COMPONENTS JB_CONN_COMPS +/* #define COMPONENTS JB_CHARACTERS */ +/* #define COMPONENTS JB_WORDS */ + +static PIXA *PixaOutlineTemplates(PIXA *pixas, NUMA *na); + + +int main(int argc, + char **argv) +{ +l_int32 i, w, h; +BOX *box; +JBDATA *data; +JBCLASSER *classer; +NUMA *na; +SARRAY *sa; +PIX *pix1, *pix2; +PIXA *pixa1, *pixa2; +L_REGPARAMS *rp; + + if (regTestSetup(argc, argv, &rp)) + return 1; + + lept_mkdir("lept/class"); + + /* Set up the input data */ + pix1 = pixRead("pageseg1.tif"); + pixGetDimensions(pix1, &w, &h, NULL); + box = boxCreate(0, 0, w, h / 2); + pix2 = pixClipRectangle(pix1, box, NULL); + pixWrite("/tmp/lept/class/pix1.tif", pix2, IFF_TIFF_G4); + pixDestroy(&pix1); + pixDestroy(&pix2); + pix1 = pixRead("pageseg4.tif"); + pix2 = pixClipRectangle(pix1, box, NULL); + pixWrite("/tmp/lept/class/pix2.tif", pix2, IFF_TIFF_G4); + pixDestroy(&pix1); + pixDestroy(&pix2); + boxDestroy(&box); + sa = sarrayCreate(2); + sarrayAddString(sa, "/tmp/lept/class/pix1.tif", L_COPY); + sarrayAddString(sa, "/tmp/lept/class/pix2.tif", L_COPY); + + /*--------------------------------------------------------------*/ + + /* Run the correlation-based classifier */ + classer = jbCorrelationInit(COMPONENTS, 0, 0, 0.8, 0.6); + jbAddPages(classer, sa); + + /* Save and write out the result */ + data = jbDataSave(classer); + jbDataWrite("/tmp/lept/class/corr", data); + lept_stderr("Number of classes: %d\n", classer->nclass); + + pix1 = pixRead("/tmp/lept/class/corr.templates.png"); + regTestWritePixAndCheck(rp, pix1, IFF_TIFF_G4); /* 0 */ + pixDisplayWithTitle(pix1, 0, 0, NULL, rp->display); + pixDestroy(&pix1); + + /* Render the pages from the classifier data. + * Use debugflag == FALSE to omit outlines of each component. */ + pixa1 = jbDataRender(data, FALSE); + for (i = 0; i < 2; i++) { + pix1 = pixaGetPix(pixa1, i, L_CLONE); + regTestWritePixAndCheck(rp, pix1, IFF_TIFF_G4); /* 1, 2 */ + pixDestroy(&pix1); + } + pixaDestroy(&pixa1); + + /* Display all instances, organized by template */ + pixa1 = pixaaFlattenToPixa(classer->pixaa, &na, L_CLONE); + pixa2 = PixaOutlineTemplates(pixa1, na); + pix1 = pixaDisplayTiledInColumns(pixa2, 40, 1.0, 10, 0); + regTestWritePixAndCheck(rp, pix1, IFF_TIFF_G4); /* 3 */ + pixDestroy(&pix1); + pixaDestroy(&pixa1); + pixaDestroy(&pixa2); + numaDestroy(&na); + jbClasserDestroy(&classer); + jbDataDestroy(&data); + + /*--------------------------------------------------------------*/ + + lept_mkdir("lept/class2"); + + /* Run the rank hausdorff-based classifier */ + classer = jbRankHausInit(COMPONENTS, 0, 0, 2, 0.97); + jbAddPages(classer, sa); + + /* Save and write out the result */ + data = jbDataSave(classer); + jbDataWrite("/tmp/lept/class2/haus", data); + lept_stderr("Number of classes: %d\n", classer->nclass); + + pix1 = pixRead("/tmp/lept/class2/haus.templates.png"); + regTestWritePixAndCheck(rp, pix1, IFF_TIFF_G4); /* 4 */ + pixDisplayWithTitle(pix1, 200, 0, NULL, rp->display); + pixDestroy(&pix1); + + /* Render the pages from the classifier data. + * Use debugflag == FALSE to omit outlines of each component. */ + pixa1 = jbDataRender(data, FALSE); + for (i = 0; i < 2; i++) { + pix1 = pixaGetPix(pixa1, i, L_CLONE); + regTestWritePixAndCheck(rp, pix1, IFF_TIFF_G4); /* 5, 6 */ + pixDestroy(&pix1); + } + pixaDestroy(&pixa1); + + /* Display all instances, organized by template */ + pixa1 = pixaaFlattenToPixa(classer->pixaa, &na, L_CLONE); + pixa2 = PixaOutlineTemplates(pixa1, na); + pix1 = pixaDisplayTiledInColumns(pixa2, 40, 1.0, 10, 0); + regTestWritePixAndCheck(rp, pix1, IFF_TIFF_G4); /* 7 */ + pixDestroy(&pix1); + pixaDestroy(&pixa1); + pixaDestroy(&pixa2); + numaDestroy(&na); + jbClasserDestroy(&classer); + jbDataDestroy(&data); + + /*--------------------------------------------------------------*/ + + sarrayDestroy(&sa); + return regTestCleanup(rp); +} + + +static PIXA * +PixaOutlineTemplates(PIXA *pixas, + NUMA *na) +{ +l_int32 i, n, val, prev, curr; +NUMA *nai; +PIX *pix1, *pix2, *pix3; +PIXA *pixad; + + /* Make an indicator array with a 1 for each template image */ + n = numaGetCount(na); + nai = numaCreate(n); + prev = -1; + for (i = 0; i < n; i++) { + numaGetIValue(na, i, &curr); + if (curr != prev) { /* index change */ + prev = curr; + numaAddNumber(nai, 1); + } else { + numaAddNumber(nai, 0); + } + } + + /* Add a boundary of 3 white and 1 black pixels to templates */ + pixad = pixaCreate(n); + for (i = 0; i < n; i++) { + pix1 = pixaGetPix(pixas, i, L_CLONE); + numaGetIValue(nai, i, &val); + if (val == 0) { + pixaAddPix(pixad, pix1, L_INSERT); + } else { + pix2 = pixAddBorder(pix1, 3, 0); + pix3 = pixAddBorder(pix2, 1, 1); + pixaAddPix(pixad, pix3, L_INSERT); + pixDestroy(&pix1); + pixDestroy(&pix2); + } + } + + numaDestroy(&nai); + return pixad; +} diff --git a/leptonica/prog/jbcorrelation.c b/leptonica/prog/jbcorrelation.c new file mode 100644 index 00000000..205d66f9 --- /dev/null +++ b/leptonica/prog/jbcorrelation.c @@ -0,0 +1,226 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * jbcorrelation.c + * + * jbcorrelation dirin thresh weight [firstpage npages] + * + * dirin: directory of input pages + * thresh: 0.80 - 0.85 is a reasonable compromise between accuracy + * and number of classes, for characters + * weight: 0.6 seems to work reasonably with thresh = 0.8. + * + * Notes: + * (1) All components larger than a default size are not saved. + * The default size is given in jbclass.c. + * (2) The two output files (for templates and c.c. data) + * are written with the rootname + * /tmp/lept/jb/result + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + + /* Choose one of these */ +#define COMPONENTS JB_CONN_COMPS +/* #define COMPONENTS JB_CHARACTERS */ +/* #define COMPONENTS JB_WORDS */ + +#define BUF_SIZE 512 + + /* Select additional debug output */ +#define DEBUG_TEST_DATA_IO 0 +#define RENDER_DEBUG 1 +#define DISPLAY_DIFFERENCE 1 +#define DISPLAY_ALL_INSTANCES 0 + +static const char rootname[] = "/tmp/lept/jb/result"; + +int main(int argc, + char **argv) +{ +char filename[BUF_SIZE]; +char *dirin; +l_int32 i, firstpage, npages, nfiles; +l_float32 thresh, weight; +JBDATA *data; +JBCLASSER *classer; +SARRAY *safiles; +PIX *pix; +PIXA *pixa, *pixadb; +static char mainName[] = "jbcorrelation"; + + if (argc != 4 && argc != 6) + return ERROR_INT( + " Syntax: jbcorrelation dirin thresh weight [firstpage, npages]", + mainName, 1); + dirin = argv[1]; + thresh = atof(argv[2]); + weight = atof(argv[3]); + + if (argc == 4) { + firstpage = 0; + npages = 0; + } + else { + firstpage = atoi(argv[4]); + npages = atoi(argv[5]); + } + + setLeptDebugOK(1); + lept_mkdir("lept/jb"); + +#if 0 + + /*--------------------------------------------------------------*/ + + jbCorrelation(dirin, thresh, weight, COMPONENTS, rootname, + firstpage, npages, 1); + + /*--------------------------------------------------------------*/ + +#else + + /*--------------------------------------------------------------*/ + + safiles = getSortedPathnamesInDirectory(dirin, NULL, firstpage, npages); + nfiles = sarrayGetCount(safiles); + +/* sarrayWriteStream(stderr, safiles); */ + + /* Classify components on requested pages */ + startTimer(); + classer = jbCorrelationInit(COMPONENTS, 0, 0, thresh, weight); + jbAddPages(classer, safiles); + lept_stderr("Time to generate classes: %6.3f sec\n", stopTimer()); + + /* Save and write out the result */ + data = jbDataSave(classer); + jbDataWrite(rootname, data); + lept_stderr("Number of classes: %d\n", classer->nclass); + + /* Render the pages from the classifier data. + * Use debugflag == FALSE to omit outlines of each component. */ + pixa = jbDataRender(data, FALSE); + + /* Write the pages out */ + npages = pixaGetCount(pixa); + if (npages != nfiles) + lept_stderr("npages = %d, nfiles = %d, not equal!\n", npages, nfiles); + for (i = 0; i < npages; i++) { + pix = pixaGetPix(pixa, i, L_CLONE); + snprintf(filename, BUF_SIZE, "%s.%03d", rootname, i); + lept_stderr("filename: %s\n", filename); + pixWrite(filename, pix, IFF_PNG); + pixDestroy(&pix); + } + +#if DISPLAY_DIFFERENCE + { + char *fname; + PIX *pix1, *pix2; + fname = sarrayGetString(safiles, 0, L_NOCOPY); + pix1 = pixRead(fname); + pix2 = pixaGetPix(pixa, 0, L_CLONE); + pixXor(pix1, pix1, pix2); + pixWrite("/tmp/lept/jb/output_diff.png", pix1, IFF_PNG); + pixDestroy(&pix1); + pixDestroy(&pix2); + } +#endif /* DISPLAY_DIFFERENCE */ + +#if DEBUG_TEST_DATA_IO + { + JBDATA *newdata; + PIX *newpix; + PIXA *newpixa; + l_int32 same, iofail; + + /* Read the data back in and render the pages */ + newdata = jbDataRead(rootname); + newpixa = jbDataRender(newdata, FALSE); + iofail = FALSE; + for (i = 0; i < npages; i++) { + pix = pixaGetPix(pixa, i, L_CLONE); + newpix = pixaGetPix(newpixa, i, L_CLONE); + pixEqual(pix, newpix, &same); + if (!same) { + iofail = TRUE; + lept_stderr("pix on page %d are unequal!\n", i); + } + pixDestroy(&pix); + pixDestroy(&newpix); + + } + if (iofail) + lept_stderr("read/write for jbdata fails\n"); + else + lept_stderr("read/write for jbdata succeeds\n"); + jbDataDestroy(&newdata); + pixaDestroy(&newpixa); + } +#endif /* DEBUG_TEST_DATA_IO */ + +#if RENDER_DEBUG + /* Use debugflag == TRUE to see outlines of each component. */ + pixadb = jbDataRender(data, TRUE); + /* Write the debug pages out */ + npages = pixaGetCount(pixadb); + for (i = 0; i < npages; i++) { + pix = pixaGetPix(pixadb, i, L_CLONE); + snprintf(filename, BUF_SIZE, "%s.db.%04d", rootname, i); + lept_stderr("filename: %s\n", filename); + pixWrite(filename, pix, IFF_PNG); + pixDestroy(&pix); + } + pixaDestroy(&pixadb); +#endif /* RENDER_DEBUG */ + +#if DISPLAY_ALL_INSTANCES + /* Display all instances, organized by template. + * The display programs have a lot of trouble with these. */ + pix = pixaaDisplayByPixa(classer->pixaa, 5, 1.0, 10, 0, 0); + pixWrite("/tmp/lept/jb/output_instances", pix, IFF_PNG); + pixDestroy(&pix); +#endif /* DISPLAY_ALL_INSTANCES */ + + pixaDestroy(&pixa); + sarrayDestroy(&safiles); + jbClasserDestroy(&classer); + jbDataDestroy(&data); + + /*--------------------------------------------------------------*/ + +#endif + + return 0; +} + + diff --git a/leptonica/prog/jbrankhaus.c b/leptonica/prog/jbrankhaus.c new file mode 100644 index 00000000..d4eb54f5 --- /dev/null +++ b/leptonica/prog/jbrankhaus.c @@ -0,0 +1,224 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * jbrankhaus.c + * + * jbrankhaus dirin size rank rootname [firstpage npages] + * + * dirin: directory of input pages + * size: size of SE used for dilation + * rank: min pixel fraction required in both directions in match + * + * Notes: + * (1) All components larger than a default size are not saved. + * The default size is given in jbclass.c. + * (2) A set of reasonable values for cc or characters, that + * gives good accuracy without too manyclasses, is: + * size = 2 (2 x 2 structuring element) + * rank = 0.97 + * (3) The two output files (for templates and c.c. data) + * are written with the rootname + * /tmp/lept/jb/result + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + + /* Choose one of these */ +#define COMPONENTS JB_CONN_COMPS +/* #define COMPONENTS JB_CHARACTERS */ +/* #define COMPONENTS JB_WORDS */ + +#define BUF_SIZE 512 + + /* select additional debug output */ +#define DEBUG_TEST_DATA_IO 0 +#define RENDER_DEBUG 1 +#define DISPLAY_DIFFERENCE 1 +#define DISPLAY_ALL_INSTANCES 0 + +static const char rootname[] = "/tmp/lept/jb/result"; + +int main(int argc, + char **argv) +{ +char filename[BUF_SIZE]; +char *dirin, *fname; +l_int32 i, size, firstpage, npages, nfiles; +l_float32 rank; +JBDATA *data; +JBCLASSER *classer; +SARRAY *safiles; +PIX *pix, *pixt; +PIXA *pixa, *pixadb; +static char mainName[] = "jbrankhaus"; + + if (argc != 4 && argc != 6) + return ERROR_INT( + " Syntax: jbrankhaus dirin size rank [firstpage, npages]", + mainName, 1); + dirin = argv[1]; + size = atoi(argv[2]); + rank = atof(argv[3]); + if (argc == 4) { + firstpage = 0; + npages = 0; + } + else { + firstpage = atoi(argv[4]); + npages = atoi(argv[5]); + } + + setLeptDebugOK(1); + lept_mkdir("lept/jb"); + +#if 0 + + /*--------------------------------------------------------------*/ + + jbRankHaus(dirin, size, rank, COMPONENTS, rootname, firstpage, npages, 1); + + /*--------------------------------------------------------------*/ + +#else + + /*--------------------------------------------------------------*/ + + safiles = getSortedPathnamesInDirectory(dirin, NULL, firstpage, npages); + nfiles = sarrayGetCount(safiles); + +/* sarrayWriteStream(stderr, safiles); */ + + /* Classify components on requested pages */ + startTimer(); + classer = jbRankHausInit(COMPONENTS, 0, 0, size, rank); + jbAddPages(classer, safiles); + lept_stderr("Time to classify components: %6.3f sec\n", stopTimer()); + + /* Save and write out the result */ + data = jbDataSave(classer); + jbDataWrite(rootname, data); + + /* Render the pages from the classifier data. + * Use debugflag == FALSE to omit outlines of each component. */ + pixa = jbDataRender(data, FALSE); + + /* Write the pages out */ + npages = pixaGetCount(pixa); + if (npages != nfiles) + lept_stderr("npages = %d, nfiles = %d, not equal!\n", npages, nfiles); + for (i = 0; i < npages; i++) { + pix = pixaGetPix(pixa, i, L_CLONE); + snprintf(filename, BUF_SIZE, "%s.%03d", rootname, i); + lept_stderr("filename: %s\n", filename); + pixWrite(filename, pix, IFF_PNG); + pixDestroy(&pix); + } + +#if DISPLAY_DIFFERENCE + { + char *fname; + PIX *pix1, *pix2; + fname = sarrayGetString(safiles, 0, L_NOCOPY); + pix1 = pixRead(fname); + pix2 = pixaGetPix(pixa, 0, L_CLONE); + pixXor(pix1, pix1, pix2); + pixWrite("/tmp/lept/jb/output_diff.png", pix1, IFF_PNG); + pixDestroy(&pix1); + pixDestroy(&pix2); + } +#endif /* DISPLAY_DIFFERENCE */ + +#if DEBUG_TEST_DATA_IO + { + JBDATA *newdata; + PIX *newpix; + PIXA *newpixa; + l_int32 same, iofail; + + /* Read the data back in and render the pages */ + newdata = jbDataRead(rootname); + newpixa = jbDataRender(newdata, FALSE); + iofail = FALSE; + for (i = 0; i < npages; i++) { + pix = pixaGetPix(pixa, i, L_CLONE); + newpix = pixaGetPix(newpixa, i, L_CLONE); + pixEqual(pix, newpix, &same); + if (!same) { + iofail = TRUE; + lept_stderr("pix on page %d are unequal!\n", i); + } + pixDestroy(&pix); + pixDestroy(&newpix); + + } + if (iofail) + lept_stderr("read/write for jbdata fails\n"); + else + lept_stderr("read/write for jbdata succeeds\n"); + jbDataDestroy(&newdata); + pixaDestroy(&newpixa); + } +#endif /* DEBUG_TEST_DATA_IO */ + +#if RENDER_DEBUG + /* Use debugflag == TRUE to see outlines of each component. */ + pixadb = jbDataRender(data, TRUE); + /* Write the debug pages out */ + npages = pixaGetCount(pixadb); + for (i = 0; i < npages; i++) { + pix = pixaGetPix(pixadb, i, L_CLONE); + snprintf(filename, BUF_SIZE, "%s.db.%04d", rootname, i); + lept_stderr("filename: %s\n", filename); + pixWrite(filename, pix, IFF_PNG); + pixDestroy(&pix); + } + pixaDestroy(&pixadb); +#endif /* RENDER_DEBUG */ + +#if DISPLAY_ALL_INSTANCES + /* Display all instances, organized by template + * The display programs have a lot of trouble with these. */ + pix = pixaaDisplayByPixa(classer->pixaa, 5, 1.0, 10, 0, 0); + pixWrite("/tmp/lept/jb/output_instances", pix, IFF_PNG); + pixDestroy(&pix); +#endif /* DISPLAY_ALL_INSTANCES */ + + pixaDestroy(&pixa); + sarrayDestroy(&safiles); + jbClasserDestroy(&classer); + jbDataDestroy(&data); + + /*--------------------------------------------------------------*/ + +#endif + + return 0; +} diff --git a/leptonica/prog/jbwords.c b/leptonica/prog/jbwords.c new file mode 100644 index 00000000..582cb415 --- /dev/null +++ b/leptonica/prog/jbwords.c @@ -0,0 +1,135 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * jbwords.c + * + * jbwords dirin thresh weight rootname [firstpage npages] + * + * dirin: directory of input pages + * reduction: 1 (full res) or 2 (half-res) + * thresh: 0.80 is a reasonable compromise between accuracy + * and number of classes, for characters + * weight: 0.6 seems to work reasonably with thresh = 0.8. + * rootname: used for naming the two output files (templates + * and c.c. data) + * firstpage: <optional> 0-based; default is 0 + * npages: <optional> use 0 for all pages; default is 0 + * + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + + /* Eliminate very large "words" */ +static const l_int32 MAX_WORD_WIDTH = 500; +static const l_int32 MAX_WORD_HEIGHT = 200; + +#define BUF_SIZE 512 + + /* select additional debug output */ +#define RENDER_PAGES 1 +#define RENDER_DEBUG 1 + + +int main(int argc, + char **argv) +{ +char filename[BUF_SIZE]; +char *dirin, *rootname; +l_int32 reduction, i, firstpage, npages; +l_float32 thresh, weight; +JBDATA *data; +JBCLASSER *classer; +NUMA *natl; +PIX *pix; +PIXA *pixa, *pixadb; +static char mainName[] = "jbwords"; + + if (argc != 6 && argc != 8) + return ERROR_INT(" Syntax: jbwords dirin reduction thresh " + "weight rootname [firstpage, npages]", mainName, 1); + dirin = argv[1]; + reduction = atoi(argv[2]); + thresh = atof(argv[3]); + weight = atof(argv[4]); + rootname = argv[5]; + if (argc == 6) { + firstpage = 0; + npages = 0; + } else { + firstpage = atoi(argv[6]); + npages = atoi(argv[7]); + } + setLeptDebugOK(1); + + classer = jbWordsInTextlines(dirin, reduction, MAX_WORD_WIDTH, + MAX_WORD_HEIGHT, thresh, weight, + &natl, firstpage, npages); + + /* Save and write out the result */ + data = jbDataSave(classer); + jbDataWrite(rootname, data); + +#if RENDER_PAGES + /* Render the pages from the classifier data, and write to file. + * Use debugflag == FALSE to omit outlines of each component. */ + pixa = jbDataRender(data, FALSE); + npages = pixaGetCount(pixa); + for (i = 0; i < npages; i++) { + pix = pixaGetPix(pixa, i, L_CLONE); + snprintf(filename, BUF_SIZE, "%s.%05d", rootname, i); + lept_stderr("filename: %s\n", filename); + pixWrite(filename, pix, IFF_PNG); + pixDestroy(&pix); + } + pixaDestroy(&pixa); +#endif /* RENDER_PAGES */ + +#if RENDER_DEBUG + /* Use debugflag == TRUE to see outlines of each component. */ + pixadb = jbDataRender(data, TRUE); + /* Write the debug pages out */ + npages = pixaGetCount(pixadb); + for (i = 0; i < npages; i++) { + pix = pixaGetPix(pixadb, i, L_CLONE); + snprintf(filename, BUF_SIZE, "%s.db.%05d", rootname, i); + lept_stderr("filename: %s\n", filename); + pixWrite(filename, pix, IFF_PNG); + pixDestroy(&pix); + } + pixaDestroy(&pixadb); +#endif /* RENDER_DEBUG */ + + jbClasserDestroy(&classer); + jbDataDestroy(&data); + numaDestroy(&natl); + return 0; +} + diff --git a/leptonica/prog/jp2kio_reg.c b/leptonica/prog/jp2kio_reg.c new file mode 100644 index 00000000..678063ab --- /dev/null +++ b/leptonica/prog/jp2kio_reg.c @@ -0,0 +1,184 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * jp2kio_reg.c + * + * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + * This is the Leptonica regression test for lossy read/write + * I/O in jp2k format. + * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + * + * This tests reading and writing of images in jp2k format. + * + * * jp2k supports 8 bpp gray, rgb, and rgba. + * * This makes calls into the jpeg2000 library libopenjp2. + * * Compared to reading and writing jpeg, reading jp2k is + * very slow, and writing jp2k is miserably slow. + * * If we try to run this starting with image half the size, + * the library gives opj_start_compress() encoding errors! + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include <math.h> +#include "allheaders.h" + + /* Needed for HAVE_LIBJP2K */ +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +void DoJp2kTest1(L_REGPARAMS *rp, const char *fname); +void DoJp2kTest2(L_REGPARAMS *rp, const char *fname); + + +int main(int argc, + char **argv) +{ +L_REGPARAMS *rp; + +#if !HAVE_LIBJP2K + lept_stderr("jp2kio is not enabled\n" + "libopenjp2 is required for jp2kio_reg\n" + "See environ.h: #define HAVE_LIBJP2K\n" + "See prog/Makefile: link in -lopenjp2\n\n"); + return 0; +#endif /* abort */ + + /* This test uses libjpeg */ +#if !HAVE_LIBJPEG + lept_stderr("libjpeg is required for jp2kio_reg\n\n"); + return 0; +#endif /* abort */ + + if (regTestSetup(argc, argv, &rp)) + return 1; + + DoJp2kTest1(rp, "karen8.jpg"); + DoJp2kTest1(rp, "test24.jpg"); +/* DoJp2kTest2(rp, "karen8.jpg"); */ /* encode fails on smallest image */ + DoJp2kTest2(rp, "test24.jpg"); + return regTestCleanup(rp); +} + + +void DoJp2kTest1(L_REGPARAMS *rp, + const char *fname) +{ +char buf[64]; +char *name; +l_int32 w, h; +BOX *box; +PIX *pix0, *pix1, *pix2, *pix3; + + /* Read, write, read back and write again */ + pix0 = pixRead(fname); + pix1 = pixScale(pix0, 0.5, 0.5); + pixGetDimensions(pix1, &w, &h, NULL); + regTestWritePixAndCheck(rp, pix1, IFF_JP2); + name = regTestGenLocalFilename(rp, -1, IFF_JP2); + pix2 = pixRead(name); + regTestWritePixAndCheck(rp, pix2, IFF_JP2); + pixDisplayWithTitle(pix2, 0, 100, "1", rp->display); + pixDestroy(&pix1); + pixDestroy(&pix2); + + /* Test cropping and scaling in the jp2 interface */ + box = boxCreate(w / 4, h / 4, w / 2, h / 2); + pix1 = pixReadJp2k(name, 1, box, 0, 0); /* read cropped to the box */ + snprintf(buf, sizeof(buf), "/tmp/lept/regout/jp2kio.%02d.jp2", + rp->index + 1); + pixWriteJp2k(buf, pix1, 38, 0, 0, 0); /* write cropped to the box */ + regTestCheckFile(rp, buf); + pix2 = pixRead(buf); /* read the cropped image */ + regTestWritePixAndCheck(rp, pix2, IFF_JP2); + pixDisplayWithTitle(pix2, 500, 100, "2", rp->display); + pix3 = pixReadJp2k(buf, 2, NULL, 0, 0); /* read cropped image at 2x red */ + regTestWritePixAndCheck(rp, pix3, IFF_JP2); + pixDisplayWithTitle(pix3, 1000, 100, "3", rp->display); + pixDestroy(&pix0); + pixDestroy(&pix1); + pixDestroy(&pix2); + pixDestroy(&pix3); + boxDestroy(&box); + lept_free(name); + return; +} + +void DoJp2kTest2(L_REGPARAMS *rp, + const char *fname) +{ +char buf[256]; +char *name; +l_uint8 *data; +l_int32 w, h; +size_t nbytes; +BOX *box; +PIX *pix0, *pix1, *pix2, *pix3; + + /* Test the memory interface */ + pix0 = pixRead(fname); + pix1 = pixScale(pix0, 0.5, 0.5); + pixGetDimensions(pix1, &w, &h, NULL); + regTestWritePixAndCheck(rp, pix1, IFF_JP2); + name = regTestGenLocalFilename(rp, -1, IFF_JP2); + pix2 = pixRead(name); + regTestWritePixAndCheck(rp, pix2, IFF_JP2); + data = l_binaryRead(name, &nbytes); + pix3 = pixReadMemJp2k(data, nbytes, 1, NULL, 0, 0); + regTestWritePixAndCheck(rp, pix3, IFF_JP2); + pixDisplayWithTitle(pix3, 0, 100, "1", rp->display); + pixDestroy(&pix1); + pixDestroy(&pix2); + pixDestroy(&pix3); + lept_free(data); + + /* Test scaling on read with the memory interface */ + box = boxCreate(w / 3, h / 3, w / 3, h / 3); + pix1 = pixReadJp2k(name, 1, box, 0, 0); /* just read the box region */ + snprintf(buf, sizeof(buf), "/tmp/lept/regout/jp2kio.%02d.jp2", + rp->index + 1); + pixWriteJp2k(buf, pix1, 38, 0, 0, 0); /* write cropped to the box */ + regTestCheckFile(rp, buf); + data = l_binaryRead(buf, &nbytes); + pix2 = pixReadMemJp2k(data, nbytes, 1, NULL, 0, 0); /* read it again */ + regTestWritePixAndCheck(rp, pix2, IFF_JP2); + pixDisplayWithTitle(pix2, 500, 100, "2", rp->display); + pix3 = pixReadMemJp2k(data, nbytes, 2, NULL, 0, 0); /* read at 2x red */ + regTestWritePixAndCheck(rp, pix3, IFF_JP2); + pixDisplayWithTitle(pix3, 1000, 100, "3", rp->display); + boxDestroy(&box); + pixDestroy(&pix0); + pixDestroy(&pix1); + pixDestroy(&pix2); + pixDestroy(&pix3); + lept_free(data); + lept_free(name); + return; +} diff --git a/leptonica/prog/jpeg-coded.tif b/leptonica/prog/jpeg-coded.tif Binary files differnew file mode 100644 index 00000000..d4bfb3f7 --- /dev/null +++ b/leptonica/prog/jpeg-coded.tif diff --git a/leptonica/prog/jpegio_reg.c b/leptonica/prog/jpegio_reg.c new file mode 100644 index 00000000..c9a03b69 --- /dev/null +++ b/leptonica/prog/jpegio_reg.c @@ -0,0 +1,265 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * jpegio_reg.c + * + * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + * This is a Leptonica regression test for jpeg I/O + * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + * + * This tests reading and writing of images and image + * metadata, between Pix and compressed data in jpeg format. + * + * This only tests properly written jpeg files. To test + * reading of corrupted jpeg files to insure that the + * reader does not crash, use prog/corrupttest.c. + * + * TODO (5/5/14): Add tests for + * (1) different color spaces + * (2) no chroma subsampling + * (3) luminance only reading + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include <string.h> +#include "allheaders.h" + + /* Needed for HAVE_LIBJPEG */ +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +void DoJpegTest1(L_REGPARAMS *rp, const char *fname); +void DoJpegTest2(L_REGPARAMS *rp, const char *fname); +void DoJpegTest3(L_REGPARAMS *rp, const char *fname); +void DoJpegTest4(L_REGPARAMS *rp, const char *fname); + + +int main(int argc, + char **argv) +{ +L_REGPARAMS *rp; + +#if !HAVE_LIBJPEG + lept_stderr("jpegio is not enabled\n" + "See environ.h: #define HAVE_LIBJPEG\n" + "See prog/Makefile: link in -ljpeg\n\n"); + return 0; +#endif /* abort */ + + if (regTestSetup(argc, argv, &rp)) + return 1; + + DoJpegTest1(rp, "test8.jpg"); + DoJpegTest1(rp, "fish24.jpg"); + DoJpegTest1(rp, "test24.jpg"); + DoJpegTest2(rp, "weasel2.png"); + DoJpegTest2(rp, "weasel2.4g.png"); + DoJpegTest2(rp, "weasel4.png"); + DoJpegTest2(rp, "weasel4.5g.png"); + DoJpegTest2(rp, "weasel4.16c.png"); + DoJpegTest2(rp, "weasel8.16g.png"); + DoJpegTest2(rp, "weasel8.240c.png"); + DoJpegTest3(rp, "lucasta.150.jpg"); + DoJpegTest3(rp, "tetons.jpg"); + DoJpegTest4(rp, "karen8.jpg"); + + return regTestCleanup(rp); +} + + +/* Use this for 8 bpp (no cmap), 24 bpp or 32 bpp pix */ +void DoJpegTest1(L_REGPARAMS *rp, + const char *fname) +{ +size_t size; +l_uint8 *data; +char buf[256]; +PIX *pixs, *pix1, *pix2, *pix3, *pix4, *pix5; + + /* Test file read/write (general functions) */ + pixs = pixRead(fname); + snprintf(buf, sizeof(buf), "/tmp/lept/regout/jpegio.%d.jpg", rp->index + 1); + pixWrite(buf, pixs, IFF_JFIF_JPEG); + pix1 = pixRead(buf); + regTestCompareSimilarPix(rp, pixs, pix1, 6, 0.01, 0); + pixDisplayWithTitle(pix1, 500, 100, "pix1", rp->display); + + /* Test memory read/write (general functions) */ + pixWriteMemJpeg(&data, &size, pixs, 75, 0); + pix2 = pixReadMem(data, size); + regTestComparePix(rp, pix1, pix2); + lept_free(data); + + /* Test file read/write (specialized jpeg functions) */ + pix3 = pixReadJpeg(fname, 0, 1, NULL, 0); + regTestComparePix(rp, pixs, pix3); + snprintf(buf, sizeof(buf), "/tmp/lept/regout/jpegio.%d.jpg", rp->index + 1); + pixWriteJpeg(buf, pix3, 75, 0); + pix4 = pixReadJpeg(buf, 0, 1, NULL, 0); + regTestComparePix(rp, pix2, pix4); + + /* Test memory read/write (specialized jpeg functions) */ + pixWriteMemJpeg(&data, &size, pixs, 75, 0); + pix5 = pixReadMemJpeg(data, size, 0, 1, NULL, 0); + regTestComparePix(rp, pix4, pix5); + lept_free(data); + + pixDestroy(&pixs); + pixDestroy(&pix1); + pixDestroy(&pix2); + pixDestroy(&pix3); + pixDestroy(&pix4); + pixDestroy(&pix5); + return; +} + +/* Use this for colormapped pix and for pix with d < 8 */ +void DoJpegTest2(L_REGPARAMS *rp, + const char *fname) +{ +size_t size; +l_uint8 *data; +char buf[256]; +PIX *pixs, *pix1, *pix2, *pix3, *pix4, *pix5, *pix6; + + /* Test file read/write (general functions) */ + pixs = pixRead(fname); + snprintf(buf, sizeof(buf), "/tmp/lept/regout/jpegio.%d.jpg", rp->index + 1); + pixWrite(buf, pixs, IFF_JFIF_JPEG); + pix1 = pixRead(buf); + if (pixGetColormap(pixs) != NULL) + pix2 = pixRemoveColormap(pixs, REMOVE_CMAP_BASED_ON_SRC); + else + pix2 = pixConvertTo8(pixs, 0); + regTestCompareSimilarPix(rp, pix1, pix2, 20, 0.2, 0); + pixDisplayWithTitle(pix1, 500, 100, "pix1", rp->display); + + /* Test memory read/write (general functions) */ + pixWriteMemJpeg(&data, &size, pixs, 75, 0); + pix3 = pixReadMem(data, size); + regTestComparePix(rp, pix1, pix3); + lept_free(data); + + /* Test file write (specialized jpeg function) */ + pix4 = pixRead(fname); + snprintf(buf, sizeof(buf), "/tmp/lept/regout/jpegio.%d.jpg", rp->index + 1); + pixWriteJpeg(buf, pix4, 75, 0); + pix5 = pixReadJpeg(buf, 0, 1, NULL, 0); + regTestComparePix(rp, pix5, pix5); + + /* Test memory write (specialized jpeg function) */ + pixWriteMemJpeg(&data, &size, pixs, 75, 0); + pix6 = pixReadMemJpeg(data, size, 0, 1, NULL, 0); + regTestComparePix(rp, pix5, pix6); + lept_free(data); + + pixDestroy(&pixs); + pixDestroy(&pix1); + pixDestroy(&pix2); + pixDestroy(&pix3); + pixDestroy(&pix4); + pixDestroy(&pix5); + pixDestroy(&pix6); + return; +} + +void DoJpegTest3(L_REGPARAMS *rp, + const char *fname) +{ +l_int32 w1, h1, bps1, spp1, w2, h2, bps2, spp2, format1, format2; +size_t size; +l_uint8 *data; +PIX *pixs; + + /* Test header reading (specialized jpeg functions) */ + readHeaderJpeg(fname, &w1, &h1, &spp1, NULL, NULL); + pixs = pixRead(fname); + pixWriteMemJpeg(&data, &size, pixs, 75, 0); + readHeaderMemJpeg(data, size, &w2, &h2, &spp2, NULL, NULL); + regTestCompareValues(rp, w1, w2, 0.0); + regTestCompareValues(rp, h1, h2, 0.0); + regTestCompareValues(rp, spp1, spp2, 0.0); + lept_free(data); + + /* Test header reading (general jpeg functions) */ + pixReadHeader(fname, &format1, &w1, &h1, &bps1, &spp1, NULL); + pixWriteMem(&data, &size, pixs, IFF_JFIF_JPEG); + pixReadHeaderMem(data, size, &format2, &w2, &h2, &bps2, &spp2, NULL); + regTestCompareValues(rp, format1, format2, 0.0); + regTestCompareValues(rp, w1, w2, 0.0); + regTestCompareValues(rp, h1, h2, 0.0); + regTestCompareValues(rp, bps1, bps2, 0.0); + regTestCompareValues(rp, bps1, 8, 0.0); + regTestCompareValues(rp, spp1, spp2, 0.0); + lept_stderr("w = %d, h = %d, bps = %d, spp = %d, format = %d\n", + w1, h1, bps1, spp1, format1); + + pixDestroy(&pixs); + lept_free(data); + return; +} + +void DoJpegTest4(L_REGPARAMS *rp, + const char *fname) +{ +char buf[256]; +char comment1[256]; +l_uint8 *comment2; +l_int32 xres, yres; +FILE *fp; +PIX *pixs; + + /* Test special comment and resolution readers */ + pixs = pixRead(fname); + snprintf(comment1, sizeof(comment1), "Test %d", rp->index + 1); + pixSetText(pixs, comment1); + pixSetResolution(pixs, 137, 137); + snprintf(buf, sizeof(buf), "/tmp/lept/regout/jpegio.%d.jpg", rp->index + 1); + pixWrite(buf, pixs, IFF_JFIF_JPEG); + regTestCheckFile(rp, buf); + fp = lept_fopen(buf, "rb"); + fgetJpegResolution(fp, &xres, &yres); + fgetJpegComment(fp, &comment2); + if (!comment2) + comment2 = (l_uint8 *)stringNew(""); + lept_fclose(fp); + regTestCompareValues(rp, xres, 137, 0.0); + regTestCompareValues(rp, yres, 137, 0.0); + regTestCompareStrings(rp, (l_uint8 *)comment1, strlen(comment1), + comment2, strlen((char *)comment2)); + lept_stderr("xres = %d, yres = %d, comment = %s\n", xres, yres, comment1); + + lept_free(comment2); + pixDestroy(&pixs); + return; +} + + diff --git a/leptonica/prog/juditharismax.jpg b/leptonica/prog/juditharismax.jpg Binary files differnew file mode 100644 index 00000000..f1a510d8 --- /dev/null +++ b/leptonica/prog/juditharismax.jpg diff --git a/leptonica/prog/karen8.jpg b/leptonica/prog/karen8.jpg Binary files differnew file mode 100644 index 00000000..e9627d5b --- /dev/null +++ b/leptonica/prog/karen8.jpg diff --git a/leptonica/prog/kernel_reg.c b/leptonica/prog/kernel_reg.c new file mode 100644 index 00000000..997d0d7e --- /dev/null +++ b/leptonica/prog/kernel_reg.c @@ -0,0 +1,356 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * kernel_reg.c + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include <string.h> +#include "allheaders.h" + +static const char *kdatastr = " 20.3 50 80 50 20 " + " 51.4 100 140 100 50 " + " 92.5 160 200 160 90 " + " 53.7 100 140 100 50 " + " 24.9 50 80 50 20 "; + +int main(int argc, + char **argv) +{ +char *str; +l_int32 i, j, same, ok, plottype; +l_float32 sum, avediff, rmsdiff; +L_KERNEL *kel1, *kel2, *kel3, *kel4, *kelx, *kely; +BOX *box; +PIX *pix, *pixs, *pixb, *pixg, *pixd, *pixp, *pixt; +PIX *pixt1, *pixt2, *pixt3; +PIXA *pixa; +PIXAA *paa; +SARRAY *sa; +L_REGPARAMS *rp; + +#if !defined(HAVE_LIBPNG) + L_ERROR("This test requires libpng to run.\n", "kernel_reg"); + exit(77); +#endif + + if (regTestSetup(argc, argv, &rp)) + return 1; + + paa = pixaaCreate(0); + + /* Test creating from a string */ + pixa = pixaCreate(0); + kel1 = kernelCreateFromString(5, 5, 2, 2, kdatastr); + pixd = kernelDisplayInPix(kel1, 41, 2); + pixWrite("/tmp/lept/regout/pixkern.png", pixd, IFF_PNG); + regTestCheckFile(rp, "/tmp/lept/regout/pixkern.png"); /* 0 */ + pixaAddPix(pixa, pixd, L_INSERT); + pixaaAddPixa(paa, pixa, L_INSERT); + kernelDestroy(&kel1); + + /* Test read/write for kernel. Note that both get + * compared to the same golden file, which is + * overwritten with a copy of /tmp/lept/regout/kern2.kel */ + kel1 = kernelCreateFromString(5, 5, 2, 2, kdatastr); + kernelWrite("/tmp/lept/regout/kern1.kel", kel1); + regTestCheckFile(rp, "/tmp/lept/regout/kern1.kel"); /* 1 */ + kel2 = kernelRead("/tmp/lept/regout/kern1.kel"); + kernelWrite("/tmp/lept/regout/kern2.kel", kel2); + regTestCheckFile(rp, "/tmp/lept/regout/kern2.kel"); /* 2 */ + regTestCompareFiles(rp, 1, 2); /* 3 */ + kernelDestroy(&kel1); + kernelDestroy(&kel2); + + /* Test creating from a file */ + pixa = pixaCreate(0); + sa = sarrayCreate(0); + sarrayAddString(sa, "# small 3x3 kernel", L_COPY); + sarrayAddString(sa, "3 5", L_COPY); + sarrayAddString(sa, "1 2", L_COPY); + sarrayAddString(sa, "20.5 50 80 50 20", L_COPY); + sarrayAddString(sa, "82. 120 180 120 80", L_COPY); + sarrayAddString(sa, "22.1 50 80 50 20", L_COPY); + str = sarrayToString(sa, 1); + l_binaryWrite("/tmp/lept/regout/kernfile.kel", "w", str, strlen(str)); + kel2 = kernelCreateFromFile("/tmp/lept/regout/kernfile.kel"); + pixd = kernelDisplayInPix(kel2, 41, 2); + pixWrite("/tmp/lept/regout/ker1.png", pixd, IFF_PNG); + regTestCheckFile(rp, "/tmp/lept/regout/ker1.png"); /* 4 */ + pixaAddPix(pixa, pixd, L_INSERT); + sarrayDestroy(&sa); + lept_free(str); + kernelDestroy(&kel2); + + /* Test creating from a pix */ + pixt = pixCreate(5, 3, 8); + pixSetPixel(pixt, 0, 0, 20); + pixSetPixel(pixt, 1, 0, 50); + pixSetPixel(pixt, 2, 0, 80); + pixSetPixel(pixt, 3, 0, 50); + pixSetPixel(pixt, 4, 0, 20); + pixSetPixel(pixt, 0, 1, 80); + pixSetPixel(pixt, 1, 1, 120); + pixSetPixel(pixt, 2, 1, 180); + pixSetPixel(pixt, 3, 1, 120); + pixSetPixel(pixt, 4, 1, 80); + pixSetPixel(pixt, 0, 0, 20); + pixSetPixel(pixt, 1, 2, 50); + pixSetPixel(pixt, 2, 2, 80); + pixSetPixel(pixt, 3, 2, 50); + pixSetPixel(pixt, 4, 2, 20); + kel3 = kernelCreateFromPix(pixt, 1, 2); + pixd = kernelDisplayInPix(kel3, 41, 2); + pixWrite("/tmp/lept/regout/ker2.png", pixd, IFF_PNG); + regTestCheckFile(rp, "/tmp/lept/regout/ker2.png"); /* 5 */ + pixaAddPix(pixa, pixd, L_INSERT); + pixaaAddPixa(paa, pixa, L_INSERT); + pixDestroy(&pixt); + kernelDestroy(&kel3); + + /* Test convolution with kel1 */ + pixa = pixaCreate(0); + pixs = pixRead("test24.jpg"); + pixg = pixScaleRGBToGrayFast(pixs, 3, COLOR_GREEN); + pixaAddPix(pixa, pixg, L_INSERT); + kel1 = kernelCreateFromString(5, 5, 2, 2, kdatastr); + pixd = pixConvolve(pixg, kel1, 8, 1); + pixWrite("/tmp/lept/regout/ker3.png", pixd, IFF_PNG); + regTestCheckFile(rp, "/tmp/lept/regout/ker3.png"); /* 6 */ + pixaAddPix(pixa, pixd, L_INSERT); + pixaaAddPixa(paa, pixa, L_INSERT); + pixDestroy(&pixs); + kernelDestroy(&kel1); + + /* Test convolution with flat rectangular kel; also test + * block convolution with tiling. */ + pixa = pixaCreate(0); + pixs = pixRead("test24.jpg"); + pixg = pixScaleRGBToGrayFast(pixs, 3, COLOR_GREEN); + kel2 = makeFlatKernel(11, 11, 5, 5); + pixd = pixConvolve(pixg, kel2, 8, 1); + pixaAddPix(pixa, pixd, L_COPY); + pixWrite("/tmp/lept/regout/ker4.png", pixd, IFF_PNG); + regTestCheckFile(rp, "/tmp/lept/regout/ker4.png"); /* 7 */ + pixt = pixBlockconv(pixg, 5, 5); + pixaAddPix(pixa, pixt, L_COPY); + pixWrite("/tmp/lept/regout/ker5.png", pixt, IFF_PNG); + regTestCheckFile(rp, "/tmp/lept/regout/ker5.png"); /* 8 */ + if (rp->display) + pixCompareGray(pixd, pixt, L_COMPARE_ABS_DIFF, GPLOT_PNG, NULL, + NULL, NULL, NULL); + pixt2 = pixBlockconvTiled(pixg, 5, 5, 3, 6); + pixaAddPix(pixa, pixt2, L_INSERT); + pixaaAddPixa(paa, pixa, L_INSERT); + pixWrite("/tmp/lept/regout/ker5a.png", pixt2, IFF_PNG); + regTestCheckFile(rp, "/tmp/lept/regout/ker5a.png"); /* 9 */ + + ok = TRUE; + for (i = 1; i <= 7; i++) { + for (j = 1; j <= 7; j++) { + if (i == 1 && j == 1) continue; + pixt2 = pixBlockconvTiled(pixg, 5, 5, j, i); + pixEqual(pixt2, pixd, &same); + if (!same) { + lept_stderr("Error for nx = %d, ny = %d\n", j, i); + ok = FALSE; + } + pixDestroy(&pixt2); + } + } + if (ok) + lept_stderr("OK: Tiled results identical to pixConvolve()\n"); + else + lept_stderr("ERROR: Tiled results not identical to pixConvolve()\n"); + + pixDestroy(&pixs); + pixDestroy(&pixg); + pixDestroy(&pixd); + pixDestroy(&pixt); + kernelDestroy(&kel2); + + /* Do another flat rectangular test; this time with white at edge. + * About 1% of the pixels near the image edge differ by 1 between + * the pixConvolve() and pixBlockconv(). For what it's worth, + * pixConvolve() gives the more accurate result; namely, 255 for + * pixels at the edge. */ + pix = pixRead("pageseg1.tif"); + box = boxCreate(100, 100, 2260, 3160); + pixb = pixClipRectangle(pix, box, NULL); + pixs = pixScaleToGray4(pixb); + + pixa = pixaCreate(0); + kel3 = makeFlatKernel(7, 7, 3, 3); + startTimer(); + pixt = pixConvolve(pixs, kel3, 8, 1); + lept_stderr("Generic convolution time: %5.3f sec\n", stopTimer()); + pixaAddPix(pixa, pixt, L_INSERT); + pixWrite("/tmp/lept/regout/conv1.png", pixt, IFF_PNG); + regTestCheckFile(rp, "/tmp/lept/regout/conv1.png"); /* 10 */ + + startTimer(); + pixt2 = pixBlockconv(pixs, 3, 3); + lept_stderr("Flat block convolution time: %5.3f sec\n", stopTimer()); + pixaAddPix(pixa, pixt2, L_INSERT); + pixWrite("/tmp/lept/regout/conv2.png", pixt2, IFF_PNG); /* ditto */ + regTestCheckFile(rp, "/tmp/lept/regout/conv2.png"); /* 11 */ + + plottype = (rp->display) ? GPLOT_PNG : 0; + pixCompareGray(pixt, pixt2, L_COMPARE_ABS_DIFF, plottype, NULL, + &avediff, &rmsdiff, NULL); + pixp = pixRead("/tmp/lept/comp/compare_gray0.png"); + pixaAddPix(pixa, pixp, L_INSERT); + pixaaAddPixa(paa, pixa, L_INSERT); + pixWrite("/tmp/lept/regout/conv3.png", pixp, IFF_PNG); + regTestCheckFile(rp, "/tmp/lept/regout/conv3.png"); /* 12 */ + lept_stderr("Ave diff = %6.4f, RMS diff = %6.4f\n", avediff, rmsdiff); + if (avediff <= 0.01) + lept_stderr("OK: avediff = %6.4f <= 0.01\n", avediff); + else + lept_stderr("Bad?: avediff = %6.4f > 0.01\n", avediff); + + pixDestroy(&pixs); + pixDestroy(&pix); + pixDestroy(&pixb); + boxDestroy(&box); + kernelDestroy(&kel3); + + /* Do yet another set of flat rectangular tests, this time + * on an RGB image */ + pixs = pixRead("test24.jpg"); + kel4 = makeFlatKernel(7, 7, 3, 3); + startTimer(); + pixt1 = pixConvolveRGB(pixs, kel4); + lept_stderr("Time 7x7 non-separable: %7.3f sec\n", stopTimer()); + pixWrite("/tmp/lept/regout/conv4.jpg", pixt1, IFF_JFIF_JPEG); + regTestCheckFile(rp, "/tmp/lept/regout/conv4.jpg"); /* 13 */ + + kelx = makeFlatKernel(1, 7, 0, 3); + kely = makeFlatKernel(7, 1, 3, 0); + startTimer(); + pixt2 = pixConvolveRGBSep(pixs, kelx, kely); + lept_stderr("Time 7x1,1x7 separable: %7.3f sec\n", stopTimer()); + pixWrite("/tmp/lept/regout/conv5.jpg", pixt2, IFF_JFIF_JPEG); + regTestCheckFile(rp, "/tmp/lept/regout/conv5.jpg"); /* 14 */ + + startTimer(); + pixt3 = pixBlockconv(pixs, 3, 3); + lept_stderr("Time 7x7 blockconv: %7.3f sec\n", stopTimer()); + pixWrite("/tmp/lept/regout/conv6.jpg", pixt3, IFF_JFIF_JPEG); + regTestCheckFile(rp, "/tmp/lept/regout/conv6.jpg"); /* 15 */ + regTestComparePix(rp, pixt1, pixt2); /* 16 */ + regTestCompareSimilarPix(rp, pixt2, pixt3, 15, 0.0005, 0); /* 17 */ + + pixDestroy(&pixs); + pixDestroy(&pixt1); + pixDestroy(&pixt2); + pixDestroy(&pixt3); + kernelDestroy(&kel4); + kernelDestroy(&kelx); + kernelDestroy(&kely); + + /* Test generation and convolution with gaussian kernel */ + pixa = pixaCreate(0); + pixs = pixRead("test8.jpg"); + pixaAddPix(pixa, pixs, L_COPY); + kel1 = makeGaussianKernel(5, 5, 3.0, 5.0); + kernelGetSum(kel1, &sum); + lept_stderr("Sum for gaussian kernel = %f\n", sum); + kernelWrite("/tmp/lept/regout/gauss.kel", kel1); + pixt = pixConvolve(pixs, kel1, 8, 1); + pixt2 = pixConvolve(pixs, kel1, 16, 0); + pixaAddPix(pixa, pixt, L_INSERT); + pixaAddPix(pixa, pixt2, L_INSERT); + pixWrite("/tmp/lept/regout/ker6.png", pixt, IFF_PNG); + regTestCheckFile(rp, "/tmp/lept/regout/ker6.png"); /* 18 */ + + pixt = kernelDisplayInPix(kel1, 25, 2); + pixaAddPix(pixa, pixt, L_INSERT); + pixaaAddPixa(paa, pixa, L_INSERT); + kernelDestroy(&kel1); + pixDestroy(&pixs); + + /* Test generation and convolution with separable gaussian kernel */ + pixa = pixaCreate(0); + pixs = pixRead("test8.jpg"); + pixaAddPix(pixa, pixs, L_INSERT); + makeGaussianKernelSep(5, 5, 3.0, 5.0, &kelx, &kely); + kernelGetSum(kelx, &sum); + lept_stderr("Sum for x gaussian kernel = %f\n", sum); + kernelGetSum(kely, &sum); + lept_stderr("Sum for y gaussian kernel = %f\n", sum); + kernelWrite("/tmp/lept/regout/gauss.kelx", kelx); + kernelWrite("/tmp/lept/regout/gauss.kely", kely); + + pixt = pixConvolveSep(pixs, kelx, kely, 8, 1); + pixt2 = pixConvolveSep(pixs, kelx, kely, 16, 0); + pixaAddPix(pixa, pixt, L_INSERT); + pixaAddPix(pixa, pixt2, L_INSERT); + pixWrite("/tmp/lept/regout/ker7.png", pixt, IFF_PNG); + regTestCheckFile(rp, "/tmp/lept/regout/ker7.png"); /* 19 */ + + pixt = kernelDisplayInPix(kelx, 25, 2); + pixaAddPix(pixa, pixt, L_INSERT); + pixt = kernelDisplayInPix(kely, 25, 2); + pixaAddPix(pixa, pixt, L_INSERT); + pixaaAddPixa(paa, pixa, L_INSERT); + kernelDestroy(&kelx); + kernelDestroy(&kely); + + /* Test generation and convolution with diff of gaussians kernel */ +/* pixt = pixRead("marge.jpg"); + pixs = pixConvertRGBToLuminance(pixt); + pixDestroy(&pixt); */ + pixa = pixaCreate(0); + pixs = pixRead("test8.jpg"); + pixaAddPix(pixa, pixs, L_INSERT); + kel1 = makeDoGKernel(7, 7, 1.5, 2.7); + kernelGetSum(kel1, &sum); + lept_stderr("Sum for DoG kernel = %f\n", sum); + kernelWrite("/tmp/lept/regout/dog.kel", kel1); + pixt = pixConvolve(pixs, kel1, 8, 0); +/* pixInvert(pixt, pixt); */ + pixaAddPix(pixa, pixt, L_INSERT); + pixWrite("/tmp/lept/regout/ker8.png", pixt, IFF_PNG); + regTestCheckFile(rp, "/tmp/lept/regout/ker8.png"); /* 20 */ + + pixt = kernelDisplayInPix(kel1, 20, 2); + pixaAddPix(pixa, pixt, L_INSERT); + pixaaAddPixa(paa, pixa, L_INSERT); + kernelDestroy(&kel1); + + pixd = pixaaDisplayByPixa(paa, 10, 1.0, 20, 20, 0); + pixDisplayWithTitle(pixd, 100, 100, NULL, rp->display); + pixWrite("/tmp/lept/regout/kernel.jpg", pixd, IFF_JFIF_JPEG); + pixDestroy(&pixd); + pixaaDestroy(&paa); + + return regTestCleanup(rp); +} diff --git a/leptonica/prog/keystone.png b/leptonica/prog/keystone.png Binary files differnew file mode 100644 index 00000000..7b88eb6f --- /dev/null +++ b/leptonica/prog/keystone.png diff --git a/leptonica/prog/label_reg.c b/leptonica/prog/label_reg.c new file mode 100644 index 00000000..ef3e522b --- /dev/null +++ b/leptonica/prog/label_reg.c @@ -0,0 +1,220 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * label_reg.c + * + * Regression test for earthmover distance and these labelling operations: + * Connected component labelling + * Connected component area labelling + * Color coded transform of 1 bpp images + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + +void FindEMD(PIX *pix1, PIX *pix2, l_float32 *pdistr, l_float32 *pdistg, + l_float32 *pdistb); + +l_int32 main(int argc, + char **argv) +{ +l_float32 dist, distr, distg, distb; +NUMA *na1, *na2; +PIX *pix1, *pix2, *pix3, *pix4, *pix5, *pix6; +L_REGPARAMS *rp; + + if (regTestSetup(argc, argv, &rp)) + return 1; + + /* Test earthmover distance: extreme example */ + lept_stderr("Test earthmover distance\n"); + na1 = numaMakeConstant(0, 201); + na2 = numaMakeConstant(0, 201); + numaSetValue(na1, 0, 100); + numaSetValue(na2, 200, 100); + numaEarthMoverDistance(na1, na2, &dist); + regTestCompareValues(rp, 200.0, dist, 0.0001); /* 0 */ + numaDestroy(&na1); + numaDestroy(&na2); + + /* Test connected component labelling */ + lept_stderr("Test c.c. labelling\n"); + pix1 = pixRead("feyn-fract.tif"); + pix2 = pixConnCompTransform(pix1, 8, 8); + regTestWritePixAndCheck(rp, pix2, IFF_PNG); /* 1 */ + pixDisplayWithTitle(pix2, 0, 0, NULL, rp->display); + pix3 = pixConnCompTransform(pix1, 8, 16); + pix4 = pixConvert16To8(pix3, L_LS_BYTE); + regTestCompareSimilarPix(rp, pix2, pix4, 3, 0.001, 0); /* 2 */ + pix5 = pixConnCompTransform(pix1, 8, 32); + pix6 = pixConvert32To8(pix5, L_LS_TWO_BYTES, L_LS_BYTE); + regTestCompareSimilarPix(rp, pix2, pix6, 3, 0.001, 0); /* 3 */ + pixDestroy(&pix2); + pixDestroy(&pix3); + pixDestroy(&pix4); + pixDestroy(&pix5); + pixDestroy(&pix6); + + /* Test connected component area labelling */ + lept_stderr("Test c.c. area labelling\n"); + pix2 = pixConnCompAreaTransform(pix1, 8); + pix3 = pixConvert32To8(pix2, L_LS_TWO_BYTES, L_CLIP_TO_FF); + regTestWritePixAndCheck(rp, pix3, IFF_PNG); /* 4 */ + pixDisplayWithTitle(pix3, 0, 350, NULL, rp->display); + pixMultConstantGray(pix2, 0.3); + pix4 = pixConvert32To8(pix2, L_LS_TWO_BYTES, L_CLIP_TO_FF); + regTestWritePixAndCheck(rp, pix4, IFF_PNG); /* 5 */ + pixDisplayWithTitle(pix4, 0, 700, NULL, rp->display); + pixDestroy(&pix1); + pixDestroy(&pix2); + pixDestroy(&pix3); + pixDestroy(&pix4); + + /* Test color transform: 4-fold symmetry */ + lept_stderr("Test color transform: 4-fold symmetry\n"); + pix1 = pixRead("form1.tif"); + pix2 = pixRotateOrth(pix1, 1); + pix3 = pixRotateOrth(pix1, 2); + pix4 = pixRotateOrth(pix1, 3); + pix5 = pixLocToColorTransform(pix1); + regTestWritePixAndCheck(rp, pix5, IFF_PNG); /* 6 */ + pix6 = pixLocToColorTransform(pix2); + regTestWritePixAndCheck(rp, pix6, IFF_PNG); /* 7 */ + FindEMD(pix5, pix6, &distr, &distg, &distb); + regTestCompareValues(rp, 0.12, distr, 0.01); /* 8 */ + regTestCompareValues(rp, 0.00, distg, 0.01); /* 9 */ + regTestCompareValues(rp, 0.00, distb, 0.01); /* 10 */ + lept_stderr("90 deg rotation: dist (r,g,b) = (%5.2f, %5.2f, %5.2f)\n", + distr, distg, distb); + pixDestroy(&pix6); + pix6 = pixLocToColorTransform(pix3); + regTestWritePixAndCheck(rp, pix6, IFF_PNG); /* 11 */ + FindEMD(pix5, pix6, &distr, &distg, &distb); + regTestCompareValues(rp, 0.12, distr, 0.01); /* 12 */ + regTestCompareValues(rp, 0.09, distg, 0.01); /* 13 */ + regTestCompareValues(rp, 0.00, distb, 0.01); /* 14 */ + lept_stderr("180 deg rotation: dist (r,g,b) = (%5.2f, %5.2f, %5.2f)\n", + distr, distg, distb); + pixDestroy(&pix6); + pix6 = pixLocToColorTransform(pix4); + regTestWritePixAndCheck(rp, pix6, IFF_PNG); /* 15 */ + FindEMD(pix5, pix6, &distr, &distg, &distb); + regTestCompareValues(rp, 0.00, distr, 0.01); /* 16 */ + regTestCompareValues(rp, 0.09, distg, 0.01); /* 17 */ + regTestCompareValues(rp, 0.00, distb, 0.01); /* 18 */ + lept_stderr("270 deg rotation: dist (r,g,b) = (%5.2f, %5.2f, %5.2f)\n", + distr, distg, distb); + pixDestroy(&pix1); + pixDestroy(&pix2); + pixDestroy(&pix3); + pixDestroy(&pix4); + pixDestroy(&pix5); + pixDestroy(&pix6); + + /* Test color transform: same form with translation */ + lept_stderr("Test color transform with translation\n"); + pix1 = pixRead("form1.tif"); + pix2 = pixLocToColorTransform(pix1); + pixDisplayWithTitle(pix2, 0, 0, NULL, rp->display); + pixTranslate(pix1, pix1, 10, 10, L_BRING_IN_WHITE); + pix3 = pixLocToColorTransform(pix1); + regTestWritePixAndCheck(rp, pix3, IFF_PNG); /* 19 */ + pixDisplayWithTitle(pix3, 470, 0, NULL, rp->display); + FindEMD(pix2, pix3, &distr, &distg, &distb); + regTestCompareValues(rp, 1.76, distr, 0.01); /* 20 */ + regTestCompareValues(rp, 2.65, distg, 0.01); /* 21 */ + regTestCompareValues(rp, 2.03, distb, 0.01); /* 22 */ + lept_stderr("Translation dist (r,g,b) = (%5.2f, %5.2f, %5.2f)\n", + distr, distg, distb); + pixDestroy(&pix1); + pixDestroy(&pix2); + pixDestroy(&pix3); + + /* Test color transform: same form with small rotation */ + lept_stderr("Test color transform with small rotation\n"); + pix1 = pixRead("form1.tif"); + pix2 = pixLocToColorTransform(pix1); + pixRotateShearCenterIP(pix1, 0.1, L_BRING_IN_WHITE); + pix3 = pixLocToColorTransform(pix1); + regTestWritePixAndCheck(rp, pix3, IFF_PNG); /* 23 */ + pixDisplayWithTitle(pix3, 880, 0, NULL, rp->display); + FindEMD(pix2, pix3, &distr, &distg, &distb); + regTestCompareValues(rp, 1.50, distr, 0.01); /* 24 */ + regTestCompareValues(rp, 1.71, distg, 0.01); /* 25 */ + regTestCompareValues(rp, 1.42, distb, 0.01); /* 26 */ + lept_stderr("Rotation dist (r,g,b) = (%5.2f, %5.2f, %5.2f)\n", + distr, distg, distb); + pixDestroy(&pix1); + pixDestroy(&pix2); + pixDestroy(&pix3); + + /* Test color transform: 2 different forms */ + lept_stderr("Test color transform (2 forms)\n"); + pix1 = pixRead("form1.tif"); + pix2 = pixLocToColorTransform(pix1); + pixDisplayWithTitle(pix2, 0, 600, NULL, rp->display); + pix3 = pixRead("form2.tif"); + pix4 = pixLocToColorTransform(pix3); + regTestWritePixAndCheck(rp, pix4, IFF_PNG); /* 27 */ + pixDisplayWithTitle(pix4, 470, 600, NULL, rp->display); + FindEMD(pix2, pix4, &distr, &distg, &distb); + regTestCompareValues(rp, 6.10, distr, 0.02); /* 28 */ + regTestCompareValues(rp, 11.13, distg, 0.01); /* 29 */ + regTestCompareValues(rp, 10.53, distb, 0.01); /* 30 */ + lept_stderr("Different forms: dist (r,g,b) = (%5.2f, %5.2f, %5.2f)\n", + distr, distg, distb); + pixDestroy(&pix1); + pixDestroy(&pix2); + pixDestroy(&pix3); + pixDestroy(&pix4); + + return regTestCleanup(rp); +} + + +void FindEMD(PIX *pix1, PIX *pix2, + l_float32 *pdistr, l_float32 *pdistg, l_float32 *pdistb) +{ +NUMA *nar1, *nar2, *nag1, *nag2, *nab1, *nab2; + + pixGetColorHistogram(pix1, 1, &nar1, &nag1, &nab1); + pixGetColorHistogram(pix2, 1, &nar2, &nag2, &nab2); + numaEarthMoverDistance(nar1, nar2, pdistr); + numaEarthMoverDistance(nag1, nag2, pdistg); + numaEarthMoverDistance(nab1, nab2, pdistb); + numaDestroy(&nar1); + numaDestroy(&nar2); + numaDestroy(&nag1); + numaDestroy(&nag2); + numaDestroy(&nab1); + numaDestroy(&nab2); + return; +} + diff --git a/leptonica/prog/lapide.052.100.jpg b/leptonica/prog/lapide.052.100.jpg Binary files differnew file mode 100644 index 00000000..ca3fbf17 --- /dev/null +++ b/leptonica/prog/lapide.052.100.jpg diff --git a/leptonica/prog/leptonica-license.txt b/leptonica/prog/leptonica-license.txt new file mode 100644 index 00000000..73d44c60 --- /dev/null +++ b/leptonica/prog/leptonica-license.txt @@ -0,0 +1,26 @@ +/*====================================================================* + - Copyright (C) 2001-2020 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. + *====================================================================*/ + diff --git a/leptonica/prog/lightcolortest.c b/leptonica/prog/lightcolortest.c new file mode 100644 index 00000000..dee4adc7 --- /dev/null +++ b/leptonica/prog/lightcolortest.c @@ -0,0 +1,128 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * lightcolortest.c + * + * Determines if there are light colors on the image. + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + +static const l_int32 nbins = 10; + +int main(int argc, + char **argv) +{ +char *name, *tail; +l_int32 i, j, n, minval, maxval, rdiff, gdiff, bdiff, maxdiff; +l_uint32 *rau32, *gau32, *bau32, *carray, *darray; +PIX *pixs, *pix1, *pix2, *pix3, *pix4; +PIXA *pixa, *pixa1; +SARRAY *sa; +static char mainName[] = "lightcolortest"; + + if (argc != 1) + return ERROR_INT(" Syntax: lightcolortest", mainName, 1); + + setLeptDebugOK(1); + sa = getSortedPathnamesInDirectory( ".", "comap.", 0, 0); + sarrayWriteStream(stderr, sa); + n = sarrayGetCount(sa); + lept_stderr("n = %d\n", n); + pixa = pixaCreate(n); + for (i = 0; i < n; i++) { + pixa1 = pixaCreate(2); + name = sarrayGetString(sa, i, L_NOCOPY); + splitPathAtDirectory(name, NULL, &tail); + pixs = pixRead(name); + lept_stderr("%s:\n", tail); + pix1 = pixScaleBySampling(pixs, 0.2, 0.2); + + pixGetBinnedComponentRange(pix1, nbins, 2, L_SELECT_RED, + &minval, &maxval, &rau32, 0); + lept_stderr(" Red: max = %d, min = %d\n", maxval, minval); + rdiff = maxval - minval; + pixGetBinnedComponentRange(pix1, nbins, 2, L_SELECT_GREEN, + &minval, &maxval, &gau32, 0); + lept_stderr(" Green: max = %d, min = %d\n", maxval, minval); + gdiff = maxval - minval; + pixGetBinnedComponentRange(pix1, nbins, 2, L_SELECT_BLUE, + &minval, &maxval, &bau32, 0); + lept_stderr(" Blue: max = %d, min = %d\n", maxval, minval); + bdiff = maxval - minval; + lept_stderr("rdiff = %d, gdiff = %d, bdiff = %d\n\n", + rdiff, gdiff, bdiff); + maxdiff = L_MAX(rdiff, gdiff); + maxdiff = L_MAX(maxdiff, bdiff); + if (maxdiff == rdiff) { + carray = rau32; + lept_free(gau32); + lept_free(bau32); + } else if (maxdiff == gdiff) { + carray = gau32; + lept_free(bau32); + lept_free(rau32); + } else { /* maxdiff == bdiff */ + carray = bau32; + lept_free(rau32); + lept_free(gau32); + } + + pix2 = pixDisplayColorArray(carray, nbins, 200, 5, 6); + pixaAddPix(pixa1, pix2, L_INSERT); + + darray = (l_uint32 *)lept_calloc(nbins, sizeof(l_uint32)); + for (j = 0; j < nbins; j++) { + pixelLinearMapToTargetColor(carray[j], carray[nbins - 1], + 0xffffff00, &darray[j]); + } + pix3 = pixDisplayColorArray(darray, nbins, 200, 5, 6); + pixaAddPix(pixa1, pix3, L_INSERT); + pix4 = pixaDisplayLinearly(pixa1, L_VERT, 1.0, 0, 30, 3, NULL); + pixaAddPix(pixa, pix4, L_INSERT); + + pixaDestroy(&pixa1); + pixDestroy(&pixs); + pixDestroy(&pix1); + lept_free(tail); + lept_free(carray); + lept_free(darray); + } + + lept_mkdir("lept/color"); + pixaConvertToPdf(pixa, 100, 1.0, L_FLATE_ENCODE, 0, "lightcolortest", + "/tmp/lept/color/lightcolortest.pdf"); + L_INFO("Generated pdf file: /tmp/lept/color/lightcolortest.pdf", + mainName); + pixaDestroy(&pixa); + sarrayDestroy(&sa); + return 0; +} diff --git a/leptonica/prog/lighttext.jpg b/leptonica/prog/lighttext.jpg Binary files differnew file mode 100644 index 00000000..c5205275 --- /dev/null +++ b/leptonica/prog/lighttext.jpg diff --git a/leptonica/prog/lineremoval_reg.c b/leptonica/prog/lineremoval_reg.c new file mode 100644 index 00000000..422a24b3 --- /dev/null +++ b/leptonica/prog/lineremoval_reg.c @@ -0,0 +1,124 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * lineremoval_reg.c + * + * A fun little application, saved as a regression test. + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + +int main(int argc, + char **argv) +{ +l_float32 angle, conf, deg2rad; +PIX *pixs, *pix1, *pix2, *pix3, *pix4, *pix5; +PIX *pix6, *pix7, *pix8, *pix9; +PIXA *pixa; +L_REGPARAMS *rp; + + if (regTestSetup(argc, argv, &rp)) + return 1; + + deg2rad = 3.14159 / 180.; + pixs = pixRead("dave-orig.png"); + pixa = pixaCreate(0); + + /* Threshold to binary, extracting much of the lines */ + pix1 = pixThresholdToBinary(pixs, 170); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 0 */ + pixaAddPix(pixa, pix1, L_INSERT); + + /* Find the skew angle and deskew using an interpolated + * rotator for anti-aliasing (to avoid jaggies) */ + pixFindSkew(pix1, &angle, &conf); + pix2 = pixRotateAMGray(pixs, deg2rad * angle, 255); + regTestWritePixAndCheck(rp, pix2, IFF_PNG); /* 1 */ + pixaAddPix(pixa, pix2, L_INSERT); + + /* Extract the lines to be removed */ + pix3 = pixCloseGray(pix2, 51, 1); + regTestWritePixAndCheck(rp, pix3, IFF_PNG); /* 2 */ + pixaAddPix(pixa, pix3, L_INSERT); + + /* Solidify the lines to be removed */ + pix4 = pixErodeGray(pix3, 1, 5); + regTestWritePixAndCheck(rp, pix4, IFF_PNG); /* 3 */ + pixaAddPix(pixa, pix4, L_INSERT); + + /* Clean the background of those lines */ + pix5 = pixThresholdToValue(NULL, pix4, 210, 255); + regTestWritePixAndCheck(rp, pix5, IFF_PNG); /* 4 */ + pixaAddPix(pixa, pix5, L_INSERT); + + pix6 = pixThresholdToValue(NULL, pix5, 200, 0); + regTestWritePixAndCheck(rp, pix6, IFF_PNG); /* 5 */ + pixaAddPix(pixa, pix6, L_COPY); + + /* Get paint-through mask for changed pixels */ + pix7 = pixThresholdToBinary(pix6, 210); + regTestWritePixAndCheck(rp, pix7, IFF_PNG); /* 6 */ + pixaAddPix(pixa, pix7, L_INSERT); + + /* Add the inverted, cleaned lines to orig. Because + * the background was cleaned, the inversion is 0, + * so when you add, it doesn't lighten those pixels. + * It only lightens (to white) the pixels in the lines! */ + pixInvert(pix6, pix6); + pix8 = pixAddGray(NULL, pix2, pix6); + regTestWritePixAndCheck(rp, pix8, IFF_PNG); /* 7 */ + pixaAddPix(pixa, pix8, L_COPY); + + pix9 = pixOpenGray(pix8, 1, 9); + regTestWritePixAndCheck(rp, pix9, IFF_PNG); /* 8 */ + pixaAddPix(pixa, pix9, L_INSERT); + pixCombineMasked(pix8, pix9, pix7); + regTestWritePixAndCheck(rp, pix8, IFF_PNG); /* 9 */ + pixaAddPix(pixa, pix8, L_INSERT); + + if (rp->display) { + lept_rmdir("lept/lines"); + lept_mkdir("lept/lines"); + lept_stderr("Writing to: /tmp/lept/lines/lineremoval.pdf\n"); + pixaConvertToPdf(pixa, 0, 1.0, L_FLATE_ENCODE, 0, "lineremoval example", + "/tmp/lept/lines/lineremoval.pdf"); + pix1 = pixaDisplayTiledInColumns(pixa, 5, 0.5, 30, 2); + pixWrite("/tmp/lept/lines/lineremoval.jpg", pix1, IFF_JFIF_JPEG); + pixDisplay(pix1, 100, 100); + pixDestroy(&pix1); + } + + pixaDestroy(&pixa); + pixDestroy(&pixs); + pixDestroy(&pix6); + return regTestCleanup(rp); +} + diff --git a/leptonica/prog/lion-mask.00010.tif b/leptonica/prog/lion-mask.00010.tif Binary files differnew file mode 100644 index 00000000..e66122a6 --- /dev/null +++ b/leptonica/prog/lion-mask.00010.tif diff --git a/leptonica/prog/lion-mask.00016.tif b/leptonica/prog/lion-mask.00016.tif Binary files differnew file mode 100644 index 00000000..d524a80c --- /dev/null +++ b/leptonica/prog/lion-mask.00016.tif diff --git a/leptonica/prog/lion-page.00010.jpg b/leptonica/prog/lion-page.00010.jpg Binary files differnew file mode 100644 index 00000000..41113342 --- /dev/null +++ b/leptonica/prog/lion-page.00010.jpg diff --git a/leptonica/prog/lion-page.00011.png b/leptonica/prog/lion-page.00011.png Binary files differnew file mode 100644 index 00000000..f6252728 --- /dev/null +++ b/leptonica/prog/lion-page.00011.png diff --git a/leptonica/prog/lion-page.00012.png b/leptonica/prog/lion-page.00012.png Binary files differnew file mode 100644 index 00000000..28cf2deb --- /dev/null +++ b/leptonica/prog/lion-page.00012.png diff --git a/leptonica/prog/lion-page.00013.png b/leptonica/prog/lion-page.00013.png Binary files differnew file mode 100644 index 00000000..b41b0a99 --- /dev/null +++ b/leptonica/prog/lion-page.00013.png diff --git a/leptonica/prog/lion-page.00016.jpg b/leptonica/prog/lion-page.00016.jpg Binary files differnew file mode 100644 index 00000000..25427dc3 --- /dev/null +++ b/leptonica/prog/lion-page.00016.jpg diff --git a/leptonica/prog/lion-page.00017.png b/leptonica/prog/lion-page.00017.png Binary files differnew file mode 100644 index 00000000..c7b1c0f3 --- /dev/null +++ b/leptonica/prog/lion-page.00017.png diff --git a/leptonica/prog/listtest.c b/leptonica/prog/listtest.c new file mode 100644 index 00000000..ecbb43df --- /dev/null +++ b/leptonica/prog/listtest.c @@ -0,0 +1,279 @@ +/*====================================================================* + - 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. + *====================================================================*/ + + +/* + * listtest.c + * + * This file tests the main functions in the generic + * list facility, given in list.c and list.h. + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + +int main(int argc, + char **argv) +{ +char *filein; +l_int32 i, n, w, h, samecount, count; +BOX *box, *boxc; +BOXA *boxa, *boxan; +DLLIST *head, *tail, *head2, *tail2, *elem, *nextelem; +PIX *pixs; +static char mainName[] = "listtest"; + + if (argc != 2) + return ERROR_INT(" Syntax: listtest filein", mainName, 1); + filein = argv[1]; + setLeptDebugOK(1); + + boxa = boxan = NULL; + if ((pixs = pixRead(filein)) == NULL) + return ERROR_INT("pix not made", mainName, 1); + + /* start with a boxa */ + boxa = pixConnComp(pixs, NULL, 4); + n = boxaGetCount(boxa); + + /*-------------------------------------------------------* + * Do one of these two ... + *-------------------------------------------------------*/ + if (1) { + /* listAddToTail(): make a list by adding to tail */ + head = NULL; + tail = NULL; + for (i = 0; i < n; i++) { + box = boxaGetBox(boxa, i, L_CLONE); + listAddToTail(&head, &tail, box); + } + } else { + /* listAddToHead(): make a list by adding to head */ + head = NULL; + for (i = 0; i < n; i++) { + box = boxaGetBox(boxa, i, L_CLONE); + listAddToHead(&head, box); + } + } + + /* list concatenation */ + head2 = NULL; /* cons up 2nd list from null */ + tail2 = NULL; + for (i = 0; i < n; i++) { + box = boxaGetBox(boxa, i, L_CLONE); + listAddToTail(&head2, &tail2, box); + } + listJoin(&head, &head2); + + count = listGetCount(head); + lept_stderr("%d items in list\n", count); + listReverse(&head); + count = listGetCount(head); + lept_stderr("%d items in reversed list\n", count); + listReverse(&head); + count = listGetCount(head); + lept_stderr("%d items in doubly reversed list\n", count); + + boxan = boxaCreate(n); + + /*-------------------------------------------------------* + * Then do one of these ... + *-------------------------------------------------------*/ + if (1) { + /* Removal of all elements and data from a list, + * without using L_BEGIN_LIST_FORWARD macro */ + for (elem = head; elem; elem = nextelem) { + nextelem = elem->next; + box = (BOX *)elem->data; + boxaAddBox(boxan, box, L_INSERT); + elem->data = NULL; + listRemoveElement(&head, elem); + } + } else if (0) { + /* Removal of all elements and data from a list, + * using L_BEGIN_LIST_FORWARD macro */ + L_BEGIN_LIST_FORWARD(head, elem) + box = (BOX *)elem->data; + boxaAddBox(boxan, box, L_INSERT); + elem->data = NULL; + listRemoveElement(&head, elem); + L_END_LIST + } else if (0) { + /* Removal of all elements and data from a list, + * using L_BEGIN_LIST_REVERSE macro */ + tail = listFindTail(head); + L_BEGIN_LIST_REVERSE(tail, elem) + box = (BOX *)elem->data; + boxaAddBox(boxan, box, L_INSERT); + elem->data = NULL; + listRemoveElement(&head, elem); + L_END_LIST + } else if (0) { + /* boxa and boxan are same when list made with listAddToHead() */ + tail = listFindTail(head); + L_BEGIN_LIST_REVERSE(tail, elem) + box = (BOX *)elem->data; + boxaAddBox(boxan, box, L_INSERT); + elem->data = NULL; + listRemoveElement(&head, elem); + L_END_LIST + for (i = 0, samecount = 0; i < n; i++) { + if (boxa->box[i]->w == boxan->box[i]->w && + boxa->box[i]->h == boxan->box[i]->h) + samecount++; + } + lept_stderr(" num boxes = %d, same count = %d\n", + boxaGetCount(boxa), samecount); + } else if (0) { + /* boxa and boxan are same when list made with listAddToTail() */ + L_BEGIN_LIST_FORWARD(head, elem) + box = (BOX *)elem->data; + boxaAddBox(boxan, box, L_INSERT); + elem->data = NULL; + listRemoveElement(&head, elem); + L_END_LIST + for (i = 0, samecount = 0; i < n; i++) { + if (boxa->box[i]->w == boxan->box[i]->w && + boxa->box[i]->h == boxan->box[i]->h) + samecount++; + } + lept_stderr(" num boxes = %d, same count = %d\n", + boxaGetCount(boxa), samecount); + } else if (0) { + /* Destroy the boxes and then the list */ + L_BEGIN_LIST_FORWARD(head, elem) + box = (BOX *)elem->data; + boxDestroy(&box); + elem->data = NULL; + L_END_LIST + listDestroy(&head); + } else if (0) { + /* listInsertBefore(): inserting a copy BEFORE each element */ + L_BEGIN_LIST_FORWARD(head, elem) + box = (BOX *)elem->data; + boxc = boxCopy(box); + listInsertBefore(&head, elem, boxc); + L_END_LIST + L_BEGIN_LIST_FORWARD(head, elem) + box = (BOX *)elem->data; + boxaAddBox(boxan, box, L_INSERT); + elem->data = NULL; + L_END_LIST + listDestroy(&head); + } else if (0) { + /* listInsertAfter(): inserting a copy AFTER that element */ + L_BEGIN_LIST_FORWARD(head, elem) + box = (BOX *)elem->data; + boxc = boxCopy(box); + listInsertAfter(&head, elem, boxc); + L_END_LIST + L_BEGIN_LIST_FORWARD(head, elem) + box = (BOX *)elem->data; + boxaAddBox(boxan, box, L_INSERT); + elem->data = NULL; + listRemoveElement(&head, elem); + L_END_LIST +/* listDestroy(&head); */ + } else if (0) { + /* Test listRemoveFromHead(), to successively + * remove the head of the list for all elements. */ + count = 0; + while (head) { + box = (BOX *)listRemoveFromHead(&head); + boxDestroy(&box); + count++; + } + lept_stderr("removed %d items\n", count); + } else if (0) { + /* Another version to test listRemoveFromHead(), using + * an iterator macro. */ + count = 0; + L_BEGIN_LIST_FORWARD(head, elem) + box = (BOX *)listRemoveFromHead(&head); + boxDestroy(&box); + count++; + L_END_LIST + lept_stderr("removed %d items\n", count); + } else if (0) { + /* test listRemoveFromTail(), to successively remove + * the tail of the list for all elements. */ + count = 0; + tail = NULL; /* will find tail automatically */ + while (head) { + box = (BOX *)listRemoveFromTail(&head, &tail); + boxDestroy(&box); + count++; + } + lept_stderr("removed %d items\n", count); + } else if (0) { + /* another version to test listRemoveFromTail(), using + * an iterator macro. */ + count = 0; + tail = listFindTail(head); /* need to initialize tail */ + L_BEGIN_LIST_REVERSE(tail, elem) + box = (BOX *)listRemoveFromTail(&head, &tail); + boxDestroy(&box); + count++; + L_END_LIST + lept_stderr("removed %d items\n", count); + } else if (0) { + /* Iterate backwards over the box array, and use + * listFindElement() to find each corresponding data structure + * within the list; then remove it. Should completely + * destroy the list. Note that listFindElement() + * returns the cell without removing it from the list! */ + n = boxaGetCount(boxa); + for (i = 0, count = 0; i < n; i++) { + box = boxaGetBox(boxa, n - i - 1, L_CLONE); + if (i % 1709 == 0) boxPrintStreamInfo(stderr, box); + elem = listFindElement(head, box); + boxDestroy(&box); + if (elem) { /* found */ + box = (BOX *)listRemoveElement(&head, elem); + if (i % 1709 == 0) boxPrintStreamInfo(stderr, box); + boxDestroy(&box); + count++; + } + } + lept_stderr("removed %d items\n", count); + } + + lept_stderr("boxa count = %d; boxan count = %d\n", + boxaGetCount(boxa), boxaGetCount(boxan)); + boxaGetExtent(boxa, &w, &h, NULL); + lept_stderr("boxa extent = (%d, %d)\n", w, h); + boxaGetExtent(boxan, &w, &h, NULL); + lept_stderr("boxan extent = (%d, %d)\n", w, h); + + pixDestroy(&pixs); + boxaDestroy(&boxa); + boxaDestroy(&boxan); + return 0; +} + diff --git a/leptonica/prog/livre_adapt.c b/leptonica/prog/livre_adapt.c new file mode 100644 index 00000000..f897a317 --- /dev/null +++ b/leptonica/prog/livre_adapt.c @@ -0,0 +1,105 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * livre_adapt.c + * + * This shows two ways to normalize a document image for uneven + * illumination. It is somewhat more complicated than using the + * morphological tophat. + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + +int main(int argc, + char **argv) +{ +PIX *pixs, *pix1, *pix2, *pix3, *pixr, *pixg, *pixb, *pixsg, *pixsm; +PIXA *pixa; +static char mainName[] = "livre_adapt"; + + if (argc != 1) + return ERROR_INT(" Syntax: livre_adapt", mainName, 1); + setLeptDebugOK(1); + + /* Read the image in at 150 ppi. */ + if ((pixs = pixRead("brothers.150.jpg")) == NULL) + return ERROR_INT("pix not made", mainName, 1); + pixa = pixaCreate(0); + pixaAddPix(pixa, pixs, L_INSERT); + + /* Normalize for uneven illumination on RGB image */ + pixBackgroundNormRGBArraysMorph(pixs, NULL, 4, 5, 200, + &pixr, &pixg, &pixb); + pix1 = pixApplyInvBackgroundRGBMap(pixs, pixr, pixg, pixb, 4, 4); + pixaAddPix(pixa, pix1, L_INSERT); + pixDestroy(&pixr); + pixDestroy(&pixg); + pixDestroy(&pixb); + + /* Convert the RGB image to grayscale. */ + pixsg = pixConvertRGBToLuminance(pixs); + pixaAddPix(pixa, pixsg, L_INSERT); + + /* Remove the text in the fg. */ + pix1 = pixCloseGray(pixsg, 25, 25); + pixaAddPix(pixa, pix1, L_INSERT); + + /* Smooth the bg with a convolution. */ + pixsm = pixBlockconv(pix1, 15, 15); + pixaAddPix(pixa, pixsm, L_INSERT); + + /* Normalize for uneven illumination on gray image. */ + pixBackgroundNormGrayArrayMorph(pixsg, NULL, 4, 5, 200, &pixg); + pix1 = pixApplyInvBackgroundGrayMap(pixsg, pixg, 4, 4); + pixaAddPix(pixa, pix1, L_INSERT); + pixDestroy(&pixg); + + /* Increase the dynamic range. */ + pix2 = pixGammaTRC(NULL, pix1, 1.0, 30, 180); + pixaAddPix(pixa, pix2, L_INSERT); + + /* Threshold to 1 bpp. */ + pix3 = pixThresholdToBinary(pix2, 120); + pixaAddPix(pixa, pix3, L_INSERT); + + /* Generate the output image and pdf */ + lept_mkdir("lept/livre"); + lept_stderr("Writing jpg and pdf to: /tmp/lept/livre/adapt.*\n"); + pix1 = pixaDisplayTiledAndScaled(pixa, 8, 350, 4, 0, 25, 2); + pixWrite("/tmp/lept/livre/adapt.jpg", pix1, IFF_DEFAULT); + pixDisplay(pix1, 100, 100); + pixaConvertToPdf(pixa, 0, 1.0, 0, 0, "Livre: adaptive thresholding", + "/tmp/lept/livre/adapt.pdf"); + pixDestroy(&pix1); + pixaDestroy(&pixa); + return 0; +} + diff --git a/leptonica/prog/livre_hmt.c b/leptonica/prog/livre_hmt.c new file mode 100644 index 00000000..835d2078 --- /dev/null +++ b/leptonica/prog/livre_hmt.c @@ -0,0 +1,151 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * livre_hmt.c + * + * This demonstrates use of pixGenerateSelBoundary() to + * generate a hit-miss Sel. + * + * (1) The Sel is displayed with the hit and miss elements in color. + * + * (2) We produce several 4 bpp colormapped renditions, + * with the matched pattern either highlighted or removed. + * + * (3) For figures in the Document Image Applications chapter: + * fig 7: livre_hmt 1 8 + * fig 8: livre_hmt 2 4 + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + + /* for pixDisplayHitMissSel() */ +static const l_uint32 HitColor = 0x33aa4400; +static const l_uint32 MissColor = 0xaa44bb00; + + /* Patterns at full resolution */ +static const char *patname[3] = { + "", + "tribune-word.png", /* patno = 1 */ + "tribune-t.png"}; /* patno = 2 */ + + +int main(int argc, + char **argv) +{ +l_int32 patno, reduction, width, cols, cx, cy; +PIX *pixs, *pixt, *pix, *pixr, *pixp, *pixsel, *pixhmt; +PIX *pixd1, *pixd2, *pixd3, *pixd; +PIXA *pixa; +SEL *selhm; +static char mainName[] = "livre_hmt"; + + if (argc != 3) + return ERROR_INT(" Syntax: livre_hmt pattern reduction", mainName, 1); + patno = atoi(argv[1]); + reduction = atoi(argv[2]); + + setLeptDebugOK(1); + lept_mkdir("lept/livre"); + if ((pixs = pixRead(patname[patno])) == NULL) + return ERROR_INT("pixs not made", mainName, 1); + if (reduction != 4 && reduction != 8 && reduction != 16) + return ERROR_INT("reduction not 4, 8 or 16", mainName, 1); + + if (reduction == 4) + pixt = pixReduceRankBinaryCascade(pixs, 4, 4, 0, 0); + else if (reduction == 8) + pixt = pixReduceRankBinaryCascade(pixs, 4, 4, 2, 0); + else /* reduction == 16 */ + pixt = pixReduceRankBinaryCascade(pixs, 4, 4, 2, 2); + + /* Make a hit-miss sel */ + if (reduction == 4) + selhm = pixGenerateSelBoundary(pixt, 2, 2, 20, 30, 1, 1, 0, 0, &pixp); + else if (reduction == 8) + selhm = pixGenerateSelBoundary(pixt, 1, 2, 6, 12, 1, 1, 0, 0, &pixp); + else /* reduction == 16 */ + selhm = pixGenerateSelBoundary(pixt, 1, 1, 4, 8, 0, 0, 0, 0, &pixp); + + /* Display the sel */ + pixsel = pixDisplayHitMissSel(pixp, selhm, 7, HitColor, MissColor); + pixDisplay(pixsel, 1000, 300); + pixWrite("/tmp/lept/livre/pixsel1", pixsel, IFF_PNG); + + /* Use the Sel to find all instances in the page */ + pix = pixRead("tribune-page-4x.png"); /* 4x reduced */ + if (reduction == 4) + pixr = pixClone(pix); + else if (reduction == 8) + pixr = pixReduceRankBinaryCascade(pix, 2, 0, 0, 0); + else /* reduction == 16 */ + pixr = pixReduceRankBinaryCascade(pix, 2, 2, 0, 0); + + startTimer(); + pixhmt = pixHMT(NULL, pixr, selhm); + lept_stderr("Time to find patterns = %7.3f\n", stopTimer()); + + /* Color each instance at full res */ + selGetParameters(selhm, NULL, NULL, &cy, &cx); + pixd1 = pixDisplayMatchedPattern(pixr, pixp, pixhmt, + cx, cy, 0x0000ff00, 1.0, 5); + pixWrite("/tmp/lept/livre/pixd11", pixd1, IFF_PNG); + + /* Color each instance at 0.5 scale */ + pixd2 = pixDisplayMatchedPattern(pixr, pixp, pixhmt, + cx, cy, 0x0000ff00, 0.5, 5); + pixWrite("/tmp/lept/livre/pixd12", pixd2, IFF_PNG); + + /* Remove each instance from the input image */ + pixd3 = pixCopy(NULL, pixr); + pixRemoveMatchedPattern(pixd3, pixp, pixhmt, cx, cy, 1); + pixWrite("/tmp/lept/livre/pixr1", pixd3, IFF_PNG); + + pixa = pixaCreate(2); + pixaAddPix(pixa, pixs, L_CLONE); + pixaAddPix(pixa, pixsel, L_CLONE); + cols = (patno == 1) ? 1 : 2; + width = (patno == 1) ? 800 : 400; + pixd = pixaDisplayTiledAndScaled(pixa, 32, width, cols, 0, 30, 2); + pixWrite("/tmp/lept/livre/hmt.png", pixd, IFF_PNG); + pixDisplay(pixd, 1000, 600); + + selDestroy(&selhm); + pixDestroy(&pixp); + pixDestroy(&pixsel); + pixDestroy(&pixhmt); + pixDestroy(&pixd1); + pixDestroy(&pixd2); + pixDestroy(&pixd3); + pixDestroy(&pixs); + pixDestroy(&pix); + pixDestroy(&pixt); + return 0; +} diff --git a/leptonica/prog/livre_makefigs.c b/leptonica/prog/livre_makefigs.c new file mode 100644 index 00000000..8f7ed8df --- /dev/null +++ b/leptonica/prog/livre_makefigs.c @@ -0,0 +1,107 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * livre_makefigs.c + * + * This makes all the figures in Chapter 18, "Document Image Applications", + * of the book "Mathematical morphology: from theory to applications", + * edited by Laurent Najman and hugues Talbot. Published by Hermes + * Scientific Publishing, Ltd, 2010. + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + +int main(int argc, + char **argv) +{ +char buf[256]; +l_int32 ignore; +static char mainName[] = "livre_makefigs"; + + if (argc != 1) + return ERROR_INT(" Syntax: livre_makefigs", mainName, 1); + + setLeptDebugOK(1); + lept_mkdir("lept/livre"); + + /* Generate Figure 1 (page segmentation) */ + ignore = system("livre_seedgen"); + snprintf(buf, sizeof(buf), + "cp /tmp/lept/livre/seedgen.png /tmp/lept/livre/dia_fig1.png"); + ignore = system(buf); + + /* Generate Figures 2-5 (page segmentation) */ + snprintf(buf, sizeof(buf), "livre_pageseg pageseg2.tif"); + ignore = system(buf); + snprintf(buf, sizeof(buf), + "cp /tmp/lept/livre/segout.1.png /tmp/lept/livre/dia_fig2.png"); + ignore = system(buf); + snprintf(buf, sizeof(buf), + "cp /tmp/lept/livre/segout.2.png /tmp/lept/livre/dia_fig3.png"); + ignore = system(buf); + snprintf(buf, sizeof(buf), + "cp /tmp/lept/livre/segout.3.png /tmp/lept/livre/dia_fig4.png"); + ignore = system(buf); + snprintf(buf, sizeof(buf), + "cp /tmp/lept/livre/segout.4.png /tmp/lept/livre/dia_fig5.png"); + ignore = system(buf); + + /* Generate Figure 6 (hmt sels for text orientation) */ + ignore = system("livre_orient"); + snprintf(buf, sizeof(buf), + "cp /tmp/lept/livre/orient.png /tmp/lept/livre/dia_fig6.png"); + ignore = system(buf); + + /* Generate Figure 7 (hmt sel for fancy "Tribune") */ + ignore = system("livre_hmt 1 8"); + snprintf(buf, sizeof(buf), + "cp /tmp/lept/livre/hmt.png /tmp/lept/livre/dia_fig7.png"); + ignore = system(buf); + + /* Generate Figure 8 (hmt sel for fancy "T") */ + ignore = system("livre_hmt 2 4"); + snprintf(buf, sizeof(buf), + "cp /tmp/lept/livre/hmt.png /tmp/lept/livre/dia_fig8.png"); + ignore = system(buf); + + /* Generate Figure 9 (tophat background cleaning) */ + ignore = system("livre_tophat"); + snprintf(buf, sizeof(buf), + "cp /tmp/lept/livre/tophat.jpg /tmp/lept/livre/dia_fig9.jpg"); + ignore = system(buf); + + /* Run livre_adapt to generate an expanded version of Figure 9 */ + ignore = system("livre_adapt"); + + + return 0; +} + diff --git a/leptonica/prog/livre_orient.c b/leptonica/prog/livre_orient.c new file mode 100644 index 00000000..c7ba784c --- /dev/null +++ b/leptonica/prog/livre_orient.c @@ -0,0 +1,94 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * livre_orient.c + * + * This generates an image of the set of 4 HMT Sels that are + * used for counting ascenders and descenders to detect + * text orientation. + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + +static const char *textsel1 = "x oo " + "x oOo " + "x o " + "x " + "xxxxxx"; + +static const char *textsel2 = " oo x" + " oOo x" + " o x" + " x" + "xxxxxx"; + +static const char *textsel3 = "xxxxxx" + "x " + "x o " + "x oOo " + "x oo "; + +static const char *textsel4 = "xxxxxx" + " x" + " o x" + " oOo x" + " oo x"; + +int main(int argc, + char **argv) +{ +PIX *pix1; +SEL *sel1, *sel2, *sel3, *sel4; +SELA *sela; + + setLeptDebugOK(1); + lept_mkdir("lept/livre"); + + sel1 = selCreateFromString(textsel1, 5, 6, NULL); + sel2 = selCreateFromString(textsel2, 5, 6, NULL); + sel3 = selCreateFromString(textsel3, 5, 6, NULL); + sel4 = selCreateFromString(textsel4, 5, 6, NULL); + + sela = selaCreate(4); + selaAddSel(sela, sel1, "textsel1", L_INSERT); + selaAddSel(sela, sel2, "textsel2", L_INSERT); + selaAddSel(sela, sel3, "textsel3", L_INSERT); + selaAddSel(sela, sel4, "textsel4", L_INSERT); + + pix1 = selaDisplayInPix(sela, 28, 3, 30, 4); + pixWrite("/tmp/lept/livre/orient.png", pix1, IFF_PNG); + pixDisplay(pix1, 1200, 1200); + + pixDestroy(&pix1); + selaDestroy(&sela); + return 0; +} + diff --git a/leptonica/prog/livre_pageseg.c b/leptonica/prog/livre_pageseg.c new file mode 100644 index 00000000..40d96fec --- /dev/null +++ b/leptonica/prog/livre_pageseg.c @@ -0,0 +1,311 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * livre_pageseg.c + * + * This gives examples of the use of binary morphology for + * some simple and fast document segmentation operations. + * + * The operations are carried out at 2x reduction. + * For images scanned at 300 ppi, this is typically + * high enough resolution for accurate results. + * + * This generates several of the figures used in Chapter 18 of + * "Mathematical morphology: from theory to applications", + * edited by Laurent Najman and Hugues Talbot. Published by + * Hermes Scientific Publishing, Ltd, 2010. + * + * Use pageseg*.tif input images. + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + + /* Control the display output */ +#define DFLAG 0 + + +l_int32 DoPageSegmentation(PIX *pixs, l_int32 which); + +int main(int argc, + char **argv) +{ +char *filein; +l_int32 i; +PIX *pixs; /* input image should be at least 300 ppi */ +static char mainName[] = "livre_pageseg"; + + if (argc != 2) + return ERROR_INT(" Syntax: livre_pageseg filein", mainName, 1); + filein = argv[1]; + setLeptDebugOK(1); + + if ((pixs = pixRead(filein)) == NULL) + return ERROR_INT("pix not made", mainName, 1); + + for (i = 1; i <= 4; i++) + DoPageSegmentation(pixs, i); + pixDestroy(&pixs); + return 0; +} + + +l_int32 +DoPageSegmentation(PIX *pixs, /* should be at least 300 ppi */ + l_int32 which) /* 1, 2, 3, 4 */ +{ +char buf[256]; +l_int32 zero; +BOXA *boxatm, *boxahm; +PIX *pixr; /* image reduced to 150 ppi */ +PIX *pixhs; /* image of halftone seed, 150 ppi */ +PIX *pixm; /* image of mask of components, 150 ppi */ +PIX *pixhm1; /* image of halftone mask, 150 ppi */ +PIX *pixhm2; /* image of halftone mask, 300 ppi */ +PIX *pixht; /* image of halftone components, 150 ppi */ +PIX *pixnht; /* image without halftone components, 150 ppi */ +PIX *pixi; /* inverted image, 150 ppi */ +PIX *pixvws; /* image of vertical whitespace, 150 ppi */ +PIX *pixm1; /* image of closed textlines, 150 ppi */ +PIX *pixm2; /* image of refined text line mask, 150 ppi */ +PIX *pixm3; /* image of refined text line mask, 300 ppi */ +PIX *pixb1; /* image of text block mask, 150 ppi */ +PIX *pixb2; /* image of text block mask, 300 ppi */ +PIX *pixnon; /* image of non-text or halftone, 150 ppi */ +PIX *pix1, *pix2, *pix3; +PIXA *pixa; +PIXCMAP *cmap; +PTAA *ptaa; +l_int32 ht_flag = 0; +l_int32 ws_flag = 0; +l_int32 text_flag = 0; +l_int32 block_flag = 0; + + PROCNAME("DoPageSegmentation"); + + if (which == 1) + ht_flag = 1; + else if (which == 2) + ws_flag = 1; + else if (which == 3) + text_flag = 1; + else if (which == 4) + block_flag = 1; + else + return ERROR_INT("invalid parameter: not in [1...4]", procName, 1); + + pixa = pixaCreate(0); + lept_mkdir("lept/livre"); + + /* Reduce to 150 ppi */ + pix1 = pixScaleToGray2(pixs); + if (ws_flag || ht_flag || block_flag) pixaAddPix(pixa, pix1, L_COPY); + if (which == 1) + pixWrite("/tmp/lept/livre/orig.gray.150.png", pix1, IFF_PNG); + pixDestroy(&pix1); + pixr = pixReduceRankBinaryCascade(pixs, 1, 0, 0, 0); + + /* Get seed for halftone parts */ + pix1 = pixReduceRankBinaryCascade(pixr, 4, 4, 3, 0); + pix2 = pixOpenBrick(NULL, pix1, 5, 5); + pixhs = pixExpandBinaryPower2(pix2, 8); + if (ht_flag) pixaAddPix(pixa, pixhs, L_COPY); + if (which == 1) + pixWrite("/tmp/lept/livre/htseed.150.png", pixhs, IFF_PNG); + pixDestroy(&pix1); + pixDestroy(&pix2); + + /* Get mask for connected regions */ + pixm = pixCloseSafeBrick(NULL, pixr, 4, 4); + if (ht_flag) pixaAddPix(pixa, pixm, L_COPY); + if (which == 1) + pixWrite("/tmp/lept/livre/ccmask.150.png", pixm, IFF_PNG); + + /* Fill seed into mask to get halftone mask */ + pixhm1 = pixSeedfillBinary(NULL, pixhs, pixm, 4); + if (ht_flag) pixaAddPix(pixa, pixhm1, L_COPY); + if (which == 1) pixWrite("/tmp/lept/livre/htmask.150.png", pixhm1, IFF_PNG); + pixhm2 = pixExpandBinaryPower2(pixhm1, 2); + + /* Extract halftone stuff */ + pixht = pixAnd(NULL, pixhm1, pixr); + if (which == 1) pixWrite("/tmp/lept/livre/ht.150.png", pixht, IFF_PNG); + + /* Extract non-halftone stuff */ + pixnht = pixXor(NULL, pixht, pixr); + if (text_flag) pixaAddPix(pixa, pixnht, L_COPY); + if (which == 1) pixWrite("/tmp/lept/livre/text.150.png", pixnht, IFF_PNG); + pixZero(pixht, &zero); + if (zero) + lept_stderr("No halftone parts found\n"); + else + lept_stderr("Halftone parts found\n"); + + /* Get bit-inverted image */ + pixi = pixInvert(NULL, pixnht); + if (ws_flag) pixaAddPix(pixa, pixi, L_COPY); + if (which == 1) pixWrite("/tmp/lept/livre/invert.150.png", pixi, IFF_PNG); + + /* The whitespace mask will break textlines where there + * is a large amount of white space below or above. + * We can prevent this by identifying regions of the + * inverted image that have large horizontal (bigger than + * the separation between columns) and significant + * vertical extent (bigger than the separation between + * textlines), and subtracting this from the whitespace mask. */ + pix1 = pixMorphCompSequence(pixi, "o80.60", 0); + pix2 = pixSubtract(NULL, pixi, pix1); + if (ws_flag) pixaAddPix(pixa, pix2, L_COPY); + pixDestroy(&pix1); + + /* Identify vertical whitespace by opening inverted image */ + pix3 = pixOpenBrick(NULL, pix2, 5, 1); /* removes thin vertical lines */ + pixvws = pixOpenBrick(NULL, pix3, 1, 200); /* gets long vertical lines */ + if (text_flag || ws_flag) pixaAddPix(pixa, pixvws, L_COPY); + if (which == 1) pixWrite("/tmp/lept/livre/vertws.150.png", pixvws, IFF_PNG); + pixDestroy(&pix2); + pixDestroy(&pix3); + + /* Get proto (early processed) text line mask. */ + /* First close the characters and words in the textlines */ + pixm1 = pixCloseSafeBrick(NULL, pixnht, 30, 1); + if (text_flag) pixaAddPix(pixa, pixm1, L_COPY); + if (which == 1) + pixWrite("/tmp/lept/livre/textmask1.150.png", pixm1, IFF_PNG); + + /* Next open back up the vertical whitespace corridors */ + pixm2 = pixSubtract(NULL, pixm1, pixvws); + if (which == 1) + pixWrite("/tmp/lept/livre/textmask2.150.png", pixm2, IFF_PNG); + + /* Do a small opening to remove noise */ + pixOpenBrick(pixm2, pixm2, 3, 3); + if (text_flag) pixaAddPix(pixa, pixm2, L_COPY); + if (which == 1) + pixWrite("/tmp/lept/livre/textmask3.150.png", pixm2, IFF_PNG); + pixm3 = pixExpandBinaryPower2(pixm2, 2); + + /* Join pixels vertically to make text block mask */ + pixb1 = pixMorphSequence(pixm2, "c1.10 + o4.1", 0); + if (block_flag) pixaAddPix(pixa, pixb1, L_COPY); + if (which == 1) + pixWrite("/tmp/lept/livre/textblock1.150.png", pixb1, IFF_PNG); + + /* Solidify the textblock mask and remove noise: + * (1) For each c.c., close the blocks and dilate slightly + * to form a solid mask. + * (2) Small horizontal closing between components + * (3) Open the white space between columns, again + * (4) Remove small components */ + pix1 = pixMorphSequenceByComponent(pixb1, "c30.30 + d3.3", 8, 0, 0, NULL); + pixCloseSafeBrick(pix1, pix1, 10, 1); + if (block_flag) pixaAddPix(pixa, pix1, L_COPY); + pix2 = pixSubtract(NULL, pix1, pixvws); + pix3 = pixSelectBySize(pix2, 25, 5, 8, L_SELECT_IF_BOTH, + L_SELECT_IF_GTE, NULL); + if (block_flag) pixaAddPix(pixa, pix3, L_COPY); + if (which == 1) + pixWrite("/tmp/lept/livre/textblock2.150.png", pix3, IFF_PNG); + pixb2 = pixExpandBinaryPower2(pix3, 2); + pixDestroy(&pix1); + pixDestroy(&pix2); + pixDestroy(&pix3); + + /* Identify the outlines of each textblock */ + ptaa = pixGetOuterBordersPtaa(pixb2); + pix1 = pixRenderRandomCmapPtaa(pixb2, ptaa, 1, 8, 1); + cmap = pixGetColormap(pix1); + pixcmapResetColor(cmap, 0, 130, 130, 130); /* set interior to gray */ + if (which == 1) + pixWrite("/tmp/lept/livre/textblock3.300.png", pix1, IFF_PNG); + pixDisplayWithTitle(pix1, 480, 360, "textblock mask with outlines", DFLAG); + ptaaDestroy(&ptaa); + pixDestroy(&pix1); + + /* Fill line mask (as seed) into the original */ + pix1 = pixSeedfillBinary(NULL, pixm3, pixs, 8); + pixOr(pixm3, pixm3, pix1); + pixDestroy(&pix1); + if (which == 1) + pixWrite("/tmp/lept/livre/textmask.300.png", pixm3, IFF_PNG); + pixDisplayWithTitle(pixm3, 480, 360, "textline mask 4", DFLAG); + + /* Fill halftone mask (as seed) into the original */ + pix1 = pixSeedfillBinary(NULL, pixhm2, pixs, 8); + pixOr(pixhm2, pixhm2, pix1); + pixDestroy(&pix1); + if (which == 1) + pixWrite("/tmp/lept/livre/htmask.300.png", pixhm2, IFF_PNG); + pixDisplayWithTitle(pixhm2, 520, 390, "halftonemask 2", DFLAG); + + /* Find objects that are neither text nor halftones */ + pix1 = pixSubtract(NULL, pixs, pixm3); /* remove text pixels */ + pixnon = pixSubtract(NULL, pix1, pixhm2); /* remove halftone pixels */ + pixDestroy(&pix1); + if (which == 1) + pixWrite("/tmp/lept/livre/other.300.png", pixnon, IFF_PNG); + pixDisplayWithTitle(pixnon, 540, 420, "other stuff", DFLAG); + + /* Write out b.b. for text line mask and halftone mask components */ + boxatm = pixConnComp(pixm3, NULL, 4); + boxahm = pixConnComp(pixhm2, NULL, 8); + if (which == 1) { + boxaWrite("/tmp/lept/livre/textmask.boxa", boxatm); + boxaWrite("/tmp/lept/livre/htmask.boxa", boxahm); + } + + pix1 = pixaDisplayTiledAndScaled(pixa, 8, 250, 4, 0, 25, 2); + pixDisplay(pix1, 0, 375 * (which - 1)); + snprintf(buf, sizeof(buf), "/tmp/lept/livre/segout.%d.png", which); + pixWrite(buf, pix1, IFF_PNG); + pixDestroy(&pix1); + pixaDestroy(&pixa); + + /* clean up to test with valgrind */ + pixDestroy(&pixr); + pixDestroy(&pixhs); + pixDestroy(&pixm); + pixDestroy(&pixhm1); + pixDestroy(&pixhm2); + pixDestroy(&pixht); + pixDestroy(&pixi); + pixDestroy(&pixnht); + pixDestroy(&pixvws); + pixDestroy(&pixm1); + pixDestroy(&pixm2); + pixDestroy(&pixm3); + pixDestroy(&pixb1); + pixDestroy(&pixb2); + pixDestroy(&pixnon); + boxaDestroy(&boxatm); + boxaDestroy(&boxahm); + return 0; +} + diff --git a/leptonica/prog/livre_seedgen.c b/leptonica/prog/livre_seedgen.c new file mode 100644 index 00000000..f6f3d384 --- /dev/null +++ b/leptonica/prog/livre_seedgen.c @@ -0,0 +1,75 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * livre_seedgen.c + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + +int main(int argc, + char **argv) +{ +l_int32 i; +PIX *pixs, *pix1, *pix2, *pix3; +PIXA *pixa; + + setLeptDebugOK(1); + pixs = pixRead("pageseg2.tif"); + + startTimer(); + for (i = 0; i < 100; i++) { + pix1 = pixReduceRankBinaryCascade(pixs, 1, 4, 4, 3); + pixDestroy(&pix1); + } + lept_stderr("Time: %8.4f sec\n", stopTimer() / 100.); + + /* 4 2x rank reductions (levels 1, 4, 4, 3), followed by 5x5 opening */ + pixa = pixaCreate(0); + pixaAddPix(pixa, pixs, L_INSERT); + pix1 = pixReduceRankBinaryCascade(pixs, 1, 4, 0, 0); + pixaAddPix(pixa, pix1, L_INSERT); + pix2 = pixReduceRankBinaryCascade(pix1, 4, 3, 0, 0); + pixaAddPix(pixa, pix2, L_INSERT); + pixOpenBrick(pix2, pix2, 5, 5); + pix3 = pixExpandBinaryReplicate(pix2, 2, 2); + pixaAddPix(pixa, pix3, L_INSERT); + + /* Generate the output image */ + lept_mkdir("lept/livre"); + lept_stderr("Writing to: /tmp/lept/livre/seedgen.png\n"); + pix1 = pixaDisplayTiledAndScaled(pixa, 8, 350, 4, 0, 25, 2); + pixWrite("/tmp/lept/livre/seedgen.png", pix1, IFF_PNG); + pixDisplay(pix1, 1100, 0); + pixDestroy(&pix1); + pixaDestroy(&pixa); + return 0; +} + diff --git a/leptonica/prog/livre_tophat.c b/leptonica/prog/livre_tophat.c new file mode 100644 index 00000000..fc5905c7 --- /dev/null +++ b/leptonica/prog/livre_tophat.c @@ -0,0 +1,75 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * livre_tophat.c + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + +int main(int argc, + char **argv) +{ +PIX *pixs, *pixsg, *pix1, *pix2; +PIXA *pixa; +static char mainName[] = "livre_tophat"; + + if (argc != 1) + return ERROR_INT(" Syntax: livre_tophat", mainName, 1); + setLeptDebugOK(1); + + /* Read the image in at 150 ppi. */ + pixs = pixRead("brothers.150.jpg"); + pixa = pixaCreate(0); + pixaAddPix(pixa, pixs, L_INSERT); + + pixsg = pixConvertRGBToLuminance(pixs); + + /* Black tophat (closing - original-image) and invert */ + pix1 = pixTophat(pixsg, 15, 15, L_TOPHAT_BLACK); + pixInvert(pix1, pix1); + pixaAddPix(pixa, pix1, L_INSERT); + + /* Set black point at 200, white point at 245. */ + pix2 = pixGammaTRC(NULL, pix1, 1.0, 200, 245); + pixaAddPix(pixa, pix2, L_INSERT); + + /* Generate the output image */ + lept_mkdir("lept/livre"); + lept_stderr("Writing to: /tmp/lept/livre/tophat.jpg\n"); + pix1 = pixaDisplayTiledAndScaled(pixa, 8, 350, 3, 0, 25, 2); + pixWrite("/tmp/lept/livre/tophat.jpg", pix1, IFF_JFIF_JPEG); + pixDisplay(pix1, 1200, 800); + pixDestroy(&pix1); + pixaDestroy(&pixa); + pixDestroy(&pixsg); + return 0; +} + diff --git a/leptonica/prog/locminmax_reg.c b/leptonica/prog/locminmax_reg.c new file mode 100644 index 00000000..422555eb --- /dev/null +++ b/leptonica/prog/locminmax_reg.c @@ -0,0 +1,102 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * locminmax_reg.c + * + * Note: you can remove all minima that are touching the border, using: + * pix3 = pixRemoveBorderConnComps(pix1, 8); + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include <math.h> +#include "allheaders.h" + +void DoLocMinmax(L_REGPARAMS *rp, PIX *pixs, l_int32 minmax, l_int32 maxmin); + +int main(int argc, + char **argv) +{ +l_int32 i, j; +l_float32 f; +PIX *pix1, *pix2, *pix3; +L_REGPARAMS *rp; + + if (regTestSetup(argc, argv, &rp)) + return 1; + + pix1 = pixCreate(500, 500, 8); + for (i = 0; i < 500; i++) { + for (j = 0; j < 500; j++) { + f = 128.0 + 26.3 * sin(0.0438 * (l_float32)i); + f += 33.4 * cos(0.0712 * (l_float32)i); + f += 18.6 * sin(0.0561 * (l_float32)j); + f += 23.6 * cos(0.0327 * (l_float32)j); + pixSetPixel(pix1, j, i, (l_int32)f); + } + } + pix2 = pixRead("karen8.jpg"); + pix3 = pixBlockconv(pix2, 10, 10); + DoLocMinmax(rp, pix1, 0, 0); /* 0 - 2 */ + DoLocMinmax(rp, pix3, 50, 100); /* 3 - 5 */ + pixDestroy(&pix1); + pixDestroy(&pix2); + pixDestroy(&pix3); + return regTestCleanup(rp); +} + +void +DoLocMinmax(L_REGPARAMS *rp, + PIX *pixs, + l_int32 minmax, + l_int32 maxmin) +{ +l_uint32 redval, greenval; +PIX *pix1, *pix2, *pix3, *pixd; +PIXA *pixa; + + pixa = pixaCreate(0); + regTestWritePixAndCheck(rp, pixs, IFF_PNG); /* 0 */ + pixaAddPix(pixa, pixs, L_COPY); + pixLocalExtrema(pixs, minmax, maxmin, &pix1, &pix2); + composeRGBPixel(255, 0, 0, &redval); + composeRGBPixel(0, 255, 0, &greenval); + pixd = pixConvertTo32(pixs); + pixPaintThroughMask(pixd, pix2, 0, 0, greenval); + pixPaintThroughMask(pixd, pix1, 0, 0, redval); + regTestWritePixAndCheck(rp, pixd, IFF_PNG); /* 1 */ + pixaAddPix(pixa, pixd, L_INSERT); + pix3 = pixaDisplayTiledInColumns(pixa, 2, 1.0, 25, 2); + regTestWritePixAndCheck(rp, pix3, IFF_PNG); /* 2 */ + pixDisplayWithTitle(pix3, 300, 0, NULL, rp->display); + pixaDestroy(&pixa); + pixDestroy(&pix1); + pixDestroy(&pix2); + pixDestroy(&pix3); +} diff --git a/leptonica/prog/logicops_reg.c b/leptonica/prog/logicops_reg.c new file mode 100644 index 00000000..3bb2c203 --- /dev/null +++ b/leptonica/prog/logicops_reg.c @@ -0,0 +1,178 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * logicops_reg.c + * + * Regression test for pixel-wise logical operations, both in-place and + * generating new images. Implemented by rasterops. + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + +int main(int argc, + char **argv) +{ +PIX *pixs, *pix1, *pix2, *pix3, *pix4; +L_REGPARAMS *rp; + + if (regTestSetup(argc, argv, &rp)) + return 1; + + pixs = pixRead("test1.png"); + + + /* pixInvert */ + pix1 = pixInvert(NULL, pixs); + pix2 = pixCreateTemplate(pixs); /* into pixd of same size */ + pixInvert(pix2, pixs); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 0 */ + regTestComparePix(rp, pix1, pix2); /* 1 */ + + pix3 = pixRead("marge.jpg"); /* into pixd of different size */ + pixInvert(pix3, pixs); + regTestComparePix(rp, pix1, pix3); /* 2 */ + pixDestroy(&pix1); + pixDestroy(&pix2); + pixDestroy(&pix3); + + pix1 = pixOpenBrick(NULL, pixs, 1, 9); + pix2 = pixDilateBrick(NULL, pixs, 1, 9); + + /* pixOr */ + pix3 = pixCreateTemplate(pixs); + pixOr(pix3, pixs, pix1); /* existing */ + pix4 = pixOr(NULL, pixs, pix1); /* new */ + regTestWritePixAndCheck(rp, pix3, IFF_PNG); /* 3 */ + regTestComparePix(rp, pix3, pix4); /* 4 */ + pixCopy(pix4, pix1); + pixOr(pix4, pix4, pixs); /* in-place */ + regTestComparePix(rp, pix3, pix4); /* 5 */ + pixDestroy(&pix3); + pixDestroy(&pix4); + + pix3 = pixCreateTemplate(pixs); + pixOr(pix3, pixs, pix2); /* existing */ + pix4 = pixOr(NULL, pixs, pix2); /* new */ + regTestWritePixAndCheck(rp, pix3, IFF_PNG); /* 6 */ + regTestComparePix(rp, pix3, pix4); /* 7 */ + pixCopy(pix4, pix2); + pixOr(pix4, pix4, pixs); /* in-place */ + regTestComparePix(rp, pix3, pix4); /* 8 */ + pixDestroy(&pix3); + pixDestroy(&pix4); + + /* pixAnd */ + pix3 = pixCreateTemplate(pixs); + pixAnd(pix3, pixs, pix1); /* existing */ + pix4 = pixAnd(NULL, pixs, pix1); /* new */ + regTestWritePixAndCheck(rp, pix3, IFF_PNG); /* 9 */ + regTestComparePix(rp, pix3, pix4); /* 10 */ + pixCopy(pix4, pix1); + pixAnd(pix4, pix4, pixs); /* in-place */ + regTestComparePix(rp, pix3, pix4); /* 11 */ + pixDestroy(&pix3); + pixDestroy(&pix4); + + pix3 = pixCreateTemplate(pixs); + pixAnd(pix3, pixs, pix2); /* existing */ + pix4 = pixAnd(NULL, pixs, pix2); /* new */ + regTestWritePixAndCheck(rp, pix3, IFF_PNG); /* 12 */ + regTestComparePix(rp, pix3, pix4); /* 13 */ + pixCopy(pix4, pix2); + pixAnd(pix4, pix4, pixs); /* in-place */ + regTestComparePix(rp, pix3, pix4); /* 14 */ + pixDestroy(&pix3); + pixDestroy(&pix4); + + /* pixXor */ + pix3 = pixCreateTemplate(pixs); + pixXor(pix3, pixs, pix1); /* existing */ + pix4 = pixXor(NULL, pixs, pix1); /* new */ + regTestWritePixAndCheck(rp, pix3, IFF_PNG); /* 15 */ + regTestComparePix(rp, pix3, pix4); /* 16 */ + pixCopy(pix4, pix1); + pixXor(pix4, pix4, pixs); /* in-place */ + regTestComparePix(rp, pix3, pix4); /* 17 */ + pixDestroy(&pix3); + pixDestroy(&pix4); + + pix3 = pixCreateTemplate(pixs); + pixXor(pix3, pixs, pix2); /* existing */ + pix4 = pixXor(NULL, pixs, pix2); /* new */ + regTestWritePixAndCheck(rp, pix3, IFF_PNG); /* 18 */ + regTestComparePix(rp, pix3, pix4); /* 19 */ + pixCopy(pix4, pix2); + pixXor(pix4, pix4, pixs); /* in-place */ + regTestComparePix(rp, pix3, pix4); /* 20 */ + pixDestroy(&pix3); + pixDestroy(&pix4); + + /* pixSubtract */ + pix3 = pixCreateTemplate(pixs); + pixSubtract(pix3, pixs, pix1); /* existing */ + pix4 = pixSubtract(NULL, pixs, pix1); /* new */ + regTestWritePixAndCheck(rp, pix3, IFF_PNG); /* 21 */ + regTestComparePix(rp, pix3, pix4); /* 22 */ + pixCopy(pix4, pix1); + pixSubtract(pix4, pixs, pix4); /* in-place */ + regTestComparePix(rp, pix3, pix4); /* 23 */ + pixDestroy(&pix3); + pixDestroy(&pix4); + + pix3 = pixCreateTemplate(pixs); + pixSubtract(pix3, pixs, pix2); /* existing */ + pix4 = pixSubtract(NULL, pixs, pix2); /* new */ + regTestWritePixAndCheck(rp, pix3, IFF_PNG); /* 24 */ + regTestComparePix(rp, pix3, pix4); /* 25 */ + pixCopy(pix4, pix2); + pixSubtract(pix4, pixs, pix4); /* in-place */ + regTestComparePix(rp, pix3, pix4); /* 26 */ + pixDestroy(&pix3); + pixDestroy(&pix4); + + pix4 = pixRead("marge.jpg"); + pixSubtract(pix4, pixs, pixs); /* subtract from itself; should be empty */ + pix3 = pixCreateTemplate(pixs); + regTestComparePix(rp, pix3, pix4); /* 27*/ + pixDestroy(&pix3); + pixDestroy(&pix4); + + pixSubtract(pixs, pixs, pixs); /* subtract from itself; should be empty */ + pix3 = pixCreateTemplate(pixs); + regTestComparePix(rp, pix3, pixs); /* 28*/ + pixDestroy(&pix3); + + pixDestroy(&pixs); + pixDestroy(&pix1); + pixDestroy(&pix2); + return regTestCleanup(rp); +} + diff --git a/leptonica/prog/lowaccess_reg.c b/leptonica/prog/lowaccess_reg.c new file mode 100644 index 00000000..6a6ec26a --- /dev/null +++ b/leptonica/prog/lowaccess_reg.c @@ -0,0 +1,304 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * lowaccess_reg.c + * + * Test low-level accessors + * + * Note that the gnu C++ compiler: + * * allows a non-void* ptr to be passed to a function f(void *ptr) + * * forbids a void* ptr to be passed to a function f(non-void *ptr) + * ('forbids' may be too strong: it issues a warning) + * + * For this reason, the l_getData*() and l_setData*() accessors + * now take a (void *)lineptr, but internally cast to (l_uint32 *) + * so that the addressing arithmetic works properly. + * + * By the same token, the GET_DATA_*() and SET_DATA_*() macro + * accessors now cast the input ptr to (l_uint32 *) for 1, 2 and 4 bpp. + * This allows them to take a (void *)lineptr. + * + * In this test, we reconstruct pixs in different ways, pretending + * that it is composed of pixels of sizes 1, 2, 4, 8, 16 and 32 bpp. + * We also add irrelevant high order bits to the values, testing that + * masking is done properly depending on the pixel size. + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + +static void CompareResults(PIX *pixs, PIX *pix1, PIX *pix2, + l_int32 count1, l_int32 count2, + const char *descr, L_REGPARAMS *rp); + +int main(int argc, + char **argv) +{ +l_int32 i, j, k, w, h, w2, w4, w8, w16, w32, wpl; +l_int32 count1, count2, count3; +l_uint32 val32, val1, val2; +l_uint32 *data1, *line1, *data2, *line2; +void **lines1, **linet1, **linet2; +PIX *pixs, *pix1, *pix2; +L_REGPARAMS *rp; + + if (regTestSetup(argc, argv, &rp)) + return 1; + + pixs = pixRead("feyn-fract.tif"); + pixGetDimensions(pixs, &w, &h, NULL); + data1 = pixGetData(pixs); + wpl = pixGetWpl(pixs); + lines1 = pixGetLinePtrs(pixs, NULL); + + /* Get timing for the 3 different methods */ + startTimer(); + for (k = 0; k < 10; k++) { + count1 = 0; + for (i = 0; i < h; i++) { + for (j = 0; j < w; j++) { + if (GET_DATA_BIT(lines1[i], j)) + count1++; + } + } + } + lept_stderr("Time with line ptrs = %5.3f sec, count1 = %d\n", + stopTimer(), count1); + + startTimer(); + for (k = 0; k < 10; k++) { + count2 = 0; + for (i = 0; i < h; i++) { + line1 = data1 + i * wpl; + for (j = 0; j < w; j++) { + if (l_getDataBit(line1, j)) + count2++; + } + } + } + lept_stderr("Time with l_get* = %5.3f sec, count2 = %d\n", + stopTimer(), count2); + + startTimer(); + for (k = 0; k < 10; k++) { + count3 = 0; + for (i = 0; i < h; i++) { + for (j = 0; j < w; j++) { + pixGetPixel(pixs, j, i, &val32); + count3 += val32; + } + } + } + lept_stderr("Time with pixGetPixel() = %5.3f sec, count3 = %d\n", + stopTimer(), count3); + + pix1 = pixCreateTemplate(pixs); + linet1 = pixGetLinePtrs(pix1, NULL); + pix2 = pixCreateTemplate(pixs); + data2 = pixGetData(pix2); + linet2 = pixGetLinePtrs(pix2, NULL); + + /* ------------------------------------------------- */ + /* Test different methods for 1 bpp */ + /* ------------------------------------------------- */ + count1 = 0; + for (i = 0; i < h; i++) { + for (j = 0; j < w; j++) { + val1 = GET_DATA_BIT(lines1[i], j); + count1 += val1; + if (val1) SET_DATA_BIT(linet1[i], j); + } + } + count2 = 0; + for (i = 0; i < h; i++) { + line1 = data1 + i * wpl; + line2 = data2 + i * wpl; + for (j = 0; j < w; j++) { + val2 = l_getDataBit(line1, j); + count2 += val2; + if (val2) l_setDataBit(line2, j); + } + } + CompareResults(pixs, pix1, pix2, count1, count2, "1 bpp", rp); + + /* ------------------------------------------------- */ + /* Test different methods for 2 bpp */ + /* ------------------------------------------------- */ + count1 = 0; + w2 = w / 2; + for (i = 0; i < h; i++) { + for (j = 0; j < w2; j++) { + val1 = GET_DATA_DIBIT(lines1[i], j); + count1 += val1; + val1 += 0xbbbbbbbc; + SET_DATA_DIBIT(linet1[i], j, val1); + } + } + count2 = 0; + for (i = 0; i < h; i++) { + line1 = data1 + i * wpl; + line2 = data2 + i * wpl; + for (j = 0; j < w2; j++) { + val2 = l_getDataDibit(line1, j); + count2 += val2; + val2 += 0xbbbbbbbc; + l_setDataDibit(line2, j, val2); + } + } + CompareResults(pixs, pix1, pix2, count1, count2, "2 bpp", rp); + + /* ------------------------------------------------- */ + /* Test different methods for 4 bpp */ + /* ------------------------------------------------- */ + count1 = 0; + w4 = w / 4; + for (i = 0; i < h; i++) { + for (j = 0; j < w4; j++) { + val1 = GET_DATA_QBIT(lines1[i], j); + count1 += val1; + val1 += 0xbbbbbbb0; + SET_DATA_QBIT(linet1[i], j, val1); + } + } + count2 = 0; + for (i = 0; i < h; i++) { + line1 = data1 + i * wpl; + line2 = data2 + i * wpl; + for (j = 0; j < w4; j++) { + val2 = l_getDataQbit(line1, j); + count2 += val2; + val2 += 0xbbbbbbb0; + l_setDataQbit(line2, j, val2); + } + } + CompareResults(pixs, pix1, pix2, count1, count2, "4 bpp", rp); + + /* ------------------------------------------------- */ + /* Test different methods for 8 bpp */ + /* ------------------------------------------------- */ + count1 = 0; + w8 = w / 8; + for (i = 0; i < h; i++) { + for (j = 0; j < w8; j++) { + val1 = GET_DATA_BYTE(lines1[i], j); + count1 += val1; + val1 += 0xbbbbbb00; + SET_DATA_BYTE(linet1[i], j, val1); + } + } + count2 = 0; + for (i = 0; i < h; i++) { + line1 = data1 + i * wpl; + line2 = data2 + i * wpl; + for (j = 0; j < w8; j++) { + val2 = l_getDataByte(line1, j); + count2 += val2; + val2 += 0xbbbbbb00; + l_setDataByte(line2, j, val2); + } + } + CompareResults(pixs, pix1, pix2, count1, count2, "8 bpp", rp); + + /* ------------------------------------------------- */ + /* Test different methods for 16 bpp */ + /* ------------------------------------------------- */ + count1 = 0; + w16 = w / 16; + for (i = 0; i < h; i++) { + for (j = 0; j < w16; j++) { + val1 = GET_DATA_TWO_BYTES(lines1[i], j); + count1 += val1; + val1 += 0xbbbb0000; + SET_DATA_TWO_BYTES(linet1[i], j, val1); + } + } + count2 = 0; + for (i = 0; i < h; i++) { + line1 = data1 + i * wpl; + line2 = data2 + i * wpl; + for (j = 0; j < w16; j++) { + val2 = l_getDataTwoBytes(line1, j); + count2 += val2; + val2 += 0xbbbb0000; + l_setDataTwoBytes(line2, j, val2); + } + } + CompareResults(pixs, pix1, pix2, count1, count2, "16 bpp", rp); + + /* ------------------------------------------------- */ + /* Test different methods for 32 bpp */ + /* ------------------------------------------------- */ + count1 = 0; + w32 = w / 32; + for (i = 0; i < h; i++) { + for (j = 0; j < w32; j++) { + val1 = GET_DATA_FOUR_BYTES(lines1[i], j); + count1 += val1 & 0xfff; + SET_DATA_FOUR_BYTES(linet1[i], j, val1); + } + } + count2 = 0; + for (i = 0; i < h; i++) { + line1 = data1 + i * wpl; + line2 = data2 + i * wpl; + for (j = 0; j < w32; j++) { + val2 = l_getDataFourBytes(line1, j); + count2 += val2 & 0xfff; + l_setDataFourBytes(line2, j, val2); + } + } + CompareResults(pixs, pix1, pix2, count1, count2, "32 bpp", rp); + pixDestroy(&pixs); + pixDestroy(&pix1); + pixDestroy(&pix2); + lept_free(lines1); + lept_free(linet1); + lept_free(linet2); + return regTestCleanup(rp); +} + + +static void +CompareResults(PIX *pixs, + PIX *pix1, + PIX *pix2, + l_int32 count1, + l_int32 count2, + const char *descr, + L_REGPARAMS *rp) +{ + lept_stderr("Compare set: %s; index starts at %d\n", descr, rp->index + 1); + regTestComparePix(rp, pixs, pix1); + regTestComparePix(rp, pixs, pix2); + regTestCompareValues(rp, count1, count2, 1); + pixClearAll(pix1); + pixClearAll(pix2); +} + diff --git a/leptonica/prog/lowsat_reg.c b/leptonica/prog/lowsat_reg.c new file mode 100644 index 00000000..6a01dea6 --- /dev/null +++ b/leptonica/prog/lowsat_reg.c @@ -0,0 +1,107 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * lowsat_reg.c + * + * Testing functions that identify and modify image pixels that + * have low saturation (i.e., are essentially gray). + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + +int main(int argc, + char **argv) +{ +l_int32 i, j, w, h, wpl, val; +l_uint32 gray32; +l_uint32 *data, *line; +PIX *pix1, *pix2, *pix3, *pix4, *pix5, *pix6, *pix7; +PIXA *pixa; +L_REGPARAMS *rp; + + if (regTestSetup(argc, argv, &rp)) + return 1; + + lept_mkdir("lept/lowsat"); + pixa = pixaCreate(0); + pix1 = pixRead("zier.jpg"); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 0 */ + pixDisplayWithTitle(pix1, 0, 100, NULL, rp->display); + pixaAddPix(pixa, pix1, L_INSERT); + + /* Embed the image in a varying gray background */ + pix2 = pixCreate(400, 580, 32); + data = pixGetData(pix2); + wpl = pixGetWpl(pix2); + for (i = 0; i < 580; i++) { + line = data + i * wpl; + val = 150 + 50 * i / 580; + for (j = 0; j < 400; j++) { + composeRGBPixel(val, val, val, &gray32); + line[j] = gray32; + } + } + pixRasterop(pix2, 70, 90, 270, 400, PIX_SRC, pix1, 0, 0); + regTestWritePixAndCheck(rp, pix2, IFF_PNG); /* 1 */ + pixaAddPix(pixa, pix2, L_COPY); + pixDisplayWithTitle(pix2, 300, 100, NULL, rp->display); + + /* Darken the gray pixels, leaving most of the + * the others unaffected. */ + pix3 = pixDarkenGray(NULL, pix2, 220, 10); + regTestWritePixAndCheck(rp, pix3, IFF_PNG); /* 2 */ + pixaAddPix(pixa, pix3, L_COPY); + pixDisplayWithTitle(pix3, 700, 100, "gray pixels are black", rp->display); + + /* We can also generate a mask over the gray pixels, + * eliminating noise from very dark pixels morphologically. */ + pix4 = pixMaskOverGrayPixels(pix2, 220, 10); + regTestWritePixAndCheck(rp, pix4, IFF_PNG); /* 3 */ + pixaAddPix(pixa, pix4, L_INSERT); + pixDisplayWithTitle(pix4, 1100, 100, "mask over gray pixels", rp->display); + pix5 = pixMorphSequence(pix4, "o20.20", 0); /* remove noise */ + regTestWritePixAndCheck(rp, pix5, IFF_PNG); /* 4 */ + pixaAddPix(pixa, pix5, L_COPY); + pixDisplayWithTitle(pix5, 1500, 100, "clean mask over gray", rp->display); + pixInvert(pix5, pix5); + pix6 = pixConvertTo32(pix5); + pix7 = pixAddRGB(pix2, pix6); + regTestWritePixAndCheck(rp, pix7, IFF_PNG); /* 5 */ + pixaAddPix(pixa, pix7, L_INSERT); + pixDisplayWithTitle(pix7, 1900, 100, NULL, rp->display); + + pixDestroy(&pix2); + pixDestroy(&pix3); + pixDestroy(&pix5); + pixDestroy(&pix6); + pixaDestroy(&pixa); + return regTestCleanup(rp); +} diff --git a/leptonica/prog/lucasta-frag.jpg b/leptonica/prog/lucasta-frag.jpg Binary files differnew file mode 100644 index 00000000..5df491b5 --- /dev/null +++ b/leptonica/prog/lucasta-frag.jpg diff --git a/leptonica/prog/lucasta.047.jpg b/leptonica/prog/lucasta.047.jpg Binary files differnew file mode 100644 index 00000000..58328b10 --- /dev/null +++ b/leptonica/prog/lucasta.047.jpg diff --git a/leptonica/prog/lucasta.1.300.tif b/leptonica/prog/lucasta.1.300.tif Binary files differnew file mode 100644 index 00000000..b086ce19 --- /dev/null +++ b/leptonica/prog/lucasta.1.300.tif diff --git a/leptonica/prog/lucasta.150.jpg b/leptonica/prog/lucasta.150.jpg Binary files differnew file mode 100644 index 00000000..baf70b1f --- /dev/null +++ b/leptonica/prog/lucasta.150.jpg diff --git a/leptonica/prog/lyra.005.jpg b/leptonica/prog/lyra.005.jpg Binary files differnew file mode 100644 index 00000000..70b15f84 --- /dev/null +++ b/leptonica/prog/lyra.005.jpg diff --git a/leptonica/prog/lyra.036.jpg b/leptonica/prog/lyra.036.jpg Binary files differnew file mode 100644 index 00000000..8c52244f --- /dev/null +++ b/leptonica/prog/lyra.036.jpg diff --git a/leptonica/prog/lyra.5.na b/leptonica/prog/lyra.5.na new file mode 100644 index 00000000..29cb80a0 --- /dev/null +++ b/leptonica/prog/lyra.5.na @@ -0,0 +1,725 @@ + +Numa Version 1 +Number of numbers = 721 + [0] = 3.000000 + [1] = 0.000000 + [2] = 0.000000 + [3] = 0.000000 + [4] = 0.000000 + [5] = 0.000000 + [6] = 0.000000 + [7] = 0.000000 + [8] = 0.000000 + [9] = 0.000000 + [10] = 0.000000 + [11] = 0.000000 + [12] = 0.000000 + [13] = 0.000000 + [14] = 0.000000 + [15] = 0.000000 + [16] = 0.000000 + [17] = 0.000000 + [18] = 0.000000 + [19] = 0.000000 + [20] = 0.000000 + [21] = 0.000000 + [22] = 0.000000 + [23] = 0.000000 + [24] = 0.000000 + [25] = 0.000000 + [26] = 0.000000 + [27] = 0.000000 + [28] = 1.000000 + [29] = 0.000000 + [30] = 6.000000 + [31] = 5.000000 + [32] = 0.000000 + [33] = 0.000000 + [34] = 0.000000 + [35] = 0.000000 + [36] = 0.000000 + [37] = 0.000000 + [38] = 0.000000 + [39] = 0.000000 + [40] = 0.000000 + [41] = 0.000000 + [42] = 0.000000 + [43] = 0.000000 + [44] = 0.000000 + [45] = 0.000000 + [46] = 0.000000 + [47] = 0.000000 + [48] = 0.000000 + [49] = 0.000000 + [50] = 0.000000 + [51] = 0.000000 + [52] = 0.000000 + [53] = 0.000000 + [54] = 0.000000 + [55] = 0.000000 + [56] = 0.000000 + [57] = 0.000000 + [58] = 0.000000 + [59] = 0.000000 + [60] = 0.000000 + [61] = 0.000000 + [62] = 0.000000 + [63] = 0.000000 + [64] = 0.000000 + [65] = 0.000000 + [66] = 0.000000 + [67] = 0.000000 + [68] = 0.000000 + [69] = 0.000000 + [70] = 0.000000 + [71] = 0.000000 + [72] = 0.000000 + [73] = 0.000000 + [74] = 0.000000 + [75] = 0.000000 + [76] = 0.000000 + [77] = 0.000000 + [78] = 0.000000 + [79] = 0.000000 + [80] = 0.000000 + [81] = 0.000000 + [82] = 0.000000 + [83] = 0.000000 + [84] = 0.000000 + [85] = 0.000000 + [86] = 0.000000 + [87] = 0.000000 + [88] = 0.000000 + [89] = 0.000000 + [90] = 0.000000 + [91] = 0.000000 + [92] = 0.000000 + [93] = 0.000000 + [94] = 0.000000 + [95] = 0.000000 + [96] = 0.000000 + [97] = 0.000000 + [98] = 0.000000 + [99] = 0.000000 + [100] = 0.000000 + [101] = 0.000000 + [102] = 1.000000 + [103] = 0.000000 + [104] = 0.000000 + [105] = 0.000000 + [106] = 0.000000 + [107] = 0.000000 + [108] = 0.000000 + [109] = 0.000000 + [110] = 0.000000 + [111] = 0.000000 + [112] = 1.000000 + [113] = 0.000000 + [114] = 0.000000 + [115] = 0.000000 + [116] = 0.000000 + [117] = 0.000000 + [118] = 0.000000 + [119] = 0.000000 + [120] = 0.000000 + [121] = 0.000000 + [122] = 0.000000 + [123] = 0.000000 + [124] = 0.000000 + [125] = 0.000000 + [126] = 0.000000 + [127] = 0.000000 + [128] = 0.000000 + [129] = 0.000000 + [130] = 0.000000 + [131] = 0.000000 + [132] = 0.000000 + [133] = 0.000000 + [134] = 0.000000 + [135] = 0.000000 + [136] = 0.000000 + [137] = 0.000000 + [138] = 0.000000 + [139] = 0.000000 + [140] = 0.000000 + [141] = 0.000000 + [142] = 0.000000 + [143] = 0.000000 + [144] = 0.000000 + [145] = 0.000000 + [146] = 0.000000 + [147] = 0.000000 + [148] = 0.000000 + [149] = 0.000000 + [150] = 0.000000 + [151] = 0.000000 + [152] = 0.000000 + [153] = 0.000000 + [154] = 0.000000 + [155] = 0.000000 + [156] = 0.000000 + [157] = 0.000000 + [158] = 0.000000 + [159] = 0.000000 + [160] = 0.000000 + [161] = 0.000000 + [162] = 0.000000 + [163] = 0.000000 + [164] = 0.000000 + [165] = 0.000000 + [166] = 0.000000 + [167] = 7.000000 + [168] = 27.000000 + [169] = 39.000000 + [170] = 75.000000 + [171] = 95.000000 + [172] = 113.000000 + [173] = 109.000000 + [174] = 111.000000 + [175] = 103.000000 + [176] = 103.000000 + [177] = 111.000000 + [178] = 107.000000 + [179] = 83.000000 + [180] = 79.000000 + [181] = 85.000000 + [182] = 93.000000 + [183] = 77.000000 + [184] = 68.000000 + [185] = 76.000000 + [186] = 80.000000 + [187] = 80.000000 + [188] = 89.000000 + [189] = 101.000000 + [190] = 127.000000 + [191] = 135.000000 + [192] = 107.000000 + [193] = 120.000000 + [194] = 112.000000 + [195] = 124.000000 + [196] = 113.000000 + [197] = 107.000000 + [198] = 91.000000 + [199] = 78.000000 + [200] = 74.000000 + [201] = 77.000000 + [202] = 87.000000 + [203] = 85.000000 + [204] = 93.000000 + [205] = 92.000000 + [206] = 98.000000 + [207] = 102.000000 + [208] = 82.000000 + [209] = 103.000000 + [210] = 91.000000 + [211] = 99.000000 + [212] = 103.000000 + [213] = 101.000000 + [214] = 109.000000 + [215] = 89.000000 + [216] = 79.000000 + [217] = 97.000000 + [218] = 99.000000 + [219] = 95.000000 + [220] = 91.000000 + [221] = 97.000000 + [222] = 87.000000 + [223] = 97.000000 + [224] = 85.000000 + [225] = 109.000000 + [226] = 103.000000 + [227] = 107.000000 + [228] = 97.000000 + [229] = 89.000000 + [230] = 87.000000 + [231] = 95.000000 + [232] = 101.000000 + [233] = 97.000000 + [234] = 79.000000 + [235] = 85.000000 + [236] = 109.000000 + [237] = 93.000000 + [238] = 97.000000 + [239] = 87.000000 + [240] = 87.000000 + [241] = 103.000000 + [242] = 97.000000 + [243] = 93.000000 + [244] = 107.000000 + [245] = 111.000000 + [246] = 107.000000 + [247] = 131.000000 + [248] = 115.000000 + [249] = 117.000000 + [250] = 105.000000 + [251] = 81.000000 + [252] = 93.000000 + [253] = 103.000000 + [254] = 89.000000 + [255] = 75.000000 + [256] = 91.000000 + [257] = 99.000000 + [258] = 99.000000 + [259] = 133.000000 + [260] = 127.000000 + [261] = 107.000000 + [262] = 119.000000 + [263] = 101.000000 + [264] = 107.000000 + [265] = 101.000000 + [266] = 89.000000 + [267] = 97.000000 + [268] = 91.000000 + [269] = 97.000000 + [270] = 101.000000 + [271] = 107.000000 + [272] = 101.000000 + [273] = 97.000000 + [274] = 99.000000 + [275] = 97.000000 + [276] = 99.000000 + [277] = 105.000000 + [278] = 103.000000 + [279] = 103.000000 + [280] = 87.000000 + [281] = 89.000000 + [282] = 103.000000 + [283] = 87.000000 + [284] = 97.000000 + [285] = 103.000000 + [286] = 105.000000 + [287] = 107.000000 + [288] = 117.000000 + [289] = 121.000000 + [290] = 91.000000 + [291] = 111.000000 + [292] = 100.000000 + [293] = 102.000000 + [294] = 83.000000 + [295] = 95.000000 + [296] = 85.000000 + [297] = 95.000000 + [298] = 109.000000 + [299] = 115.000000 + [300] = 113.000000 + [301] = 103.000000 + [302] = 119.000000 + [303] = 111.000000 + [304] = 103.000000 + [305] = 107.000000 + [306] = 93.000000 + [307] = 102.000000 + [308] = 104.000000 + [309] = 100.000000 + [310] = 82.000000 + [311] = 85.000000 + [312] = 108.000000 + [313] = 120.000000 + [314] = 99.000000 + [315] = 111.000000 + [316] = 99.000000 + [317] = 103.000000 + [318] = 111.000000 + [319] = 101.000000 + [320] = 113.000000 + [321] = 107.000000 + [322] = 99.000000 + [323] = 105.000000 + [324] = 85.000000 + [325] = 89.000000 + [326] = 95.000000 + [327] = 81.000000 + [328] = 101.000000 + [329] = 105.000000 + [330] = 113.000000 + [331] = 95.000000 + [332] = 93.000000 + [333] = 109.000000 + [334] = 121.000000 + [335] = 109.000000 + [336] = 115.000000 + [337] = 113.000000 + [338] = 114.000000 + [339] = 118.000000 + [340] = 103.000000 + [341] = 114.000000 + [342] = 105.000000 + [343] = 107.000000 + [344] = 103.000000 + [345] = 101.000000 + [346] = 97.000000 + [347] = 91.000000 + [348] = 93.000000 + [349] = 95.000000 + [350] = 105.000000 + [351] = 107.000000 + [352] = 101.000000 + [353] = 119.000000 + [354] = 111.000000 + [355] = 95.000000 + [356] = 113.000000 + [357] = 97.000000 + [358] = 119.000000 + [359] = 99.000000 + [360] = 111.000000 + [361] = 97.000000 + [362] = 77.000000 + [363] = 93.000000 + [364] = 97.000000 + [365] = 91.000000 + [366] = 95.000000 + [367] = 95.000000 + [368] = 103.000000 + [369] = 99.000000 + [370] = 93.000000 + [371] = 99.000000 + [372] = 99.000000 + [373] = 97.000000 + [374] = 95.000000 + [375] = 85.000000 + [376] = 95.000000 + [377] = 105.000000 + [378] = 99.000000 + [379] = 105.000000 + [380] = 93.000000 + [381] = 107.000000 + [382] = 103.000000 + [383] = 95.000000 + [384] = 91.000000 + [385] = 95.000000 + [386] = 109.000000 + [387] = 105.000000 + [388] = 91.000000 + [389] = 103.000000 + [390] = 93.000000 + [391] = 95.000000 + [392] = 95.000000 + [393] = 99.000000 + [394] = 105.000000 + [395] = 107.000000 + [396] = 111.000000 + [397] = 101.000000 + [398] = 101.000000 + [399] = 93.000000 + [400] = 99.000000 + [401] = 103.000000 + [402] = 111.000000 + [403] = 101.000000 + [404] = 97.000000 + [405] = 95.000000 + [406] = 95.000000 + [407] = 113.000000 + [408] = 101.000000 + [409] = 115.000000 + [410] = 103.000000 + [411] = 85.000000 + [412] = 93.000000 + [413] = 85.000000 + [414] = 93.000000 + [415] = 95.000000 + [416] = 97.000000 + [417] = 91.000000 + [418] = 87.000000 + [419] = 75.000000 + [420] = 93.000000 + [421] = 83.000000 + [422] = 83.000000 + [423] = 85.000000 + [424] = 97.000000 + [425] = 101.000000 + [426] = 107.000000 + [427] = 113.000000 + [428] = 109.000000 + [429] = 99.000000 + [430] = 103.000000 + [431] = 99.000000 + [432] = 107.000000 + [433] = 91.000000 + [434] = 101.000000 + [435] = 91.000000 + [436] = 111.000000 + [437] = 113.000000 + [438] = 81.000000 + [439] = 87.000000 + [440] = 91.000000 + [441] = 93.000000 + [442] = 97.000000 + [443] = 105.000000 + [444] = 105.000000 + [445] = 89.000000 + [446] = 87.000000 + [447] = 93.000000 + [448] = 97.000000 + [449] = 83.000000 + [450] = 85.000000 + [451] = 67.000000 + [452] = 81.000000 + [453] = 103.000000 + [454] = 99.000000 + [455] = 71.000000 + [456] = 77.000000 + [457] = 83.000000 + [458] = 85.000000 + [459] = 79.000000 + [460] = 89.000000 + [461] = 101.000000 + [462] = 83.000000 + [463] = 87.000000 + [464] = 81.000000 + [465] = 81.000000 + [466] = 73.000000 + [467] = 73.000000 + [468] = 79.000000 + [469] = 77.000000 + [470] = 75.000000 + [471] = 95.000000 + [472] = 101.000000 + [473] = 103.000000 + [474] = 97.000000 + [475] = 95.000000 + [476] = 99.000000 + [477] = 93.000000 + [478] = 95.000000 + [479] = 103.000000 + [480] = 101.000000 + [481] = 101.000000 + [482] = 107.000000 + [483] = 81.000000 + [484] = 91.000000 + [485] = 103.000000 + [486] = 91.000000 + [487] = 79.000000 + [488] = 77.000000 + [489] = 97.000000 + [490] = 91.000000 + [491] = 85.000000 + [492] = 91.000000 + [493] = 71.000000 + [494] = 85.000000 + [495] = 71.000000 + [496] = 83.000000 + [497] = 93.000000 + [498] = 85.000000 + [499] = 89.000000 + [500] = 87.000000 + [501] = 109.000000 + [502] = 89.000000 + [503] = 75.000000 + [504] = 89.000000 + [505] = 75.000000 + [506] = 87.000000 + [507] = 93.000000 + [508] = 87.000000 + [509] = 81.000000 + [510] = 91.000000 + [511] = 91.000000 + [512] = 91.000000 + [513] = 89.000000 + [514] = 101.000000 + [515] = 105.000000 + [516] = 111.000000 + [517] = 99.000000 + [518] = 93.000000 + [519] = 105.000000 + [520] = 103.000000 + [521] = 101.000000 + [522] = 87.000000 + [523] = 93.000000 + [524] = 89.000000 + [525] = 91.000000 + [526] = 79.000000 + [527] = 59.000000 + [528] = 13.000000 + [529] = 9.000000 + [530] = 7.000000 + [531] = 5.000000 + [532] = 5.000000 + [533] = 1.000000 + [534] = 0.000000 + [535] = 0.000000 + [536] = 0.000000 + [537] = 0.000000 + [538] = 0.000000 + [539] = 0.000000 + [540] = 0.000000 + [541] = 0.000000 + [542] = 0.000000 + [543] = 0.000000 + [544] = 0.000000 + [545] = 0.000000 + [546] = 0.000000 + [547] = 0.000000 + [548] = 0.000000 + [549] = 0.000000 + [550] = 0.000000 + [551] = 1.000000 + [552] = 0.000000 + [553] = 0.000000 + [554] = 0.000000 + [555] = 0.000000 + [556] = 0.000000 + [557] = 0.000000 + [558] = 0.000000 + [559] = 0.000000 + [560] = 0.000000 + [561] = 0.000000 + [562] = 0.000000 + [563] = 0.000000 + [564] = 0.000000 + [565] = 0.000000 + [566] = 0.000000 + [567] = 0.000000 + [568] = 0.000000 + [569] = 0.000000 + [570] = 0.000000 + [571] = 0.000000 + [572] = 0.000000 + [573] = 0.000000 + [574] = 0.000000 + [575] = 0.000000 + [576] = 0.000000 + [577] = 0.000000 + [578] = 0.000000 + [579] = 0.000000 + [580] = 0.000000 + [581] = 0.000000 + [582] = 0.000000 + [583] = 0.000000 + [584] = 0.000000 + [585] = 0.000000 + [586] = 0.000000 + [587] = 0.000000 + [588] = 0.000000 + [589] = 0.000000 + [590] = 0.000000 + [591] = 0.000000 + [592] = 0.000000 + [593] = 0.000000 + [594] = 0.000000 + [595] = 5.000000 + [596] = 17.000000 + [597] = 7.000000 + [598] = 7.000000 + [599] = 0.000000 + [600] = 0.000000 + [601] = 0.000000 + [602] = 0.000000 + [603] = 0.000000 + [604] = 0.000000 + [605] = 0.000000 + [606] = 0.000000 + [607] = 0.000000 + [608] = 0.000000 + [609] = 0.000000 + [610] = 0.000000 + [611] = 0.000000 + [612] = 0.000000 + [613] = 0.000000 + [614] = 1.000000 + [615] = 5.000000 + [616] = 43.000000 + [617] = 87.000000 + [618] = 87.000000 + [619] = 83.000000 + [620] = 95.000000 + [621] = 93.000000 + [622] = 91.000000 + [623] = 101.000000 + [624] = 87.000000 + [625] = 89.000000 + [626] = 87.000000 + [627] = 91.000000 + [628] = 86.000000 + [629] = 81.000000 + [630] = 71.000000 + [631] = 87.000000 + [632] = 77.000000 + [633] = 91.000000 + [634] = 87.000000 + [635] = 79.000000 + [636] = 79.000000 + [637] = 89.000000 + [638] = 93.000000 + [639] = 87.000000 + [640] = 89.000000 + [641] = 101.000000 + [642] = 95.000000 + [643] = 99.000000 + [644] = 83.000000 + [645] = 83.000000 + [646] = 71.000000 + [647] = 71.000000 + [648] = 81.000000 + [649] = 84.000000 + [650] = 98.000000 + [651] = 101.000000 + [652] = 81.000000 + [653] = 83.000000 + [654] = 90.000000 + [655] = 91.000000 + [656] = 80.000000 + [657] = 85.000000 + [658] = 91.000000 + [659] = 79.000000 + [660] = 99.000000 + [661] = 83.000000 + [662] = 81.000000 + [663] = 102.000000 + [664] = 105.000000 + [665] = 89.000000 + [666] = 86.000000 + [667] = 84.000000 + [668] = 78.000000 + [669] = 86.000000 + [670] = 101.000000 + [671] = 90.000000 + [672] = 82.000000 + [673] = 91.000000 + [674] = 93.000000 + [675] = 93.000000 + [676] = 95.000000 + [677] = 95.000000 + [678] = 97.000000 + [679] = 89.000000 + [680] = 90.000000 + [681] = 90.000000 + [682] = 104.000000 + [683] = 90.000000 + [684] = 83.000000 + [685] = 84.000000 + [686] = 96.000000 + [687] = 86.000000 + [688] = 86.000000 + [689] = 74.000000 + [690] = 76.000000 + [691] = 86.000000 + [692] = 86.000000 + [693] = 87.000000 + [694] = 100.000000 + [695] = 90.000000 + [696] = 84.000000 + [697] = 92.000000 + [698] = 90.000000 + [699] = 83.000000 + [700] = 79.000000 + [701] = 79.000000 + [702] = 71.000000 + [703] = 81.000000 + [704] = 79.000000 + [705] = 89.000000 + [706] = 85.000000 + [707] = 83.000000 + [708] = 95.000000 + [709] = 87.000000 + [710] = 73.000000 + [711] = 74.000000 + [712] = 72.000000 + [713] = 67.000000 + [714] = 74.000000 + [715] = 80.000000 + [716] = 78.000000 + [717] = 80.000000 + [718] = 82.000000 + [719] = 0.000000 + [720] = 0.000000 + diff --git a/leptonica/prog/makefile.static b/leptonica/prog/makefile.static new file mode 100644 index 00000000..d85c42b1 --- /dev/null +++ b/leptonica/prog/makefile.static @@ -0,0 +1,1236 @@ +#/*====================================================================* +# - 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. +# *====================================================================*/ + +# makefile (for linux) +# +# For a nodebug version: make +# For a debug version: make DEBUG=yes +# For a shared library version: make SHARED=yes +# With nonstandard library directories: +# make EXTRALIBS="-L<nonstandard-lib-dir>" +# With nonstandard header directories +# make EXTRAINCLUDES="-I<nonstandard-incl-dir>" +# +# To remove all executables: make clean +# +# ======================================================================== +# IMPORTANT: This Makefile is set up to link with liblept.a and liblept.so +# that were built using using src/makefile (i.e., with 'make' in src). +# If instead you built the library with configure/make/makeinstall, +# you must do this here: +# +# (1) Change LIB_NODEBUG_DIR: +# LIB_NODEBUG_DIR = /usr/local/lib [or wherever you installed +# liblept.a] +# (2) Edit ALL_LIBS to include the imaging libraries on your system, +# as found in config_auto.h. For example, if you have the +# jpeg, png, tiff and gif libraries, set +# ALL_LIBS = $(LEPTLIB) -ltiff -ljpeg -lpng -lgif -lz -lm +# ======================================================================== +# +# To link and run programs using shared (dynamic linked) libraries, +# you must do one of the following two things: +# +# (a) make sure your LD_LIBRARY_PATH variable points to the +# directory in which the *.so files are placed; e.g. +# export LD_LIBRARY_PATH=../lib/shared:$LD_LIBRARY_PATH +# or +# (b) have the *.so files (or links to them) in this directory +# +# On cygwin, remove -fPIC from CC. I believe that these files -- +# convertfilestops.c, jbcorrelation.c, jbrankhaus.c, maketile.c, +# and htmlviewer.c -- which use posix directory functions, will +# now work properly. +# +# See below for enabling gif read/write. + + +# Libraries are built into a binary tree with its root in the +# parent directory +ROOT_DIR = .. + +LIB_NODEBUG_DIR = $(ROOT_DIR)/lib/nodebug +LIB_DEBUG_DIR = $(ROOT_DIR)/lib/debug +LIB_SHARED_DIR = $(ROOT_DIR)/lib/shared + +# Include files are found within the same tree +IMAGELIB_INCL = $(ROOT_DIR)/src + +CC = gcc -std=c99 -U__STRICT_ANSI__ -D__USE_MINGW_ANSI_STDIO +#CC = gcc -std=c89 -U__STRICT_ANSI__ -D__USE_MINGW_ANSI_STDIO +#CC = gcc -std=gnu99 -D_POSIX_C_SOURCE=200809L -DANSI -fPIC +#CC = gcc -std=gnu89 -DANSI -fPIC +#CC = gcc -std=gnu89 -Werror -DANSI -fPIC +#CC = g++ -Werror -fPIC + +ifdef SHARED + LIB_DIR = $(LIB_SHARED_DIR) + OPTIMIZE = -O2 +else + ifdef DEBUG + LIB_DIR = $(LIB_DEBUG_DIR) + OPTIMIZE = -g + else + LIB_DIR = $(LIB_NODEBUG_DIR) + OPTIMIZE = -O2 + endif +endif + +OPTIONS = + +INCLUDES = -I$(IMAGELIB_INCL) -I/usr/X11R6/include $(EXTRAINCLUDES) +#INCLUDES = -I$(IMAGELIB_INCL) -I/usr/X11R6/include -I/usr/local/include $(EXTRAINCLUDES) + +CFLAGS = $(OPTIMIZE) $(OPTIONS) + +# Use -D_STANDARD_C to stub out the non-posix GNU functions fmemopen() +# and open_memstream() +CPPFLAGS = $(INCLUDES) + +LDFLAGS += -L$(LIB_DIR) -L/usr/X11R6/lib -L/usr/lib $(EXTRALIBS) +#LDFLAGS += -L$(LIB_DIR) -L/usr/X11R6/lib -L/usr/local/lib -L/usr/lib $(EXTRALIBS) + +ifdef SHARED + LEPTLIB = $(LIB_DIR)/liblept.so +else + LEPTLIB = $(LIB_DIR)/liblept.a +endif + +# To enable webp read/write: +# (1) In src/environ.h: #define HAVE_LIBWEBP +# (2) Install libwebp +# (3) Include -lwebp in ALL_LIBS +# To enable webpanim read/write: +# (1) In src/environ.h: #define HAVE_LIBWEBP_ANIM +# (2) Install libwebp with +# ./configure --enable-everything (to get mux/demux libs) +# Modify makefile.unix to add -fPIC: +# CFLAGS = -O3 -DNDEBUG $(EXTRA_FLAGS) -fPIC +# (3) Include -lwebpmux in ALL_LIBS +# To enable gif read/write: +# (1) In src/environ.h: #define HAVE_LIBGIF +# (2) Install libgif +# (3) Include -lgif in ALL_LIBS + +# Be sure LD_LIBRARY_PATH includes the appropriate library directories, such +# as /usr/local/include, in which libwebp.so and/or libgif.so are installed +# Use or modify an appropriate line below for ALL_LIBS: +ALL_LIBS = $(LEPTLIB) -ltiff -ljpeg -lpng -lz -lm +#ALL_LIBS = $(LEPTLIB) -ltiff -ljpeg -lpng -lwebp -lz -lm +#ALL_LIBS = $(LEPTLIB) -ltiff -ljpeg -lpng -lwebp -lwebpmux -lz -lm +#ALL_LIBS = $(LEPTLIB) -ltiff -ljpeg -lpng -lwebp -lopenjp2 -lz -lm +#ALL_LIBS = $(LEPTLIB) -ltiff -ljpeg -lpng -lwebp -lopenjp2 -lgif -lz -lm +#ALL_LIBS = $(LEPTLIB) -ltiff -ljpeg -lpng -lwebp -lwebpmux -lopenjp2 -lgif -lz -lm + +######################################################################### + +SRC = adaptmap_reg.c adaptnorm_reg.c affine_reg.c \ + alltests_reg.c alphaops_reg.c alphaxform_reg.c \ + baseline_reg.c bilateral1_reg.c bilateral2_reg.c \ + bilinear_reg.c binarize_reg.c \ + binmorph1_reg.c binmorph2_reg.c binmorph3_reg.c \ + binmorph4_reg.c binmorph5_reg.c binmorph6_reg.c \ + blackwhite_reg.c blend1_reg.c blend2_reg.c \ + blend3_reg.c blend4_reg.c blend5_reg.c \ + boxa1_reg.c boxa2_reg.c boxa3_reg.c boxa4_reg.c \ + bytea_reg.c ccbord_reg.c ccthin1_reg.c ccthin2_reg.c \ + checkerboard_reg.c circle_reg.c \ + cmapquant_reg.c colorcontent_reg.c \ + colorfill_reg.c coloring_reg.c colorize_reg.c \ + colormask_reg.c colormorph_reg.c colorquant_reg.c \ + colorseg_reg.c colorspace_reg.c \ + compare_reg.c compfilter_reg.c \ + conncomp_reg.c conversion_reg.c convolve_reg.c \ + crop_reg.c dewarp_reg.c distance_reg.c \ + dither_reg.c dna_reg.c \ + dwamorph1_reg.c dwamorph2_reg.c \ + edge_reg.c encoding_reg.c enhance_reg.c equal_reg.c \ + expand_reg.c extrema_reg.c falsecolor_reg.c \ + fhmtauto_reg.c files_reg.c \ + findcorners_reg.c findpattern_reg.c \ + flipdetect_reg.c fmorphauto_reg.c \ + fpix1_reg.c fpix2_reg.c \ + genfonts_reg.c gifio_reg.c \ + grayfill_reg.c graymorph1_reg.c \ + graymorph2_reg.c grayquant_reg.c \ + hardlight_reg.c hash_reg.c heap_reg.c \ + insert_reg.c ioformats_reg.c \ + iomisc_reg.c italic_reg.c \ + jbclass_reg.c jp2kio_reg.c jpegio_reg.c kernel_reg.c \ + label_reg.c lineremoval_reg.c locminmax_reg.c \ + logicops_reg.c lowaccess_reg.c lowsat_reg.c \ + maze_reg.c morphseq_reg.c mtiff_reg.c \ + multitype_reg.c nearline_reg.c newspaper_reg.c \ + numa1_reg.c numa2_reg.c numa3_reg.c \ + overlap_reg.c pageseg_reg.c paint_reg.c paintmask_reg.c \ + pdfio1_reg.c pdfio2_reg.c pdfseg_reg.c \ + pixa1_reg.c pixa2_reg.c \ + pixadisp_reg.c pixalloc_reg.c \ + pixcomp_reg.c pixmem_reg.c \ + pixserial_reg.c pixtile_reg.c \ + pngio_reg.c pnmio_reg.c \ + projection_reg.c projective_reg.c \ + psio_reg.c psioseg_reg.c \ + pta_reg.c ptra1_reg.c ptra2_reg.c quadtree_reg.c \ + rankbin_reg.c rankhisto_reg.c rank_reg.c \ + rasteropip_reg.c rasterop_reg.c rectangle_reg.c \ + rotate1_reg.c rotate2_reg.c rotateorth_reg.c \ + scale_reg.c seedspread_reg.c selio_reg.c \ + shear1_reg.c shear2_reg.c skew_reg.c \ + smallpix_reg.c smoothedge_reg.c \ + speckle_reg.c splitcomp_reg.c \ + string_reg.c subpixel_reg.c \ + texturefill_reg.c threshnorm_reg.c \ + translate_reg.c warper_reg.c \ + watershed_reg.c webpanimio_reg.c webpio_reg.c \ + wordboxes_reg.c writetext_reg.c xformbox_reg.c \ + adaptmap_dark.c arabic_lines.c arithtest.c \ + autogentest1.c autogentest2.c barcodetest.c \ + binarizefiles.c binarize_set.c bincompare.c \ + blendcmaptest.c buffertest.c \ + ccbordtest.c cctest1.c \ + cleanpdf.c colorsegtest.c comparepages.c \ + comparepixa.c comparetest.c \ + concatpdf.c contrasttest.c \ + convertfilestopdf.c convertfilestops.c \ + convertformat.c \ + convertsegfilestopdf.c convertsegfilestops.c \ + converttogray.c converttopdf.c converttops.c \ + cornertest.c corrupttest.c \ + croptext.c deskew_it.c \ + dewarprules.c dewarptest1.c dewarptest2.c \ + dewarptest3.c dewarptest4.c dewarptest5.c \ + digitprep1.c displayboxa.c displayboxes_on_pixa.c \ + displaypix.c displaypixa.c dwalineargen.c \ + fcombautogen.c fhmtautogen.c \ + fileinfo.c findbinding.c find_colorregions.c \ + findpattern1.c findpattern2.c findpattern3.c \ + fmorphautogen.c \ + fpixcontours.c gammatest.c \ + graphicstest.c graymorphtest.c \ + histoduptest.c histotest.c \ + htmlviewer.c imagetops.c \ + jbcorrelation.c jbrankhaus.c jbwords.c \ + lightcolortest.c listtest.c \ + livre_adapt.c livre_hmt.c livre_makefigs.c livre_orient.c \ + livre_pageseg.c livre_seedgen.c livre_tophat.c \ + maketile.c maptest.c messagetest.c misctest1.c \ + modifyhuesat.c morphtest1.c \ + numaranktest.c otsutest1.c otsutest2.c \ + pagesegtest1.c pagesegtest2.c \ + partifytest.c partitiontest.c percolatetest.c \ + pixaatest.c pixafileinfo.c plottest.c \ + printimage.c printsplitimage.c printtiff.c \ + rasteroptest.c rbtreetest.c \ + recog_bootnum1.c recog_bootnum2.c recog_bootnum3.c \ + recogsort.c recogtest1.c recogtest2.c recogtest3.c \ + recogtest4.c recogtest5.c recogtest6.c recogtest7.c \ + reducetest.c removecmap.c \ + renderfonts.c replacebytes.c \ + rotatefastalt.c rotate_it.c \ + rotateorthtest1.c rotatetest1.c \ + runlengthtest.c scaleandtile.c \ + scale_it.c scaletest1.c scaletest2.c \ + seedfilltest.c settest.c sharptest.c \ + sheartest.c showedges.c \ + skewtest.c sorttest.c splitimage2pdf.c \ + sudokutest.c textorient.c \ + tiffpdftest.c trctest.c \ + underlinetest.c warpertest.c wordsinorder.c \ + writemtiff.c xtractprotos.c yuvtest.c + +# Remove the .o files from these on clean +SRC2 = autogen.137.c dwalinear.3.c dwalinearlow.3.c + +###################################################################### + +all: $(SRC:%.c=%) + +# Jan 2018 (even smaller set of nine utility programs) +#debian: convertfilestopdf convertfilestops convertformat \ +# convertsegfilestopdf convertsegfilestops \ +# converttopdf converttops fileinfo xtractprotos + +# Jan 2014 (minimal set of utility programs) +#debian: convertfilestopdf convertfilestops convertformat \ +# convertsegfilestopdf convertsegfilestops \ +# converttopdf converttops fileinfo \ +# printimage printsplitimage printtiff \ +# splitimage2pdf xtractprotos + +# Jan 2014 (could have been in Jan 2014 debian, but left off) +# grayfill_reg histotest_reg sudokutest watershedtest + +# Jan 2012 +#debian: binarize_reg binmorph2_reg ccthin2_reg colorquant_reg \ +# colorseg_reg convolve_reg dewarp_reg \ +# dwamorph1_reg dwamorph2_reg \ +# distance_reg enhance_reg ioformats_reg \ +# maze_reg paintmask_reg \ +# rotate1_reg rotate2_reg scale_reg \ +# seedspread_reg splitcomp_reg threshnorm_reg \ +# warper_reg convertfilestopdf convertfilestops \ +# convertjpegfilestopdf converttops dewarptest1 \ +# fcombautogen fhmtautogen fileinfo \ +# fmorphautogen pdfiotest \ +# printimage printsplitimage splitimage2pdf \ +# sudokutest watershedtest xtractprotos + + +# Jan 2011 +#debian: binarize_reg cctest1 ccthin1_reg \ +# colormorphtest colorquant_reg colorspacetest \ +# comparetest convertfilestopdf convertfilestops \ +# convertformat converttops dewarp_reg \ +# distance_reg dithertest fileinfo \ +# flipdetect_reg fmorphauto_reg gammatest \ +# grayfill_reg graymorph1_reg grayquant_reg \ +# hardlight_reg ioformats_reg jbcorrelation \ +# kernel_reg lineremoval maze_reg \ +# pagesegtest1 paint_reg paintmask_reg \ +# printimage printsplitimage printtiff \ +# rank_reg ranktest scale_reg \ +# skewtest splitcomp_reg warper_reg \ +# watershedtest xtractprotos + +###################################################################### + +adaptmap_reg: adaptmap_reg.o $(LEPTLIB) + $(CC) -o adaptmap_reg adaptmap_reg.o $(ALL_LIBS) $(EXTRALIBS) + +adaptnorm_reg: adaptnorm_reg.o $(LEPTLIB) + $(CC) -o adaptnorm_reg adaptnorm_reg.o $(ALL_LIBS) $(EXTRALIBS) + +affine_reg: affine_reg.o $(LEPTLIB) + $(CC) -o affine_reg affine_reg.o $(ALL_LIBS) $(EXTRALIBS) + +alltests_reg: alltests_reg.o $(LEPTLIB) + $(CC) -o alltests_reg alltests_reg.o $(ALL_LIBS) $(EXTRALIBS) + +alphaops_reg: alphaops_reg.o $(LEPTLIB) + $(CC) -o alphaops_reg alphaops_reg.o $(ALL_LIBS) $(EXTRALIBS) + +alphaxform_reg: alphaxform_reg.o $(LEPTLIB) + $(CC) -o alphaxform_reg alphaxform_reg.o $(ALL_LIBS) $(EXTRALIBS) + +baseline_reg: baseline_reg.o $(LEPTLIB) + $(CC) -o baseline_reg baseline_reg.o $(ALL_LIBS) $(EXTRALIBS) + +bilateral1_reg: bilateral1_reg.o $(LEPTLIB) + $(CC) -o bilateral1_reg bilateral1_reg.o $(ALL_LIBS) $(EXTRALIBS) + +bilateral2_reg: bilateral2_reg.o $(LEPTLIB) + $(CC) -o bilateral2_reg bilateral2_reg.o $(ALL_LIBS) $(EXTRALIBS) + +bilinear_reg: bilinear_reg.o $(LEPTLIB) + $(CC) -o bilinear_reg bilinear_reg.o $(ALL_LIBS) $(EXTRALIBS) + +binarize_reg: binarize_reg.o $(LEPTLIB) + $(CC) -o binarize_reg binarize_reg.o $(ALL_LIBS) $(EXTRALIBS) + +binmorph1_reg: binmorph1_reg.o $(LEPTLIB) + $(CC) -o binmorph1_reg binmorph1_reg.o $(ALL_LIBS) $(EXTRALIBS) + +binmorph2_reg: binmorph2_reg.o $(LEPTLIB) + $(CC) -o binmorph2_reg binmorph2_reg.o $(ALL_LIBS) $(EXTRALIBS) + +binmorph3_reg: binmorph3_reg.o $(LEPTLIB) + $(CC) -o binmorph3_reg binmorph3_reg.o $(ALL_LIBS) $(EXTRALIBS) + +binmorph4_reg: binmorph4_reg.o $(LEPTLIB) + $(CC) -o binmorph4_reg binmorph4_reg.o $(ALL_LIBS) $(EXTRALIBS) + +binmorph5_reg: binmorph5_reg.o $(LEPTLIB) + $(CC) -o binmorph5_reg binmorph5_reg.o $(ALL_LIBS) $(EXTRALIBS) + +binmorph6_reg: binmorph6_reg.o $(LEPTLIB) + $(CC) -o binmorph6_reg binmorph6_reg.o $(ALL_LIBS) $(EXTRALIBS) + +blackwhite_reg: blackwhite_reg.o $(LEPTLIB) + $(CC) -o blackwhite_reg blackwhite_reg.o $(ALL_LIBS) $(EXTRALIBS) + +blend1_reg: blend1_reg.o $(LEPTLIB) + $(CC) -o blend1_reg blend1_reg.o $(ALL_LIBS) $(EXTRALIBS) + +blend2_reg: blend2_reg.o $(LEPTLIB) + $(CC) -o blend2_reg blend2_reg.o $(ALL_LIBS) $(EXTRALIBS) + +blend3_reg: blend3_reg.o $(LEPTLIB) + $(CC) -o blend3_reg blend3_reg.o $(ALL_LIBS) $(EXTRALIBS) + +blend4_reg: blend4_reg.o $(LEPTLIB) + $(CC) -o blend4_reg blend4_reg.o $(ALL_LIBS) $(EXTRALIBS) + +blend5_reg: blend5_reg.o $(LEPTLIB) + $(CC) -o blend5_reg blend5_reg.o $(ALL_LIBS) $(EXTRALIBS) + +boxa1_reg: boxa1_reg.o $(LEPTLIB) + $(CC) -o boxa1_reg boxa1_reg.o $(ALL_LIBS) $(EXTRALIBS) + +boxa2_reg: boxa2_reg.o $(LEPTLIB) + $(CC) -o boxa2_reg boxa2_reg.o $(ALL_LIBS) $(EXTRALIBS) + +boxa3_reg: boxa3_reg.o $(LEPTLIB) + $(CC) -o boxa3_reg boxa3_reg.o $(ALL_LIBS) $(EXTRALIBS) + +boxa4_reg: boxa4_reg.o $(LEPTLIB) + $(CC) -o boxa4_reg boxa4_reg.o $(ALL_LIBS) $(EXTRALIBS) + +bytea_reg: bytea_reg.o $(LEPTLIB) + $(CC) -o bytea_reg bytea_reg.o $(ALL_LIBS) $(EXTRALIBS) + +ccbord_reg: ccbord_reg.o $(LEPTLIB) + $(CC) -o ccbord_reg ccbord_reg.o $(ALL_LIBS) $(EXTRALIBS) + +ccthin1_reg: ccthin1_reg.o $(LEPTLIB) + $(CC) -o ccthin1_reg ccthin1_reg.o $(ALL_LIBS) $(EXTRALIBS) + +ccthin2_reg: ccthin2_reg.o $(LEPTLIB) + $(CC) -o ccthin2_reg ccthin2_reg.o $(ALL_LIBS) $(EXTRALIBS) + +checkerboard_reg: checkerboard_reg.o $(LEPTLIB) + $(CC) -o checkerboard_reg checkerboard_reg.o $(ALL_LIBS) $(EXTRALIBS) + +circle_reg: circle_reg.o $(LEPTLIB) + $(CC) -o circle_reg circle_reg.o $(ALL_LIBS) $(EXTRALIBS) + +cmapquant_reg: cmapquant_reg.o $(LEPTLIB) + $(CC) -o cmapquant_reg cmapquant_reg.o $(ALL_LIBS) $(EXTRALIBS) + +colorcontent_reg: colorcontent_reg.o $(LEPTLIB) + $(CC) -o colorcontent_reg colorcontent_reg.o $(ALL_LIBS) $(EXTRALIBS) + +colorfill_reg: colorfill_reg.o $(LEPTLIB) + $(CC) -o colorfill_reg colorfill_reg.o $(ALL_LIBS) $(EXTRALIBS) + +coloring_reg: coloring_reg.o $(LEPTLIB) + $(CC) -o coloring_reg coloring_reg.o $(ALL_LIBS) $(EXTRALIBS) + +colorize_reg: colorize_reg.o $(LEPTLIB) + $(CC) -o colorize_reg colorize_reg.o $(ALL_LIBS) $(EXTRALIBS) + +colormask_reg: colormask_reg.o $(LEPTLIB) + $(CC) -o colormask_reg colormask_reg.o $(ALL_LIBS) $(EXTRALIBS) + +colormorph_reg: colormorph_reg.o $(LEPTLIB) + $(CC) -o colormorph_reg colormorph_reg.o $(ALL_LIBS) $(EXTRALIBS) + +colorquant_reg: colorquant_reg.o $(LEPTLIB) + $(CC) -o colorquant_reg colorquant_reg.o $(ALL_LIBS) $(EXTRALIBS) + +colorseg_reg: colorseg_reg.o $(LEPTLIB) + $(CC) -o colorseg_reg colorseg_reg.o $(ALL_LIBS) $(EXTRALIBS) + +colorspace_reg: colorspace_reg.o $(LEPTLIB) + $(CC) -o colorspace_reg colorspace_reg.o $(ALL_LIBS) $(EXTRALIBS) + +compare_reg: compare_reg.o $(LEPTLIB) + $(CC) -o compare_reg compare_reg.o $(ALL_LIBS) $(EXTRALIBS) + +compfilter_reg: compfilter_reg.o $(LEPTLIB) + $(CC) -o compfilter_reg compfilter_reg.o $(ALL_LIBS) $(EXTRALIBS) + +conncomp_reg: conncomp_reg.o $(LEPTLIB) + $(CC) -o conncomp_reg conncomp_reg.o $(ALL_LIBS) $(EXTRALIBS) + +conversion_reg: conversion_reg.o $(LEPTLIB) + $(CC) -o conversion_reg conversion_reg.o $(ALL_LIBS) $(EXTRALIBS) + +convolve_reg: convolve_reg.o $(LEPTLIB) + $(CC) -o convolve_reg convolve_reg.o $(ALL_LIBS) $(EXTRALIBS) + +crop_reg: crop_reg.o $(LEPTLIB) + $(CC) -o crop_reg crop_reg.o $(ALL_LIBS) $(EXTRALIBS) + +dewarp_reg: dewarp_reg.o $(LEPTLIB) + $(CC) -o dewarp_reg dewarp_reg.o $(ALL_LIBS) $(EXTRALIBS) + +distance_reg: distance_reg.o $(LEPTLIB) + $(CC) -o distance_reg distance_reg.o $(ALL_LIBS) $(EXTRALIBS) + +dither_reg: dither_reg.o $(LEPTLIB) + $(CC) -o dither_reg dither_reg.o $(ALL_LIBS) $(EXTRALIBS) + +dna_reg: dna_reg.o $(LEPTLIB) + $(CC) -o dna_reg dna_reg.o $(ALL_LIBS) $(EXTRALIBS) + +dwamorph1_reg: dwamorph1_reg.o dwalinear.3.o dwalinearlow.3.o $(LEPTLIB) + $(CC) -o dwamorph1_reg dwamorph1_reg.o dwalinear.3.o dwalinearlow.3.o $(ALL_LIBS) $(EXTRALIBS) + +dwamorph2_reg: dwamorph2_reg.o dwalinear.3.o dwalinearlow.3.o $(LEPTLIB) + $(CC) -o dwamorph2_reg dwamorph2_reg.o dwalinear.3.o dwalinearlow.3.o $(ALL_LIBS) $(EXTRALIBS) + +edge_reg: edge_reg.o $(LEPTLIB) + $(CC) -o edge_reg edge_reg.o $(ALL_LIBS) $(EXTRALIBS) + +encoding_reg: encoding_reg.o $(LEPTLIB) + $(CC) -o encoding_reg encoding_reg.o $(ALL_LIBS) $(EXTRALIBS) + +enhance_reg: enhance_reg.o $(LEPTLIB) + $(CC) -o enhance_reg enhance_reg.o $(ALL_LIBS) $(EXTRALIBS) + +equal_reg: equal_reg.o $(LEPTLIB) + $(CC) -o equal_reg equal_reg.o $(ALL_LIBS) $(EXTRALIBS) + +expand_reg: expand_reg.o $(LEPTLIB) + $(CC) -o expand_reg expand_reg.o $(ALL_LIBS) $(EXTRALIBS) + +extrema_reg: extrema_reg.o $(LEPTLIB) + $(CC) -o extrema_reg extrema_reg.o $(ALL_LIBS) $(EXTRALIBS) + +falsecolor_reg: falsecolor_reg.o $(LEPTLIB) + $(CC) -o falsecolor_reg falsecolor_reg.o $(ALL_LIBS) $(EXTRALIBS) + +fhmtauto_reg: fhmtauto_reg.o $(LEPTLIB) + $(CC) -o fhmtauto_reg fhmtauto_reg.o $(ALL_LIBS) $(EXTRALIBS) + +files_reg: files_reg.o $(LEPTLIB) + $(CC) -o files_reg files_reg.o $(ALL_LIBS) $(EXTRALIBS) + +findcorners_reg: findcorners_reg.o $(LEPTLIB) + $(CC) -o findcorners_reg findcorners_reg.o $(ALL_LIBS) $(EXTRALIBS) + +findpattern_reg: findpattern_reg.o $(LEPTLIB) + $(CC) -o findpattern_reg findpattern_reg.o $(ALL_LIBS) $(EXTRALIBS) + +flipdetect_reg: flipdetect_reg.o $(LEPTLIB) + $(CC) -o flipdetect_reg flipdetect_reg.o $(ALL_LIBS) $(EXTRALIBS) + +fmorphauto_reg: fmorphauto_reg.o $(LEPTLIB) + $(CC) -o fmorphauto_reg fmorphauto_reg.o $(ALL_LIBS) $(EXTRALIBS) + +fpix1_reg: fpix1_reg.o $(LEPTLIB) + $(CC) -o fpix1_reg fpix1_reg.o $(ALL_LIBS) $(EXTRALIBS) + +fpix2_reg: fpix2_reg.o $(LEPTLIB) + $(CC) -o fpix2_reg fpix2_reg.o $(ALL_LIBS) $(EXTRALIBS) + +genfonts_reg: genfonts_reg.o $(LEPTLIB) + $(CC) -o genfonts_reg genfonts_reg.o $(ALL_LIBS) $(EXTRALIBS) + +gifio_reg: gifio_reg.o $(LEPTLIB) + $(CC) -o gifio_reg gifio_reg.o $(ALL_LIBS) $(EXTRALIBS) + +grayfill_reg: grayfill_reg.o $(LEPTLIB) + $(CC) -o grayfill_reg grayfill_reg.o $(ALL_LIBS) $(EXTRALIBS) + +graymorph1_reg: graymorph1_reg.o $(LEPTLIB) + $(CC) -o graymorph1_reg graymorph1_reg.o $(ALL_LIBS) $(EXTRALIBS) + +graymorph2_reg: graymorph2_reg.o $(LEPTLIB) + $(CC) -o graymorph2_reg graymorph2_reg.o $(ALL_LIBS) $(EXTRALIBS) + +grayquant_reg: grayquant_reg.o $(LEPTLIB) + $(CC) -o grayquant_reg grayquant_reg.o $(ALL_LIBS) $(EXTRALIBS) + +hardlight_reg: hardlight_reg.o $(LEPTLIB) + $(CC) -o hardlight_reg hardlight_reg.o $(ALL_LIBS) $(EXTRALIBS) + +hash_reg: hash_reg.o $(LEPTLIB) + $(CC) -o hash_reg hash_reg.o $(ALL_LIBS) $(EXTRALIBS) + +heap_reg: heap_reg.o $(LEPTLIB) + $(CC) -o heap_reg heap_reg.o $(ALL_LIBS) $(EXTRALIBS) + +insert_reg: insert_reg.o $(LEPTLIB) + $(CC) -o insert_reg insert_reg.o $(ALL_LIBS) $(EXTRALIBS) + +ioformats_reg: ioformats_reg.o $(LEPTLIB) + $(CC) -o ioformats_reg ioformats_reg.o $(ALL_LIBS) $(EXTRALIBS) + +iomisc_reg: iomisc_reg.o $(LEPTLIB) + $(CC) -o iomisc_reg iomisc_reg.o $(ALL_LIBS) $(EXTRALIBS) + +italic_reg: italic_reg.o $(LEPTLIB) + $(CC) -o italic_reg italic_reg.o $(ALL_LIBS) $(EXTRALIBS) + +jbclass_reg: jbclass_reg.o $(LEPTLIB) + $(CC) -o jbclass_reg jbclass_reg.o $(ALL_LIBS) $(EXTRALIBS) + +jp2kio_reg: jp2kio_reg.o $(LEPTLIB) + $(CC) -o jp2kio_reg jp2kio_reg.o $(ALL_LIBS) $(EXTRALIBS) + +jpegio_reg: jpegio_reg.o $(LEPTLIB) + $(CC) -o jpegio_reg jpegio_reg.o $(ALL_LIBS) $(EXTRALIBS) + +kernel_reg: kernel_reg.o $(LEPTLIB) + $(CC) -o kernel_reg kernel_reg.o $(ALL_LIBS) $(EXTRALIBS) + +label_reg: label_reg.o $(LEPTLIB) + $(CC) -o label_reg label_reg.o $(ALL_LIBS) $(EXTRALIBS) + +lineremoval_reg: lineremoval_reg.o $(LEPTLIB) + $(CC) -o lineremoval_reg lineremoval_reg.o $(ALL_LIBS) $(EXTRALIBS) + +locminmax_reg: locminmax_reg.o $(LEPTLIB) + $(CC) -o locminmax_reg locminmax_reg.o $(ALL_LIBS) $(EXTRALIBS) + +logicops_reg: logicops_reg.o $(LEPTLIB) + $(CC) -o logicops_reg logicops_reg.o $(ALL_LIBS) $(EXTRALIBS) + +lowsat_reg: lowsat_reg.o $(LEPTLIB) + $(CC) -o lowsat_reg lowsat_reg.o $(ALL_LIBS) $(EXTRALIBS) + +lowaccess_reg: lowaccess_reg.o $(LEPTLIB) + $(CC) -o lowaccess_reg lowaccess_reg.o $(ALL_LIBS) $(EXTRALIBS) + +maze_reg: maze_reg.o $(LEPTLIB) + $(CC) -o maze_reg maze_reg.o $(ALL_LIBS) $(EXTRALIBS) + +morphseq_reg: morphseq_reg.o $(LEPTLIB) + $(CC) -o morphseq_reg morphseq_reg.o $(ALL_LIBS) $(EXTRALIBS) + +mtiff_reg: mtiff_reg.o $(LEPTLIB) + $(CC) -o mtiff_reg mtiff_reg.o $(ALL_LIBS) $(EXTRALIBS) + +multitype_reg: multitype_reg.o $(LEPTLIB) + $(CC) -o multitype_reg multitype_reg.o $(ALL_LIBS) $(EXTRALIBS) + +nearline_reg: nearline_reg.o $(LEPTLIB) + $(CC) -o nearline_reg nearline_reg.o $(ALL_LIBS) $(EXTRALIBS) + +newspaper_reg: newspaper_reg.o $(LEPTLIB) + $(CC) -o newspaper_reg newspaper_reg.o $(ALL_LIBS) $(EXTRALIBS) + +numa1_reg: numa1_reg.o $(LEPTLIB) + $(CC) -o numa1_reg numa1_reg.o $(ALL_LIBS) $(EXTRALIBS) + +numa2_reg: numa2_reg.o $(LEPTLIB) + $(CC) -o numa2_reg numa2_reg.o $(ALL_LIBS) $(EXTRALIBS) + +numa3_reg: numa3_reg.o $(LEPTLIB) + $(CC) -o numa3_reg numa3_reg.o $(ALL_LIBS) $(EXTRALIBS) + +overlap_reg: overlap_reg.o $(LEPTLIB) + $(CC) -o overlap_reg overlap_reg.o $(ALL_LIBS) $(EXTRALIBS) + +pageseg_reg: pageseg_reg.o $(LEPTLIB) + $(CC) -o pageseg_reg pageseg_reg.o $(ALL_LIBS) $(EXTRALIBS) + +paint_reg: paint_reg.o $(LEPTLIB) + $(CC) -o paint_reg paint_reg.o $(ALL_LIBS) $(EXTRALIBS) + +paintmask_reg: paintmask_reg.o $(LEPTLIB) + $(CC) -o paintmask_reg paintmask_reg.o $(ALL_LIBS) $(EXTRALIBS) + +pdfio1_reg: pdfio1_reg.o $(LEPTLIB) + $(CC) -o pdfio1_reg pdfio1_reg.o $(ALL_LIBS) $(EXTRALIBS) + +pdfio2_reg: pdfio2_reg.o $(LEPTLIB) + $(CC) -o pdfio2_reg pdfio2_reg.o $(ALL_LIBS) $(EXTRALIBS) + +pdfseg_reg: pdfseg_reg.o $(LEPTLIB) + $(CC) -o pdfseg_reg pdfseg_reg.o $(ALL_LIBS) $(EXTRALIBS) + +pixa1_reg: pixa1_reg.o $(LEPTLIB) + $(CC) -o pixa1_reg pixa1_reg.o $(ALL_LIBS) $(EXTRALIBS) + +pixa2_reg: pixa2_reg.o $(LEPTLIB) + $(CC) -o pixa2_reg pixa2_reg.o $(ALL_LIBS) $(EXTRALIBS) + +pixadisp_reg: pixadisp_reg.o $(LEPTLIB) + $(CC) -o pixadisp_reg pixadisp_reg.o $(ALL_LIBS) $(EXTRALIBS) + +pixalloc_reg: pixalloc_reg.o $(LEPTLIB) + $(CC) -o pixalloc_reg pixalloc_reg.o $(ALL_LIBS) $(EXTRALIBS) + +pixcomp_reg: pixcomp_reg.o $(LEPTLIB) + $(CC) -o pixcomp_reg pixcomp_reg.o $(ALL_LIBS) $(EXTRALIBS) + +pixmem_reg: pixmem_reg.o $(LEPTLIB) + $(CC) -o pixmem_reg pixmem_reg.o $(ALL_LIBS) $(EXTRALIBS) + +pixserial_reg: pixserial_reg.o $(LEPTLIB) + $(CC) -o pixserial_reg pixserial_reg.o $(ALL_LIBS) $(EXTRALIBS) + +pixtile_reg: pixtile_reg.o $(LEPTLIB) + $(CC) -o pixtile_reg pixtile_reg.o $(ALL_LIBS) $(EXTRALIBS) + +pngio_reg: pngio_reg.o $(LEPTLIB) + $(CC) -o pngio_reg pngio_reg.o $(ALL_LIBS) $(EXTRALIBS) + +pnmio_reg: pnmio_reg.o $(LEPTLIB) + $(CC) -o pnmio_reg pnmio_reg.o $(ALL_LIBS) $(EXTRALIBS) + +projection_reg: projection_reg.o $(LEPTLIB) + $(CC) -o projection_reg projection_reg.o $(ALL_LIBS) $(EXTRALIBS) + +projective_reg: projective_reg.o $(LEPTLIB) + $(CC) -o projective_reg projective_reg.o $(ALL_LIBS) $(EXTRALIBS) + +psio_reg: psio_reg.o $(LEPTLIB) + $(CC) -o psio_reg psio_reg.o $(ALL_LIBS) $(EXTRALIBS) + +psioseg_reg: psioseg_reg.o $(LEPTLIB) + $(CC) -o psioseg_reg psioseg_reg.o $(ALL_LIBS) $(EXTRALIBS) + +pta_reg: pta_reg.o $(LEPTLIB) + $(CC) -o pta_reg pta_reg.o $(ALL_LIBS) $(EXTRALIBS) + +ptra1_reg: ptra1_reg.o $(LEPTLIB) + $(CC) -o ptra1_reg ptra1_reg.o $(ALL_LIBS) $(EXTRALIBS) + +ptra2_reg: ptra2_reg.o $(LEPTLIB) + $(CC) -o ptra2_reg ptra2_reg.o $(ALL_LIBS) $(EXTRALIBS) + +quadtree_reg: quadtree_reg.o $(LEPTLIB) + $(CC) -o quadtree_reg quadtree_reg.o $(ALL_LIBS) $(EXTRALIBS) + +rank_reg: rank_reg.o $(LEPTLIB) + $(CC) -o rank_reg rank_reg.o $(ALL_LIBS) $(EXTRALIBS) + +rankbin_reg: rankbin_reg.o $(LEPTLIB) + $(CC) -o rankbin_reg rankbin_reg.o $(ALL_LIBS) $(EXTRALIBS) + +rankhisto_reg: rankhisto_reg.o $(LEPTLIB) + $(CC) -o rankhisto_reg rankhisto_reg.o $(ALL_LIBS) $(EXTRALIBS) + +rasterop_reg: rasterop_reg.o $(LEPTLIB) + $(CC) -o rasterop_reg rasterop_reg.o $(ALL_LIBS) $(EXTRALIBS) + +rasteropip_reg: rasteropip_reg.o $(LEPTLIB) + $(CC) -o rasteropip_reg rasteropip_reg.o $(ALL_LIBS) $(EXTRALIBS) + +rectangle_reg: rectangle_reg.o $(LEPTLIB) + $(CC) -o rectangle_reg rectangle_reg.o $(ALL_LIBS) $(EXTRALIBS) + +rotate1_reg: rotate1_reg.o $(LEPTLIB) + $(CC) -o rotate1_reg rotate1_reg.o $(ALL_LIBS) $(EXTRALIBS) + +rotate2_reg: rotate2_reg.o $(LEPTLIB) + $(CC) -o rotate2_reg rotate2_reg.o $(ALL_LIBS) $(EXTRALIBS) + +rotateorth_reg: rotateorth_reg.o $(LEPTLIB) + $(CC) -o rotateorth_reg rotateorth_reg.o $(ALL_LIBS) $(EXTRALIBS) + +scale_reg: scale_reg.o $(LEPTLIB) + $(CC) -o scale_reg scale_reg.o $(ALL_LIBS) $(EXTRALIBS) + +seedspread_reg: seedspread_reg.o $(LEPTLIB) + $(CC) -o seedspread_reg seedspread_reg.o $(ALL_LIBS) $(EXTRALIBS) + +selio_reg: selio_reg.o $(LEPTLIB) + $(CC) -o selio_reg selio_reg.o $(ALL_LIBS) $(EXTRALIBS) + +shear1_reg: shear1_reg.o $(LEPTLIB) + $(CC) -o shear1_reg shear1_reg.o $(ALL_LIBS) $(EXTRALIBS) + +shear2_reg: shear2_reg.o $(LEPTLIB) + $(CC) -o shear2_reg shear2_reg.o $(ALL_LIBS) $(EXTRALIBS) + +skew_reg: skew_reg.o $(LEPTLIB) + $(CC) -o skew_reg skew_reg.o $(ALL_LIBS) $(EXTRALIBS) + +smallpix_reg: smallpix_reg.o $(LEPTLIB) + $(CC) -o smallpix_reg smallpix_reg.o $(ALL_LIBS) $(EXTRALIBS) + +smoothedge_reg: smoothedge_reg.o $(LEPTLIB) + $(CC) -o smoothedge_reg smoothedge_reg.o $(ALL_LIBS) $(EXTRALIBS) + +speckle_reg: speckle_reg.o $(LEPTLIB) + $(CC) -o speckle_reg speckle_reg.o $(ALL_LIBS) $(EXTRALIBS) + +splitcomp_reg: splitcomp_reg.o $(LEPTLIB) + $(CC) -o splitcomp_reg splitcomp_reg.o $(ALL_LIBS) $(EXTRALIBS) + +string_reg: string_reg.o $(LEPTLIB) + $(CC) -o string_reg string_reg.o $(ALL_LIBS) $(EXTRALIBS) + +subpixel_reg: subpixel_reg.o $(LEPTLIB) + $(CC) -o subpixel_reg subpixel_reg.o $(ALL_LIBS) $(EXTRALIBS) + +texturefill_reg: texturefill_reg.o $(LEPTLIB) + $(CC) -o texturefill_reg texturefill_reg.o $(ALL_LIBS) $(EXTRALIBS) + +threshnorm_reg: threshnorm_reg.o $(LEPTLIB) + $(CC) -o threshnorm_reg threshnorm_reg.o $(ALL_LIBS) $(EXTRALIBS) + +translate_reg: translate_reg.o $(LEPTLIB) + $(CC) -o translate_reg translate_reg.o $(ALL_LIBS) $(EXTRALIBS) + +warper_reg: warper_reg.o $(LEPTLIB) + $(CC) -o warper_reg warper_reg.o $(ALL_LIBS) $(EXTRALIBS) + +watershed_reg: watershed_reg.o $(LEPTLIB) + $(CC) -o watershed_reg watershed_reg.o $(ALL_LIBS) $(EXTRALIBS) + +webpanimio_reg: webpanimio_reg.o $(LEPTLIB) + $(CC) -o webpanimio_reg webpanimio_reg.o $(ALL_LIBS) $(EXTRALIBS) + +webpio_reg: webpio_reg.o $(LEPTLIB) + $(CC) -o webpio_reg webpio_reg.o $(ALL_LIBS) $(EXTRALIBS) + +wordboxes_reg: wordboxes_reg.o $(LEPTLIB) + $(CC) -o wordboxes_reg wordboxes_reg.o $(ALL_LIBS) $(EXTRALIBS) + +writetext_reg: writetext_reg.o $(LEPTLIB) + $(CC) -o writetext_reg writetext_reg.o $(ALL_LIBS) $(EXTRALIBS) + +xformbox_reg: xformbox_reg.o $(LEPTLIB) + $(CC) -o xformbox_reg xformbox_reg.o $(ALL_LIBS) $(EXTRALIBS) + +adaptmap_dark: adaptmap_dark.o $(LEPTLIB) + $(CC) -o adaptmap_dark adaptmap_dark.o $(ALL_LIBS) $(EXTRALIBS) + +arabic_lines: arabic_lines.o $(LEPTLIB) + $(CC) -o arabic_lines arabic_lines.o $(ALL_LIBS) $(EXTRALIBS) + +arithtest: arithtest.o $(LEPTLIB) + $(CC) -o arithtest arithtest.o $(ALL_LIBS) $(EXTRALIBS) + +autogentest1: autogentest1.o $(LEPTLIB) + $(CC) -o autogentest1 autogentest1.o $(ALL_LIBS) $(EXTRALIBS) + +autogentest2: autogentest2.o autogen.137.o $(LEPTLIB) + $(CC) -o autogentest2 autogentest2.o autogen.137.o $(ALL_LIBS) $(EXTRALIBS) + +barcodetest: barcodetest.o $(LEPTLIB) + $(CC) -o barcodetest barcodetest.o $(ALL_LIBS) $(EXTRALIBS) + +binarizefiles: binarizefiles.o $(LEPTLIB) + $(CC) -o binarizefiles binarizefiles.o $(ALL_LIBS) $(EXTRALIBS) + +binarize_set: binarize_set.o $(LEPTLIB) + $(CC) -o binarize_set binarize_set.o $(ALL_LIBS) $(EXTRALIBS) + +bincompare: bincompare.o $(LEPTLIB) + $(CC) -o bincompare bincompare.o $(ALL_LIBS) $(EXTRALIBS) + +blendcmaptest: blendcmaptest.o $(LEPTLIB) + $(CC) -o blendcmaptest blendcmaptest.o $(ALL_LIBS) $(EXTRALIBS) + +buffertest: buffertest.o $(LEPTLIB) + $(CC) -o buffertest buffertest.o $(ALL_LIBS) $(EXTRALIBS) + +ccbordtest: ccbordtest.o $(LEPTLIB) + $(CC) -o ccbordtest ccbordtest.o $(ALL_LIBS) $(EXTRALIBS) + +cctest1: cctest1.o $(LEPTLIB) + $(CC) -o cctest1 cctest1.o $(ALL_LIBS) $(EXTRALIBS) + +cleanpdf: cleanpdf.o $(LEPTLIB) + $(CC) -o cleanpdf cleanpdf.o $(ALL_LIBS) $(EXTRALIBS) + +colorsegtest: colorsegtest.o $(LEPTLIB) + $(CC) -o colorsegtest colorsegtest.o $(ALL_LIBS) $(EXTRALIBS) + +comparepages: comparepages.o $(LEPTLIB) + $(CC) -o comparepages comparepages.o $(ALL_LIBS) $(EXTRALIBS) + +comparepixa: comparepixa.o $(LEPTLIB) + $(CC) -o comparepixa comparepixa.o $(ALL_LIBS) $(EXTRALIBS) + +comparetest: comparetest.o $(LEPTLIB) + $(CC) -o comparetest comparetest.o $(ALL_LIBS) $(EXTRALIBS) + +concatpdf: concatpdf.o $(LEPTLIB) + $(CC) -o concatpdf concatpdf.o $(ALL_LIBS) $(EXTRALIBS) + +contrasttest: contrasttest.o $(LEPTLIB) + $(CC) -o contrasttest contrasttest.o $(ALL_LIBS) $(EXTRALIBS) + +convertfilestopdf: convertfilestopdf.o $(LEPTLIB) + $(CC) -o convertfilestopdf convertfilestopdf.o $(ALL_LIBS) $(EXTRALIBS) + +convertfilestops: convertfilestops.o $(LEPTLIB) + $(CC) -o convertfilestops convertfilestops.o $(ALL_LIBS) $(EXTRALIBS) + +convertformat: convertformat.o $(LEPTLIB) + $(CC) -o convertformat convertformat.o $(ALL_LIBS) $(EXTRALIBS) + +convertsegfilestopdf: convertsegfilestopdf.o $(LEPTLIB) + $(CC) -o convertsegfilestopdf convertsegfilestopdf.o $(ALL_LIBS) $(EXTRALIBS) + +convertsegfilestops: convertsegfilestops.o $(LEPTLIB) + $(CC) -o convertsegfilestops convertsegfilestops.o $(ALL_LIBS) $(EXTRALIBS) + +converttogray: converttogray.o $(LEPTLIB) + $(CC) -o converttogray converttogray.o $(ALL_LIBS) $(EXTRALIBS) + +converttopdf: converttopdf.o $(LEPTLIB) + $(CC) -o converttopdf converttopdf.o $(ALL_LIBS) $(EXTRALIBS) + +converttops: converttops.o $(LEPTLIB) + $(CC) -o converttops converttops.o $(ALL_LIBS) $(EXTRALIBS) + +cornertest: cornertest.o $(LEPTLIB) + $(CC) -o cornertest cornertest.o $(ALL_LIBS) $(EXTRALIBS) + +corrupttest: corrupttest.o $(LEPTLIB) + $(CC) -o corrupttest corrupttest.o $(ALL_LIBS) $(EXTRALIBS) + +croptext: croptext.o $(LEPTLIB) + $(CC) -o croptext croptext.o $(ALL_LIBS) $(EXTRALIBS) + +deskew_it: deskew_it.o $(LEPTLIB) + $(CC) -o deskew_it deskew_it.o $(ALL_LIBS) $(EXTRALIBS) + +dewarprules: dewarprules.o $(LEPTLIB) + $(CC) -o dewarprules dewarprules.o $(ALL_LIBS) $(EXTRALIBS) + +dewarptest1: dewarptest1.o $(LEPTLIB) + $(CC) -o dewarptest1 dewarptest1.o $(ALL_LIBS) $(EXTRALIBS) + +dewarptest2: dewarptest2.o $(LEPTLIB) + $(CC) -o dewarptest2 dewarptest2.o $(ALL_LIBS) $(EXTRALIBS) + +dewarptest3: dewarptest3.o $(LEPTLIB) + $(CC) -o dewarptest3 dewarptest3.o $(ALL_LIBS) $(EXTRALIBS) + +dewarptest4: dewarptest4.o $(LEPTLIB) + $(CC) -o dewarptest4 dewarptest4.o $(ALL_LIBS) $(EXTRALIBS) + +dewarptest5: dewarptest5.o $(LEPTLIB) + $(CC) -o dewarptest5 dewarptest5.o $(ALL_LIBS) $(EXTRALIBS) + +digitprep1: digitprep1.o $(LEPTLIB) + $(CC) -o digitprep1 digitprep1.o $(ALL_LIBS) $(EXTRALIBS) + +displayboxa: displayboxa.o $(LEPTLIB) + $(CC) -o displayboxa displayboxa.o $(ALL_LIBS) $(EXTRALIBS) + +displayboxes_on_pixa: displayboxes_on_pixa.o $(LEPTLIB) + $(CC) -o displayboxes_on_pixa displayboxes_on_pixa.o $(ALL_LIBS) $(EXTRALIBS) + +displaypix: displaypix.o $(LEPTLIB) + $(CC) -o displaypix displaypix.o $(ALL_LIBS) $(EXTRALIBS) + +displaypixa: displaypixa.o $(LEPTLIB) + $(CC) -o displaypixa displaypixa.o $(ALL_LIBS) $(EXTRALIBS) + +dwalineargen: dwalineargen.o $(LEPTLIB) + $(CC) -o dwalineargen dwalineargen.o $(ALL_LIBS) $(EXTRALIBS) + +fhmtautogen: fhmtautogen.o $(LEPTLIB) + $(CC) -o fhmtautogen fhmtautogen.o $(ALL_LIBS) $(EXTRALIBS) + +fileinfo: fileinfo.o $(LEPTLIB) + $(CC) -o fileinfo fileinfo.o $(ALL_LIBS) $(EXTRALIBS) + +findbinding: findbinding.o $(LEPTLIB) + $(CC) -o findbinding findbinding.o $(ALL_LIBS) $(EXTRALIBS) + +find_colorregions: find_colorregions.o $(LEPTLIB) + $(CC) -o find_colorregions find_colorregions.o $(ALL_LIBS) $(EXTRALIBS) + +findpattern1: findpattern1.o $(LEPTLIB) + $(CC) -o findpattern1 findpattern1.o $(ALL_LIBS) $(EXTRALIBS) + +findpattern2: findpattern2.o $(LEPTLIB) + $(CC) -o findpattern2 findpattern2.o $(ALL_LIBS) $(EXTRALIBS) + +findpattern3: findpattern3.o $(LEPTLIB) + $(CC) -o findpattern3 findpattern3.o $(ALL_LIBS) $(EXTRALIBS) + +fcombautogen: fcombautogen.o $(LEPTLIB) + $(CC) -o fcombautogen fcombautogen.o $(ALL_LIBS) $(EXTRALIBS) + +fmorphautogen: fmorphautogen.o $(LEPTLIB) + $(CC) -o fmorphautogen fmorphautogen.o $(ALL_LIBS) $(EXTRALIBS) + +fpixcontours: fpixcontours.o $(LEPTLIB) + $(CC) -o fpixcontours fpixcontours.o $(ALL_LIBS) $(EXTRALIBS) + +gammatest: gammatest.o $(LEPTLIB) + $(CC) -o gammatest gammatest.o $(ALL_LIBS) $(EXTRALIBS) + +graphicstest: graphicstest.o $(LEPTLIB) + $(CC) -o graphicstest graphicstest.o $(ALL_LIBS) $(EXTRALIBS) + +graymorphtest: graymorphtest.o $(LEPTLIB) + $(CC) -o graymorphtest graymorphtest.o $(ALL_LIBS) $(EXTRALIBS) + +histoduptest: histoduptest.o $(LEPTLIB) + $(CC) -o histoduptest histoduptest.o $(ALL_LIBS) $(EXTRALIBS) + +histotest: histotest.o $(LEPTLIB) + $(CC) -o histotest histotest.o $(ALL_LIBS) $(EXTRALIBS) + +htmlviewer: htmlviewer.o $(LEPTLIB) + $(CC) -o htmlviewer htmlviewer.o $(ALL_LIBS) $(EXTRALIBS) + +imagetops: imagetops.o $(LEPTLIB) + $(CC) -o imagetops imagetops.o $(ALL_LIBS) $(EXTRALIBS) + +jbcorrelation: jbcorrelation.o $(LEPTLIB) + $(CC) -o jbcorrelation jbcorrelation.o $(ALL_LIBS) $(EXTRALIBS) + +jbrankhaus: jbrankhaus.o $(LEPTLIB) + $(CC) -o jbrankhaus jbrankhaus.o $(ALL_LIBS) $(EXTRALIBS) + +jbwords: jbwords.o $(LEPTLIB) + $(CC) -o jbwords jbwords.o $(ALL_LIBS) $(EXTRALIBS) + +lightcolortest: lightcolortest.o $(LEPTLIB) + $(CC) -o lightcolortest lightcolortest.o $(ALL_LIBS) $(EXTRALIBS) + +listtest: listtest.o $(LEPTLIB) + $(CC) -o listtest listtest.o $(ALL_LIBS) $(EXTRALIBS) + +livre_adapt: livre_adapt.o $(LEPTLIB) + $(CC) -o livre_adapt livre_adapt.o $(ALL_LIBS) $(EXTRALIBS) + +livre_hmt: livre_hmt.o $(LEPTLIB) + $(CC) -o livre_hmt livre_hmt.o $(ALL_LIBS) $(EXTRALIBS) + +livre_makefigs: livre_makefigs.o $(LEPTLIB) + $(CC) -o livre_makefigs livre_makefigs.o $(ALL_LIBS) $(EXTRALIBS) + +livre_orient: livre_orient.o $(LEPTLIB) + $(CC) -o livre_orient livre_orient.o $(ALL_LIBS) $(EXTRALIBS) + +livre_pageseg: livre_pageseg.o $(LEPTLIB) + $(CC) -o livre_pageseg livre_pageseg.o $(ALL_LIBS) $(EXTRALIBS) + +livre_seedgen: livre_seedgen.o $(LEPTLIB) + $(CC) -o livre_seedgen livre_seedgen.o $(ALL_LIBS) $(EXTRALIBS) + +livre_tophat: livre_tophat.o $(LEPTLIB) + $(CC) -o livre_tophat livre_tophat.o $(ALL_LIBS) $(EXTRALIBS) + +maketile: maketile.o $(LEPTLIB) + $(CC) -o maketile maketile.o $(ALL_LIBS) $(EXTRALIBS) + +maptest: maptest.o $(LEPTLIB) + $(CC) -o maptest maptest.o $(ALL_LIBS) $(EXTRALIBS) + +messagetest: messagetest.o $(LEPTLIB) + $(CC) -o messagetest messagetest.o $(ALL_LIBS) $(EXTRALIBS) + +misctest1: misctest1.o $(LEPTLIB) + $(CC) -o misctest1 misctest1.o $(ALL_LIBS) $(EXTRALIBS) + +modifyhuesat: modifyhuesat.o $(LEPTLIB) + $(CC) -o modifyhuesat modifyhuesat.o $(ALL_LIBS) $(EXTRALIBS) + +morphtest1: morphtest1.o $(LEPTLIB) + $(CC) -o morphtest1 morphtest1.o $(ALL_LIBS) $(EXTRALIBS) + +numaranktest: numaranktest.o $(LEPTLIB) + $(CC) -o numaranktest numaranktest.o $(ALL_LIBS) $(EXTRALIBS) + +otsutest1: otsutest1.o $(LEPTLIB) + $(CC) -o otsutest1 otsutest1.o $(ALL_LIBS) $(EXTRALIBS) + +otsutest2: otsutest2.o $(LEPTLIB) + $(CC) -o otsutest2 otsutest2.o $(ALL_LIBS) $(EXTRALIBS) + +pagesegtest1: pagesegtest1.o $(LEPTLIB) + $(CC) -o pagesegtest1 pagesegtest1.o $(ALL_LIBS) $(EXTRALIBS) + +pagesegtest2: pagesegtest2.o $(LEPTLIB) + $(CC) -o pagesegtest2 pagesegtest2.o $(ALL_LIBS) $(EXTRALIBS) + +partifytest: partifytest.o $(LEPTLIB) + $(CC) -o partifytest partifytest.o $(ALL_LIBS) $(EXTRALIBS) + +partitiontest: partitiontest.o $(LEPTLIB) + $(CC) -o partitiontest partitiontest.o $(ALL_LIBS) $(EXTRALIBS) + +percolatetest: percolatetest.o $(LEPTLIB) + $(CC) -o percolatetest percolatetest.o $(ALL_LIBS) $(EXTRALIBS) + +pixaatest: pixaatest.o $(LEPTLIB) + $(CC) -o pixaatest pixaatest.o $(ALL_LIBS) $(EXTRALIBS) + +pixafileinfo: pixafileinfo.o $(LEPTLIB) + $(CC) -o pixafileinfo pixafileinfo.o $(ALL_LIBS) $(EXTRALIBS) + +plottest: plottest.o $(LEPTLIB) + $(CC) -o plottest plottest.o $(ALL_LIBS) $(EXTRALIBS) + +printimage: printimage.o $(LEPTLIB) + $(CC) -o printimage printimage.o $(ALL_LIBS) $(EXTRALIBS) + +printsplitimage: printsplitimage.o $(LEPTLIB) + $(CC) -o printsplitimage printsplitimage.o $(ALL_LIBS) $(EXTRALIBS) + +printtiff: printtiff.o $(LEPTLIB) + $(CC) -o printtiff printtiff.o $(ALL_LIBS) $(EXTRALIBS) + +rasteroptest: rasteroptest.o $(LEPTLIB) + $(CC) -o rasteroptest rasteroptest.o $(ALL_LIBS) $(EXTRALIBS) + +rbtreetest: rbtreetest.o $(LEPTLIB) + $(CC) -o rbtreetest rbtreetest.o $(ALL_LIBS) $(EXTRALIBS) + +recog_bootnum1: recog_bootnum1.o $(LEPTLIB) + $(CC) -o recog_bootnum1 recog_bootnum1.o $(ALL_LIBS) $(EXTRALIBS) + +recog_bootnum2: recog_bootnum2.o $(LEPTLIB) + $(CC) -o recog_bootnum2 recog_bootnum2.o $(ALL_LIBS) $(EXTRALIBS) + +recog_bootnum3: recog_bootnum3.o $(LEPTLIB) + $(CC) -o recog_bootnum3 recog_bootnum3.o $(ALL_LIBS) $(EXTRALIBS) + +recogsort: recogsort.o $(LEPTLIB) + $(CC) -o recogsort recogsort.o $(ALL_LIBS) $(EXTRALIBS) + +recogtest1: recogtest1.o $(LEPTLIB) + $(CC) -o recogtest1 recogtest1.o $(ALL_LIBS) $(EXTRALIBS) + +recogtest2: recogtest2.o $(LEPTLIB) + $(CC) -o recogtest2 recogtest2.o $(ALL_LIBS) $(EXTRALIBS) + +recogtest3: recogtest3.o $(LEPTLIB) + $(CC) -o recogtest3 recogtest3.o $(ALL_LIBS) $(EXTRALIBS) + +recogtest4: recogtest4.o $(LEPTLIB) + $(CC) -o recogtest4 recogtest4.o $(ALL_LIBS) $(EXTRALIBS) + +recogtest5: recogtest5.o $(LEPTLIB) + $(CC) -o recogtest5 recogtest5.o $(ALL_LIBS) $(EXTRALIBS) + +recogtest6: recogtest6.o $(LEPTLIB) + $(CC) -o recogtest6 recogtest6.o $(ALL_LIBS) $(EXTRALIBS) + +recogtest7: recogtest7.o $(LEPTLIB) + $(CC) -o recogtest7 recogtest7.o $(ALL_LIBS) $(EXTRALIBS) + +reducetest: reducetest.o $(LEPTLIB) + $(CC) -o reducetest reducetest.o $(ALL_LIBS) $(EXTRALIBS) + +removecmap: removecmap.o $(LEPTLIB) + $(CC) -o removecmap removecmap.o $(ALL_LIBS) $(EXTRALIBS) + +renderfonts: renderfonts.o $(LEPTLIB) + $(CC) -o renderfonts renderfonts.o $(ALL_LIBS) $(EXTRALIBS) + +replacebytes: replacebytes.o $(LEPTLIB) + $(CC) -o replacebytes replacebytes.o $(ALL_LIBS) $(EXTRALIBS) + +rotatefastalt: rotatefastalt.o $(LEPTLIB) + $(CC) -o rotatefastalt rotatefastalt.o $(ALL_LIBS) $(EXTRALIBS) + +rotate_it: rotate_it.o $(LEPTLIB) + $(CC) -o rotate_it rotate_it.o $(ALL_LIBS) $(EXTRALIBS) + +rotateorthtest1: rotateorthtest1.o $(LEPTLIB) + $(CC) -o rotateorthtest1 rotateorthtest1.o $(ALL_LIBS) $(EXTRALIBS) + +rotatetest1: rotatetest1.o $(LEPTLIB) + $(CC) -o rotatetest1 rotatetest1.o $(ALL_LIBS) $(EXTRALIBS) + +runlengthtest: runlengthtest.o $(LEPTLIB) + $(CC) -o runlengthtest runlengthtest.o $(ALL_LIBS) $(EXTRALIBS) + +scaleandtile: scaleandtile.o $(LEPTLIB) + $(CC) -o scaleandtile scaleandtile.o $(ALL_LIBS) $(EXTRALIBS) + +scale_it: scale_it.o $(LEPTLIB) + $(CC) -o scale_it scale_it.o $(ALL_LIBS) $(EXTRALIBS) + +scaletest1: scaletest1.o $(LEPTLIB) + $(CC) -o scaletest1 scaletest1.o $(ALL_LIBS) $(EXTRALIBS) + +scaletest2: scaletest2.o $(LEPTLIB) + $(CC) -o scaletest2 scaletest2.o $(ALL_LIBS) $(EXTRALIBS) + +seedfilltest: seedfilltest.o $(LEPTLIB) + $(CC) -o seedfilltest seedfilltest.o $(ALL_LIBS) $(EXTRALIBS) + +settest: settest.o $(LEPTLIB) + $(CC) -o settest settest.o $(ALL_LIBS) $(EXTRALIBS) + +sharptest: sharptest.o $(LEPTLIB) + $(CC) -o sharptest sharptest.o $(ALL_LIBS) $(EXTRALIBS) + +sheartest: sheartest.o $(LEPTLIB) + $(CC) -o sheartest sheartest.o $(ALL_LIBS) $(EXTRALIBS) + +showedges: showedges.o $(LEPTLIB) + $(CC) -o showedges showedges.o $(ALL_LIBS) $(EXTRALIBS) + +skewtest: skewtest.o $(LEPTLIB) + $(CC) -o skewtest skewtest.o $(ALL_LIBS) $(EXTRALIBS) + +sorttest: sorttest.o $(LEPTLIB) + $(CC) -o sorttest sorttest.o $(ALL_LIBS) $(EXTRALIBS) + +splitimage2pdf: splitimage2pdf.o $(LEPTLIB) + $(CC) -o splitimage2pdf splitimage2pdf.o $(ALL_LIBS) $(EXTRALIBS) + +sudokutest: sudokutest.o $(LEPTLIB) + $(CC) -o sudokutest sudokutest.o $(ALL_LIBS) $(EXTRALIBS) + +textorient: textorient.o $(LEPTLIB) + $(CC) -o textorient textorient.o $(ALL_LIBS) $(EXTRALIBS) + +tiffpdftest: tiffpdftest.o $(LEPTLIB) + $(CC) -o tiffpdftest tiffpdftest.o $(ALL_LIBS) $(EXTRALIBS) + +trctest: trctest.o $(LEPTLIB) + $(CC) -o trctest trctest.o $(ALL_LIBS) $(EXTRALIBS) + +underlinetest: underlinetest.o $(LEPTLIB) + $(CC) -o underlinetest underlinetest.o $(ALL_LIBS) $(EXTRALIBS) + +warpertest: warpertest.o $(LEPTLIB) + $(CC) -o warpertest warpertest.o $(ALL_LIBS) $(EXTRALIBS) + +wordsinorder: wordsinorder.o $(LEPTLIB) + $(CC) -o wordsinorder wordsinorder.o $(ALL_LIBS) $(EXTRALIBS) + +writemtiff: writemtiff.o $(LEPTLIB) + $(CC) -o writemtiff writemtiff.o $(ALL_LIBS) $(EXTRALIBS) + +xtractprotos: xtractprotos.o $(LEPTLIB) + $(CC) -o xtractprotos xtractprotos.o $(ALL_LIBS) + cp xtractprotos ../src + +yuvtest: yuvtest.o $(LEPTLIB) + $(CC) -o yuvtest yuvtest.o $(ALL_LIBS) $(EXTRALIBS) + +########################################################### + +clean: + -@ for file in $(SRC:%.c=%) ; do \ + rm -f $$file; \ + done ; + -@ for file in $(SRC:%.c=%.o) ; do \ + rm -f $$file; \ + done ; + -@ for file in $(SRC2:%.c=%.o) ; do \ + rm -f $$file; \ + done ; + +########################################################### + +install: + mkdir -p $(DESTDIR)/usr/bin/leptonica + -@ for file in $(SRC:%.c=%) ; do \ + install $$file $(DESTDIR)/usr/bin/leptonica; \ + done ; + +########################################################### + +depend: + $(BIN)/makedepend -DNO_PROTOS $(CPPFLAGS) $(SRC) + +dependprotos: + $(BIN)/makedepend $(CPPFLAGS) $(SRC) + +# DO NOT DELETE THIS LINE -- make depend depends on it. diff --git a/leptonica/prog/maketile.c b/leptonica/prog/maketile.c new file mode 100644 index 00000000..8aaa7484 --- /dev/null +++ b/leptonica/prog/maketile.c @@ -0,0 +1,118 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * maketile.c + * + * Generates a single image tiling of all images of a specific depth + * in a directory. The tiled images are scaled by a specified + * isotropic scale factor. One can also specify the approximate width + * of the output image file, and the background color that is between + * the tiled images. + * + * Input: dirin: directory that has image files + * depth (use 32 for RGB) + * scale factor + * width (approx. width of output tiled image) + * background (0 for white, 1 for black) + * fileout: output tiled image file + * + * Note: this program is Unix only; it will not compile under cygwin. + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include <string.h> +#include "allheaders.h" + +int main(int argc, + char **argv) +{ +char *dirin, *fileout, *fname, *fullname; +l_int32 depth, width, background, i, nfiles; +l_float32 scale; +SARRAY *safiles; +PIX *pix, *pixt, *pixd; +PIXA *pixa; +static char mainName[] = "maketile"; + + if (argc != 7) + return ERROR_INT( + "Syntax: maketile dirin depth scale width background fileout", + mainName, 1); + dirin = argv[1]; + depth = atoi(argv[2]); + scale = atof(argv[3]); + width = atoi(argv[4]); + background = atoi(argv[5]); + fileout = argv[6]; + setLeptDebugOK(1); + + /* capture the filenames in the input directory; ignore directories */ + if ((safiles = getFilenamesInDirectory(dirin)) == NULL) + return ERROR_INT("safiles not made", mainName, 1); + + /* capture images with the requisite depth */ + nfiles = sarrayGetCount(safiles); + pixa = pixaCreate(nfiles); + for (i = 0; i < nfiles; i++) { + fname = sarrayGetString(safiles, i, L_NOCOPY); + fullname = genPathname(dirin, fname); + pix = pixRead(fullname); + lept_free(fullname); + if (!pix) + continue; + if (pixGetDepth(pix) != depth) { + pixDestroy(&pix); + continue; + } + if (pixGetHeight(pix) > 5000) { + lept_stderr("%s too tall\n", fname); + continue; + } + pixt = pixScale(pix, scale, scale); + pixaAddPix(pixa, pixt, L_INSERT); + pixDestroy(&pix); +/* lept_stderr("%d..", i); */ + } + lept_stderr("\n"); + + /* tile them */ + pixd = pixaDisplayTiled(pixa, width, background, 15); + + if (depth < 8) + pixWrite(fileout, pixd, IFF_PNG); + else + pixWrite(fileout, pixd, IFF_JFIF_JPEG); + + pixaDestroy(&pixa); + pixDestroy(&pixd); + sarrayDestroy(&safiles); + return 0; +} + diff --git a/leptonica/prog/map.057.jpg b/leptonica/prog/map.057.jpg Binary files differnew file mode 100644 index 00000000..7681e0c4 --- /dev/null +++ b/leptonica/prog/map.057.jpg diff --git a/leptonica/prog/map1.jpg b/leptonica/prog/map1.jpg Binary files differnew file mode 100644 index 00000000..09fb85ec --- /dev/null +++ b/leptonica/prog/map1.jpg diff --git a/leptonica/prog/maptest.c b/leptonica/prog/maptest.c new file mode 100644 index 00000000..b1ac52df --- /dev/null +++ b/leptonica/prog/maptest.c @@ -0,0 +1,426 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * maptest.c + * + * Tests map function for RGB (uint32) keys and count (int32) values. + * The underlying rbtree takes 64 bit keys and values, so it also works + * transparently with 32 bit keys and values. + * + * We take a colormapped image and use the map to accumulate a + * histogram of the colors, using the 32-bit rgb value as the key. + * The value is the number of pixels with that color that we have seen. + * + * Also: + * * test the forward and backward iterators on the map + * * build an inverse colormap table using a map. + * * test RGB histogram and counting functions in pix4.c + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + +static L_AMAP *BuildMapHistogram(PIX *pix, l_int32 factor, l_int32 print); +static void DisplayMapHistogram(L_AMAP *m, PIXCMAP *cmap, + const char *rootname); +static void DisplayMapRGBHistogram(L_AMAP *m, const char *rootname); +static void TestMapIterator1(L_AMAP *m, l_int32 print); +static void TestMapIterator2(L_AMAP *m, l_int32 print); +static void TestMapIterator3(L_AMAP *m, l_int32 print); +static void TestMapIterator4(L_AMAP *m, l_int32 print); +static void TestMapIterator5(L_AMAP *m, l_int32 print); + + +l_int32 main(int argc, + char **argv) +{ +l_int32 i, n, w, h, ncolors; +l_uint32 val32; +L_AMAP *m; +NUMA *na; +PIX *pix; +PIXCMAP *cmap; +RB_TYPE key, value; +RB_TYPE *pval; + + setLeptDebugOK(1); + lept_mkdir("lept/map"); + + pix = pixRead("weasel8.240c.png"); + pixGetDimensions(pix, &w, &h, NULL); + lept_stderr("Image area in pixels: %d\n", w * h); + cmap = pixGetColormap(pix); + + /* Build the histogram, stored in a map. Then compute + * and display the histogram as the number of pixels vs + * the colormap index */ + m = BuildMapHistogram(pix, 1, FALSE); + TestMapIterator1(m, FALSE); + TestMapIterator2(m, FALSE); + DisplayMapHistogram(m, cmap, "/tmp/lept/map/map1"); + l_amapDestroy(&m); + + /* Ditto, but just with a few pixels */ + m = BuildMapHistogram(pix, 14, TRUE); + DisplayMapHistogram(m, cmap, "/tmp/lept/map/map2"); + l_amapDestroy(&m); + + /* Do in-order tranversals, using the iterators */ + m = BuildMapHistogram(pix, 7, FALSE); + TestMapIterator1(m, TRUE); + TestMapIterator2(m, TRUE); + l_amapDestroy(&m); + + /* Do in-order tranversals, with iterators and destroying the map */ + m = BuildMapHistogram(pix, 7, FALSE); + TestMapIterator3(m, TRUE); + lept_free(m); + m = BuildMapHistogram(pix, 7, FALSE); + TestMapIterator4(m, TRUE); + lept_free(m); + + /* Do in-order tranversals, with iterators and reversing the map */ + m = BuildMapHistogram(pix, 7, FALSE); + TestMapIterator5(m, TRUE); + l_amapDestroy(&m); + + /* Build a histogram the old-fashioned way */ + na = pixGetCmapHistogram(pix, 1); + numaWrite("/tmp/lept/map/map2.na", na); + gplotSimple1(na, GPLOT_PNG, "/tmp/lept/map/map3", NULL); + numaDestroy(&na); + + /* Build a separate map from (rgb) --> colormap index ... */ + m = l_amapCreate(L_UINT_TYPE); + n = pixcmapGetCount(cmap); + for (i = 0; i < n; i++) { + pixcmapGetColor32(cmap, i, &val32); + key.utype = val32; + value.itype = i; + l_amapInsert(m, key, value); + } + /* ... and test the map */ + for (i = 0; i < n; i++) { + pixcmapGetColor32(cmap, i, &val32); + key.utype = val32; + pval = l_amapFind(m, key); + if (pval && (i != pval->itype)) + lept_stderr("i = %d != val = %llx\n", i, pval->itype); + } + l_amapDestroy(&m); + pixDestroy(&pix); + + /* Build and display a real RGB histogram */ + pix = pixRead("wyom.jpg"); + m = pixGetColorAmapHistogram(pix, 1); + DisplayMapRGBHistogram(m, "/tmp/lept/map/map4"); + pixNumColors(pix, 1, &ncolors); + lept_stderr(" Using pixNumColors: %d\n", ncolors); + pixCountRGBColors(pix, 1, &ncolors); + lept_stderr(" Using pixCountRGBColors: %d\n", ncolors); + l_amapDestroy(&m); + pixDestroy(&pix); + + return 0; +} + +static L_AMAP * +BuildMapHistogram(PIX *pix, + l_int32 factor, + l_int32 print) +{ +l_int32 i, j, w, h, wpl, val; +l_uint32 val32; +l_uint32 *data, *line; +L_AMAP *m; +PIXCMAP *cmap; +RB_TYPE key, value; +RB_TYPE *pval; + + lept_stderr("\n --------------- Begin building map --------------\n"); + m = l_amapCreate(L_UINT_TYPE); + data = pixGetData(pix); + wpl = pixGetWpl(pix); + cmap = pixGetColormap(pix); + pixGetDimensions(pix, &w, &h, NULL); + for (i = 0; i < h; i += factor) { + line = data + i * wpl; + for (j = 0; j < w; j += factor) { + val = GET_DATA_BYTE(line, j); + pixcmapGetColor32(cmap, val, &val32); + key.utype = val32; + pval = l_amapFind(m, key); + if (!pval) + value.itype = 1; + else + value.itype = 1 + pval->itype; + if (print) + lept_stderr("key = %llx, val = %lld\n", key.utype, value.itype); + l_amapInsert(m, key, value); + } + } + lept_stderr("Size: %d\n", l_amapSize(m)); + if (print) + l_rbtreePrint(stderr, m); + lept_stderr(" ----------- End Building map -----------------\n"); + + return m; +} + + +static void +DisplayMapHistogram(L_AMAP *m, + PIXCMAP *cmap, + const char *rootname) +{ +char buf[128]; +l_int32 i, n, ival; +l_uint32 val32; +NUMA *na; +RB_TYPE key; +RB_TYPE *pval; + + n = pixcmapGetCount(cmap); + na = numaCreate(n); + for (i = 0; i < n; i++) { + pixcmapGetColor32(cmap, i, &val32); + key.utype = val32; + pval = l_amapFind(m, key); + if (pval) { + ival = pval->itype; + numaAddNumber(na, ival); + } + } + gplotSimple1(na, GPLOT_PNG, rootname, NULL); + snprintf(buf, sizeof(buf), "%s.png", rootname); + l_fileDisplay(buf, 700, 0, 1.0); + numaDestroy(&na); + return; +} + +static void +DisplayMapRGBHistogram(L_AMAP *m, + const char *rootname) +{ +char buf[128]; +l_int32 ncolors, npix, ival, maxn, maxn2; +l_uint32 maxcolor; +L_AMAP_NODE *n; +NUMA *na; + + lept_stderr("\n --------------- Display RGB histogram ------------\n"); + na = numaCreate(0); + ncolors = npix = 0; + maxn = 0; + maxcolor = 0; + n = l_amapGetFirst(m); + while (n) { + ncolors++; + ival = n->value.itype; + if (ival > maxn) { + maxn = ival; + maxcolor = n->key.utype; + } + numaAddNumber(na, ival); + npix += ival; + n = l_amapGetNext(n); + } + lept_stderr(" Num colors = %d, Num pixels = %d\n", ncolors, npix); + lept_stderr(" Color %x has count %d\n", maxcolor, maxn); + maxn2 = amapGetCountForColor(m, maxcolor); + if (maxn != maxn2) + lept_stderr(" Error: maxn2 = %d; not equal to %d\n", maxn, maxn2); + gplotSimple1(na, GPLOT_PNG, rootname, NULL); + snprintf(buf, sizeof(buf), "%s.png", rootname); + l_fileDisplay(buf, 1400, 0, 1.0); + numaDestroy(&na); + return; +} + +static void +TestMapIterator1(L_AMAP *m, + l_int32 print) /* forward iterator; fixed tree */ +{ +l_int32 count, npix, ival; +l_uint32 ukey; +L_AMAP_NODE *n; + + n = l_amapGetFirst(m); + count = 0; + npix = 0; + lept_stderr("\n ---------- Begin forward iter listing -----------\n"); + while (n) { + count++; + ukey = n->key.utype; + ival = n->value.itype; + npix += ival; + if (print) + lept_stderr("key = %x, val = %d\n", ukey, ival); + n = l_amapGetNext(n); + } + lept_stderr("Count from iterator: %d\n", count); + lept_stderr("Number of pixels: %d\n", npix); + lept_stderr(" ------------ End forward iter listing -----------\n"); + return; +} + +static void +TestMapIterator2(L_AMAP *m, + l_int32 print) /* reverse iterator; fixed tree */ +{ +l_int32 count, npix, ival; +l_uint32 ukey; +L_AMAP_NODE *n; + + n = l_amapGetLast(m); + count = 0; + npix = 0; + lept_stderr("\n ---------- Begin reverse iter listing -----------\n"); + while (n) { + count++; + ukey = n->key.utype; + ival = n->value.itype; + npix += ival; + if (print) + lept_stderr("key = %x, val = %d\n", ukey, ival); + n = l_amapGetPrev(n); + } + lept_stderr("Count from iterator: %d\n", count); + lept_stderr("Number of pixels: %d\n", npix); + lept_stderr(" ------------ End reverse iter listing -----------\n"); + return; +} + +static void +TestMapIterator3(L_AMAP *m, + l_int32 print) /* forward iterator; delete the tree */ +{ +l_int32 count, npix, ival; +l_uint32 ukey; +L_AMAP_NODE *n, *nn; + + n = l_amapGetFirst(m); + count = 0; + npix = 0; + lept_stderr("\n ------ Begin forward iter; delete tree ---------\n"); + while (n) { + nn = l_amapGetNext(n); + count++; + ukey = n->key.utype; + ival = n->value.itype; + npix += ival; + if (print) + lept_stderr("key = %x, val = %d\n", ukey, ival); + l_amapDelete(m, n->key); + n = nn; + } + lept_stderr("Count from iterator: %d\n", count); + lept_stderr("Number of pixels: %d\n", npix); + lept_stderr(" ------ End forward iter; delete tree ---------\n"); + return; +} + +static void +TestMapIterator4(L_AMAP *m, + l_int32 print) /* reverse iterator; delete the tree */ +{ +l_int32 count, npix, ival; +l_uint32 ukey; +L_AMAP_NODE *n, *np; + + n = l_amapGetLast(m); + count = 0; + npix = 0; + lept_stderr("\n ------- Begin reverse iter; delete tree --------\n"); + while (n) { + np = l_amapGetPrev(n); + count++; + ukey = n->key.utype; + ival = n->value.itype; + npix += ival; + if (print) + lept_stderr("key = %x, val = %d\n", ukey, ival); + l_amapDelete(m, n->key); + n = np; + } + lept_stderr("Count from iterator: %d\n", count); + lept_stderr("Number of pixels: %d\n", npix); + lept_stderr(" ------- End reverse iter; delete tree --------\n"); + return; +} + +static void +TestMapIterator5(L_AMAP *m, + l_int32 print) /* reverse iterator; rebuild the tree */ +{ +l_int32 count, npix, ival; +l_uint32 ukey; +L_AMAP *m2; +L_AMAP_NODE *n, *np; + + m2 = l_amapCreate(L_UINT_TYPE); + n = l_amapGetLast(m); + count = npix = 0; + lept_stderr("\n ------- Begin reverse iter; rebuild tree --------\n"); + while (n) { + np = l_amapGetPrev(n); + count++; + ukey = n->key.utype; + ival = n->value.itype; + l_amapInsert(m2, n->key, n->value); + npix += ival; + if (print) + lept_stderr("key = %x, val = %d\n", ukey, ival); + l_amapDelete(m, n->key); + n = np; + } + m->root = m2->root; + lept_free(m2); + lept_stderr("Count from iterator: %d\n", count); + lept_stderr("Number of pixels: %d\n", npix); + count = npix = 0; + n = l_amapGetLast(m); + while (n) { + np = l_amapGetPrev(n); + count++; + ukey = n->key.utype; + ival = n->value.itype; + npix += ival; + if (print) + lept_stderr("key = %x, val = %d\n", ukey, ival); + n = np; + } + lept_stderr("Count from iterator: %d\n", count); + lept_stderr("Number of pixels: %d\n", npix); + lept_stderr(" ------- End reverse iter; rebuild tree --------\n"); + return; +} + + diff --git a/leptonica/prog/marge.jpg b/leptonica/prog/marge.jpg Binary files differnew file mode 100644 index 00000000..2a14582e --- /dev/null +++ b/leptonica/prog/marge.jpg diff --git a/leptonica/prog/maze_reg.c b/leptonica/prog/maze_reg.c new file mode 100644 index 00000000..9bbda980 --- /dev/null +++ b/leptonica/prog/maze_reg.c @@ -0,0 +1,110 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * maze_reg.c + * + * Tests the functions in maze.c: binary and gray maze search + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include <string.h> +#include "allheaders.h" + +#define NPATHS 6 +static const l_int32 x0[NPATHS] = {42, 73, 73, 42, 324, 471}; +static const l_int32 y0[NPATHS] = {117, 319, 319, 117, 170, 201}; +static const l_int32 x1[NPATHS] = {419, 419, 233, 326, 418, 128}; +static const l_int32 y1[NPATHS] = {383, 383, 112, 168, 371, 341}; + +int main(int argc, + char **argv) +{ +l_int32 i, w, h; +PIX *pixm, *pixs, *pixg, *pixt, *pixd; +PIXA *pixa; +PIXAA *paa; +PTA *pta; +PTAA *ptaa; +L_REGPARAMS *rp; + + if (regTestSetup(argc, argv, &rp)) + return 1; + + paa = pixaaCreate(2); + + /* ---------------- Shortest path in binary maze ---------------- */ + /* Generate the maze */ + pixa = pixaCreate(0); + pixm = generateBinaryMaze(200, 200, 20, 20, 0.65, 0.25); + pixd = pixExpandBinaryReplicate(pixm, 3, 3); + pixaAddPix(pixa, pixd, L_INSERT); + + /* Find the shortest path between two points */ + pta = pixSearchBinaryMaze(pixm, 20, 20, 170, 170, NULL); + pixt = pixDisplayPta(NULL, pixm, pta); + pixd = pixScaleBySampling(pixt, 3., 3.); + pixaAddPix(pixa, pixd, L_INSERT); + pixaaAddPixa(paa, pixa, L_INSERT); + regTestWritePixAndCheck(rp, pixd, IFF_PNG); /* 0 */ + ptaDestroy(&pta); + pixDestroy(&pixt); + pixDestroy(&pixm); + + /* ---------------- Shortest path in gray maze ---------------- */ + pixg = pixRead("test8.jpg"); + pixGetDimensions(pixg, &w, &h, NULL); + ptaa = ptaaCreate(NPATHS); + for (i = 0; i < NPATHS; i++) { + if (x0[i] >= w || x1[i] >= w || y0[i] >= h || y1[i] >= h) { + lept_stderr("path %d extends beyond image; skipping\n", i); + continue; + } + pta = pixSearchGrayMaze(pixg, x0[i], y0[i], x1[i], y1[i], NULL); + ptaaAddPta(ptaa, pta, L_INSERT); + } + + pixt = pixDisplayPtaa(pixg, ptaa); + pixd = pixScaleBySampling(pixt, 2., 2.); + pixa = pixaCreate(0); + pixaAddPix(pixa, pixd, L_INSERT); + pixaaAddPixa(paa, pixa, L_INSERT); + regTestWritePixAndCheck(rp, pixd, IFF_PNG); /* 1 */ + ptaaDestroy(&ptaa); + pixDestroy(&pixg); + pixDestroy(&pixt); + + /* Bundle it all up */ + pixd = pixaaDisplayByPixa(paa, 3, 1.0, 20, 40, 0); + regTestWritePixAndCheck(rp, pixd, IFF_PNG); /* 2 */ + pixDisplayWithTitle(pixd, 100, 100, NULL, rp->display); + pixDestroy(&pixd); + pixaaDestroy(&paa); + return regTestCleanup(rp); +} diff --git a/leptonica/prog/messagetest.c b/leptonica/prog/messagetest.c new file mode 100644 index 00000000..73133681 --- /dev/null +++ b/leptonica/prog/messagetest.c @@ -0,0 +1,181 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* Test the message severity system. */ + +/* There are three parts: + * o The first part demonstrates the message severity functionality. + * o The second part demonstrates a combination of message severity control + * and redirect of output to stderr (in this case to dev null). + * o The third part shows that the naked fprintf() is not affected by the + * callback handler, and the default handler is restored with NULL input. + * + * Notes on the message severity functionality + * -------------------------------------------- + * + * The program prints info, warning, and error messages at the initial + * run-time severity, which defaults to L_SEVERITY_INFO. Then it resets the + * severity to the value specified by an environment variable (or failing + * that, specified by one of 7 severity control variables) and prints three + * more info, warning, and error messages. + * + * Which messages actually print depend on the compile-time definitions of the + * MINIMUM_SEVERITY and DEFAULT_SEVERITY identifiers and the run-time + * definition of the LEPT_MSG_SEVERITY environment variable. For example: + * + * These commands... --> ...print these messages + * ============================== ==================================== + * $ make + * + * $ ./print --> info, warn, error, info, warn, error + * $ LEPT_MSG_SEVERITY=0 ./print --> info, warn, error, info, warn, error + * $ LEPT_MSG_SEVERITY=5 ./print --> info, warn, error, error + * $ LEPT_MSG_SEVERITY=6 ./print --> info, warn, error + * + * + * $ make clean ; make DEFINES='-D DEFAULT_SEVERITY=L_SEVERITY_WARNING' + * + * $ ./print --> warn, error, warn, error + * $ LEPT_MSG_SEVERITY=0 ./print --> warn, error, info, warn, error + * $ LEPT_MSG_SEVERITY=5 ./print --> warn, error, error + * $ LEPT_MSG_SEVERITY=6 ./print --> warn, error + * + * + * $ make clean ; make DEFINES='-D MINIMUM_SEVERITY=L_SEVERITY_WARNING' + * + * $ ./print --> warn, error, warn, error + * $ LEPT_MSG_SEVERITY=0 ./print --> warn, error, warn, error + * $ LEPT_MSG_SEVERITY=5 ./print --> warn, error, error + * $ LEPT_MSG_SEVERITY=6 ./print --> warn, error + * + * + * $ make clean ; make DEFINES='-D NO_CONSOLE_IO' + * + * $ ./print --> (no messages) + * $ LEPT_MSG_SEVERITY=0 ./print --> (no messages) + * $ LEPT_MSG_SEVERITY=5 ./print --> (no messages) + * $ LEPT_MSG_SEVERITY=6 ./print --> (no messages) + * + * Note that in the first and second cases, code is generated to print all six + * messages, while in the third and fourth cases, code is not generated to + * print info or all messages, respectively. This allows the run-time overhead + * and code space of the print statements to be removed from the library, if + * desired. + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + +void TestMessageControl(l_int32 severity); +void TestStderrRedirect(); + + /* dev null callback for stderr redirect */ +static void send_to_devnull(const char *msg) {} + +int main () +{ + /* Part 1: all output to stderr */ + lept_stderr("\nSeverity tests\n"); + TestMessageControl(L_SEVERITY_EXTERNAL); + TestMessageControl(L_SEVERITY_INFO); + TestMessageControl(L_SEVERITY_WARNING); + TestMessageControl(L_SEVERITY_ERROR); + TestMessageControl(L_SEVERITY_NONE); + + /* Part 2: test combination of severity and redirect */ + lept_stderr("\nRedirect Tests\n\n"); + setMsgSeverity(L_SEVERITY_INFO); + TestStderrRedirect(); + setMsgSeverity(L_SEVERITY_WARNING); + TestStderrRedirect(); + setMsgSeverity(L_SEVERITY_ERROR); + TestStderrRedirect(); + setMsgSeverity(L_SEVERITY_NONE); + TestStderrRedirect(); + + /* Part 3: test of naked fprintf and output with callback handler. + * All lines should print except for line 4. */ + lept_stderr("1. text\n"); + lept_stderr("2. text\n"); + leptSetStderrHandler(send_to_devnull); + lept_stderr("3. text\n"); + lept_stderr("4. text\n"); + leptSetStderrHandler(NULL); + lept_stderr("5. text\n"); + lept_stderr("6. text\n"); + + return 0; +} + +void TestMessageControl(l_int32 severity) +{ +l_int32 orig_severity; + + setMsgSeverity(DEFAULT_SEVERITY); + fputc ('\n', stderr); + + /* Print a set of messages with the default setting */ + L_INFO ("First message\n", "messagetest"); + L_WARNING ("First message\n", "messagetest"); + L_ERROR ("First message\n", "messagetest"); + + /* Set the run-time severity to the value specified by the + LEPT_MSG_SEVERITY environment variable. If the variable + is not defined, set the run-time severity to the input value */ + orig_severity = setMsgSeverity(severity); + + /* Print messages allowed by the new severity setting */ + L_INFO ("Second message\n", "messagetest"); + L_WARNING ("Second message\n", "messagetest"); + L_ERROR ("Second message\n", "messagetest"); +}; + +void TestStderrRedirect() { +PIX *pix1; + + /* Output to stderr works */ + L_INFO("test output 1 to stderr\n", "messagetest"); + L_WARNING("test output 1 to stderr\n", "messagetest"); + L_ERROR("test output 1 to stderr\n", "messagetest"); + pix1 = pixRead("doesn't_exist"); + /* There is no "test output 2" */ + leptSetStderrHandler(send_to_devnull); + L_INFO("test output 2 to stderr\n", "messagetest"); + L_WARNING("test output 2 to stderr\n", "messagetest"); + L_ERROR("test output 2 to stderr\n", "messagetest"); + pix1 = pixRead("doesn't_exist"); + leptSetStderrHandler(NULL); + /* Output is restored to stderr */ + L_INFO("test output 3 to stderr\n", "messagetest"); + L_WARNING("test output 3 to stderr\n", "messagetest"); + L_ERROR("test output 3 to stderr\n", "messagetest"); + pix1 = pixRead("doesn't_exist"); + lept_stderr("---------------------------------\n"); +} + diff --git a/leptonica/prog/minisblack.tif b/leptonica/prog/minisblack.tif Binary files differnew file mode 100644 index 00000000..1db57855 --- /dev/null +++ b/leptonica/prog/minisblack.tif diff --git a/leptonica/prog/miniswhite.tif b/leptonica/prog/miniswhite.tif Binary files differnew file mode 100644 index 00000000..46d7e4f4 --- /dev/null +++ b/leptonica/prog/miniswhite.tif diff --git a/leptonica/prog/misctest1.c b/leptonica/prog/misctest1.c new file mode 100644 index 00000000..543af538 --- /dev/null +++ b/leptonica/prog/misctest1.c @@ -0,0 +1,331 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * misctest1.c + * * Combine two grayscale images using a mask + * * Combine two binary images using a mask + * * Do a restricted seedfill + * * Colorize a grayscale image + * * Convert color to gray + * * Extract text lines + * * Plot box side locations and dimension of a boxa + * * Extract and display rank sized components + * * Extract parts of an image using a boxa + * * Display pixaa in row major order by component pixa. + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + +#define SHOW 0 + +int main(int argc, + char **argv) +{ +l_int32 w, h, bx, by, bw, bh, i, j; +BOX *box1, *box2; +BOXA *boxa1, *boxa2, *boxae, *boxao; +PIX *pixs, *pix1, *pix2, *pix3, *pixg, *pixb, *pixd, *pixc; +PIX *pixm, *pixm2, *pixd2, *pixs2; +PIXA *pixa1, *pixa2; +PIXAA *paa; +PIXCMAP *cmap, *cmapg; + + setLeptDebugOK(1); + lept_mkdir("lept/misc"); + paa = pixaaCreate(0); + + /* Combine two grayscale images using a mask */ + lept_stderr("Combine two grayscale images using a mask\n"); + pixa1 = pixaCreate(0); + pixd = pixRead("feyn.tif"); + pixs = pixRead("rabi.png"); + pixm = pixRead("pageseg2-seed.png"); + pixd2 = pixScaleToGray2(pixd); + pixs2 = pixScaleToGray2(pixs); + pixaAddPix(pixa1, pixd2, L_COPY); + pixaAddPix(pixa1, pixs2, L_INSERT); + pixaAddPix(pixa1, pixm, L_COPY); + pixCombineMaskedGeneral(pixd2, pixs2, pixm, 100, 100); + pixaAddPix(pixa1, pixd2, L_INSERT); + pixDisplayWithTitle(pixd2, 100, 100, NULL, SHOW); + pixaaAddPixa(paa, pixa1, L_INSERT); + + /* Combine two binary images using a mask */ + lept_stderr("Combine two binary images using a mask\n"); + pixa1 = pixaCreate(0); + pixm2 = pixExpandBinaryReplicate(pixm, 2, 2); + pix1 = pixCopy(NULL, pixd); + pixCombineMaskedGeneral(pixd, pixs, pixm2, 200, 200); + pixaAddPix(pixa1, pixd, L_COPY); + pixDisplayWithTitle(pixd, 700, 100, NULL, SHOW); + pixCombineMasked(pix1, pixs, pixm2); + pixaAddPix(pixa1, pix1, L_INSERT); + pixaaAddPixa(paa, pixa1, L_INSERT); + pixDestroy(&pixd); + pixDestroy(&pixs); + pixDestroy(&pixm); + pixDestroy(&pixm2); + + /* Do a restricted seedfill */ + lept_stderr("Do a restricted seedfill\n"); + pixa1 = pixaCreate(0); + pixs = pixRead("pageseg2-seed.png"); + pixm = pixRead("pageseg2-mask.png"); + pixd = pixSeedfillBinaryRestricted(NULL, pixs, pixm, 8, 50, 175); + pixaAddPix(pixa1, pixs, L_INSERT); + pixaAddPix(pixa1, pixm, L_INSERT); + pixaAddPix(pixa1, pixd, L_INSERT); + pixaaAddPixa(paa, pixa1, L_INSERT); + pix1 = pixaaDisplayByPixa(paa, 10, 0.5, 40, 40, 2); + pixWrite("/tmp/lept/misc/mos1.png", pix1, IFF_PNG); + pixDisplay(pix1, 100, 100); + pixaaDestroy(&paa); + pixDestroy(&pix1); + + /* Colorize a grayscale image */ + lept_stderr("Colorize a grayscale image\n"); + paa = pixaaCreate(0); + pixa1 = pixaCreate(0); + pixs = pixRead("lucasta.150.jpg"); + pixGetDimensions(pixs, &w, &h, NULL); + pixb = pixThresholdToBinary(pixs, 128); + boxa1 = pixConnComp(pixb, &pixa2, 8); + pixaAddPix(pixa1, pixs, L_COPY); + cmap = pixcmapGrayToColor(0x6f90c0); + pixSetColormap(pixs, cmap); + pixaAddPix(pixa1, pixs, L_COPY); + pixc = pixaDisplayRandomCmap(pixa2, w, h); + pixcmapResetColor(pixGetColormap(pixc), 0, 255, 255, 255); + pixaAddPix(pixa1, pixc, L_INSERT); + pixaaAddPixa(paa, pixa1, L_INSERT); + pixDestroy(&pixs); + pixDestroy(&pixb); + boxaDestroy(&boxa1); + pixaDestroy(&pixa2); + + /* Convert color to gray */ + lept_stderr("Convert color to gray\n"); + pixa1 = pixaCreate(0); + pixs = pixRead("weasel4.16c.png"); + pixaAddPix(pixa1, pixs, L_INSERT); + pixc = pixConvertTo32(pixs); + pix1 = pixConvertRGBToGray(pixc, 3., 7., 5.); /* bad weights */ + pixaAddPix(pixa1, pix1, L_INSERT); + pix2 = pixConvertRGBToGrayFast(pixc); + pixaAddPix(pixa1, pix2, L_INSERT); + pixg = pixCopy(NULL, pixs); + cmap = pixGetColormap(pixs); + cmapg = pixcmapColorToGray(cmap, 4., 6., 3.); + pixSetColormap(pixg, cmapg); + pixaAddPix(pixa1, pixg, L_INSERT); + pixaaAddPixa(paa, pixa1, L_INSERT); + pixDestroy(&pixc); + + pix1 = pixaaDisplayByPixa(paa, 10, 1.0, 20, 20, 0); + pixWrite("/tmp/lept/misc/mos2.png", pix1, IFF_PNG); + pixDisplay(pix1, 400, 100); + pixaaDestroy(&paa); + pixDestroy(&pix1); + + /* Extract text lines */ + lept_stderr("Extract text lines\n"); + pix1 = pixRead("feyn.tif"); + pixa1 = pixExtractTextlines(pix1, 150, 150, 0, 0, 5, 5, NULL); + boxa1 = pixaGetBoxa(pixa1, L_CLONE); + boxaWrite("/tmp/lept/misc/lines1.ba", boxa1); + pix2 = pixaDisplayRandomCmap(pixa1, 0, 0); + pixcmapResetColor(pixGetColormap(pix2), 0, 255, 255, 255); + pixDisplay(pix2, 400, 0); + pixWrite("/tmp/lept/misc/lines1.png", pix2, IFF_PNG); + boxaDestroy(&boxa1); + pixDestroy(&pix1); + pixDestroy(&pix2); + pixaDestroy(&pixa1); + + pix1 = pixRead("arabic.png"); + pixa1 = pixExtractTextlines(pix1, 150, 150, 0, 0, 5, 5, NULL); + pix2 = pixaDisplayRandomCmap(pixa1, 0, 0); + pixcmapResetColor(pixGetColormap(pix2), 0, 255, 255, 255); + pixDisplay(pix2, 400, 400); + pixWrite("/tmp/lept/misc/lines2.png", pix2, IFF_PNG); + pixDestroy(&pix1); + pixDestroy(&pix2); + pixaDestroy(&pixa1); + + pix1 = pixRead("arabic2.png"); + pixa1 = pixExtractTextlines(pix1, 150, 150, 0, 0, 5, 5, NULL); + pix2 = pixaDisplayRandomCmap(pixa1, 0, 0); + pixcmapResetColor(pixGetColormap(pix2), 0, 255, 255, 255); + pixDisplay(pix2, 400, 800); + pixWrite("/tmp/lept/misc/lines3.png", pix2, IFF_PNG); + pixDestroy(&pix1); + pixDestroy(&pix2); + pixaDestroy(&pixa1); + + /* Plot box side locations and dimensions of a boxa */ + lept_stderr("Plot box side locations and dimensions of a boxa\n"); + pixa1 = pixaCreate(0); + boxa1 = boxaRead("boxa2.ba"); + boxaSplitEvenOdd(boxa1, 0, &boxae, &boxao); + boxaPlotSides(boxae, "1-sides-even", NULL, NULL, NULL, NULL, &pix1); + pixaAddPix(pixa1, pix1, L_INSERT); + boxaPlotSides(boxao, "1-sides-odd", NULL, NULL, NULL, NULL, &pix1); + pixaAddPix(pixa1, pix1, L_INSERT); + boxaPlotSizes(boxae, "1-sizes-even", NULL, NULL, &pix1); + pixaAddPix(pixa1, pix1, L_INSERT); + boxaPlotSizes(boxao, "1-sizes-odd", NULL, NULL, &pix1); + pixaAddPix(pixa1, pix1, L_INSERT); + boxaDestroy(&boxae); + boxaDestroy(&boxao); + boxaDestroy(&boxa1); + boxa1 = boxaRead("boxa3.ba"); + boxaSplitEvenOdd(boxa1, 0, &boxae, &boxao); + boxaPlotSides(boxae, "2-sides-even", NULL, NULL, NULL, NULL, &pix1); + pixaAddPix(pixa1, pix1, L_INSERT); + boxaPlotSides(boxao, "2-sides-odd", NULL, NULL, NULL, NULL, &pix1); + pixaAddPix(pixa1, pix1, L_INSERT); + boxaPlotSizes(boxae, "2-sizes-even", NULL, NULL, &pix1); + pixaAddPix(pixa1, pix1, L_INSERT); + boxaPlotSizes(boxao, "2-sizes-odd", NULL, NULL, &pix1); + pixaAddPix(pixa1, pix1, L_INSERT); + boxaDestroy(&boxae); + boxaDestroy(&boxao); + boxaDestroy(&boxa1); + pix1 = pixaDisplayTiledInRows(pixa1, 32, 1500, 1.0, 0, 30, 2); + pixWrite("/tmp/lept/misc/boxaplots.png", pix1, IFF_PNG); + pixDisplay(pix1, 800, 0); + pixDestroy(&pix1); + pixaDestroy(&pixa1); + + /* Extract and display rank sized components */ + lept_stderr("Extract and display rank sized components\n"); + pixs = pixRead("rabi-tiny.png"); + pixa1 = pixaCreate(0); + for (i = 1; i <= 5; i++) { + pixaAddPix(pixa1, pixs, L_COPY); + pixGetDimensions(pixs, &w, &h, NULL); + pixd = pixCreate(w, h, 32); + pixSetAll(pixd); + for (j = 0; j < 6; j++) { + pix1 = pixSelectComponentBySize(pixs, j, i, 8, &box1); + pix2 = pixConvertTo32(pix1); + boxGetGeometry(box1, &bx, &by, &bw, &bh); + pixRasterop(pixd, bx, by, bw, bh, PIX_SRC, pix2, 0, 0); + box2 = boxAdjustSides(NULL, box1, -2, 2, -2, 2); + pixRenderBoxArb(pixd, box2, 2, 255, 0, 0); + pixaAddPix(pixa1, pixd, L_COPY); + pixDestroy(&pix1); + pixDestroy(&pix2); + boxDestroy(&box1); + boxDestroy(&box2); + } + pixDestroy(&pixd); + } + pix3 = pixaDisplayTiledAndScaled(pixa1, 32, 300, 7, 0, 30, 2); + pixWrite("/tmp/lept/misc/comps.png", pix3, IFF_PNG); + pixDisplay(pix3, 600, 300); + pixaDestroy(&pixa1); + pixDestroy(&pixs); + pixDestroy(&pix3); + + /* Extract parts of an image using a boxa */ + lept_stderr("Extract parts of an image using a boxa\n"); + pix1 = pixRead("feyn-fract.tif"); + boxa1 = pixConnCompBB(pix1, 4); + boxa2 = boxaSelectBySize(boxa1, 0, 28, L_SELECT_HEIGHT, L_SELECT_IF_GT, + NULL), + pix2 = pixCopyWithBoxa(pix1, boxa2, L_SET_WHITE); + pixWrite("/tmp/lept/misc/tallcomps.png", pix2, IFF_PNG); + pixDisplay(pix2, 600, 600); + pixDestroy(&pix1); + pixDestroy(&pix2); + boxaDestroy(&boxa1); + boxaDestroy(&boxa2); + + /* Display pixaa in row major order by component pixa. */ + lept_stderr("Display pixaa in row major order by component pixa\n"); + pix1 = pixRead("char.tif"); + paa = pixaaCreate(100); + for (i = 0; i < 50; i++) { + pixa1 = pixaCreate(100); + for (j = 0; j < 125 - 2 * i; j++) + pixaAddPix(pixa1, pix1, L_COPY); + pixaaAddPixa(paa, pixa1, L_INSERT); + } + pix2 = pixaaDisplayByPixa(paa, 50, 1.0, 10, 5, 0); + pixWrite("/tmp/lept/misc/display.png", pix2, IFF_PNG); + pixDisplay(pix2, 100, 100); + pixaaDestroy(&paa); + pixDestroy(&pix1); + pixDestroy(&pix2); + + /* Test the set and clear block functions in cmapped pix */ + lept_stderr("Test the set and clear block functions in cmapped pix\n"); + lept_stderr("******************************************************\n"); + lept_stderr("* Testing error checking: ignore two reported errors *\n"); + pix1 = pixRead("weasel4.11c.png"); + pixa1 = pixaCreate(0); + pix2 = pixCopy(NULL, pix1); + pixClearAll(pix2); + pixaAddPix(pixa1, pix2, L_INSERT); + pix2 = pixCopy(NULL, pix1); + pixSetAll(pix2); /* error */ + pixaAddPix(pixa1, pix2, L_INSERT); + pix2 = pixCopy(NULL, pix1); + pixSetAllArbitrary(pix2, 4); + pixaAddPix(pixa1, pix2, L_INSERT); + pix2 = pixCopy(NULL, pix1); + pixSetAllArbitrary(pix2, 11); /* warning */ + pixaAddPix(pixa1, pix2, L_INSERT); + + box1 = boxCreate(20, 20, 30, 30); + pix2 = pixCopy(NULL, pix1); + pixClearInRect(pix2, box1); + pixaAddPix(pixa1, pix2, L_INSERT); + pix2 = pixCopy(NULL, pix1); + pixSetInRect(pix2, box1); /* error */ + pixaAddPix(pixa1, pix2, L_INSERT); + pix2 = pixCopy(NULL, pix1); + pixSetInRectArbitrary(pix2, box1, 4); + pixaAddPix(pixa1, pix2, L_INSERT); + pix2 = pixCopy(NULL, pix1); + pixSetInRectArbitrary(pix2, box1, 12); /* warning */ + pixaAddPix(pixa1, pix2, L_INSERT); + lept_stderr("******************************************************\n"); + + pix3 = pixaDisplayTiledInColumns(pixa1, 10, 1.0, 15, 2); + pixWrite("/tmp/lept/misc/setting.png", pix3, IFF_PNG); + pixDisplay(pix3, 500, 100); + pixDestroy(&pix1); + pixDestroy(&pix3); + pixaDestroy(&pixa1); + return 0; +} diff --git a/leptonica/prog/modifyhuesat.c b/leptonica/prog/modifyhuesat.c new file mode 100644 index 00000000..b1f25592 --- /dev/null +++ b/leptonica/prog/modifyhuesat.c @@ -0,0 +1,107 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * modifyhuesat.c + * + * modifyhuesat filein nhue dhue nsat dsat fileout + * + * where nhue and nsat are odd + * + * This gives a rectangle of nhue x nsat output images, + * where the center image is not modified. + * + * Example: modifyhuesat test24.jpg 5 0.2 5 0.2 /tmp/junkout.jpg + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + +int main(int argc, + char **argv) +{ +char *filein, *fileout; +l_int32 i, j, w, d, nhue, nsat, tilewidth; +l_float32 scale, dhue, dsat, delhue, delsat; +PIX *pixs, *pixt1, *pixt2, *pixd; +PIXA *pixa; +static char mainName[] = "modifyhuesat"; + + if (argc != 7) + return ERROR_INT( + " Syntax: modifyhuesat filein nhue dhue nsat dsat fileout", + mainName, 1); + filein = argv[1]; + nhue = atoi(argv[2]); + dhue = atof(argv[3]); + nsat = atoi(argv[4]); + dsat = atof(argv[5]); + fileout = argv[6]; + if (nhue % 2 == 0) { + nhue++; + lept_stderr("nhue must be odd; raised to %d\n", nhue); + } + if (nsat % 2 == 0) { + nsat++; + lept_stderr("nsat must be odd; raised to %d\n", nsat); + } + + setLeptDebugOK(1); + if ((pixt1 = pixRead(filein)) == NULL) + return ERROR_INT("pixt1 not read", mainName, 1); + pixGetDimensions(pixt1, &w, NULL, NULL); + scale = 250.0 / (l_float32)w; + pixt2 = pixScale(pixt1, scale, scale); + pixs = pixConvertTo32(pixt2); + pixDestroy(&pixt1); + pixDestroy(&pixt2); + + pixGetDimensions(pixs, &w, NULL, &d); + pixa = pixaCreate(nhue * nsat); + for (i = 0; i < nsat; i++) { + delsat = (i - nsat / 2.0) * dsat; + pixt1 = pixModifySaturation(NULL, pixs, delsat); + for (j = 0; j < nhue; j++) { + delhue = (j - nhue / 2.0) * dhue; + pixt2 = pixModifyHue(NULL, pixt1, delhue); + pixaAddPix(pixa, pixt2, L_INSERT); + } + pixDestroy(&pixt1); + } + + tilewidth = L_MIN(w, 1500 / nsat); + pixd = pixaDisplayTiledAndScaled(pixa, d, tilewidth, nsat, 0, 25, 3); + pixWrite(fileout, pixd, IFF_JFIF_JPEG); + + pixDestroy(&pixs); + pixDestroy(&pixd); + pixaDestroy(&pixa); + return 0; +} + diff --git a/leptonica/prog/morphseq_reg.c b/leptonica/prog/morphseq_reg.c new file mode 100644 index 00000000..00389cce --- /dev/null +++ b/leptonica/prog/morphseq_reg.c @@ -0,0 +1,121 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * morphseq_reg.c + * + * Simple regression test for binary morph sequence (interpreter), + * showing display mode and rejection of invalid sequence components. + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + +#define SEQUENCE1 "O1.3 + C3.1 + R22 + D2.2 + X4" +#define SEQUENCE2 "O2.13 + C5.23 + R22 + X4" +#define SEQUENCE3 "e3.3 + d3.3 + tw5.5" +#define SEQUENCE4 "O3.3 + C3.3" +#define SEQUENCE5 "O5.5 + C5.5" +#define BAD_SEQUENCE "O1.+D8 + E2.4 + e.4 + r25 + R + R.5 + X + x5 + y7.3" + +#define DISPLAY_SEPARATION 0 /* use 250 to get images displayed */ + +int main(int argc, + char **argv) +{ +PIX *pixs, *pixg, *pixc, *pixd; +static char mainName[] = "morphseq_reg"; + + if (argc != 1) + return ERROR_INT(" Syntax: morphseq_reg", mainName, 1); + + setLeptDebugOK(1); + lept_mkdir("lept"); + pixs = pixRead("feyn.tif"); + + /* 1 bpp */ + pixd = pixMorphSequence(pixs, SEQUENCE1, -1); + pixDestroy(&pixd); + pixd = pixMorphSequence(pixs, SEQUENCE1, DISPLAY_SEPARATION); + pixWrite("/tmp/lept/morphseq1.png", pixd, IFF_PNG); + pixDestroy(&pixd); + + pixd = pixMorphCompSequence(pixs, SEQUENCE2, -2); + pixDestroy(&pixd); + pixd = pixMorphCompSequence(pixs, SEQUENCE2, DISPLAY_SEPARATION); + pixWrite("/tmp/lept/morphseq2.png", pixd, IFF_PNG); + pixDestroy(&pixd); + + lept_stderr("\n ------------------ Error messages -----------------\n"); + lept_stderr(" ------------ DWA v23 Sel doesn't exist -----------\n"); + lept_stderr(" ---------------------------------------------------\n"); + pixd = pixMorphSequenceDwa(pixs, SEQUENCE2, -3); + pixDestroy(&pixd); + pixd = pixMorphSequenceDwa(pixs, SEQUENCE2, DISPLAY_SEPARATION); + pixWrite("/tmp/lept/morphseq3.png", pixd, IFF_PNG); + pixDestroy(&pixd); + + pixd = pixMorphCompSequenceDwa(pixs, SEQUENCE2, -4); + pixDestroy(&pixd); + pixd = pixMorphCompSequenceDwa(pixs, SEQUENCE2, DISPLAY_SEPARATION); + pixWrite("/tmp/lept/morphseq4.png", pixd, IFF_PNG); + pixDestroy(&pixd); + + /* 8 bpp */ + pixg = pixScaleToGray(pixs, 0.25); + pixd = pixGrayMorphSequence(pixg, SEQUENCE3, -5, 150); + pixDestroy(&pixd); + pixd = pixGrayMorphSequence(pixg, SEQUENCE3, DISPLAY_SEPARATION, 150); + pixWrite("/tmp/lept/morphseq5.png", pixd, IFF_PNG); + pixDestroy(&pixd); + + pixd = pixGrayMorphSequence(pixg, SEQUENCE4, -6, 300); + pixWrite("/tmp/lept/morphseq6.png", pixd, IFF_PNG); + pixDestroy(&pixd); + + /* 32 bpp */ + pixc = pixRead("wyom.jpg"); + pixd = pixColorMorphSequence(pixc, SEQUENCE5, -7, 150); + pixDestroy(&pixd); + pixd = pixColorMorphSequence(pixc, SEQUENCE5, DISPLAY_SEPARATION, 450); + pixWrite("/tmp/lept/morphseq7.png", pixd, IFF_PNG); + pixDestroy(&pixc); + pixDestroy(&pixd); + + /* Syntax error handling */ + lept_stderr("\n ----------------- Error messages ------------------\n"); + lept_stderr(" ---------------- Invalid sequence -----------------\n"); + lept_stderr(" ---------------------------------------------------\n"); + pixd = pixMorphSequence(pixs, BAD_SEQUENCE, 50); /* fails; returns null */ + pixd = pixGrayMorphSequence(pixg, BAD_SEQUENCE, 50, 0); /* this fails */ + + pixDestroy(&pixg); + pixDestroy(&pixs); + return 0; +} diff --git a/leptonica/prog/morphtemplate1.txt b/leptonica/prog/morphtemplate1.txt new file mode 100644 index 00000000..5a769fd5 --- /dev/null +++ b/leptonica/prog/morphtemplate1.txt @@ -0,0 +1,224 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/*! + * Top-level fast binary morphology with auto-generated sels + * +--- * PIX *pixMorphDwa_*() +--- * PIX *pixFMorphopGen_*() + */ + +#include <string.h> +#include "allheaders.h" + +--- This file is: morphtemplate1.txt +--- +--- We need to include these prototypes: +--- PIX *pixMorphDwa_*(PIX *pixd, PIX *pixs, l_int32 operation, +--- char *selname); +--- PIX *pixFMorphopGen_*(PIX *pixd, PIX *pixs, l_int32 operation, +--- char *selname); +--- l_int32 fmorphopgen_low_*(l_uint32 *datad, l_int32 w, l_int32 h, +--- l_int32 wpld, l_uint32 *datas, +--- l_int32 wpls, l_int32 index); +--- +--- We need to input two static globals here: +--- static l_int32 NUM_SELS_GENERATED = <some number>; +--- static char SEL_NAMES[][80] = {"<string1>", "<string2>", ...}; + +/*! +--- * \brief pixMorphDwa_*() + * + * \param[in] pixd usual 3 choices: null, == pixs, != pixs + * \param[in] pixs 1 bpp + * \param[in] operation L_MORPH_DILATE, L_MORPH_ERODE, + * L_MORPH_OPEN, L_MORPH_CLOSE + * \param[in] sel name + * \return pixd + * + * <pre> + * Notes: + * (1) This simply adds a border, calls the appropriate + * pixFMorphopGen_*(), and removes the border. + * See the notes for that function. + * (2) The size of the border depends on the operation + * and the boundary conditions. + * </pre> + */ +PIX * +--- pixMorphDwa_*(PIX *pixd, + PIX *pixs, + l_int32 operation, + char *selname) +{ +l_int32 bordercolor, bordersize; +PIX *pixt1, *pixt2, *pixt3; + +--- PROCNAME("pixMorpDwa_*"); + + if (!pixs) + return (PIX *)ERROR_PTR("pixs not defined", procName, pixd); + if (pixGetDepth(pixs) != 1) + return (PIX *)ERROR_PTR("pixs must be 1 bpp", procName, pixd); + + /* Set the border size */ + bordercolor = getMorphBorderPixelColor(L_MORPH_ERODE, 1); + bordersize = 32; + if (bordercolor == 0 && operation == L_MORPH_CLOSE) + bordersize += 32; + + pixt1 = pixAddBorder(pixs, bordersize, 0); +--- pixt2 = pixFMorphopGen_*(NULL, pixt1, operation, selname); + pixt3 = pixRemoveBorder(pixt2, bordersize); + pixDestroy(&pixt1); + pixDestroy(&pixt2); + + if (!pixd) + return pixt3; + + pixCopy(pixd, pixt3); + pixDestroy(&pixt3); + return pixd; +} + + +/*! +--- * \brief pixFMorphopGen_*() + * + * \param[in] pixd usual 3 choices: null, == pixs, != pixs + * \param[in] pixs 1 bpp + * \param[in] operation L_MORPH_DILATE, L_MORPH_ERODE, + * L_MORPH_OPEN, L_MORPH_CLOSE + * \param[in] sel name + * \return pixd + * + * <pre> + * Notes: + * (1) This is a dwa operation, and the Sels must be limited in + * size to not more than 31 pixels about the origin. + * (2) A border of appropriate size (32 pixels, or 64 pixels + * for safe closing with asymmetric b.c.) must be added before + * this function is called. + * (3) This handles all required setting of the border pixels + * before erosion and dilation. + * (4) The closing operation is safe; no pixels can be removed + * near the boundary. + * </pre> + */ +PIX * +--- pixFMorphopGen_*(PIX *pixd, + PIX *pixs, + l_int32 operation, + char *selname) +{ +l_int32 i, index, found, w, h, wpls, wpld, bordercolor, erodeop, borderop; +l_uint32 *datad, *datas, *datat; +PIX *pixt; + +--- PROCNAME("pixFMorphopGen_*"); + + if (!pixs) + return (PIX *)ERROR_PTR("pixs not defined", procName, pixd); + if (pixGetDepth(pixs) != 1) + return (PIX *)ERROR_PTR("pixs must be 1 bpp", procName, pixd); + + /* Get boundary colors to use */ + bordercolor = getMorphBorderPixelColor(L_MORPH_ERODE, 1); + if (bordercolor == 1) + erodeop = PIX_SET; + else + erodeop = PIX_CLR; + + found = FALSE; + for (i = 0; i < NUM_SELS_GENERATED; i++) { + if (strcmp(selname, SEL_NAMES[i]) == 0) { + found = TRUE; + index = 2 * i; + break; + } + } + if (found == FALSE) + return (PIX *)ERROR_PTR("sel index not found", procName, pixd); + + if (!pixd) { + if ((pixd = pixCreateTemplate(pixs)) == NULL) + return (PIX *)ERROR_PTR("pixd not made", procName, NULL); + } + else /* for in-place or pre-allocated */ + pixResizeImageData(pixd, pixs); + wpls = pixGetWpl(pixs); + wpld = pixGetWpl(pixd); + + /* The images must be surrounded, in advance, with a border of + * size 32 pixels (or 64, for closing), that we'll read from. + * Fabricate a "proper" image as the subimage within the 32 + * pixel border, having the following parameters: */ + w = pixGetWidth(pixs) - 64; + h = pixGetHeight(pixs) - 64; + datas = pixGetData(pixs) + 32 * wpls + 1; + datad = pixGetData(pixd) + 32 * wpld + 1; + + if (operation == L_MORPH_DILATE || operation == L_MORPH_ERODE) { + borderop = PIX_CLR; + if (operation == L_MORPH_ERODE) { + borderop = erodeop; + index++; + } + if (pixd == pixs) { /* in-place; generate a temp image */ + if ((pixt = pixCopy(NULL, pixs)) == NULL) + return (PIX *)ERROR_PTR("pixt not made", procName, pixd); + datat = pixGetData(pixt) + 32 * wpls + 1; + pixSetOrClearBorder(pixt, 32, 32, 32, 32, borderop); +--- fmorphopgen_low_*(datad, w, h, wpld, datat, wpls, index); + pixDestroy(&pixt); + } + else { /* not in-place */ + pixSetOrClearBorder(pixs, 32, 32, 32, 32, borderop); +--- fmorphopgen_low_*(datad, w, h, wpld, datas, wpls, index); + } + } + else { /* opening or closing; generate a temp image */ + if ((pixt = pixCreateTemplate(pixs)) == NULL) + return (PIX *)ERROR_PTR("pixt not made", procName, pixd); + datat = pixGetData(pixt) + 32 * wpls + 1; + if (operation == L_MORPH_OPEN) { + pixSetOrClearBorder(pixs, 32, 32, 32, 32, erodeop); +--- fmorphopgen_low_*(datat, w, h, wpls, datas, wpls, index + 1); + pixSetOrClearBorder(pixt, 32, 32, 32, 32, PIX_CLR); +--- fmorphopgen_low_*(datad, w, h, wpld, datat, wpls, index); + } + else { /* closing */ + pixSetOrClearBorder(pixs, 32, 32, 32, 32, PIX_CLR); +--- fmorphopgen_low_*(datat, w, h, wpls, datas, wpls, index); + pixSetOrClearBorder(pixt, 32, 32, 32, 32, erodeop); +--- fmorphopgen_low_*(datad, w, h, wpld, datat, wpls, index + 1); + } + pixDestroy(&pixt); + } + + return pixd; +} + diff --git a/leptonica/prog/morphtemplate2.txt b/leptonica/prog/morphtemplate2.txt new file mode 100644 index 00000000..6b876774 --- /dev/null +++ b/leptonica/prog/morphtemplate2.txt @@ -0,0 +1,104 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/*! + * Low-level fast binary morphology with auto-generated sels + * + * Dispatcher: +--- * l_int32 fmorphopgen_low_*() + * + * Static Low-level: +--- * void fdilate_*_*() +--- * void ferode_*_*() + */ + +#include "allheaders.h" + +--- This file is: morphtemplate2.txt +--- +--- insert static protos here ... + + +/*---------------------------------------------------------------------* + * Fast morph dispatcher * + *---------------------------------------------------------------------*/ +/*! +--- * fmorphopgen_low_*() + * + * a dispatcher to appropriate low-level code + */ +l_int32 +--- fmorphopgen_low_*(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls, + l_int32 index) +{ + + switch (index) + { +--- insert dispatcher code for fdilate* and ferode* routines ... + } + + return 0; +} + + +/*--------------------------------------------------------------------------* + * Low-level auto-generated static routines * + *--------------------------------------------------------------------------*/ +/* + * N.B. In all the low-level routines, the part of the image + * that is accessed has been clipped by 32 pixels on + * all four sides. This is done in the higher level + * code by redefining w and h smaller and by moving the + * start-of-image pointers up to the beginning of this + * interior rectangle. + */ +--- static void fdilate_*_*(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; +--- declare wplsN args as necessary ... + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { +--- insert barrel-op code for *dptr here ... + } + } +} + diff --git a/leptonica/prog/morphtest1.c b/leptonica/prog/morphtest1.c new file mode 100644 index 00000000..7c61f4c0 --- /dev/null +++ b/leptonica/prog/morphtest1.c @@ -0,0 +1,140 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * morphtest1.c + * + * - Timing test for rasterop-based morphological operations + * - Example repository of binary morph operations + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + +#define NTIMES 100 +#define IMAGE_SIZE 8. /* megapixels */ +#define SEL_SIZE 9 +#define BASIC_OPS 1. /* 1 for erosion/dilation; 2 for open/close */ +#define CPU_SPEED 866. /* MHz: set it for the machine you're using */ + +int main(int argc, + char **argv) +{ +l_int32 i, index; +l_float32 cputime, epo; +char *filein, *fileout; +PIX *pixs, *pixd; +SEL *sel; +SELA *sela; +static char mainName[] = "morphtest1"; + + if (argc != 3) + return ERROR_INT(" Syntax: morphtest1 filein fileout", mainName, 1); + filein = argv[1]; + fileout = argv[2]; + setLeptDebugOK(1); + + if ((pixs = pixRead(filein)) == NULL) + return ERROR_INT("pix not made", mainName, 1); + sela = selaAddBasic(NULL); + + /* ------------------------ Timing -------------------------------*/ +#if 1 + selaFindSelByName(sela, "sel_9h", &index, &sel); + selWriteStream(stderr, sel); + pixd = pixCreateTemplate(pixs); + + startTimer(); + for (i = 0; i < NTIMES; i++) { + pixDilate(pixd, pixs, sel); +/* if ((i % 10) == 0) lept_stderr("%d iters\n", i); */ + } + cputime = stopTimer(); + /* Get the elementary pixel operations/sec */ + epo = BASIC_OPS * SEL_SIZE * NTIMES * IMAGE_SIZE /(cputime * CPU_SPEED); + + lept_stderr("Time: %7.3f sec\n", cputime); + lept_stderr("Speed: %7.3f epo/cycle\n", epo); + pixWrite(fileout, pixd, IFF_PNG); + pixDestroy(&pixd); +#endif + + /* ------------------ Example operation from repository --------------*/ +#if 1 + /* Select a structuring element */ + selaFindSelByName(sela, "sel_50h", &index, &sel); + selWriteStream(stderr, sel); + + /* Do these operations. See below for other ops + * that can be substituted here. */ + pixd = pixOpen(NULL, pixs, sel); + pixXor(pixd, pixd, pixs); + pixWrite(fileout, pixd, IFF_PNG); + pixDestroy(&pixd); +#endif + + pixDestroy(&pixs); + return 0; +} + + +/* ==================================================================== */ + +/* -------------------------------------------------------------------- * + * Repository for selecting various operations * + * that might be used * + * -------------------------------------------------------------------- */ +#if 0 + pixd = pixCreateTemplate(pixs); + + pixd = pixDilate(NULL, pixs, sel); + pixd = pixErode(NULL, pixs, sel); + pixd = pixOpen(NULL, pixs, sel); + pixd = pixClose(NULL, pixs, sel); + + pixDilate(pixd, pixs, sel); + pixErode(pixd, pixs, sel); + pixOpen(pixd, pixs, sel); + pixClose(pixd, pixs, sel); + + pixAnd(pixd, pixd, pixs); + pixOr(pixd, pixd, pixs); + pixXor(pixd, pixd, pixs); + pixSubtract(pixd, pixd, pixs); + pixInvert(pixd, pixs); + + pixd = pixAnd(NULL, pixd, pixs); + pixd = pixOr(NULL, pixd, pixs); + pixd = pixXor(NULL, pixd, pixs); + pixd = pixSubtract(NULL, pixd, pixs); + pixd = pixInvert(NULL, pixs); + + pixInvert(pixs, pixs); +#endif /* 0 */ + diff --git a/leptonica/prog/mtiff_reg.c b/leptonica/prog/mtiff_reg.c new file mode 100644 index 00000000..1441b017 --- /dev/null +++ b/leptonica/prog/mtiff_reg.c @@ -0,0 +1,378 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * mtiff_reg.c + * + * Tests tiff I/O for: + * + * - multipage tiff read/write + * - writing special tiff tags to file [not tested here] + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" +#include <string.h> + +static const char *weasel_rev = "/tmp/lept/tiff/weasel_rev.tif"; +static const char *weasel_rev_rev = "/tmp/lept/tiff/weasel_rev_rev.tif"; +static const char *weasel_orig = "/tmp/lept/tiff/weasel_orig.tif"; + +int main(int argc, + char **argv) +{ +l_uint8 *data; +char *fname, *filename; +const char *str; +char buf[512]; +l_int32 i, n, npages, equal, success; +size_t offset, size; +FILE *fp; +PIX *pix1, *pix2; +PIXA *pixa, *pixa1, *pixa2, *pixa3; +SARRAY *sa; +L_REGPARAMS *rp; + +#if !defined(HAVE_LIBPNG) + L_ERROR("This test requires libpng to run.\n", "mtiff_reg"); + exit(77); +#endif + + if (regTestSetup(argc, argv, &rp)) + return 1; + + lept_mkdir("lept/tiff"); + + /* ---------------------- Test multipage I/O -----------------------*/ + /* This puts every image file in the directory with a string + * match to "weasel8" into a multipage tiff file. + * Images with 1 bpp are coded as g4; the others as zip. + * It then reads back into a pix and displays. */ + writeMultipageTiff(".", "weasel8.", "/tmp/lept/tiff/weasel8.tif"); + regTestCheckFile(rp, "/tmp/lept/tiff/weasel8.tif"); /* 0 */ + pixa = pixaReadMultipageTiff("/tmp/lept/tiff/weasel8.tif"); + pix1 = pixaDisplayTiledInRows(pixa, 1, 1200, 0.5, 0, 15, 4); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 1 */ + pixDisplayWithTitle(pix1, 0, 0, NULL, rp->display); + pixDestroy(&pix1); + pix1 = pixaDisplayTiledInRows(pixa, 8, 1200, 0.8, 0, 15, 4); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 2 */ + pixDisplayWithTitle(pix1, 0, 200, NULL, rp->display); + pixDestroy(&pix1); + pix1 = pixaDisplayTiledInRows(pixa, 32, 1200, 1.2, 0, 15, 4); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 3 */ + pixDisplayWithTitle(pix1, 0, 400, NULL, rp->display); + pixDestroy(&pix1); + pixaDestroy(&pixa); + + /* This uses the offset method for linearizing overhead of + * reading from a multi-image tiff file. */ + offset = 0; + n = 0; + pixa = pixaCreate(8); + do { + pix1 = pixReadFromMultipageTiff("/tmp/lept/tiff/weasel8.tif", &offset); + if (!pix1) continue; + pixaAddPix(pixa, pix1, L_INSERT); + if (rp->display) + lept_stderr("offset = %ld\n", (unsigned long)offset); + n++; + } while (offset != 0); + if (rp->display) lept_stderr("Num images = %d\n", n); + pix1 = pixaDisplayTiledInRows(pixa, 32, 1200, 1.2, 0, 15, 4); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 4 */ + pixDisplayWithTitle(pix1, 0, 600, NULL, rp->display); + pixDestroy(&pix1); + pixaDestroy(&pixa); + + /* This uses the offset method for linearizing overhead of + * reading from a multi-image tiff file in memory. */ + offset = 0; + n = 0; + pixa = pixaCreate(8); + data = l_binaryRead("/tmp/lept/tiff/weasel8.tif", &size); + do { + pix1 = pixReadMemFromMultipageTiff(data, size, &offset); + if (!pix1) continue; + pixaAddPix(pixa, pix1, L_INSERT); + if (rp->display) + lept_stderr("offset = %ld\n", (unsigned long)offset); + n++; + } while (offset != 0); + if (rp->display) lept_stderr("Num images = %d\n", n); + pix1 = pixaDisplayTiledInRows(pixa, 32, 1200, 1.2, 0, 15, 4); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 5 */ + pixDisplayWithTitle(pix1, 0, 800, NULL, rp->display); + pixDestroy(&pix1); + pixaDestroy(&pixa); + lept_free(data); + regTestCompareFiles(rp, 3, 4); /* 6 */ + regTestCompareFiles(rp, 3, 5); /* 7 */ + + /* This makes a 1000 image tiff file and gives timing + * for writing and reading. Reading uses both the offset method + * for returning individual pix and atomic pixaReadMultipageTiff() + * method for returning a pixa of all the images. Reading time + * is linear in the number of images, but the writing time is + * quadratic, and the actual wall clock time is significantly + * more than the printed value. */ + pix1 = pixRead("char.tif"); + startTimer(); + pixWriteTiff("/tmp/lept/tiff/junkm.tif", pix1, IFF_TIFF_G4, "w"); + for (i = 1; i < 1000; i++) { + pixWriteTiff("/tmp/lept/tiff/junkm.tif", pix1, IFF_TIFF_G4, "a"); + } + regTestCheckFile(rp, "/tmp/lept/tiff/junkm.tif"); /* 8 */ + pixDestroy(&pix1); + if (rp->display) { + lept_stderr("\n1000 image file: /tmp/lept/tiff/junkm.tif\n"); + lept_stderr("Time to write 1000 images: %7.3f sec\n", stopTimer()); + } + + startTimer(); + offset = 0; + n = 0; + do { + pix1 = pixReadFromMultipageTiff("/tmp/lept/tiff/junkm.tif", &offset); + if (!pix1) continue; + if (rp->display && (n % 100 == 0)) + lept_stderr("offset = %ld\n", (unsigned long)offset); + pixDestroy(&pix1); + n++; + } while (offset != 0); + regTestCompareValues(rp, 1000, n, 0); /* 9 */ + if (rp->display) + lept_stderr("Time to read %d images: %6.3f sec\n", n, stopTimer()); + + startTimer(); + pixa = pixaReadMultipageTiff("/tmp/lept/tiff/junkm.tif"); + lept_stderr("Time to read %d images and return a pixa: %6.3f sec\n", + pixaGetCount(pixa), stopTimer()); + pix1 = pixaDisplayTiledInRows(pixa, 8, 1500, 0.8, 0, 15, 4); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 10 */ + pixDestroy(&pix1); + pixaDestroy(&pixa); + + /* This does the following sequence of operations: + * (1) makes pixa1 and writes a multipage tiff file from it + * (2) reads that file into memory + * (3) generates pixa2 from the data in memory + * (4) tiff compresses pixa2 back to memory + * (5) generates pixa3 by uncompressing the memory data + * (6) compares pixa3 with pixa1 */ + pix1 = pixRead("weasel8.240c.png"); /* (1) */ + pixa1 = pixaCreate(10); + for (i = 0; i < 10; i++) + pixaAddPix(pixa1, pix1, L_COPY); + pixDestroy(&pix1); + pixaWriteMultipageTiff("/tmp/lept/tiff/junkm2.tif", pixa1); + regTestCheckFile(rp, "/tmp/lept/tiff/junkm2.tif"); /* 11 */ + data = l_binaryRead("/tmp/lept/tiff/junkm2.tif", &size); /* (2) */ + pixa2 = pixaCreate(10); /* (3) */ + offset = 0; + n = 0; + do { + pix1 = pixReadMemFromMultipageTiff(data, size, &offset); + pixaAddPix(pixa2, pix1, L_INSERT); + n++; + } while (offset != 0); + regTestCompareValues(rp, 10, n, 0); /* 12 */ + if (rp->display) lept_stderr("\nRead %d images\n", n); + lept_free(data); + pixaWriteMemMultipageTiff(&data, &size, pixa2); /* (4) */ + pixa3 = pixaReadMemMultipageTiff(data, size); /* (5) */ + pix1 = pixaDisplayTiledInRows(pixa3, 8, 1500, 0.8, 0, 15, 4); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 13 */ + pixDestroy(&pix1); + n = pixaGetCount(pixa3); + if (rp->display) lept_stderr("Write/read %d images\n", n); + success = TRUE; + for (i = 0; i < n; i++) { + pix1 = pixaGetPix(pixa1, i, L_CLONE); + pix2 = pixaGetPix(pixa3, i, L_CLONE); + pixEqual(pix1, pix2, &equal); + if (!equal) success = FALSE; + pixDestroy(&pix1); + pixDestroy(&pix2); + } + regTestCompareValues(rp, TRUE, success, 0); /* 14 */ + pixaDestroy(&pixa1); + pixaDestroy(&pixa2); + pixaDestroy(&pixa3); + lept_free(data); + + /* ------------------ Test single-to-multipage I/O -------------------*/ + /* Read the files and generate a multipage tiff file of G4 images. + * Then convert that to a G4 compressed and ascii85 encoded PS file. */ + sa = getSortedPathnamesInDirectory(".", "weasel4.", 0, 4); + if (rp->display) sarrayWriteStream(stderr, sa); + sarraySort(sa, sa, L_SORT_INCREASING); + if (rp->display) sarrayWriteStream(stderr, sa); + npages = sarrayGetCount(sa); + for (i = 0; i < npages; i++) { + fname = sarrayGetString(sa, i, L_NOCOPY); + filename = genPathname(".", fname); + pix1 = pixRead(filename); + if (!pix1) continue; + pix2 = pixConvertTo1(pix1, 128); + if (i == 0) + pixWriteTiff("/tmp/lept/tiff/weasel4", pix2, IFF_TIFF_G4, "w+"); + else + pixWriteTiff("/tmp/lept/tiff/weasel4", pix2, IFF_TIFF_G4, "a"); + pixDestroy(&pix1); + pixDestroy(&pix2); + lept_free(filename); + } + regTestCheckFile(rp, "/tmp/lept/tiff/junkm2.tif"); /* 15 */ + + /* Write it out as a PS file */ + lept_stderr("Writing to: /tmp/lept/tiff/weasel4.ps\n"); + convertTiffMultipageToPS("/tmp/lept/tiff/weasel4", + "/tmp/lept/tiff/weasel4.ps", 0.95); + regTestCheckFile(rp, "/tmp/lept/tiff/weasel4.ps"); /* 16 */ + + /* Write it out as a pdf file */ + lept_stderr("Writing to: /tmp/lept/tiff/weasel4.pdf\n"); + l_pdfSetDateAndVersion(FALSE); + convertTiffMultipageToPdf("/tmp/lept/tiff/weasel4", + "/tmp/lept/tiff/weasel4.pdf"); + regTestCheckFile(rp, "/tmp/lept/tiff/weasel4.pdf"); /* 17 */ + sarrayDestroy(&sa); + + /* ------------------ Test multipage I/O -------------------*/ + /* Read count of pages in tiff multipage file */ + writeMultipageTiff(".", "weasel2", weasel_orig); + regTestCheckFile(rp, weasel_orig); /* 18 */ + fp = lept_fopen(weasel_orig, "rb"); + success = fileFormatIsTiff(fp); + regTestCompareValues(rp, TRUE, success, 0); /* 19 */ + if (success) { + tiffGetCount(fp, &npages); + regTestCompareValues(rp, 5, npages, 0); /* 20 */ + lept_stderr(" Tiff: %d page\n", npages); + } + lept_fclose(fp); + + /* Split into separate page files */ + for (i = 0; i < npages + 1; i++) { /* read one beyond to catch error */ + pix1 = pixReadTiff(weasel_orig, i); + if (!pix1) continue; + snprintf(buf, sizeof(buf), "/tmp/lept/tiff/%03d.tif", i); + pixWrite(buf, pix1, IFF_TIFF_ZIP); + pixDestroy(&pix1); + } + + /* Read separate page files and write reversed file */ + for (i = npages - 1; i >= 0; i--) { + snprintf(buf, sizeof(buf), "/tmp/lept/tiff/%03d.tif", i); + pix1 = pixRead(buf); + if (!pix1) continue; + if (i == npages - 1) + pixWriteTiff(weasel_rev, pix1, IFF_TIFF_ZIP, "w+"); + else + pixWriteTiff(weasel_rev, pix1, IFF_TIFF_ZIP, "a"); + pixDestroy(&pix1); + } + regTestCheckFile(rp, weasel_rev); /* 21 */ + + /* Read reversed file and reverse again */ + pixa = pixaCreate(npages); + for (i = 0; i < npages; i++) { + pix1 = pixReadTiff(weasel_rev, i); + pixaAddPix(pixa, pix1, L_INSERT); + } + for (i = npages - 1; i >= 0; i--) { + pix1 = pixaGetPix(pixa, i, L_CLONE); + if (i == npages - 1) + pixWriteTiff(weasel_rev_rev, pix1, IFF_TIFF_ZIP, "w+"); + else + pixWriteTiff(weasel_rev_rev, pix1, IFF_TIFF_ZIP, "a"); + pixDestroy(&pix1); + } + regTestCheckFile(rp, weasel_rev_rev); /* 22 */ + regTestCompareFiles(rp, 18, 22); /* 23 */ + pixaDestroy(&pixa); + + +#if 1 /* ----- test adding custom public tags to a tiff header ----- */ +{ + size_t length; + NUMA *naflags, *nasizes; + SARRAY *savals, *satypes; + + pix1 = pixRead("feyn.tif"); + naflags = numaCreate(10); + savals = sarrayCreate(10); + satypes = sarrayCreate(10); + nasizes = numaCreate(10); + +/* numaAddNumber(naflags, TIFFTAG_XMLPACKET); */ /* XMP: 700 */ + numaAddNumber(naflags, 700); + str = "<xmp>This is a Fake XMP packet</xmp>\n<text>Guess what ...?</text>"; + length = strlen(str); + sarrayAddString(savals, str, L_COPY); + sarrayAddString(satypes, "char*", L_COPY); + numaAddNumber(nasizes, length); /* get it all */ + + numaAddNumber(naflags, 269); /* DOCUMENTNAME */ + sarrayAddString(savals, "One silly title", L_COPY); + sarrayAddString(satypes, "const char*", L_COPY); + numaAddNumber(naflags, 270); /* IMAGEDESCRIPTION */ + sarrayAddString(savals, "One page of text", L_COPY); + sarrayAddString(satypes, "const char*", L_COPY); + /* the max sample is used by rendering programs + * to scale the dynamic range */ + numaAddNumber(naflags, 281); /* MAXSAMPLEVALUE */ + sarrayAddString(savals, "4", L_COPY); + sarrayAddString(satypes, "l_uint16", L_COPY); + /* note that date is required to be a 20 byte string */ + numaAddNumber(naflags, 306); /* DATETIME */ + sarrayAddString(savals, "2004:10:11 09:35:15", L_COPY); + sarrayAddString(satypes, "const char*", L_COPY); + /* note that page number requires 2 l_uint16 input */ + numaAddNumber(naflags, 297); /* PAGENUMBER */ + sarrayAddString(savals, "1-412", L_COPY); + sarrayAddString(satypes, "l_uint16-l_uint16", L_COPY); + pixWriteTiffCustom("/tmp/lept/tiff/tags.tif", pix1, IFF_TIFF_G4, "w", naflags, + savals, satypes, nasizes); + fprintTiffInfo(stderr, "/tmp/lept/tiff/tags.tif"); + lept_stderr("num flags = %d\n", numaGetCount(naflags)); + lept_stderr("num sizes = %d\n", numaGetCount(nasizes)); + lept_stderr("num vals = %d\n", sarrayGetCount(savals)); + lept_stderr("num types = %d\n", sarrayGetCount(satypes)); + numaDestroy(&naflags); + numaDestroy(&nasizes); + sarrayDestroy(&savals); + sarrayDestroy(&satypes); + pixDestroy(&pix1); +} +#endif + + return regTestCleanup(rp); +} diff --git a/leptonica/prog/multitype_reg.c b/leptonica/prog/multitype_reg.c new file mode 100644 index 00000000..4f899036 --- /dev/null +++ b/leptonica/prog/multitype_reg.c @@ -0,0 +1,483 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * multitype_reg.c + * + * Tests various functions against a set of the different image types. + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + +static const char *fnames[10] = {"feyn-fract.tif", "speckle2.png", + "weasel2.4g.png", "speckle4.png", + "weasel4.16c.png", "dreyfus8.png", + "weasel8.240c.png", "test8.jpg", + "marge.jpg", "test-gray-alpha.png"}; + + /* Affine uses the first 3 pt pairs; projective & bilinear use all 4 */ +static const l_int32 xs[] = {300, 1200, 225, 750}; +static const l_int32 xd[] = {330, 1225, 250, 870}; +static const l_int32 ys[] = {1250, 1120, 250, 200}; +static const l_int32 yd[] = {1150, 1200, 250, 290}; + +enum { + PROJECTIVE = 1, + BILINEAR = 2 +}; + +static l_float32 *Generate3PtTransformVector(); +static l_float32 *Generate4PtTransformVector(l_int32 type); + +#define DO_ALL 1 + +int main(int argc, + char **argv) +{ +l_int32 w, h, x, y, i, n; +l_float32 *vc; +PIX *pix1, *pix2, *pix3, *pix4, *pix5; +PIXA *pixas, *pixa; +L_REGPARAMS *rp; + + if (regTestSetup(argc, argv, &rp)) + return 1; + + pixas = pixaCreate(11); + for (i = 0; i < 10; i++) { /* this preserves any alpha */ + pix1 = pixRead(fnames[i]); + pix2 = pixScaleBySamplingToSize(pix1, 250, 150); + pixaAddPix(pixas, pix2, L_INSERT); + pixDestroy(&pix1); + } + + /* Add a transparent grid over the rgb image */ + pix1 = pixaGetPix(pixas, 8, L_COPY); + pixGetDimensions(pix1, &w, &h, NULL); + pix2 = pixCreate(w, h, 1); + for (i = 0; i < 5; i++) { + y = h * (i + 1) / 6; + pixRenderLine(pix2, 0, y, w, y, 3, L_SET_PIXELS); + } + for (i = 0; i < 7; i++) { + x = w * (i + 1) / 8; + pixRenderLine(pix2, x, 0, x, h, 3, L_SET_PIXELS); + } + pix3 = pixConvertTo8(pix2, 0); /* 1 --> 0 ==> transparent */ + pixSetRGBComponent(pix1, pix3, L_ALPHA_CHANNEL); + pixaAddPix(pixas, pix1, L_INSERT); + n = pixaGetCount(pixas); + pixDestroy(&pix2); + pixDestroy(&pix3); + +#if DO_ALL + /* Display with and without removing alpha with white bg */ + pix1 = pixaDisplayTiledInRows(pixas, 32, 1200, 1.0, 0, 25, 2); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 0 */ + pixDisplayWithTitle(pix1, 0, 0, NULL, rp->display); + pixDestroy(&pix1); + pixa = pixaCreate(n); + for (i = 0; i < n; i++) { + pix1 = pixaGetPix(pixas, i, L_COPY); + pix2 = pixRemoveAlpha(pix1); + pixaAddPix(pixa, pix2, L_INSERT); + pixDestroy(&pix1); + } + pix1 = pixaDisplayTiledInRows(pixa, 32, 1200, 1.0, 0, 25, 2); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 1 */ + pixDisplayWithTitle(pix1, 200, 0, NULL, rp->display); + pixDestroy(&pix1); + pixaDestroy(&pixa); +#endif + +#if DO_ALL + /* Setting to gray */ + pixa = pixaCreate(n); + for (i = 0; i < n; i++) { + pix1 = pixaGetPix(pixas, i, L_COPY); + pixSetAllGray(pix1, 170); + pix2 = pixRemoveAlpha(pix1); + pixaAddPix(pixa, pix2, L_INSERT); + pixDestroy(&pix1); + } + pix1 = pixaDisplayTiledInRows(pixa, 32, 1200, 1.0, 0, 25, 2); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 2 */ + pixDisplayWithTitle(pix1, 400, 0, NULL, rp->display); + pixDestroy(&pix1); + pixaDestroy(&pixa); +#endif + +#if DO_ALL + /* General scaling */ + pixa = pixaCreate(n); + for (i = 0; i < n; i++) { + pix1 = pixaGetPix(pixas, i, L_COPY); + pix2 = pixScaleToSize(pix1, 350, 650); + pix3 = pixScaleToSize(pix2, 200, 200); + pix4 = pixRemoveAlpha(pix3); + pixaAddPix(pixa, pix4, L_INSERT); + pixDestroy(&pix1); + pixDestroy(&pix2); + pixDestroy(&pix3); + } + pix1 = pixaDisplayTiledInRows(pixa, 32, 1200, 1.0, 0, 25, 2); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 3 */ + pixDisplayWithTitle(pix1, 600, 0, NULL, rp->display); + pixDestroy(&pix1); + pixaDestroy(&pixa); +#endif + +#if DO_ALL + /* Scaling by sampling */ + pixa = pixaCreate(n); + for (i = 0; i < n; i++) { + pix1 = pixaGetPix(pixas, i, L_COPY); + pix2 = pixScaleBySamplingToSize(pix1, 350, 650); + pix3 = pixScaleBySamplingToSize(pix2, 200, 200); + pix4 = pixRemoveAlpha(pix3); + pixaAddPix(pixa, pix4, L_INSERT); + pixDestroy(&pix1); + pixDestroy(&pix2); + pixDestroy(&pix3); + } + pix1 = pixaDisplayTiledInRows(pixa, 32, 1200, 1.0, 0, 25, 2); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 4 */ + pixDisplayWithTitle(pix1, 800, 0, NULL, rp->display); + pixDestroy(&pix1); + pixaDestroy(&pixa); +#endif + +#if DO_ALL + /* Rotation by area mapping; no embedding */ + pixa = pixaCreate(n); + for (i = 0; i < n; i++) { + pix1 = pixaGetPix(pixas, i, L_COPY); + pix2 = pixRotate(pix1, 0.25, L_ROTATE_AREA_MAP, + L_BRING_IN_WHITE, 0, 0); + pix3 = pixRotate(pix2, -0.35, L_ROTATE_AREA_MAP, + L_BRING_IN_WHITE, 0, 0); + pix4 = pixRemoveAlpha(pix3); + pixaAddPix(pixa, pix4, L_INSERT); + pixDestroy(&pix1); + pixDestroy(&pix2); + pixDestroy(&pix3); + } + pix1 = pixaDisplayTiledInRows(pixa, 32, 1200, 1.0, 0, 25, 2); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 5 */ + pixDisplayWithTitle(pix1, 1000, 0, NULL, rp->display); + pixDestroy(&pix1); + pixaDestroy(&pixa); +#endif + +#if DO_ALL + /* Rotation by area mapping; with embedding */ + pixa = pixaCreate(n); + for (i = 0; i < n; i++) { + pix1 = pixaGetPix(pixas, i, L_COPY); + pix2 = pixRotate(pix1, 0.25, L_ROTATE_AREA_MAP, + L_BRING_IN_WHITE, 250, 150); + pix3 = pixRotate(pix2, -0.35, L_ROTATE_AREA_MAP, + L_BRING_IN_WHITE, 250, 150); + pix4 = pixRemoveBorderToSize(pix3, 250, 150); + pix5 = pixRemoveAlpha(pix4); + pixaAddPix(pixa, pix5, L_INSERT); + pixDestroy(&pix1); + pixDestroy(&pix2); + pixDestroy(&pix3); + pixDestroy(&pix4); + } + pix1 = pixaDisplayTiledInRows(pixa, 32, 1200, 1.0, 0, 25, 2); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 6 */ + pixDisplayWithTitle(pix1, 0, 400, NULL, rp->display); + pixDestroy(&pix1); + pixaDestroy(&pixa); +#endif + +#if DO_ALL + /* Rotation by 3-shear; no embedding */ + pixa = pixaCreate(n); + for (i = 0; i < n; i++) { + pix1 = pixaGetPix(pixas, i, L_COPY); + pix2 = pixRotate(pix1, 0.25, L_ROTATE_SHEAR, + L_BRING_IN_WHITE, 0, 0); + pix3 = pixRotate(pix2, -0.35, L_ROTATE_SHEAR, + L_BRING_IN_WHITE, 0, 0); + pix4 = pixRemoveAlpha(pix3); + pixaAddPix(pixa, pix4, L_INSERT); + pixDestroy(&pix1); + pixDestroy(&pix2); + pixDestroy(&pix3); + } + pix1 = pixaDisplayTiledInRows(pixa, 32, 1200, 1.0, 0, 25, 2); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 7 */ + pixDisplayWithTitle(pix1, 200, 400, NULL, rp->display); + pixDestroy(&pix1); + pixaDestroy(&pixa); +#endif + +#if DO_ALL + /* Rotation by 3-shear; with embedding */ + pixa = pixaCreate(n); + for (i = 0; i < n; i++) { + pix1 = pixaGetPix(pixas, i, L_COPY); + pix2 = pixRotate(pix1, 0.25, L_ROTATE_SHEAR, + L_BRING_IN_WHITE, 250, 150); + pix3 = pixRotate(pix2, -0.35, L_ROTATE_SHEAR, + L_BRING_IN_WHITE, 250, 150); + pix4 = pixRemoveBorderToSize(pix3, 250, 150); + pix5 = pixRemoveAlpha(pix4); + pixaAddPix(pixa, pix5, L_INSERT); + pixDestroy(&pix1); + pixDestroy(&pix2); + pixDestroy(&pix3); + pixDestroy(&pix4); + } + pix1 = pixaDisplayTiledInRows(pixa, 32, 1200, 1.0, 0, 25, 2); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 8 */ + pixDisplayWithTitle(pix1, 400, 400, NULL, rp->display); + pixDestroy(&pix1); + pixaDestroy(&pixa); +#endif + +#if DO_ALL + /* Rotation by 2-shear about the center */ + pixa = pixaCreate(n); + for (i = 0; i < n; i++) { + pix1 = pixaGetPix(pixas, i, L_COPY); + pixGetDimensions(pix1, &w, &h, NULL); + pix2 = pixRotate2Shear(pix1, w / 2, h / 2, 0.25, L_BRING_IN_WHITE); + pix3 = pixRotate2Shear(pix2, w / 2, h / 2, -0.35, L_BRING_IN_WHITE); + pix4 = pixRemoveAlpha(pix3); + pixaAddPix(pixa, pix4, L_INSERT); + pixDestroy(&pix1); + pixDestroy(&pix2); + pixDestroy(&pix3); + } + pix1 = pixaDisplayTiledInRows(pixa, 32, 1200, 1.0, 0, 25, 2); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 9 */ + pixDisplayWithTitle(pix1, 600, 400, NULL, rp->display); + pixDestroy(&pix1); + pixaDestroy(&pixa); +#endif + +#if DO_ALL + /* Rotation by sampling; no embedding */ + pixa = pixaCreate(n); + for (i = 0; i < n; i++) { + pix1 = pixaGetPix(pixas, i, L_COPY); + pix2 = pixRotate(pix1, 0.25, L_ROTATE_SAMPLING, + L_BRING_IN_WHITE, 0, 0); + pix3 = pixRotate(pix2, -0.35, L_ROTATE_SAMPLING, + L_BRING_IN_WHITE, 0, 0); + pix4 = pixRemoveAlpha(pix3); + pixaAddPix(pixa, pix4, L_INSERT); + pixDestroy(&pix1); + pixDestroy(&pix2); + pixDestroy(&pix3); + } + pix1 = pixaDisplayTiledInRows(pixa, 32, 1200, 1.0, 0, 25, 2); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 10 */ + pixDisplayWithTitle(pix1, 800, 400, NULL, rp->display); + pixDestroy(&pix1); + pixaDestroy(&pixa); +#endif + +#if DO_ALL + /* Rotation by sampling; with embedding */ + pixa = pixaCreate(n); + for (i = 0; i < n; i++) { + pix1 = pixaGetPix(pixas, i, L_COPY); + pix2 = pixRotate(pix1, 0.25, L_ROTATE_SAMPLING, + L_BRING_IN_WHITE, 250, 150); + pix3 = pixRotate(pix2, -0.35, L_ROTATE_SAMPLING, + L_BRING_IN_WHITE, 250, 150); + pix4 = pixRemoveBorderToSize(pix3, 250, 150); + pix5 = pixRemoveAlpha(pix4); + pixaAddPix(pixa, pix5, L_INSERT); + pixDestroy(&pix1); + pixDestroy(&pix2); + pixDestroy(&pix3); + pixDestroy(&pix4); + } + pix1 = pixaDisplayTiledInRows(pixa, 32, 1200, 1.0, 0, 25, 2); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 11 */ + pixDisplayWithTitle(pix1, 1000, 400, NULL, rp->display); + pixDestroy(&pix1); + pixaDestroy(&pixa); +#endif + +#if DO_ALL + /* Rotation by area mapping at corner */ + pixa = pixaCreate(n); + for (i = 0; i < n; i++) { + pix1 = pixaGetPix(pixas, i, L_COPY); + pix2 = pixRotateAMCorner(pix1, 0.25, L_BRING_IN_WHITE); + pix3 = pixRotateAMCorner(pix2, -0.35, L_BRING_IN_WHITE); + pix4 = pixRemoveAlpha(pix3); + pixaAddPix(pixa, pix4, L_INSERT); + pixDestroy(&pix1); + pixDestroy(&pix2); + pixDestroy(&pix3); + } + pix1 = pixaDisplayTiledInRows(pixa, 32, 1200, 1.0, 0, 25, 2); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 12 */ + pixDisplayWithTitle(pix1, 0, 800, NULL, rp->display); + pixDestroy(&pix1); + pixaDestroy(&pixa); +#endif + +#if DO_ALL + /* Affine transform by interpolation */ + pixa = pixaCreate(n); + vc = Generate3PtTransformVector(); + for (i = 0; i < n; i++) { + pix1 = pixaGetPix(pixas, i, L_COPY); + pix2 = pixAffine(pix1, vc, L_BRING_IN_WHITE); +/* pix2 = pixAffineSampled(pix1, vc, L_BRING_IN_WHITE); */ + pix3 = pixRemoveAlpha(pix2); + pixaAddPix(pixa, pix3, L_INSERT); + pixDestroy(&pix1); + pixDestroy(&pix2); + } + pix1 = pixaDisplayTiledInRows(pixa, 32, 1200, 1.0, 0, 25, 2); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 13 */ + pixDisplayWithTitle(pix1, 200, 800, NULL, rp->display); + pixDestroy(&pix1); + pixaDestroy(&pixa); + lept_free(vc); +#endif + +#if DO_ALL + /* Projective transform by sampling */ + pixa = pixaCreate(n); + vc = Generate4PtTransformVector(PROJECTIVE); + for (i = 0; i < n; i++) { + pix1 = pixaGetPix(pixas, i, L_COPY); + pix2 = pixProjectiveSampled(pix1, vc, L_BRING_IN_WHITE); + pix3 = pixRemoveAlpha(pix2); + pixaAddPix(pixa, pix3, L_INSERT); + pixDestroy(&pix1); + pixDestroy(&pix2); + } + pix1 = pixaDisplayTiledInRows(pixa, 32, 1200, 1.0, 0, 25, 2); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 14 */ + pixDisplayWithTitle(pix1, 400, 800, NULL, rp->display); + pixDestroy(&pix1); + pixaDestroy(&pixa); + lept_free(vc); +#endif + +#if DO_ALL + /* Projective transform by interpolation */ + pixa = pixaCreate(n); + vc = Generate4PtTransformVector(PROJECTIVE); + for (i = 0; i < n; i++) { + pix1 = pixaGetPix(pixas, i, L_COPY); + pix2 = pixProjective(pix1, vc, L_BRING_IN_WHITE); + pix3 = pixRemoveAlpha(pix2); + pixaAddPix(pixa, pix3, L_INSERT); + pixDestroy(&pix1); + pixDestroy(&pix2); + } + pix1 = pixaDisplayTiledInRows(pixa, 32, 1200, 1.0, 0, 25, 2); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 15 */ + pixDisplayWithTitle(pix1, 600, 800, NULL, rp->display); + pixDestroy(&pix1); + pixaDestroy(&pixa); + lept_free(vc); +#endif + +#if DO_ALL + /* Bilinear transform by interpolation */ + pixa = pixaCreate(n); + vc = Generate4PtTransformVector(BILINEAR); + for (i = 0; i < n; i++) { + pix1 = pixaGetPix(pixas, i, L_COPY); + pix2 = pixBilinear(pix1, vc, L_BRING_IN_WHITE); + pix3 = pixRemoveAlpha(pix2); + pixaAddPix(pixa, pix3, L_INSERT); + pixDestroy(&pix1); + pixDestroy(&pix2); + } + pix1 = pixaDisplayTiledInRows(pixa, 32, 1200, 1.0, 0, 25, 2); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 16 */ + pixDisplayWithTitle(pix1, 800, 800, NULL, rp->display); + pixDestroy(&pix1); + pixaDestroy(&pixa); + lept_free(vc); +#endif + + pixaDestroy(&pixas); + return regTestCleanup(rp); +} + + +static l_float32 * +Generate3PtTransformVector() +{ +l_int32 i; +l_float32 *vc; +PTA *ptas, *ptad; + + ptas = ptaCreate(3); + ptad = ptaCreate(3); + for (i = 0; i < 3; i++) { + ptaAddPt(ptas, xs[i], ys[i]); + ptaAddPt(ptad, xd[i], yd[i]); + } + + getAffineXformCoeffs(ptad, ptas, &vc); + ptaDestroy(&ptas); + ptaDestroy(&ptad); + return vc; +} + +static l_float32 * +Generate4PtTransformVector(l_int32 type) +{ +l_int32 i; +l_float32 *vc; +PTA *ptas, *ptad; + + ptas = ptaCreate(4); + ptad = ptaCreate(4); + for (i = 0; i < 4; i++) { + ptaAddPt(ptas, xs[i], ys[i]); + ptaAddPt(ptad, xd[i], yd[i]); + } + + if (type == PROJECTIVE) + getProjectiveXformCoeffs(ptad, ptas, &vc); + else /* BILINEAR */ + getBilinearXformCoeffs(ptad, ptas, &vc); + ptaDestroy(&ptas); + ptaDestroy(&ptad); + return vc; +} diff --git a/leptonica/prog/nearline_reg.c b/leptonica/prog/nearline_reg.c new file mode 100644 index 00000000..3fd3a4ab --- /dev/null +++ b/leptonica/prog/nearline_reg.c @@ -0,0 +1,189 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * nearline_reg.c + * + * Regression test for finding min or max values (and averages) + * near a specified line. + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + +l_int32 main(int argc, + char **argv) +{ +l_int32 ret, i, n, similar, x1, y1, val1, val2, val3, val4; +l_float32 minave, minave2, maxave, fract; +NUMA *na1, *na2, *na3, *na4, *na5, *na6; +NUMAA *naa; +PIX *pixs, *pix1, *pix2, *pix3, *pix4; +L_REGPARAMS *rp; + +#if !defined(HAVE_LIBPNG) + L_ERROR("This test requires libpng to run.\n", "nearline_reg"); + exit(77); +#endif + + if (regTestSetup(argc, argv, &rp)) + return 1; + + pixs = pixRead("feyn.tif"); + pix1 = pixScaleToGray6(pixs); + pixDisplayWithTitle(pix1, 100, 600, NULL, rp->display); + + /* Find averages of min and max along about 120 horizontal lines */ + lept_stderr("******************************************************\n"); + lept_stderr("* Testing error checking: ignore 12 error messages *\n"); + na1 = numaCreate(0); + na3 = numaCreate(0); + for (y1 = 40; y1 < 575; y1 += 5) { + ret = pixMinMaxNearLine(pix1, 20, y1, 400, y1, 5, L_SCAN_BOTH, + NULL, NULL, &minave, &maxave); + if (!ret) { + numaAddNumber(na1, (l_int32)minave); + numaAddNumber(na3, (l_int32)maxave); + if (rp->display) + lept_stderr("y = %d: minave = %d, maxave = %d\n", + y1, (l_int32)minave, (l_int32)maxave); + } + } + + /* Find averages along about 120 vertical lines. We've rotated + * the image by 90 degrees, so the results should be nearly + * identical to the first set. Also generate a single-sided + * scan (L_SCAN_NEGATIVE) for comparison with the double-sided scans. */ + pix2 = pixRotateOrth(pix1, 3); + pixDisplayWithTitle(pix2, 600, 600, NULL, rp->display); + na2 = numaCreate(0); + na4 = numaCreate(0); + na5 = numaCreate(0); + for (x1 = 40; x1 < 575; x1 += 5) { + ret = pixMinMaxNearLine(pix2, x1, 20, x1, 400, 5, L_SCAN_BOTH, + NULL, NULL, &minave, &maxave); + pixMinMaxNearLine(pix2, x1, 20, x1, 400, 5, L_SCAN_NEGATIVE, + NULL, NULL, &minave2, NULL); + if (!ret) { + numaAddNumber(na2, (l_int32)minave); + numaAddNumber(na4, (l_int32)maxave); + numaAddNumber(na5, (l_int32)minave2); + if (rp->display) + lept_stderr("x = %d: minave = %d, minave2 = %d, maxave = %d\n", + x1, (l_int32)minave, (l_int32)minave2, (l_int32)maxave); + } + } + lept_stderr("******************************************************\n"); + + numaSimilar(na1, na2, 3.0, &similar); /* should be TRUE */ + regTestCompareValues(rp, similar, 1, 0); /* 0 */ + numaSimilar(na3, na4, 1.0, &similar); /* should be TRUE */ + regTestCompareValues(rp, similar, 1, 0); /* 1 */ + numaWrite("/tmp/lept/regout/na1.na", na1); + numaWrite("/tmp/lept/regout/na2.na", na2); + numaWrite("/tmp/lept/regout/na3.na", na3); + numaWrite("/tmp/lept/regout/na4.na", na4); + numaWrite("/tmp/lept/regout/na5.na", na5); + regTestCheckFile(rp, "/tmp/lept/regout/na1.na"); /* 2 */ + regTestCheckFile(rp, "/tmp/lept/regout/na2.na"); /* 3 */ + regTestCheckFile(rp, "/tmp/lept/regout/na3.na"); /* 4 */ + regTestCheckFile(rp, "/tmp/lept/regout/na4.na"); /* 5 */ + regTestCheckFile(rp, "/tmp/lept/regout/na5.na"); /* 6 */ + + /* Plot the average minimums for the 3 cases */ + naa = numaaCreate(3); + numaaAddNuma(naa, na1, L_INSERT); /* portrait, double-sided */ + numaaAddNuma(naa, na2, L_INSERT); /* landscape, double-sided */ + numaaAddNuma(naa, na5, L_INSERT); /* landscape, single-sided */ + gplotSimpleN(naa, GPLOT_PNG, "/tmp/lept/regout/nearline", + "Average minimums along lines"); + pix3 = pixRead("/tmp/lept/regout/nearline.png"); + regTestWritePixAndCheck(rp, pix3, IFF_PNG); /* 7 */ + pixDisplayWithTitle(pix3, 100, 100, NULL, rp->display); + + if (rp->display) { + n = numaGetCount(na3); + for (i = 0; i < n; i++) { + numaGetIValue(na1, i, &val1); + numaGetIValue(na2, i, &val2); + numaGetIValue(na3, i, &val3); + numaGetIValue(na4, i, &val4); + lept_stderr("val1 = %d, val2 = %d, diff = %d; " + "val3 = %d, val4 = %d, diff = %d\n", + val1, val2, L_ABS(val1 - val2), + val3, val4, L_ABS(val3 - val4)); + } + } + + numaaDestroy(&naa); + numaDestroy(&na3); + numaDestroy(&na4); + + /* Plot minima along a single line, with different distances */ + pixMinMaxNearLine(pix1, 20, 200, 400, 200, 2, L_SCAN_BOTH, + &na1, NULL, NULL, NULL); + pixMinMaxNearLine(pix1, 20, 200, 400, 200, 5, L_SCAN_BOTH, + &na2, NULL, NULL, NULL); + pixMinMaxNearLine(pix1, 20, 200, 400, 200, 15, L_SCAN_BOTH, + &na3, NULL, NULL, NULL); + numaWrite("/tmp/lept/regout/na6.na", na1); + regTestCheckFile(rp, "/tmp/lept/regout/na6.na"); /* 8 */ + n = numaGetCount(na1); + fract = 100.0 / n; + na4 = numaTransform(na1, 0.0, fract); + na5 = numaTransform(na2, 0.0, fract); + na6 = numaTransform(na3, 0.0, fract); + numaDestroy(&na1); + numaDestroy(&na2); + numaDestroy(&na3); + na1 = numaUniformSampling(na4, 100); + na2 = numaUniformSampling(na5, 100); + na3 = numaUniformSampling(na6, 100); + naa = numaaCreate(3); + numaaAddNuma(naa, na1, L_INSERT); + numaaAddNuma(naa, na2, L_INSERT); + numaaAddNuma(naa, na3, L_INSERT); + gplotSimpleN(naa, GPLOT_PNG, "/tmp/lept/regout/nearline2", + "Min along line"); + pix4 = pixRead("/tmp/lept/regout/nearline2.png"); + regTestWritePixAndCheck(rp, pix4, IFF_PNG); /* 9 */ + pixDisplayWithTitle(pix4, 800, 100, NULL, rp->display); + numaaDestroy(&naa); + numaDestroy(&na4); + numaDestroy(&na5); + numaDestroy(&na6); + + pixDestroy(&pix1); + pixDestroy(&pix2); + pixDestroy(&pix3); + pixDestroy(&pix4); + pixDestroy(&pixs); + return regTestCleanup(rp); +} + diff --git a/leptonica/prog/newspaper_reg.c b/leptonica/prog/newspaper_reg.c new file mode 100644 index 00000000..a1f12b36 --- /dev/null +++ b/leptonica/prog/newspaper_reg.c @@ -0,0 +1,171 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * newspaper_seg.c + * + * Segmenting newspaper articles using morphology. + * + * Most of the work is done at 4x reduction (approx. 75 ppi), + * which makes it very fast. + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + +int main(int argc, + char **argv) +{ +l_int32 w, h; +BOXA *boxa; +PIX *pixs, *pixt, *pix1, *pix2, *pix3, *pix4, *pix5; +PIX *pix6, *pix7, *pix8, *pix9, *pix10, *pix11; +PIXA *pixa1, *pixa2; +PIXCMAP *cmap; +L_REGPARAMS *rp; + + if (regTestSetup(argc, argv, &rp)) + return 1; + + pixs = pixRead("scots-frag.tif"); + pixa1 = pixaCreate(12); + + pixt = pixScaleToGray4(pixs); + pixaAddPix(pixa1, pixt, L_INSERT); + regTestWritePixAndCheck(rp, pixt, IFF_JFIF_JPEG); /* 0 */ + + /* Rank reduce 2x */ + pix1 = pixReduceRankBinary2(pixs, 2, NULL); + pixt = pixScale(pix1, 0.5, 0.5); + pixaAddPix(pixa1, pixt, L_INSERT); + + /* Open out the vertical lines */ + pix2 = pixMorphSequence(pix1, "o1.50", 0); + pixt = pixScale(pix2, 0.5, 0.5); + pixaAddPix(pixa1, pixt, L_INSERT); + regTestWritePixAndCheck(rp, pixt, IFF_TIFF_G4); /* 1 */ + pixDisplayWithTitle(pixt, 0, 0, "open vertical lines", rp->display); + + /* Seedfill back to get those lines in their entirety */ + pix3 = pixSeedfillBinary(NULL, pix2, pix1, 8); + pixt = pixScale(pix3, 0.5, 0.5); + pixaAddPix(pixa1, pixt, L_INSERT); + regTestWritePixAndCheck(rp, pixt, IFF_TIFF_G4); /* 2 */ + pixDisplayWithTitle(pixt, 300, 0, "seedfill vertical", rp->display); + + /* Remove the vertical lines (and some of the images) */ + pixXor(pix2, pix1, pix3); + pixt = pixScale(pix2, 0.5, 0.5); + pixaAddPix(pixa1, pixt, L_INSERT); + regTestWritePixAndCheck(rp, pixt, IFF_TIFF_G4); /* 3 */ + pixDisplayWithTitle(pixt, 600, 0, "remove vertical lines", rp->display); + + /* Open out the horizontal lines */ + pix4 = pixMorphSequence(pix2, "o50.1", 0); + pixt = pixScale(pix4, 0.5, 0.5); + pixaAddPix(pixa1, pixt, L_INSERT); + + /* Seedfill back to get those lines in their entirety */ + pix5 = pixSeedfillBinary(NULL, pix4, pix2, 8); + pixt = pixScale(pix5, 0.5, 0.5); + pixaAddPix(pixa1, pixt, L_INSERT); + regTestWritePixAndCheck(rp, pixt, IFF_TIFF_G4); /* 4 */ + pixDisplayWithTitle(pixt, 900, 0, "seedfill horizontal", rp->display); + + /* Remove the horizontal lines */ + pixXor(pix4, pix2, pix5); + pixt = pixScale(pix4, 0.5, 0.5); + pixaAddPix(pixa1, pixt, L_INSERT); + regTestWritePixAndCheck(rp, pixt, IFF_TIFF_G4); /* 5 */ + pixDisplayWithTitle(pixt, 1200, 0, "remove horiz lines", rp->display); + + /* Invert and identify vertical gutters between text columns */ + pix6 = pixReduceRankBinaryCascade(pix4, 1, 1, 0, 0); + pixInvert(pix6, pix6); + pixt = pixScale(pix6, 2.0, 2.0); + pixaAddPix(pixa1, pixt, L_INSERT); + regTestWritePixAndCheck(rp, pixt, IFF_TIFF_G4); /* 6 */ + pixDisplayWithTitle(pixt, 1500, 0, NULL, rp->display); + pix7 = pixMorphSequence(pix6, "o1.50", 0); + pixt = pixScale(pix7, 2.0, 2.0); + pixaAddPix(pixa1, pixt, L_INSERT); + regTestWritePixAndCheck(rp, pixt, IFF_TIFF_G4); /* 7 */ + pixDisplayWithTitle(pixt, 0, 300, "vertical gutters", rp->display); + pix8 = pixExpandBinaryPower2(pix7, 4); /* gutter mask */ + regTestWritePixAndCheck(rp, pix8, IFF_TIFF_G4); /* 8 */ + + /* Solidify text blocks */ + pix9 = pixMorphSequence(pix4, "c50.1 + c1.10", 0); + pixSubtract(pix9, pix9, pix8); /* preserve gutter */ + pix10 = pixMorphSequence(pix9, "d3.3", 0); + pixt = pixScale(pix10, 0.5, 0.5); + pixaAddPix(pixa1, pixt, L_INSERT); + regTestWritePixAndCheck(rp, pixt, IFF_TIFF_G4); /* 9 */ + pixDisplayWithTitle(pixt, 300, 300, "solidify text", rp->display); + + /* Show stuff under this mask */ + pixGetDimensions(pix10, &w, &h, NULL); + boxa = pixConnComp(pix10, &pixa2, 8); + pix11 = pixaDisplayRandomCmap(pixa2, w, h); + pixPaintThroughMask(pix11, pix4, 0, 0, 0); + pixt = pixScale(pix11, 0.5, 0.5); + pixaAddPix(pixa1, pixt, L_INSERT); + regTestWritePixAndCheck(rp, pixt, IFF_PNG); /* 10 */ + pixDisplayWithTitle(pixt, 600, 300, "stuff under mask1", rp->display); + boxaDestroy(&boxa); + pixaDestroy(&pixa2); + + /* Paint the background white */ + cmap = pixGetColormap(pix11); + pixcmapResetColor(cmap, 0, 255, 255, 255); + regTestWritePixAndCheck(rp, pix11, IFF_PNG); /* 11 */ + pixt = pixScale(pix11, 0.5, 0.5); + pixaAddPix(pixa1, pixt, L_INSERT); + regTestWritePixAndCheck(rp, pixt, IFF_PNG); /* 12 */ + pixDisplayWithTitle(pixt, 900, 300, "stuff under mask2", rp->display); + pixaConvertToPdf(pixa1, 75, 1.0, 0, 0, "Segmentation: newspaper_reg", + "/tmp/lept/regout/newspaper.pdf"); + L_INFO("Output pdf: /tmp/lept/regout/newspaper.pdf\n", rp->testname); + + pixaDestroy(&pixa1); + pixDestroy(&pixs); + pixDestroy(&pix1); + pixDestroy(&pix2); + pixDestroy(&pix3); + pixDestroy(&pix4); + pixDestroy(&pix5); + pixDestroy(&pix6); + pixDestroy(&pix7); + pixDestroy(&pix8); + pixDestroy(&pix9); + pixDestroy(&pix10); + pixDestroy(&pix11); + return regTestCleanup(rp); +} + diff --git a/leptonica/prog/numa1_reg.c b/leptonica/prog/numa1_reg.c new file mode 100644 index 00000000..414bdd60 --- /dev/null +++ b/leptonica/prog/numa1_reg.c @@ -0,0 +1,321 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * numa1_reg.c + * + * Tests: + * * histograms + * * interpolation + * * integration/differentiation + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include <math.h> +#include "allheaders.h" + +int main(int argc, + char **argv) +{ +l_int32 i, n, binsize, binstart, nbins; +l_float32 pi, val, angle, xval, yval, x0, y0, startval, fbinsize; +l_float32 minval, maxval, meanval, median, variance, rankval, rank, rmsdev; +GPLOT *gplot; +NUMA *na, *nahisto, *nax, *nay, *nasx, *nasy; +NUMA *nadx, *nady, *nafx, *nafy; +PIX *pixs, *pix1, *pix2, *pix3, *pix4, *pix5, *pix6, *pix7, *pixd; +PIXA *pixa; +L_REGPARAMS *rp; + +#if !defined(HAVE_LIBPNG) + L_ERROR("This test requires libpng to run.\n", "numa1_reg"); + exit(77); +#endif + + if (regTestSetup(argc, argv, &rp)) + return 1; + + lept_mkdir("lept/numa1"); + + /* -------------------------------------------------------------------* + * Histograms * + * -------------------------------------------------------------------*/ + pi = 3.1415926535; + na = numaCreate(5000); + for (i = 0; i < 500000; i++) { + angle = 0.02293 * i * pi; + val = (l_float32)(999. * sin(angle)); + numaAddNumber(na, val); + } + + nahisto = numaMakeHistogramClipped(na, 6, 2000); + nbins = numaGetCount(nahisto); + nax = numaMakeSequence(0, 1, nbins); + pix1 = gplotGeneralPix2(nax, nahisto, GPLOT_LINES, "/tmp/lept/numa1/histo1", + "example histo 1", "i", "histo[i]"); + numaDestroy(&nax); + numaDestroy(&nahisto); + + nahisto = numaMakeHistogram(na, 1000, &binsize, &binstart); + nbins = numaGetCount(nahisto); + nax = numaMakeSequence(binstart, binsize, nbins); + lept_stderr(" binsize = %d, binstart = %d\n", binsize, binstart); + pix2 = gplotGeneralPix2(nax, nahisto, GPLOT_LINES, "/tmp/lept/numa1/histo2", + "example histo 2", "i", "histo[i]"); + numaDestroy(&nax); + numaDestroy(&nahisto); + + nahisto = numaMakeHistogram(na, 1000, &binsize, NULL); + nbins = numaGetCount(nahisto); + nax = numaMakeSequence(0, binsize, nbins); + lept_stderr(" binsize = %d, binstart = %d\n", binsize, 0); + pix3 = gplotGeneralPix2(nax, nahisto, GPLOT_LINES, "/tmp/lept/numa1/histo3", + "example histo 3", "i", "histo[i]"); + numaDestroy(&nax); + numaDestroy(&nahisto); + + nahisto = numaMakeHistogramAuto(na, 1000); + nbins = numaGetCount(nahisto); + numaGetParameters(nahisto, &startval, &fbinsize); + nax = numaMakeSequence(startval, fbinsize, nbins); + lept_stderr(" binsize = %7.4f, binstart = %8.3f\n", fbinsize, startval); + pix4 = gplotGeneralPix2(nax, nahisto, GPLOT_LINES, "/tmp/lept/numa1/histo4", + "example histo 4", "i", "histo[i]"); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 0 */ + regTestWritePixAndCheck(rp, pix2, IFF_PNG); /* 1 */ + regTestWritePixAndCheck(rp, pix3, IFF_PNG); /* 2 */ + regTestWritePixAndCheck(rp, pix4, IFF_PNG); /* 3 */ + pixa = pixaCreate(4); + pixaAddPix(pixa, pix1, L_INSERT); + pixaAddPix(pixa, pix2, L_INSERT); + pixaAddPix(pixa, pix3, L_INSERT); + pixaAddPix(pixa, pix4, L_INSERT); + if (rp->display) { + pixd = pixaDisplayTiledInRows(pixa, 32, 1500, 1.0, 0, 20, 2); + pixDisplayWithTitle(pixd, 0, 0, NULL, 1); + pixDestroy(&pixd); + } + pixaDestroy(&pixa); + numaDestroy(&nax); + numaDestroy(&nahisto); + + numaGetStatsUsingHistogram(na, 2000, &minval, &maxval, &meanval, + &variance, &median, 0.80, &rankval, &nahisto); + rmsdev = sqrt((l_float64)variance); + numaHistogramGetRankFromVal(nahisto, rankval, &rank); + regTestCompareValues(rp, -999.00, minval, 0.1); /* 4 */ + regTestCompareValues(rp, 999.00, maxval, 0.1); /* 5 */ + regTestCompareValues(rp, 0.055, meanval, 0.001); /* 6 */ + regTestCompareValues(rp, 0.30, median, 0.005); /* 7 */ + regTestCompareValues(rp, 706.41, rmsdev, 0.1); /* 8 */ + regTestCompareValues(rp, 808.15, rankval, 0.1); /* 9 */ + regTestCompareValues(rp, 0.800, rank, 0.01); /* 10 */ + if (rp->display) { + lept_stderr("Sin histogram: \n" + " min val = %7.3f -- should be -999.00\n" + " max val = %7.3f -- should be 999.00\n" + " mean val = %7.3f -- should be 0.055\n" + " median = %7.3f -- should be 0.30\n" + " rmsdev = %7.3f -- should be 706.41\n" + " rank val = %7.3f -- should be 808.152\n" + " rank = %7.3f -- should be 0.800\n", + minval, maxval, meanval, median, rmsdev, rankval, rank); + } + numaDestroy(&nahisto); + numaDestroy(&na); + + /* -------------------------------------------------------------------* + * Interpolation * + * -------------------------------------------------------------------*/ + /* Test numaInterpolateEqxInterval() */ + pixs = pixRead("test8.jpg"); + na = pixGetGrayHistogramMasked(pixs, NULL, 0, 0, 1); + nasy = numaGetPartialSums(na); + pix1 = gplotGeneralPix1(nasy, GPLOT_LINES, "/tmp/lept/numa1/int1", + "partial sums", NULL, NULL); + pix2 = gplotGeneralPix1(na, GPLOT_LINES, "/tmp/lept/numa1/int2", + "simple test", NULL, NULL); + numaInterpolateEqxInterval(0.0, 1.0, na, L_LINEAR_INTERP, + 0.0, 255.0, 15, &nax, &nay); + pix3 = gplotGeneralPix2(nax, nay, GPLOT_LINES, "/tmp/lept/numa1/int3", + "test interpolation", "pix val", "num pix"); + numaDestroy(&na); + numaDestroy(&nasy); + numaDestroy(&nax); + numaDestroy(&nay); + pixDestroy(&pixs); + + /* Test numaInterpolateArbxInterval() */ + pixs = pixRead("test8.jpg"); + na = pixGetGrayHistogramMasked(pixs, NULL, 0, 0, 1); + nasy = numaGetPartialSums(na); + numaInsertNumber(nasy, 0, 0.0); + nasx = numaMakeSequence(0.0, 1.0, 257); + numaInterpolateArbxInterval(nasx, nasy, L_LINEAR_INTERP, + 10.0, 250.0, 23, &nax, &nay); + pix4 = gplotGeneralPix2(nax, nay, GPLOT_LINES, "/tmp/lept/numa1/int4", + "arbx interpolation", "pix val", "cum num pix"); + numaDestroy(&na); + numaDestroy(&nasx); + numaDestroy(&nasy); + numaDestroy(&nax); + numaDestroy(&nay); + pixDestroy(&pixs); + + /* Test numaInterpolateArbxVal() */ + pixs = pixRead("test8.jpg"); + na = pixGetGrayHistogramMasked(pixs, NULL, 0, 0, 1); + nasy = numaGetPartialSums(na); + numaInsertNumber(nasy, 0, 0.0); + nasx = numaMakeSequence(0.0, 1.0, 257); + nax = numaMakeSequence(15.0, (250.0 - 15.0) / 23.0, 24); + n = numaGetCount(nax); + nay = numaCreate(n); + for (i = 0; i < n; i++) { + numaGetFValue(nax, i, &xval); + numaInterpolateArbxVal(nasx, nasy, L_QUADRATIC_INTERP, xval, &yval); + numaAddNumber(nay, yval); + } + pix5 = gplotGeneralPix2(nax, nay, GPLOT_LINES, "/tmp/lept/numa1/int5", + "arbx interpolation", "pix val", "cum num pix"); + numaDestroy(&na); + numaDestroy(&nasx); + numaDestroy(&nasy); + numaDestroy(&nax); + numaDestroy(&nay); + pixDestroy(&pixs); + + /* Test interpolation */ + nasx = numaRead("testangle.na"); + nasy = numaRead("testscore.na"); + gplot = gplotCreate("/tmp/lept/numa1/int6", GPLOT_PNG, "arbx interpolation", + "angle", "score"); + numaInterpolateArbxInterval(nasx, nasy, L_LINEAR_INTERP, + -2.00, 0.0, 50, &nax, &nay); + gplotAddPlot(gplot, nax, nay, GPLOT_LINES, "linear"); + numaDestroy(&nax); + numaDestroy(&nay); + numaInterpolateArbxInterval(nasx, nasy, L_QUADRATIC_INTERP, + -2.00, 0.0, 50, &nax, &nay); + gplotAddPlot(gplot, nax, nay, GPLOT_LINES, "quadratic"); + numaDestroy(&nax); + numaDestroy(&nay); + pix6 = gplotMakeOutputPix(gplot); + gplotDestroy(&gplot); + gplot = gplotCreate("/tmp/lept/numa1/int7", GPLOT_PNG, "arbx interpolation", + "angle", "score"); + numaInterpolateArbxInterval(nasx, nasy, L_LINEAR_INTERP, + -1.2, -0.8, 50, &nax, &nay); + gplotAddPlot(gplot, nax, nay, GPLOT_LINES, "quadratic"); + pix7 = gplotMakeOutputPix(gplot); + gplotDestroy(&gplot); + numaFitMax(nay, &yval, nax, &xval); + if (rp->display) lept_stderr("max = %f at loc = %f\n", yval, xval); + pixa = pixaCreate(7); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 11 */ + regTestWritePixAndCheck(rp, pix2, IFF_PNG); /* 12 */ + regTestWritePixAndCheck(rp, pix3, IFF_PNG); /* 13 */ + regTestWritePixAndCheck(rp, pix4, IFF_PNG); /* 14 */ + regTestWritePixAndCheck(rp, pix5, IFF_PNG); /* 15 */ + regTestWritePixAndCheck(rp, pix6, IFF_PNG); /* 16 */ + regTestWritePixAndCheck(rp, pix7, IFF_PNG); /* 17 */ + pixaAddPix(pixa, pix1, L_INSERT); + pixaAddPix(pixa, pix2, L_INSERT); + pixaAddPix(pixa, pix3, L_INSERT); + pixaAddPix(pixa, pix4, L_INSERT); + pixaAddPix(pixa, pix5, L_INSERT); + pixaAddPix(pixa, pix6, L_INSERT); + pixaAddPix(pixa, pix7, L_INSERT); + if (rp->display) { + pixd = pixaDisplayTiledInRows(pixa, 32, 1500, 1.0, 0, 20, 2); + pixDisplayWithTitle(pixd, 300, 0, NULL, 1); + pixDestroy(&pixd); + } + pixaDestroy(&pixa); + numaDestroy(&nasx); + numaDestroy(&nasy); + numaDestroy(&nax); + numaDestroy(&nay); + + /* -------------------------------------------------------------------* + * Integration and differentiation * + * -------------------------------------------------------------------*/ + /* Test integration and differentiation */ + nasx = numaRead("testangle.na"); + nasy = numaRead("testscore.na"); + /* ---------- Plot the derivative ---------- */ + numaDifferentiateInterval(nasx, nasy, -2.0, 0.0, 50, &nadx, &nady); + pix1 = gplotGeneralPix2(nadx, nady, GPLOT_LINES, "/tmp/lept/numa1/diff1", + "derivative", "angle", "slope"); + /* ---------- Plot the original function ----------- */ + /* and the integral of the derivative; the two */ + /* should be approximately the same. */ + gplot = gplotCreate("/tmp/lept/numa1/diff2", GPLOT_PNG, "integ-diff", + "angle", "val"); + numaInterpolateArbxInterval(nasx, nasy, L_LINEAR_INTERP, + -2.00, 0.0, 50, &nafx, &nafy); + gplotAddPlot(gplot, nafx, nafy, GPLOT_LINES, "function"); + n = numaGetCount(nadx); + numaGetFValue(nafx, 0, &x0); + numaGetFValue(nafy, 0, &y0); + nay = numaCreate(n); + /* (Note: this tests robustness of the integrator: we go from + * i = 0, and choose to have only 1 point in the interpolation + * there, which is too small and causes the function to bomb out.) */ + lept_stderr("******************************************************\n"); + lept_stderr("* Testing error checking: ignore 'npts < 2' error *\n"); + for (i = 0; i < n; i++) { + numaGetFValue(nadx, i, &xval); + numaIntegrateInterval(nadx, nady, x0, xval, 2 * i + 1, &yval); + numaAddNumber(nay, y0 + yval); + } + lept_stderr("******************************************************\n"); + gplotAddPlot(gplot, nafx, nay, GPLOT_LINES, "anti-derivative"); + pix2 = gplotMakeOutputPix(gplot); + gplotDestroy(&gplot); + pixa = pixaCreate(2); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 18 */ + regTestWritePixAndCheck(rp, pix2, IFF_PNG); /* 19 */ + pixaAddPix(pixa, pix1, L_INSERT); + pixaAddPix(pixa, pix2, L_INSERT); + if (rp->display) { + pixd = pixaDisplayTiledInRows(pixa, 32, 1500, 1.0, 0, 20, 2); + pixDisplayWithTitle(pixd, 600, 0, NULL, 1); + pixDestroy(&pixd); + } + pixaDestroy(&pixa); + numaDestroy(&nasx); + numaDestroy(&nasy); + numaDestroy(&nafx); + numaDestroy(&nafy); + numaDestroy(&nadx); + numaDestroy(&nady); + numaDestroy(&nay); + return regTestCleanup(rp); +} diff --git a/leptonica/prog/numa2_reg.c b/leptonica/prog/numa2_reg.c new file mode 100644 index 00000000..34786893 --- /dev/null +++ b/leptonica/prog/numa2_reg.c @@ -0,0 +1,490 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * numa_reg2.c + * + * Tests: + * * numa windowed stats + * * numa extraction from pix on a line + * * pixel averages and variances + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include <math.h> +#include "allheaders.h" + +#define DO_ALL 0 + +/* Tiny helper */ +void SaveColorSquare(PIXA *pixa, l_uint32 rgbval); + + +int main(int argc, + char **argv) +{ +l_int32 i, j; +l_int32 w, h, bw, bh, wpls, rval, gval, bval, same; +l_uint32 pixel, avergb; +l_uint32 *lines, *datas; +l_float32 sum1, sum2, ave1, ave2, ave3, ave4, diff1, diff2; +l_float32 var1, var2, var3; +BOX *box1, *box2, *box3; +NUMA *na, *na1, *na2, *na3, *na4; +PIX *pixs, *pix1, *pix2, *pix3, *pix4, *pix5, *pix6, *pixg, *pixd; +PIXA *pixa1; +L_REGPARAMS *rp; + +#if !defined(HAVE_LIBPNG) + L_ERROR("This test requires libpng to run.\n", "numa2_reg"); + exit(77); +#endif + + if (regTestSetup(argc, argv, &rp)) + return 1; + + lept_mkdir("lept/numa2"); + + /* -------------------------------------------------------------------* + * Numa-windowed stats * + * -------------------------------------------------------------------*/ + na = numaRead("lyra.5.na"); + numaWindowedStats(na, 5, &na1, &na2, &na3, &na4); + gplotSimple1(na, GPLOT_PNG, "/tmp/lept/numa2/lyra1", "Original"); + gplotSimple1(na1, GPLOT_PNG, "/tmp/lept/numa2/lyra2", "Mean"); + gplotSimple1(na2, GPLOT_PNG, "/tmp/lept/numa2/lyra3", "Mean Square"); + gplotSimple1(na3, GPLOT_PNG, "/tmp/lept/numa2/lyra4", "Variance"); + gplotSimple1(na4, GPLOT_PNG, "/tmp/lept/numa2/lyra5", "RMS Difference"); + pix1 = pixRead("/tmp/lept/numa2/lyra1.png"); + pix2 = pixRead("/tmp/lept/numa2/lyra2.png"); + pix3 = pixRead("/tmp/lept/numa2/lyra3.png"); + pix4 = pixRead("/tmp/lept/numa2/lyra4.png"); + pix5 = pixRead("/tmp/lept/numa2/lyra5.png"); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 0 */ + regTestWritePixAndCheck(rp, pix2, IFF_PNG); /* 1 */ + regTestWritePixAndCheck(rp, pix3, IFF_PNG); /* 2 */ + regTestWritePixAndCheck(rp, pix4, IFF_PNG); /* 3 */ + regTestWritePixAndCheck(rp, pix5, IFF_PNG); /* 4 */ + pixa1 = pixaCreate(5); + pixaAddPix(pixa1, pix1, L_INSERT); + pixaAddPix(pixa1, pix2, L_INSERT); + pixaAddPix(pixa1, pix3, L_INSERT); + pixaAddPix(pixa1, pix4, L_INSERT); + pixaAddPix(pixa1, pix5, L_INSERT); + if (rp->display) { + pixd = pixaDisplayTiledInRows(pixa1, 32, 1500, 1.0, 0, 20, 2); + pixDisplayWithTitle(pixd, 0, 0, NULL, 1); + pixDestroy(&pixd); + } + pixaDestroy(&pixa1); + numaDestroy(&na); + numaDestroy(&na1); + numaDestroy(&na2); + numaDestroy(&na3); + numaDestroy(&na4); + + /* -------------------------------------------------------------------* + * Extraction on a line * + * -------------------------------------------------------------------*/ + /* First, make a pretty image */ + w = h = 200; + pixs = pixCreate(w, h, 32); + wpls = pixGetWpl(pixs); + datas = pixGetData(pixs); + for (i = 0; i < 200; i++) { + lines = datas + i * wpls; + for (j = 0; j < 200; j++) { + rval = (l_int32)((255. * j) / w + (255. * i) / h); + gval = (l_int32)((255. * 2 * j) / w + (255. * 2 * i) / h) % 255; + bval = (l_int32)((255. * 4 * j) / w + (255. * 4 * i) / h) % 255; + composeRGBPixel(rval, gval, bval, &pixel); + lines[j] = pixel; + } + } + pixg = pixConvertTo8(pixs, 0); /* and a grayscale version */ + regTestWritePixAndCheck(rp, pixg, IFF_PNG); /* 5 */ + pixDisplayWithTitle(pixg, 0, 300, NULL, rp->display); + + na1 = pixExtractOnLine(pixg, 20, 20, 180, 20, 1); + na2 = pixExtractOnLine(pixg, 40, 30, 40, 170, 1); + na3 = pixExtractOnLine(pixg, 20, 170, 180, 30, 1); + na4 = pixExtractOnLine(pixg, 20, 190, 180, 10, 1); + gplotSimple1(na1, GPLOT_PNG, "/tmp/lept/numa2/ext1", "Horizontal"); + gplotSimple1(na2, GPLOT_PNG, "/tmp/lept/numa2/ext2", "Vertical"); + gplotSimple1(na3, GPLOT_PNG, "/tmp/lept/numa2/ext3", + "Slightly more horizontal than vertical"); + gplotSimple1(na4, GPLOT_PNG, "/tmp/lept/numa2/ext4", + "Slightly more vertical than horizontal"); + pix1 = pixRead("/tmp/lept/numa2/ext1.png"); + pix2 = pixRead("/tmp/lept/numa2/ext2.png"); + pix3 = pixRead("/tmp/lept/numa2/ext3.png"); + pix4 = pixRead("/tmp/lept/numa2/ext4.png"); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 6 */ + regTestWritePixAndCheck(rp, pix2, IFF_PNG); /* 7 */ + regTestWritePixAndCheck(rp, pix3, IFF_PNG); /* 8 */ + regTestWritePixAndCheck(rp, pix4, IFF_PNG); /* 9 */ + pixa1 = pixaCreate(4); + pixaAddPix(pixa1, pix1, L_INSERT); + pixaAddPix(pixa1, pix2, L_INSERT); + pixaAddPix(pixa1, pix3, L_INSERT); + pixaAddPix(pixa1, pix4, L_INSERT); + if (rp->display) { + pixd = pixaDisplayTiledInRows(pixa1, 32, 1500, 1.0, 0, 20, 2); + pixDisplayWithTitle(pixd, 300, 0, NULL, 1); + pixDestroy(&pixd); + } + pixaDestroy(&pixa1); + pixDestroy(&pixg); + pixDestroy(&pixs); + numaDestroy(&na1); + numaDestroy(&na2); + numaDestroy(&na3); + numaDestroy(&na4); + + /* -------------------------------------------------------------------* + * Row and column pixel sums * + * -------------------------------------------------------------------*/ + /* Sum by columns in two halves (left and right) */ + pixs = pixRead("test8.jpg"); + pixGetDimensions(pixs, &w, &h, NULL); + box1 = boxCreate(0, 0, w / 2, h); + box2 = boxCreate(w / 2, 0, w - 2 / 2, h); + na1 = pixAverageByColumn(pixs, box1, L_BLACK_IS_MAX); + na2 = pixAverageByColumn(pixs, box2, L_BLACK_IS_MAX); + numaJoin(na1, na2, 0, -1); + na3 = pixAverageByColumn(pixs, NULL, L_BLACK_IS_MAX); + numaSimilar(na1, na3, 0.0, &same); /* for columns */ + regTestCompareValues(rp, 1, same, 0); /* 10 */ + pix1 = pixConvertTo32(pixs); + pixRenderPlotFromNumaGen(&pix1, na3, L_HORIZONTAL_LINE, 3, h / 2, 80, 1, + 0xff000000); + pixRenderPlotFromNuma(&pix1, na3, L_PLOT_AT_BOT, 3, 80, 0xff000000); + boxDestroy(&box1); + boxDestroy(&box2); + numaDestroy(&na1); + numaDestroy(&na2); + numaDestroy(&na3); + + /* Sum by rows in two halves (top and bottom) */ + box1 = boxCreate(0, 0, w, h / 2); + box2 = boxCreate(0, h / 2, w, h - h / 2); + na1 = pixAverageByRow(pixs, box1, L_WHITE_IS_MAX); + na2 = pixAverageByRow(pixs, box2, L_WHITE_IS_MAX); + numaJoin(na1, na2, 0, -1); + na3 = pixAverageByRow(pixs, NULL, L_WHITE_IS_MAX); + numaSimilar(na1, na3, 0.0, &same); /* for rows */ + regTestCompareValues(rp, 1, same, 0); /* 11 */ + pixRenderPlotFromNumaGen(&pix1, na3, L_VERTICAL_LINE, 3, w / 2, 80, 1, + 0x00ff0000); + pixRenderPlotFromNuma(&pix1, na3, L_PLOT_AT_RIGHT, 3, 80, 0x00ff0000); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 12 */ + pixDisplayWithTitle(pix1, 0, 600, NULL, rp->display); + pixDestroy(&pix1); + boxDestroy(&box1); + boxDestroy(&box2); + numaDestroy(&na1); + numaDestroy(&na2); + numaDestroy(&na3); + + /* Average left by rows; right by columns; compare totals */ + box1 = boxCreate(0, 0, w / 2, h); + box2 = boxCreate(w / 2, 0, w - 2 / 2, h); + na1 = pixAverageByRow(pixs, box1, L_WHITE_IS_MAX); + na2 = pixAverageByColumn(pixs, box2, L_WHITE_IS_MAX); + numaGetSum(na1, &sum1); /* sum of averages of left box */ + numaGetSum(na2, &sum2); /* sum of averages of right box */ + ave1 = sum1 / h; + ave2 = 2.0 * sum2 / w; + ave3 = 0.5 * (ave1 + ave2); /* average over both halves */ + regTestCompareValues(rp, 189.59, ave1, 0.01); /* 13 */ + regTestCompareValues(rp, 207.89, ave2, 0.01); /* 14 */ + + if (rp->display) { + lept_stderr("ave1 = %8.4f\n", sum1 / h); + lept_stderr("ave2 = %8.4f\n", 2.0 * sum2 / w); + } + pixAverageInRect(pixs, NULL, NULL, 0, 255, 1, &ave4); /* entire image */ + diff1 = ave4 - ave3; + diff2 = w * h * ave4 - (0.5 * w * sum1 + h * sum2); + regTestCompareValues(rp, 0.0, diff1, 0.001); /* 15 */ + regTestCompareValues(rp, 10.0, diff2, 10.0); /* 16 */ + + /* Variance left and right halves. Variance doesn't average + * in a simple way, unlike pixel sums. */ + pixVarianceInRect(pixs, box1, &var1); /* entire image */ + pixVarianceInRect(pixs, box2, &var2); /* entire image */ + pixVarianceInRect(pixs, NULL, &var3); /* entire image */ + regTestCompareValues(rp, 82.06, 0.5 * (var1 + var2), 0.01); /* 17 */ + regTestCompareValues(rp, 82.66, var3, 0.01); /* 18 */ + boxDestroy(&box1); + boxDestroy(&box2); + numaDestroy(&na1); + numaDestroy(&na2); + + /* -------------------------------------------------------------------* + * Row and column variances * + * -------------------------------------------------------------------*/ + /* Display variance by rows and columns */ + box1 = boxCreate(415, 0, 130, 425); + boxGetGeometry(box1, NULL, NULL, &bw, &bh); + na1 = pixVarianceByRow(pixs, box1); + na2 = pixVarianceByColumn(pixs, box1); + pix1 = pixConvertTo32(pixs); + pix2 = pixCopy(NULL, pix1); + pixRenderPlotFromNumaGen(&pix1, na1, L_VERTICAL_LINE, 3, 415, 100, 1, + 0xff000000); + pixRenderPlotFromNumaGen(&pix1, na2, L_HORIZONTAL_LINE, 3, bh / 2, 100, 1, + 0x00ff0000); + pixRenderPlotFromNuma(&pix2, na1, L_PLOT_AT_LEFT, 3, 60, 0x00ff0000); + pixRenderPlotFromNuma(&pix2, na1, L_PLOT_AT_MID_VERT, 3, 60, 0x0000ff00); + pixRenderPlotFromNuma(&pix2, na1, L_PLOT_AT_RIGHT, 3, 60, 0xff000000); + pixRenderPlotFromNuma(&pix2, na2, L_PLOT_AT_TOP, 3, 60, 0x0000ff00); + pixRenderPlotFromNuma(&pix2, na2, L_PLOT_AT_MID_HORIZ, 3, 60, 0xff000000); + pixRenderPlotFromNuma(&pix2, na2, L_PLOT_AT_BOT, 3, 60, 0x00ff0000); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 19 */ + regTestWritePixAndCheck(rp, pix2, IFF_PNG); /* 20 */ + pixa1 = pixaCreate(2); + pixaAddPix(pixa1, pix1, L_INSERT); + pixaAddPix(pixa1, pix2, L_INSERT); + if (rp->display) { + pixd = pixaDisplayTiledInRows(pixa1, 32, 1500, 1.0, 0, 20, 2); + pixDisplayWithTitle(pixd, 400, 600, NULL, 1); + pixDestroy(&pixd); + } + pixaDestroy(&pixa1); + boxDestroy(&box1); + numaDestroy(&na1); + numaDestroy(&na2); + pixDestroy(&pixs); + + /* Again on a different image */ + pix1 = pixRead("boxedpage.jpg"); + pix2 = pixConvertTo8(pix1, 0); + pixGetDimensions(pix2, &w, &h, NULL); + na1 = pixVarianceByRow(pix2, NULL); + pix3 = pixConvertTo32(pix1); + pixRenderPlotFromNumaGen(&pix3, na1, L_VERTICAL_LINE, 3, 0, 70, 1, + 0xff000000); + na2 = pixVarianceByColumn(pix2, NULL); + pixRenderPlotFromNumaGen(&pix3, na2, L_HORIZONTAL_LINE, 3, bh - 1, 70, 1, + 0x00ff0000); + regTestWritePixAndCheck(rp, pix3, IFF_PNG); /* 21 */ + numaDestroy(&na1); + numaDestroy(&na2); + + /* Again, with an erosion */ + pix4 = pixErodeGray(pix2, 3, 21); + na1 = pixVarianceByRow(pix4, NULL); + pix5 = pixConvertTo32(pix1); + pixRenderPlotFromNumaGen(&pix5, na1, L_VERTICAL_LINE, 3, 30, 70, 1, + 0xff000000); + na2 = pixVarianceByColumn(pix4, NULL); + pixRenderPlotFromNumaGen(&pix5, na2, L_HORIZONTAL_LINE, 3, bh - 1, 70, 1, + 0x00ff0000); + regTestWritePixAndCheck(rp, pix5, IFF_PNG); /* 22 */ + pixa1 = pixaCreate(2); + pixaAddPix(pixa1, pix3, L_INSERT); + pixaAddPix(pixa1, pix5, L_INSERT); + if (rp->display) { + pixd = pixaDisplayTiledInRows(pixa1, 32, 1500, 1.0, 0, 20, 2); + pixDisplayWithTitle(pixd, 800, 600, NULL, 1); + pixDestroy(&pixd); + } + pixaDestroy(&pixa1); + pixDestroy(&pix1); + pixDestroy(&pix2); + pixDestroy(&pix4); + numaDestroy(&na1); + numaDestroy(&na2); + + /* -------------------------------------------------------------------* + * Windowed variance along a line * + * -------------------------------------------------------------------*/ + pix1 = pixRead("boxedpage.jpg"); + pix2 = pixConvertTo8(pix1, 0); + pixGetDimensions(pix2, &w, &h, NULL); + pix3 = pixCopy(NULL, pix1); + + /* Plot along horizontal line */ + pixWindowedVarianceOnLine(pix2, L_HORIZONTAL_LINE, h / 2 - 30, 0, + w, 5, &na1); + pixRenderPlotFromNumaGen(&pix1, na1, L_HORIZONTAL_LINE, 3, h / 2 - 30, + 80, 1, 0xff000000); + pixRenderPlotFromNuma(&pix3, na1, L_PLOT_AT_TOP, 3, 60, 0x00ff0000); + pixRenderPlotFromNuma(&pix3, na1, L_PLOT_AT_BOT, 3, 60, 0x0000ff00); + + /* Plot along vertical line */ + pixWindowedVarianceOnLine(pix2, L_VERTICAL_LINE, 0.78 * w, 0, + h, 5, &na2); + pixRenderPlotFromNumaGen(&pix1, na2, L_VERTICAL_LINE, 3, 0.78 * w, 60, + 1, 0x00ff0000); + pixRenderPlotFromNuma(&pix3, na2, L_PLOT_AT_LEFT, 3, 60, 0xff000000); + pixRenderPlotFromNuma(&pix3, na2, L_PLOT_AT_RIGHT, 3, 60, 0x00ff0000); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 23 */ + regTestWritePixAndCheck(rp, pix3, IFF_PNG); /* 24 */ + pixa1 = pixaCreate(2); + pixaAddPix(pixa1, pix1, L_INSERT); + pixaAddPix(pixa1, pix3, L_INSERT); + if (rp->display) { + pixd = pixaDisplayTiledInRows(pixa1, 32, 1500, 1.0, 0, 20, 2); + pixDisplayWithTitle(pixd, 1200, 600, NULL, 1); + pixDestroy(&pixd); + } + pixaDestroy(&pixa1); + pixDestroy(&pix2); + numaDestroy(&na1); + numaDestroy(&na2); + + /* -------------------------------------------------------------------* + * Test pixel average function for gray * + * -------------------------------------------------------------------*/ + pix1 = pixRead("lyra.005.jpg"); + pix2 = pixConvertRGBToLuminance(pix1); + box1 = boxCreate(20, 150, 700, 515); + pix3 = pixClipRectangle(pix2, box1, NULL); + /* No mask, no box, different subsampling */ + pixAverageInRect(pix3, NULL, NULL, 0, 255, 1, &ave1); /* no mask */ + regTestCompareValues(rp, 176.97, ave1, 0.1); /* 25 */ + if (rp->display) lept_stderr("ave1 = %6.2f\n", ave1); + pixAverageInRect(pix3, NULL, NULL, 0, 255, 2, &ave2); /* no mask */ + regTestCompareValues(rp, ave1, ave2, 0.1); /* 26 */ + if (rp->display) lept_stderr("ave2 = %6.2f\n", ave2); + /* Mask allows bg, no box */ + pix4 = pixThresholdToBinary(pix3, 80); /* use light pixels */ + pixAverageInRect(pix3, pix4, NULL, 0, 255, 1, &ave1); /* mask bg */ + regTestCompareValues(rp, 187.58, ave1, 0.1); /* 27 */ + if (rp->display) lept_stderr("ave = %6.2f\n", ave1); + /* Mask allows fg, no box */ + pixInvert(pix4, pix4); /* use dark pixels */ + pixAverageInRect(pix3, pix4, NULL, 0, 255, 1, &ave1); /* mask fg */ + regTestCompareValues(rp, 46.37, ave1, 0.1); /* 28 */ + if (rp->display) lept_stderr("ave = %6.2f\n", ave1); + /* Mask allows fg, no box, restricted range with samples */ + pixAverageInRect(pix3, pix4, NULL, 50, 60, 1, &ave1); /* mask fg */ + regTestCompareValues(rp, 55.18, ave1, 0.1); /* 29 */ + if (rp->display) lept_stderr("ave = %6.2f\n", ave1); + /* Mask allows fg, no box, restricted range without samples */ + pixAverageInRect(pix3, pix4, NULL, 100, 255, 1, &ave1); + regTestCompareValues(rp, 0.0, ave1, 0.0); /* 30 */ /* mask fg */ + if (rp->display) lept_stderr("ave = %6.2f\n", ave1); + /* No mask, use box */ + box2 = boxCreate(100, 100, 200, 150); + pixAverageInRect(pix3, NULL, box2, 0, 255, 1, &ave1); /* no mask */ + regTestCompareValues(rp, 165.63, ave1, 0.1); /* 31 */ + if (rp->display) lept_stderr("ave1 = %6.2f\n", ave1); + /* No mask, pix cropped to box */ + pixInvert(pix4, pix4); /* use light pixels */ + pix5 = pixClipRectangle(pix3, box2, NULL); + pixAverageInRect(pix5, NULL, NULL, 0, 255, 1, &ave2); /* no mask */ + regTestCompareValues(rp, ave1, ave2, 0.1); /* 32 */ + if (rp->display) lept_stderr("ave2 = %6.2f\n", ave2); + /* Mask allows bg, use box */ + pixAverageInRect(pix3, pix4, box2, 0, 255, 1, &ave1); /* mask bg */ + regTestCompareValues(rp, 175.65, ave1, 0.1); /* 33 */ + if (rp->display) lept_stderr("ave1 = %6.2f\n", ave1); + /* Cropped mask allows bg, pix cropped to box */ + pix6 = pixThresholdToBinary(pix5, 80); /* use light pixels */ + pixAverageInRect(pix5, pix6, NULL, 0, 255, 1, &ave2); + regTestCompareValues(rp, ave1, ave2, 0.1); /* 34 */ + if (rp->display) lept_stderr("ave2 = %6.2f\n", ave2); + /* Mask allows bg, use box, restricted range */ + pixAverageInRect(pix3, pix4, box2, 100, 125, 1, &ave1); + regTestCompareValues(rp, 112.20, ave1, 0.1); /* 35 */ + if (rp->display) lept_stderr("ave = %6.2f\n", ave1); + /* Cropped mask allows bg, pix cropped to box, restricted range */ + pixAverageInRect(pix5, pix6, NULL, 100, 125, 1, &ave2); + regTestCompareValues(rp, ave1, ave2, 0.1); /* 36 */ + if (rp->display) lept_stderr("ave = %6.2f\n", ave2); + pixDestroy(&pix1); + pixDestroy(&pix2); + pixDestroy(&pix3); + pixDestroy(&pix4); + pixDestroy(&pix5); + pixDestroy(&pix6); + boxDestroy(&box1); + boxDestroy(&box2); + + /* -------------------------------------------------------------------* + * Test pixel average function for color * + * -------------------------------------------------------------------*/ + pix1 = pixRead("lyra.005.jpg"); + box1 = boxCreate(20, 150, 700, 515); + pix2 = pixClipRectangle(pix1, box1, NULL); + pixa1 = pixaCreate(0); + /* No mask, no box, different subsampling */ + pixAverageInRectRGB(pix2, NULL, NULL, 1, &avergb); + regTestCompareValues(rp, 0xc7b09000, avergb, 0); /* 37 */ + SaveColorSquare(pixa1, avergb); + pixAverageInRectRGB(pix2, NULL, NULL, 10, &avergb); + regTestCompareValues(rp, 0xc7af8f00, avergb, 0); /* 38 */ + SaveColorSquare(pixa1, avergb); + /* Mask allows bg, no box */ + pix3 = pixConvertTo1(pix2, 128); /* use light pixels */ + pixAverageInRectRGB(pix2, pix3, NULL, 1, &avergb); + regTestCompareValues(rp, 0xd5bf9d00, avergb, 0); /* 39 */ + SaveColorSquare(pixa1, avergb); + /* Mask allows fg, no box */ + pixInvert(pix3, pix3); /* use dark pixels */ + pixAverageInRectRGB(pix2, pix3, NULL, 1, &avergb); + regTestCompareValues(rp, 0x5c3b2800, avergb, 0); /* 40 */ + SaveColorSquare(pixa1, avergb); + /* Mask allows bg, box at lower left */ + pixInvert(pix3, pix3); /* use light pixels */ + box2 = boxCreate(20, 400, 100, 100); + pixAverageInRectRGB(pix2, pix3, box2, 1, &avergb); + regTestCompareValues(rp, 0xbba48500, avergb, 0); /* 41 */ + SaveColorSquare(pixa1, avergb); + /* Mask allows bg, box at upper right */ + box3 = boxCreate(600, 20, 100, 100); + pixAverageInRectRGB(pix2, pix3, box3, 1, &avergb); + regTestCompareValues(rp, 0xfdfddd00, avergb, 0); /* 42 */ + SaveColorSquare(pixa1, avergb); + if (rp->display) { + pix4 = pixaDisplayTiledInRows(pixa1, 32, 1500, 1.0, 0, 20, 2); + pixDisplay(pix4, 0, 800); + pixDestroy(&pix4); + } + pixDestroy(&pix1); + pixDestroy(&pix2); + pixDestroy(&pix3); + boxDestroy(&box1); + boxDestroy(&box2); + boxDestroy(&box3); + pixaDestroy(&pixa1); + + return regTestCleanup(rp);; +} + + +void SaveColorSquare(PIXA *pixa, + l_uint32 rgbval) { + PIX *pixc = pixMakeColorSquare(rgbval, 0, 1, L_ADD_BELOW, 0xff000000); + pixaAddPix(pixa, pixc, L_INSERT); +} + diff --git a/leptonica/prog/numa3_reg.c b/leptonica/prog/numa3_reg.c new file mode 100644 index 00000000..826fe36a --- /dev/null +++ b/leptonica/prog/numa3_reg.c @@ -0,0 +1,215 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * numa3_reg.c + * + * Tests: + * * rank extraction + * * numa-morphology + * * find threshold from numa + * * insertion in sorted array + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include <math.h> +#include "allheaders.h" + +int main(int argc, + char **argv) +{ +char buf1[64], buf2[64]; +l_int32 i, n, hw, thresh, same, ival; +l_float32 val, maxval, rank; +NUMA *na, *nax, *nay, *nap, *nasy, *na1, *na2, *na3, *na4; +PIX *pixs, *pix1, *pix2, *pix3, *pix4, *pix5, *pixd; +PIXA *pixa; +L_REGPARAMS *rp; + +#if !defined(HAVE_LIBPNG) + L_ERROR("This test requires libpng to run.\n", "numa3_reg"); + exit(77); +#endif + + if (regTestSetup(argc, argv, &rp)) + return 1; + + lept_mkdir("lept/numa3"); + + /* -------------------------------------------------------------------* + * Rank extraction * + * -------------------------------------------------------------------*/ + /* Rank extraction with interpolation */ + pixs = pixRead("test8.jpg"); + nasy= pixGetGrayHistogramMasked(pixs, NULL, 0, 0, 1); + numaMakeRankFromHistogram(0.0, 1.0, nasy, 350, &nax, &nay); + pix1 = gplotGeneralPix2(nax, nay, GPLOT_LINES, "/tmp/lept/numa1/rank1", + "test rank extractor", "pix val", "rank val"); + numaDestroy(&nasy); + numaDestroy(&nax); + numaDestroy(&nay); + pixDestroy(&pixs); + + /* Rank extraction, point by point */ + pixs = pixRead("test8.jpg"); + nap = numaCreate(200); + pixGetRankValueMasked(pixs, NULL, 0, 0, 2, 0.0, &val, &na); + for (i = 0; i < 101; i++) { + rank = 0.01 * i; + numaHistogramGetValFromRank(na, rank, &val); + numaAddNumber(nap, val); + } + pix2 = gplotGeneralPix1(nap, GPLOT_LINES, "/tmp/lept/numa1/rank2", + "rank value", NULL, NULL); + pixa = pixaCreate(2); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 0 */ + regTestWritePixAndCheck(rp, pix2, IFF_PNG); /* 1 */ + pixaAddPix(pixa, pix1, L_INSERT); + pixaAddPix(pixa, pix2, L_INSERT); + if (rp->display) { + pixd = pixaDisplayTiledInRows(pixa, 32, 1500, 1.0, 0, 20, 2); + pixDisplayWithTitle(pixd, 900, 0, NULL, 1); + pixDestroy(&pixd); + } + pixaDestroy(&pixa); + numaDestroy(&na); + numaDestroy(&nap); + pixDestroy(&pixs); + + /* -------------------------------------------------------------------* + * Numa-morphology * + * -------------------------------------------------------------------*/ + na = numaRead("lyra.5.na"); + pix1 = gplotGeneralPix1(na, GPLOT_LINES, "/tmp/lept/numa1/lyra1", + "Original", NULL, NULL); + na1 = numaErode(na, 21); + pix2 = gplotGeneralPix1(na1, GPLOT_LINES, "/tmp/lept/numa1/lyra2", + "Erosion", NULL, NULL); + na2 = numaDilate(na, 21); + pix3 = gplotGeneralPix1(na2, GPLOT_LINES, "/tmp/lept/numa1/lyra3", + "Dilation", NULL, NULL); + na3 = numaOpen(na, 21); + pix4 = gplotGeneralPix1(na3, GPLOT_LINES, "/tmp/lept/numa1/lyra4", + "Opening", NULL, NULL); + na4 = numaClose(na, 21); + pix5 = gplotGeneralPix1(na4, GPLOT_LINES, "/tmp/lept/numa1/lyra5", + "Closing", NULL, NULL); + pixa = pixaCreate(2); + pixaAddPix(pixa, pix1, L_INSERT); + pixaAddPix(pixa, pix2, L_INSERT); + pixaAddPix(pixa, pix3, L_INSERT); + pixaAddPix(pixa, pix4, L_INSERT); + pixaAddPix(pixa, pix5, L_INSERT); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 2 */ + regTestWritePixAndCheck(rp, pix2, IFF_PNG); /* 3 */ + regTestWritePixAndCheck(rp, pix3, IFF_PNG); /* 4 */ + regTestWritePixAndCheck(rp, pix4, IFF_PNG); /* 5 */ + regTestWritePixAndCheck(rp, pix5, IFF_PNG); /* 6 */ + if (rp->display) { + pixd = pixaDisplayTiledInRows(pixa, 32, 1500, 1.0, 0, 20, 2); + pixDisplayWithTitle(pixd, 1200, 0, NULL, 1); + pixDestroy(&pixd); + } + pixaDestroy(&pixa); + numaDestroy(&na); + numaDestroy(&na1); + numaDestroy(&na2); + numaDestroy(&na3); + numaDestroy(&na4); + pixaDestroy(&pixa); + + /* -------------------------------------------------------------------* + * Find threshold from numa * + * -------------------------------------------------------------------*/ + na1 = numaRead("two-peak-histo.na"); + na4 = numaCreate(0); + pixa = pixaCreate(0); + for (hw = 2; hw < 21; hw += 2) { + na2 = numaWindowedMean(na1, hw); /* smoothing */ + numaGetMax(na2, &maxval, NULL); + na3 = numaTransform(na2, 0.0, 1.0 / maxval); + numaFindLocForThreshold(na3, 0, &thresh, NULL); + numaAddNumber(na4, thresh); + snprintf(buf1, sizeof(buf1), "/tmp/lept/numa1/histoplot-%d", hw); + snprintf(buf2, sizeof(buf2), "halfwidth = %d, skip = 20, thresh = %d", + hw, thresh); + pix1 = gplotGeneralPix1(na3, GPLOT_LINES, buf1, buf2, NULL, NULL); + if (hw == 4 || hw == 20) + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 7, 8 */ + pixaAddPix(pixa, pix1, L_INSERT); + numaDestroy(&na2); + numaDestroy(&na3); + } + numaWrite("/tmp/lept/numa1/threshvals.na", na4); + regTestCheckFile(rp, "/tmp/lept/numa1/threshvals.na"); /* 9 */ + L_INFO("writing /tmp/lept/numa1/histoplots.pdf\n", "numa1_reg"); + pixaConvertToPdf(pixa, 0, 1.0, L_FLATE_ENCODE, 0, + "Effect of smoothing on threshold value", + "/tmp/lept/numa1/histoplots.pdf"); + numaDestroy(&na1); + numaDestroy(&na4); + pixaDestroy(&pixa); + + /* -------------------------------------------------------------------* + * Insertion in a sorted array * + * -------------------------------------------------------------------*/ + na1 = numaCreate(0); + srand(5); + numaAddNumber(na1, 27); + numaAddNumber(na1, 13); + for (i = 0; i < 70; i++) { + genRandomIntOnInterval(0, 200, 0, &ival); + numaAddSorted(na1, ival); + } + if (rp->display) numaWriteStderr(na1); + na2 = numaSort(NULL, na1, L_SORT_INCREASING); + numaReverse(na2, na2); + numaSimilar(na1, na2, 0.0, &same); + regTestCompareValues(rp, 1, same, 0.0); /* 10 */ + numaDestroy(&na1); + numaDestroy(&na2); + + na1 = numaCreate(0); + srand(6); + numaAddNumber(na1, 13); + numaAddNumber(na1, 27); + for (i = 0; i < 70; i++) { + genRandomIntOnInterval(0, 200, 0, &ival); + numaAddSorted(na1, ival); + } + if (rp->display) numaWriteStderr(na1); + na2 = numaSort(NULL, na1, L_SORT_DECREASING); + numaReverse(na2, na2); + numaSimilar(na1, na2, 0.0, &same); + regTestCompareValues(rp, 1, same, 0.0); /* 11 */ + numaDestroy(&na1); + numaDestroy(&na2); + + return regTestCleanup(rp); +} diff --git a/leptonica/prog/numaranktest.c b/leptonica/prog/numaranktest.c new file mode 100644 index 00000000..083f0fbc --- /dev/null +++ b/leptonica/prog/numaranktest.c @@ -0,0 +1,97 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * numaranktest.c + * + * Test on 8 bpp grayscale (e.g., w91frag.jpg) + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + +static const l_int32 BIN_SIZE = 1; + +int main(int argc, + char **argv) +{ +char *filein; +l_int32 i, j, w, h, d, sampling; +l_float32 rank, rval; +l_uint32 val; +NUMA *na, *nah, *nar, *nav; +PIX *pix; +static char mainName[] = "numaranktest"; + + if (argc != 3) + return ERROR_INT(" Syntax: numaranktest filein sampling", mainName, 1); + filein = argv[1]; + sampling = atoi(argv[2]); + + setLeptDebugOK(1); + lept_mkdir("lept/numa"); + + if ((pix = pixRead(filein)) == NULL) + return ERROR_INT("pix not made", mainName, 1); + pixGetDimensions(pix, &w, &h, &d); + if (d != 8) + return ERROR_INT("d != 8 bpp", mainName, 1); + + na = numaCreate(0); + for (i = 0; i < h; i += sampling) { + for (j = 0; j < w; j += sampling) { + pixGetPixel(pix, j, i, &val); + numaAddNumber(na, val); + } + } + nah = numaMakeHistogramClipped(na, BIN_SIZE, 255); + + nar = numaCreate(0); + for (rval = 0.0; rval < 256.0; rval += 2.56) { + numaHistogramGetRankFromVal(nah, rval, &rank); + numaAddNumber(nar, rank); + } + gplotSimple1(nar, GPLOT_PNG, "/tmp/lept/numa/rank", "rank vs val"); + l_fileDisplay("/tmp/lept/numa/rank.png", 0, 0, 1.0); + + nav = numaCreate(0); + for (rank = 0.0; rank <= 1.0; rank += 0.01) { + numaHistogramGetValFromRank(nah, rank, &rval); + numaAddNumber(nav, rval); + } + gplotSimple1(nav, GPLOT_PNG, "/tmp/lept/numa/val", "val vs rank"); + l_fileDisplay("/tmp/lept/numa/val.png", 750, 0, 1.0); + + pixDestroy(&pix); + numaDestroy(&na); + numaDestroy(&nah); + numaDestroy(&nar); + numaDestroy(&nav); + return 0; +} diff --git a/leptonica/prog/ortiz-02.tif b/leptonica/prog/ortiz-02.tif Binary files differnew file mode 100644 index 00000000..0609c118 --- /dev/null +++ b/leptonica/prog/ortiz-02.tif diff --git a/leptonica/prog/ortiz-03.tif b/leptonica/prog/ortiz-03.tif Binary files differnew file mode 100644 index 00000000..50a28f08 --- /dev/null +++ b/leptonica/prog/ortiz-03.tif diff --git a/leptonica/prog/ortiz-04.tif b/leptonica/prog/ortiz-04.tif Binary files differnew file mode 100644 index 00000000..1c57a2d1 --- /dev/null +++ b/leptonica/prog/ortiz-04.tif diff --git a/leptonica/prog/ortiz-05.tif b/leptonica/prog/ortiz-05.tif Binary files differnew file mode 100644 index 00000000..98bfa062 --- /dev/null +++ b/leptonica/prog/ortiz-05.tif diff --git a/leptonica/prog/otsutest1.c b/leptonica/prog/otsutest1.c new file mode 100644 index 00000000..1584a51e --- /dev/null +++ b/leptonica/prog/otsutest1.c @@ -0,0 +1,161 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * otsutest1.c + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include <math.h> +#include "allheaders.h" + +static const l_int32 NTests = 5; +static const l_int32 gaussmean1[5] = {20, 40, 60, 80, 60}; +static const l_int32 gaussstdev1[5] = {10, 20, 20, 20, 30}; +static const l_int32 gaussmean2[5] = {220, 200, 140, 180, 150}; +static const l_int32 gaussstdev2[5] = {15, 20, 40, 20, 30}; +static const l_float32 gaussfract1[5] = {0.2f, 0.3f, 0.1f, 0.5f, 0.3f}; +static char buf[256]; + +static l_int32 GenerateSplitPlot(l_int32 i); +static NUMA *MakeGaussian(l_int32 mean, l_int32 stdev, l_float32 fract); + + +int main(int argc, + char **argv) +{ +l_int32 i; +PIX *pix; +PIXA *pixa; + + setLeptDebugOK(1); + lept_mkdir("lept/otsu"); + for (i = 0; i < NTests; i++) + GenerateSplitPlot(i); + + /* Read the results back in ... */ + pixa = pixaCreate(0); + for (i = 0; i < NTests; i++) { + snprintf(buf, sizeof(buf), "/tmp/lept/otsu/plot.%d.png", i); + pix = pixRead(buf); + pixaAddPix(pixa, pix, L_INSERT); + snprintf(buf, sizeof(buf), "/tmp/lept/otsu/plots.%d.png", i); + pix = pixRead(buf); + pixaAddPix(pixa, pix, L_INSERT); + } + + /* ... and save into a tiled pix */ + pix = pixaDisplayTiledInColumns(pixa, 2, 1.0, 25, 0); + pixWrite("/tmp/lept/otsu/plot.png", pix, IFF_PNG); + pixDisplay(pix, 100, 100); + pixaDestroy(&pixa); + pixDestroy(&pix); + return 0; +} + + +static l_int32 +GenerateSplitPlot(l_int32 i) +{ +char title[256]; +l_int32 split; +l_float32 ave1, ave2, num1, num2, maxnum, maxscore; +GPLOT *gplot; +NUMA *na1, *na2, *nascore, *nax, *nay; + + /* Generate a fake histogram composed of 2 gaussians */ + na1 = MakeGaussian(gaussmean1[i], gaussstdev1[i], gaussfract1[i]); + na2 = MakeGaussian(gaussmean2[i], gaussstdev1[i], 1.0 - gaussfract1[i]); + numaArithOp(na1, na1, na2, L_ARITH_ADD); + + /* Otsu splitting */ + numaSplitDistribution(na1, 0.08, &split, &ave1, &ave2, &num1, &num2, + &nascore); + lept_stderr("split = %d, ave1 = %6.1f, ave2 = %6.1f\n", split, ave1, ave2); + lept_stderr("num1 = %8.0f, num2 = %8.0f\n", num1, num2); + + /* Prepare for plotting a vertical line at the split point */ + nax = numaMakeConstant(split, 2); + numaGetMax(na1, &maxnum, NULL); + nay = numaMakeConstant(0, 2); + numaReplaceNumber(nay, 1, (l_int32)(0.5 * maxnum)); + + /* Plot the input histogram with the split location */ + snprintf(buf, sizeof(buf), "/tmp/lept/otsu/plot.%d", i); + snprintf(title, sizeof(title), "Plot %d", i); + gplot = gplotCreate(buf, GPLOT_PNG, + "Histogram: mixture of 2 gaussians", + "Grayscale value", "Number of pixels"); + gplotAddPlot(gplot, NULL, na1, GPLOT_LINES, title); + gplotAddPlot(gplot, nax, nay, GPLOT_LINES, NULL); + gplotMakeOutput(gplot); + gplotDestroy(&gplot); + numaDestroy(&na1); + numaDestroy(&na2); + + /* Plot the score function */ + snprintf(buf, sizeof(buf), "/tmp/lept/otsu/plots.%d", i); + snprintf(title, sizeof(title), "Plot %d", i); + gplot = gplotCreate(buf, GPLOT_PNG, + "Otsu score function for splitting", + "Grayscale value", "Score"); + gplotAddPlot(gplot, NULL, nascore, GPLOT_LINES, title); + numaGetMax(nascore, &maxscore, NULL); + numaReplaceNumber(nay, 1, maxscore); + gplotAddPlot(gplot, nax, nay, GPLOT_LINES, NULL); + gplotMakeOutput(gplot); + gplotDestroy(&gplot); + numaDestroy(&nax); + numaDestroy(&nay); + numaDestroy(&nascore); + return 0; +} + + +static NUMA * +MakeGaussian(l_int32 mean, l_int32 stdev, l_float32 fract) +{ +l_int32 i, total; +l_float32 norm, val; +NUMA *na; + + na = numaMakeConstant(0.0, 256); + norm = fract / ((l_float32)stdev * sqrt(2 * 3.14159)); + total = 0; + for (i = 0; i < 256; i++) { + val = norm * 1000000. * exp(-(l_float32)((i - mean) * (i - mean)) / + (l_float32)(2 * stdev * stdev)); + total += (l_int32)val; + numaSetValue(na, i, val); + } + lept_stderr("Total = %d\n", total); + + return na; +} + diff --git a/leptonica/prog/otsutest2.c b/leptonica/prog/otsutest2.c new file mode 100644 index 00000000..cbe94f45 --- /dev/null +++ b/leptonica/prog/otsutest2.c @@ -0,0 +1,129 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * otsutest2.c + * + * This demonstrates the usefulness of the modified version of Otsu + * for thresholding an image that doesn't have a well-defined + * background color. + * + * Standard Otsu binarization is done with scorefract = 0.0, which + * returns the threshold at the maximum value of the score. However. + * this value is up on the shoulder of the background, and its + * use causes some of the dark background to be binarized as foreground. + * + * Using the modified Otsu with scorefract = 0.1 returns a threshold + * at the lowest value of this histogram such that the score + * is at least 0.9 times the maximum value of the score. This allows + * the threshold to be taken in the histogram minimum between + * the fg and bg peaks, producing a much cleaner binarization. + */ + + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + + +int main(int argc, + char **argv) +{ +char textstr[256]; +l_int32 i, thresh, fgval, bgval; +l_float32 scorefract; +L_BMF *bmf; +PIX *pixs, *pixb, *pixg, *pixp, *pix1, *pix2, *pix3; +PIXA *pixa1, *pixad; + + setLeptDebugOK(1); + lept_mkdir("lept/otsu"); + + pixs = pixRead("1555.007.jpg"); + pixg = pixConvertTo8(pixs, 0); + bmf = bmfCreate(NULL, 8); + pixad = pixaCreate(0); + for (i = 0; i < 3; i++) { + pixa1 = pixaCreate(2); + scorefract = 0.1 * i; + + /* Get a 1 bpp version; use a single tile */ + pixOtsuAdaptiveThreshold(pixg, 2000, 2000, 0, 0, scorefract, + NULL, &pixb); + pixaAddPix(pixa1, pixg, L_COPY); + pixaAddPix(pixa1, pixb, L_INSERT); + + /* Show the histogram of gray values and the split location */ + pixSplitDistributionFgBg(pixg, scorefract, 1, + &thresh, &fgval, &bgval, &pixp); + lept_stderr("thresh = %d, fgval = %d, bgval = %d\n", + thresh, fgval, bgval); + pixaAddPix(pixa1, pixp, L_INSERT); + + /* Join these together and add some text */ + pix1 = pixaDisplayTiledInColumns(pixa1, 3, 1.0, 20, 2); + snprintf(textstr, sizeof(textstr), + "Scorefract = %3.1f ........... Thresh = %d", scorefract, thresh); + pix2 = pixAddSingleTextblock(pix1, bmf, textstr, 0x00ff0000, + L_ADD_BELOW, NULL); + + /* Save and display the result */ + pixaAddPix(pixad, pix2, L_INSERT); + snprintf(textstr, sizeof(textstr), "/tmp/lept/otsu/%03d.png", i); + pixWrite(textstr, pix2, IFF_PNG); + pixDisplay(pix2, 100, 100); + pixDestroy(&pix1); + pixaDestroy(&pixa1); + } + + /* Use a smaller tile for Otsu */ + for (i = 0; i < 2; i++) { + scorefract = 0.1 * i; + pixOtsuAdaptiveThreshold(pixg, 300, 300, 0, 0, scorefract, + NULL, &pixb); + pix1 = pixAddBlackOrWhiteBorder(pixb, 2, 2, 2, 2, L_GET_BLACK_VAL); + pix2 = pixScale(pix1, 0.5, 0.5); + snprintf(textstr, sizeof(textstr), + "Scorefract = %3.1f", scorefract); + pix3 = pixAddSingleTextblock(pix2, bmf, textstr, 1, + L_ADD_BELOW, NULL); + pixaAddPix(pixad, pix3, L_INSERT); + pixDestroy(&pixb); + pixDestroy(&pix1); + pixDestroy(&pix2); + } + + lept_stderr("Writing to: /tmp/lept/otsu/result1.pdf\n"); + pixaConvertToPdf(pixad, 75, 1.0, 0, 0, "Otsu thresholding", + "/tmp/lept/otsu/result1.pdf"); + bmfDestroy(&bmf); + pixDestroy(&pixs); + pixDestroy(&pixg); + pixaDestroy(&pixad); + return 0; +} diff --git a/leptonica/prog/overlap_reg.c b/leptonica/prog/overlap_reg.c new file mode 100644 index 00000000..d24649d0 --- /dev/null +++ b/leptonica/prog/overlap_reg.c @@ -0,0 +1,261 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * overlap_reg.c + * + * Tests functions that combine boxes that overlap into + * their bounding regions. + * + * Also tests the overlap and separation distance between boxes. + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + + /* Determines maximum size of randomly-generated boxes. Note the + * rapid change in results as the maximum box dimension approaches + * the critical size of 28. */ +static const l_float32 maxsize[] = {5.0, 10.0, 15.0, 20.0, 25.0, 26.0, 27.0}; + + /* Alternative implementation; just for fun */ +BOXA *boxaCombineOverlapsAlt(BOXA *boxas); + + +int main(int argc, + char **argv) +{ +l_int32 i, j, n, k, x, y, w, h, result, hovl, hsep, vovl, vsep; +l_uint8 *data; +size_t nbytes; +BOX *box1, *box2; +BOXA *boxa1, *boxa2, *boxa3, *boxa4; +FILE *fp; +PIX *pix1, *pix2, *pix3; +PIXA *pixa1; +L_REGPARAMS *rp; + + if (regTestSetup(argc, argv, &rp)) + return 1; + + /* -------------------------------------------------------- */ + /* Show the result as a kind of percolation problem */ + /* -------------------------------------------------------- */ + for (k = 0; k < 7; k++) { + srand(45617); + pixa1 = pixaCreate(2); + boxa1 = boxaCreate(0); + for (i = 0; i < 500; i++) { + x = (l_int32)(600.0 * (l_float64)rand() / (l_float64)RAND_MAX); + y = (l_int32)(600.0 * (l_float64)rand() / (l_float64)RAND_MAX); + w = (l_int32) + (1.0 + maxsize[k] * (l_float64)rand() / (l_float64)RAND_MAX); + h = (l_int32) + (1.0 + maxsize[k] * (l_float64)rand() / (l_float64)RAND_MAX); + box1 = boxCreate(x, y, w, h); + boxaAddBox(boxa1, box1, L_INSERT); + } + + pix1 = pixCreate(660, 660, 1); + pixRenderBoxa(pix1, boxa1, 2, L_SET_PIXELS); + pixaAddPix(pixa1, pix1, L_INSERT); + boxa2 = boxaCombineOverlaps(boxa1, NULL); + pix2 = pixCreate(660, 660, 1); + pixRenderBoxa(pix2, boxa2, 2, L_SET_PIXELS); + pixaAddPix(pixa1, pix2, L_INSERT); + + pix3 = pixaDisplayTiledInRows(pixa1, 1, 1500, 1.0, 0, 50, 2); + pixDisplayWithTitle(pix3, 100, 100 + 100 * k, NULL, rp->display); + regTestWritePixAndCheck(rp, pix3, IFF_PNG); /* 0 - 6 */ + lept_stderr("Test %d, maxsize = %d: n_init = %d, n_final = %d\n", + k + 1, (l_int32)maxsize[k] + 1, + boxaGetCount(boxa1), boxaGetCount(boxa2)); + pixDestroy(&pix3); + boxaDestroy(&boxa1); + boxaDestroy(&boxa2); + pixaDestroy(&pixa1); + } + + /* -------------------------------------------------------- */ + /* Show for one case, with debugging, and compare with an */ + /* an alternative version. */ + /* -------------------------------------------------------- */ + boxa1 = boxaCreate(0); + pixa1 = pixaCreate(10); + n = 80; + for (i = 0; i < n; i++) { + x = (l_int32)(600.0 * (l_float64)rand() / (l_float64)RAND_MAX); + y = (l_int32)(600.0 * (l_float64)rand() / (l_float64)RAND_MAX); + w = (l_int32) + (10 + 48 * (l_float64)rand() / (l_float64)RAND_MAX); + h = (l_int32) + (10 + 53 * (l_float64)rand() / (l_float64)RAND_MAX); + box1 = boxCreate(x, y, w, h); + boxaAddBox(boxa1, box1, L_INSERT); + } + + boxa2 = boxaCombineOverlaps(boxa1, pixa1); + boxaContainedInBoxa(boxa2, boxa1, &result); /* 7 */ + regTestCompareValues(rp, 1, result, 0); + + pix1 = pixaDisplayTiledInRows(pixa1, 32, 1500, 1.0, 0, 50, 2); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 8 */ + pixDisplayWithTitle(pix1, 600, 0, NULL, rp->display); + pixaDestroy(&pixa1); + pixDestroy(&pix1); + + /* Show the boxa from both functions are identical */ + boxa3 = boxaCombineOverlapsAlt(boxa1); + boxaContainedInBoxa(boxa3, boxa2, &result); + regTestCompareValues(rp, 1, result, 0); /* 9 */ + boxaContainedInBoxa(boxa2, boxa3, &result); + regTestCompareValues(rp, 1, result, 0); /* 10 */ + boxaDestroy(&boxa1); + boxaDestroy(&boxa2); + boxaDestroy(&boxa3); + + /* --------------------------------------------------------- */ + /* Show for two boxa that are greedily munching each other */ + /* --------------------------------------------------------- */ + boxa1 = boxaCreate(0); + boxa2 = boxaCreate(0); + n = 80; + for (i = 0; i < n; i++) { + x = (l_int32)(600.0 * (l_float64)rand() / (l_float64)RAND_MAX); + y = (l_int32)(600.0 * (l_float64)rand() / (l_float64)RAND_MAX); + w = (l_int32) + (10 + 55 * (l_float64)rand() / (l_float64)RAND_MAX); + h = (l_int32) + (10 + 55 * (l_float64)rand() / (l_float64)RAND_MAX); + box1 = boxCreate(x, y, w, h); + if (i < n / 2) + boxaAddBox(boxa1, box1, L_INSERT); + else + boxaAddBox(boxa2, box1, L_INSERT); + } + + pixa1 = pixaCreate(0); + boxaCombineOverlapsInPair(boxa1, boxa2, &boxa3, &boxa4, pixa1); + pix1 = pixaDisplayTiledInRows(pixa1, 32, 1500, 1.0, 0, 50, 2); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 11 */ + pixDisplayWithTitle(pix1, 1200, 0, NULL, rp->display); + pixDestroy(&pix1); + pixaDestroy(&pixa1); + boxaDestroy(&boxa1); + boxaDestroy(&boxa2); + boxaDestroy(&boxa3); + boxaDestroy(&boxa4); + + /* --------------------------------------------------------- */ + /* Test the overlap and separation distance functions */ + /* --------------------------------------------------------- */ + box1 = boxCreate(0, 0, 1, 1); + lept_mkdir("lept/overlap"); + fp = fopenWriteStream("/tmp/lept/overlap/result.dat", "w"); + for (i = 0; i < 3; i++) { /* 9 1x1 boxes on a 3x3 square */ + for (j = 0; j < 3; j++) { + box2 = boxCreate(i, j, 1, 1); + boxOverlapDistance(box1, box2, &hovl, &vovl); + boxSeparationDistance(box1, box2, &hsep, &vsep); + fprintf(fp, "(%d,%d): ovl = (%d,%d); sep = (%d,%d)\n", + i, j, hovl, vovl, hsep, vsep); + boxDestroy(&box2); + } + } + fclose(fp); + data = l_binaryRead("/tmp/lept/overlap/result.dat", &nbytes); + regTestWriteDataAndCheck(rp, data, nbytes, "dat"); /* 12 */ + lept_free(data); + boxDestroy(&box1); + return regTestCleanup(rp); +} + + +/* -------------------------------------------------------------------- * + * Alternative (less elegant) implementation of boxaCombineOverlaps() * + * -------------------------------------------------------------------- */ +BOXA * +boxaCombineOverlapsAlt(BOXA *boxas) +{ +l_int32 i, j, n1, n2, inter, interfound, niters; +BOX *box1, *box2, *box3; +BOXA *boxa1, *boxa2; + + PROCNAME("boxaCombineOverlapsAlt"); + + if (!boxas) + return (BOXA *)ERROR_PTR("boxas not defined", procName, NULL); + + boxa1 = boxaCopy(boxas, L_COPY); + n1 = boxaGetCount(boxa1); + niters = 0; + while (1) { /* loop until no change from previous iteration */ + niters++; + boxa2 = boxaCreate(n1); + for (i = 0; i < n1; i++) { + box1 = boxaGetBox(boxa1, i, L_COPY); + if (i == 0) { + boxaAddBox(boxa2, box1, L_INSERT); + continue; + } + n2 = boxaGetCount(boxa2); + /* Now test box1 against all boxes already put in boxa2. + * If it is found to intersect with an existing box, + * replace that box by the union of the two boxes, + * and break to the outer loop. If no overlap is + * found, add box1 to boxa2. */ + interfound = FALSE; + for (j = 0; j < n2; j++) { + box2 = boxaGetBox(boxa2, j, L_CLONE); + boxIntersects(box1, box2, &inter); + if (inter == 1) { + box3 = boxBoundingRegion(box1, box2); + boxaReplaceBox(boxa2, j, box3); + boxDestroy(&box1); + boxDestroy(&box2); + interfound = TRUE; + break; + } + boxDestroy(&box2); + } + if (interfound == FALSE) + boxaAddBox(boxa2, box1, L_INSERT); + } + + n2 = boxaGetCount(boxa2); + if (n2 == n1) /* we're done */ + break; + + n1 = n2; + boxaDestroy(&boxa1); + boxa1 = boxa2; + } + boxaDestroy(&boxa1); + return boxa2; +} diff --git a/leptonica/prog/pageseg1.tif b/leptonica/prog/pageseg1.tif Binary files differnew file mode 100644 index 00000000..901950bc --- /dev/null +++ b/leptonica/prog/pageseg1.tif diff --git a/leptonica/prog/pageseg2-mask.png b/leptonica/prog/pageseg2-mask.png Binary files differnew file mode 100644 index 00000000..051b8dcb --- /dev/null +++ b/leptonica/prog/pageseg2-mask.png diff --git a/leptonica/prog/pageseg2-seed.png b/leptonica/prog/pageseg2-seed.png Binary files differnew file mode 100644 index 00000000..ff5cc907 --- /dev/null +++ b/leptonica/prog/pageseg2-seed.png diff --git a/leptonica/prog/pageseg2.tif b/leptonica/prog/pageseg2.tif Binary files differnew file mode 100644 index 00000000..30a60a26 --- /dev/null +++ b/leptonica/prog/pageseg2.tif diff --git a/leptonica/prog/pageseg3.tif b/leptonica/prog/pageseg3.tif Binary files differnew file mode 100644 index 00000000..d70f46c7 --- /dev/null +++ b/leptonica/prog/pageseg3.tif diff --git a/leptonica/prog/pageseg4.tif b/leptonica/prog/pageseg4.tif Binary files differnew file mode 100644 index 00000000..a34683fd --- /dev/null +++ b/leptonica/prog/pageseg4.tif diff --git a/leptonica/prog/pageseg_reg.c b/leptonica/prog/pageseg_reg.c new file mode 100644 index 00000000..2298446f --- /dev/null +++ b/leptonica/prog/pageseg_reg.c @@ -0,0 +1,237 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * pageseg_reg.c + * + * This is a regresssion test for some of the page segmentation + * algorithms. You can run some of these algorithms on any selected page + * image using prog/pagesegtest1. + * Tests are for: + * - Generic page segmentation + * - Foreground finding + * - Greedy whitespace rectangle finder + * - Table finder + * - Text auto-inversion + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + +int main(int argc, + char **argv) +{ +l_uint8 *data; +char *fname; +l_int32 i, n, w, h, istable, score; +size_t size; +BOX *box; +BOXA *boxa; +PIX *pixs, *pix1, *pix2, *pix3, *pix4, *pix5; +PIX *pixhm, *pixtm, *pixtb, *pixdb; +PIXA *pixadb; +PIXAC *pixac; +SARRAY *sa; +L_REGPARAMS *rp; + +#if !defined(HAVE_LIBPNG) + L_ERROR("This test requires libpng to run.\n", "pageseg_reg"); + exit(77); +#endif +#if !defined(HAVE_LIBJPEG) + L_ERROR("This test requires libjpeg to run.\n", "pageseg_reg"); + exit(77); +#endif +#if !defined(HAVE_LIBTIFF) + L_ERROR("This test requires libtiff to run.\n", "pageseg_reg"); + exit(77); +#endif + + if (regTestSetup(argc, argv, &rp)) + return 1; + +#if 1 + /* Test the generic page segmentation */ + pixs = pixRead("pageseg1.tif"); + pixadb = pixaCreate(0); + pixGetRegionsBinary(pixs, &pixhm, &pixtm, &pixtb, pixadb); + pixDestroy(&pixhm); + pixDestroy(&pixtm); + pixDestroy(&pixtb); + + n = pixaGetCount(pixadb); + for (i = 0; i < n; i++) { + pix1 = pixaGetPix(pixadb, i, L_CLONE); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 0 - 19 */ + pixDestroy(&pix1); + } + + /* Display intermediate images and final segmentation */ + if (rp->display) { + pix1 = pixaDisplayTiledAndScaled(pixadb, 32, 400, 4, 0, 20, 3); + pixDisplay(pix1, 0, 0); + pixDestroy(&pix1); + pix1 = pixaGetPix(pixadb, 18, L_CLONE); + pixDisplay(pix1, 510, 0); + pixDestroy(&pix1); + pix1 = pixaGetPix(pixadb, 19, L_CLONE); + pixDisplay(pix1, 1140, 0); + pixDestroy(&pix1); + } + pixaDestroy(&pixadb); + + /* Test foreground finding */ + sa = getSortedPathnamesInDirectory(".", "lion-page", 0, 0); + n = sarrayGetCount(sa); + boxa = boxaCreate(n); + box = boxCreate(0, 0, 0, 0); /* invalid box */ + boxaInitFull(boxa, box); /* Init to invalid boxes */ + boxDestroy(&box); + pixac = pixacompCreate(n); + for (i = 0; i < n; i++) { + fname = sarrayGetString(sa, i, L_NOCOPY); + pix1 = pixRead(fname); + box = pixFindPageForeground(pix1, 170, 70, 30, 0, pixac); + if (!box) { + pixDestroy(&pix1); + continue; + } + boxaReplaceBox(boxa, i, box); + pixDestroy(&pix1); + } + boxaWriteMem(&data, &size, boxa); + regTestWriteDataAndCheck(rp, data, size, "ba"); /* 20 */ + boxaDestroy(&boxa); + lept_free(data); + l_pdfSetDateAndVersion(0); + pixacompConvertToPdfData(pixac, 0, 1.0, L_DEFAULT_ENCODE, 0, + "Page foreground", &data, &size); + regTestWriteDataAndCheck(rp, data, size, "pdf"); /* 21 */ + lept_free(data); + sarrayDestroy(&sa); + pixacompDestroy(&pixac); + + /* Test the greedy rectangle finder for white space */ + pix1 = pixScale(pixs, 0.5, 0.5); + pixFindLargeRectangles(pix1, 0, 20, &boxa, &pixdb); + regTestWritePixAndCheck(rp, pixdb, IFF_PNG); /* 22 */ + pixDisplayWithTitle(pixdb, 0, 700, NULL, rp->display); + pixDestroy(&pixs); + pixDestroy(&pix1); + pixDestroy(&pixdb); + boxaDestroy(&boxa); + + /* Test the table finder */ + pix1 = pixRead("table.15.tif"); + pixadb = pixaCreate(0); + pixDecideIfTable(pix1, NULL, L_PORTRAIT_MODE, &score, pixadb); + istable = (score >= 2) ? 1 : 0; + regTestCompareValues(rp, 1.0, istable, 0.0); /* 23 */ + pix2 = pixaDisplayTiledInRows(pixadb, 32, 2000, 1.0, 0, 30, 2); + regTestWritePixAndCheck(rp, pix2, IFF_PNG); /* 24 */ + pixDisplayWithTitle(pix2, 620, 700, NULL, rp->display); + pixDestroy(&pix1); + pixDestroy(&pix2); + pixaDestroy(&pixadb); + + pix1 = pixRead("table.27.tif"); + pixadb = pixaCreate(0); + pixDecideIfTable(pix1, NULL, L_PORTRAIT_MODE, &score, pixadb); + istable = (score >= 2) ? 1 : 0; + regTestCompareValues(rp, 1.0, istable, 0.0); /* 25 */ + pix2 = pixaDisplayTiledInRows(pixadb, 32, 2000, 1.0, 0, 30, 2); + regTestWritePixAndCheck(rp, pix2, IFF_PNG); /* 26 */ + pixDisplayWithTitle(pix2, 1000, 700, NULL, rp->display); + pixDestroy(&pix1); + pixDestroy(&pix2); + pixaDestroy(&pixadb); + + pix1 = pixRead("table.150.png"); + pixadb = pixaCreate(0); + pixDecideIfTable(pix1, NULL, L_PORTRAIT_MODE, &score, pixadb); + istable = (score >= 2) ? 1 : 0; + regTestCompareValues(rp, 1.0, istable, 0.0); /* 27 */ + pix2 = pixaDisplayTiledInRows(pixadb, 32, 2000, 1.0, 0, 30, 2); + regTestWritePixAndCheck(rp, pix2, IFF_PNG); /* 28 */ + pixDisplayWithTitle(pix2, 1300, 700, NULL, rp->display); + pixDestroy(&pix1); + pixDestroy(&pix2); + pixaDestroy(&pixadb); + + pix1 = pixRead("toc.99.tif"); /* not a table */ + pixadb = pixaCreate(0); + pixDecideIfTable(pix1, NULL, L_PORTRAIT_MODE, &score, pixadb); + istable = (score >= 2) ? 1 : 0; + regTestCompareValues(rp, 0.0, istable, 0.0); /* 29 */ + pix2 = pixaDisplayTiledInRows(pixadb, 32, 2000, 1.0, 0, 30, 2); + regTestWritePixAndCheck(rp, pix2, IFF_PNG); /* 30 */ + pixDisplayWithTitle(pix2, 1600, 700, NULL, rp->display); + pixDestroy(&pix1); + pixDestroy(&pix2); + pixaDestroy(&pixadb); +#endif + + /* Tests of auto-inversion of text */ + pix1 = pixRead("zanotti-78.jpg"); + pix2 = pixConvertRGBToLuminance(pix1); + pixadb = pixaCreate(0); + pixaAddPix(pixadb, pix2, L_COPY); + pixGetDimensions(pix2, &w, &h, NULL); + pixRasterop(pix2, 0.2 * w, 0.08 * h, 0.4 * w, 0.23 * h, PIX_NOT(PIX_DST), + NULL, 0, 0); + pixRasterop(pix2, 0.6 * w, 0.5 * h, 0.2 * w, 0.15 * h, PIX_NOT(PIX_DST), + NULL, 0, 0); + pix3 = pixAutoPhotoinvert(pix2, 128, &pix4, pixadb); + pix5 = pixaDisplayTiledInColumns(pixadb, 5, 0.3, 20, 2); + regTestWritePixAndCheck(rp, pix2, IFF_PNG); /* 31 */ + regTestWritePixAndCheck(rp, pix4, IFF_PNG); /* 32 */ + regTestWritePixAndCheck(rp, pix5, IFF_PNG); /* 33 */ + pixDisplayWithTitle(pix5, 1750, 200, NULL, rp->display); + pixaDestroy(&pixadb); + pixDestroy(&pix1); + pixDestroy(&pix2); + pixDestroy(&pix3); + pixDestroy(&pix4); + pixDestroy(&pix5); + + pix1 = pixRead("invertedtext.tif"); + pixadb = pixaCreate(0); + pixaAddPix(pixadb, pix1, L_COPY); + pix2 = pixAutoPhotoinvert(pix1, 128, &pix3, pixadb); + pix4 = pixaDisplayTiledInColumns(pixadb, 5, 1.0, 20, 2); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 34 */ + regTestWritePixAndCheck(rp, pix3, IFF_PNG); /* 35 */ + regTestWritePixAndCheck(rp, pix4, IFF_PNG); /* 36 */ + pixDisplayWithTitle(pix4, 1750, 0, NULL, rp->display); + pixDestroy(&pix1); + pixDestroy(&pix2); + pixDestroy(&pix3); + pixDestroy(&pix4); + return regTestCleanup(rp); +} diff --git a/leptonica/prog/pagesegtest1.c b/leptonica/prog/pagesegtest1.c new file mode 100644 index 00000000..7feaae20 --- /dev/null +++ b/leptonica/prog/pagesegtest1.c @@ -0,0 +1,71 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * pagesegtest1.c + * + * Use on, e.g.: feyn.tif, witten.tif, + * pageseg1.tif, pageseg2.tif, pageseg3.tif, pageseg4.tif + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + +int main(int argc, + char **argv) +{ +PIX *pixs, *pixhm, *pixtm, *pixtb, *pixd; +PIXA *pixadb; +char *filein; +static char mainName[] = "pagesegtest1"; + + if (argc != 2) + return ERROR_INT(" Syntax: pagesegtest1 filein", mainName, 1); + filein = argv[1]; + setLeptDebugOK(1); + + if ((pixs = pixRead(filein)) == NULL) + return ERROR_INT("pixs not made", mainName, 1); + + pixadb = pixaCreate(0); + pixGetRegionsBinary(pixs, &pixhm, &pixtm, &pixtb, pixadb); + pixDestroy(&pixhm); + pixDestroy(&pixtm); + pixDestroy(&pixtb); + pixDestroy(&pixs); + + /* Display intermediate images in a single image */ + lept_mkdir("lept/pagseg"); + pixd = pixaDisplayTiledAndScaled(pixadb, 32, 400, 4, 0, 20, 3); + pixWrite("/tmp/lept/pageseg/debug.png", pixd, IFF_PNG); + pixaDestroy(&pixadb); + pixDestroy(&pixd); + return 0; +} + diff --git a/leptonica/prog/pagesegtest2.c b/leptonica/prog/pagesegtest2.c new file mode 100644 index 00000000..93668287 --- /dev/null +++ b/leptonica/prog/pagesegtest2.c @@ -0,0 +1,131 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * pagesegtest2.c + * + * Demonstrates morphological approach to segmenting images. + * + * pagesegtest2 filein fileout + * + * where: + * filein: 1, 8 or 32 bpp page image + * fileout: photomask for image regions at full resolution + * + * This example shows how to use the morphseq specification of + * a sequence of morphological and reduction/expansion operations. + * + * This is much simpler than generating the structuring elements + * for the morph operations, specifying each of the function + * calls, keeping track of the intermediate images, and removing + * them at the end. + * + * The specific sequences below tend to work ok for images scanned at + * about 600 ppi. + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + + /* Mask at 4x reduction */ +static const char *mask_sequence = "r11"; + /* Seed at 4x reduction, formed by doing a 16x reduction, + * an opening, and finally a 4x replicative expansion. */ +static const char *seed_sequence = "r1143 + o5.5+ x4"; + /* Simple dilation */ +static const char *dilation_sequence = "d3.3"; + +#define DFLAG 1 + +int main(int argc, + char **argv) +{ +char *filein, *fileout; +l_int32 thresh; +PIX *pixs, *pixg, *pixb; +PIX *pixmask4, *pixseed4, *pixsf4, *pixd4, *pixd; +static char mainName[] = "pagesegtest2"; + + if (argc != 4) + return ERROR_INT(" Syntax: pagesegtest2 filein thresh fileout", + mainName, 1); + filein = argv[1]; + thresh = atoi(argv[2]); + fileout = argv[3]; + setLeptDebugOK(1); + + /* Get a 1 bpp version of the page */ + if ((pixs = pixRead(filein)) == NULL) + return ERROR_INT("pixs not made", mainName, 1); + if (pixGetDepth(pixs) == 32) + pixg = pixConvertRGBToGrayFast(pixs); + else + pixg = pixClone(pixs); + if (pixGetDepth(pixg) == 8) + pixb = pixThresholdToBinary(pixg, thresh); + else + pixb = pixClone(pixg); + + /* Make seed and mask, and fill seed into mask */ + pixseed4 = pixMorphSequence(pixb, seed_sequence, 0); + pixmask4 = pixMorphSequence(pixb, mask_sequence, 0); + pixsf4 = pixSeedfillBinary(NULL, pixseed4, pixmask4, 8); + pixd4 = pixMorphSequence(pixsf4, dilation_sequence, 0); + + /* Mask at full resolution */ + pixd = pixExpandBinaryPower2(pixd4, 4); + pixWrite(fileout, pixd, IFF_TIFF_G4); + + /* Extract non-image parts (e.g., text) at full resolution */ + pixSubtract(pixb, pixb, pixd); + + pixDisplayWithTitle(pixseed4, 400, 100, "halftone seed", DFLAG); + pixDisplayWithTitle(pixmask4, 100, 100, "halftone seed mask", DFLAG); + pixDisplayWithTitle(pixd4, 700, 100, "halftone mask", DFLAG); + pixDisplayWithTitle(pixb, 1000, 100, "non-halftone", DFLAG); + +#if 1 + pixWrite("junkseed", pixseed4, IFF_TIFF_G4); + pixWrite("junkmask", pixmask4, IFF_TIFF_G4); + pixWrite("junkfill", pixd4, IFF_TIFF_G4); + pixWrite("junktext", pixb, IFF_TIFF_G4); +#endif + + pixDestroy(&pixs); + pixDestroy(&pixg); + pixDestroy(&pixb); + pixDestroy(&pixseed4); + pixDestroy(&pixmask4); + pixDestroy(&pixsf4); + pixDestroy(&pixd4); + pixDestroy(&pixd); + return 0; +} + + diff --git a/leptonica/prog/paint_reg.c b/leptonica/prog/paint_reg.c new file mode 100644 index 00000000..dd3a08c5 --- /dev/null +++ b/leptonica/prog/paint_reg.c @@ -0,0 +1,364 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * paint_reg.c + * + * Regression test for: + * (1) painting on images of various types and depths. + * (2) painting through masks (test by reconstructing cmapped image) + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + +static PIX * ReconstructByValue(L_REGPARAMS *rp, const char *fname); +static PIX * FakeReconstructByBand(L_REGPARAMS *rp, const char *fname); + + +int main(int argc, + char **argv) +{ +l_int32 index; +l_uint32 val32; +BOX *box, *box1, *box2, *box3, *box4, *box5; +BOXA *boxa; +L_KERNEL *kel; +PIX *pixs, *pixg, *pixb, *pixd, *pixt, *pix1, *pix2, *pix3, *pix4; +PIXA *pixa; +PIXCMAP *cmap; +L_REGPARAMS *rp; + + if (regTestSetup(argc, argv, &rp)) + return 1; + + pixa = pixaCreate(0); + + /* Color non-white pixels on RGB */ + pixs = pixRead("lucasta-frag.jpg"); + pixt = pixConvert8To32(pixs); + box = boxCreate(120, 30, 200, 200); + pixColorGray(pixt, box, L_PAINT_DARK, 220, 0, 0, 255); + regTestWritePixAndCheck(rp, pixt, IFF_JFIF_JPEG); /* 0 */ + pixaAddPix(pixa, pixt, L_COPY); + pixColorGray(pixt, NULL, L_PAINT_DARK, 220, 255, 100, 100); + regTestWritePixAndCheck(rp, pixt, IFF_JFIF_JPEG); /* 1 */ + pixaAddPix(pixa, pixt, L_INSERT); + boxDestroy(&box); + + /* Color non-white pixels on colormap */ + pixt = pixThresholdTo4bpp(pixs, 6, 1); + box = boxCreate(120, 30, 200, 200); + pixColorGray(pixt, box, L_PAINT_DARK, 220, 0, 0, 255); + regTestWritePixAndCheck(rp, pixt, IFF_PNG); /* 2 */ + pixaAddPix(pixa, pixt, L_COPY); + pixColorGray(pixt, NULL, L_PAINT_DARK, 220, 255, 100, 100); + regTestWritePixAndCheck(rp, pixt, IFF_PNG); /* 3 */ + pixaAddPix(pixa, pixt, L_INSERT); + boxDestroy(&box); + + /* Color non-black pixels on RGB */ + pixt = pixConvert8To32(pixs); + box = boxCreate(120, 30, 200, 200); + pixColorGray(pixt, box, L_PAINT_LIGHT, 20, 0, 0, 255); + regTestWritePixAndCheck(rp, pixt, IFF_PNG); /* 4 */ + pixaAddPix(pixa, pixt, L_COPY); + pixColorGray(pixt, NULL, L_PAINT_LIGHT, 80, 255, 100, 100); + regTestWritePixAndCheck(rp, pixt, IFF_PNG); /* 5 */ + pixaAddPix(pixa, pixt, L_INSERT); + boxDestroy(&box); + + /* Color non-black pixels on colormap */ + pixt = pixThresholdTo4bpp(pixs, 6, 1); + box = boxCreate(120, 30, 200, 200); + pixColorGray(pixt, box, L_PAINT_LIGHT, 20, 0, 0, 255); + regTestWritePixAndCheck(rp, pixt, IFF_PNG); /* 6 */ + pixaAddPix(pixa, pixt, L_COPY); + pixColorGray(pixt, NULL, L_PAINT_LIGHT, 20, 255, 100, 100); + regTestWritePixAndCheck(rp, pixt, IFF_PNG); /* 7 */ + pixaAddPix(pixa, pixt, L_INSERT); + boxDestroy(&box); + + /* Add highlight color to RGB */ + pixt = pixConvert8To32(pixs); + box = boxCreate(507, 5, 385, 45); + pixg = pixClipRectangle(pixs, box, NULL); + pixb = pixThresholdToBinary(pixg, 180); + pixInvert(pixb, pixb); + composeRGBPixel(50, 0, 250, &val32); + pixPaintThroughMask(pixt, pixb, box->x, box->y, val32); + boxDestroy(&box); + pixDestroy(&pixg); + pixDestroy(&pixb); + box = boxCreate(236, 107, 262, 40); + pixg = pixClipRectangle(pixs, box, NULL); + pixb = pixThresholdToBinary(pixg, 180); + pixInvert(pixb, pixb); + composeRGBPixel(250, 0, 50, &val32); + pixPaintThroughMask(pixt, pixb, box->x, box->y, val32); + boxDestroy(&box); + pixDestroy(&pixg); + pixDestroy(&pixb); + box = boxCreate(222, 208, 247, 43); + pixg = pixClipRectangle(pixs, box, NULL); + pixb = pixThresholdToBinary(pixg, 180); + pixInvert(pixb, pixb); + composeRGBPixel(60, 250, 60, &val32); + pixPaintThroughMask(pixt, pixb, box->x, box->y, val32); + regTestWritePixAndCheck(rp, pixt, IFF_PNG); /* 8 */ + pixaAddPix(pixa, pixt, L_INSERT); + boxDestroy(&box); + pixDestroy(&pixg); + pixDestroy(&pixb); + + /* Add highlight color to colormap */ + pixt = pixThresholdTo4bpp(pixs, 5, 1); + cmap = pixGetColormap(pixt); + pixcmapGetIndex(cmap, 255, 255, 255, &index); + box = boxCreate(507, 5, 385, 45); + pixSetSelectCmap(pixt, box, index, 50, 0, 250); + boxDestroy(&box); + box = boxCreate(236, 107, 262, 40); + pixSetSelectCmap(pixt, box, index, 250, 0, 50); + boxDestroy(&box); + box = boxCreate(222, 208, 247, 43); + pixSetSelectCmap(pixt, box, index, 60, 250, 60); + regTestWritePixAndCheck(rp, pixt, IFF_PNG); /* 9 */ + pixaAddPix(pixa, pixt, L_INSERT); + boxDestroy(&box); + + /* Paint lines on RGB */ + pixt = pixConvert8To32(pixs); + pixRenderLineArb(pixt, 450, 20, 850, 320, 5, 200, 50, 125); + pixRenderLineArb(pixt, 30, 40, 440, 40, 5, 100, 200, 25); + box = boxCreate(70, 80, 300, 245); + pixRenderBoxArb(pixt, box, 3, 200, 200, 25); + regTestWritePixAndCheck(rp, pixt, IFF_JFIF_JPEG); /* 10 */ + pixaAddPix(pixa, pixt, L_INSERT); + boxDestroy(&box); + + /* Paint lines on colormap */ + pixt = pixThresholdTo4bpp(pixs, 5, 1); + pixRenderLineArb(pixt, 450, 20, 850, 320, 5, 200, 50, 125); + pixRenderLineArb(pixt, 30, 40, 440, 40, 5, 100, 200, 25); + box = boxCreate(70, 80, 300, 245); + pixRenderBoxArb(pixt, box, 3, 200, 200, 25); + regTestWritePixAndCheck(rp, pixt, IFF_PNG); /* 11 */ + pixaAddPix(pixa, pixt, L_INSERT); + boxDestroy(&box); + + /* Blend lines on RGB */ + pixt = pixConvert8To32(pixs); + pixRenderLineBlend(pixt, 450, 20, 850, 320, 5, 200, 50, 125, 0.35); + pixRenderLineBlend(pixt, 30, 40, 440, 40, 5, 100, 200, 25, 0.35); + box = boxCreate(70, 80, 300, 245); + pixRenderBoxBlend(pixt, box, 3, 200, 200, 25, 0.6); + regTestWritePixAndCheck(rp, pixt, IFF_JFIF_JPEG); /* 12 */ + pixaAddPix(pixa, pixt, L_INSERT); + boxDestroy(&box); + + /* Colorize gray on cmapped image. */ + pix1 = pixRead("lucasta.150.jpg"); + pix2 = pixThresholdTo4bpp(pix1, 7, 1); + box1 = boxCreate(73, 206, 140, 27); + pixColorGrayCmap(pix2, box1, L_PAINT_LIGHT, 130, 207, 43); + regTestWritePixAndCheck(rp, pix2, IFF_PNG); /* 13 */ + pixaAddPix(pixa, pix2, L_COPY); + if (rp->display) + pixPrintStreamInfo(stderr, pix2, "One box added"); + + box2 = boxCreate(255, 404, 197, 25); + pixColorGrayCmap(pix2, box2, L_PAINT_LIGHT, 230, 67, 119); + regTestWritePixAndCheck(rp, pix2, IFF_PNG); /* 14 */ + pixaAddPix(pixa, pix2, L_COPY); + if (rp->display) + pixPrintStreamInfo(stderr, pix2, "Two boxes added"); + + box3 = boxCreate(122, 756, 224, 22); + pixColorGrayCmap(pix2, box3, L_PAINT_DARK, 230, 67, 119); + regTestWritePixAndCheck(rp, pix2, IFF_PNG); /* 15 */ + pixaAddPix(pixa, pix2, L_COPY); + if (rp->display) + pixPrintStreamInfo(stderr, pix2, "Three boxes added"); + + box4 = boxCreate(11, 780, 147, 22); + pixColorGrayCmap(pix2, box4, L_PAINT_LIGHT, 70, 137, 229); + regTestWritePixAndCheck(rp, pix2, IFF_PNG); /* 16 */ + pixaAddPix(pixa, pix2, L_COPY); + if (rp->display) + pixPrintStreamInfo(stderr, pix2, "Four boxes added"); + + box5 = boxCreate(163, 605, 78, 22); + pixColorGrayCmap(pix2, box5, L_PAINT_LIGHT, 70, 137, 229); + regTestWritePixAndCheck(rp, pix2, IFF_PNG); /* 17 */ + pixaAddPix(pixa, pix2, L_INSERT); + if (rp->display) + pixPrintStreamInfo(stderr, pix2, "Five boxes added"); + pixDestroy(&pix1); + boxDestroy(&box1); + boxDestroy(&box2); + boxDestroy(&box3); + boxDestroy(&box4); + boxDestroy(&box5); + pixDestroy(&pixs); + + /* Make a gray image and identify the fg pixels (val > 230) */ + pixs = pixRead("feyn-fract.tif"); + pix1 = pixConvertTo8(pixs, 0); + kel = makeGaussianKernel(2, 2, 1.5, 1.0); + pix2 = pixConvolve(pix1, kel, 8, 1); + pix3 = pixThresholdToBinary(pix2, 230); + boxa = pixConnComp(pix3, NULL, 8); + pixDestroy(&pixs); + pixDestroy(&pix1); + pixDestroy(&pix3); + kernelDestroy(&kel); + + /* Color the individual components in the gray image */ + pix4 = pixColorGrayRegions(pix2, boxa, L_PAINT_DARK, 230, 255, 0, 0); + regTestWritePixAndCheck(rp, pix4, IFF_PNG); /* 18 */ + pixaAddPix(pixa, pix4, L_INSERT); + pixDisplayWithTitle(pix4, 0, 0, NULL, rp->display); + + /* Threshold to 10 levels of gray */ + pix3 = pixThresholdOn8bpp(pix2, 10, 1); + regTestWritePixAndCheck(rp, pix3, IFF_PNG); /* 19 */ + pixaAddPix(pixa, pix3, L_COPY); + + /* Color the individual components in the cmapped image */ + pix4 = pixColorGrayRegions(pix3, boxa, L_PAINT_DARK, 230, 255, 0, 0); + regTestWritePixAndCheck(rp, pix4, IFF_PNG); /* 20 */ + pixaAddPix(pixa, pix4, L_INSERT); + pixDisplayWithTitle(pix4, 0, 100, NULL, rp->display); + boxaDestroy(&boxa); + + /* Color the entire gray image (not component-wise) */ + pixColorGray(pix2, NULL, L_PAINT_DARK, 230, 255, 0, 0); + regTestWritePixAndCheck(rp, pix2, IFF_PNG); /* 21 */ + pixaAddPix(pixa, pix2, L_INSERT); + + /* Color the entire cmapped image (not component-wise) */ + pixColorGray(pix3, NULL, L_PAINT_DARK, 230, 255, 0, 0); + regTestWritePixAndCheck(rp, pix3, IFF_PNG); /* 22 */ + pixaAddPix(pixa, pix3, L_INSERT); + + /* Reconstruct cmapped images */ + pixd = ReconstructByValue(rp, "weasel2.4c.png"); + regTestWritePixAndCheck(rp, pixd, IFF_PNG); /* 23 */ + pixaAddPix(pixa, pixd, L_INSERT); + pixd = ReconstructByValue(rp, "weasel4.11c.png"); + regTestWritePixAndCheck(rp, pixd, IFF_PNG); /* 24 */ + pixaAddPix(pixa, pixd, L_INSERT); + pixd = ReconstructByValue(rp, "weasel8.240c.png"); + regTestWritePixAndCheck(rp, pixd, IFF_PNG); /* 25 */ + pixaAddPix(pixa, pixd, L_INSERT); + + /* Fake reconstruct cmapped images, with one color into a band */ + pixd = FakeReconstructByBand(rp, "weasel2.4c.png"); + regTestWritePixAndCheck(rp, pixd, IFF_PNG); /* 26 */ + pixaAddPix(pixa, pixd, L_INSERT); + pixd = FakeReconstructByBand(rp, "weasel4.11c.png"); + regTestWritePixAndCheck(rp, pixd, IFF_PNG); /* 27 */ + pixaAddPix(pixa, pixd, L_INSERT); + pixd = FakeReconstructByBand(rp, "weasel8.240c.png"); + regTestWritePixAndCheck(rp, pixd, IFF_PNG); /* 28 */ + pixaAddPix(pixa, pixd, L_INSERT); + + /* If in testing mode, make a pdf */ + if (rp->display) { + pixaConvertToPdf(pixa, 100, 1.0, L_FLATE_ENCODE, 0, + "Colorize and paint", "/tmp/lept/regout/paint.pdf"); + L_INFO("Output pdf: /tmp/lept/regout/paint.pdf\n", rp->testname); + } + + pixaDestroy(&pixa); + return regTestCleanup(rp); +} + + +static PIX * +ReconstructByValue(L_REGPARAMS *rp, + const char *fname) +{ +l_int32 i, n, rval, gval, bval; +PIX *pixs, *pixm, *pixd; +PIXCMAP *cmap; + + pixs = pixRead(fname); + cmap = pixGetColormap(pixs); + n = pixcmapGetCount(cmap); + pixd = pixCreateTemplate(pixs); + for (i = 0; i < n; i++) { + pixm = pixGenerateMaskByValue(pixs, i, 1); + pixcmapGetColor(cmap, i, &rval, &gval, &bval); + pixSetMaskedCmap(pixd, pixm, 0, 0, rval, gval, bval); + pixDestroy(&pixm); + } + + regTestComparePix(rp, pixs, pixd); + pixDestroy(&pixs); + return pixd; +} + +static PIX * +FakeReconstructByBand(L_REGPARAMS *rp, + const char *fname) +{ +l_int32 i, jlow, jup, n, nbands; +l_int32 rval1, gval1, bval1, rval2, gval2, bval2, rval, gval, bval; +PIX *pixs, *pixm, *pixd; +PIXCMAP *cmaps, *cmapd; + + pixs = pixRead(fname); + cmaps = pixGetColormap(pixs); + n = pixcmapGetCount(cmaps); + nbands = (n + 1) / 2; + pixd = pixCreateTemplate(pixs); + cmapd = pixcmapCreate(pixGetDepth(pixs)); + pixSetColormap(pixd, cmapd); + for (i = 0; i < nbands; i++) { + jlow = 2 * i; + jup = L_MIN(jlow + 1, n - 1); + pixm = pixGenerateMaskByBand(pixs, jlow, jup, 1, 1); + + /* Get average color in the band */ + pixcmapGetColor(cmaps, jlow, &rval1, &gval1, &bval1); + pixcmapGetColor(cmaps, jup, &rval2, &gval2, &bval2); + rval = (rval1 + rval2) / 2; + gval = (gval1 + gval2) / 2; + bval = (bval1 + bval2) / 2; + + pixcmapAddColor(cmapd, rval, gval, bval); + pixSetMaskedCmap(pixd, pixm, 0, 0, rval, gval, bval); + pixDestroy(&pixm); + } + + pixDestroy(&pixs); + return pixd; +} diff --git a/leptonica/prog/paintmask_reg.c b/leptonica/prog/paintmask_reg.c new file mode 100644 index 00000000..d944f438 --- /dev/null +++ b/leptonica/prog/paintmask_reg.c @@ -0,0 +1,215 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * paintmask_reg.c + * + * Regression test for painting through a mask onto various + * depth images. + * + * This file shows how one can start with a 32 bpp RGB image and + * derive from it the following: + * 8 bpp color, cmapped + * 4 bpp color, cmapped + * 2 bpp color, cmapped + * 8 bpp gray + * 4 bpp gray + * 4 bpp gray, cmapped + * 2 bpp gray + * 2 bpp gray, cmapped + * + * For each of these, pixClipMasked() is used to place a 1 bpp + * mask over part of the image, clip out the rectangular region + * supporting the mask, and paint a given color through the + * mask onto the result. + * + * Finally we do a clip/mask operation on 1 bpp sources. + * + * If you run 'paintmask_reg display', a pdf of the results is made. + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + +int main(int argc, + char **argv) +{ +BOX *box; +PIX *pixs, *pixs8, *pixm, *pixt1, *pixt2, *pixd; +PIXA *pixa; +L_REGPARAMS *rp; + + if (regTestSetup(argc, argv, &rp)) + return 1; + + pixa = pixaCreate(0); + + /* Start with a 32 bpp image and a mask. Use the + * same mask for all clip/masked operations. */ + pixs = pixRead("test24.jpg"); + pixt1 = pixRead("rabi.png"); + box = boxCreate(303, 1983, 800, 500); + pixm = pixClipRectangle(pixt1, box, NULL); + pixInvert(pixm, pixm); + boxDestroy(&box); + box = boxCreate(100, 100, 800, 500); /* clips on pixs and derivatives */ + pixt2 = pixClipRectangle(pixs, box, NULL); + regTestWritePixAndCheck(rp, pixt2, IFF_JFIF_JPEG); /* 0 */ + pixaAddPix(pixa, pixt2, L_INSERT); + pixDestroy(&pixt1); + + /* Clip 32 bpp RGB */ + pixd = pixClipMasked(pixs, pixm, 100, 100, 0x03c08000); + regTestWritePixAndCheck(rp, pixd, IFF_JFIF_JPEG); /* 1 */ + pixaAddPix(pixa, pixd, L_INSERT); + + /* Clip 8 bpp colormapped */ + pixt1 = pixMedianCutQuant(pixs, 0); + pixt2 = pixClipRectangle(pixt1, box, NULL); + regTestWritePixAndCheck(rp, pixt2, IFF_PNG); /* 2 */ + pixaAddPix(pixa, pixt2, L_INSERT); + pixd = pixClipMasked(pixt1, pixm, 100, 100, 0x03c08000); + regTestWritePixAndCheck(rp, pixd, IFF_PNG); /* 3 */ + pixaAddPix(pixa, pixd, L_INSERT); + pixDestroy(&pixt1); + + /* Clip 4 bpp colormapped */ + pixt1 = pixOctreeQuantNumColors(pixs, 16, 1); + pixt2 = pixClipRectangle(pixt1, box, NULL); + regTestWritePixAndCheck(rp, pixt2, IFF_PNG); /* 4 */ + pixaAddPix(pixa, pixt2, L_INSERT); + pixd = pixClipMasked(pixt1, pixm, 100, 100, 0x03c08000); + regTestWritePixAndCheck(rp, pixd, IFF_PNG); /* 5 */ + pixaAddPix(pixa, pixd, L_INSERT); + pixDestroy(&pixt1); + + /* Clip 2 bpp colormapped */ + pixt1 = pixMedianCutQuantGeneral(pixs, 0, 2, 4, 5, 1, 1); + pixt2 = pixClipRectangle(pixt1, box, NULL); + regTestWritePixAndCheck(rp, pixt2, IFF_PNG); /* 6 */ + pixaAddPix(pixa, pixt2, L_INSERT); + pixd = pixClipMasked(pixt1, pixm, 100, 100, 0x03608000); + regTestWritePixAndCheck(rp, pixd, IFF_PNG); /* 7 */ + pixaAddPix(pixa, pixd, L_INSERT); + pixDestroy(&pixt1); + + /* Clip 8 bpp gray */ + pixs8 = pixConvertRGBToLuminance(pixs); + pixt2 = pixClipRectangle(pixs8, box, NULL); + regTestWritePixAndCheck(rp, pixt2, IFF_JFIF_JPEG); /* 8 */ + pixaAddPix(pixa, pixt2, L_INSERT); + pixd = pixClipMasked(pixs8, pixm, 100, 100, 90); + regTestWritePixAndCheck(rp, pixd, IFF_JFIF_JPEG); /* 9 */ + pixaAddPix(pixa, pixd, L_INSERT); + + /* Clip 4 bpp gray */ + pixt1 = pixThresholdTo4bpp(pixs8, 16, 0); + pixt2 = pixClipRectangle(pixt1, box, NULL); + regTestWritePixAndCheck(rp, pixt2, IFF_PNG); /* 10 */ + pixaAddPix(pixa, pixt2, L_INSERT); + pixd = pixClipMasked(pixt1, pixm, 100, 100, 0); + regTestWritePixAndCheck(rp, pixd, IFF_PNG); /* 11 */ + pixaAddPix(pixa, pixd, L_INSERT); + pixd = pixClipMasked(pixt1, pixm, 100, 100, 5); + regTestWritePixAndCheck(rp, pixd, IFF_PNG); /* 12 */ + pixaAddPix(pixa, pixd, L_INSERT); + pixd = pixClipMasked(pixt1, pixm, 100, 100, 15); + regTestWritePixAndCheck(rp, pixd, IFF_PNG); /* 13 */ + pixaAddPix(pixa, pixd, L_INSERT); + pixDestroy(&pixt1); + + /* Clip 4 bpp gray, colormapped */ + pixt1 = pixThresholdTo4bpp(pixs8, 16, 1); + pixt2 = pixClipRectangle(pixt1, box, NULL); + regTestWritePixAndCheck(rp, pixt2, IFF_PNG); /* 14 */ + pixaAddPix(pixa, pixt2, L_INSERT); + pixd = pixClipMasked(pixt1, pixm, 100, 100, 0x55555500); + regTestWritePixAndCheck(rp, pixd, IFF_PNG); /* 15 */ + pixaAddPix(pixa, pixd, L_INSERT); + pixDestroy(&pixt1); + + /* Clip 2 bpp gray */ + pixt1 = pixThresholdTo2bpp(pixs8, 4, 0); + pixt2 = pixClipRectangle(pixt1, box, NULL); + regTestWritePixAndCheck(rp, pixt2, IFF_PNG); /* 16 */ + pixaAddPix(pixa, pixt2, L_INSERT); + pixd = pixClipMasked(pixt1, pixm, 100, 100, 1); + regTestWritePixAndCheck(rp, pixd, IFF_PNG); /* 17 */ + pixaAddPix(pixa, pixd, L_INSERT); + pixDestroy(&pixt1); + + /* Clip 2 bpp gray, colormapped */ + pixt1 = pixThresholdTo2bpp(pixs8, 4, 1); + pixt2 = pixClipRectangle(pixt1, box, NULL); + pixd = pixClipMasked(pixt1, pixm, 100, 100, 0x55555500); + regTestWritePixAndCheck(rp, pixd, IFF_PNG); /* 18 */ + pixaAddPix(pixa, pixd, L_INSERT); + pixDestroy(&pixt1); + pixDestroy(&pixt2); + + pixDestroy(&pixm); + pixDestroy(&pixs); + pixDestroy(&pixs8); + boxDestroy(&box); + + /* Finally, do the 1 bpp painting through clipped region. + * We start with two 1 bpp text sources, use the inverse + * of the 2nd for the mask (so we take all of the 1st + * pixels under this mask), and for the remainder, which + * are the fg pixels in the 2nd, we paint them black (1). + * So this is a simple and fast blending of two 1 bpp pix. */ + pixs = pixRead("feyn.tif"); + box = boxCreate(670, 827, 800, 500); + pixt2 = pixClipRectangle(pixs, box, NULL); + regTestWritePixAndCheck(rp, pixt2, IFF_PNG); /* 19 */ + pixaAddPix(pixa, pixt2, L_INSERT); + boxDestroy(&box); + pixt1 = pixRead("rabi.png"); + box = boxCreate(303, 1983, 800, 500); + pixm = pixClipRectangle(pixt1, box, NULL); + pixInvert(pixm, pixm); + regTestWritePixAndCheck(rp, pixm, IFF_PNG); /* 20 */ + pixaAddPix(pixa, pixm, L_INSERT); + pixd = pixClipMasked(pixs, pixm, 670, 827, 1); + regTestWritePixAndCheck(rp, pixd, IFF_PNG); /* 21 */ + pixaAddPix(pixa, pixd, L_INSERT); + pixDestroy(&pixs); + pixDestroy(&pixt1); + boxDestroy(&box); + + /* If in testing mode, make a pdf */ + if (rp->display) { + pixaConvertToPdf(pixa, 100, 1.0, L_FLATE_ENCODE, 0, + "Paint through mask", "/tmp/lept/regout/paintmask.pdf"); + L_INFO("Output pdf: /tmp/lept/regout/paintmask.pdf\n", rp->testname); + } + + pixaDestroy(&pixa); + return regTestCleanup(rp); +} diff --git a/leptonica/prog/pancrazi.15.jpg b/leptonica/prog/pancrazi.15.jpg Binary files differnew file mode 100644 index 00000000..5bfdd594 --- /dev/null +++ b/leptonica/prog/pancrazi.15.jpg diff --git a/leptonica/prog/partifytest.c b/leptonica/prog/partifytest.c new file mode 100644 index 00000000..8ef59f5b --- /dev/null +++ b/leptonica/prog/partifytest.c @@ -0,0 +1,53 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * partifytest.c + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + +int main(int argc, + char **argv) +{ +static char mainName[] = "partifytest"; + + if (argc != 1) + return ERROR_INT("syntax: partifytest", mainName, 1); + + setLeptDebugOK(1); + lept_mkdir("lept/partify"); +#if 0 + partifyFiles(".", "bois", 3, "/tmp/lept/partify/bois", "/tmp/lept/partify/debug.pdf"); +#else + partifyFiles(".", "ortiz", 5, "/tmp/lept/partify/ortiz", "/tmp/lept/partify/debug.pdf"); +#endif + return 0; +} diff --git a/leptonica/prog/partitiontest.c b/leptonica/prog/partitiontest.c new file mode 100644 index 00000000..d89309fa --- /dev/null +++ b/leptonica/prog/partitiontest.c @@ -0,0 +1,177 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * partitiontest.c + * + * partitiontest <fname> type [maxboxes ovlap] + * + * where type is: + * 5: L_SORT_BY_WIDTH + * 6: L_SORT_BY_HEIGHT + * 7: L_SORT_BY_MIN_DIMENSION + * 8: L_SORT_BY_MAX_DIMENSION + * 9: L_SORT_BY_PERIMETER + * 10: L_SORT_BY_AREA + * + * This partitions the input (1 bpp) image using boxaGetWhiteblocks(), + * which is an elegant but flawed method in computational geometry to + * extract the significant rectangular white blocks in a 1 bpp image. + * See partition.c for details. + * + * It then sorts the regions according to the selected input type, + * and displays the top sorted blocks in several different ways: + * - as outlines or solid filled regions + * - with random or specific colors + * - as an rgb or colormapped image. + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + +int main(int argc, + char **argv) +{ +char *filename; +l_int32 w, h, type, maxboxes; +l_float32 ovlap; +BOX *box; +BOXA *boxa, *boxat, *boxad; +PIX *pix, *pixs, *pix1, *pix2; +PIXA *pixa; +static char mainName[] = "partitiontest"; + + if (argc != 3 && argc != 5) + return ERROR_INT("syntax: partitiontest <fname> type [maxboxes ovlap]", + mainName, 1); + filename = argv[1]; + type = atoi(argv[2]); + + if (type == L_SORT_BY_WIDTH) { + lept_stderr("Sorting by width:\n"); + } else if (type == L_SORT_BY_HEIGHT) { + lept_stderr("Sorting by height:\n"); + } else if (type == L_SORT_BY_MAX_DIMENSION) { + lept_stderr("Sorting by maximum dimension:\n"); + } else if (type == L_SORT_BY_MIN_DIMENSION) { + lept_stderr("Sorting by minimum dimension:\n"); + } else if (type == L_SORT_BY_PERIMETER) { + lept_stderr("Sorting by perimeter:\n"); + } else if (type == L_SORT_BY_AREA) { + lept_stderr("Sorting by area:\n"); + } else { + lept_stderr("Use one of the following for 'type':\n" + " 5: L_SORT_BY_WIDTH\n" + " 6: L_SORT_BY_HEIGHT\n" + " 7: L_SORT_BY_MIN_DIMENSION\n" + " 8: L_SORT_BY_MAX_DIMENSION\n" + " 9: L_SORT_BY_PERIMETER\n" + " 10: L_SORT_BY_AREA\n"); + return ERROR_INT("invalid type: see source", mainName, 1); + } + if (argc == 5) { + maxboxes = atoi(argv[3]); + ovlap = atof(argv[4]); + } else { + maxboxes = 100; + ovlap = 0.2; + } + + setLeptDebugOK(1); + pixa = pixaCreate(0); + pix = pixRead(filename); + pixs = pixConvertTo1(pix, 128); + pixDilateBrick(pixs, pixs, 5, 5); + pixaAddPix(pixa, pixs, L_COPY); + boxa = pixConnComp(pixs, NULL, 4); + pixGetDimensions(pixs, &w, &h, NULL); + box = boxCreate(0, 0, w, h); + startTimer(); + boxaPermuteRandom(boxa, boxa); + boxat = boxaSelectBySize(boxa, 500, 500, L_SELECT_IF_BOTH, + L_SELECT_IF_LT, NULL); + boxad = boxaGetWhiteblocks(boxat, box, type, maxboxes, ovlap, + 200, 0.15, 20000); + lept_stderr("Time: %7.3f sec\n", stopTimer()); +/* boxaWriteStream(stderr, boxad); */ + + /* Display box outlines in a single color in a cmapped image */ + pix1 = pixDrawBoxa(pixs, boxad, 7, 0xe0708000); + pixaAddPix(pixa, pix1, L_INSERT); + + /* Display box outlines in a single color in an RGB image */ + pix1 = pixConvertTo8(pixs, FALSE); + pix2 = pixDrawBoxa(pix1, boxad, 7, 0x40a0c000); + pixaAddPix(pixa, pix2, L_INSERT); + pixDestroy(&pix1); + + /* Display box outlines with random colors in a cmapped image */ + pix1 = pixDrawBoxaRandom(pixs, boxad, 7); + pixaAddPix(pixa, pix1, L_INSERT); + + /* Display box outlines with random colors in an RGB image */ + pix1 = pixConvertTo8(pixs, FALSE); + pix2 = pixDrawBoxaRandom(pix1, boxad, 7); + pixaAddPix(pixa, pix2, L_INSERT); + pixDestroy(&pix1); + + /* Display boxes in the same color in a cmapped image */ + pix1 = pixPaintBoxa(pixs, boxad, 0x60e0a000); + pixaAddPix(pixa, pix1, L_INSERT); + + /* Display boxes in the same color in an RGB image */ + pix1 = pixConvertTo8(pixs, FALSE); + pix2 = pixPaintBoxa(pix2, boxad, 0xc030a000); + pixaAddPix(pixa, pix2, L_INSERT); + pixDestroy(&pix1); + + /* Display boxes in random colors in a cmapped image */ + pix1 = pixPaintBoxaRandom(pixs, boxad); + pixaAddPix(pixa, pix1, L_INSERT); + + /* Display boxes in random colors in an RGB image */ + pix1 = pixConvertTo8(pixs, FALSE); + pix2 = pixPaintBoxaRandom(pix1, boxad); + pixaAddPix(pixa, pix2, L_INSERT); + pixDestroy(&pix1); + + lept_stderr("Writing to: /tmp/lept/part/partition.pdf\n"); + lept_mkdir("lept/part"); + pixaConvertToPdf(pixa, 300, 1.0, L_FLATE_ENCODE, 0, "Partition test", + "/tmp/lept/part/partition.pdf"); + pixaDestroy(&pixa); + + pixDestroy(&pix); + pixDestroy(&pixs); + boxDestroy(&box); + boxaDestroy(&boxa); + boxaDestroy(&boxat); + boxaDestroy(&boxad); + return 0; +} diff --git a/leptonica/prog/patent.png b/leptonica/prog/patent.png Binary files differnew file mode 100644 index 00000000..bcb3cc43 --- /dev/null +++ b/leptonica/prog/patent.png diff --git a/leptonica/prog/pdf2jpeg b/leptonica/prog/pdf2jpeg new file mode 100644 index 00000000..c5b1f4da --- /dev/null +++ b/leptonica/prog/pdf2jpeg @@ -0,0 +1,58 @@ +#!/bin/bash +# pdf2jpeg +# +# Rasterizes a PDF file, saving as a set of 24 bpp RGB images +# +# input: PDF +# root name of output files +# output: 24 bpp RGB jpeg files for each page +# +# Note 1: Requires ghostscript +# +# Note 2: A modern alternative to ghostcript is to use poplar: +# If the pdf is composed of images that were orthographically generated: +# pdftoppm -png <pdf-file> <pdf-root> [output in png] +# If the pdf is composed of images that were scanned: +# pdftoppm -jpeg <pdf-file> <pdf-root> [output in jpeg] + +scriptname=${0##*/} + +if test $# != 2 +then + echo "usage: " $scriptname " inpdffile outjpgroot" + exit -1 +fi + +inpdffile=$1 +outjpgroot=$2 + +# strip off directory and suffix parts of $1 to use in other names +basename=${1##*/} +baseroot=${basename%.*} + +# make names for temporary files +tmppdffile=${baseroot}.$$_.pdf +tmppdfroot=${tmppdffile%.*} + +# have the temporary files deleted on exit, interrupt, etc: +trap "/bin/rm -f ${tmppdfroot}*" EXIT SIGHUP SIGINT SIGTERM + +cp $inpdffile $tmppdffile + +# need mysterious "primer" +# choose one of the two options below + +#--------------------------------------------------------------------# +# output image size depending on resolution # +#--------------------------------------------------------------------# +echo "0 neg 0 neg" translate | gs -sDEVICE=jpeg -sOutputFile=${outjpgroot}%03d.jpg -r300x300 -q - ${tmppdffile} +#echo "0 neg 0 neg" translate | gs -sDEVICE=jpeg -sOutputFile=${outjpgroot}%03d.jpg -r150x150 -q - ${tmppdffile} +#echo "0 neg 0 neg" translate | gs -sDEVICE=jpeg -sOutputFile=${outjpgroot}%03d.jpg -r75x75 -q - ${tmppdffile} + + +#--------------------------------------------------------------------# +# output fixed image size # +#--------------------------------------------------------------------# +#echo "0 neg 0 neg" translate | gs -sDEVICE=jpeg -sOutputFile=${outjpgroot}%03d.jpg -g2550x3300 -r300x300 -q - ${tmppdffile} + + diff --git a/leptonica/prog/pdf2mtiff b/leptonica/prog/pdf2mtiff new file mode 100755 index 00000000..60fd8f7b --- /dev/null +++ b/leptonica/prog/pdf2mtiff @@ -0,0 +1,51 @@ +#!/bin/bash +# pdf2mtiff +# +# Rasterizes a PDF file, saving as a single multipage g4 compressed +# tiff file +# +# input: PDF file +# output file +# output: ccitt-g4 compressed mulitipage tiff file +# +# Note 1: Requires ghostscript +# Note 2: If you give it images with bpp > 1, the result will be ugly. +# Note 3: A modern alternative to ghostcript is to use poplar: +# If the pdf is composed of images that were orthographically generated: +# pdftoppm -png <pdf-file> <pdf-root> [output in png] +# If the pdf is composed of images that were scanned: +# pdftoppm -jpeg <pdf-file> <pdf-root> [output in jpeg] + +scriptname=${0##*/} + +if test $# != 2 +then + echo "usage: " $scriptname " pdfin tiffout" + exit -1 +fi + +pdfin=$1 +tiffout=$2 + +# assert (input pdf filename ends in .pdf) +if test ${pdfin##*.} != pdf +then + echo $scriptname ": " $pdfin "does not end in .pdf" + exit -1 +fi + +# 'echo "0 neg 0 neg" translate' is the mysterious "primer" +rm /tmp/junkpdf* + +# --------- Choose one of the two options below --------- + +# output image size at 300 ppi +#echo "0 neg 0 neg" translate | /usr/bin/gs -sDEVICE=tiffg4 -sOutputFile=/tmp/junkpdf%03d.tif -r300x300 -q - ${pdfin} +#./writemtiff /tmp junkpdf ${tiffout} + +# output image size at 600 ppi +echo "0 neg 0 neg" translate | /usr/bin/gs -sDEVICE=tiffg4 -sOutputFile=/tmp/junkpdf%03d.tif -r600x600 -q - ${pdfin} +./writemtiff /tmp junkpdf ${tiffout} + +# ------------------------------------------------------ + diff --git a/leptonica/prog/pdf2png b/leptonica/prog/pdf2png new file mode 100644 index 00000000..90049071 --- /dev/null +++ b/leptonica/prog/pdf2png @@ -0,0 +1,46 @@ +#!/bin/bash +# pdf2png +# +# Rasterizes a PDF file, saving as a set of binary png images +# +# input: PDF +# root name of output files +# output: png binary files for each page +# +# Note 1: Requires ghostscript +# +# Note 2: A modern alternative to ghostcript is to use poplar: +# If the pdf is composed of images that were orthographically generated: +# pdftoppm -png <pdf-file> <pdf-root> [output in png] +# If the pdf is composed of images that were scanned: +# pdftoppm -jpeg <pdf-file> <pdf-root> [output in jpeg] + +scriptname=${0##*/} + +if test $# != 2 +then + echo "usage: " $scriptname " inpdffile outpngroot" + exit -1 +fi + +inpdffile=$1 +outpngroot=$2 + +# strip off directory and suffix parts of $1 to use in other names +basename=${1##*/} +baseroot=${basename%.*} + +# make names for temporary files +tmppdffile=${baseroot}.$$_.pdf +tmppdfroot=${tmppdffile%.*} + +# have the temporary files deleted on exit, interrupt, etc: +trap "/bin/rm -f ${tmppdfroot}*" EXIT SIGHUP SIGINT SIGTERM + +cp $inpdffile $tmppdffile + +# need mysterious "primer" +#echo "0 neg 0 neg" translate | gs -sDEVICE=pngmono -sOutputFile=${outpngroot}%03d.png -r300x300 -q - ${tmppdffile} +echo "0 neg 0 neg" translate | gs -sDEVICE=pngmono -sOutputFile=${outpngroot}%03d.png -g2550x3300 -r300x300 -q - ${tmppdffile} + + diff --git a/leptonica/prog/pdf2png-binary b/leptonica/prog/pdf2png-binary new file mode 100644 index 00000000..efa24d5b --- /dev/null +++ b/leptonica/prog/pdf2png-binary @@ -0,0 +1,38 @@ +#!/bin/bash +# pdf2png-binary +# +# Rasterizes a PDF file, saving as a set of binary png images +# +# input: PDF +# root name of output files +# output: 1 bpp png files for each page +# +# Note 1: Requires ghostscript +# +# Note 2: A modern alternative to ghostcript is to use poplar: +# If the pdf is composed of images that were orthographically generated: +# pdftoppm -png <pdf-file> <pdf-root> [output in png] +# If the pdf is composed of images that were scanned: +# pdftoppm -jpeg <pdf-file> <pdf-root> [output in jpeg] + +scriptname=${0##*/} + +if test $# != 2 +then + echo "usage: " $scriptname " inpdffile outpngroot" + exit -1 +fi + +inpdffile=$1 +outpngroot=$2 + +# need mysterious "primer" +# choose one of the two options below + +# output image size depending on resolution +echo "0 neg 0 neg" translate | gs -sDEVICE=pngmono -sOutputFile=${outpngroot}%03d.png -r300x300 -q - ${inpdffile} + +# output fixed image size +#echo "0 neg 0 neg" translate | gs -sDEVICE=pngmono -sOutputFile=${outpngroot}%03d.png -g2550x3300 -r300x300 -q - ${inpdffile} + + diff --git a/leptonica/prog/pdf2png-color b/leptonica/prog/pdf2png-color new file mode 100644 index 00000000..47f41b3f --- /dev/null +++ b/leptonica/prog/pdf2png-color @@ -0,0 +1,46 @@ +#!/bin/bash +# pdf2png-color +# +# Rasterizes a PDF file, saving a set of 24 bpp RGB png images +# +# input: PDF +# root name of output files +# output: 24 bpp RGB png files for each page +# +# Note 1: Requires ghostscript +# +# Note 2: A modern alternative to ghostcript is to use poplar: +# If the pdf is composed of images that were orthographically generated: +# pdftoppm -png <pdf-file> <pdf-root> [output in png] +# If the pdf is composed of images that were scanned: +# pdftoppm -jpeg <pdf-file> <pdf-root> [output in jpeg] + +scriptname=${0##*/} + +if test $# != 2 +then + echo "usage: " $scriptname " inpdffile outpngroot" + exit -1 +fi + +inpdffile=$1 +outpngroot=$2 + +# strip off directory and suffix parts of $1 to use in other names +basename=${1##*/} +baseroot=${basename%.*} + +# make names for temporary files +tmppdffile=${baseroot}.$$_.pdf +tmppdfroot=${tmppdffile%.*} + +# have the temporary files deleted on exit, interrupt, etc: +trap "/bin/rm -f ${tmppdfroot}*" EXIT SIGHUP SIGINT SIGTERM + +cp $inpdffile $tmppdffile + +# need mysterious "primer" +#echo "0 neg 0 neg" translate | gs -sDEVICE=png16m -sOutputFile=${outpngroot}%03d.png -r300x300 -q - ${tmppdffile} +echo "0 neg 0 neg" translate | gs -sDEVICE=png16m -sOutputFile=${outpngroot}%03d.png -g2550x3300 -r300x300 -q - ${tmppdffile} + + diff --git a/leptonica/prog/pdf2png-gray b/leptonica/prog/pdf2png-gray new file mode 100644 index 00000000..89a663e8 --- /dev/null +++ b/leptonica/prog/pdf2png-gray @@ -0,0 +1,46 @@ +#!/bin/bash +# pdf2png-gray +# +# Rasterizes a PDF file, saving a set of 8 bpp grayscale png images +# +# input: PDF +# root name of output files +# output: 8 bpp png files for each page +# +# Note 1: Requires ghostscript +# +# Note 2: A modern alternative to ghostcript is to use poplar: +# If the pdf is composed of images that were orthographically generated: +# pdftoppm -png <pdf-file> <pdf-root> [output in png] +# If the pdf is composed of images that were scanned: +# pdftoppm -jpeg <pdf-file> <pdf-root> [output in jpeg] + +scriptname=${0##*/} + +if test $# != 2 +then + echo "usage: " $scriptname " inpdffile outpngroot" + exit -1 +fi + +inpdffile=$1 +outpngroot=$2 + +# strip off directory and suffix parts of $1 to use in other names +basename=${1##*/} +baseroot=${basename%.*} + +# make names for temporary files +tmppdffile=${baseroot}.$$_.pdf +tmppdfroot=${tmppdffile%.*} + +# have the temporary files deleted on exit, interrupt, etc: +trap "/bin/rm -f ${tmppdfroot}*" EXIT SIGHUP SIGINT SIGTERM + +cp $inpdffile $tmppdffile + +# need mysterious "primer" +#echo "0 neg 0 neg" translate | gs -sDEVICE=pnggray -sOutputFile=${outpngroot}%03d.png -r300x300 -q - ${tmppdffile} +echo "0 neg 0 neg" translate | gs -sDEVICE=pnggray -sOutputFile=${outpngroot}%03d.png -g2550x3300 -r300x300 -q - ${tmppdffile} + + diff --git a/leptonica/prog/pdf2tiff b/leptonica/prog/pdf2tiff new file mode 100644 index 00000000..47270f1b --- /dev/null +++ b/leptonica/prog/pdf2tiff @@ -0,0 +1,47 @@ +#!/bin/bash +# pdf2tiff +# +# Rasterizes a PDF file, saving as a set of g4 compressed tiff images +# +# input: PDF +# root name of output files +# output: g4 compressed tiff binary files for each page +# +# Note 1: Requires ghostscript +# +# Note 2: A modern alternative to ghostcript is to use poplar: +# If the pdf is composed of images that were orthographically generated: +# pdftoppm -png <pdf-file> <pdf-root> [output in png] +# If the pdf is composed of images that were scanned: +# pdftoppm -jpeg <pdf-file> <pdf-root> [output in jpeg] + +scriptname=${0##*/} + +if test $# != 2 +then + echo "usage: " $scriptname " inpdffile outtifroot" + exit -1 +fi + +inpdffile=$1 +outtifroot=$2 + +# strip off directory and suffix parts of $1 to use in other names +basename=${1##*/} +baseroot=${basename%.*} + +# make names for temporary files +tmppdffile=${baseroot}.$$_.pdf +tmppdfroot=${tmppdffile%.*} + +# have the temporary files deleted on exit, interrupt, etc: +trap "/bin/rm -f ${tmppdfroot}*" EXIT SIGHUP SIGINT SIGTERM + +cp $inpdffile $tmppdffile + +# need mysterious "primer" +#echo "0 neg 0 neg" translate | gs -sDEVICE=tiffg4 -sOutputFile=${outtifroot}%03d.tif -r300x300 -q - ${tmppdffile} +echo "0 neg 0 neg" translate | gs -sDEVICE=tiffg4 -sOutputFile=${outtifroot}%03d.tif -g2550x3300 -r300x300 -q - ${tmppdffile} + +#tiffcp -c g4 ${tmppsfile%.*}*.tif $outtiffile + diff --git a/leptonica/prog/pdfio1_reg.c b/leptonica/prog/pdfio1_reg.c new file mode 100644 index 00000000..1d93b491 --- /dev/null +++ b/leptonica/prog/pdfio1_reg.c @@ -0,0 +1,318 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * pdfio1_reg.c + * + * Basic high-level interface tests + * Single images + * Multiple images + * Segmented images, with and without colormaps + * 1 bpp images + * + * Low-level interface tests for 1 bpp images + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include <string.h> +#include "allheaders.h" + +int main(int argc, + char **argv) +{ +l_uint8 *data8; +l_int32 i, j, seq; +size_t nbytes; +const char *title; +BOX *box; +L_COMP_DATA *cid; +L_PDF_DATA *lpd; +PIX *pix1, *pix2, *pix3; +PIX *pixs, *pixt, *pixg, *pixgc, *pixc; +PIXCMAP *cmap; +L_REGPARAMS *rp; + +#if !defined(HAVE_LIBPNG) + L_ERROR("This test requires libpng to run.\n", "pdfio1_reg"); + exit(77); +#endif +#if !defined(HAVE_LIBJPEG) + L_ERROR("This test requires libjpeg to run.\n", "pdfio1_reg"); + exit(77); +#endif +#if !defined(HAVE_LIBTIFF) + L_ERROR("This test requires libtiff to run.\n", "pdfio1_reg"); + exit(77); +#endif + + if (regTestSetup(argc, argv, &rp)) + return 1; + + l_pdfSetDateAndVersion(0); + lept_mkdir("lept/pdf1"); + +#if 1 + /* --------------- Single image tests ------------------- */ + lept_stderr("\n*** Writing single images as pdf files\n"); + convertToPdf("weasel2.4c.png", L_FLATE_ENCODE, 0, + "/tmp/lept/pdf1/file00.pdf", + 0, 0, 72, "weasel2.4c.png", NULL, 0); + convertToPdf("test24.jpg", L_JPEG_ENCODE, 0, "/tmp/lept/pdf1/file01.pdf", + 0, 0, 72, "test24.jpg", NULL, 0); + convertToPdf("feyn.tif", L_G4_ENCODE, 0, "/tmp/lept/pdf1/file02.pdf", + 0, 0, 300, "feyn.tif", NULL, 0); + + pixs = pixRead("feyn.tif"); + pixConvertToPdf(pixs, L_G4_ENCODE, 0, "/tmp/lept/pdf1/file03.pdf", 0, 0, 300, + "feyn.tif", NULL, 0); + pixDestroy(&pixs); + + pixs = pixRead("test24.jpg"); + pixConvertToPdf(pixs, L_JPEG_ENCODE, 5, "/tmp/lept/pdf1/file04.pdf", + 0, 0, 72, "test24.jpg", NULL, 0); + pixDestroy(&pixs); + + pixs = pixRead("feyn.tif"); + pixt = pixScaleToGray2(pixs); + pixWrite("/tmp/lept/pdf1/feyn8.png", pixt, IFF_PNG); + convertToPdf("/tmp/lept/pdf1/feyn8.png", L_JPEG_ENCODE, 0, + "/tmp/lept/pdf1/file05.pdf", 0, 0, 150, "feyn8.png", NULL, 0); + pixDestroy(&pixs); + pixDestroy(&pixt); + + convertToPdf("weasel4.16g.png", L_FLATE_ENCODE, 0, + "/tmp/lept/pdf1/file06.pdf", 0, 0, 30, + "weasel4.16g.png", NULL, 0); + + pixs = pixRead("test24.jpg"); + pixg = pixConvertTo8(pixs, 0); + box = boxCreate(100, 100, 100, 100); + pixc = pixClipRectangle(pixs, box, NULL); + pixgc = pixClipRectangle(pixg, box, NULL); + pixWrite("/tmp/lept/pdf1/pix32.jpg", pixc, IFF_JFIF_JPEG); + pixWrite("/tmp/lept/pdf1/pix8.jpg", pixgc, IFF_JFIF_JPEG); + convertToPdf("/tmp/lept/pdf1/pix32.jpg", L_FLATE_ENCODE, 0, + "/tmp/lept/pdf1/file07.pdf", 0, 0, 72, "pix32.jpg", NULL, 0); + convertToPdf("/tmp/lept/pdf1/pix8.jpg", L_FLATE_ENCODE, 0, + "/tmp/lept/pdf1/file08.pdf", 0, 0, 72, "pix8.jpg", NULL, 0); + pixDestroy(&pixs); + pixDestroy(&pixg); + pixDestroy(&pixc); + pixDestroy(&pixgc); + boxDestroy(&box); +#endif + + +#if 1 + /* --------------- Multiple image tests ------------------- */ + lept_stderr("\n*** Writing multiple images as single page pdf files\n"); + pix1 = pixRead("feyn-fract.tif"); + pix2 = pixRead("weasel8.240c.png"); + + /* First, write the 1 bpp image through the mask onto the weasels */ + for (i = 0; i < 5; i++) { + for (j = 0; j < 10; j++) { + seq = (i == 0 && j == 0) ? L_FIRST_IMAGE : L_NEXT_IMAGE; + title = (i == 0 && j == 0) ? "feyn-fract.tif" : NULL; + pixConvertToPdf(pix2, L_FLATE_ENCODE, 0, NULL, 100 * j, + 100 * i, 70, title, &lpd, seq); + } + } + pixConvertToPdf(pix1, L_G4_ENCODE, 0, "/tmp/lept/pdf1/file09.pdf", 0, 0, 80, + NULL, &lpd, L_LAST_IMAGE); + + /* Now, write the 1 bpp image over the weasels */ + l_pdfSetG4ImageMask(0); + for (i = 0; i < 5; i++) { + for (j = 0; j < 10; j++) { + seq = (i == 0 && j == 0) ? L_FIRST_IMAGE : L_NEXT_IMAGE; + title = (i == 0 && j == 0) ? "feyn-fract.tif" : NULL; + pixConvertToPdf(pix2, L_FLATE_ENCODE, 0, NULL, 100 * j, + 100 * i, 70, title, &lpd, seq); + } + } + pixConvertToPdf(pix1, L_G4_ENCODE, 0, "/tmp/lept/pdf1/file10.pdf", 0, 0, 80, + NULL, &lpd, L_LAST_IMAGE); + l_pdfSetG4ImageMask(1); + pixDestroy(&pix1); + pixDestroy(&pix2); +#endif + +#if 1 + /* -------- pdf convert segmented with no image regions -------- */ + lept_stderr("\n*** Writing segmented images without image regions\n"); + pix1 = pixRead("rabi.png"); + pix2 = pixScaleToGray2(pix1); + pixWrite("/tmp/lept/pdf1/rabi8.jpg", pix2, IFF_JFIF_JPEG); + pix3 = pixThresholdTo4bpp(pix2, 16, 1); + pixWrite("/tmp/lept/pdf1/rabi4.png", pix3, IFF_PNG); + pixDestroy(&pix1); + pixDestroy(&pix2); + pixDestroy(&pix3); + + /* 1 bpp input */ + convertToPdfSegmented("rabi.png", 300, L_G4_ENCODE, 128, NULL, 0, 0, + NULL, "/tmp/lept/pdf1/file11.pdf"); + convertToPdfSegmented("rabi.png", 300, L_JPEG_ENCODE, 128, NULL, 0, 0, + NULL, "/tmp/lept/pdf1/file12.pdf"); + convertToPdfSegmented("rabi.png", 300, L_FLATE_ENCODE, 128, NULL, 0, 0, + NULL, "/tmp/lept/pdf1/file13.pdf"); + + /* 8 bpp input, no cmap */ + convertToPdfSegmented("/tmp/lept/pdf1/rabi8.jpg", 150, L_G4_ENCODE, 128, + NULL, 0, 0, NULL, "/tmp/lept/pdf1/file14.pdf"); + convertToPdfSegmented("/tmp/lept/pdf1/rabi8.jpg", 150, L_JPEG_ENCODE, 128, + NULL, 0, 0, NULL, "/tmp/lept/pdf1/file15.pdf"); + convertToPdfSegmented("/tmp/lept/pdf1/rabi8.jpg", 150, L_FLATE_ENCODE, 128, + NULL, 0, 0, NULL, "/tmp/lept/pdf1/file16.pdf"); + + /* 4 bpp input, cmap */ + convertToPdfSegmented("/tmp/lept/pdf1/rabi4.png", 150, L_G4_ENCODE, 128, + NULL, 0, 0, NULL, "/tmp/lept/pdf1/file17.pdf"); + convertToPdfSegmented("/tmp/lept/pdf1/rabi4.png", 150, L_JPEG_ENCODE, 128, + NULL, 0, 0, NULL, "/tmp/lept/pdf1/file18.pdf"); + convertToPdfSegmented("/tmp/lept/pdf1/rabi4.png", 150, L_FLATE_ENCODE, 128, + NULL, 0, 0, NULL, "/tmp/lept/pdf1/file19.pdf"); + +#endif + +#if 1 + /* ---------- Generating from 1 bpp images (high-level) -------------- */ + lept_stderr("\n*** Writing 1 bpp images as pdf files (high-level)\n"); + pix1 = pixRead("feyn-fract.tif"); + pixWrite("/tmp/lept/pdf1/feyn-nocmap.png", pix1, IFF_PNG); + pix2 = pixCopy(NULL, pix1); + cmap = pixcmapCreate(1); + pixcmapAddColor(cmap, 0, 0, 0); /* with cmap: black bg, white letters */ + pixcmapAddColor(cmap, 255, 255, 255); + pixSetColormap(pix2, cmap); + pixWrite("/tmp/lept/pdf1/feyn-cmap1.png", pix2, IFF_PNG); + cmap = pixcmapCreate(1); + pixcmapAddColor(cmap, 200, 0, 0); /* with cmap: red bg, white letters */ + pixcmapAddColor(cmap, 255, 255, 255); + pixSetColormap(pix1, cmap); + pixWrite("/tmp/lept/pdf1/feyn-cmap2.png", pix1, IFF_PNG); + + convertToPdf("/tmp/lept/pdf1/feyn-nocmap.png", L_FLATE_ENCODE, 0, + "/tmp/lept/pdf1/file20.pdf", + 0, 0, 0, NULL, NULL, 0); + convertToPdf("/tmp/lept/pdf1/feyn-cmap1.png", L_FLATE_ENCODE, 0, + "/tmp/lept/pdf1/file21.pdf", + 0, 0, 0, NULL, NULL, 0); + convertToPdf("/tmp/lept/pdf1/feyn-cmap2.png", L_FLATE_ENCODE, 0, + "/tmp/lept/pdf1/file22.pdf", + 0, 0, 0, NULL, NULL, 0); + pixDestroy(&pix1); + pixDestroy(&pix2); +#endif + +#if 1 + /* ---------- Generating from 1 bpp images (low-level) -------------- */ + lept_stderr("\n*** Writing 1 bpp images as pdf files (low-level)\n"); + pix1 = pixRead("cat-and-mouse.png"); + pix2 = pixConvertRGBToCmapLossless(pix1); /* restore the cmap */ + + /* Add a black/white colormap */ + cmap = pixcmapCreate(1); + pixcmapAddColor(cmap, 255, 255, 255); /* white = 0 */ + pixcmapAddColor(cmap, 0, 0, 0); /* black = 1 */ + pixSetColormap(pix2, cmap); /* replace with a b/w colormap */ + pixWrite("/tmp/lept/pdf1/cat-and-mouse-cmap1.png", pix2, IFF_PNG); + + /* Generate a pdf from this pix. The pdf has the colormap */ + pixGenerateCIData(pix2, L_FLATE_ENCODE, 0, 0, &cid); + lept_stderr(" Should have 2 colors: %d\n", cid->ncolors); + cidConvertToPdfData(cid, "with colormap", &data8, &nbytes); + l_binaryWrite("/tmp/lept/pdf1/file23.pdf", "w", data8, nbytes); + lept_free(data8); + + /* Generate a pdf from the colormap file: + * l_generateCIDataForPdf() calls l_generateFlateDataPdf() + * which calls pixRead(), removing the cmap */ + l_generateCIDataForPdf("/tmp/lept/pdf1/cat-and-mouse-cmap1.png", + NULL, 75, &cid); + lept_stderr(" Should have 0 colors: %d\n", cid->ncolors); + cidConvertToPdfData(cid, "no colormap", &data8, &nbytes); + l_binaryWrite("/tmp/lept/pdf1/file24.pdf", "w", data8, nbytes); + lept_free(data8); + + /* Use an arbitrary colormap */ + cmap = pixcmapCreate(1); + pixcmapAddColor(cmap, 254, 240, 185); // yellow + pixcmapAddColor(cmap, 50, 50, 130); // blue + pixSetColormap(pix2, cmap); + pixWrite("/tmp/lept/pdf1/cat-and-mouse-cmap2.png", pix2, IFF_PNG); + + /* Generate a pdf from this pix. The pdf has the colormap. */ + pixGenerateCIData(pix2, L_FLATE_ENCODE, 0, 0, &cid); + lept_stderr(" Should have 2 colors: %d\n", cid->ncolors); + cidConvertToPdfData(cid, "with colormap", &data8, &nbytes); + l_binaryWrite("/tmp/lept/pdf1/file25.pdf", "w", data8, nbytes); + lept_free(data8); + + /* Generate a pdf from the cmap file. No cmap in the pdf. */ + l_generateCIDataForPdf("/tmp/lept/pdf1/cat-and-mouse-cmap2.png", + NULL, 75, &cid); + lept_stderr(" Should have 0 colors: %d\n", cid->ncolors); + cidConvertToPdfData(cid, "no colormap", &data8, &nbytes); + l_binaryWrite("/tmp/lept/pdf1/file26.pdf", "w", data8, nbytes); + lept_free(data8); + pixDestroy(&pix1); + pixDestroy(&pix2); +#endif + + regTestCheckFile(rp, "/tmp/lept/pdf1/file00.pdf"); + regTestCheckFile(rp, "/tmp/lept/pdf1/file01.pdf"); + regTestCheckFile(rp, "/tmp/lept/pdf1/file02.pdf"); + regTestCheckFile(rp, "/tmp/lept/pdf1/file03.pdf"); + regTestCheckFile(rp, "/tmp/lept/pdf1/file04.pdf"); + regTestCheckFile(rp, "/tmp/lept/pdf1/file05.pdf"); + regTestCheckFile(rp, "/tmp/lept/pdf1/file06.pdf"); + regTestCheckFile(rp, "/tmp/lept/pdf1/file07.pdf"); + regTestCheckFile(rp, "/tmp/lept/pdf1/file08.pdf"); + regTestCheckFile(rp, "/tmp/lept/pdf1/file09.pdf"); + regTestCheckFile(rp, "/tmp/lept/pdf1/file10.pdf"); + regTestCheckFile(rp, "/tmp/lept/pdf1/file11.pdf"); + regTestCheckFile(rp, "/tmp/lept/pdf1/file12.pdf"); + regTestCheckFile(rp, "/tmp/lept/pdf1/file13.pdf"); + regTestCheckFile(rp, "/tmp/lept/pdf1/file14.pdf"); + regTestCheckFile(rp, "/tmp/lept/pdf1/file15.pdf"); + regTestCheckFile(rp, "/tmp/lept/pdf1/file16.pdf"); + regTestCheckFile(rp, "/tmp/lept/pdf1/file17.pdf"); + regTestCheckFile(rp, "/tmp/lept/pdf1/file18.pdf"); + regTestCheckFile(rp, "/tmp/lept/pdf1/file19.pdf"); + regTestCheckFile(rp, "/tmp/lept/pdf1/file20.pdf"); + regTestCheckFile(rp, "/tmp/lept/pdf1/file21.pdf"); + regTestCheckFile(rp, "/tmp/lept/pdf1/file22.pdf"); + regTestCheckFile(rp, "/tmp/lept/pdf1/file23.pdf"); + regTestCheckFile(rp, "/tmp/lept/pdf1/file24.pdf"); + regTestCheckFile(rp, "/tmp/lept/pdf1/file25.pdf"); + regTestCheckFile(rp, "/tmp/lept/pdf1/file26.pdf"); + return regTestCleanup(rp); +} diff --git a/leptonica/prog/pdfio2_reg.c b/leptonica/prog/pdfio2_reg.c new file mode 100644 index 00000000..696907fc --- /dev/null +++ b/leptonica/prog/pdfio2_reg.c @@ -0,0 +1,376 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * pdfio2_reg.c + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include <string.h> +#include "allheaders.h" + +static void GetImageMask(PIX *pixs, l_int32 res, BOXA **pboxa, + L_REGPARAMS *rp, const char *debugfile); +static PIX * QuantizeNonImageRegion(PIX *pixs, PIX *pixm, l_int32 levels); + + +int main(int argc, + char **argv) +{ +l_uint8 *data; +l_int32 w, h, same; +size_t nbytes; +BOXA *boxa1, *boxa2; +L_BYTEA *ba; +PIX *pix1, *pix2, *pix3, *pix4, *pix5, *pix6; +L_REGPARAMS *rp; + +#if !defined(HAVE_LIBPNG) + L_ERROR("This test requires libpng to run.\n", "pdfio2_reg"); + exit(77); +#endif +#if !defined(HAVE_LIBJPEG) + L_ERROR("This test requires libjpeg to run.\n", "pdfio2_reg"); + exit(77); +#endif +#if !defined(HAVE_LIBTIFF) + L_ERROR("This test requires libtiff to run.\n", "pdfio2_reg"); + exit(77); +#endif + + if (regTestSetup(argc, argv, &rp)) + return 1; + + l_pdfSetDateAndVersion(0); + lept_mkdir("lept/pdf2"); + + /* ---------- pdf convert segmented with image regions ---------- */ + lept_stderr("\n*** Writing segmented images with image regions\n"); + startTimer(); + + /* Get the image region(s) for rabi.png. There are two + * small bogus regions at the top, but we'll keep them for + * the demonstration. */ + pix1 = pixRead("rabi.png"); + pix2 = pixScaleToGray2(pix1); + pixWrite("/tmp/lept/pdf2/rabi8.jpg", pix2, IFF_JFIF_JPEG); + pix3 = pixThresholdTo4bpp(pix2, 16, 1); + pixWrite("/tmp/lept/pdf2/rabi4.png", pix3, IFF_PNG); + pixDestroy(&pix2); + pixDestroy(&pix3); + pixSetResolution(pix1, 300, 300); + pixGetDimensions(pix1, &w, &h, NULL); + pix2 = pixGenerateHalftoneMask(pix1, NULL, NULL, NULL); + pix3 = pixMorphSequence(pix2, "c20.1 + c1.20", 0); + boxa1 = pixConnComp(pix3, NULL, 8); + boxa2 = boxaTransform(boxa1, 0, 0, 0.5, 0.5); + pixDestroy(&pix1); + pixDestroy(&pix2); + pixDestroy(&pix3); + + /* 1 bpp input */ + convertToPdfSegmented("rabi.png", 300, L_G4_ENCODE, 128, boxa1, + 0, 0.25, NULL, "/tmp/lept/pdf2/file00.pdf"); + convertToPdfSegmented("rabi.png", 300, L_JPEG_ENCODE, 128, boxa1, + 0, 0.25, NULL, "/tmp/lept/pdf2/file01.pdf"); + convertToPdfSegmented("rabi.png", 300, L_FLATE_ENCODE, 128, boxa1, + 0, 0.25, NULL, "/tmp/lept/pdf2/file02.pdf"); + + /* 8 bpp input, no cmap */ + convertToPdfSegmented("/tmp/lept/pdf2/rabi8.jpg", 150, L_G4_ENCODE, 128, + boxa2, 0, 0.5, NULL, "/tmp/lept/pdf2/file03.pdf"); + convertToPdfSegmented("/tmp/lept/pdf2/rabi8.jpg", 150, L_JPEG_ENCODE, 128, + boxa2, 0, 0.5, NULL, "/tmp/lept/pdf2/file04.pdf"); + convertToPdfSegmented("/tmp/lept/pdf2/rabi8.jpg", 150, L_FLATE_ENCODE, 128, + boxa2, 0, 0.5, NULL, "/tmp/lept/pdf2/file05.pdf"); + + /* 4 bpp input, cmap */ + convertToPdfSegmented("/tmp/lept/pdf2/rabi4.png", 150, L_G4_ENCODE, 128, + boxa2, 0, 0.5, NULL, "/tmp/lept/pdf2/file06.pdf"); + convertToPdfSegmented("/tmp/lept/pdf2/rabi4.png", 150, L_JPEG_ENCODE, 128, + boxa2, 0, 0.5, NULL, "/tmp/lept/pdf2/file07.pdf"); + convertToPdfSegmented("/tmp/lept/pdf2/rabi4.png", 150, L_FLATE_ENCODE, 128, + boxa2, 0, 0.5, NULL, "/tmp/lept/pdf2/file08.pdf"); + + /* 4 bpp input, cmap, data output */ + data = NULL; + convertToPdfDataSegmented("/tmp/lept/pdf2/rabi4.png", 150, L_G4_ENCODE, + 128, boxa2, 0, 0.5, NULL, &data, &nbytes); + l_binaryWrite("/tmp/lept/pdf2/file09.pdf", "w", data, nbytes); + lept_free(data); + convertToPdfDataSegmented("/tmp/lept/pdf2/rabi4.png", 150, L_JPEG_ENCODE, + 128, boxa2, 0, 0.5, NULL, &data, &nbytes); + l_binaryWrite("/tmp/lept/pdf2/file10.pdf", "w", data, nbytes); + lept_free(data); + convertToPdfDataSegmented("/tmp/lept/pdf2/rabi4.png", 150, L_FLATE_ENCODE, + 128, boxa2, 0, 0.5, NULL, &data, &nbytes); + l_binaryWrite("/tmp/lept/pdf2/file11.pdf", "w", data, nbytes); + lept_free(data); + lept_stderr("Segmented images time: %7.3f\n", stopTimer()); + + boxaDestroy(&boxa1); + boxaDestroy(&boxa2); + +#if 1 + /* -------- pdf convert segmented from color image -------- */ + lept_stderr("\n*** Writing color segmented images\n"); + startTimer(); + + pix1 = pixRead("candelabrum.011.jpg"); + pix2 = pixScale(pix1, 3.0, 3.0); + pixWrite("/tmp/lept/pdf2/candelabrum3.jpg", pix2, IFF_JFIF_JPEG); + GetImageMask(pix2, 200, &boxa1, rp, "/tmp/lept/pdf2/seg1.jpg"); + convertToPdfSegmented("/tmp/lept/pdf2/candelabrum3.jpg", 200, L_G4_ENCODE, + 100, boxa1, 0, 0.25, NULL, + "/tmp/lept/pdf2/file12.pdf"); + convertToPdfSegmented("/tmp/lept/pdf2/candelabrum3.jpg", 200, L_JPEG_ENCODE, + 100, boxa1, 0, 0.25, NULL, + "/tmp/lept/pdf2/file13.pdf"); + convertToPdfSegmented("/tmp/lept/pdf2/candelabrum3.jpg", 200, L_FLATE_ENCODE, + 100, boxa1, 0, 0.25, NULL, + "/tmp/lept/pdf2/file14.pdf"); + + pixDestroy(&pix1); + pixDestroy(&pix2); + boxaDestroy(&boxa1); + + pix1 = pixRead("lion-page.00016.jpg"); + pix2 = pixScale(pix1, 3.0, 3.0); + pixWrite("/tmp/lept/pdf2/lion16.jpg", pix2, IFF_JFIF_JPEG); + pix3 = pixRead("lion-mask.00016.tif"); + boxa1 = pixConnComp(pix3, NULL, 8); + boxa2 = boxaTransform(boxa1, 0, 0, 3.0, 3.0); + convertToPdfSegmented("/tmp/lept/pdf2/lion16.jpg", 200, L_G4_ENCODE, + 190, boxa2, 0, 0.5, NULL, "/tmp/lept/pdf2/file15.pdf"); + convertToPdfSegmented("/tmp/lept/pdf2/lion16.jpg", 200, L_JPEG_ENCODE, + 190, boxa2, 0, 0.5, NULL, "/tmp/lept/pdf2/file16.pdf"); + convertToPdfSegmented("/tmp/lept/pdf2/lion16.jpg", 200, L_FLATE_ENCODE, + 190, boxa2, 0, 0.5, NULL, "/tmp/lept/pdf2/file17.pdf"); + + /* Quantize the non-image part and flate encode. + * This is useful because it results in a smaller file than + * when you flate-encode the un-quantized non-image regions. */ + pix4 = pixScale(pix3, 3.0, 3.0); /* higher res mask, for combining */ + pix5 = QuantizeNonImageRegion(pix2, pix4, 12); + pixWrite("/tmp/lept/pdf2/lion16-quant.png", pix5, IFF_PNG); + convertToPdfSegmented("/tmp/lept/pdf2/lion16-quant.png", 200, L_FLATE_ENCODE, + 190, boxa2, 0, 0.5, NULL, "/tmp/lept/pdf2/file18.pdf"); + lept_stderr("Color segmented images time: %7.3f\n", stopTimer()); + + pixDestroy(&pix1); + pixDestroy(&pix2); + pixDestroy(&pix3); + pixDestroy(&pix4); + pixDestroy(&pix5); + boxaDestroy(&boxa1); + boxaDestroy(&boxa2); +#endif + +#if 1 + /* -- Test simple interface for generating multi-page pdf from images -- */ + lept_stderr("\n*** Writing multipage pdfs from images"); + startTimer(); + + /* Put four image files in a directory. They will be encoded thus: + * file1.png: flate (8 bpp, only 10 colors) + * file2.jpg: dct (8 bpp, 256 colors because of the jpeg encoding) + * file3.tif: g4 (1 bpp) + * file4.jpg: dct (32 bpp) */ + lept_mkdir("lept/image"); + pix1 = pixRead("feyn.tif"); + pix2 = pixRead("rabi.png"); + pix3 = pixScaleToGray3(pix1); + pix4 = pixScaleToGray3(pix2); + pix5 = pixScale(pix1, 0.33, 0.33); + pix6 = pixRead("test24.jpg"); + pixWrite("/tmp/lept/image/file1.png", pix3, IFF_PNG); /* 10 colors */ + pixWrite("/tmp/lept/image/file2.jpg", pix4, IFF_JFIF_JPEG); /* 256 colors */ + pixWrite("/tmp/lept/image/file3.tif", pix5, IFF_TIFF_G4); + pixWrite("/tmp/lept/image/file4.jpg", pix6, IFF_JFIF_JPEG); + + startTimer(); + convertFilesToPdf("/tmp/lept/image", "file", 100, 0.8, 0, 75, "4 file test", + "/tmp/lept/pdf2/file19.pdf"); + lept_stderr("4-page pdf generated: /tmp/lept/pdf2/file19.pdf\n" + "Multi-page gen time: %7.3f\n", stopTimer()); + pixDestroy(&pix1); + pixDestroy(&pix2); + pixDestroy(&pix3); + pixDestroy(&pix4); + pixDestroy(&pix5); + pixDestroy(&pix6); +#endif + + regTestCheckFile(rp, "/tmp/lept/pdf2/file00.pdf"); + regTestCheckFile(rp, "/tmp/lept/pdf2/file01.pdf"); + regTestCheckFile(rp, "/tmp/lept/pdf2/file02.pdf"); + regTestCheckFile(rp, "/tmp/lept/pdf2/file03.pdf"); + regTestCheckFile(rp, "/tmp/lept/pdf2/file04.pdf"); + regTestCheckFile(rp, "/tmp/lept/pdf2/file05.pdf"); + regTestCheckFile(rp, "/tmp/lept/pdf2/file06.pdf"); + regTestCheckFile(rp, "/tmp/lept/pdf2/file07.pdf"); + regTestCheckFile(rp, "/tmp/lept/pdf2/file08.pdf"); + regTestCheckFile(rp, "/tmp/lept/pdf2/file09.pdf"); + regTestCheckFile(rp, "/tmp/lept/pdf2/file10.pdf"); + regTestCheckFile(rp, "/tmp/lept/pdf2/file11.pdf"); + regTestCheckFile(rp, "/tmp/lept/pdf2/file12.pdf"); + regTestCheckFile(rp, "/tmp/lept/pdf2/file13.pdf"); + regTestCheckFile(rp, "/tmp/lept/pdf2/file14.pdf"); + regTestCheckFile(rp, "/tmp/lept/pdf2/file15.pdf"); + regTestCheckFile(rp, "/tmp/lept/pdf2/file16.pdf"); + regTestCheckFile(rp, "/tmp/lept/pdf2/file17.pdf"); + regTestCheckFile(rp, "/tmp/lept/pdf2/file18.pdf"); + regTestCheckFile(rp, "/tmp/lept/pdf2/file19.pdf"); + +#if 1 + /* ------------------ Test multipage pdf generation ----------------- */ + lept_stderr("\n*** Writing multipage pdfs from single page pdfs\n"); + + /* Generate a multi-page pdf from all these files */ + startTimer(); + concatenatePdf("/tmp/lept/pdf2", "file", "/tmp/lept/pdf2/cat_lept.pdf"); + lept_stderr("All files are concatenated: /tmp/lept/pdf2/cat_lept.pdf\n" + "Concatenation time: %7.3f\n", stopTimer()); +#endif + +#if 1 + /* ----------- Test corruption recovery by concatenation ------------ */ + /* Put two good pdf files in a directory */ + startTimer(); + lept_rmdir("lept/good"); + lept_mkdir("lept/good"); + lept_cp("testfile1.pdf", "lept/good", NULL, NULL); + lept_cp("testfile2.pdf", "lept/good", NULL, NULL); + concatenatePdf("/tmp/lept/good", "file", "/tmp/lept/pdf2/good.pdf"); + + /* Make a bad version with the pdf id removed, so that it is not + * recognized as a pdf */ + lept_rmdir("lept/bad"); + lept_mkdir("lept/bad"); + ba = l_byteaInitFromFile("testfile2.pdf"); + data = l_byteaGetData(ba, &nbytes); + l_binaryWrite("/tmp/lept/bad/testfile0.notpdf.pdf", "w", + data + 10, nbytes - 10); + + /* Make a version with a corrupted trailer */ + if (data) + data[2297] = '2'; /* munge trailer object 6: change 458 --> 428 */ + l_binaryWrite("/tmp/lept/bad/testfile2.bad.pdf", "w", data, nbytes); + l_byteaDestroy(&ba); + + /* Copy testfile1.pdf to the /tmp/lept/bad directory. Then + * run concat on the bad files. The "not pdf" file should be + * ignored, and the corrupted pdf file should be properly parsed, + * so the resulting concatenated pdf files should be identical. */ + lept_stderr("\nWe attempt to build from a bad directory\n"); + lept_stderr("******************************************************\n"); + lept_stderr("* The next 3 error messages are intentional *\n"); + lept_cp("testfile1.pdf", "lept/bad", NULL, NULL); + concatenatePdf("/tmp/lept/bad", "file", "/tmp/lept/pdf2/bad.pdf"); + lept_stderr("******************************************************\n"); + filesAreIdentical("/tmp/lept/pdf2/good.pdf", "/tmp/lept/pdf2/bad.pdf", + &same); + if (same) + lept_stderr("Fixed: files are the same\nAttempt succeeded\n"); + else + lept_stderr("Busted: files are different\n"); + lept_stderr("Corruption recovery time: %7.3f\n", stopTimer()); +#endif + +#if 0 +{ + char buffer[512]; + char *tempfile1, *tempfile2; + l_int32 ret; + + lept_stderr("\n*** pdftk writes multipage pdfs from images\n"); + tempfile1 = genPathname("/tmp/lept/pdf2", "file*.pdf"); + tempfile2 = genPathname("/tmp/lept/pdf2", "cat_pdftk.pdf"); + snprintf(buffer, sizeof(buffer), "pdftk %s output %s", + tempfile1, tempfile2); + ret = system(buffer); /* pdftk */ + lept_free(tempfile1); + lept_free(tempfile2); +} +#endif + + return regTestCleanup(rp); +} + + +static void +GetImageMask(PIX *pixs, + l_int32 res, + BOXA **pboxa, + L_REGPARAMS *rp, + const char *debugfile) +{ +PIX *pix1, *pix2, *pix3, *pix4; +PIXA *pixa; + + pixSetResolution(pixs, 200, 200); + pix1 = pixConvertTo1(pixs, 100); + pix2 = pixGenerateHalftoneMask(pix1, NULL, NULL, NULL); + pix3 = pixMorphSequence(pix2, "c20.1 + c1.20", 0); + *pboxa = pixConnComp(pix3, NULL, 8); + if (debugfile) { + pixa = pixaCreate(0); + pixaAddPix(pixa, pixs, L_COPY); + pixaAddPix(pixa, pix1, L_INSERT); + pixaAddPix(pixa, pix2, L_INSERT); + pixaAddPix(pixa, pix3, L_INSERT); + pix4 = pixaDisplayTiledInRows(pixa, 32, 1800, 0.25, 0, 25, 2); + pixWrite(debugfile, pix4, IFF_JFIF_JPEG); + pixDisplayWithTitle(pix4, 100, 100, NULL, rp->display); + pixDestroy(&pix4); + pixaDestroy(&pixa); + } else { + pixDestroy(&pix1); + pixDestroy(&pix2); + pixDestroy(&pix3); + } + + return; +} + +static PIX * +QuantizeNonImageRegion(PIX *pixs, + PIX *pixm, + l_int32 levels) +{ +PIX *pix1, *pix2, *pixd; + + pix1 = pixConvertTo8(pixs, 0); + pix2 = pixThresholdOn8bpp(pix1, levels, 1); + pixd = pixConvertTo32(pix2); /* save in rgb */ + pixCombineMasked(pixd, pixs, pixm); /* rgb result */ + pixDestroy(&pix1); + pixDestroy(&pix2); + return pixd; +} diff --git a/leptonica/prog/pdfseg_reg.c b/leptonica/prog/pdfseg_reg.c new file mode 100644 index 00000000..0d020152 --- /dev/null +++ b/leptonica/prog/pdfseg_reg.c @@ -0,0 +1,183 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * pdfseg_reg.c + * + * Generates segmented images and encodes them efficiently in pdf. + * The encoding is mixed-raster, with the image parts encoded as + * DCT at one resolution and the non-image parts encoded at (typically) + * a higher resolution. + * + * Uses 6 images, all segmented and scaled to a fixed width + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + + /* All images scaled to this width */ +static const l_int32 WIDTH = 800; + +int main(int argc, + char **argv) +{ +l_int32 h; +l_float32 scalefactor; +BOX *box; +BOXA *boxa1, *boxa2; +BOXAA *baa; +PIX *pix1, *pix2, *pix3, *pix4, *pix5, *pix6, *pix7, *pix8, *pix9; +L_REGPARAMS *rp; + +#if !defined(HAVE_LIBPNG) + L_ERROR("This test requires libpng to run.\n", "pdfseg_reg"); + exit(77); +#endif +#if !defined(HAVE_LIBJPEG) + L_ERROR("This test requires libjpeg to run.\n", "pdfseg_reg"); + exit(77); +#endif +#if !defined(HAVE_LIBTIFF) + L_ERROR("This test requires libtiff to run.\n", "pdfseg_reg"); + exit(77); +#endif + + if (regTestSetup(argc, argv, &rp)) + return 1; + + lept_rmdir("lept/pdfseg"); + lept_mkdir("lept/pdfseg"); + baa = boxaaCreate(5); + + /* Image region input. */ + pix1 = pixRead("wet-day.jpg"); + pix2 = pixScaleToSize(pix1, WIDTH, 0); + pixWrite("/tmp/lept/pdfseg/0.jpg", pix2, IFF_JFIF_JPEG); + regTestCheckFile(rp, "/tmp/lept/pdfseg/0.jpg"); /* 0 */ + box = boxCreate(105, 161, 620, 872); /* image region */ + boxa1 = boxaCreate(1); + boxaAddBox(boxa1, box, L_INSERT); + boxaaAddBoxa(baa, boxa1, L_INSERT); + pixDestroy(&pix1); + pixDestroy(&pix2); + + /* Compute image region at w = 2 * WIDTH */ + pix1 = pixRead("candelabrum.011.jpg"); + pix2 = pixScaleToSize(pix1, WIDTH, 0); + pix3 = pixConvertTo1(pix2, 100); + pix4 = pixExpandBinaryPower2(pix3, 2); /* w = 2 * WIDTH */ + pix5 = pixGenerateHalftoneMask(pix4, NULL, NULL, NULL); + pix6 = pixMorphSequence(pix5, "c20.1 + c1.20", 0); + pix7 = pixMaskConnComp(pix6, 8, &boxa1); + pix8 = pixReduceBinary2(pix7, NULL); /* back to w = WIDTH */ + pix9 = pixBackgroundNormSimple(pix2, pix8, NULL); + pixWrite("/tmp/lept/pdfseg/1.jpg", pix9, IFF_JFIF_JPEG); + regTestCheckFile(rp, "/tmp/lept/pdfseg/1.jpg"); /* 1 */ + boxa2 = boxaTransform(boxa1, 0, 0, 0.5, 0.5); /* back to w = WIDTH */ + boxaaAddBoxa(baa, boxa2, L_INSERT); + boxaDestroy(&boxa1); + pixDestroy(&pix1); + pixDestroy(&pix2); + pixDestroy(&pix3); + pixDestroy(&pix4); + pixDestroy(&pix5); + pixDestroy(&pix6); + pixDestroy(&pix7); + pixDestroy(&pix8); + pixDestroy(&pix9); + + /* Use mask to find image region */ + pix1 = pixRead("lion-page.00016.jpg"); + pix2 = pixScaleToSize(pix1, WIDTH, 0); + pixWrite("/tmp/lept/pdfseg/2.jpg", pix2, IFF_JFIF_JPEG); + regTestCheckFile(rp, "/tmp/lept/pdfseg/2.jpg"); /* 2 */ + pix3 = pixRead("lion-mask.00016.tif"); + pix4 = pixScaleToSize(pix3, WIDTH, 0); + boxa1 = pixConnComp(pix4, NULL, 8); + boxaaAddBoxa(baa, boxa1, L_INSERT); + pixDestroy(&pix1); + pixDestroy(&pix2); + pixDestroy(&pix3); + pixDestroy(&pix4); + + /* Compute image region at full res */ + pix1 = pixRead("rabi.png"); + scalefactor = (l_float32)WIDTH / (l_float32)pixGetWidth(pix1); + pix2 = pixScaleToGray(pix1, scalefactor); + pixWrite("/tmp/lept/pdfseg/3.jpg", pix2, IFF_JFIF_JPEG); + regTestCheckFile(rp, "/tmp/lept/pdfseg/3.jpg"); /* 3 */ + pix3 = pixGenerateHalftoneMask(pix1, NULL, NULL, NULL); + pix4 = pixMorphSequence(pix3, "c20.1 + c1.20", 0); + boxa1 = pixConnComp(pix4, NULL, 8); + boxa2 = boxaTransform(boxa1, 0, 0, scalefactor, scalefactor); + boxaaAddBoxa(baa, boxa2, L_INSERT); + pixDestroy(&pix1); + pixDestroy(&pix2); + pixDestroy(&pix3); + pixDestroy(&pix4); + boxaDestroy(&boxa1); + + /* Page with no image regions */ + pix1 = pixRead("lucasta.047.jpg"); + pix2 = pixScaleToSize(pix1, WIDTH, 0); + boxa1 = boxaCreate(1); + pixWrite("/tmp/lept/pdfseg/4.jpg", pix2, IFF_JFIF_JPEG); + regTestCheckFile(rp, "/tmp/lept/pdfseg/4.jpg"); /* 4 */ + boxaaAddBoxa(baa, boxa1, L_INSERT); + pixDestroy(&pix1); + pixDestroy(&pix2); + + /* Page that is all image */ + pix1 = pixRead("map1.jpg"); + pix2 = pixScaleToSize(pix1, WIDTH, 0); + pixWrite("/tmp/lept/pdfseg/5.jpg", pix2, IFF_JFIF_JPEG); + regTestCheckFile(rp, "/tmp/lept/pdfseg/5.jpg"); /* 5 */ + h = pixGetHeight(pix2); + box = boxCreate(0, 0, WIDTH, h); + boxa1 = boxaCreate(1); + boxaAddBox(boxa1, box, L_INSERT); + boxaaAddBoxa(baa, boxa1, L_INSERT); + pixDestroy(&pix1); + pixDestroy(&pix2); + + /* Save the boxaa file */ + boxaaWrite("/tmp/lept/pdfseg/images.baa", baa); + regTestCheckFile(rp, "/tmp/lept/pdfseg/images.baa"); /* 6 */ + + /* Do the conversion */ + l_pdfSetDateAndVersion(FALSE); + convertSegmentedFilesToPdf("/tmp/lept/pdfseg", "jpg", 100, L_G4_ENCODE, + 140, baa, 75, 0.6, "Segmentation Test", + "/tmp/lept/regout/pdfseg.7.pdf"); + L_INFO("Generated pdf file: /tmp/lept/regout/pdfseg.7.pdf\n", rp->testname); + regTestCheckFile(rp, "/tmp/lept/regout/pdfseg.7.pdf"); /* 7 */ + + boxaaDestroy(&baa); + return regTestCleanup(rp); +} diff --git a/leptonica/prog/pedante.079.jpg b/leptonica/prog/pedante.079.jpg Binary files differnew file mode 100644 index 00000000..30aae0da --- /dev/null +++ b/leptonica/prog/pedante.079.jpg diff --git a/leptonica/prog/percolate-4cc.png b/leptonica/prog/percolate-4cc.png Binary files differnew file mode 100644 index 00000000..c5392e0c --- /dev/null +++ b/leptonica/prog/percolate-4cc.png diff --git a/leptonica/prog/percolate-8cc.png b/leptonica/prog/percolate-8cc.png Binary files differnew file mode 100644 index 00000000..a1cfd91a --- /dev/null +++ b/leptonica/prog/percolate-8cc.png diff --git a/leptonica/prog/percolatetest.c b/leptonica/prog/percolatetest.c new file mode 100644 index 00000000..eb182b48 --- /dev/null +++ b/leptonica/prog/percolatetest.c @@ -0,0 +1,322 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * percolatetest.c + * + * This tests the code that keeps track of connected components as + * pixels are added (randomly, here) to a pix. + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + +static PIX *PixDisplayWithColormap(PIX *pixs, l_int32 repl); + + +l_int32 main(int argc, + char **argv) +{ +l_int32 i, x, y, ncc, npta; +NUMA *na1; +PIX *pixs, *pix1, *pix2, *pix3; +PIXA *pixa; +PTAA *ptaa; + + if (argc != 1) { + lept_stderr(" Syntax: percolatetest\n"); + return 1; + } + + setLeptDebugOK(1); + lept_mkdir("lept/perc"); + + /* Fill in a tiny pix; 4 connected */ + pixa = pixaCreate(0); + pixs = pixCreate(5, 5, 1); + pixConnCompIncrInit(pixs, 4, &pix1, &ptaa, &ncc); + lept_stderr("ncc = %d, npta = %d\n", ncc, ptaaGetCount(ptaa)); + srand(26); + for (i = 0; i < 50; i++) { + pixGetRandomPixel(pix1, NULL, &x, &y); + pixConnCompIncrAdd(pix1, ptaa, &ncc, x, y, 2); + npta = ptaaGetCount(ptaa); + lept_stderr("x,y = (%d,%d), num c.c. = %d, num pta = %d\n", + x, y, ncc, npta); + pix2 = PixDisplayWithColormap(pix1, 20); + pixaAddPix(pixa, pix2, L_INSERT); + } + pix3 = pixaDisplayTiledInRows(pixa, 32, 1500, 1.0, 0, 30, 2); + pixDisplay(pix3, 0, 0); + pixWrite("/tmp/lept/perc/file1.png", pix3, IFF_PNG); + pixDestroy(&pixs); + pixDestroy(&pix1); + pixDestroy(&pix3); + pixaDestroy(&pixa); + ptaaDestroy(&ptaa); + + /* Fill in a tiny pix; 8 connected */ + pixa = pixaCreate(0); + pixs = pixCreate(5, 5, 1); + pixConnCompIncrInit(pixs, 8, &pix1, &ptaa, &ncc); + lept_stderr("ncc = %d, npta = %d\n", ncc, ptaaGetCount(ptaa)); + srand(26); + for (i = 0; i < 50; i++) { + pixGetRandomPixel(pix1, NULL, &x, &y); + pixConnCompIncrAdd(pix1, ptaa, &ncc, x, y, 2); + npta = ptaaGetCount(ptaa); + lept_stderr("x,y = (%d,%d), num c.c. = %d, num pta = %d\n", + x, y, ncc, npta); + pix2 = PixDisplayWithColormap(pix1, 20); + pixaAddPix(pixa, pix2, L_INSERT); + } + pix3 = pixaDisplayTiledInRows(pixa, 32, 1500, 1.0, 0, 30, 2); + pixDisplay(pix3, 0, 560); + pixWrite("/tmp/lept/perc/file2.png", pix3, IFF_PNG); + pixDestroy(&pixs); + pixDestroy(&pix1); + pixDestroy(&pix3); + pixaDestroy(&pixa); + ptaaDestroy(&ptaa); + + /* Fill in a small pix; 4 connected */ + na1 = numaCreate(700); + pixa = pixaCreate(0); + pixs = pixCreate(20, 20, 1); + pixConnCompIncrInit(pixs, 4, &pix1, &ptaa, &ncc); + lept_stderr("ncc = %d, npta = %d\n", ncc, ptaaGetCount(ptaa)); + srand(26); + for (i = 0; i < 700; i++) { + pixGetRandomPixel(pix1, NULL, &x, &y); + pixConnCompIncrAdd(pix1, ptaa, &ncc, x, y, 2); + numaAddNumber(na1, ncc); + npta = ptaaGetCount(ptaa); + if (i < 100) { + lept_stderr("x,y = (%d,%d), num c.c. = %d, num pta = %d\n", + x, y, ncc, npta); + } + if (i % 30 == 1) { + pix2 = PixDisplayWithColormap(pix1, 5); + pixaAddPix(pixa, pix2, L_INSERT); + } + } + pix3 = pixaDisplayTiledInRows(pixa, 32, 1500, 1.0, 0, 30, 2); + pixDisplay(pix3, 0, 0); + pixWrite("/tmp/lept/perc/file3.png", pix3, IFF_PNG); + gplotSimple1(na1, GPLOT_PNG, "/tmp/lept/plot1", + "Number of components: 4 cc"); + pixDestroy(&pixs); + pixDestroy(&pix1); + pixDestroy(&pix3); + pixaDestroy(&pixa); + ptaaDestroy(&ptaa); + numaDestroy(&na1); + + /* Fill in a small pix; 8 connected */ + na1 = numaCreate(700); + pixa = pixaCreate(0); + pixs = pixCreate(20, 20, 1); + pixConnCompIncrInit(pixs, 8, &pix1, &ptaa, &ncc); + lept_stderr("ncc = %d, npta = %d\n", ncc, ptaaGetCount(ptaa)); + srand(26); + for (i = 0; i < 700; i++) { + pixGetRandomPixel(pix1, NULL, &x, &y); + pixConnCompIncrAdd(pix1, ptaa, &ncc, x, y, 2); + numaAddNumber(na1, ncc); + npta = ptaaGetCount(ptaa); + if (i < 100) { + lept_stderr("x,y = (%d,%d), num c.c. = %d, num pta = %d\n", + x, y, ncc, npta); + } + if (i % 30 == 1) { + pix2 = PixDisplayWithColormap(pix1, 5); + pixaAddPix(pixa, pix2, L_INSERT); + } + } + pix3 = pixaDisplayTiledInRows(pixa, 32, 1500, 1.0, 0, 30, 2); + pixDisplay(pix3, 0, 360); + pixWrite("/tmp/lept/perc/file4.png", pix3, IFF_PNG); + gplotSimple1(na1, GPLOT_PNG, "/tmp/lept/plot2", + "Number of components: 8 cc"); + pixDestroy(&pixs); + pixDestroy(&pix1); + pixDestroy(&pix3); + pixaDestroy(&pixa); + ptaaDestroy(&ptaa); + numaDestroy(&na1); + + /* Fill in a larger pix; 4 connected */ + pixa = pixaCreate(0); + na1 = numaCreate(20000); + pixs = pixCreate(195, 56, 1); + pixConnCompIncrInit(pixs, 4, &pix1, &ptaa, &ncc); + lept_stderr("ncc = %d, npta = %d\n", ncc, ptaaGetCount(ptaa)); + srand(26); + for (i = 0; i < 20000; i++) { + pixGetRandomPixel(pix1, NULL, &x, &y); + pixConnCompIncrAdd(pix1, ptaa, &ncc, x, y, 3); + npta = ptaaGetCount(ptaa); + numaAddNumber(na1, ncc); + if (i % 500 == 1) { + pix2 = PixDisplayWithColormap(pix1, 3); + pixaAddPix(pixa, pix2, L_INSERT); + lept_stderr("x,y = (%d,%d), num c.c. = %d, num pta = %d\n", + x, y, ncc, npta); + } + } + pix3 = pixaDisplayTiledInRows(pixa, 32, 1500, 1.0, 0, 30, 2); + pixDisplay(pix3, 0, 0); + pixWrite("/tmp/lept/perc/file5.png", pix3, IFF_PNG); + gplotSimple1(na1, GPLOT_PNG, "/tmp/lept/plot3", + "Number of components: 4 connected"); + pixDestroy(&pixs); + pixDestroy(&pix1); + pixDestroy(&pix3); + pixaDestroy(&pixa); + ptaaDestroy(&ptaa); + numaDestroy(&na1); + + /* Fill in a larger pix; 8 connected */ + pixa = pixaCreate(0); + na1 = numaCreate(20000); + pixs = pixCreate(195, 56, 1); + pixConnCompIncrInit(pixs, 8, &pix1, &ptaa, &ncc); + srand(26); + lept_stderr("ncc = %d, npta = %d\n", ncc, ptaaGetCount(ptaa)); + for (i = 0; i < 20000; i++) { + pixGetRandomPixel(pix1, NULL, &x, &y); + pixConnCompIncrAdd(pix1, ptaa, &ncc, x, y, 3); + npta = ptaaGetCount(ptaa); + numaAddNumber(na1, ncc); + if (i % 500 == 1) { + pix2 = PixDisplayWithColormap(pix1, 3); + pixaAddPix(pixa, pix2, L_INSERT); + lept_stderr("x,y = (%d,%d), num c.c. = %d, num pta = %d\n", + x, y, ncc, npta); + } + } + pix3 = pixaDisplayTiledInRows(pixa, 32, 1500, 1.0, 0, 30, 2); + pixDisplay(pix3, 340, 0); + pixWrite("/tmp/lept/perc/file6.png", pix3, IFF_PNG); + gplotSimple1(na1, GPLOT_PNG, "/tmp/lept/plot4", + "Number of components: 8 connected"); + pixDestroy(&pixs); + pixDestroy(&pix1); + pixDestroy(&pix3); + pixaDestroy(&pixa); + ptaaDestroy(&ptaa); + numaDestroy(&na1); + + /* Fill in a larger pix; 8 connected; init with feyn-word.tif */ + pixa = pixaCreate(0); + na1 = numaCreate(20000); + pixs = pixRead("feyn-word.tif"); + pixConnCompIncrInit(pixs, 8, &pix1, &ptaa, &ncc); + srand(26); + lept_stderr("ncc = %d, npta = %d\n", ncc, ptaaGetCount(ptaa)); + for (i = 0; i < 20000; i++) { + pixGetRandomPixel(pix1, NULL, &x, &y); + pixConnCompIncrAdd(pix1, ptaa, &ncc, x, y, 3); + npta = ptaaGetCount(ptaa); + numaAddNumber(na1, ncc); + if (i % 500 == 1) { + pix2 = PixDisplayWithColormap(pix1, 3); + pixaAddPix(pixa, pix2, L_INSERT); + lept_stderr("x,y = (%d,%d), num c.c. = %d, num pta = %d\n", + x, y, ncc, npta); + } + } + pix3 = pixaDisplayTiledInRows(pixa, 32, 1500, 1.0, 0, 30, 2); + pixDisplay(pix3, 0, 0); + pixWrite("/tmp/lept/perc/file7.png", pix3, IFF_PNG); + gplotSimple1(na1, GPLOT_PNG, "/tmp/lept/plot5", + "Number of components: 8 connected"); + pixDestroy(&pixs); + pixDestroy(&pix1); + pixDestroy(&pix3); + pixaDestroy(&pixa); + ptaaDestroy(&ptaa); + numaDestroy(&na1); + + /* Do 10M pixel adds on an 8M pixel image! + * This gets it down to about 385 8-connected components. + * With 18.3M pixel adds, you finally arrive at 1 component. + * Speed: this does about 1.3M pixel adds/sec. Most of the time + * is used to write the 280MB plot data file and then generate + * the plot (percolate-4cc.png, percolate-8cc.png). */ +#if 0 + pixs = pixRead("feyn.tif"); +// pixs = pixCreate(2500, 3200, 1); + na1 = numaCreate(10000000); + pixConnCompIncrInit(pixs, 4, &pix1, &ptaa, &ncc); + pix2 = PixDisplayWithColormap(pix1, 1); + pixDisplay(pix2, 0, 0); + pixDestroy(&pix2); + lept_stderr("ncc = %d, npta = %d\n", ncc, ptaaGetCount(ptaa)); + lept_stderr("Now add 10M points: this takes about 7 seconds!\n"); + for (i = 0; i < 10000000; i++) { + pixGetRandomPixel(pix1, NULL, &x, &y); + pixConnCompIncrAdd(pix1, ptaa, &ncc, x, y, 0); + numaAddNumber(na1, ncc); + } + + lept_stderr("Plot the 10M points: this takes about 20 seconds\n"); + gplotSimple1(na1, GPLOT_PNG, "/tmp/lept/plot6", + "Number of components: 4 connected, 8 million pixels"); + pix3 = pixRead("/tmp/lept/plot6.png"); + pixDisplay(pix3, 500, 0); + pixDestroy(&pixs); + pixDestroy(&pix1); + pixDestroy(&pix3); + pixaDestroy(&pixa); + ptaaDestroy(&ptaa); + numaDestroy(&na1); +#endif + return 0; +} + + + /* This displays a pix where the pixel values are 32 bit labels + * using a random colormap whose index is the LSB of each pixel value, + * and where white is at index 0. */ +PIX * +PixDisplayWithColormap(PIX *pixs, l_int32 repl) +{ +PIX *pix1, *pixd; +PIXCMAP *cmap; + + cmap = pixcmapCreateRandom(8, 0, 0); + pixcmapResetColor(cmap, 0, 255, 255, 255); + pix1 = pixConvert32To8(pixs, L_LS_TWO_BYTES, L_LS_BYTE); + pixd = pixExpandReplicate(pix1, repl); + pixSetColormap(pixd, cmap); + pixDestroy(&pix1); + return pixd; +} + diff --git a/leptonica/prog/pixa1_reg.c b/leptonica/prog/pixa1_reg.c new file mode 100644 index 00000000..5de883b3 --- /dev/null +++ b/leptonica/prog/pixa1_reg.c @@ -0,0 +1,170 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * pixa1_reg.c + * + * Tests removal of connected components. + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + +static const l_int32 CONNECTIVITY = 8; + +int main(int argc, + char **argv) +{ +l_int32 size, i, n, n0; +BOXA *boxa; +GPLOT *gplot; +NUMA *nax, *nay1, *nay2; +PIX *pixs, *pix1, *pixd; +PIXA *pixa; +L_REGPARAMS *rp; + + if (regTestSetup(argc, argv, &rp)) + return 1; + + pixs = pixRead("feyn-fract.tif"); + lept_mkdir("lept/pixa"); + pixa = pixaCreate(2); + + /* ---------------- Remove small components --------------- */ + boxa = pixConnComp(pixs, NULL, 8); + n0 = boxaGetCount(boxa); + nax = numaMakeSequence(0, 2, 51); + nay1 = numaCreate(51); + nay2 = numaCreate(51); + boxaDestroy(&boxa); + + if (rp->display) { + lept_stderr("\n Select Large if Both\n"); + lept_stderr("Iter 0: n = %d\n", n0); + } + numaAddNumber(nay1, n0); + for (i = 1; i <= 50; i++) { + size = 2 * i; + pixd = pixSelectBySize(pixs, size, size, CONNECTIVITY, + L_SELECT_IF_BOTH, L_SELECT_IF_GTE, NULL); + boxa = pixConnComp(pixd, NULL, 8); + n = boxaGetCount(boxa); + numaAddNumber(nay1, n); + if (rp->display) lept_stderr("Iter %d: n = %d\n", i, n); + boxaDestroy(&boxa); + pixDestroy(&pixd); + } + + if (rp->display) { + lept_stderr("\n Select Large if Either\n"); + lept_stderr("Iter 0: n = %d\n", n0); + } + numaAddNumber(nay2, n0); + for (i = 1; i <= 50; i++) { + size = 2 * i; + pixd = pixSelectBySize(pixs, size, size, CONNECTIVITY, + L_SELECT_IF_EITHER, L_SELECT_IF_GTE, NULL); + boxa = pixConnComp(pixd, NULL, 8); + n = boxaGetCount(boxa); + numaAddNumber(nay2, n); + if (rp->display) lept_stderr("Iter %d: n = %d\n", i, n); + boxaDestroy(&boxa); + pixDestroy(&pixd); + } + + gplot = gplotCreate("/tmp/lept/pixa/root1", GPLOT_PNG, + "Select large: number of cc vs size removed", + "min size", "number of c.c."); + gplotAddPlot(gplot, nax, nay1, GPLOT_LINES, "select if both"); + gplotAddPlot(gplot, nax, nay2, GPLOT_LINES, "select if either"); + pix1 = gplotMakeOutputPix(gplot); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 0 */ + pixaAddPix(pixa, pix1, L_INSERT); + gplotDestroy(&gplot); + + /* ---------------- Remove large components --------------- */ + numaEmpty(nay1); + numaEmpty(nay2); + + if (rp->display) { + lept_stderr("\n Select Small if Both\n"); + lept_stderr("Iter 0: n = %d\n", 0); + } + numaAddNumber(nay1, 0); + for (i = 1; i <= 50; i++) { + size = 2 * i; + pixd = pixSelectBySize(pixs, size, size, CONNECTIVITY, + L_SELECT_IF_BOTH, L_SELECT_IF_LTE, NULL); + boxa = pixConnComp(pixd, NULL, 8); + n = boxaGetCount(boxa); + numaAddNumber(nay1, n); + if (rp->display) lept_stderr("Iter %d: n = %d\n", i, n); + boxaDestroy(&boxa); + pixDestroy(&pixd); + } + + if (rp->display) { + lept_stderr("\n Select Small if Either\n"); + lept_stderr("Iter 0: n = %d\n", 0); + } + numaAddNumber(nay2, 0); + for (i = 1; i <= 50; i++) { + size = 2 * i; + pixd = pixSelectBySize(pixs, size, size, CONNECTIVITY, + L_SELECT_IF_EITHER, L_SELECT_IF_LTE, NULL); + boxa = pixConnComp(pixd, NULL, 8); + n = boxaGetCount(boxa); + numaAddNumber(nay2, n); + if (rp->display) lept_stderr("Iter %d: n = %d\n", i, n); + boxaDestroy(&boxa); + pixDestroy(&pixd); + } + + gplot = gplotCreate("/tmp/lept/pixa/root2", GPLOT_PNG, + "Remove large: number of cc vs size removed", + "min size", "number of c.c."); + gplotAddPlot(gplot, nax, nay1, GPLOT_LINES, "select if both"); + gplotAddPlot(gplot, nax, nay2, GPLOT_LINES, "select if either"); + pix1 = gplotMakeOutputPix(gplot); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 1 */ + pixaAddPix(pixa, pix1, L_INSERT); + gplotDestroy(&gplot); + + pixd = pixaDisplayTiledInRows(pixa, 32, 1500, 1.0, 0, 20, 2); + pixDisplayWithTitle(pixd, 100, 0, NULL, rp->display); + pixWrite("/tmp/lept/pixa/root.png", pixd, IFF_PNG); + pixDestroy(&pixd); + pixaDestroy(&pixa); + + numaDestroy(&nax); + numaDestroy(&nay1); + numaDestroy(&nay2); + pixDestroy(&pixs); + return regTestCleanup(rp); +} diff --git a/leptonica/prog/pixa2_reg.c b/leptonica/prog/pixa2_reg.c new file mode 100644 index 00000000..5b651df9 --- /dev/null +++ b/leptonica/prog/pixa2_reg.c @@ -0,0 +1,121 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * pixa2_reg.c + * + * Tests various replacement functions on pixa. + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + +int main(int argc, + char **argv) +{ +const char *name; +l_int32 i, n; +BOX *box; +PIX *pix0, *pix1, *pixd; +PIXA *pixa; +SARRAY *sa1, *sa2, *sa3, *sa4; +L_REGPARAMS *rp; + + if (regTestSetup(argc, argv, &rp)) + return 1; + + /* ---------------- Find all the jpg and tif images --------------- */ + sa1 = getSortedPathnamesInDirectory(".", ".jpg", 0, 0); + sa2 = getSortedPathnamesInDirectory(".", ".tif", 0, 0); + sa3 = sarraySelectByRange(sa1, 10, 19); + sa4 = sarraySelectByRange(sa2, 10, 19); + sarrayJoin(sa3, sa4); + n =sarrayGetCount(sa3); + sarrayDestroy(&sa1); + sarrayDestroy(&sa2); + sarrayDestroy(&sa4); + if (rp->display) sarrayWriteStream(stderr, sa3); + + /* ---------------- Use replace to fill up a pixa -------------------*/ + pixa = pixaCreate(1); + pixaExtendArrayToSize(pixa, n); + if ((pix0 = pixRead("marge.jpg")) == NULL) + rp->success = FALSE; + pix1 = pixScaleToSize(pix0, 144, 108); /* scale 0.25 */ + pixDestroy(&pix0); + pixaInitFull(pixa, pix1, NULL); /* fill it up */ + pixd = pixaDisplayTiledInRows(pixa, 32, 1000, 1.0, 0, 25, 2); + pixDisplayWithTitle(pixd, 100, 100, NULL, rp->display); + pixWrite("/tmp/lept/regout/pixa2-1.jpg", pixd, IFF_JFIF_JPEG); + pixDestroy(&pix1); + pixDestroy(&pixd); + + /* ---------------- And again with jpgs and tifs -------------------*/ + for (i = 0; i < n; i++) { + name = sarrayGetString(sa3, i, L_NOCOPY); + if ((pix0 = pixRead(name)) == NULL) { + lept_stderr("Error in %s_reg: failed to read %s\n", + rp->testname, name); + rp->success = FALSE; + continue; + } + pix1 = pixScaleToSize(pix0, 144, 108); + pixaReplacePix(pixa, i, pix1, NULL); + pixDestroy(&pix0); + } + pixd = pixaDisplayTiledInRows(pixa, 32, 1000, 1.0, 0, 25, 2); + pixDisplayWithTitle(pixd, 400, 100, NULL, rp->display); + pixWrite("/tmp/lept/regout/pixa2-2.jpg", pixd, IFF_JFIF_JPEG); + pixDestroy(&pixd); + + /* ---------------- And again, reversing the order ------------------*/ + box = boxCreate(0, 0, 0, 0); + pixaInitFull(pixa, NULL, box); + boxDestroy(&box); + for (i = 0; i < n; i++) { + name = sarrayGetString(sa3, i, L_NOCOPY); + if ((pix0 = pixRead(name)) == NULL) { + lept_stderr("Error in %s_reg: failed to read %s\n", + rp->testname, name); + rp->success = FALSE; + continue; + } + pix1 = pixScaleToSize(pix0, 144, 108); + pixaReplacePix(pixa, n - 1 - i, pix1, NULL); + pixDestroy(&pix0); + } + pixd = pixaDisplayTiledInRows(pixa, 32, 1000, 1.0, 0, 25, 2); + pixDisplayWithTitle(pixd, 700, 100, NULL, rp->display); + pixWrite("/tmp/lept/regout/pixa2-3.jpg", pixd, IFF_JFIF_JPEG); + pixDestroy(&pixd); + sarrayDestroy(&sa3); + + pixaDestroy(&pixa); + return regTestCleanup(rp); +} diff --git a/leptonica/prog/pixaatest.c b/leptonica/prog/pixaatest.c new file mode 100644 index 00000000..2053f01c --- /dev/null +++ b/leptonica/prog/pixaatest.c @@ -0,0 +1,109 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * pixaatest.c + * + * Syntax: pixaatest + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + +static const l_int32 nx = 10; +static const l_int32 ny = 12; +static const l_int32 ncols = 3; + +int main(int argc, + char **argv) +{ +l_int32 w, d, tilewidth; +PIX *pixs; +PIXA *pixa, *pixad1, *pixad2; +PIXAA *pixaa1, *pixaa2; +static char mainName[] = "pixaatest"; + + if (argc != 1) + return ERROR_INT(" Syntax: pixaatest", mainName, 1); + + setLeptDebugOK(1); + lept_mkdir("/lept/paa"); + + /* Read in file, split it into a set of tiles, and generate a pdf. + * Two things to note for these tiny images: + * (1) If you use dct format (jpeg) for each image instead of + * flate (lossless), the quantization will be apparent. + * (2) If the resolution in pixaConvertToPdf() is above 50, and + * you add a red boundary, you will see errors in the boundary + * width. + */ + pixs = pixRead("test24.jpg"); + pixGetDimensions(pixs, &w, NULL, &d); + pixa = pixaSplitPix(pixs, nx, ny, 0, 0); +/* pixa = pixaSplitPix(pixs, nx, ny, 2, 0xff000000); */ /* red border */ + pixWrite("/tmp/lept/paa/pix0", pixa->pix[0], IFF_PNG); + pixWrite("/tmp/lept/paa/pix9", pixa->pix[9], IFF_PNG); + pixaConvertToPdf(pixa, 50, 1.0, 0, 95, "individual", + "/tmp/lept/paa/out1.pdf"); + + /* Generate two pixaa by sampling the pixa, and write them to file */ + pixaa1 = pixaaCreateFromPixa(pixa, nx, L_CHOOSE_CONSECUTIVE, L_CLONE); + pixaa2 = pixaaCreateFromPixa(pixa, nx, L_CHOOSE_SKIP_BY, L_CLONE); + pixaaWrite("/tmp/lept/paa/pts1.paa", pixaa1); + pixaaWrite("/tmp/lept/paa/pts2.paa", pixaa2); + pixaDestroy(&pixa); + pixaaDestroy(&pixaa1); + pixaaDestroy(&pixaa2); + + /* Read each pixaa from file; tile/scale into a pixa */ + pixaa1 = pixaaRead("/tmp/lept/paa/pts1.paa"); + pixaa2 = pixaaRead("/tmp/lept/paa/pts2.paa"); + tilewidth = w / nx; + pixad1 = pixaaDisplayTiledAndScaled(pixaa1, d, tilewidth, ncols, 0, 10, 0); + pixad2 = pixaaDisplayTiledAndScaled(pixaa2, d, tilewidth, ncols, 0, 10, 0); + + /* Generate a pdf from each pixa */ + pixaConvertToPdf(pixad1, 50, 1.0, 0, 75, "consecutive", + "/tmp/lept/paa/out2.pdf"); + pixaConvertToPdf(pixad2, 50, 1.0, 0, 75, "skip_by", + "/tmp/lept/paa/out3.pdf"); + + /* Write each pixa to a set of files, and generate a PS */ + pixaWriteFiles("/tmp/lept/paa/split1.", pixad1, IFF_JFIF_JPEG); + pixaWriteFiles("/tmp/lept/paa/split2.", pixad2, IFF_JFIF_JPEG); + convertFilesToPS("/tmp/lept/paa", "split1", 40, "/tmp/lept/paa/out1out1.ps"); + convertFilesToPS("/tmp/lept/paa", "split2", 40, "/tmp/lept/paa/out1out2.ps"); + + pixDestroy(&pixs); + pixaaDestroy(&pixaa1); + pixaaDestroy(&pixaa2); + pixaDestroy(&pixad1); + pixaDestroy(&pixad2); + return 0; +} diff --git a/leptonica/prog/pixadisp_reg.c b/leptonica/prog/pixadisp_reg.c new file mode 100644 index 00000000..52116a44 --- /dev/null +++ b/leptonica/prog/pixadisp_reg.c @@ -0,0 +1,166 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * pixadisp_reg.c + * + * Regression test exercising various pixaDisplay*() functions. + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + +int main(int argc, + char **argv) +{ +l_int32 ws, hs, ncols; +BOX *box; +BOXA *boxa; +PIX *pixs, *pix32, *pix1, *pix2, *pix3, *pix4; +PIXA *pixa, *pixa1, *pixa2, *pixa3; +L_REGPARAMS *rp; + + if (regTestSetup(argc, argv, &rp)) + return 1; + + pixa = pixaCreate(0); + pix32 = pixRead("marge.jpg"); + pixs = pixRead("feyn.tif"); + box = boxCreate(683, 799, 970, 479); + pix1 = pixClipRectangle(pixs, box, NULL); + boxDestroy(&box); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 0 */ + pixaAddPix(pixa, pix1, L_INSERT); + + /* Generate pixa2 from pixs and pixa3 from pix1 */ + boxa = pixConnComp(pixs, &pixa1, 8); + pixa2 = pixaSelectBySize(pixa1, 60, 60, L_SELECT_IF_BOTH, + L_SELECT_IF_LTE, NULL); + pixaDestroy(&pixa1); + boxaDestroy(&boxa); + boxa = pixConnComp(pix1, &pixa3, 8); + boxaDestroy(&boxa); + + /* pixaDisplay() */ + pixGetDimensions(pixs, &ws, &hs, NULL); + pix2 = pixaDisplay(pixa2, ws, hs); + regTestWritePixAndCheck(rp, pix2, IFF_PNG); /* 1 */ + pixaAddPix(pixa, pix2, L_INSERT); + pixDestroy(&pixs); + + /* pixaDisplayRandomCmap() */ + pix2 = pixaDisplayRandomCmap(pixa2, ws, hs); /* black bg */ + regTestWritePixAndCheck(rp, pix2, IFF_PNG); /* 2 */ + pixaAddPix(pixa, pix2, L_COPY); + pixcmapResetColor(pixGetColormap(pix2), 0, 255, 255, 255); /* white bg */ + regTestWritePixAndCheck(rp, pix2, IFF_PNG); /* 3 */ + pixaAddPix(pixa, pix2, L_INSERT); + pixaDestroy(&pixa2); + + /* pixaDisplayOnLattice() */ + pix2 = pixaDisplayOnLattice(pixa3, 50, 50, &ncols, &boxa); + regTestWritePixAndCheck(rp, pix2, IFF_PNG); /* 4 */ + pixaAddPix(pixa, pix2, L_INSERT); + lept_stderr("Number of columns = %d; number of boxes: %d\n", + ncols, boxaGetCount(boxa)); + boxaDestroy(&boxa); + + /* pixaDisplayUnsplit() */ + pixa1 = pixaSplitPix(pix32, 5, 7, 10, 0x0000ff00); + pix2 = pixaDisplayUnsplit(pixa1, 5, 7, 10, 0x00ff0000); + regTestWritePixAndCheck(rp, pix2, IFF_JFIF_JPEG); /* 5 */ + pixaAddPix(pixa, pix2, L_INSERT); + pixaDestroy(&pixa1); + + /* pixaDisplayTiled() */ + pix2 = pixaDisplayTiled(pixa3, 1000, 0, 10); + regTestWritePixAndCheck(rp, pix2, IFF_PNG); /* 6 */ + pixaAddPix(pixa, pix2, L_INSERT); + + /* pixaDisplayTiledInRows() */ + pix2 = pixaDisplayTiledInRows(pixa3, 1, 1000, 1.0, 0, 10, 2); + regTestWritePixAndCheck(rp, pix2, IFF_PNG); /* 7 */ + pixaAddPix(pixa, pix2, L_INSERT); + + /* pixaDisplayTiledAndScaled() */ + pix2 = pixaDisplayTiledAndScaled(pixa3, 1, 25, 20, 0, 5, 0); + regTestWritePixAndCheck(rp, pix2, IFF_PNG); /* 8 */ + pixaAddPix(pixa, pix2, L_INSERT); + pixaDestroy(&pixa3); + + pixa1 = pixaCreate(10); + pix2 = pixRankFilter(pix32, 8, 8, 0.5); + pixaAddPix(pixa1, pix2, L_INSERT); + pix3 = pixScale(pix32, 0.5, 0.5); + pix2 = pixRankFilter(pix3, 8, 8, 0.5); + pixaAddPix(pixa1, pix2, L_INSERT); + pixDestroy(&pix3); + pix3 = pixScale(pix32, 0.25, 0.25); + pix2 = pixRankFilter(pix3, 8, 8, 0.5); + pixaAddPix(pixa1, pix2, L_INSERT); + pixDestroy(&pix3); + pix2 = pixaDisplayTiledAndScaled(pixa1, 32, 500, 3, 0, 25, 0); + regTestWritePixAndCheck(rp, pix2, IFF_JFIF_JPEG); /* 9 */ + pixaAddPix(pixa, pix2, L_INSERT); + pixaDestroy(&pixa1); + pixDestroy(&pix32); + + /* pixaMakeFromTiledPix() and pixaDisplayOnLattice() */ + pix1 = pixRead("sevens.tif"); + pixa1 = pixaMakeFromTiledPix(pix1, 20, 30, 0, 0, NULL); + pix2 = pixaDisplayOnLattice(pixa1, 20, 30, NULL, NULL); + regTestComparePix(rp, pix1, pix2); /* 10 */ + pix3 = pixaDisplayOnLattice(pixa1, 20, 30, NULL, &boxa); + pixa2 = pixaMakeFromTiledPix(pix3, 0, 0, 0, 0, boxa); + pix4 = pixaDisplayOnLattice(pixa2, 20, 30, NULL, NULL); + regTestComparePix(rp, pix2, pix4); /* 11 */ + pixaAddPix(pixa, pixScale(pix4, 2.5, 2.5), L_INSERT); + pixDestroy(&pix1); + pixDestroy(&pix2); + pixDestroy(&pix3); + pixDestroy(&pix4); + boxaDestroy(&boxa); + pixaDestroy(&pixa1); + pixaDestroy(&pixa2); + + if (rp->display) { + lept_mkdir("lept/padisp"); + lept_stderr("Writing to: /tmp/lept/padisp/pixadisp.pdf\n"); + pixaConvertToPdf(pixa, 0, 1.0, L_FLATE_ENCODE, 0, "pixadisp-test", + "/tmp/lept/padisp/pixadisp.pdf"); + lept_stderr("Writing to: /tmp/lept/padisp/pixadisp.jpg\n"); + pix1 = pixaDisplayTiledInColumns(pixa, 2, 0.5, 30, 2); + pixWrite("/tmp/lept/padisp/pixadisp.jpg", pix1, IFF_JFIF_JPEG); + pixDisplay(pix1, 100, 100); + pixDestroy(&pix1); + } + + pixaDestroy(&pixa); + return regTestCleanup(rp); +} diff --git a/leptonica/prog/pixafileinfo.c b/leptonica/prog/pixafileinfo.c new file mode 100644 index 00000000..07ba9454 --- /dev/null +++ b/leptonica/prog/pixafileinfo.c @@ -0,0 +1,82 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * pixafileinfo.c + * + * Returns information about the images in the pixa or pixacomp file + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include <string.h> +#include "allheaders.h" + +int main(int argc, + char **argv) +{ +char buf[64]; +char *sn; +l_int32 i, n; +PIX *pix; +PIXA *pixa; +PIXAC *pac; +char *filein; +static char mainName[] = "pixafileinfo"; + + if (argc != 2) + return ERROR_INT(" Syntax: pixafileinfo filein", mainName, 1); + setLeptDebugOK(1); + + /* Input file can be either pixa or pixacomp */ + filein = argv[1]; + l_getStructStrFromFile(filein, L_STR_NAME, &sn); + if (strcmp(sn, "Pixa") == 0) { + if ((pixa = pixaRead(filein)) == NULL) + return ERROR_INT("pixa not made", mainName, 1); + } else if (strcmp(sn, "Pixacomp") == 0) { + if ((pac = pixacompRead(filein)) == NULL) + return ERROR_INT("pac not made", mainName, 1); + pixa = pixaCreateFromPixacomp(pac, L_COPY); + pixacompDestroy(&pac); + } else { + return ERROR_INT("invalid file type", mainName, 1); + } + + n = pixaGetCount(pixa); + for (i = 0; i < n; i++) { + pix = pixaGetPix(pixa, i, L_CLONE); + snprintf(buf, sizeof(buf), "Pix(%d)", i); + pixPrintStreamInfo(stderr, pix, buf); + pixDestroy(&pix); + lept_stderr("=================================\n"); + } + + pixaDestroy(&pixa); + return 0; +} diff --git a/leptonica/prog/pixalloc_reg.c b/leptonica/prog/pixalloc_reg.c new file mode 100644 index 00000000..3ee29022 --- /dev/null +++ b/leptonica/prog/pixalloc_reg.c @@ -0,0 +1,208 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * pixalloc_reg.c + * + * Tests custom pix allocator. + * + * The custom allocator is intended for situations where a number of large + * pix will be repeatedly allocated and freed over the lifetime of a program. + * If those pix are large, relying on malloc and free can result in + * fragmentation, even if there are no small memory leaks in the program. + * + * Here we test the allocator in two situations: + * * a small number of relatively large pix + * * a large number of very small pix + * + * For the second case, timing shows that the custom allocator does + * about as well as (malloc, free), even for thousands of very small pix. + * (Turn off logging to get a fair comparison). + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include <math.h> +#include "allheaders.h" + +static const l_int32 logging = FALSE; + +static const l_int32 ncopies = 2; +static const l_int32 nlevels = 4; +static const l_int32 ntimes = 30; + + +PIXA *GenerateSetOfMargePix(void); +void CopyStoreClean(PIXA *pixas, l_int32 nlevels, l_int32 ncopies); + + +int main(int argc, + char **argv) +{ +l_int32 i; +BOXA *boxa; +NUMA *nas, *nab; +PIX *pixs; +PIXA *pixa, *pixas; + + setLeptDebugOK(1); + lept_mkdir("lept/alloc"); + + /* ----------------- Custom with a few large pix -----------------*/ + /* Set up pms */ + nas = numaCreate(4); /* small */ + numaAddNumber(nas, 5); + numaAddNumber(nas, 4); + numaAddNumber(nas, 3); + numaAddNumber(nas, 2); + setPixMemoryManager(pmsCustomAlloc, pmsCustomDealloc); + pmsCreate(200000, 400000, nas, "/tmp/lept/alloc/file1.log"); + + /* Make the pix and do successive copies and removals of the copies */ + pixas = GenerateSetOfMargePix(); + startTimer(); + for (i = 0; i < ntimes; i++) + CopyStoreClean(pixas, nlevels, ncopies); + lept_stderr("Time (big pix; custom) = %7.3f sec\n", stopTimer()); + + /* Clean up */ + numaDestroy(&nas); + pixaDestroy(&pixas); + pmsDestroy(); + + + /* ----------------- Standard with a few large pix -----------------*/ + setPixMemoryManager(malloc, free); + + /* Make the pix and do successive copies and removals of the copies */ + startTimer(); + pixas = GenerateSetOfMargePix(); + for (i = 0; i < ntimes; i++) + CopyStoreClean(pixas, nlevels, ncopies); + lept_stderr("Time (big pix; standard) = %7.3f sec\n", stopTimer()); + pixaDestroy(&pixas); + + + /* ----------------- Custom with many small pix -----------------*/ + /* Set up pms */ + nab = numaCreate(10); + numaAddNumber(nab, 2000); + numaAddNumber(nab, 2000); + numaAddNumber(nab, 2000); + numaAddNumber(nab, 500); + numaAddNumber(nab, 100); + numaAddNumber(nab, 100); + numaAddNumber(nab, 100); + setPixMemoryManager(pmsCustomAlloc, pmsCustomDealloc); + if (logging) /* use logging == 0 for speed comparison */ + pmsCreate(20, 40, nab, "/tmp/lept/alloc/file2.log"); + else + pmsCreate(20, 40, nab, NULL); + pixs = pixRead("feyn.tif"); + + startTimer(); + for (i = 0; i < 5; i++) { + boxa = pixConnComp(pixs, &pixa, 8); + boxaDestroy(&boxa); + pixaDestroy(&pixa); + } + + numaDestroy(&nab); + pixDestroy(&pixs); + pmsDestroy(); + lept_stderr("Time (custom) = %7.3f sec\n", stopTimer()); + + + /* ----------------- Standard with many small pix -----------------*/ + setPixMemoryManager(malloc, free); + pixs = pixRead("feyn.tif"); + + startTimer(); + for (i = 0; i < 5; i++) { + boxa = pixConnComp(pixs, &pixa, 8); + boxaDestroy(&boxa); + pixaDestroy(&pixa); + } + pixDestroy(&pixs); + lept_stderr("Time (standard) = %7.3f sec\n", stopTimer()); + return 0; +} + + +PIXA * +GenerateSetOfMargePix(void) +{ +l_float32 factor; +BOX *box; +PIX *pixs, *pixt1, *pixt2, *pixt3, *pixt4; +PIXA *pixa; + + pixs = pixRead("marge.jpg"); + box = boxCreate(130, 93, 263, 253); + factor = sqrt(2.0); + pixt1 = pixClipRectangle(pixs, box, NULL); /* 266 KB */ + pixt2 = pixScale(pixt1, factor, factor); /* 532 KB */ + pixt3 = pixScale(pixt2, factor, factor); /* 1064 KB */ + pixt4 = pixScale(pixt3, factor, factor); /* 2128 KB */ + pixa = pixaCreate(4); + pixaAddPix(pixa, pixt1, L_INSERT); + pixaAddPix(pixa, pixt2, L_INSERT); + pixaAddPix(pixa, pixt3, L_INSERT); + pixaAddPix(pixa, pixt4, L_INSERT); + boxDestroy(&box); + pixDestroy(&pixs); + return pixa; +} + + +void +CopyStoreClean(PIXA *pixas, + l_int32 nlevels, + l_int32 ncopies) +{ +l_int32 i, j; +PIX *pix, *pixt; +PIXA *pixa; +PIXAA *paa; + + paa = pixaaCreate(0); + for (i = 0; i < nlevels ; i++) { + pixa = pixaCreate(0); + pixaaAddPixa(paa, pixa, L_INSERT); + pix = pixaGetPix(pixas, i, L_CLONE); + for (j = 0; j < ncopies; j++) { + pixt = pixCopy(NULL, pix); + pixaAddPix(pixa, pixt, L_INSERT); + } + pixDestroy(&pix); + } + pixaaDestroy(&paa); + + return; +} + diff --git a/leptonica/prog/pixcomp_reg.c b/leptonica/prog/pixcomp_reg.c new file mode 100644 index 00000000..ea581541 --- /dev/null +++ b/leptonica/prog/pixcomp_reg.c @@ -0,0 +1,236 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * pixcomp_reg.c + * + * Regression test for compressed pix and compressed pix arrays + * in memory. + * + * We also show some other ways to accumulate and display pixa. + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include <math.h> +#include "allheaders.h" + +static const char *fnames[] = {"weasel32.png", "weasel2.4c.png", + "weasel4.16c.png", "weasel4.8g.png", + "weasel8.149g.png", "weasel8.16g.png"}; + +LEPT_DLL extern const char *ImageFileFormatExtensions[]; +static void get_format_data(l_int32 i, l_uint8 *data, size_t size); + +int main(int argc, + char **argv) +{ +l_uint8 *data1, *data2; +l_int32 i; +size_t size1, size2; +BOX *box; +PIX *pix, *pix1, *pix2, *pix3; +PIXA *pixa, *pixa1; +PIXC *pixc, *pixc1, *pixc2; +PIXAC *pixac, *pixac1, *pixac2; +L_REGPARAMS *rp; +SARRAY *sa; + + if (regTestSetup(argc, argv, &rp)) + return 1; + + lept_mkdir("lept/comp"); + + pixac = pixacompCreate(1); + pixa = pixaCreate(0); + + /* --- Read in the images --- */ + pix1 = pixRead("marge.jpg"); + pixc1 = pixcompCreateFromPix(pix1, IFF_JFIF_JPEG); + pix2 = pixCreateFromPixcomp(pixc1); + pixc2 = pixcompCreateFromPix(pix2, IFF_JFIF_JPEG); + pix3 = pixCreateFromPixcomp(pixc2); + regTestWritePixAndCheck(rp, pix3, IFF_JFIF_JPEG); /* 0 */ + pixaAddPix(pixa, pix3, L_INSERT); + pixacompAddPix(pixac, pix1, IFF_DEFAULT); + pixDestroy(&pix1); + pixDestroy(&pix2); + pixcompDestroy(&pixc1); + pixcompDestroy(&pixc2); + + pix = pixRead("feyn.tif"); + pix1 = pixScaleToGray6(pix); + pixc1 = pixcompCreateFromPix(pix1, IFF_JFIF_JPEG); + pix2 = pixCreateFromPixcomp(pixc1); + pixc2 = pixcompCreateFromPix(pix2, IFF_JFIF_JPEG); + pix3 = pixCreateFromPixcomp(pixc2); + regTestWritePixAndCheck(rp, pix3, IFF_JFIF_JPEG); /* 1 */ + pixaAddPix(pixa, pix3, L_INSERT); + pixacompAddPix(pixac, pix1, IFF_DEFAULT); + pixDestroy(&pix1); + pixDestroy(&pix2); + pixcompDestroy(&pixc1); + pixcompDestroy(&pixc2); + + box = boxCreate(1144, 611, 690, 180); + pix1 = pixClipRectangle(pix, box, NULL); + pixc1 = pixcompCreateFromPix(pix1, IFF_TIFF_G4); + pix2 = pixCreateFromPixcomp(pixc1); + pixc2 = pixcompCreateFromPix(pix2, IFF_TIFF_G4); + pix3 = pixCreateFromPixcomp(pixc2); + regTestWritePixAndCheck(rp, pix3, IFF_TIFF_G4); /* 2 */ + pixaAddPix(pixa, pix3, L_INSERT); + pixacompAddPix(pixac, pix1, IFF_DEFAULT); + boxDestroy(&box); + pixDestroy(&pix); + pixDestroy(&pix1); + pixDestroy(&pix2); + pixcompDestroy(&pixc1); + pixcompDestroy(&pixc2); + + pix1 = pixRead("weasel4.11c.png"); + pixc1 = pixcompCreateFromPix(pix1, IFF_PNG); + pix2 = pixCreateFromPixcomp(pixc1); + pixc2 = pixcompCreateFromPix(pix2, IFF_PNG); + pix3 = pixCreateFromPixcomp(pixc2); + regTestWritePixAndCheck(rp, pix3, IFF_PNG); /* 3 */ + pixaAddPix(pixa, pix3, L_INSERT); + pixacompAddPix(pixac, pix1, IFF_DEFAULT); + pixDestroy(&pix1); + pixDestroy(&pix2); + pixcompDestroy(&pixc1); + pixcompDestroy(&pixc2); + + /* --- Extract formatting info from compressed strings --- */ + for (i = 0; i < 4; i++) { + pixc = pixacompGetPixcomp(pixac, i, L_NOCOPY); + get_format_data(i, pixc->data, pixc->size); + } + + /* Save a tiled composite from the pixa */ + pix1 = pixaDisplayTiledAndScaled(pixa, 32, 400, 4, 0, 20, 2); + regTestWritePixAndCheck(rp, pix1, IFF_JFIF_JPEG); /* 4 */ + pixaDestroy(&pixa); + pixDestroy(&pix1); + + /* Convert the pixac --> pixa and save a tiled composite */ + pixa1 = pixaCreateFromPixacomp(pixac, L_COPY); + pix1 = pixaDisplayTiledAndScaled(pixa1, 32, 400, 4, 0, 20, 2); + regTestWritePixAndCheck(rp, pix1, IFF_JFIF_JPEG); /* 5 */ + pixaDestroy(&pixa1); + pixDestroy(&pix1); + + /* Make a pixacomp from files, and join */ + sa = sarrayCreate(0); + for (i = 0; i < 6; i++) + sarrayAddString(sa, fnames[i], L_COPY); + pixac1 = pixacompCreateFromSA(sa, IFF_DEFAULT); + pixacompJoin(pixac1, pixac, 0, -1); + pixa1 = pixaCreateFromPixacomp(pixac1, L_COPY); + pix1 = pixaDisplayTiledAndScaled(pixa1, 32, 250, 10, 0, 20, 2); + regTestWritePixAndCheck(rp, pix1, IFF_JFIF_JPEG); /* 6 */ + pixacompDestroy(&pixac1); + pixaDestroy(&pixa1); + pixDestroy(&pix1); + sarrayDestroy(&sa); + + /* Test serialized I/O */ + pixacompWrite("/tmp/lept/comp/file1.pac", pixac); + regTestCheckFile(rp, "/tmp/lept/comp/file1.pac"); /* 7 */ + pixac1 = pixacompRead("/tmp/lept/comp/file1.pac"); + pixacompWrite("/tmp/lept/comp/file2.pac", pixac1); + regTestCheckFile(rp, "/tmp/lept/comp/file2.pac"); /* 8 */ + regTestCompareFiles(rp, 7, 8); /* 9 */ + pixac2 = pixacompRead("/tmp/lept/comp/file2.pac"); + pixa1 = pixaCreateFromPixacomp(pixac2, L_COPY); + pix1 = pixaDisplayTiledAndScaled(pixa1, 32, 250, 4, 0, 20, 2); + regTestWritePixAndCheck(rp, pix1, IFF_JFIF_JPEG); /* 10 */ + pixacompDestroy(&pixac1); + pixacompDestroy(&pixac2); + pixaDestroy(&pixa1); + pixDestroy(&pix1); + + /* Test serialized pixacomp I/O to and from memory */ + pixacompWriteMem(&data1, &size1, pixac); + pixac1 = pixacompReadMem(data1, size1); + pixacompWriteMem(&data2, &size2, pixac1); + pixac2 = pixacompReadMem(data2, size2); + pixacompWrite("/tmp/lept/comp/file3.pac", pixac1); + regTestCheckFile(rp, "/tmp/lept/comp/file3.pac"); /* 11 */ + pixacompWrite("/tmp/lept/comp/file4.pac", pixac2); + regTestCheckFile(rp, "/tmp/lept/comp/file4.pac"); /* 12 */ + regTestCompareFiles(rp, 11, 12); /* 13 */ + pixacompDestroy(&pixac1); + pixacompDestroy(&pixac2); + lept_free(data1); + lept_free(data2); + + /* Test pdf generation (both with and without transcoding */ + pixacompDestroy(&pixac); + pix1 = pixRead("test24.jpg"); + pix2 = pixRead("marge.jpg"); + pixac = pixacompCreate(2); + pixacompAddPix(pixac, pix1, IFF_JFIF_JPEG); + pixacompAddPix(pixac, pix2, IFF_JFIF_JPEG); + l_pdfSetDateAndVersion(0); + pixacompConvertToPdfData(pixac, 0, 1.0, L_DEFAULT_ENCODE, 0, "test1", + &data1, &size1); + regTestWriteDataAndCheck(rp, data1, size1, "pdf"); /* 13 */ + pixacompFastConvertToPdfData(pixac, "test2", &data2, &size2); + regTestWriteDataAndCheck(rp, data2, size2, "pdf"); /* 14 */ + pixDestroy(&pix1); + pixDestroy(&pix2); + pixacompDestroy(&pixac); + lept_free(data1); + lept_free(data2); + + return regTestCleanup(rp); +} + + +static void +get_format_data(l_int32 i, + l_uint8 *data, + size_t size) +{ +l_int32 ret, format, w, h, d, bps, spp, iscmap; + + ret = pixReadHeaderMem(data, size, &format, &w, &h, &bps, &spp, &iscmap); + d = bps * spp; + if (d == 24) d = 32; + if (ret) + lept_stderr("Error: couldn't read data: size = %d\n", (l_int32)size); + else + lept_stderr("Format data for image %d:\n" + " format: %s, size (w, h, d) = (%d, %d, %d)\n" + " bps = %d, spp = %d, iscmap = %d\n", + i, ImageFileFormatExtensions[format], w, h, d, + bps, spp, iscmap); + return; +} + diff --git a/leptonica/prog/pixmem_reg.c b/leptonica/prog/pixmem_reg.c new file mode 100644 index 00000000..6dfd4c12 --- /dev/null +++ b/leptonica/prog/pixmem_reg.c @@ -0,0 +1,152 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * pixmem_reg.c + * + * Tests low-level pix data accessors, and functions that call them. + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + +int main(int argc, + char **argv) +{ +l_uint32 *data; +PIX *pix1, *pix2, *pix3, *pix4, *pix5; +PIXA *pixa; +L_REGPARAMS *rp; + + if (regTestSetup(argc, argv, &rp)) + return 1; + + pixa = pixaCreate(0); + + /* Copy with internal resizing: onto a cmapped image */ + pix1 = pixRead("weasel4.16c.png"); + pix2 = pixRead("feyn-fract.tif"); + pix3 = pixRead("lucasta.150.jpg"); + pixCopy(pix3, pix2); + regTestComparePix(rp, pix2, pix3); /* 0 */ + pixaAddPix(pixa, pix3, L_INSERT); + pixCopy(pix1, pix3); + regTestComparePix(rp, pix1, pix2); /* 1 */ + pixaAddPix(pixa, pix1, L_INSERT); + pixDestroy(&pix2); + + /* Copy with internal resizing: from a cmapped image */ + pix1 = pixRead("weasel4.16c.png"); + pix2 = pixRead("feyn-fract.tif"); + pix3 = pixRead("lucasta.150.jpg"); + pixCopy(pix2, pix1); + regTestComparePix(rp, pix1, pix2); /* 2 */ + pixaAddPix(pixa, pix2, L_INSERT); + pixCopy(pix3, pix2); + regTestComparePix(rp, pix2, pix3); /* 3 */ + pixaAddPix(pixa, pix3, L_INSERT); + pixDestroy(&pix1); + + /* Transfer of data pixs --> pixd, when pixs is not cloned. + * pixs is destroyed. */ + pix1 = pixRead("weasel4.16c.png"); + pix2 = pixRead("feyn-fract.tif"); + pix3 = pixRead("lucasta.150.jpg"); + pix4 = pixCopy(NULL, pix1); + pixTransferAllData(pix2, &pix1, 0, 0); + regTestComparePix(rp, pix2, pix4); /* 4 */ + pixaAddPix(pixa, pix2, L_COPY); + pixTransferAllData(pix3, &pix2, 0, 0); + regTestComparePix(rp, pix3, pix4); /* 5 */ + pixaAddPix(pixa, pix3, L_INSERT); + pixDestroy(&pix4); + + /* Another transfer of data pixs --> pixd, when pixs is not cloned. + * pixs is destroyed. */ + pix1 = pixRead("weasel4.16c.png"); + pix2 = pixRead("feyn-fract.tif"); + pix3 = pixRead("lucasta.150.jpg"); + pix4 = pixCopy(NULL, pix1); + pixTransferAllData(pix2, &pix4, 0, 0); + regTestComparePix(rp, pix1, pix2); /* 6 */ + pixaAddPix(pixa, pix2, L_COPY); + pixTransferAllData(pix3, &pix2, 0, 0); + regTestComparePix(rp, pix1, pix3); /* 7 */ + pixaAddPix(pixa, pix3, L_INSERT); + pixDestroy(&pix1); + + /* Transfer of data pixs --> pixd, when pixs is cloned. + * pixs has its refcount reduced by 1. */ + pix1 = pixRead("weasel4.16c.png"); + pix2 = pixRead("feyn-fract.tif"); + pix3 = pixRead("lucasta.150.jpg"); + pix4 = pixClone(pix1); + pix5 = pixClone(pix2); + pixTransferAllData(pix2, &pix4, 0, 0); + regTestComparePix(rp, pix1, pix2); /* 8 */ + pixaAddPix(pixa, pix2, L_INSERT); + pixTransferAllData(pix3, &pix5, 0, 0); + regTestComparePix(rp, pix1, pix3); /* 9 */ + pixaAddPix(pixa, pix3, L_INSERT); + pixDestroy(&pix1); + + /* Extraction of data when pixs is not cloned, putting + * the data into a new template of pixs. */ + pix2 = pixRead("feyn-fract.tif"); + pix3 = pixCopy(NULL, pix2); /* for later reference */ + data = pixExtractData(pix2); + pix4 = pixCreateTemplateNoInit(pix2); + pixFreeData(pix4); + pixSetData(pix4, data); + regTestComparePix(rp, pix3, pix4); /* 10 */ + pixaAddPix(pixa, pix4, L_INSERT); + pixDestroy(&pix2); + pixDestroy(&pix3); + + /* Extraction of data when pixs is cloned, putting + * a copy of the data into a new template of pixs. */ + pix1 = pixRead("weasel4.16c.png"); + pix2 = pixClone(pix1); /* bump refcount of pix1 to 2 */ + data = pixExtractData(pix1); /* should make a copy of data */ + pix3 = pixCreateTemplateNoInit(pix1); + pixFreeData(pix3); + pixSetData(pix3, data); + regTestComparePix(rp, pix2, pix3); /* 11 */ + pixaAddPix(pixa, pix3, L_INSERT); + pixDestroy(&pix1); + pixDestroy(&pix2); + + pix1 = pixaDisplayTiledInRows(pixa, 32, 1500, 0.5, 0, 30, 2); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 12 */ + pixDisplayWithTitle(pix1, 100, 100, NULL, rp->display); + pixaDestroy(&pixa); + pixDestroy(&pix1); + + return regTestCleanup(rp); +} diff --git a/leptonica/prog/pixserial_reg.c b/leptonica/prog/pixserial_reg.c new file mode 100644 index 00000000..4c34a547 --- /dev/null +++ b/leptonica/prog/pixserial_reg.c @@ -0,0 +1,142 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * pixserial_reg.c + * + * Tests the fast (uncompressed) serialization of pix to a string + * in memory and the deserialization back to a pix. + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + + /* Use this set */ +static l_int32 nfiles = 10; +static const char *filename[] = { + "feyn.tif", /* 1 bpp */ + "dreyfus2.png", /* 2 bpp cmapped */ + "dreyfus4.png", /* 4 bpp cmapped */ + "weasel4.16c.png", /* 4 bpp cmapped */ + "dreyfus8.png", /* 8 bpp cmapped */ + "weasel8.240c.png", /* 8 bpp cmapped */ + "karen8.jpg", /* 8 bpp, not cmapped */ + "test16.tif", /* 8 bpp, not cmapped */ + "marge.jpg", /* rgb */ + "test24.jpg" /* rgb */ + }; + +int main(int argc, + char **argv) +{ +char buf[256]; +size_t size; +l_int32 i, w, h; +l_int32 format, bps, spp, iscmap, format2, w2, h2, bps2, spp2, iscmap2; +l_uint8 *data; +l_uint32 *data32, *data32r; +BOX *box; +PIX *pixs, *pixt, *pixt2, *pixd; +L_REGPARAMS *rp; + + if (regTestSetup(argc, argv, &rp)) + return 1; + + /* Test basic serialization/deserialization */ + data32 = NULL; + for (i = 0; i < nfiles; i++) { + pixs = pixRead(filename[i]); + /* Serialize to memory */ + pixSerializeToMemory(pixs, &data32, &size); + /* Just for fun, write and read back from file */ + l_binaryWrite("/tmp/lept/regout/array", "w", data32, size); + data32r = (l_uint32 *)l_binaryRead("/tmp/lept/regout/array", &size); + /* Deserialize */ + pixd = pixDeserializeFromMemory(data32r, size); + regTestComparePix(rp, pixs, pixd); /* i */ + pixDestroy(&pixd); + pixDestroy(&pixs); + lept_free(data32); + lept_free(data32r); + } + + /* Test read/write fileio interface */ + for (i = 0; i < nfiles; i++) { + pixs = pixRead(filename[i]); + pixGetDimensions(pixs, &w, &h, NULL); + box = boxCreate(0, 0, L_MIN(150, w), L_MIN(150, h)); + pixt = pixClipRectangle(pixs, box, NULL); + boxDestroy(&box); + snprintf(buf, sizeof(buf), "/tmp/lept/regout/pixs.%d.spix", + rp->index + 1); + pixWrite(buf, pixt, IFF_SPIX); + regTestCheckFile(rp, buf); /* nfiles + 2 * i */ + pixt2 = pixRead(buf); + regTestComparePix(rp, pixt, pixt2); /* nfiles + 2 * i + 1 */ + pixDestroy(&pixs); + pixDestroy(&pixt); + pixDestroy(&pixt2); + } + + /* Test read header. Note that for rgb input, spp = 3, + * but for 32 bpp spix, we set spp = 4. */ + data = NULL; + for (i = 0; i < nfiles; i++) { + pixs = pixRead(filename[i]); + pixWriteMem(&data, &size, pixs, IFF_SPIX); + pixReadHeader(filename[i], &format, &w, &h, &bps, &spp, &iscmap); + pixReadHeaderMem(data, size, &format2, &w2, &h2, &bps2, + &spp2, &iscmap2); + if (format2 != IFF_SPIX || w != w2 || h != h2 || bps != bps2 || + iscmap != iscmap2) { + if (rp->fp) + fprintf(rp->fp, "Failure comparing data"); + else + lept_stderr("Failure comparing data"); + } + pixDestroy(&pixs); + lept_free(data); + } + +#if 0 + /* Do timing */ + for (i = 0; i < nfiles; i++) { + pixs = pixRead(filename[i]); + startTimer(); + pixSerializeToMemory(pixs, &data32, &size); + pixd = pixDeserializeFromMemory(data32, size); + lept_stderr("Time for %s: %7.3f sec\n", filename[i], stopTimer()); + lept_free(data32); + pixDestroy(&pixs); + pixDestroy(&pixd); + } +#endif + + return regTestCleanup(rp); +} diff --git a/leptonica/prog/pixtile_reg.c b/leptonica/prog/pixtile_reg.c new file mode 100644 index 00000000..cad6c64e --- /dev/null +++ b/leptonica/prog/pixtile_reg.c @@ -0,0 +1,105 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * pixtile_reg.c + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + +static l_int32 TestTiling(PIX *pixd, PIX *pixs, l_int32 nx, l_int32 ny, + l_int32 w, l_int32 h, l_int32 xoverlap, + l_int32 yoverlap); + + +int main(int argc, + char **argv) +{ +PIX *pixs, *pixd; + + setLeptDebugOK(1); + pixs = pixRead("test24.jpg"); + pixd = pixCreateTemplateNoInit(pixs); + + TestTiling(pixd, pixs, 1, 1, 0, 0, 183, 83); + TestTiling(pixd, pixs, 0, 1, 60, 0, 30, 20); + TestTiling(pixd, pixs, 1, 0, 0, 60, 40, 40); + TestTiling(pixd, pixs, 0, 0, 27, 31, 27, 31); + TestTiling(pixd, pixs, 0, 0, 400, 400, 40, 20); + TestTiling(pixd, pixs, 7, 9, 0, 0, 35, 35); + TestTiling(pixd, pixs, 0, 0, 27, 31, 0, 0); + TestTiling(pixd, pixs, 7, 9, 0, 0, 0, 0); + + pixDestroy(&pixs); + pixDestroy(&pixd); + return 0; +} + + +l_int32 +TestTiling(PIX *pixd, + PIX *pixs, + l_int32 nx, + l_int32 ny, + l_int32 w, + l_int32 h, + l_int32 xoverlap, + l_int32 yoverlap) +{ +l_int32 i, j, same; +PIX *pixt; +PIXTILING *pt; + + pixClearAll(pixd); + pt = pixTilingCreate(pixs, nx, ny, w, h, xoverlap, yoverlap); + pixTilingGetCount(pt, &nx, &ny); + pixTilingGetSize(pt, &w, &h); + if (pt) + lept_stderr("nx,ny = %d,%d; w,h = %d,%d; overlap = %d,%d\n", + nx, ny, w, h, pt->xoverlap, pt->yoverlap); + else + return 1; + + for (i = 0; i < ny; i++) { + for (j = 0; j < nx; j++) { + pixt = pixTilingGetTile(pt, i, j); + pixTilingPaintTile(pixd, i, j, pixt, pt); + pixDestroy(&pixt); + } + } + pixEqual(pixs, pixd, &same); + if (same) + lept_stderr("Tiling OK\n"); + else + lept_stderr("Tiling ERROR !\n"); + + pixTilingDestroy(&pt); + return 0; +} diff --git a/leptonica/prog/plottest.c b/leptonica/prog/plottest.c new file mode 100644 index 00000000..3b0cfc73 --- /dev/null +++ b/leptonica/prog/plottest.c @@ -0,0 +1,156 @@ +/*====================================================================* + - 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. + *====================================================================*/ + + +/* + * plottest.c + * + * This tests the gplot library functions that generate + * the plot commands and data required for input to gnuplot. + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include <string.h> +#include <math.h> + +#include "allheaders.h" + + /* for GPLOT_STYLE, use one of the following set: + * GPLOT_LINES + * GPLOT_POINTS + * GPLOT_IMPULSE + * GPLOT_LINESPOINTS + * GPLOT_DOTS */ +#define GPLOT_STYLE GPLOT_LINES + + /* for GPLOT_OUTPUT use one of the following set: + * GPLOT_PNG + * GPLOT_PS + * GPLOT_EPS + * GPLOT_LATEX + */ + +#define GPLOT_OUTPUT GPLOT_PNG + +int main(int argc, + char **argv) +{ +char *str1, *str2, *pngname; +l_int32 i; +size_t size1, size2; +l_float32 x, y1, y2, pi; +GPLOT *gplot1, *gplot2, *gplot3, *gplot4, *gplot5; +NUMA *nax, *nay1, *nay2; +static char mainName[] = "plottest"; + + if (argc != 1) + return ERROR_INT(" Syntax: plottest", mainName, 1); + + setLeptDebugOK(1); + lept_mkdir("lept/plot"); + + /* Generate plot data */ + nax = numaCreate(0); + nay1 = numaCreate(0); + nay2 = numaCreate(0); + pi = 3.1415926535; + for (i = 0; i < 180; i++) { + x = (pi / 180.) * i; + y1 = (l_float32)sin(2.4 * x); + y2 = (l_float32)cos(2.4 * x); + numaAddNumber(nax, x); + numaAddNumber(nay1, y1); + numaAddNumber(nay2, y2); + } + + /* Show the plot */ + gplot1 = gplotCreate("/tmp/lept/plot/set1", GPLOT_OUTPUT, "Example plots", + "theta", "f(theta)"); + gplotAddPlot(gplot1, nax, nay1, GPLOT_STYLE, "sin (2.4 * theta)"); + gplotAddPlot(gplot1, nax, nay2, GPLOT_STYLE, "cos (2.4 * theta)"); + gplotMakeOutput(gplot1); + + /* Also save the plot to png */ + gplot1->outformat = GPLOT_PNG; + pngname = genPathname("/tmp/lept/plot", "set1.png"); + stringReplace(&gplot1->outname, pngname); + gplotMakeOutput(gplot1); + l_fileDisplay("/tmp/lept/plot/set1.png", 100, 100, 1.0); + lept_free(pngname); + + /* Test gplot serialization */ + gplotWrite("/tmp/lept/plot/plot1.gp", gplot1); + if ((gplot2 = gplotRead("/tmp/lept/plot/plot1.gp")) == NULL) + return ERROR_INT("gplotRead failure!", mainName, 1); + gplotWrite("/tmp/lept/plot/plot2.gp", gplot2); + + /* Are the two written gplot files the same? */ + str1 = (char *)l_binaryRead("/tmp/lept/plot/plot1.gp", &size1); + str2 = (char *)l_binaryRead("/tmp/lept/plot/plot2.gp", &size2); + if (size1 != size2) + lept_stderr("Error: size1 = %lu, size2 = %lu\n", + (unsigned long)size1, (unsigned long)size2); + else + lept_stderr("Correct: size1 = size2 = %lu\n", (unsigned long)size1); + if (strcmp(str1, str2) != 0) + lept_stderr("Error: str1 != str2\n"); + else + lept_stderr("Correct: str1 == str2\n"); + lept_free(str1); + lept_free(str2); + + /* Read from file and regenerate the plot */ + gplot3 = gplotRead("/tmp/lept/plot/plot2.gp"); + stringReplace(&gplot3->title , "Example plots regen"); + gplot3->outformat = GPLOT_PNG; + gplotMakeOutput(gplot3); + + /* Build gplot but do not make the output formatted stuff */ + gplot4 = gplotCreate("/tmp/lept/plot/set2", GPLOT_OUTPUT, + "Example plots 2", "theta", "f(theta)"); + gplotAddPlot(gplot4, nax, nay1, GPLOT_STYLE, "sin (2.4 * theta)"); + gplotAddPlot(gplot4, nax, nay2, GPLOT_STYLE, "cos (2.4 * theta)"); + + /* Write, read back, and generate the plot */ + gplotWrite("/tmp/lept/plot/plot4.gp", gplot4); + if ((gplot5 = gplotRead("/tmp/lept/plot/plot4.gp")) == NULL) + return ERROR_INT("gplotRead failure!", mainName, 1); + gplotMakeOutput(gplot5); + l_fileDisplay("/tmp/lept/plot/set2.png", 750, 100, 1.0); + + gplotDestroy(&gplot1); + gplotDestroy(&gplot2); + gplotDestroy(&gplot3); + gplotDestroy(&gplot4); + gplotDestroy(&gplot5); + numaDestroy(&nax); + numaDestroy(&nay1); + numaDestroy(&nay2); + return 0; +} diff --git a/leptonica/prog/pngio_reg.c b/leptonica/prog/pngio_reg.c new file mode 100644 index 00000000..5bf3409b --- /dev/null +++ b/leptonica/prog/pngio_reg.c @@ -0,0 +1,477 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * pngio_reg.c + * + * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + * This is the Leptonica regression test for lossless read/write + * I/O in png format. + * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + * + * This tests reading and writing of images in png format for + * various depths, with and without colormaps. + * + * This test is dependent on the following external libraries: + * libpng, libz + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + + /* Needed for checking libraries */ +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#define FILE_1BPP "rabi.png" +#define FILE_2BPP "speckle2.png" +#define FILE_2BPP_C "weasel2.4g.png" +#define FILE_4BPP "speckle4.png" +#define FILE_4BPP_C "weasel4.16c.png" +#define FILE_8BPP "dreyfus8.png" +#define FILE_8BPP_C "weasel8.240c.png" +#define FILE_16BPP "test16.png" +#define FILE_32BPP "weasel32.png" +#define FILE_32BPP_ALPHA "test32-alpha.png" +#define FILE_CMAP_ALPHA "test-cmap-alpha.png" +#define FILE_CMAP_ALPHA2 "test-cmap-alpha2.png" +#define FILE_TRANS_ALPHA "test-fulltrans-alpha.png" +#define FILE_GRAY_ALPHA "test-gray-alpha.png" + +static l_int32 test_mem_png(const char *fname); +static l_int32 get_header_data(const char *filename); +static l_int32 test_1bpp_trans(L_REGPARAMS *rp); +static l_int32 test_1bpp_color(L_REGPARAMS *rp); +static l_int32 test_1bpp_gray(L_REGPARAMS *rp); +static l_int32 test_1bpp_bw1(L_REGPARAMS *rp); +static l_int32 test_1bpp_bw2(L_REGPARAMS *rp); +static l_int32 test_8bpp_trans(L_REGPARAMS *rp); + +LEPT_DLL extern const char *ImageFileFormatExtensions[]; + +int main(int argc, + char **argv) +{ +l_int32 success, failure; +L_REGPARAMS *rp; + +#if !defined(HAVE_LIBPNG) + L_ERROR("This test requires libpng to run.\n", "pngio_reg"); + exit(77); +#endif + + if (regTestSetup(argc, argv, &rp)) + return 1; + + /* --------- Part 1: Test lossless r/w to file ---------*/ + + failure = FALSE; + success = TRUE; + lept_stderr("Test bmp 1 bpp file:\n"); + if (ioFormatTest(FILE_1BPP)) success = FALSE; + lept_stderr("\nTest 2 bpp file:\n"); + if (ioFormatTest(FILE_2BPP)) success = FALSE; + lept_stderr("\nTest 2 bpp file with cmap:\n"); + if (ioFormatTest(FILE_2BPP_C)) success = FALSE; + lept_stderr("\nTest 4 bpp file:\n"); + if (ioFormatTest(FILE_4BPP)) success = FALSE; + lept_stderr("\nTest 4 bpp file with cmap:\n"); + if (ioFormatTest(FILE_4BPP_C)) success = FALSE; + lept_stderr("\nTest 8 bpp grayscale file with cmap:\n"); + if (ioFormatTest(FILE_8BPP)) success = FALSE; + lept_stderr("\nTest 8 bpp color file with cmap:\n"); + if (ioFormatTest(FILE_8BPP_C)) success = FALSE; + lept_stderr("\nTest 16 bpp file:\n"); + if (ioFormatTest(FILE_16BPP)) success = FALSE; + lept_stderr("\nTest 32 bpp RGB file:\n"); + if (ioFormatTest(FILE_32BPP)) success = FALSE; + lept_stderr("\nTest 32 bpp RGBA file:\n"); + if (ioFormatTest(FILE_32BPP_ALPHA)) success = FALSE; + lept_stderr("\nTest spp = 1, cmap with alpha file:\n"); + if (ioFormatTest(FILE_CMAP_ALPHA)) success = FALSE; + lept_stderr("\nTest spp = 1, cmap with alpha (small alpha array):\n"); + if (ioFormatTest(FILE_CMAP_ALPHA2)) success = FALSE; + lept_stderr("\nTest spp = 1, fully transparent with alpha file:\n"); + if (ioFormatTest(FILE_TRANS_ALPHA)) success = FALSE; + lept_stderr("\nTest spp = 2, gray with alpha file:\n"); + if (ioFormatTest(FILE_GRAY_ALPHA)) success = FALSE; + if (success) { + lept_stderr( + "\n ********** Success on lossless r/w to file *********\n\n"); + } else { + lept_stderr( + "\n ******* Failure on at least one r/w to file ******\n\n"); + } + if (!success) failure = TRUE; + + /* ------------ Part 2: Test lossless r/w to memory ------------ */ + success = TRUE; + if (test_mem_png(FILE_1BPP)) success = FALSE; + if (test_mem_png(FILE_2BPP)) success = FALSE; + if (test_mem_png(FILE_2BPP_C)) success = FALSE; + if (test_mem_png(FILE_4BPP)) success = FALSE; + if (test_mem_png(FILE_4BPP_C)) success = FALSE; + if (test_mem_png(FILE_8BPP)) success = FALSE; + if (test_mem_png(FILE_8BPP_C)) success = FALSE; + if (test_mem_png(FILE_16BPP)) success = FALSE; + if (test_mem_png(FILE_32BPP)) success = FALSE; + if (test_mem_png(FILE_32BPP_ALPHA)) success = FALSE; + if (test_mem_png(FILE_CMAP_ALPHA)) success = FALSE; + if (test_mem_png(FILE_CMAP_ALPHA2)) success = FALSE; + if (test_mem_png(FILE_TRANS_ALPHA)) success = FALSE; + if (test_mem_png(FILE_GRAY_ALPHA)) success = FALSE; + if (success) { + lept_stderr( + "\n ****** Success on lossless r/w to memory *****\n"); + } else { + lept_stderr( + "\n ******* Failure on at least one r/w to memory ******\n"); + } + if (!success) failure = TRUE; + + /* ------------ Part 3: Test lossless 1 and 8 bpp r/w ------------ */ + lept_stderr("\nTest lossless 1 and 8 bpp r/w\n"); + success = TRUE; + if (test_1bpp_trans(rp) == 0) success = FALSE; + if (test_1bpp_color(rp) == 0) success = FALSE; + if (test_1bpp_gray(rp) == 0) success = FALSE; + if (test_1bpp_bw1(rp) == 0) success = FALSE; + if (test_1bpp_bw2(rp) == 0) success = FALSE; + if (test_8bpp_trans(rp) == 0) success = FALSE; + + if (success) { + lept_stderr( + "\n ******* Success on 1 and 8 bpp lossless *******\n\n"); + } else { + lept_stderr( + "\n ******* Failure on 1 and 8 bpp lossless *******\n\n"); + } + if (!success) failure = TRUE; + + /* -------------- Part 4: Read header information -------------- */ + success = TRUE; + if (get_header_data(FILE_1BPP)) success = FALSE; + if (get_header_data(FILE_2BPP)) success = FALSE; + if (get_header_data(FILE_2BPP_C)) success = FALSE; + if (get_header_data(FILE_4BPP)) success = FALSE; + if (get_header_data(FILE_4BPP_C)) success = FALSE; + if (get_header_data(FILE_8BPP)) success = FALSE; + if (get_header_data(FILE_8BPP_C)) success = FALSE; + if (get_header_data(FILE_16BPP)) success = FALSE; + if (get_header_data(FILE_32BPP)) success = FALSE; + if (get_header_data(FILE_32BPP_ALPHA)) success = FALSE; + if (get_header_data(FILE_CMAP_ALPHA)) success = FALSE; + if (get_header_data(FILE_CMAP_ALPHA2)) success = FALSE; + if (get_header_data(FILE_TRANS_ALPHA)) success = FALSE; + if (get_header_data(FILE_GRAY_ALPHA)) success = FALSE; + + if (success) { + lept_stderr("\n ******* Success on reading headers *******\n\n"); + } else { + lept_stderr("\n ******* Failure on reading headers *******\n\n"); + } + if (!success) failure = TRUE; + + if (!failure) { + lept_stderr(" ******* Success on all tests *******\n\n"); + } else { + lept_stderr(" ******* Failure on at least one test *******\n\n"); + } + + if (failure) rp->success = FALSE; + return regTestCleanup(rp); +} + + + /* Returns 1 on error */ +static l_int32 +test_mem_png(const char *fname) +{ +l_uint8 *data = NULL; +l_int32 same; +size_t size = 0; +PIX *pixs; +PIX *pixd = NULL; + + if ((pixs = pixRead(fname)) == NULL) { + lept_stderr("Failure to read %s\n", fname); + return 1; + } + if (pixWriteMem(&data, &size, pixs, IFF_PNG)) { + lept_stderr("Mem write fail for png\n"); + return 1; + } + if ((pixd = pixReadMem(data, size)) == NULL) { + lept_stderr("Mem read fail for png\n"); + lept_free(data); + return 1; + } + + pixEqual(pixs, pixd, &same); + if (!same) + lept_stderr("Mem write/read fail for file %s\n", fname); + pixDestroy(&pixs); + pixDestroy(&pixd); + lept_free(data); + return (!same); +} + + /* Retrieve header data from file and from array in memory */ +static l_int32 +get_header_data(const char *filename) +{ +l_uint8 *data; +l_int32 ret1, ret2, format1, format2; +l_int32 w1, w2, h1, h2, d1, d2, bps1, bps2, spp1, spp2, iscmap1, iscmap2; +size_t nbytes1, nbytes2; + + /* Read header from file */ + nbytes1 = nbytesInFile(filename); + ret1 = pixReadHeader(filename, &format1, &w1, &h1, &bps1, &spp1, &iscmap1); + d1 = bps1 * spp1; + if (d1 == 24) d1 = 32; + if (ret1) { + lept_stderr("Error: couldn't read header data from file: %s\n", + filename); + } else { + lept_stderr("Format data for image %s with format %s:\n" + " nbytes = %lu, size (w, h, d) = (%d, %d, %d)\n" + " bps = %d, spp = %d, iscmap = %d\n", + filename, ImageFileFormatExtensions[format1], + (unsigned long)nbytes1, w1, h1, d1, bps1, spp1, iscmap1); + if (format1 != IFF_PNG) { + lept_stderr("Error: format is %d; should be %d\n", + format1, IFF_PNG); + ret1 = 1; + } + } + + /* Read header from array in memory */ + data = l_binaryRead(filename, &nbytes2); + ret2 = pixReadHeaderMem(data, nbytes2, &format2, &w2, &h2, &bps2, + &spp2, &iscmap2); + lept_free(data); + d2 = bps2 * spp2; + if (d2 == 24) d2 = 32; + if (ret2) { + lept_stderr("Error: couldn't mem-read header data: %s\n", filename); + } else { + if (nbytes1 != nbytes2 || format1 != format2 || w1 != w2 || + h1 != h2 || d1 != d2 || bps1 != bps2 || spp1 != spp2 || + iscmap1 != iscmap2) { + lept_stderr("Incomsistency reading image %s with format %s\n", + filename, ImageFileFormatExtensions[IFF_PNG]); + ret2 = 1; + } + } + + return ret1 || ret2; +} + +static l_int32 +test_1bpp_trans(L_REGPARAMS *rp) +{ +l_int32 same, transp; +FILE *fp; +PIX *pix1, *pix2; +PIXCMAP *cmap; + + pix1 = pixRead("feyn-fract2.tif"); + cmap = pixcmapCreate(1); + pixSetColormap(pix1, cmap); + pixcmapAddRGBA(cmap, 180, 130, 220, 0); /* transparent */ + pixcmapAddRGBA(cmap, 20, 120, 0, 255); /* opaque */ + pixWrite("/tmp/lept/regout/1bpp-trans.png", pix1, IFF_PNG); + pix2 = pixRead("/tmp/lept/regout/1bpp-trans.png"); + pixEqual(pix1, pix2, &same); + if (same) + lept_stderr("1bpp_trans: success\n"); + else + lept_stderr("1bpp_trans: bad output\n"); + pixDisplayWithTitle(pix2, 700, 0, NULL, rp->display); + pixDestroy(&pix1); + pixDestroy(&pix2); + fp = fopenReadStream("/tmp/lept/regout/1bpp-trans.png"); + fgetPngColormapInfo(fp, &cmap, &transp); + if (fp) fclose(fp); + if (transp) + lept_stderr("1bpp_trans: correct -- transparency found\n"); + else + lept_stderr("1bpp_trans: error -- no transparency found!\n"); + if (rp->display) pixcmapWriteStream(stderr, cmap); + pixcmapDestroy(&cmap); + return same; +} + +static l_int32 +test_1bpp_color(L_REGPARAMS *rp) +{ +l_int32 same, transp; +FILE *fp; +PIX *pix1, *pix2; +PIXCMAP *cmap; + + pix1 = pixRead("feyn-fract2.tif"); + cmap = pixcmapCreate(1); + pixSetColormap(pix1, cmap); + pixcmapAddRGBA(cmap, 180, 130, 220, 255); /* color, opaque */ + pixcmapAddRGBA(cmap, 20, 120, 0, 255); /* color, opaque */ + pixWrite("/tmp/lept/regout/1bpp-color.png", pix1, IFF_PNG); + pix2 = pixRead("/tmp/lept/regout/1bpp-color.png"); + pixEqual(pix1, pix2, &same); + if (same) + lept_stderr("1bpp_color: success\n"); + else + lept_stderr("1bpp_color: bad output\n"); + pixDisplayWithTitle(pix2, 700, 100, NULL, rp->display); + pixDestroy(&pix1); + pixDestroy(&pix2); + fp = fopenReadStream("/tmp/lept/regout/1bpp-color.png"); + fgetPngColormapInfo(fp, &cmap, &transp); + if (fp) fclose(fp); + if (transp) + lept_stderr("1bpp_color: error -- transparency found!\n"); + else + lept_stderr("1bpp_color: correct -- no transparency found\n"); + if (rp->display) pixcmapWriteStream(stderr, cmap); + pixcmapDestroy(&cmap); + return same; +} + +static l_int32 +test_1bpp_gray(L_REGPARAMS *rp) +{ +l_int32 same; +PIX *pix1, *pix2; +PIXCMAP *cmap; + + pix1 = pixRead("feyn-fract2.tif"); + cmap = pixcmapCreate(1); + pixSetColormap(pix1, cmap); + pixcmapAddRGBA(cmap, 180, 180, 180, 255); /* light, opaque */ + pixcmapAddRGBA(cmap, 60, 60, 60, 255); /* dark, opaque */ + pixWrite("/tmp/lept/regout/1bpp-gray.png", pix1, IFF_PNG); + pix2 = pixRead("/tmp/lept/regout/1bpp-gray.png"); + pixEqual(pix1, pix2, &same); + if (same) + lept_stderr("1bpp_gray: success\n"); + else + lept_stderr("1bpp_gray: bad output\n"); + pixDisplayWithTitle(pix2, 700, 200, NULL, rp->display); + pixDestroy(&pix1); + pixDestroy(&pix2); + return same; +} + +static l_int32 +test_1bpp_bw1(L_REGPARAMS *rp) +{ +l_int32 same; +PIX *pix1, *pix2; +PIXCMAP *cmap; + + pix1 = pixRead("feyn-fract2.tif"); + cmap = pixcmapCreate(1); + pixSetColormap(pix1, cmap); + pixcmapAddRGBA(cmap, 0, 0, 0, 255); /* black, opaque */ + pixcmapAddRGBA(cmap, 255, 255, 255, 255); /* white, opaque */ + pixWrite("/tmp/lept/regout/1bpp-bw1.png", pix1, IFF_PNG); + pix2 = pixRead("/tmp/lept/regout/1bpp-bw1.png"); + pixEqual(pix1, pix2, &same); + if (same) + lept_stderr("1bpp_bw1: success\n"); + else + lept_stderr("1bpp_bw1: bad output\n"); + pixDisplayWithTitle(pix2, 700, 300, NULL, rp->display); + pixDestroy(&pix1); + pixDestroy(&pix2); + return same; +} + +static l_int32 +test_1bpp_bw2(L_REGPARAMS *rp) +{ +l_int32 same; +PIX *pix1, *pix2; +PIXCMAP *cmap; + + pix1 = pixRead("feyn-fract2.tif"); + cmap = pixcmapCreate(1); + pixSetColormap(pix1, cmap); + pixcmapAddRGBA(cmap, 255, 255, 255, 255); /* white, opaque */ + pixcmapAddRGBA(cmap, 0, 0, 0, 255); /* black, opaque */ + pixWrite("/tmp/lept/regout/1bpp-bw2.png", pix1, IFF_PNG); + pix2 = pixRead("/tmp/lept/regout/1bpp-bw2.png"); + pixEqual(pix1, pix2, &same); + if (same) + lept_stderr("1bpp_bw2: success\n"); + else + lept_stderr("1bpp_bw2: bad output\n"); + pixDisplayWithTitle(pix2, 700, 400, NULL, rp->display); + pixDestroy(&pix1); + pixDestroy(&pix2); + return same; +} + +static l_int32 +test_8bpp_trans(L_REGPARAMS *rp) +{ +l_int32 same, transp; +FILE *fp; +PIX *pix1, *pix2, *pix3; +PIXCMAP *cmap; + + pix1 = pixRead("wyom.jpg"); + pix2 = pixColorSegment(pix1, 75, 10, 8, 7, 0); + cmap = pixGetColormap(pix2); + pixcmapSetAlpha(cmap, 0, 0); /* set blueish sky color to transparent */ + pixWrite("/tmp/lept/regout/8bpp-trans.png", pix2, IFF_PNG); + pix3 = pixRead("/tmp/lept/regout/8bpp-trans.png"); + pixEqual(pix2, pix3, &same); + if (same) + lept_stderr("8bpp_trans: success\n"); + else + lept_stderr("8bpp_trans: bad output\n"); + pixDisplayWithTitle(pix3, 700, 0, NULL, rp->display); + pixDestroy(&pix1); + pixDestroy(&pix2); + pixDestroy(&pix3); + fp = fopenReadStream("/tmp/lept/regout/8bpp-trans.png"); + fgetPngColormapInfo(fp, &cmap, &transp); + if (fp) fclose(fp); + if (transp) + lept_stderr("8bpp_trans: correct -- transparency found\n"); + else + lept_stderr("8bpp_trans: error -- no transparency found!\n"); + if (rp->display) pixcmapWriteStream(stderr, cmap); + pixcmapDestroy(&cmap); + return same; +} + diff --git a/leptonica/prog/pnmio_reg.c b/leptonica/prog/pnmio_reg.c new file mode 100644 index 00000000..ae30fe3e --- /dev/null +++ b/leptonica/prog/pnmio_reg.c @@ -0,0 +1,183 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * pnmio_reg.c + * + * Tests read and write of both ascii and packed pnm, using + * pix with 1, 2, 4, 8 and 32 bpp. + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + +l_int32 main(l_int32 argc, + char **argv) +{ +l_uint8 *data; +size_t size; +FILE *fp; +PIX *pix1, *pix2, *pix3, *pix4, *pix5; +L_REGPARAMS *rp; + + if (regTestSetup(argc, argv, &rp)) + return 1; + +#if !USE_PNMIO + lept_stderr("pnm/pam writing is not enabled\n" + "See environ.h: #define USE_PNMIO 1\n\n"); + + regTestCleanup(rp); + return 0; +#endif /* abort */ + + lept_rmdir("lept/pnm"); + lept_mkdir("lept/pnm"); + + /* Test 1 bpp (pbm) read/write */ + pix1 = pixRead("char.tif"); + fp = lept_fopen("/tmp/lept/pnm/pix1.1.pnm", "wb"); + pixWriteStreamAsciiPnm(fp, pix1); + lept_fclose(fp); + pix2 = pixRead("/tmp/lept/pnm/pix1.1.pnm"); + pixWrite("/tmp/lept/pnm/pix2.1.pnm", pix2, IFF_PNM); + pix3 = pixRead("/tmp/lept/pnm/pix2.1.pnm"); + regTestComparePix(rp, pix1, pix3); /* 0 */ + /* write PAM */ + fp = lept_fopen("/tmp/lept/pnm/pix3.1.pnm", "wb"); + pixWriteStreamPam(fp, pix1); + lept_fclose(fp); + pix4 = pixRead("/tmp/lept/pnm/pix3.1.pnm"); + regTestComparePix(rp, pix1, pix4); /* 1 */ + pixDestroy(&pix1); + pixDestroy(&pix2); + pixDestroy(&pix3); + pixDestroy(&pix4); + + /* Test 2, 4 and 8 bpp (pgm) read/write */ + pix1 = pixRead("weasel8.png"); + pix2 = pixThresholdTo2bpp(pix1, 4, 0); + fp = lept_fopen("/tmp/lept/pnm/pix2.2.pnm", "wb"); + pixWriteStreamAsciiPnm(fp, pix2); + lept_fclose(fp); + pix3 = pixRead("/tmp/lept/pnm/pix2.2.pnm"); + pixWrite("/tmp/lept/pnm/pix3.2.pnm", pix3, IFF_PNM); + pix4 = pixRead("/tmp/lept/pnm/pix3.2.pnm"); + regTestComparePix(rp, pix2, pix4); /* 2 */ + /* write PAM */ + fp = lept_fopen("/tmp/lept/pnm/pix4.2.pnm", "wb"); + pixWriteStreamPam(fp, pix2); + lept_fclose(fp); + pix5 = pixRead("/tmp/lept/pnm/pix4.2.pnm"); + regTestComparePix(rp, pix2, pix5); /* 3 */ + pixDestroy(&pix2); + pixDestroy(&pix3); + pixDestroy(&pix4); + pixDestroy(&pix5); + + pix2 = pixThresholdTo4bpp(pix1, 16, 0); + fp = lept_fopen("/tmp/lept/pnm/pix2.4.pnm", "wb"); + pixWriteStreamAsciiPnm(fp, pix2); + lept_fclose(fp); + pix3 = pixRead("/tmp/lept/pnm/pix2.4.pnm"); + pixWrite("/tmp/lept/pnm/pix3.4.pnm", pix3, IFF_PNM); + pix4 = pixRead("/tmp/lept/pnm/pix3.4.pnm"); + regTestComparePix(rp, pix2, pix4); /* 4 */ + /* write PAM */ + fp = lept_fopen("/tmp/lept/pnm/pix4.4.pnm", "wb"); + pixWriteStreamPam(fp, pix2); + lept_fclose(fp); + pix5 = pixRead("/tmp/lept/pnm/pix4.4.pnm"); + regTestComparePix(rp, pix2, pix5); /* 5 */ + pixDestroy(&pix2); + pixDestroy(&pix3); + pixDestroy(&pix4); + pixDestroy(&pix5); + + fp = lept_fopen("/tmp/lept/pnm/pix1.8.pnm", "wb"); + pixWriteStreamAsciiPnm(fp, pix1); + lept_fclose(fp); + pix2 = pixRead("/tmp/lept/pnm/pix1.8.pnm"); + pixWrite("/tmp/lept/pnm/pix2.8.pnm", pix2, IFF_PNM); + pix3 = pixRead("/tmp/lept/pnm/pix2.8.pnm"); + regTestComparePix(rp, pix1, pix3); /* 6 */ + /* write PAM */ + fp = lept_fopen("/tmp/lept/pnm/pix3.8.pnm", "wb"); + pixWriteStreamPam(fp, pix1); + lept_fclose(fp); + pix4 = pixRead("/tmp/lept/pnm/pix3.8.pnm"); + regTestComparePix(rp, pix1, pix4); /* 7 */ + pixDestroy(&pix1); + pixDestroy(&pix2); + pixDestroy(&pix3); + pixDestroy(&pix4); + + /* Test ppm (24 bpp rgb) read/write */ + pix1 = pixRead("marge.jpg"); + fp = lept_fopen("/tmp/lept/pnm/pix1.24.pnm", "wb"); + /* write ascii */ + pixWriteStreamAsciiPnm(fp, pix1); + lept_fclose(fp); + pix2 = pixRead("/tmp/lept/pnm/pix1.24.pnm"); + /* write pnm */ + pixWrite("/tmp/lept/pnm/pix2.24.pnm", pix2, IFF_PNM); + pix3 = pixRead("/tmp/lept/pnm/pix2.24.pnm"); + regTestComparePix(rp, pix1, pix3); /* 8 */ + pixDestroy(&pix3); + /* write mem pnm */ + pixWriteMemPnm(&data, &size, pix1); + pix3 = pixReadMemPnm(data, size); + regTestComparePix(rp, pix1, pix3); /* 9 */ + lept_free(data); + /* write pam */ + fp = lept_fopen("/tmp/lept/pnm/pix3.24.pnm", "wb"); + pixWriteStreamPam(fp, pix1); + lept_fclose(fp); + pix4 = pixRead("/tmp/lept/pnm/pix3.24.pnm"); + regTestComparePix(rp, pix1, pix4); /* 10 */ + pixDestroy(&pix1); + pixDestroy(&pix2); + pixDestroy(&pix3); + pixDestroy(&pix4); + + /* Test pam (32 bpp rgba) read/write */ + pix1 = pixRead("test32-alpha.png"); + fp = lept_fopen("/tmp/lept/pnm/pix1.32.pnm", "wb"); + pixWriteStreamPam(fp, pix1); + lept_fclose(fp); + pix2 = pixRead("/tmp/lept/pnm/pix1.32.pnm"); + pixWrite("/tmp/lept/pnm/pix2.32.pnm", pix2, IFF_PNM); + pix3 = pixRead("/tmp/lept/pnm/pix2.32.pnm"); + regTestComparePix(rp, pix1, pix3); /* 11 */ + pixDestroy(&pix1); + pixDestroy(&pix2); + pixDestroy(&pix3); + + return regTestCleanup(rp); +} diff --git a/leptonica/prog/printimage.c b/leptonica/prog/printimage.c new file mode 100644 index 00000000..9d195b2a --- /dev/null +++ b/leptonica/prog/printimage.c @@ -0,0 +1,158 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * printimage.c + * + * This prints an image. It rotates and isotropically scales the image, + * as necessary, to get a maximum filling when printing onto an + * 8.5 x 11 inch page. + * + * Syntax: printimage <filein> [printer, other lpr args] + * + * The simplest input would be something like + * printimage myfile.jpg + * This generates the PostScript file /tmp/print_image.ps, but + * does not send it to a printer. + * + * If you have lpr, you can specify a printer; e.g. + * printimage myfile.jpg myprinter + * + * You can add lpr flags. Two useful ones are: + * * to print more than one copy + * -#N (prints N copies) + * * to print in color (flag is printer-dependent) + * -o ColorModel=Color or + * -o ColorModel=CMYK + * + * For example, to make 3 color copies, you might use: + * printimage myfile.jpg myprinter -#3 -o ColorModel=Color + * + * By default, the intermediate PostScript file generated is + * level 3 (compressed): + * /tmp/print_image.ps + * + * If your system does not have lpr, it likely has lp. You can run + * printimage to make the PostScript file, and then print with lp: + * lp -d <printer> /tmp/print_image.ps + * lp -d <printer> -o ColorModel=Color /tmp/print_image.ps + * etc. + * + * *************************************************************** + * N.B. If a printer is specified, this program invokes lpr via + * "system'. It could pose a security vulnerability if used + * as a service in a production environment. Consequently, + * this program should only be used for debug and testing. + * *************************************************************** + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + +#define USE_COMPRESSED 1 + +static const l_float32 FILL_FACTOR = 0.95; /* fill factor on 8.5 x 11 page */ + +int main(int argc, + char **argv) +{ +char *filein, *printer, *extra, *fname; +char buffer[512]; +l_int32 i, w, h, ret, index; +l_float32 scale; +FILE *fp; +PIX *pixs, *pix1; +SARRAY *sa; +static char mainName[] = "printimage"; + + if (argc < 2) + return ERROR_INT( + " Syntax: printimage <filein> [printer, other lpr args]", + mainName, 1); + filein = argv[1]; + printer = (argc > 2) ? argv[2] : NULL; + + lept_stderr( + "\n!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n" + " Warning: this program should only be used for testing,\n" + " and not in a production environment, because of a\n" + " potential vulnerability with the 'system' call.\n" + "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n\n"); + + setLeptDebugOK(1); + (void)lept_rm(NULL, "print_image.ps"); + + if ((pixs = pixRead(filein)) == NULL) + return ERROR_INT("pixs not made", mainName, 1); + + pixGetDimensions(pixs, &w, &h, NULL); + if (w > h) { + pix1 = pixRotate90(pixs, 1); + pixGetDimensions(pix1, &w, &h, NULL); + } + else { + pix1 = pixClone(pixs); + } + scale = L_MIN(FILL_FACTOR * 2550 / w, FILL_FACTOR * 3300 / h); + fname = genPathname("/tmp", "print_image.ps"); +#if USE_COMPRESSED + index = 0; + pixWriteCompressedToPS(pix1, fname, (l_int32)(300. / scale), 3, &index); +#else /* uncompressed, level 1 */ + fp = lept_fopen(fname, "wb+"); + pixWriteStreamPS(fp, pix1, NULL, 300, scale); + lept_fclose(fp); +#endif /* USE_COMPRESSED */ + + /* Optionally print it out */ + if (argc > 2) { + extra = NULL; + if (argc > 3) { /* concatenate the extra args */ + sa = sarrayCreate(0); + for (i = 3; i < argc; i++) + sarrayAddString(sa, argv[i], L_COPY); + extra = sarrayToString(sa, 2); + sarrayDestroy(&sa); + } + if (!extra) { + snprintf(buffer, sizeof(buffer), "lpr %s -P%s &", fname, printer); + ret = system(buffer); + } else { + snprintf(buffer, sizeof(buffer), "lpr %s -P%s %s &", + fname, printer, extra); + ret = system(buffer); + } + lept_free(extra); + } + + lept_free(fname); + pixDestroy(&pixs); + pixDestroy(&pix1); + return 0; +} diff --git a/leptonica/prog/printsplitimage.c b/leptonica/prog/printsplitimage.c new file mode 100644 index 00000000..4c8d35ba --- /dev/null +++ b/leptonica/prog/printsplitimage.c @@ -0,0 +1,150 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * printsplitimage.c + * + * Syntax: printsplitimage filein nx ny [printer] + * + * nx = number of horizontal tiles + * ny = number of vertical tiles + * + * If printer is not specified, the only action is that the + * image is split into a set of tiles, and these are written + * out as a set of compressed (level 3) Postscript files. + * The images in the PostScript files are scaled to each fill + * an 8.5 x 11 inch page, up to the FILLING_FACTOR fraction + * in each direction. + * + * If printer is specified, these are printed on separate pages, + * because some printers cannot print multi-page Postscript of images. + * + * If your system does not have lpr, it likely has lp. You can run + * printsplitimage to make the PostScript files, and print them with lp: + * lp -d <printer> /tmp/lept/split/image0.ps + * lp -d <printer> /tmp/lept/split/image1.ps + * ... + * To print in color, see prog/printimage.c. + * + * *************************************************************** + * N.B. If a printer is specified, this program invokes lpr via + * "system'. It could pose a security vulnerability if used + * as a service in a production environment. Consequently, + * this program should only be used for debug and testing. + * *************************************************************** + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + +#define USE_COMPRESSED 1 + + /* fill factor on 8.5 x 11 inch output page */ +static const l_float32 FILL_FACTOR = 0.95; + +int main(int argc, + char **argv) +{ +char *filein, *fname, *printer; +char buf[512]; +l_int32 nx, ny, i, w, h, ws, hs, n, ignore, index; +l_float32 scale; +FILE *fp; +PIX *pixs, *pixt, *pixr; +PIXA *pixa; +SARRAY *sa; +static char mainName[] = "printsplitimage"; + + if (argc != 4 && argc != 5) + return ERROR_INT(" Syntax: printsplitimage filein nx ny [printer]", + mainName, 1); + filein = argv[1]; + nx = atoi(argv[2]); + ny = atoi(argv[3]); + printer = (argc == 5) ? argv[4] : NULL; + + lept_stderr( + "\n!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n" + " Warning: this program should only be used for testing,\n" + " and not in a production environment, because of a\n" + " potential vulnerability with the 'system' call.\n" + "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n\n"); + + setLeptDebugOK(1); + lept_rmdir("lept/split"); + lept_mkdir("lept/split"); + + if ((pixs = pixRead(filein)) == NULL) + return ERROR_INT("pixs not made", mainName, 1); + pixGetDimensions(pixs, &ws, &hs, NULL); + if (ny * ws > nx * hs) { + pixr = pixRotate90(pixs, 1); + pixa = pixaSplitPix(pixr, ny, nx, 0, 0); + } else { + pixr = pixClone(pixs); + pixa = pixaSplitPix(pixr, nx, ny, 0, 0); + } + pixDestroy(&pixr); + + n = pixaGetCount(pixa); + sa = sarrayCreate(n); + for (i = 0; i < n; i++) { + pixt = pixaGetPix(pixa, i, L_CLONE); + pixGetDimensions(pixt, &w, &h, NULL); + scale = L_MIN(FILL_FACTOR * 2550 / w, FILL_FACTOR * 3300 / h); + snprintf(buf, sizeof(buf), "image%d.ps", i); + fname = genPathname("/tmp/lept/split", buf); + lept_stderr("fname: %s\n", fname); + sarrayAddString(sa, fname, L_INSERT); +#if USE_COMPRESSED + index = 0; + pixWriteCompressedToPS(pixt, fname, (l_int32)(300. / scale), 3, &index); + index = 0; /* write each out to a separate file */ +#else /* uncompressed, level 1 */ + fp = lept_fopen(fname, "wb+"); + pixWriteStreamPS(fp, pixt, NULL, 300, scale); + lept_fclose(fp); +#endif /* USE_COMPRESSED */ + pixDestroy(&pixt); + } + + if (argc == 5) { + for (i = 0; i < n; i++) { + fname = sarrayGetString(sa, i, L_NOCOPY); + snprintf(buf, sizeof(buf), "lpr -P%s %s &", printer, fname); + ignore = system(buf); + } + } + + sarrayDestroy(&sa); + pixaDestroy(&pixa); + pixDestroy(&pixs); + return 0; +} + diff --git a/leptonica/prog/printtiff.c b/leptonica/prog/printtiff.c new file mode 100644 index 00000000..ef60f746 --- /dev/null +++ b/leptonica/prog/printtiff.c @@ -0,0 +1,98 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * printtiff.c + * + * Syntax: printtiff filein [printer] + * + * Prints a multipage tiff file of 1 bpp images to a printer. + * If the tiff is at standard fax resolution, it expands the + * vertical size by a factor of two before encapsulating in + * ccittg4 encoded PostScript. The PostScript file is left in /tmp, + * and erased (deleted, removed, unlinked) on the next invocation. + * + * If the printer is not specified, this just writes the PostScript + * file /tmp/print_tiff.ps. + * + * If your system does not have lpr, it likely has lp. You can run + * printtiff to make the PostScript file, and then print with lp: + * lp -d <printer> /tmp/print_tiff.ps + * lp -d <printer> -o ColorModel=Color /tmp/print_tiff.ps + * etc. + * + * *************************************************************** + * N.B. If a printer is specified, this program invokes lpr via + * "system'. It could pose a security vulnerability if used + * as a service in a production environment. Consequently, + * this program should only be used for debug and testing. + * *************************************************************** + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + +#define TEMP_PS "print_tiff.ps" /* in the temp directory */ +#define FILL_FACTOR 0.95 + +int main(int argc, + char **argv) +{ +l_int32 ret; +char *filein, *tempfile, *printer; +char buf[512]; +static char mainName[] = "printtiff"; + + if (argc != 2 && argc != 3) + return ERROR_INT(" Syntax: printtiff filein [printer]", mainName, 1); + filein = argv[1]; + if (argc == 3) + printer = argv[2]; + + lept_stderr( + "\n!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n" + " Warning: this program should only be used for testing,\n" + " and not in a production environment, because of a\n" + " potential vulnerability with the 'system' call.\n" + "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n\n"); + + setLeptDebugOK(1); + (void)lept_rm(NULL, TEMP_PS); + tempfile = genPathname("/tmp", TEMP_PS); + convertTiffMultipageToPS(filein, tempfile, FILL_FACTOR); + + if (argc == 3) { + snprintf(buf, sizeof(buf), "lpr -P%s %s &", printer, tempfile); + ret = system(buf); + } + + lept_free(tempfile); + return 0; +} + diff --git a/leptonica/prog/projection_reg.c b/leptonica/prog/projection_reg.c new file mode 100644 index 00000000..04b267dd --- /dev/null +++ b/leptonica/prog/projection_reg.c @@ -0,0 +1,155 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * projection_reg.c + * + * Tests projection stats for rows and columns. + * Just for interest, a number of different tests are done. + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + +void TestProjection(L_REGPARAMS *rp, PIX *pix); + +int main(int argc, + char **argv) +{ +PIX *pixs, *pix1, *pix2; +L_REGPARAMS *rp; + + if (regTestSetup(argc, argv, &rp)) + return 1; + + /* Use for input two different images */ + pixs = pixRead("projectionstats.jpg"); + pix1 = pixConvertTo8(pixs, 0); + pixDestroy(&pixs); + pixs = pixRead("feyn.tif"); + pix2 = pixScaleToGray4(pixs); + pixDestroy(&pixs); + + TestProjection(rp, pix1); + TestProjection(rp, pix2); + pixDestroy(&pix1); + pixDestroy(&pix2); + return regTestCleanup(rp); +} + + +/* + * Test both vertical and horizontal projections on this image. + * Rotate the image by 90 degrees for the horizontal projection, + * so that the two results should be identical. + */ +void +TestProjection(L_REGPARAMS *rp, + PIX *pixs) +{ +NUMA *na1, *na2, *na3, *na4, *na5, *na6; +NUMA *na7, *na8, *na9, *na10, *na11, *na12; +PIX *pixd, *pix1, *pix2, *pix3, *pix4, *pix5, *pix6; +PIX *pix7, *pix8, *pix9, *pix10, *pix11, *pix12; +PIXA *pixa; + + pixColumnStats(pixs, NULL, &na1, &na3, &na5, &na7, &na9, &na11); + pixd = pixRotateOrth(pixs, 1); + pixRowStats(pixd, NULL, &na2, &na4, &na6, &na8, &na10, &na12); + pixDestroy(&pixd); + + pix1 = gplotSimplePix1(na1, "Mean value"); + pix2 = gplotSimplePix1(na2, "Mean value"); + pix3 = gplotSimplePix1(na3, "Median value"); + pix4 = gplotSimplePix1(na4, "Median value"); + pix5 = gplotSimplePix1(na5, "Mode value"); + pix6 = gplotSimplePix1(na6, "Mode value"); + pix7 = gplotSimplePix1(na7, "Mode count"); + pix8 = gplotSimplePix1(na8, "Mode count"); + pix9 = gplotSimplePix1(na9, "Variance"); + pix10 = gplotSimplePix1(na10, "Variance"); + pix11 = gplotSimplePix1(na11, "Square Root Variance"); + pix12 = gplotSimplePix1(na12, "Square Root Variance"); + + /* This is run twice, on two different images */ + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 0, 19 */ + regTestWritePixAndCheck(rp, pix2, IFF_PNG); /* 1, 20 */ + regTestWritePixAndCheck(rp, pix3, IFF_PNG); /* 2, 21 */ + regTestWritePixAndCheck(rp, pix4, IFF_PNG); /* 3, 22 */ + regTestWritePixAndCheck(rp, pix5, IFF_PNG); /* 4, 23 */ + regTestWritePixAndCheck(rp, pix6, IFF_PNG); /* 5, 24 */ + regTestWritePixAndCheck(rp, pix7, IFF_PNG); /* 6, 25 */ + regTestWritePixAndCheck(rp, pix8, IFF_PNG); /* 7, 26 */ + regTestWritePixAndCheck(rp, pix9, IFF_PNG); /* 8, 27 */ + regTestWritePixAndCheck(rp, pix10, IFF_PNG); /* 9, 28 */ + regTestWritePixAndCheck(rp, pix11, IFF_PNG); /* 10, 29 */ + regTestWritePixAndCheck(rp, pix12, IFF_PNG); /* 11, 30 */ + + /* Compare by pairs */ + regTestComparePix(rp, pix1, pix2); /* 12, 31 */ + regTestComparePix(rp, pix3, pix4); /* 13, 32 */ + regTestComparePix(rp, pix5, pix6); /* 14, 33 */ + regTestComparePix(rp, pix7, pix8); /* 15, 34 */ + regTestComparePix(rp, pix9, pix10); /* 16, 35 */ + regTestComparePix(rp, pix11, pix12); /* 17, 36 */ + + pixa = pixaCreate(0); + pixaAddPix(pixa, pix1, L_INSERT); + pixaAddPix(pixa, pix2, L_INSERT); + pixaAddPix(pixa, pix3, L_INSERT); + pixaAddPix(pixa, pix4, L_INSERT); + pixaAddPix(pixa, pix5, L_INSERT); + pixaAddPix(pixa, pix6, L_INSERT); + pixaAddPix(pixa, pix7, L_INSERT); + pixaAddPix(pixa, pix8, L_INSERT); + pixaAddPix(pixa, pix9, L_INSERT); + pixaAddPix(pixa, pix10, L_INSERT); + pixaAddPix(pixa, pix11, L_INSERT); + pixaAddPix(pixa, pix12, L_INSERT); + + pix1 = pixaDisplayTiledInColumns(pixa, 2, 1.0, 25, 2); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 18, 37 */ + pixDisplayWithTitle(pix1, 100, 100, NULL, rp->display); + pixDestroy(&pix1); + pixaDestroy(&pixa); + + numaDestroy(&na1); + numaDestroy(&na2); + numaDestroy(&na3); + numaDestroy(&na4); + numaDestroy(&na5); + numaDestroy(&na6); + numaDestroy(&na7); + numaDestroy(&na8); + numaDestroy(&na9); + numaDestroy(&na10); + numaDestroy(&na11); + numaDestroy(&na12); + return; +} diff --git a/leptonica/prog/projectionstats.jpg b/leptonica/prog/projectionstats.jpg Binary files differnew file mode 100644 index 00000000..0d9f23cd --- /dev/null +++ b/leptonica/prog/projectionstats.jpg diff --git a/leptonica/prog/projective_reg.c b/leptonica/prog/projective_reg.c new file mode 100644 index 00000000..70fcd040 --- /dev/null +++ b/leptonica/prog/projective_reg.c @@ -0,0 +1,234 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * projective_reg.c + * + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + +static void MakePtas(l_int32 i, PTA **pptas, PTA **pptad); + + /* Sample values. + * 1-3: invertability tests + * 4: comparison between sampling and sequential + * 5: test with large distortion + */ +static const l_int32 x1[] = { 300, 300, 300, 300, 32}; +static const l_int32 y1[] = {1200, 1200, 1250, 1250, 934}; +static const l_int32 x2[] = {1200, 1200, 1125, 1300, 487}; +static const l_int32 y2[] = {1100, 1100, 1100, 1250, 934}; +static const l_int32 x3[] = { 200, 200, 200, 250, 32}; +static const l_int32 y3[] = { 200, 200, 200, 300, 67}; +static const l_int32 x4[] = {1200, 1200, 1300, 1250, 332}; +static const l_int32 y4[] = { 400, 200, 200, 300, 57}; + +static const l_int32 xp1[] = { 300, 300, 1150, 300, 32}; +static const l_int32 yp1[] = {1200, 1400, 1150, 1350, 934}; +static const l_int32 xp2[] = {1100, 1400, 320, 1300, 487}; +static const l_int32 yp2[] = {1000, 1500, 1300, 1200, 904}; +static const l_int32 xp3[] = { 250, 200, 1310, 300, 61}; +static const l_int32 yp3[] = { 200, 300, 250, 325, 83}; +static const l_int32 xp4[] = {1250, 1200, 240, 1250, 412}; +static const l_int32 yp4[] = { 300, 300, 250, 350, 83}; + +#define ADDED_BORDER_PIXELS 250 +#define ALL 1 + + +int main(int argc, + char **argv) +{ +l_int32 i; +PIX *pixs, *pixsc, *pixb, *pixg, *pixc, *pixcs, *pix1, *pix2, *pixd; +PIXA *pixa; +PTA *ptas, *ptad; +L_REGPARAMS *rp; + + if (regTestSetup(argc, argv, &rp)) + return 1; + + pixs = pixRead("feyn.tif"); + pixsc = pixScale(pixs, 0.3, 0.3); + +#if ALL + /* Test invertability of sampling */ + lept_stderr("Test invertability of sampling\n"); + pixa = pixaCreate(0); + for (i = 0; i < 3; i++) { + pixb = pixAddBorder(pixsc, ADDED_BORDER_PIXELS, 0); + MakePtas(i, &ptas, &ptad); + pix1 = pixProjectiveSampledPta(pixb, ptad, ptas, L_BRING_IN_WHITE); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 0,3,6 */ + pixaAddPix(pixa, pix1, L_INSERT); + pix2 = pixProjectiveSampledPta(pix1, ptas, ptad, L_BRING_IN_WHITE); + regTestWritePixAndCheck(rp, pix2, IFF_PNG); /* 1,4,7 */ + pixaAddPix(pixa, pix2, L_INSERT); + pixd = pixRemoveBorder(pix2, ADDED_BORDER_PIXELS); + pixXor(pixd, pixd, pixsc); + regTestWritePixAndCheck(rp, pixd, IFF_PNG); /* 2,5,8 */ + pixaAddPix(pixa, pixd, L_INSERT); + pixDestroy(&pixb); + ptaDestroy(&ptas); + ptaDestroy(&ptad); + } + + pix1 = pixaDisplayTiledInColumns(pixa, 3, 0.5, 20, 3); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 9 */ + pixDisplayWithTitle(pix1, 0, 100, NULL, rp->display); + pixDestroy(&pix1); + pixDestroy(&pixsc); + pixaDestroy(&pixa); +#endif + +#if ALL + /* Test invertability of interpolation on grayscale */ + lept_stderr("Test invertability of grayscale interpolation\n"); + pixa = pixaCreate(0); + pixg = pixScaleToGray(pixs, 0.2); + for (i = 0; i < 2; i++) { + pixb = pixAddBorder(pixg, ADDED_BORDER_PIXELS / 2, 255); + MakePtas(i, &ptas, &ptad); + pix1 = pixProjectivePta(pixb, ptad, ptas, L_BRING_IN_WHITE); + regTestWritePixAndCheck(rp, pix1, IFF_JFIF_JPEG); /* 10,13 */ + pixaAddPix(pixa, pix1, L_INSERT); + pix2 = pixProjectivePta(pix1, ptas, ptad, L_BRING_IN_WHITE); + regTestWritePixAndCheck(rp, pix2, IFF_JFIF_JPEG); /* 11,14 */ + pixaAddPix(pixa, pix2, L_INSERT); + pixd = pixRemoveBorder(pix2, ADDED_BORDER_PIXELS / 2); + pixXor(pixd, pixd, pixg); + pixInvert(pixd, pixd); + regTestWritePixAndCheck(rp, pixd, IFF_JFIF_JPEG); /* 12,15 */ + pixaAddPix(pixa, pixd, L_INSERT); + pixDestroy(&pixb); + ptaDestroy(&ptas); + ptaDestroy(&ptad); + } + + pix1 = pixaDisplayTiledInColumns(pixa, 3, 0.5, 20, 3); + regTestWritePixAndCheck(rp, pix1, IFF_JFIF_JPEG); /* 16 */ + pixDisplayWithTitle(pix1, 300, 100, NULL, rp->display); + pixDestroy(&pix1); + pixDestroy(&pixg); + pixaDestroy(&pixa); +#endif + +#if ALL + /* Test invertability of interpolation on color */ + lept_stderr("Test invertability of color interpolation\n"); + pixa = pixaCreate(0); + pixc = pixRead("test24.jpg"); + pixcs = pixScale(pixc, 0.3, 0.3); + for (i = 0; i < 5; i++) { + if (i == 2) continue; + pixb = pixAddBorder(pixcs, ADDED_BORDER_PIXELS / 2, 0xffffff00); + MakePtas(i, &ptas, &ptad); + pix1 = pixProjectivePta(pixb, ptad, ptas, L_BRING_IN_WHITE); + regTestWritePixAndCheck(rp, pix1, IFF_JFIF_JPEG); /* 17,20,23,26 */ + pixaAddPix(pixa, pix1, L_INSERT); + pix2 = pixProjectivePta(pix1, ptas, ptad, L_BRING_IN_WHITE); + regTestWritePixAndCheck(rp, pix2, IFF_JFIF_JPEG); /* 18,21,24,27 */ + pixaAddPix(pixa, pix2, L_INSERT); + pixd = pixRemoveBorder(pix2, ADDED_BORDER_PIXELS / 2); + pixXor(pixd, pixd, pixcs); + pixInvert(pixd, pixd); + regTestWritePixAndCheck(rp, pixd, IFF_JFIF_JPEG); /* 19,22,25,28 */ + pixaAddPix(pixa, pixd, L_INSERT); + pixDestroy(&pixb); + ptaDestroy(&ptas); + ptaDestroy(&ptad); + } + + pix1 = pixaDisplayTiledInColumns(pixa, 3, 0.5, 20, 3); + regTestWritePixAndCheck(rp, pix1, IFF_JFIF_JPEG); /* 29 */ + pixDisplayWithTitle(pix1, 600, 100, NULL, rp->display); + pixDestroy(&pix1); + pixDestroy(&pixc); + pixDestroy(&pixcs); + pixaDestroy(&pixa); +#endif + +#if ALL + /* Comparison between sampling and interpolated */ + lept_stderr("Compare sampling with interpolated\n"); + MakePtas(3, &ptas, &ptad); + pixa = pixaCreate(0); + pixg = pixScaleToGray(pixs, 0.2); + + /* Use sampled transform */ + pix1 = pixProjectiveSampledPta(pixg, ptas, ptad, L_BRING_IN_WHITE); + regTestWritePixAndCheck(rp, pix1, IFF_JFIF_JPEG); /* 30 */ + pixaAddPix(pixa, pix1, L_INSERT); + + /* Use interpolated transforms */ + pix2 = pixProjectivePta(pixg, ptas, ptad, L_BRING_IN_WHITE); + regTestWritePixAndCheck(rp, pix2, IFF_JFIF_JPEG); /* 31 */ + pixaAddPix(pixa, pix2, L_COPY); + + /* Compare the results */ + pixXor(pix2, pix2, pix1); + pixInvert(pix2, pix2); + regTestWritePixAndCheck(rp, pix2, IFF_JFIF_JPEG); /* 32 */ + pixaAddPix(pixa, pix2, L_INSERT); + + pix1 = pixaDisplayTiledInColumns(pixa, 3, 0.5, 20, 3); + regTestWritePixAndCheck(rp, pix1, IFF_JFIF_JPEG); /* 33 */ + pixDisplayWithTitle(pix1, 900, 100, NULL, rp->display); + pixDestroy(&pix1); + pixDestroy(&pixg); + pixaDestroy(&pixa); + ptaDestroy(&ptas); + ptaDestroy(&ptad); +#endif + + pixDestroy(&pixs); + return regTestCleanup(rp); +} + +static void +MakePtas(l_int32 i, + PTA **pptas, + PTA **pptad) +{ + + *pptas = ptaCreate(4); + ptaAddPt(*pptas, x1[i], y1[i]); + ptaAddPt(*pptas, x2[i], y2[i]); + ptaAddPt(*pptas, x3[i], y3[i]); + ptaAddPt(*pptas, x4[i], y4[i]); + *pptad = ptaCreate(4); + ptaAddPt(*pptad, xp1[i], yp1[i]); + ptaAddPt(*pptad, xp2[i], yp2[i]); + ptaAddPt(*pptad, xp3[i], yp3[i]); + ptaAddPt(*pptad, xp4[i], yp4[i]); + return; +} + diff --git a/leptonica/prog/ps2jpeg b/leptonica/prog/ps2jpeg new file mode 100644 index 00000000..8f533ac4 --- /dev/null +++ b/leptonica/prog/ps2jpeg @@ -0,0 +1,32 @@ +#!/bin/bash +# ps2jpeg +# +# Rasterizes a postscript file, saving as a set of RGB images +# +# input: PostScript file +# root name of output files +# output: 24 bpp RGB jpeg files for each page +# +# N.B. Requires ghostscript + +scriptname=${0##*/} + +if test $# != 2 +then + echo "usage: " $scriptname " inpsfile outjpgroot" + exit -1 +fi + +inpsfile=$1 +outjpgroot=$2 + +# (need mysterious "primer") +# choose one of the two options below + +# output image size depending on resolution +echo "0 neg 0 neg" translate | /usr/local/bin/gs -sDEVICE=jpeg -sOutputFile=${outjpgroot}%03d.jpg -r300x300 -q - ${inpsfile} + +# output fixed image size +#echo "0 neg 0 neg" translate | gs -sDEVICE=jpeg -sOutputFile=${outjpgroot}%03d.jpg -g2550x3300 -r300x300 -q - ${inpsfile} + + diff --git a/leptonica/prog/ps2png b/leptonica/prog/ps2png new file mode 100644 index 00000000..bace17a4 --- /dev/null +++ b/leptonica/prog/ps2png @@ -0,0 +1,43 @@ +#!/bin/bash +# ps2png +# +# Rasterizes a postscript file, saving as a set of bitmaps +# +# input: PostScript file +# root name of output files +# output: png binary files for each page +# +# Restriction: the input PostScript file must be binary +# +# N.B. Requires ghostscript + +scriptname=${0##*/} + +if test $# != 2 +then + echo "usage: " $scriptname " inpsfile outpngroot" + exit -1 +fi + +inpsfile=$1 +outpngroot=$2 + +# strip off directory and suffix parts of $1 to use in other names +basename=${1##*/} +baseroot=${basename%.*} + +# make names for temporary files +tmppsfile=${baseroot}.$$_.ps +tmppsroot=${tmppsfile%.*} + +# have the temporary files deleted on exit, interrupt, etc: +trap "/bin/rm -f ${tmppsroot}*" EXIT SIGHUP SIGINT SIGTERM + +cp $inpsfile $tmppsfile + +# need mysterious "primer" +echo "0 neg 0 neg" translate | gs -sDEVICE=pngmono -sOutputFile=${outpngroot}%03d.png -g2550x3300 -r300x300 -q - ${tmppsfile} + + + + diff --git a/leptonica/prog/ps2png-binary b/leptonica/prog/ps2png-binary new file mode 100644 index 00000000..fae33e14 --- /dev/null +++ b/leptonica/prog/ps2png-binary @@ -0,0 +1,35 @@ +#!/bin/bash +# ps2png-binary +# +# Rasterizes a postscript file, saving as a set of binary png images +# +# input: PostScript file +# root name of output files +# output: png binary files for each page +# +# Restriction: the input PostScript file must be binary +# +# N.B. Requires ghostscript + +scriptname=${0##*/} + +if test $# != 2 +then + echo "usage: " $scriptname " inpsfile outpngroot" + exit -1 +fi + +inpsfile=$1 +outpngroot=$2 + +# need mysterious "primer" +# choose one of the two options below + +# output image size depending on resolution +echo "0 neg 0 neg" translate | gs -sDEVICE=pngmono -sOutputFile=${outpngroot}%03d.png -r300x300 -q - ${inpsfile} + +# output fixed image size +#echo "0 neg 0 neg" translate | gs -sDEVICE=pngmono -sOutputFile=${outpngroot}%03d.png -g2550x3300 -r300x300 -q - ${inpsfile} + + + diff --git a/leptonica/prog/ps2png-color b/leptonica/prog/ps2png-color new file mode 100644 index 00000000..e9c18941 --- /dev/null +++ b/leptonica/prog/ps2png-color @@ -0,0 +1,33 @@ +#!/bin/bash +# ps2png-color +# +# Rasterizes a postscript file, saving as a set of 24 bpp RGB png images +# +# input: PostScript file +# root name of output files +# output: 24 bpp RGB png files for each page +# +# N.B. Requires ghostscript + +scriptname=${0##*/} + +if test $# != 2 +then + echo "usage: " $scriptname " inpsfile outpngroot" + exit -1 +fi + +inpsfile=$1 +outpngroot=$2 + +# need mysterious "primer" +# choose one of the two options below + +# output image size depending on resolution +echo "0 neg 0 neg" translate | gs -sDEVICE=png16m -sOutputFile=${outpngroot}%03d.png -r300x300 -q - ${inpsfile} + +# output fixed image size +echo "0 neg 0 neg" translate | gs -sDEVICE=png16m -sOutputFile=${outpngroot}%03d.png -g2550x3300 -r300x300 -q - ${inpsfile} + + + diff --git a/leptonica/prog/ps2png-gray b/leptonica/prog/ps2png-gray new file mode 100644 index 00000000..ab03da81 --- /dev/null +++ b/leptonica/prog/ps2png-gray @@ -0,0 +1,33 @@ +#!/bin/bash +# ps2png-gray +# +# Rasterizes a postscript file, saving as a set of 8 bpp png images +# +# input: PostScript file +# root name of output files +# output: 8 bpp png files for each page +# +# N.B. Requires ghostscript + +scriptname=${0##*/} + +if test $# != 2 +then + echo "usage: " $scriptname " inpsfile outpngroot" + exit -1 +fi + +inpsfile=$1 +outpngroot=$2 + +# need mysterious "primer" +# choose one of the two options below + +# output image size depending on resolution +echo "0 neg 0 neg" translate | gs -sDEVICE=pnggray -sOutputFile=${outpngroot}%03d.png -r300x300 -q - ${inpsfile} + +# output fixed image size +#echo "0 neg 0 neg" translate | gs -sDEVICE=pnggray -sOutputFile=${outpngroot}%03d.png -g2550x3300 -r300x300 -q - ${inpsfile} + + + diff --git a/leptonica/prog/ps2tiff b/leptonica/prog/ps2tiff new file mode 100644 index 00000000..f6b7c966 --- /dev/null +++ b/leptonica/prog/ps2tiff @@ -0,0 +1,42 @@ +#!/bin/bash +# ps2tiff +# +# Rasterizes a postscript file, saving as a set of g4 compressed +# tiff images +# +# input: PostScript file +# root name of output files +# output: ccitt-g4 compressed tiff binary files for each page +# +# Restriction: the input PostScript file must be binary +# +# N.B. Requires ghostscript + +scriptname=${0##*/} + +if test $# != 2 +then + echo "usage: " $scriptname " inpsfile outtifroot" + exit -1 +fi + +inpsfile=$1 +outtifroot=$2 + +# assert (input postscript filename ends in .ps) +if test ${inpsfile##*.} != ps +then + echo $scriptname ": " $inpsfile "does not end in .ps" + exit -1 +fi + +# output image size depending on resolution +#echo "0 neg 0 neg" translate | gs -sDEVICE=tiffg4 -sOutputFile=${outtifroot}%03d.tif -r300x300 -q - ${inpsfile} +echo "0 neg 0 neg" translate | ~/pckg/gs/ghostscript-8.53/bin/gs -sDEVICE=tiffg4 -sOutputFile=${outtifroot}%03d.tif -r300x300 -q - ${inpsfile} + +# output fixed image size +#echo "0 neg 0 neg" translate | gs -sDEVICE=tiffg4 -sOutputFile=${outtifroot}%03d.tif -g2550x3300 -r300x300 -q - ${inpsfile} + +# use this to output to a single multipage tiff file +#tiffcp -c g4 ${outtifroot}*.tif ${outtifroot}.tif + diff --git a/leptonica/prog/psio_reg.c b/leptonica/prog/psio_reg.c new file mode 100644 index 00000000..e14a65b2 --- /dev/null +++ b/leptonica/prog/psio_reg.c @@ -0,0 +1,250 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * psio_reg.c + * + * Tests writing of images in PS, with arbitrary scaling and + * translation, in the following formats: + * + * - uncompressed + * - DCT compressed (jpeg for 8 bpp grayscale and RGB) + * - CCITT-G4 compressed (g4 fax compression for 1 bpp) + * - Flate compressed (gzip compression) + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + +static const char *WeaselNames[] = {"weasel2.4c.png", + "weasel2.4g.png", + "weasel2.png", + "weasel4.11c.png", + "weasel4.8g.png", + "weasel4.16g.png", + "weasel8.16g.png", + "weasel8.149g.png", + "weasel8.240c.png", + "weasel8.png", + "weasel32.png"}; +int main(int argc, + char **argv) +{ +l_int32 i, w, h; +l_float32 factor, scale; +BOX *box; +FILE *fp1; +PIX *pixs, *pixt; +PIXA *pixa; +SARRAY *sa; +L_REGPARAMS *rp; + +#if !defined(HAVE_LIBPNG) + L_ERROR("This test requires libpng to run.\n", "psio_reg"); + exit(77); +#endif +#if !defined(HAVE_LIBJPEG) + L_ERROR("This test requires libjpeg to run.\n", "psio_reg"); + exit(77); +#endif +#if !defined(HAVE_LIBTIFF) + L_ERROR("This test requires libtiff to run.\n", "psio_reg"); + exit(77); +#endif + + if (regTestSetup(argc, argv, &rp)) + return 1; + +#if !USE_PSIO + lept_stderr("psio writing is not enabled\n" + "See environ.h: #define USE_PSIO 1\n\n"); + regTestCleanup(rp); + return 0; +#endif /* abort */ + + factor = 0.95; + + /* Uncompressed PS with scaling but centered on the page */ + pixs = pixRead("feyn-fract.tif"); + pixGetDimensions(pixs, &w, &h, NULL); + scale = L_MIN(factor * 2550 / w, factor * 3300 / h); + fp1 = lept_fopen("/tmp/lept/regout/psio0.ps", "wb+"); + pixWriteStreamPS(fp1, pixs, NULL, 300, scale); + lept_fclose(fp1); + regTestCheckFile(rp, "/tmp/lept/regout/psio0.ps"); /* 0 */ + pixDestroy(&pixs); + + /* Uncompressed PS with scaling, with LL corner at (1500, 1500) mils */ + pixs = pixRead("weasel4.11c.png"); + pixGetDimensions(pixs, &w, &h, NULL); + scale = L_MIN(factor * 2550 / w, factor * 3300 / h); + box = boxCreate(1500, 1500, (l_int32)(1000 * scale * w / 300), + (l_int32)(1000 * scale * h / 300)); + fp1 = lept_fopen("/tmp/lept/regout/psio1.ps", "wb+"); + pixWriteStreamPS(fp1, pixs, box, 300, 1.0); + lept_fclose(fp1); + regTestCheckFile(rp, "/tmp/lept/regout/psio1.ps"); /* 1 */ + boxDestroy(&box); + pixDestroy(&pixs); + + /* DCT compressed PS with LL corner at (300, 1000) pixels */ + pixs = pixRead("marge.jpg"); + pixt = pixConvertTo32(pixs); + pixWrite("/tmp/lept/regout/psio2.jpg", pixt, IFF_JFIF_JPEG); + convertJpegToPS("/tmp/lept/regout/psio2.jpg", "/tmp/lept/regout/psio3.ps", + "w", 300, 1000, 0, 4.0, 1, 1); + regTestCheckFile(rp, "/tmp/lept/regout/psio2.jpg"); /* 2 */ + regTestCheckFile(rp, "/tmp/lept/regout/psio3.ps"); /* 3 */ + pixDestroy(&pixt); + pixDestroy(&pixs); + + /* For each page, apply tiff g4 image first; then jpeg or png over it */ + convertG4ToPS("feyn.tif", "/tmp/lept/regout/psio4.ps", "w", + 0, 0, 0, 1.0, 1, 1, 0); + convertJpegToPS("marge.jpg", "/tmp/lept/regout/psio4.ps", + "a", 500, 100, 300, 2.0, 1, 0); + convertFlateToPS("weasel4.11c.png", "/tmp/lept/regout/psio4.ps", + "a", 300, 400, 300, 6.0, 1, 0); + convertJpegToPS("marge.jpg", "/tmp/lept/regout/psio4.ps", + "a", 100, 800, 300, 1.5, 1, 1); + + convertG4ToPS("feyn.tif", "/tmp/lept/regout/psio4.ps", + "a", 0, 0, 0, 1.0, 2, 1, 0); + convertJpegToPS("marge.jpg", "/tmp/lept/regout/psio4.ps", + "a", 1000, 700, 300, 2.0, 2, 0); + convertJpegToPS("marge.jpg", "/tmp/lept/regout/psio4.ps", + "a", 100, 200, 300, 2.0, 2, 1); + + convertG4ToPS("feyn.tif", "/tmp/lept/regout/psio4.ps", + "a", 0, 0, 0, 1.0, 3, 1, 0); + convertJpegToPS("marge.jpg", "/tmp/lept/regout/psio4.ps", + "a", 200, 200, 300, 2.0, 3, 0); + convertJpegToPS("marge.jpg", "/tmp/lept/regout/psio4.ps", + "a", 200, 900, 300, 2.0, 3, 1); + regTestCheckFile(rp, "/tmp/lept/regout/psio4.ps"); /* 4 */ + + /* Now apply jpeg first; then paint through a g4 mask. + * For gv, the first image with a b.b. determines the + * window size for the canvas, so we put down the largest + * image first. If we had rendered a small image first, + * gv and evince will not show the entire page. However, after + * conversion to pdf, everything works fine, regardless of the + * order in which images are placed into the PS. That is + * because the pdf interpreter is robust to bad hints, ignoring + * the page hints and computing the bounding box from the + * set of images rendered on the page. + * + * Concatenate several pages, with colormapped png, color + * jpeg and tiffg4 images (with the g4 image acting as a mask + * that we're painting black through. If the text layer + * is painted first, the following images occlude it; otherwise, + * the images remain in the background of the text. */ + pixs = pixRead("wyom.jpg"); + pixt = pixScaleToSize(pixs, 2528, 3300); + pixWrite("/tmp/lept/regout/psio5.jpg", pixt, IFF_JFIF_JPEG); + pixDestroy(&pixs); + pixDestroy(&pixt); + convertJpegToPS("/tmp/lept/regout/psio5.jpg", "/tmp/lept/regout/psio5.ps", + "w", 0, 0, 300, 1.0, 1, 0); + convertFlateToPS("weasel8.240c.png", "/tmp/lept/regout/psio5.ps", + "a", 100, 100, 300, 5.0, 1, 0); + convertFlateToPS("weasel8.149g.png", "/tmp/lept/regout/psio5.ps", + "a", 200, 300, 300, 5.0, 1, 0); + convertFlateToPS("weasel4.11c.png", "/tmp/lept/regout/psio5.ps", + "a", 300, 500, 300, 5.0, 1, 0); + convertG4ToPS("feyn.tif", "/tmp/lept/regout/psio5.ps", + "a", 0, 0, 0, 1.0, 1, 1, 1); + + convertJpegToPS("marge.jpg", "/tmp/lept/regout/psio5.ps", + "a", 500, 100, 300, 2.0, 2, 0); + convertFlateToPS("weasel4.11c.png", "/tmp/lept/regout/psio5.ps", + "a", 300, 400, 300, 6.0, 2, 0); + convertJpegToPS("marge.jpg", "/tmp/lept/regout/psio5.ps", + "a", 100, 800, 300, 1.5, 2, 0); + convertG4ToPS("feyn.tif", "/tmp/lept/regout/psio5.ps", + "a", 0, 0, 0, 1.0, 2, 1, 1); + + convertJpegToPS("marge.jpg", "/tmp/lept/regout/psio5.ps", + "a", 500, 100, 300, 2.0, 3, 0); + convertJpegToPS("marge.jpg", "/tmp/lept/regout/psio5.ps", + "a", 100, 800, 300, 2.0, 3, 0); + convertG4ToPS("feyn.tif", "/tmp/lept/regout/psio5.ps", + "a", 0, 0, 0, 1.0, 3, 1, 1); + + convertJpegToPS("marge.jpg", "/tmp/lept/regout/psio5.ps", + "a", 700, 700, 300, 2.0, 4, 0); + convertFlateToPS("weasel8.149g.png", "/tmp/lept/regout/psio5.ps", + "a", 400, 400, 300, 5.0, 4, 0); + convertG4ToPS("feyn.tif", "/tmp/lept/regout/psio5.ps", + "a", 0, 0, 0, 1.0, 4, 1, 0); + convertFlateToPS("weasel8.240c.png", "/tmp/lept/regout/psio5.ps", + "a", 100, 220, 300, 5.0, 4, 0); + convertJpegToPS("marge.jpg", "/tmp/lept/regout/psio5.ps", + "a", 100, 200, 300, 2.0, 4, 1); + + convertJpegToPS("marge.jpg", "/tmp/lept/regout/psio5.ps", + "a", 200, 200, 300, 1.5, 5, 0); + convertFlateToPS("weasel8.240c.png", "/tmp/lept/regout/psio5.ps", + "a", 140, 80, 300, 7.0, 5, 0); + convertG4ToPS("feyn.tif", "/tmp/lept/regout/psio5.ps", + "a", 0, 0, 0, 1.0, 5, 1, 0); + convertFlateToPS("weasel8.149g.png", "/tmp/lept/regout/psio5.ps", + "a", 280, 310, 300, 5.0, 4, 0); + convertJpegToPS("marge.jpg", "/tmp/lept/regout/psio5.ps", + "a", 200, 900, 300, 2.0, 5, 1); + regTestCheckFile(rp, "/tmp/lept/regout/psio5.ps"); /* 5 */ + + /* Generation using segmentation masks */ + convertSegmentedPagesToPS(".", "lion-page", 10, ".", "lion-mask", 10, + 0, 100, 2.0, 0.8, 190, + "/tmp/lept/regout/psio6.ps"); + regTestCheckFile(rp, "/tmp/lept/regout/psio6.ps"); /* 6 */ + + /* PS generation for embeddding */ + convertJpegToPSEmbed("tetons.jpg", "/tmp/lept/regout/psio7.ps"); + regTestCheckFile(rp, "/tmp/lept/regout/psio7.ps"); /* 7 */ + + convertG4ToPSEmbed("feyn-fract.tif", "/tmp/lept/regout/psio8.ps"); + regTestCheckFile(rp, "/tmp/lept/regout/psio8.ps"); /* 8 */ + + convertFlateToPSEmbed("weasel8.240c.png", "/tmp/lept/regout/psio9.ps"); + regTestCheckFile(rp, "/tmp/lept/regout/psio9.ps"); /* 9 */ + + /* Writing compressed from a pixa */ + sa = sarrayCreate(0); + for (i = 0; i < 11; i++) + sarrayAddString(sa, WeaselNames[i], L_COPY); + pixa = pixaReadFilesSA(sa); + pixaWriteCompressedToPS(pixa, "/tmp/lept/regout/psio10.ps", 0, 3); + regTestCheckFile(rp, "/tmp/lept/regout/psio10.ps"); /* 10 */ + pixaDestroy(&pixa); + sarrayDestroy(&sa); + + return regTestCleanup(rp); +} diff --git a/leptonica/prog/psioseg_reg.c b/leptonica/prog/psioseg_reg.c new file mode 100644 index 00000000..c0a63fff --- /dev/null +++ b/leptonica/prog/psioseg_reg.c @@ -0,0 +1,174 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * psioseg_reg.c + * + * This tests the PostScript output for images with mixed + * text and images, coming from source of different depths, + * with and without colormaps. + * + * Both convertFilesFittedToPS() and convertSegmentedPagesToPS() + * generate a compressed PostScript file from a subset of images in + * a directory. However, the latter function can also accept 1 bpp + * masks that delineate image (as opposed to text) regions in + * the corresponding page image file. Then, for page images that + * are not 1 bpp, it generates mixed raster PostScript with + * g4 encoding for the text and jpeg ("DCT") encoding for the + * maining image parts. + * + * N.B. Although not required for 'success' on the regression test, + * this program uses ps2pdf to generate the pdf output. + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + +int main(int argc, + char **argv) +{ +char buf[512]; +char *psname, *pdfname; +l_int32 w, h, wc, hc, ret; +l_float32 scalefactor; +PIX *pixs, *pixc, *pixht, *pixtxt, *pixmfull; +PIX *pix4c, *pix8c, *pix8g, *pix32, *pixcs, *pixcs2; +L_REGPARAMS *rp; + +#if !defined(HAVE_LIBPNG) + L_ERROR("This test requires libpng to run.\n", "psioseg_reg"); + exit(77); +#endif +#if !defined(HAVE_LIBJPEG) + L_ERROR("This test requires libjpeg to run.\n", "psioseg_reg"); + exit(77); +#endif +#if !defined(HAVE_LIBTIFF) + L_ERROR("This test requires libtiff to run.\n", "psioseg_reg"); + exit(77); +#endif + + if (regTestSetup(argc, argv, &rp)) + return 1; + +#if !USE_PSIO + lept_stderr("psio writing is not enabled\n" + "See environ.h: #define USE_PSIO 1\n\n"); + regTestCleanup(rp); + return 0; +#endif /* abort */ + + /* Source for generating images */ + pixs = pixRead("pageseg2.tif"); /* 1 bpp */ + pixc = pixRead("tetons.jpg"); /* 32 bpp */ + + /* Get a halftone segmentation mask for pixs */ + pixGetRegionsBinary(pixs, &pixht, NULL, NULL, 0); + pixtxt = pixSubtract(NULL, pixs, pixht); + + /* Construct a 32 bpp image in full page size, along with + * a mask that can be used to render it. */ + pixGetDimensions(pixs, &w, &h, NULL); + pixGetDimensions(pixc, &wc, NULL, NULL); + scalefactor = (l_float32)w / (l_float32)wc; + pixcs = pixScale(pixc, scalefactor, scalefactor); + pixGetDimensions(pixcs, &wc, &hc, NULL); + pixcs2 = pixCreate(w, h, 32); + pixRasterop(pixcs2, 0, 0, w, hc, PIX_SRC, pixcs, 0, 0); + pixRasterop(pixcs2, 0, hc, w, hc, PIX_SRC, pixcs, 0, 0); + regTestWritePixAndCheck(rp, pixcs2, IFF_JFIF_JPEG); /* 0 */ + pixmfull = pixCreate(w, h, 1); + pixSetAll(pixmfull); /* use as mask to render the color image */ + + /* Now make a 32 bpp input image, taking text parts from the + * page image and image parts from pixcs2. */ + pix32 = pixConvertTo32(pixtxt); + pixCombineMasked(pix32, pixcs2, pixht); + regTestWritePixAndCheck(rp, pix32, IFF_JFIF_JPEG); /* 1 */ + + /* Make an 8 bpp gray version */ + pix8g = pixConvertRGBToLuminance(pix32); + regTestWritePixAndCheck(rp, pix8g, IFF_JFIF_JPEG); /* 2 */ + + /* Make an 8 bpp colormapped version */ + pix8c = pixOctreeColorQuant(pix32, 240, 0); + regTestWritePixAndCheck(rp, pix8c, IFF_PNG); /* 3 */ + + /* Make a 4 bpp colormapped version */ + pix4c = pixOctreeQuantNumColors(pix32, 16, 4); + regTestWritePixAndCheck(rp, pix4c, IFF_PNG); /* 4 */ + + /* Write out the files to be imaged */ + lept_mkdir("lept/psio"); + pixWrite("/tmp/lept/psio/image_001.tif", pixs, IFF_TIFF_G4); + pixWrite("/tmp/lept/psio/image_002.tif", pixht, IFF_TIFF_G4); + pixWrite("/tmp/lept/psio/image_003.tif", pixtxt, IFF_TIFF_G4); + pixWrite("/tmp/lept/psio/image_004.jpg", pixcs2, IFF_JFIF_JPEG); + pixWrite("/tmp/lept/psio/mask_004.tif", pixmfull, IFF_TIFF_G4); + pixWrite("/tmp/lept/psio/image_005.jpg", pix32, IFF_JFIF_JPEG); + pixWrite("/tmp/lept/psio/mask_005.tif", pixht, IFF_TIFF_G4); + pixWrite("/tmp/lept/psio/image_006.jpg", pix8g, IFF_JFIF_JPEG); + pixWrite("/tmp/lept/psio/mask_006.tif", pixht, IFF_TIFF_G4); + pixWrite("/tmp/lept/psio/image_007.png", pix8c, IFF_PNG); + pixWrite("/tmp/lept/psio/mask_007.tif", pixht, IFF_TIFF_G4); + pixWrite("/tmp/lept/psio/image_008.png", pix4c, IFF_PNG); + pixWrite("/tmp/lept/psio/mask_008.tif", pixht, IFF_TIFF_G4); + pixDestroy(&pixs); + pixDestroy(&pixc); + pixDestroy(&pixht); + pixDestroy(&pixtxt); + pixDestroy(&pixcs); + pixDestroy(&pixcs2); + pixDestroy(&pixmfull); + pixDestroy(&pix32); + pixDestroy(&pix8g); + pixDestroy(&pix8c); + pixDestroy(&pix4c); + + /* Generate the 8 page ps */ + convertSegmentedPagesToPS("/tmp/lept/psio", "image_", 6, "/tmp/lept/psio", + "mask_", 5, 0, 10, 2.0, 0.15, 190, + "/tmp/lept/regout/psioseg.5.ps"); + regTestCheckFile(rp, "/tmp/lept/regout/psioseg.5.ps"); /* 5 */ + L_INFO("Output ps: /tmp/lept/regout/psioseg.5.ps\n", rp->testname); + + /* For convenience, also generate a pdf of this, using ps2pdf */ + psname = genPathname("/tmp/lept/regout", "psioseg.5.ps"); + pdfname = genPathname("/tmp/lept/regout", "psioseg.5.pdf"); + snprintf(buf, sizeof(buf), "ps2pdf %s %s", psname, pdfname); + ret = system(buf); /* ps2pdf */ + lept_free(psname); + lept_free(pdfname); + if (!ret) + L_INFO("Output pdf: /tmp/lept/regout/psioseg.5.pdf\n", rp->testname); + else + L_WARNING("ps2pdf failed to generate pdf\n", rp->testname); + + return regTestCleanup(rp); +} diff --git a/leptonica/prog/pta_reg.c b/leptonica/prog/pta_reg.c new file mode 100644 index 00000000..74b045d2 --- /dev/null +++ b/leptonica/prog/pta_reg.c @@ -0,0 +1,228 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * pta_reg.c + * + * This tests several ptaa functions, including: + * - ptaaGetBoundaryPixels() + * - pixRenderRandomCmapPtaa() + * - pixDisplayPtaa() + * + * Also tests these pta functions: + * - pixRenderPtaArb() + * - ptaRotate() + * - ptaSort() + * - ptaSort2d() + * - ptaEqual() + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + +static PIX *PtaDisplayRotate(PIX *pixs, l_float32 xc, l_float32 yc); + +int main(int argc, + char **argv) +{ +l_int32 i, nbox, npta, fgcount, bgcount, count, w, h, x, y, same; +BOXA *boxa; +PIX *pixs, *pixfg, *pixbg, *pixc, *pixb, *pixd; +PIX *pix1, *pix2, *pix3, *pix4; +PIXA *pixa; +PTA *pta, *pta1, *pta2, *pta3; +PTAA *ptaafg, *ptaabg; +L_REGPARAMS *rp; + + if (regTestSetup(argc, argv, &rp)) + return 1; + + pixs = pixRead("feyn-fract.tif"); + boxa = pixConnComp(pixs, NULL, 8); + nbox = boxaGetCount(boxa); + regTestCompareValues(rp, nbox, 464, 0); /* 0 */ + + /* Get fg and bg boundary pixels */ + pixfg = pixMorphSequence(pixs, "e3.3", 0); + pixXor(pixfg, pixfg, pixs); + pixCountPixels(pixfg, &fgcount, NULL); + regTestCompareValues(rp, fgcount, 58764, 0); /* 1 */ + + pixbg = pixMorphSequence(pixs, "d3.3", 0); + pixXor(pixbg, pixbg, pixs); + pixCountPixels(pixbg, &bgcount, NULL); + regTestCompareValues(rp, bgcount, 60335, 0); /* 2 */ + + /* Get ptaa of fg pixels */ + ptaafg = ptaaGetBoundaryPixels(pixs, L_BOUNDARY_FG, 8, NULL, NULL); + npta = ptaaGetCount(ptaafg); + regTestCompareValues(rp, npta, nbox, 0); /* 3 */ + count = 0; + for (i = 0; i < npta; i++) { + pta = ptaaGetPta(ptaafg, i, L_CLONE); + count += ptaGetCount(pta); + ptaDestroy(&pta); + } + regTestCompareValues(rp, fgcount, count, 0); /* 4 */ + + /* Get ptaa of bg pixels. Note that the number of bg pts + * is, in general, larger than the number of bg boundary pixels, + * because bg boundary pixels are shared by two c.c. that + * are 1 pixel apart. */ + ptaabg = ptaaGetBoundaryPixels(pixs, L_BOUNDARY_BG, 8, NULL, NULL); + npta = ptaaGetCount(ptaabg); + regTestCompareValues(rp, npta, nbox, 0); /* 5 */ + count = 0; + for (i = 0; i < npta; i++) { + pta = ptaaGetPta(ptaabg, i, L_CLONE); + count += ptaGetCount(pta); + ptaDestroy(&pta); + } + regTestCompareValues(rp, count, 60602, 0); /* 6 */ + + /* Render the fg boundary pixels on top of pixs. */ + pixa = pixaCreate(4); + pixc = pixRenderRandomCmapPtaa(pixs, ptaafg, 0, 0, 0); + regTestWritePixAndCheck(rp, pixc, IFF_PNG); /* 7 */ + pixaAddPix(pixa, pixc, L_INSERT); + + /* Render the bg boundary pixels on top of pixs. */ + pixc = pixRenderRandomCmapPtaa(pixs, ptaabg, 0, 0, 0); + regTestWritePixAndCheck(rp, pixc, IFF_PNG); /* 8 */ + pixaAddPix(pixa, pixc, L_INSERT); + pixClearAll(pixs); + + /* Render the fg boundary pixels alone. */ + pixc = pixRenderRandomCmapPtaa(pixs, ptaafg, 0, 0, 0); + regTestWritePixAndCheck(rp, pixc, IFF_PNG); /* 9 */ + pixaAddPix(pixa, pixc, L_INSERT); + + /* Verify that the fg pixels are the same set as we + * originally started with. */ + pixb = pixConvertTo1(pixc, 255); + regTestComparePix(rp, pixb, pixfg); /* 10 */ + pixDestroy(&pixb); + + /* Render the bg boundary pixels alone. */ + pixc = pixRenderRandomCmapPtaa(pixs, ptaabg, 0, 0, 0); + regTestWritePixAndCheck(rp, pixc, IFF_PNG); /* 11 */ + pixaAddPix(pixa, pixc, L_INSERT); + + /* Verify that the bg pixels are the same set as we + * originally started with. */ + pixb = pixConvertTo1(pixc, 255); + regTestComparePix(rp, pixb, pixbg); /* 12 */ + pixDestroy(&pixb); + + pixd = pixaDisplayTiledInColumns(pixa, 1, 1.0, 30, 2); + pixDisplayWithTitle(pixd, 0, 0, NULL, rp->display); + ptaaDestroy(&ptaafg); + ptaaDestroy(&ptaabg); + pixDestroy(&pixs); + pixDestroy(&pixfg); + pixDestroy(&pixbg); + pixDestroy(&pixd); + pixaDestroy(&pixa); + boxaDestroy(&boxa); + + /* Test rotation */ + pix1 = pixRead("feyn-word.tif"); + pix2 = pixAddBorderGeneral(pix1, 200, 200, 200, 200, 0); + pixa = pixaCreate(0); + pix3 = PtaDisplayRotate(pix2, 0, 0); + pixaAddPix(pixa, pix3, L_INSERT); + pix3 = PtaDisplayRotate(pix2, 500, 100); + pixaAddPix(pixa, pix3, L_INSERT); + pix3 = PtaDisplayRotate(pix2, 100, 410); + pixaAddPix(pixa, pix3, L_INSERT); + pix3 = PtaDisplayRotate(pix2, 500, 410); + pixaAddPix(pixa, pix3, L_INSERT); + pix4 = pixaDisplayTiledInRows(pixa, 32, 1500, 1.0, 0, 30, 2); + regTestWritePixAndCheck(rp, pix4, IFF_PNG); /* 13 */ + pixDisplayWithTitle(pix4, 800, 0, NULL, rp->display); + pixDestroy(&pix1); + pixDestroy(&pix2); + pixDestroy(&pix4); + pixaDestroy(&pixa); + + /* Test pta sort and pta equality */ + pix1 = pixRead("feyn-word.tif"); + pixGetDimensions(pix1, &w, &h, NULL); + pta1 = ptaGetPixelsFromPix(pix1, NULL); + ptaGetIPt(pta1, 0, &x, &y); /* add copy of first point */ + ptaAddPt(pta1, x, y); + pta2 = ptaCyclicPerm(pta1, x, y); /* first/last points must be the same */ + ptaEqual(pta1, pta2, &same); + regTestCompareValues(rp, same, 1, 0.0); /* 14 */ + pta3 = ptaReverse(pta2, 1); + ptaEqual(pta1, pta3, &same); + regTestCompareValues(rp, same, 1, 0.0); /* 15 */ + pixDestroy(&pix1); + ptaDestroy(&pta1); + ptaDestroy(&pta2); + ptaDestroy(&pta3); + + return regTestCleanup(rp); +} + + +static PIX * +PtaDisplayRotate(PIX *pixs, + l_float32 xc, + l_float32 yc) +{ +l_int32 i, w, h; +PIX *pix1, *pix2; +PTA *pta1, *pta2, *pta3, *pta4; +PTAA *ptaa; + + /* Save rotated sets of pixels */ + pta1 = ptaGetPixelsFromPix(pixs, NULL); + ptaa = ptaaCreate(0); + for (i = 0; i < 9; i++) { + pta2 = ptaRotate(pta1, xc, yc, -0.8 + 0.2 * i); + ptaaAddPta(ptaa, pta2, L_INSERT); + } + ptaDestroy(&pta1); + + /* Render them */ + pixGetDimensions(pixs, &w, &h, NULL); + pix1 = pixCreate(w, h, 32); + pixSetAll(pix1); + pta3 = generatePtaFilledCircle(4); + pta4 = ptaTranslate(pta3, xc, yc); + pixRenderPtaArb(pix1, pta4, 255, 0, 0); /* circle at rotation center */ + pix2 = pixDisplayPtaa(pix1, ptaa); /* rotated sets */ + + pixDestroy(&pix1); + ptaDestroy(&pta3); + ptaDestroy(&pta4); + ptaaDestroy(&ptaa); + return pix2; +} diff --git a/leptonica/prog/ptra1_reg.c b/leptonica/prog/ptra1_reg.c new file mode 100644 index 00000000..defaf0f9 --- /dev/null +++ b/leptonica/prog/ptra1_reg.c @@ -0,0 +1,488 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * ptra1_reg.c + * + * Testing basic ptra operations + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + +static void MakePtrasFromPixa(PIXA *pixa, L_PTRA **ppapix, L_PTRA **ppabox, + l_int32 copyflag); +static PIXA *ReconstructPixa1(L_REGPARAMS *rp, L_PTRA *papix, L_PTRA *pabox); +static PIXA *ReconstructPixa2(L_REGPARAMS *rp, L_PTRA *papix, L_PTRA *pabox); +static PIX *SaveResult(PIXA *pixac, PIXA **ppixa, l_int32 w, l_int32 h, + l_int32 newline); + +int main(int argc, + char **argv) +{ +l_int32 i, n, w, h, nactual, imax; +BOX *box; +BOXA *boxa; +PIX *pixs, *pixd, *pix; +PIXA *pixas, *pixa1, *pixa2, *pixac1, *pixac2; +L_PTRA *papix, *pabox, *papix2, *pabox2; +L_REGPARAMS *rp; + + if (regTestSetup(argc, argv, &rp)) + return 1; + + pixac1 = pixaCreate(0); + pixac2 = pixaCreate(0); + + pixs = pixRead("lucasta.1.300.tif"); + pixGetDimensions(pixs, &w, &h, NULL); + boxa = pixConnComp(pixs, &pixas, 8); + pixDestroy(&pixs); + boxaDestroy(&boxa); + n = pixaGetCount(pixas); + + /* Fill ptras with clones and reconstruct */ + if (rp->display) + lept_stderr("Fill with clones and reconstruct\n"); + MakePtrasFromPixa(pixas, &papix, &pabox, L_CLONE); + pixa1 = ReconstructPixa1(rp, papix, pabox); + ptraDestroy(&papix, 0, 1); + ptraDestroy(&pabox, 0, 1); + MakePtrasFromPixa(pixas, &papix, &pabox, L_CLONE); + pixa2 = ReconstructPixa2(rp, papix, pabox); + ptraDestroy(&papix, 0, 1); + ptraDestroy(&pabox, 0, 1); + pixd = SaveResult(pixac1, &pixa1, w, h, 1); + regTestWritePixAndCheck(rp, pixd, IFF_PNG); /* 0 */ + pixDestroy(&pixd); + pixd = SaveResult(pixac2, &pixa2, w, h, 1); + regTestWritePixAndCheck(rp, pixd, IFF_PNG); /* 1 */ + pixDestroy(&pixd); + + /* Remove every other one for the first half; + * with compaction at each removal */ + if (rp->display) + lept_stderr("Remove every other in 1st half, with compaction\n"); + MakePtrasFromPixa(pixas, &papix, &pabox, L_COPY); + for (i = 0; i < n / 2; i++) { + if (i % 2 == 0) { + pix = (PIX *)ptraRemove(papix, i, L_COMPACTION); + box = (BOX *)ptraRemove(pabox, i, L_COMPACTION); + pixDestroy(&pix); + boxDestroy(&box); + } + } + pixa1 = ReconstructPixa1(rp, papix, pabox); + ptraDestroy(&papix, 0, 1); + ptraDestroy(&pabox, 0, 1); + pixd = SaveResult(pixac1, &pixa1, w, h, 0); + regTestWritePixAndCheck(rp, pixd, IFF_PNG); /* 2 */ + pixDestroy(&pixd); + + MakePtrasFromPixa(pixas, &papix, &pabox, L_COPY); + for (i = 0; i < n / 2; i++) { + if (i % 2 == 0) { + pix = (PIX *)ptraRemove(papix, i, L_COMPACTION); + box = (BOX *)ptraRemove(pabox, i, L_COMPACTION); + pixDestroy(&pix); + boxDestroy(&box); + } + } + pixa2 = ReconstructPixa2(rp, papix, pabox); + ptraDestroy(&papix, 0, 1); + ptraDestroy(&pabox, 0, 1); + pixd = SaveResult(pixac2, &pixa2, w, h, 0); + regTestWritePixAndCheck(rp, pixd, IFF_PNG); /* 3 */ + pixDestroy(&pixd); + + /* Remove every other one for the entire set, + * but without compaction at each removal */ + if (rp->display) + lept_stderr("Remove every other in 1st half, " + "without & then with compaction\n"); + MakePtrasFromPixa(pixas, &papix, &pabox, L_COPY); + for (i = 0; i < n; i++) { + if (i % 2 == 0) { + pix = (PIX *)ptraRemove(papix, i, L_NO_COMPACTION); + box = (BOX *)ptraRemove(pabox, i, L_NO_COMPACTION); + pixDestroy(&pix); + boxDestroy(&box); + } + } + ptraCompactArray(papix); /* now do the compaction */ + ptraCompactArray(pabox); + pixa1 = ReconstructPixa1(rp, papix, pabox); + ptraDestroy(&papix, 0, 1); + ptraDestroy(&pabox, 0, 1); + pixd = SaveResult(pixac1, &pixa1, w, h, 0); + regTestWritePixAndCheck(rp, pixd, IFF_PNG); /* 4 */ + pixDestroy(&pixd); + + MakePtrasFromPixa(pixas, &papix, &pabox, L_COPY); + for (i = 0; i < n; i++) { + if (i % 2 == 0) { + pix = (PIX *)ptraRemove(papix, i, L_NO_COMPACTION); + box = (BOX *)ptraRemove(pabox, i, L_NO_COMPACTION); + pixDestroy(&pix); + boxDestroy(&box); + } + } + ptraCompactArray(papix); /* now do the compaction */ + ptraCompactArray(pabox); + pixa2 = ReconstructPixa2(rp, papix, pabox); + ptraDestroy(&papix, 0, 1); + ptraDestroy(&pabox, 0, 1); + pixd = SaveResult(pixac2, &pixa2, w, h, 0); + regTestWritePixAndCheck(rp, pixd, IFF_PNG); /* 5 */ + pixDestroy(&pixd); + + /* Fill ptras using insert at head, and reconstruct */ + if (rp->display) + lept_stderr("Insert at head and reconstruct\n"); + papix = ptraCreate(n); + pabox = ptraCreate(n); + for (i = 0; i < n; i++) { + pix = pixaGetPix(pixas, i, L_CLONE); + box = pixaGetBox(pixas, i, L_CLONE); + ptraInsert(papix, 0, pix, L_MIN_DOWNSHIFT); + ptraInsert(pabox, 0, box, L_FULL_DOWNSHIFT); + } + pixa1 = ReconstructPixa1(rp, papix, pabox); + ptraDestroy(&papix, 0, 1); + ptraDestroy(&pabox, 0, 1); + pixd = SaveResult(pixac1, &pixa1, w, h, 1); + regTestWritePixAndCheck(rp, pixd, IFF_PNG); /* 6 */ + pixDestroy(&pixd); + + papix = ptraCreate(n); + pabox = ptraCreate(n); + for (i = 0; i < n; i++) { + pix = pixaGetPix(pixas, i, L_CLONE); + box = pixaGetBox(pixas, i, L_CLONE); + ptraInsert(papix, 0, pix, L_MIN_DOWNSHIFT); + ptraInsert(pabox, 0, box, L_FULL_DOWNSHIFT); + } + pixa2 = ReconstructPixa2(rp, papix, pabox); + ptraDestroy(&papix, 0, 1); + ptraDestroy(&pabox, 0, 1); + pixd = SaveResult(pixac2, &pixa2, w, h, 1); + regTestWritePixAndCheck(rp, pixd, IFF_PNG); /* 7 */ + pixDestroy(&pixd); + + /* Reverse the arrays by swapping */ + if (rp->display) + lept_stderr("Reverse by swapping\n"); + MakePtrasFromPixa(pixas, &papix, &pabox, L_CLONE); + for (i = 0; i < n / 2; i++) { + ptraSwap(papix, i, n - i - 1); + ptraSwap(pabox, i, n - i - 1); + } + ptraCompactArray(papix); /* already compact; shouldn't do anything */ + ptraCompactArray(pabox); + pixa1 = ReconstructPixa1(rp, papix, pabox); + ptraDestroy(&papix, 0, 1); + ptraDestroy(&pabox, 0, 1); + pixd = SaveResult(pixac1, &pixa1, w, h, 0); + regTestWritePixAndCheck(rp, pixd, IFF_PNG); /* 8 */ + pixDestroy(&pixd); + + MakePtrasFromPixa(pixas, &papix, &pabox, L_CLONE); + for (i = 0; i < n / 2; i++) { + ptraSwap(papix, i, n - i - 1); + ptraSwap(pabox, i, n - i - 1); + } + ptraCompactArray(papix); /* already compact; shouldn't do anything */ + ptraCompactArray(pabox); + pixa2 = ReconstructPixa2(rp, papix, pabox); + ptraDestroy(&papix, 0, 1); + ptraDestroy(&pabox, 0, 1); + pixd = SaveResult(pixac2, &pixa2, w, h, 0); + regTestWritePixAndCheck(rp, pixd, IFF_PNG); /* 9 */ + pixDestroy(&pixd); + + /* Remove at the top of the array and push the hole to the end + * by neighbor swapping (!). This is O(n^2), so it's not a + * recommended way to copy a ptra. [joke] */ + if (rp->display) + lept_stderr( + "Remove at top, pushing hole to end by swapping -- O(n^2)\n"); + MakePtrasFromPixa(pixas, &papix, &pabox, L_CLONE); + papix2 = ptraCreate(0); + pabox2 = ptraCreate(0); + while (1) { + ptraGetActualCount(papix, &nactual); + if (nactual == 0) break; + ptraGetMaxIndex(papix, &imax); + pix = (PIX *)ptraRemove(papix, 0, L_NO_COMPACTION); + box = (BOX *)ptraRemove(pabox, 0, L_NO_COMPACTION); + ptraAdd(papix2, pix); + ptraAdd(pabox2, box); + for (i = 1; i <= imax; i++) { + ptraSwap(papix, i - 1, i); + ptraSwap(pabox, i - 1, i); + } + } + ptraCompactArray(papix); /* should be empty */ + ptraCompactArray(pabox); /* ditto */ + pixa1 = ReconstructPixa1(rp, papix, pabox); + ptraDestroy(&papix, 0, 1); + ptraDestroy(&pabox, 0, 1); + pixd = SaveResult(pixac1, &pixa1, w, h, 1); /* nothing there */ + regTestWritePixAndCheck(rp, pixd, IFF_PNG); /* 10 */ + pixDestroy(&pixd); + + pixa1 = ReconstructPixa1(rp, papix2, pabox2); + ptraDestroy(&papix2, 0, 1); + ptraDestroy(&pabox2, 0, 1); + pixd = SaveResult(pixac1, &pixa1, w, h, 0); + regTestWritePixAndCheck(rp, pixd, IFF_PNG); /* 11 */ + pixDestroy(&pixd); + + /* Remove and insert one position above, allowing minimum downshift. + * If you specify L_AUTO_DOWNSHIFT, because there is only 1 hole, + * it will do a full downshift at each insert. This is a + * situation where the heuristic (expected number of holes) + * fails to do the optimal thing. */ + if (rp->display) + lept_stderr("Remove and insert one position above (min downshift)\n"); + MakePtrasFromPixa(pixas, &papix, &pabox, L_CLONE); + for (i = 1; i < n; i++) { + pix = (PIX *)ptraRemove(papix, i, L_NO_COMPACTION); + box = (BOX *)ptraRemove(pabox, i, L_NO_COMPACTION); + ptraInsert(papix, i - 1, pix, L_MIN_DOWNSHIFT); + ptraInsert(pabox, i - 1, box, L_MIN_DOWNSHIFT); + } + pixa1 = ReconstructPixa1(rp, papix, pabox); + ptraDestroy(&papix, 0, 1); + ptraDestroy(&pabox, 0, 1); + pixd = SaveResult(pixac1, &pixa1, w, h, 1); + regTestWritePixAndCheck(rp, pixd, IFF_PNG); /* 12 */ + pixDestroy(&pixd); + + MakePtrasFromPixa(pixas, &papix, &pabox, L_CLONE); + for (i = 1; i < n; i++) { + pix = (PIX *)ptraRemove(papix, i, L_NO_COMPACTION); + box = (BOX *)ptraRemove(pabox, i, L_NO_COMPACTION); + ptraInsert(papix, i - 1, pix, L_MIN_DOWNSHIFT); + ptraInsert(pabox, i - 1, box, L_MIN_DOWNSHIFT); + } + pixa2 = ReconstructPixa2(rp, papix, pabox); + ptraDestroy(&papix, 0, 1); + ptraDestroy(&pabox, 0, 1); + pixd = SaveResult(pixac2, &pixa2, w, h, 1); + regTestWritePixAndCheck(rp, pixd, IFF_PNG); /* 13 */ + pixDestroy(&pixd); + + /* Remove and insert one position above, but this time + * forcing a full downshift at each step. */ + if (rp->display) + lept_stderr("Remove and insert one position above (full downshift)\n"); + MakePtrasFromPixa(pixas, &papix, &pabox, L_CLONE); + for (i = 1; i < n; i++) { + pix = (PIX *)ptraRemove(papix, i, L_NO_COMPACTION); + box = (BOX *)ptraRemove(pabox, i, L_NO_COMPACTION); + ptraInsert(papix, i - 1, pix, L_AUTO_DOWNSHIFT); + ptraInsert(pabox, i - 1, box, L_AUTO_DOWNSHIFT); + } + pixa1 = ReconstructPixa1(rp, papix, pabox); + ptraDestroy(&papix, 0, 1); + ptraDestroy(&pabox, 0, 1); + pixd = SaveResult(pixac1, &pixa1, w, h, 0); + regTestWritePixAndCheck(rp, pixd, IFF_PNG); /* 14 */ + pixDestroy(&pixd); + + MakePtrasFromPixa(pixas, &papix, &pabox, L_CLONE); + for (i = 1; i < n; i++) { + pix = (PIX *)ptraRemove(papix, i, L_NO_COMPACTION); + box = (BOX *)ptraRemove(pabox, i, L_NO_COMPACTION); + ptraInsert(papix, i - 1, pix, L_AUTO_DOWNSHIFT); + ptraInsert(pabox, i - 1, box, L_AUTO_DOWNSHIFT); + } + pixa2 = ReconstructPixa2(rp, papix, pabox); + ptraDestroy(&papix, 0, 1); + ptraDestroy(&pabox, 0, 1); + pixd = SaveResult(pixac2, &pixa2, w, h, 0); + regTestWritePixAndCheck(rp, pixd, IFF_PNG); /* 15 */ + pixDestroy(&pixd); + + pixd = pixaDisplayTiledInColumns(pixac1, 10, 0.5, 15, 2); + pixDisplayWithTitle(pixd, 0, 100, NULL, rp->display); + regTestWritePixAndCheck(rp, pixd, IFF_PNG); /* 16 */ + pixDestroy(&pixd); + pixd = pixaDisplayTiledInColumns(pixac2, 10, 0.5, 15, 2); + pixDisplayWithTitle(pixd, 800, 100, NULL, rp->display); + regTestWritePixAndCheck(rp, pixd, IFF_PNG); /* 17 */ + pixDestroy(&pixd); + pixaDestroy(&pixac1); + pixaDestroy(&pixac2); + pixaDestroy(&pixas); + + return regTestCleanup(rp); +} + + +static void +MakePtrasFromPixa(PIXA *pixa, + L_PTRA **ppapix, + L_PTRA **ppabox, + l_int32 copyflag) +{ +l_int32 i, n; +BOX *box; +PIX *pix; +L_PTRA *papix, *pabox; + + n = pixaGetCount(pixa); + papix = ptraCreate(n); + pabox = ptraCreate(n); + for (i = 0; i < n; i++) { + pix = pixaGetPix(pixa, i, copyflag); + box = pixaGetBox(pixa, i, copyflag); + ptraAdd(papix, pix); + ptraAdd(pabox, box); + } + + *ppapix = papix; + *ppabox = pabox; + return; +} + + + /* Reconstruction without compaction */ +static PIXA * +ReconstructPixa1(L_REGPARAMS *rp, + L_PTRA *papix, + L_PTRA *pabox) +{ +l_int32 i, imax, nactual; +BOX *box; +PIX *pix; +PIXA *pixat; + + ptraGetMaxIndex(papix, &imax); + ptraGetActualCount(papix, &nactual); + if (rp->display) + lept_stderr("Before removal: imax = %4d, actual = %4d\n", + imax, nactual); + + pixat = pixaCreate(imax + 1); + for (i = 0; i <= imax; i++) { + pix = (PIX *)ptraRemove(papix, i, L_NO_COMPACTION); + box = (BOX *)ptraRemove(pabox, i, L_NO_COMPACTION); + if (pix) pixaAddPix(pixat, pix, L_INSERT); + if (box) pixaAddBox(pixat, box, L_INSERT); + } + + ptraGetMaxIndex(papix, &imax); + ptraGetActualCount(papix, &nactual); + if (rp->display) + lept_stderr("After removal: imax = %4d, actual = %4d\n\n", + imax, nactual); + + return pixat; +} + + + /* Reconstruction with compaction */ +static PIXA * +ReconstructPixa2(L_REGPARAMS *rp, + L_PTRA *papix, + L_PTRA *pabox) +{ +l_int32 i, imax, nactual; +BOX *box; +PIX *pix; +PIXA *pixat; + + ptraGetMaxIndex(papix, &imax); + ptraGetActualCount(papix, &nactual); + if (rp->display) + lept_stderr("Before removal: imax = %4d, actual = %4d\n", + imax, nactual); + + /* Remove half */ + pixat = pixaCreate(imax + 1); + for (i = 0; i <= imax; i++) { + if (i % 2 == 0) { + pix = (PIX *)ptraRemove(papix, i, L_NO_COMPACTION); + box = (BOX *)ptraRemove(pabox, i, L_NO_COMPACTION); + if (pix) pixaAddPix(pixat, pix, L_INSERT); + if (box) pixaAddBox(pixat, box, L_INSERT); + } + } + + /* Compact */ + ptraGetMaxIndex(papix, &imax); + ptraGetActualCount(papix, &nactual); + if (rp->display) + lept_stderr("Before compaction: imax = %4d, actual = %4d\n", + imax, nactual); + ptraCompactArray(papix); + ptraCompactArray(pabox); + ptraGetMaxIndex(papix, &imax); + ptraGetActualCount(papix, &nactual); + if (rp->display) + lept_stderr("After compaction: imax = %4d, actual = %4d\n", + imax, nactual); + + /* Remove the rest (and test compaction with removal) */ + while (1) { + ptraGetActualCount(papix, &nactual); + if (nactual == 0) break; + + pix = (PIX *)ptraRemove(papix, 0, L_COMPACTION); + box = (BOX *)ptraRemove(pabox, 0, L_COMPACTION); + pixaAddPix(pixat, pix, L_INSERT); + pixaAddBox(pixat, box, L_INSERT); + } + + ptraGetMaxIndex(papix, &imax); + ptraGetActualCount(papix, &nactual); + if (rp->display) + lept_stderr("After removal: imax = %4d, actual = %4d\n\n", + imax, nactual); + + return pixat; +} + + +PIX * +SaveResult(PIXA *pixac, + PIXA **ppixa, + l_int32 w, + l_int32 h, + l_int32 newline) +{ +PIX *pixd; + + pixd = pixaDisplay(*ppixa, w, h); + pixaAddPix(pixac, pixd, L_COPY); + pixaDestroy(ppixa); + return pixd; +} diff --git a/leptonica/prog/ptra2_reg.c b/leptonica/prog/ptra2_reg.c new file mode 100644 index 00000000..e823265f --- /dev/null +++ b/leptonica/prog/ptra2_reg.c @@ -0,0 +1,266 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * ptra2_reg.c + * + * Testing: + * - basic ptra and ptraa operations + * - bin sort using ptra + * - boxaEqual() and pixaEqual() + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + +void BoxaSortTest(L_REGPARAMS *rp, const char *fname, l_int32 index, + const char *text); +void PixaSortTest(L_REGPARAMS *rp, const char *fname, l_int32 index, + const char *text); + +int main(int argc, + char **argv) +{ +L_REGPARAMS *rp; + +#if !defined(HAVE_LIBPNG) + L_ERROR("This test requires libpng to run.\n", "ptra2_reg"); + exit(77); +#endif + + if (regTestSetup(argc, argv, &rp)) + return 1; + + lept_mkdir("lept/ptra"); + + /* 0 - 8 */ + BoxaSortTest(rp, "feyn-fract.tif", 1, "Boxa sort test on small image"); + /* 9 - 17 */ + BoxaSortTest(rp, "feyn.tif", 2, "Boxa sort test on large image"); + /* 18 - 27 */ + PixaSortTest(rp, "feyn-fract.tif", 3, "Pixa sort test on small image"); + /* 28 - 37 */ + PixaSortTest(rp, "feyn.tif", 4, "Pixa sort test on large image"); + return regTestCleanup(rp); +} + + +void +BoxaSortTest(L_REGPARAMS *rp, + const char *fname, + l_int32 index, + const char *text) +{ +l_int32 i, n, m, imax, w, h, x, count, same; +BOX *box; +BOXA *boxa, *boxa1, *boxa2, *boxa3; +NUMA *na, *nad1, *nad2, *nad3, *naindex; +PIX *pixs; +L_PTRA *pa, *pad, *paindex; +L_PTRAA *paa; +char buf[256]; + + lept_stderr("Test %d: %s\n", index, text); + pixs = pixRead(fname); + boxa = pixConnComp(pixs, NULL, 8); + + /* Sort by x */ + boxa1 = boxaSort(boxa, L_SORT_BY_X, L_SORT_INCREASING, &nad1); + snprintf(buf, sizeof(buf), "/tmp/lept/ptra/boxa1.%d.ba", index); + boxaWrite(buf, boxa1); + regTestCheckFile(rp, buf); /* 0 */ + snprintf(buf, sizeof(buf), "/tmp/lept/ptra/nad1.%d.na", index); + numaWrite(buf, nad1); + regTestCheckFile(rp, buf); /* 1 */ + + boxa2 = boxaBinSort(boxa, L_SORT_BY_X, L_SORT_INCREASING, &nad2); + snprintf(buf, sizeof(buf), "/tmp/lept/ptra/boxa2.%d.ba", index); + boxaWrite(buf, boxa2); + regTestCheckFile(rp, buf); /* 2 */ + snprintf(buf, sizeof(buf), "/tmp/lept/ptra/nad2.%d.na", index); + numaWrite(buf, nad2); + regTestCheckFile(rp, buf); /* 3 */ + + boxaEqual(boxa1, boxa2, 0, NULL, &same); + regTestCompareValues(rp, 1, same, 0.0); /* 4 */ + if (rp->display && same) + lept_stderr("boxa1 and boxa2 are identical\n"); + boxaEqual(boxa1, boxa2, 2, &naindex, &same); + regTestCompareValues(rp, 1, same, 0.0); /* 5 */ + if (rp->display && same) + lept_stderr("boxa1 and boxa2 are same at maxdiff = 2\n"); + snprintf(buf, sizeof(buf), "/tmp/lept/ptra/naindex.%d.na", index); + numaWrite(buf, naindex); + regTestCheckFile(rp, buf); /* 6 */ + numaDestroy(&naindex); + boxaDestroy(&boxa1); + numaDestroy(&nad1); + numaDestroy(&nad2); + + /* Now do this stuff with ptra and ptraa */ + /* First, store the boxes in a ptraa, where each ptra contains + * the boxes, and store the sort index in a ptra of numa */ + pixGetDimensions(pixs, &w, &h, NULL); + paa = ptraaCreate(w); + paindex = ptraCreate(w); + n = boxaGetCount(boxa); + if (rp->display) lept_stderr("n = %d\n", n); + for (i = 0; i < n; i++) { + box = boxaGetBox(boxa, i, L_CLONE); + boxGetGeometry(box, &x, NULL, NULL, NULL); + pa = ptraaGetPtra(paa, x, L_HANDLE_ONLY); + na = (NUMA *)ptraGetPtrToItem(paindex, x); + if (!pa) { /* na also needs to be made */ + pa = ptraCreate(1); + ptraaInsertPtra(paa, x, pa); + na = numaCreate(1); + ptraInsert(paindex, x, na, L_MIN_DOWNSHIFT); + } + ptraAdd(pa, box); + numaAddNumber(na, i); + } + ptraGetActualCount(paindex, &count); + if (rp->display) lept_stderr("count = %d\n", count); + + /* Flatten the ptraa to a ptra containing all the boxes + * in sorted order, and put them in a boxa */ + pad = ptraaFlattenToPtra(paa); + ptraaDestroy(&paa, FALSE, FALSE); + ptraGetActualCount(pad, &m); + if (m != n) + lept_stderr("n(orig) = %d, m(new) = %d\n", n, m); + boxa3 = boxaCreate(m); + for (i = 0; i < m; i++) { + box = (BOX *)ptraRemove(pad, i, L_NO_COMPACTION); + boxaAddBox(boxa3, box, L_INSERT); + } + ptraDestroy(&pad, FALSE, FALSE); + + /* Extract the data from the ptra of Numa, putting it into + * a single Numa */ + ptraGetMaxIndex(paindex, &imax); + nad3 = numaCreate(0); + if (rp->display) lept_stderr("imax = %d\n\n", imax); + for (i = 0; i <= imax; i++) { + na = (NUMA *)ptraRemove(paindex, i, L_NO_COMPACTION); + numaJoin(nad3, na, 0, -1); + numaDestroy(&na); + } + + snprintf(buf, sizeof(buf), "/tmp/lept/ptra/boxa3.%d.ba", index); + boxaWrite(buf, boxa3); + regTestCheckFile(rp, buf); /* 7 */ + snprintf(buf, sizeof(buf), "/tmp/lept/ptra/nad3.%d.na", index); + numaWrite(buf, nad3); + regTestCheckFile(rp, buf); /* 8 */ + + boxaDestroy(&boxa2); + boxaDestroy(&boxa3); + numaDestroy(&nad3); + ptraDestroy(&paindex, FALSE, FALSE); + pixDestroy(&pixs); + boxaDestroy(&boxa); + return; +} + + +void +PixaSortTest(L_REGPARAMS *rp, + const char *fname, + l_int32 index, + const char *text) +{ +l_int32 same; +BOXA *boxa, *boxa1, *boxa2; +NUMA *nap1, *nap2, *naindex; +PIX *pixs; +PIXA *pixa, *pixa1, *pixa2; +char buf[256]; + + lept_stderr("Test %d: %s\n", index, text); + pixs = pixRead(fname); + boxa = pixConnComp(pixs, &pixa, 8); + + pixa1 = pixaSort(pixa, L_SORT_BY_X, L_SORT_INCREASING, &nap1, L_CLONE); + boxa1 = pixaGetBoxa(pixa1, L_CLONE); + snprintf(buf, sizeof(buf), "/tmp/lept/ptra/bap1.%d.ba", index); + boxaWrite(buf, boxa1); + regTestCheckFile(rp, buf); /* 0 */ + snprintf(buf, sizeof(buf), "/tmp/lept/ptra/nap1.%d.na", index); + numaWrite(buf, nap1); + regTestCheckFile(rp, buf); /* 1 */ + snprintf(buf, sizeof(buf), "/tmp/lept/ptra/pixa1.%d.pa", index); + pixaWrite(buf, pixa1); + regTestCheckFile(rp, buf); /* 2 */ + + pixa2 = pixaBinSort(pixa, L_SORT_BY_X, L_SORT_INCREASING, &nap2, L_CLONE); + boxa2 = pixaGetBoxa(pixa2, L_CLONE); + snprintf(buf, sizeof(buf), "/tmp/lept/ptra/bap2.%d.ba", index); + boxaWrite(buf, boxa2); + regTestCheckFile(rp, buf); /* 3 */ + snprintf(buf, sizeof(buf), "/tmp/lept/ptra/nap2.%d.na", index); + numaWrite(buf, nap2); + regTestCheckFile(rp, buf); /* 4 */ + snprintf(buf, sizeof(buf), "/tmp/lept/ptra/pixa2.%d.pa", index); + pixaWrite(buf, pixa2); + regTestCheckFile(rp, buf); /* 5 */ + + boxaEqual(boxa1, boxa2, 0, &naindex, &same); + regTestCompareValues(rp, 1, same, 0.0); /* 6 */ + if (rp->display && same) + lept_stderr("boxa1 and boxa2 are identical\n"); + numaDestroy(&naindex); + boxaEqual(boxa1, boxa2, 3, &naindex, &same); + regTestCompareValues(rp, 1, same, 0.0); /* 7 */ + if (rp->display && same) + lept_stderr("boxa1 and boxa2 are same at maxdiff = 2\n"); + numaDestroy(&naindex); + + pixaEqual(pixa1, pixa2, 0, &naindex, &same); + regTestCompareValues(rp, 1, same, 0.0); /* 8 */ + if (rp->display && same) + lept_stderr("pixa1 and pixa2 are identical\n"); + numaDestroy(&naindex); + pixaEqual(pixa1, pixa2, 3, &naindex, &same); + regTestCompareValues(rp, 1, same, 0.0); /* 9 */ + if (rp->display && same) + lept_stderr("pixa1 and pixa2 are same at maxdiff = 2\n\n"); + numaDestroy(&naindex); + + boxaDestroy(&boxa); + boxaDestroy(&boxa1); + boxaDestroy(&boxa2); + numaDestroy(&nap1); + numaDestroy(&nap2); + pixaDestroy(&pixa); + pixaDestroy(&pixa1); + pixaDestroy(&pixa2); + pixDestroy(&pixs); + return; +} diff --git a/leptonica/prog/quadtree_reg.c b/leptonica/prog/quadtree_reg.c new file mode 100644 index 00000000..e5ef57f5 --- /dev/null +++ b/leptonica/prog/quadtree_reg.c @@ -0,0 +1,141 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * quadtreetest.c + * + * This tests quadtree statistical functions + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + +int main(int argc, + char **argv) +{ +l_uint8 *data; +l_int32 i, j, w, h, error; +l_float32 val1, val2; +l_float32 val00, val10, val01, val11, valc00, valc10, valc01, valc11; +size_t size; +PIX *pixs, *pixg, *pix1, *pix2, *pix3, *pix4, *pix5; +FPIXA *fpixam, *fpixav, *fpixarv; +BOXAA *baa; +L_REGPARAMS *rp; + +#if !defined(HAVE_LIBPNG) + L_ERROR("This test requires libpng to run.\n", "quadtree_reg"); + exit(77); +#endif + + if (regTestSetup(argc, argv, &rp)) + return 1; + + lept_mkdir("lept/quad"); + + /* Test generation of quadtree regions. */ + baa = boxaaQuadtreeRegions(1000, 500, 3); + boxaaWriteMem(&data, &size, baa); + regTestWriteDataAndCheck(rp, data, size, "baa"); /* 0 */ + if (rp->display) boxaaWriteStream(stderr, baa); + boxaaDestroy(&baa); + lept_free(data); + baa = boxaaQuadtreeRegions(1001, 501, 3); + boxaaWriteMem(&data, &size, baa); + regTestWriteDataAndCheck(rp, data, size, "baa"); /* 1 */ + boxaaDestroy(&baa); + lept_free(data); + + /* Test quadtree stats generation */ + pixs = pixRead("rabi.png"); + pixg = pixScaleToGray4(pixs); + pixDestroy(&pixs); + pixQuadtreeMean(pixg, 8, NULL, &fpixam); + pix1 = fpixaDisplayQuadtree(fpixam, 2, 10); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 2 */ + pixDisplayWithTitle(pix1, 100, 0, NULL, rp->display); + pixQuadtreeVariance(pixg, 8, NULL, NULL, &fpixav, &fpixarv); + pix2 = fpixaDisplayQuadtree(fpixav, 2, 10); + regTestWritePixAndCheck(rp, pix2, IFF_PNG); /* 3 */ + pixDisplayWithTitle(pix2, 100, 200, NULL, rp->display); + pix3 = fpixaDisplayQuadtree(fpixarv, 2, 10); + regTestWritePixAndCheck(rp, pix3, IFF_PNG); /* 4 */ + pixDisplayWithTitle(pix3, 100, 400, NULL, rp->display); + pixDestroy(&pix1); + pixDestroy(&pix2); + pixDestroy(&pix3); + fpixaDestroy(&fpixav); + fpixaDestroy(&fpixarv); + + /* Compare with fixed-size tiling at a resolution corresponding + * to the deepest level of the quadtree above */ + pix4 = pixGetAverageTiled(pixg, 5, 6, L_MEAN_ABSVAL); + pix5 = pixExpandReplicate(pix4, 4); + regTestWritePixAndCheck(rp, pix5, IFF_PNG); /* 5 */ + pixDisplayWithTitle(pix5, 800, 0, NULL, rp->display); + pixDestroy(&pix4); + pixDestroy(&pix5); + pix4 = pixGetAverageTiled(pixg, 5, 6, L_STANDARD_DEVIATION); + pix5 = pixExpandReplicate(pix4, 4); + regTestWritePixAndCheck(rp, pix5, IFF_PNG); /* 6 */ + pixDisplayWithTitle(pix5, 800, 400, NULL, rp->display); + pixDestroy(&pix4); + pixDestroy(&pix5); + pixDestroy(&pixg); + + /* Test quadtree parent/child access */ + error = FALSE; + fpixaGetFPixDimensions(fpixam, 4, &w, &h); + for (i = 0; i < w; i += 2) { + for (j = 0; j < h; j += 2) { + quadtreeGetParent(fpixam, 4, j, i, &val1); + fpixaGetPixel(fpixam, 3, j / 2, i / 2, &val2); + if (val1 != val2) error = TRUE; + } + } + regTestCompareValues(rp, 0, error, 0.0); /* 7 */ + error = FALSE; + for (i = 0; i < w; i++) { + for (j = 0; j < h; j++) { + quadtreeGetChildren(fpixam, 4, j, i, + &val00, &val10, &val01, &val11); + fpixaGetPixel(fpixam, 5, 2 * j, 2 * i, &valc00); + fpixaGetPixel(fpixam, 5, 2 * j + 1, 2 * i, &valc10); + fpixaGetPixel(fpixam, 5, 2 * j, 2 * i + 1, &valc01); + fpixaGetPixel(fpixam, 5, 2 * j + 1, 2 * i + 1, &valc11); + if ((val00 != valc00) || (val10 != valc10) || + (val01 != valc01) || (val11 != valc11)) + error = TRUE; + } + } + regTestCompareValues(rp, 0, error, 0.0); /* 8 */ + fpixaDestroy(&fpixam); + + return regTestCleanup(rp); +} diff --git a/leptonica/prog/rabi-tiny.png b/leptonica/prog/rabi-tiny.png Binary files differnew file mode 100644 index 00000000..faf2b35d --- /dev/null +++ b/leptonica/prog/rabi-tiny.png diff --git a/leptonica/prog/rabi.png b/leptonica/prog/rabi.png Binary files differnew file mode 100644 index 00000000..b4e41a10 --- /dev/null +++ b/leptonica/prog/rabi.png diff --git a/leptonica/prog/raggededge.png b/leptonica/prog/raggededge.png Binary files differnew file mode 100644 index 00000000..d4c134fa --- /dev/null +++ b/leptonica/prog/raggededge.png diff --git a/leptonica/prog/rank_reg.c b/leptonica/prog/rank_reg.c new file mode 100644 index 00000000..ca0b4d80 --- /dev/null +++ b/leptonica/prog/rank_reg.c @@ -0,0 +1,226 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * rank_reg.c + * + * Tests grayscale and color rank functions: + * (1) pixRankFilterGray() + * (1) pixRankFilterRGB() + * (2) pixScaleGrayMinMax() + * (3) pixScaleGrayRank2() + * (3) pixScaleGrayRankCascade() + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + +int main(int argc, + char **argv) +{ +l_int32 i, j, w, h; +l_float32 t1, t2; +BOX *box; +GPLOT *gplot; +NUMA *nax, *nay1, *nay2; +PIX *pixs, *pix0, *pix1, *pix2, *pix3, *pix4; +PIXA *pixa; +L_REGPARAMS *rp; + +#if !defined(HAVE_LIBPNG) + L_ERROR("This test requires libpng to run.\n", "rank_reg"); + exit(77); +#endif + + if (regTestSetup(argc, argv, &rp)) + return 1; + + lept_mkdir("lept/rank"); + + pixs = pixRead("lucasta.150.jpg"); + pixGetDimensions(pixs, &w, &h, NULL); + + startTimer(); + pix1 = pixRankFilterGray(pixs, 15, 15, 0.4); + t1 = stopTimer(); + lept_stderr("pixRankFilterGray: %7.3f MPix/sec\n", 0.000001 * w * h / t1); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 0 */ + pixDisplayWithTitle(pixs, 0, 0, NULL, rp->display); + pixDisplayWithTitle(pix1, 600, 0, NULL, rp->display); + pixDestroy(&pix1); + + /* ---------- Compare grayscale morph with rank operator ---------- */ + /* Get results for dilation */ + startTimer(); + pix1 = pixDilateGray(pixs, 15, 15); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 1 */ + t2 = stopTimer(); + lept_stderr("Rank filter time = %7.3f, Dilation time = %7.3f sec\n", + t1, t2); + + /* Get results for erosion */ + pix2 = pixErodeGray(pixs, 15, 15); + regTestWritePixAndCheck(rp, pix2, IFF_PNG); /* 2 */ + + /* Get results using the rank filter for rank = 0.0 and 1.0. + * Don't use 0.0 or 1.0, because those are dispatched + * automatically to erosion and dilation! */ + pix3 = pixRankFilterGray(pixs, 15, 15, 0.0001); + pix4 = pixRankFilterGray(pixs, 15, 15, 0.9999); + regTestComparePix(rp, pix1, pix4); /* 3 */ + regTestComparePix(rp, pix2, pix3); /* 4 */ + pixDestroy(&pix1); + pixDestroy(&pix2); + pixDestroy(&pix3); + pixDestroy(&pix4); + + /* ------------- Timing and filter size experiments --------- */ + box = boxCreate(20, 200, 500, 125); + pix0 = pixClipRectangle(pixs, box, NULL); + boxDestroy(&box); + nax = numaMakeSequence(1, 1, 20); + nay1 = numaCreate(20); + nay2 = numaCreate(20); + gplot = gplotCreate("/tmp/lept/rank/plots", GPLOT_PNG, + "sec/MPix vs filter size", "size", "time"); + pixa = pixaCreate(20); + for (i = 1; i <= 20; i++) { + t1 = t2 = 0.0; + for (j = 0; j < 5; j++) { + startTimer(); + pix1 = pixRankFilterGray(pix0, i, 20 + 1, 0.5); + t1 += stopTimer(); + pixDestroy(&pix1); + startTimer(); + pix1 = pixRankFilterGray(pix0, 20 + 1, i, 0.5); + t2 += stopTimer(); + if (j == 0) + pixaAddPix(pixa, pix1, L_CLONE); + pixDestroy(&pix1); + } + numaAddNumber(nay1, 1000000. * t1 / (5. * w * h)); + numaAddNumber(nay2, 1000000. * t2 / (5. * w * h)); + } + gplotAddPlot(gplot, nax, nay1, GPLOT_LINES, "vertical"); + gplotAddPlot(gplot, nax, nay2, GPLOT_LINES, "horizontal"); + gplotMakeOutput(gplot); + gplotDestroy(&gplot); + pix1 = pixRead("/tmp/lept/rank/plots.png"); + pixDisplayWithTitle(pix1, 100, 100, NULL, rp->display); + pixDestroy(&pix1); + pixDestroy(&pix0); + numaDestroy(&nax); + numaDestroy(&nay1); + numaDestroy(&nay2); + + /* Display tiled */ + pix1 = pixaDisplayTiledAndScaled(pixa, 8, 250, 5, 0, 25, 2); + pixDisplayWithTitle(pix1, 100, 600, NULL, rp->display); + pixDestroy(&pix1); + pixaDestroy(&pixa); + pixDestroy(&pixs); + + /* ------------------ Gray tests ------------------ */ + pixs = pixRead("test8.jpg"); + pixa = pixaCreate(4); + for (i = 1; i <= 4; i++) { + pix1 = pixScaleGrayRank2(pixs, i); + pixaAddPix(pixa, pix1, L_INSERT); + } + pix1 = pixaDisplayTiledInRows(pixa, 8, 1500, 1.0, 0, 20, 2); + regTestWritePixAndCheck(rp, pix1, IFF_JFIF_JPEG); /* 5 */ + pixDisplayWithTitle(pix1, 100, 100, NULL, rp->display); + pixDestroy(&pixs); + pixDestroy(&pix1); + pixaDestroy(&pixa); + + pixs = pixRead("test24.jpg"); + pix1 = pixConvertRGBToLuminance(pixs); + pix2 = pixScale(pix1, 1.5, 1.5); + pixa = pixaCreate(5); + for (i = 1; i <= 4; i++) { + for (j = 1; j <= 4; j++) { + pix3 = pixScaleGrayRankCascade(pix2, i, j, 0, 0); + pixaAddPix(pixa, pix3, L_INSERT); + } + } + pix4 = pixaDisplayTiledInRows(pixa, 8, 1500, 0.7, 0, 20, 2); + regTestWritePixAndCheck(rp, pix4, IFF_JFIF_JPEG); /* 6 */ + pixDisplayWithTitle(pix4, 100, 700, NULL, rp->display); + pixDestroy(&pixs); + pixDestroy(&pix1); + pixDestroy(&pix2); + pixDestroy(&pix4); + pixaDestroy(&pixa); + + /* ---------- Compare color morph with rank operator ---------- */ + pixs = pixRead("wyom.jpg"); + box = boxCreate(400, 220, 300, 250); + pix0 = pixClipRectangle(pixs, box, NULL); + boxDestroy(&box); + pix1 = pixColorMorph(pix0, L_MORPH_DILATE, 11, 11); + pix2 = pixColorMorph(pix0, L_MORPH_ERODE, 11, 11); + regTestWritePixAndCheck(rp, pix1, IFF_JFIF_JPEG); /* 7 */ + regTestWritePixAndCheck(rp, pix2, IFF_JFIF_JPEG); /* 8 */ + + /* Get results using the rank filter for rank = 0.0 and 1.0. + * Don't use 0.0 or 1.0, because those are dispatched + * automatically to erosion and dilation! */ + pix3 = pixRankFilter(pix0, 11, 11, 0.0001); + pix4 = pixRankFilter(pix0, 11, 11, 0.9999); + regTestComparePix(rp, pix1, pix4); /* 9 */ + regTestComparePix(rp, pix2, pix3); /* 10 */ + pixDestroy(&pixs); + pixDestroy(&pix1); + pixDestroy(&pix2); + pixDestroy(&pix3); + pixDestroy(&pix4); + + /* Show color results for different rank values */ + if (rp->display) { + pixa = pixaCreate(10); + pix1 = pixColorMorph(pix0, L_MORPH_ERODE, 13, 13); + pixaAddPix(pixa, pix1, L_INSERT); + for (i = 0; i <= 10; i++) { + pix1 = pixRankFilter(pix0, 13, 13, 0.1 * i); + pixaAddPix(pixa, pix1, L_INSERT); + } + pix1 = pixColorMorph(pix0, L_MORPH_DILATE, 13, 13); + pixaAddPix(pixa, pix1, L_INSERT); + pix1 = pixaDisplayTiledAndScaled(pixa, 32, 400, 3, 0, 25, 2); + pixDisplayWithTitle(pix1, 500, 0, NULL, 1); + pixaDestroy(&pixa); + pixDestroy(&pix1); + } + pixDestroy(&pix0); + + return regTestCleanup(rp); +} + + diff --git a/leptonica/prog/rankbin_reg.c b/leptonica/prog/rankbin_reg.c new file mode 100644 index 00000000..4f02956c --- /dev/null +++ b/leptonica/prog/rankbin_reg.c @@ -0,0 +1,204 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * rankbin_reg.c + * + * Tests rank bin functions: + * (1) numaDiscretizeInBins() + * (2) numaGetRankBinValues() + * (3) pixRankBinByStrip() + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + +int main(int argc, + char **argv) +{ +l_int32 i, n, w, h, nbins; +l_uint8 *data; +l_uint32 *carray; +size_t nbytes; +BOXA *boxa1, *boxa2, *boxa3; +NUMA *naindex, *na1, *na2, *na3, *na4; +PIX *pixs, *pix1, *pix2, *pix3; +PIXA *pixa; +L_REGPARAMS *rp; + +#if !defined(HAVE_LIBPNG) + L_ERROR("This test requires libpng to run.\n", "rankbin_reg"); + exit(77); +#endif + + if (regTestSetup(argc, argv, &rp)) + return 1; + + /* Generate arrays of word widths and heights */ + pixs = pixRead("feyn.tif"); + pix1 = pixReduceRankBinaryCascade(pixs, 1, 0, 0, 0); + pixGetWordBoxesInTextlines(pix1, 6, 6, 500, 50, &boxa1, &naindex); + n = boxaGetCount(boxa1); + na1 = numaCreate(0); + na2 = numaCreate(0); + for (i = 0; i < n; i++) { + boxaGetBoxGeometry(boxa1, i, NULL, NULL, &w, &h); + numaAddNumber(na1, w); + numaAddNumber(na2, h); + } + boxaDestroy(&boxa1); + numaDestroy(&naindex); + pixDestroy(&pix1); + + /* Make the rank bin arrays of average values, with 10 bins */ + pixa = pixaCreate(0); + numaGetRankBinValues(na1, 10, &na3); + numaGetRankBinValues(na2, 10, &na4); + pix1 = gplotSimplePix1(na3, "width vs rank bins (10)"); + pix2 = gplotSimplePix1(na4, "height vs rank bins (10)"); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 0 */ + regTestWritePixAndCheck(rp, pix2, IFF_PNG); /* 1 */ + numaDestroy(&na3); + numaDestroy(&na4); + pixaAddPix(pixa, pix1, L_INSERT); + pixaAddPix(pixa, pix2, L_INSERT); + + /* Make the rank bin arrays of average values, with 30 bins */ + numaGetRankBinValues(na1, 30, &na3); + numaGetRankBinValues(na2, 30, &na4); + pix1 = gplotSimplePix1(na3, "width vs rank bins (30)"); + pix2 = gplotSimplePix1(na4, "height vs rank bins (30)"); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 2 */ + regTestWritePixAndCheck(rp, pix2, IFF_PNG); /* 3 */ + numaDestroy(&na3); + numaDestroy(&na4); + pixaAddPix(pixa, pix1, L_INSERT); + pixaAddPix(pixa, pix2, L_INSERT); + + /* Display results for debugging */ + if (rp->display) { + pix3 = pixaDisplayTiledInColumns(pixa, 2, 1.0, 25, 0); + pixDisplayWithTitle(pix3, 0, 0, NULL, 1); + pixDestroy(&pix3); + } + pixaDestroy(&pixa); + pixDestroy(&pixs); + numaDestroy(&na1); + numaDestroy(&na2); + + /* Test pixRankBinByStrip */ + pix1 = pixRead("pancrazi.15.jpg"); + pixa = pixaCreate(3); + pix2 = pixRankBinByStrip(pix1, L_SCAN_HORIZONTAL, 16, 10, L_SELECT_HUE); + pix3 = pixExpandReplicate(pix2, 20); + pixaAddPix(pixa, pix3, L_INSERT); + pixDestroy(&pix2); + pix2 = pixRankBinByStrip(pix1, L_SCAN_HORIZONTAL, 16, 10, + L_SELECT_SATURATION); + pix3 = pixExpandReplicate(pix2, 20); + pixaAddPix(pixa, pix3, L_INSERT); + pixDestroy(&pix2); + pix2 = pixRankBinByStrip(pix1, L_SCAN_HORIZONTAL, 16, 10, L_SELECT_RED); + pix3 = pixExpandReplicate(pix2, 20); + pixaAddPix(pixa, pix3, L_INSERT); + pixDestroy(&pix2); + pix2 = pixaDisplayTiledInRows(pixa, 32, 800, 1.0, 0, 30, 2); + regTestWritePixAndCheck(rp, pix2, IFF_PNG); /* 4 */ + pixDisplayWithTitle(pix2, 100, 100, NULL, rp->display); + pixDestroy(&pix1); + pixDestroy(&pix2); + pixaDestroy(&pixa); + + /* Test numaGetRankBinValues() and numaDiscretize functions */ + boxa1 = boxaRead("boxa4.ba"); + boxaSplitEvenOdd(boxa1, 0, &boxa2, &boxa3); + boxaGetSizes(boxa2, &na1, NULL); /* 26 elements */ + numaWriteMem(&data, &nbytes, na1); + regTestWriteDataAndCheck(rp, data, nbytes, ".na"); /* 5 */ + lept_free(data); + n = numaGetCount(na1); + nbins = L_MAX(5, n / 50); + numaGetRankBinValues(na1, nbins, &na2); + numaWriteMem(&data, &nbytes, na2); + regTestWriteDataAndCheck(rp, data, nbytes, ".na"); /* 6 */ + lept_free(data); + numaDestroy(&na2); + boxaDestroy(&boxa1); + boxaDestroy(&boxa2); + boxaDestroy(&boxa3); + + na3 = numaSort(NULL, na1, L_SORT_INCREASING); + numaDiscretizeSortedInBins(na3, nbins, &na4); + numaWriteMem(&data, &nbytes, na4); + regTestWriteDataAndCheck(rp, data, nbytes, ".na"); /* 7 */ + lept_free(data); + numaDestroy(&na3); + numaDestroy(&na4); + + na3 = numaMakeHistogram(na1, 100000, NULL, NULL); + numaDiscretizeHistoInBins(na3, nbins, &na4, NULL); + numaWriteMem(&data, &nbytes, na4); + regTestWriteDataAndCheck(rp, data, nbytes, ".na"); /* 8 */ + lept_free(data); + regTestCompareFiles(rp, 6, 7); /* 9 */ + regTestCompareFiles(rp, 6, 8); /* 10 */ + numaDestroy(&na1); + numaDestroy(&na3); + numaDestroy(&na4); + + pixa = pixaCreate(4); + pix1 = pixRead("karen8.jpg"); + na1 = pixGetGrayHistogram(pix1, 1); + numaDiscretizeHistoInBins(na1, 1000, &na2, &na3); + pix2 = gplotSimplePix1(na3, "rank vs gray"); + pix3 = gplotSimplePix1(na2, "gray vs rank-binval"); + regTestWritePixAndCheck(rp, pix2, IFF_PNG); /* 11 */ + regTestWritePixAndCheck(rp, pix3, IFF_PNG); /* 12 */ + pixaAddPix(pixa, pix2, L_INSERT); + pixaAddPix(pixa, pix3, L_INSERT); + pixDestroy(&pix1); + numaDestroy(&na1); + numaDestroy(&na2); + numaDestroy(&na3); + + pix1 = pixRead("wyom.jpg"); + pixGetRankColorArray(pix1, 20, L_SELECT_RED, 5, + &carray, NULL, 0); + pix2 = pixDisplayColorArray(carray, 20, 200, 5, 6); + regTestWritePixAndCheck(rp, pix2, IFF_PNG); /* 13 */ + pixaAddPix(pixa, pix1, L_INSERT); + pixaAddPix(pixa, pix2, L_INSERT); + pix3 = pixaDisplayTiledInColumns(pixa, 2, 1.0, 30, 2); + pixDisplayWithTitle(pix3, 800, 20, NULL, rp->display); + pixDestroy(&pix3); + pixaDestroy(&pixa); + lept_free(carray); + + return regTestCleanup(rp); +} diff --git a/leptonica/prog/rankhisto_reg.c b/leptonica/prog/rankhisto_reg.c new file mode 100644 index 00000000..58a031c8 --- /dev/null +++ b/leptonica/prog/rankhisto_reg.c @@ -0,0 +1,135 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * rankhisto_reg.c + * + * Tests grayscale rank functions: + * (1) pixGetRankColorArray() + * (2) numaDiscretizeHistoInBins() + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include <math.h> +#include "allheaders.h" + +int main(int argc, + char **argv) +{ +l_int32 i, w, h, nbins, factor; +l_int32 spike; +l_uint32 *array, *marray; +NUMA *na, *nabinval, *narank; +PIX *pixs, *pix1, *pix2; +PIXA *pixa; +L_REGPARAMS *rp; + +#if !defined(HAVE_LIBPNG) + L_ERROR("This test requires libpng to run.\n", "rankhisto_reg"); + exit(77); +#endif + + if (regTestSetup(argc, argv, &rp)) + return 1; + + /* Find the rank bin colors */ + pixs = pixRead("map1.jpg"); + pixGetDimensions(pixs, &w, &h, NULL); + factor = L_MAX(1, (l_int32)sqrt((l_float64)(w * h / 20000.0))); + nbins = 10; + pixa = pixaCreate(0); + pixGetRankColorArray(pixs, nbins, L_SELECT_MIN, factor, &array, pixa, 6); + if (!array) + return ERROR_INT("\n\n\nFAILURE!\n\n\n", rp->testname, 1); + pix1 = pixaDisplayTiledInColumns(pixa, 3, 1.0, 20, 0); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 0 */ + pixDisplayWithTitle(pix1, 1000, 100, NULL, rp->display); + pixaDestroy(&pixa); + pixDestroy(&pix1); + for (i = 0; i < nbins; i++) + lept_stderr("%d: %x\n", i, array[i]); + pix1 = pixDisplayColorArray(array, nbins, 200, 5, 6); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 1 */ + pixDisplayWithTitle(pix1, 0, 100, NULL, rp->display); + pixDestroy(&pix1); + + /* Modify the rank bin colors by mapping them such + * that the lightest color is mapped to white */ + marray = (l_uint32 *)lept_calloc(nbins, sizeof(l_uint32)); + for (i = 0; i < nbins; i++) + pixelLinearMapToTargetColor(array[i], array[nbins - 1], + 0xffffff00, &marray[i]); + pix1 = pixDisplayColorArray(marray, nbins, 200, 5, 6); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 2 */ + pixDisplayWithTitle(pix1, 0, 600, NULL, rp->display); + pixDestroy(&pix1); + lept_free(marray); + + /* Map to the lightest bin; then do TRC adjustment */ + pix1 = pixLinearMapToTargetColor(NULL, pixs, array[nbins - 1], 0xffffff00); + pix2 = pixGammaTRC(NULL, pix1, 1.0, 0, 240); + regTestWritePixAndCheck(rp, pix2, IFF_PNG); /* 3 */ + pixDisplayWithTitle(pix2, 1000, 100, NULL, rp->display); + pixDestroy(&pix1); + pixDestroy(&pix2); + + /* Now test the edge case where all the histo data is piled up + * at one place. We only require that the result be sensible. */ + pixa = pixaCreate(0); + for (i = 0; i < 3; i++) { + if (i == 0) + spike = 1; + else if (i == 1) + spike = 50; + else + spike = 99; + na = numaMakeConstant(0, 100); + numaReplaceNumber(na, spike, 200.0); + numaDiscretizeHistoInBins(na, 10, &nabinval, &narank); + pix1 = gplotSimplePix1(na, "Histogram"); + pixaAddPix(pixa, pix1, L_INSERT); + pix1 = gplotSimplePix1(nabinval, "Gray value vs rank bin"); + pixaAddPix(pixa, pix1, L_INSERT); + pix1 = gplotSimplePix1(narank, "rank value vs. gray value"); + pixaAddPix(pixa, pix1, L_INSERT); + numaDestroy(&na); + numaDestroy(&nabinval); + numaDestroy(&narank); + } + pix1 = pixaDisplayTiledInColumns(pixa, 3, 1.0, 20, 0); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 4 */ + pixDisplayWithTitle(pix1, 1000, 800, NULL, rp->display); + pixaDestroy(&pixa); + pixDestroy(&pix1); + + pixDestroy(&pixs); + lept_free(array); + return regTestCleanup(rp); +} + diff --git a/leptonica/prog/rasterop_reg.c b/leptonica/prog/rasterop_reg.c new file mode 100644 index 00000000..e52a09b3 --- /dev/null +++ b/leptonica/prog/rasterop_reg.c @@ -0,0 +1,103 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * rasterop_reg.c + * + * This is a fairly rigorous test of rasterop. + * It demonstrates both that the results are correct + * with many different rop configurations, and, + * if done under valgrind, that no memory violations occur. + * We use it on an image with FG extending to the edges. + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + +int main(int argc, + char **argv) +{ +l_int32 i, j, w, h, same, width, height, cx, cy; +l_uint32 val; +BOX *box; +PIX *pix0, *pixs, *pixse, *pixd1, *pixd2; +SEL *sel; +L_REGPARAMS *rp; + + if (regTestSetup(argc, argv, &rp)) + return 1; + + pix0 = pixRead("feyn-fract.tif"); + box = boxCreate(293, 37, pixGetWidth(pix0) - 691, pixGetHeight(pix0) -145); + pixs = pixClipRectangle(pix0, box, NULL); + boxDestroy(&box); + if (rp->display) pixDisplay(pixs, 100, 100); + + /* Test 63 different sizes */ + for (width = 1; width <= 25; width += 3) { /* 9 values */ + for (height = 1; height <= 25; height += 4) { /* 7 values */ + + cx = width / 2; + cy = height / 2; + + /* Dilate using an actual sel */ + sel = selCreateBrick(height, width, cy, cx, SEL_HIT); + pixd1 = pixDilate(NULL, pixs, sel); + + /* Dilate using a pix as a sel */ + pixse = pixCreate(width, height, 1); + pixSetAll(pixse); + pixd2 = pixCopy(NULL, pixs); + w = pixGetWidth(pixs); + h = pixGetHeight(pixs); + for (i = 0; i < h; i++) { + for (j = 0; j < w; j++) { + pixGetPixel(pixs, j, i, &val); + if (val) + pixRasterop(pixd2, j - cx, i - cy, width, height, + PIX_SRC | PIX_DST, pixse, 0, 0); + } + } + + pixEqual(pixd1, pixd2, &same); + regTestCompareValues(rp, 1, same, 0.0); /* 0 - 62 */ + if (same == 0) + lept_stderr("Results differ for SE (width,height) = (%d,%d)\n", + width, height); + + pixDestroy(&pixse); + pixDestroy(&pixd1); + pixDestroy(&pixd2); + selDestroy(&sel); + } + } + pixDestroy(&pix0); + pixDestroy(&pixs); + return regTestCleanup(rp); +} diff --git a/leptonica/prog/rasteropip_reg.c b/leptonica/prog/rasteropip_reg.c new file mode 100644 index 00000000..d46c9480 --- /dev/null +++ b/leptonica/prog/rasteropip_reg.c @@ -0,0 +1,81 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * rasteropip_reg.c + * + * Tests in-place operation using the general 2-image pixRasterop(). + * The in-place operation works because there is no overlap + * between the src and dest rectangles. + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + +int main(int argc, + char **argv) +{ +l_int32 i, j; +PIX *pixs, *pixt, *pixd; +L_REGPARAMS *rp; + + if (regTestSetup(argc, argv, &rp)) + return 1; + + pixs = pixRead("test8.jpg"); + pixt = pixCopy(NULL, pixs); + + /* Copy, in-place and one COLUMN at a time, from the right + side to the left side. */ + for (j = 0; j < 200; j++) + pixRasterop(pixs, 20 + j, 20, 1, 250, PIX_SRC, pixs, 250 + j, 20); + pixDisplayWithTitle(pixs, 50, 50, "in-place copy", rp->display); + + /* Copy, in-place and one ROW at a time, from the right + side to the left side. */ + for (i = 0; i < 250; i++) + pixRasterop(pixt, 20, 20 + i, 200, 1, PIX_SRC, pixt, 250, 20 + i); + + /* Test */ + regTestComparePix(rp, pixs, pixt); /* 0 */ + pixDestroy(&pixs); + pixDestroy(&pixt); + + /* Show the mirrored border, which uses the general + pixRasterop() on an image in-place. */ + pixs = pixRead("test8.jpg"); + pixt = pixRemoveBorder(pixs, 40); + pixd = pixAddMirroredBorder(pixt, 40, 40, 40, 40); + regTestWritePixAndCheck(rp, pixd, IFF_PNG); /* 1 */ + pixDisplayWithTitle(pixd, 650, 50, "mirrored border", rp->display); + pixDestroy(&pixs); + pixDestroy(&pixt); + pixDestroy(&pixd); + return regTestCleanup(rp); +} diff --git a/leptonica/prog/rasteroptest.c b/leptonica/prog/rasteroptest.c new file mode 100644 index 00000000..07ced9ce --- /dev/null +++ b/leptonica/prog/rasteroptest.c @@ -0,0 +1,143 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * rasteroptest.c + * + * This is in essence a fuzzing test for rasterop. + * + * These timings are for 1000 iterations of the inner loop. + * rasterop: + * optimizing: 0.35 sec + * valgrind: 12 sec + * rasteropIP: + * optimizing: 0.18 sec (two calls) + * valgrind: 13 sec (two calls) + * + * This has been tested with valgrind on: + * * all ops with niters = 10,000 + * * op = PIX_SRC with niters = 100,000 + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + +void GeneralTest(PIX *pix1, BOX *box1, BOX *box2, l_int32 op, l_int32 niters); +void InplaceTest(PIX *pix1, BOX *box1, BOX *box2, l_int32 op, l_int32 niters); + +int main(int argc, + char **argv) +{ +BOX *box1, *box2; +PIX *pix1; +l_int32 niters, op, selectop; + + setLeptDebugOK(1); + + pix1 = pixRead("test24.jpg"); + box1 = boxCreate(243, 127, 513, 359); + box2 = boxCreate(541, 312, 513, 359); + niters = 10000; + selectop = PIX_SRC; + +#if 1 + /* Basic rasterop */ + for (op = 0; op < 16; op++) + GeneralTest(pix1, box1, box2, op, niters); +#endif + +#if 1 + /* In-place rasterop */ + for (op = 0; op < 16; op++) + InplaceTest(pix1, box1, box2, op, niters); +#endif + +#if 0 + /* Basic rasterop; single operation */ + GeneralTest(pix1, box1, box2, selectop, niters); +#endif + + pixDestroy(&pix1); + boxDestroy(&box1); + boxDestroy(&box2); + return 0; +} + +/* ------------------------------------------------------------------- */ +void GeneralTest(PIX *pix1, BOX *box1, BOX *box2, l_int32 op, l_int32 niters) +{ +PIX *pix2, *pix3; +l_int32 i, val1, val2, val3, val4, val5, val6; + + startTimer(); + for (i = 0; i < niters; i++) { + pix2 = pixClipRectangle(pix1, box1, NULL); + pix3 = pixClipRectangle(pix1, box2, NULL); + genRandomIntOnInterval(-42, 403, 0, &val1); + genRandomIntOnInterval(-18, 289, 0, &val2); + genRandomIntOnInterval(13, 289, 0, &val3); + genRandomIntOnInterval(13, 403, 0, &val4); + genRandomIntOnInterval(-34, 289, 0, &val5); + genRandomIntOnInterval(-38, 403, 0, &val6); + pixRasterop(pix3, val1, val2, val3, val4, op, pix2, val5, val6); + if (i == op) { + lept_stderr("Rasterop: op = %d ", op); + pixDisplay(pix3, 100 * i, 100); + } + pixDestroy(&pix2); + pixDestroy(&pix3); + } + lept_stderr("Time = %7.3f sec\n", stopTimer()); +} + +/* ------------------------------------------------------------------- */ +void InplaceTest(PIX *pix1, BOX *box1, BOX *box2, l_int32 op, l_int32 niters) +{ +PIX *pix2; +l_int32 i, val1, val2, val3, val4, val5, val6; + + startTimer(); + for (i = 0; i < niters; i++) { + pix2 = pixClipRectangle(pix1, box1, NULL); + genRandomIntOnInterval(-217, 113, 0, &val1); + genRandomIntOnInterval(1, 211, 0, &val2); + genRandomIntOnInterval(-217, 143, 0, &val3); + genRandomIntOnInterval(-247, 113, 0, &val4); + genRandomIntOnInterval(1, 241, 0, &val5); + genRandomIntOnInterval(-113, 163, 0, &val6); + pixRasteropHip(pix2, val1, val2, val3, L_BRING_IN_WHITE); + pixRasteropVip(pix2, val4, val5, val6, L_BRING_IN_BLACK); + if (i == op) { + lept_stderr("Rasterop: op = %d ", op); + pixDisplay(pix2, 100 * i, 500); + } + pixDestroy(&pix2); + } + lept_stderr("Time = %7.3f sec\n", stopTimer()); +} diff --git a/leptonica/prog/rbtreetest.c b/leptonica/prog/rbtreetest.c new file mode 100644 index 00000000..3f5968e8 --- /dev/null +++ b/leptonica/prog/rbtreetest.c @@ -0,0 +1,111 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * Modified from the excellent code here: + * http://en.literateprograms.org/Red-black_tree_(C)?oldid=19567 + * which has been placed in the public domain under the Creative Commons + * CC0 1.0 waiver (http://creativecommons.org/publicdomain/zero/1.0/). + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + +#define PRINT_FULL_TREE 0 +#define TRACE 0 + +l_int32 main(int argc, + char **argv) +{ +l_int32 i; +RB_TYPE x, y; +RB_TYPE *pval; +L_RBTREE *t; + + setLeptDebugOK(1); + + t = l_rbtreeCreate(L_INT_TYPE); + l_rbtreePrint(stderr, t); + + /* Build the tree */ + for (i = 0; i < 5000; i++) { + x.itype = rand() % 10000; + y.itype = rand() % 10000; +#if TRACE + l_rbtreePrint(stderr, t); + printf("Inserting %d -> %d\n\n", x.itype, y.itype); +#endif /* TRACE */ + l_rbtreeInsert(t, x, y); + pval = l_rbtreeLookup(t, x); + if (pval->itype != y.itype) + L_ERROR("val %lld doesn't agree for key %lld\n", "main", + pval->itype, x.itype); + } + + /* Count the nodes in the tree */ + lept_stderr("count = %d\n", l_rbtreeGetCount(t)); + +#if PRINT_FULL_TREE + l_rbtreePrint(stderr, t); /* very big */ +#endif /* PRINT_FULL_TREE */ + + /* Destroy the tree and count the remaining nodes */ + l_rbtreeDestroy(&t); + l_rbtreePrint(stderr, t); /* should give an error message */ + lept_stderr("count = %d\n", l_rbtreeGetCount(t)); + + /* Build another tree */ + t = l_rbtreeCreate(L_INT_TYPE); + for (i = 0; i < 6000; i++) { + x.itype = rand() % 10000; + y.itype = rand() % 10000; + l_rbtreeInsert(t, x, y); + } + + /* Count the nodes in the tree */ + lept_stderr("count = %d\n", l_rbtreeGetCount(t)); + + /* Delete lots of nodes randomly from the tree and recount. + * Deleting 80,000 random points gets them all; deleting + * 60,000 removes all but 7 points. */ + for (i = 0; i < 60000; i++) { + x.itype = rand() % 10000; +#if TRACE + l_rbtreePrint(stderr, t); + printf("Deleting key %d\n\n", x.itype); +#endif /* TRACE */ + l_rbtreeDelete(t, x); + } + lept_stderr("count = %d\n", l_rbtreeGetCount(t)); + l_rbtreePrint(stderr, t); + lept_free(t); + + return 0; +} + diff --git a/leptonica/prog/recog/digits/bootnum1.pa b/leptonica/prog/recog/digits/bootnum1.pa Binary files differnew file mode 100644 index 00000000..cd3579ba --- /dev/null +++ b/leptonica/prog/recog/digits/bootnum1.pa diff --git a/leptonica/prog/recog/digits/bootnum2.pa b/leptonica/prog/recog/digits/bootnum2.pa Binary files differnew file mode 100644 index 00000000..f3bb0cd0 --- /dev/null +++ b/leptonica/prog/recog/digits/bootnum2.pa diff --git a/leptonica/prog/recog/digits/bootnum3.pa b/leptonica/prog/recog/digits/bootnum3.pa Binary files differnew file mode 100644 index 00000000..61880ce6 --- /dev/null +++ b/leptonica/prog/recog/digits/bootnum3.pa diff --git a/leptonica/prog/recog/digits/bootnum4.pa b/leptonica/prog/recog/digits/bootnum4.pa Binary files differnew file mode 100644 index 00000000..06996917 --- /dev/null +++ b/leptonica/prog/recog/digits/bootnum4.pa diff --git a/leptonica/prog/recog/digits/digit0.comp.tif b/leptonica/prog/recog/digits/digit0.comp.tif Binary files differnew file mode 100644 index 00000000..091e617c --- /dev/null +++ b/leptonica/prog/recog/digits/digit0.comp.tif diff --git a/leptonica/prog/recog/digits/digit1.comp.tif b/leptonica/prog/recog/digits/digit1.comp.tif Binary files differnew file mode 100644 index 00000000..32db55da --- /dev/null +++ b/leptonica/prog/recog/digits/digit1.comp.tif diff --git a/leptonica/prog/recog/digits/digit2.comp.tif b/leptonica/prog/recog/digits/digit2.comp.tif Binary files differnew file mode 100644 index 00000000..4a1391ee --- /dev/null +++ b/leptonica/prog/recog/digits/digit2.comp.tif diff --git a/leptonica/prog/recog/digits/digit3.comp.tif b/leptonica/prog/recog/digits/digit3.comp.tif Binary files differnew file mode 100644 index 00000000..ba4fd807 --- /dev/null +++ b/leptonica/prog/recog/digits/digit3.comp.tif diff --git a/leptonica/prog/recog/digits/digit4.comp.tif b/leptonica/prog/recog/digits/digit4.comp.tif Binary files differnew file mode 100644 index 00000000..c5c0129e --- /dev/null +++ b/leptonica/prog/recog/digits/digit4.comp.tif diff --git a/leptonica/prog/recog/digits/digit5.comp.tif b/leptonica/prog/recog/digits/digit5.comp.tif Binary files differnew file mode 100644 index 00000000..f839cc9d --- /dev/null +++ b/leptonica/prog/recog/digits/digit5.comp.tif diff --git a/leptonica/prog/recog/digits/digit5.orig-25.pa b/leptonica/prog/recog/digits/digit5.orig-25.pa Binary files differnew file mode 100644 index 00000000..19afb361 --- /dev/null +++ b/leptonica/prog/recog/digits/digit5.orig-25.pa diff --git a/leptonica/prog/recog/digits/digit6.comp.tif b/leptonica/prog/recog/digits/digit6.comp.tif Binary files differnew file mode 100644 index 00000000..d72570d0 --- /dev/null +++ b/leptonica/prog/recog/digits/digit6.comp.tif diff --git a/leptonica/prog/recog/digits/digit7.comp.tif b/leptonica/prog/recog/digits/digit7.comp.tif Binary files differnew file mode 100644 index 00000000..5bc50acb --- /dev/null +++ b/leptonica/prog/recog/digits/digit7.comp.tif diff --git a/leptonica/prog/recog/digits/digit8.comp.tif b/leptonica/prog/recog/digits/digit8.comp.tif Binary files differnew file mode 100644 index 00000000..c3036215 --- /dev/null +++ b/leptonica/prog/recog/digits/digit8.comp.tif diff --git a/leptonica/prog/recog/digits/digit9.comp.tif b/leptonica/prog/recog/digits/digit9.comp.tif Binary files differnew file mode 100644 index 00000000..66a79d80 --- /dev/null +++ b/leptonica/prog/recog/digits/digit9.comp.tif diff --git a/leptonica/prog/recog/digits/digit_set01.pa b/leptonica/prog/recog/digits/digit_set01.pa Binary files differnew file mode 100644 index 00000000..e22b056e --- /dev/null +++ b/leptonica/prog/recog/digits/digit_set01.pa diff --git a/leptonica/prog/recog/digits/digit_set02.pa b/leptonica/prog/recog/digits/digit_set02.pa Binary files differnew file mode 100644 index 00000000..a72e499f --- /dev/null +++ b/leptonica/prog/recog/digits/digit_set02.pa diff --git a/leptonica/prog/recog/digits/digit_set03.pa b/leptonica/prog/recog/digits/digit_set03.pa Binary files differnew file mode 100644 index 00000000..22a9f424 --- /dev/null +++ b/leptonica/prog/recog/digits/digit_set03.pa diff --git a/leptonica/prog/recog/digits/digit_set04.pa b/leptonica/prog/recog/digits/digit_set04.pa Binary files differnew file mode 100644 index 00000000..42aa8c64 --- /dev/null +++ b/leptonica/prog/recog/digits/digit_set04.pa diff --git a/leptonica/prog/recog/digits/digit_set05.pa b/leptonica/prog/recog/digits/digit_set05.pa Binary files differnew file mode 100644 index 00000000..87f5d982 --- /dev/null +++ b/leptonica/prog/recog/digits/digit_set05.pa diff --git a/leptonica/prog/recog/digits/digit_set06.pa b/leptonica/prog/recog/digits/digit_set06.pa Binary files differnew file mode 100644 index 00000000..ef6aae7f --- /dev/null +++ b/leptonica/prog/recog/digits/digit_set06.pa diff --git a/leptonica/prog/recog/digits/digit_set07.pa b/leptonica/prog/recog/digits/digit_set07.pa Binary files differnew file mode 100644 index 00000000..85b3d874 --- /dev/null +++ b/leptonica/prog/recog/digits/digit_set07.pa diff --git a/leptonica/prog/recog/digits/digit_set08.pa b/leptonica/prog/recog/digits/digit_set08.pa Binary files differnew file mode 100644 index 00000000..2a776ca7 --- /dev/null +++ b/leptonica/prog/recog/digits/digit_set08.pa diff --git a/leptonica/prog/recog/digits/digit_set09.pa b/leptonica/prog/recog/digits/digit_set09.pa Binary files differnew file mode 100644 index 00000000..cd1f4e6a --- /dev/null +++ b/leptonica/prog/recog/digits/digit_set09.pa diff --git a/leptonica/prog/recog/digits/digit_set10.pa b/leptonica/prog/recog/digits/digit_set10.pa Binary files differnew file mode 100644 index 00000000..39078a84 --- /dev/null +++ b/leptonica/prog/recog/digits/digit_set10.pa diff --git a/leptonica/prog/recog/digits/digit_set11.pa b/leptonica/prog/recog/digits/digit_set11.pa Binary files differnew file mode 100644 index 00000000..19c21c08 --- /dev/null +++ b/leptonica/prog/recog/digits/digit_set11.pa diff --git a/leptonica/prog/recog/digits/digit_set12.pa b/leptonica/prog/recog/digits/digit_set12.pa Binary files differnew file mode 100644 index 00000000..53e29c46 --- /dev/null +++ b/leptonica/prog/recog/digits/digit_set12.pa diff --git a/leptonica/prog/recog/digits/digit_set13.pa b/leptonica/prog/recog/digits/digit_set13.pa Binary files differnew file mode 100644 index 00000000..a701c5a2 --- /dev/null +++ b/leptonica/prog/recog/digits/digit_set13.pa diff --git a/leptonica/prog/recog/digits/digit_set14.pa b/leptonica/prog/recog/digits/digit_set14.pa Binary files differnew file mode 100644 index 00000000..cff1b405 --- /dev/null +++ b/leptonica/prog/recog/digits/digit_set14.pa diff --git a/leptonica/prog/recog/digits/digit_set15.pa b/leptonica/prog/recog/digits/digit_set15.pa Binary files differnew file mode 100644 index 00000000..4bd753cb --- /dev/null +++ b/leptonica/prog/recog/digits/digit_set15.pa diff --git a/leptonica/prog/recog/digits/page.306.png b/leptonica/prog/recog/digits/page.306.png Binary files differnew file mode 100644 index 00000000..a234783c --- /dev/null +++ b/leptonica/prog/recog/digits/page.306.png diff --git a/leptonica/prog/recog/digits/page.590.png b/leptonica/prog/recog/digits/page.590.png Binary files differnew file mode 100644 index 00000000..5ae2edd6 --- /dev/null +++ b/leptonica/prog/recog/digits/page.590.png diff --git a/leptonica/prog/recog/sets/samples06.png b/leptonica/prog/recog/sets/samples06.png Binary files differnew file mode 100644 index 00000000..23b7df96 --- /dev/null +++ b/leptonica/prog/recog/sets/samples06.png diff --git a/leptonica/prog/recog/sets/test01.pa b/leptonica/prog/recog/sets/test01.pa Binary files differnew file mode 100644 index 00000000..d1e4161f --- /dev/null +++ b/leptonica/prog/recog/sets/test01.pa diff --git a/leptonica/prog/recog/sets/test02.pa b/leptonica/prog/recog/sets/test02.pa Binary files differnew file mode 100644 index 00000000..79d7f506 --- /dev/null +++ b/leptonica/prog/recog/sets/test02.pa diff --git a/leptonica/prog/recog/sets/test03.pa b/leptonica/prog/recog/sets/test03.pa Binary files differnew file mode 100644 index 00000000..c9c7157b --- /dev/null +++ b/leptonica/prog/recog/sets/test03.pa diff --git a/leptonica/prog/recog/sets/test05.pa b/leptonica/prog/recog/sets/test05.pa Binary files differnew file mode 100644 index 00000000..c8a93dd5 --- /dev/null +++ b/leptonica/prog/recog/sets/test05.pa diff --git a/leptonica/prog/recog/sets/test06.pa b/leptonica/prog/recog/sets/test06.pa Binary files differnew file mode 100644 index 00000000..09a55bd8 --- /dev/null +++ b/leptonica/prog/recog/sets/test06.pa diff --git a/leptonica/prog/recog/sets/train01.pa b/leptonica/prog/recog/sets/train01.pa Binary files differnew file mode 100644 index 00000000..ad0891a5 --- /dev/null +++ b/leptonica/prog/recog/sets/train01.pa diff --git a/leptonica/prog/recog/sets/train02.pa b/leptonica/prog/recog/sets/train02.pa Binary files differnew file mode 100644 index 00000000..807d7609 --- /dev/null +++ b/leptonica/prog/recog/sets/train02.pa diff --git a/leptonica/prog/recog/sets/train03.pa b/leptonica/prog/recog/sets/train03.pa Binary files differnew file mode 100644 index 00000000..22a9f424 --- /dev/null +++ b/leptonica/prog/recog/sets/train03.pa diff --git a/leptonica/prog/recog/sets/train04.pa b/leptonica/prog/recog/sets/train04.pa Binary files differnew file mode 100644 index 00000000..47373bc9 --- /dev/null +++ b/leptonica/prog/recog/sets/train04.pa diff --git a/leptonica/prog/recog/sets/train05.pa b/leptonica/prog/recog/sets/train05.pa Binary files differnew file mode 100644 index 00000000..19c21c08 --- /dev/null +++ b/leptonica/prog/recog/sets/train05.pa diff --git a/leptonica/prog/recog/sets/train06.pa b/leptonica/prog/recog/sets/train06.pa Binary files differnew file mode 100644 index 00000000..6c22bfb0 --- /dev/null +++ b/leptonica/prog/recog/sets/train06.pa diff --git a/leptonica/prog/recog_bootnum1.c b/leptonica/prog/recog_bootnum1.c new file mode 100644 index 00000000..4143fe49 --- /dev/null +++ b/leptonica/prog/recog_bootnum1.c @@ -0,0 +1,320 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * recog_bootnum.c + * + * This does two things: + * + * (1) It makes bootnum1.pa and bootnum2.pa from stored labelled data. + * + * (2) Using these, as well as bootnum3.pa, it makes code for + * generating and compiling the the pixas, which are used by the + * boot digit recognizer. + * The output of the code generator is files such as autogen_101.*. + * These files have been edited to combine the .c and .h files into + * a single .c file: + * autogen_101.* --> src/bootnumgen1.c + * autogen_102.* --> src/bootnumgen2.c + * autogen_103.* --> src/bootnumgen3.c + * + * To add another set of templates to bootnumgen1.c: + * (a) Add a new .pa file: prog/recog/digits/digit_setN.pa (N > 15) + * (b) Add code to MakeBootnum1() for this set, selecting with the + * string those templates you want to use. + * (c) Run recog_bootnum. + * * This makes a new /tmp/lept/recog/digits/bootnum1.pa. + * Replace prog/recog/digits/bootnum1.pa with this. + * * This makes new files: /tmp/lept/auto/autogen.101.{h,c}. + * The .h file is the only one we need to use. + * Replace the encoded string in src/bootnumgen1.c with the + * one in autogen.101.h, and recompile. + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" +#include "bmfdata.h" + +static PIXA *MakeBootnum1(void); +static PIXA *MakeBootnum2(void); + +l_int32 main(int argc, + char **argv) +{ +PIX *pix1; +PIXA *pixa1, *pixa2, *pixa3; +L_STRCODE *strc; + + if (argc != 1) { + lept_stderr(" Syntax: recog_bootnum\n"); + return 1; + } + + setLeptDebugOK(1); + lept_mkdir("lept/recog/digits"); + + /* ----------------------- Bootnum 1 --------------------- */ + /* Make the bootnum pixa from the images */ + pixa1 = MakeBootnum1(); + pixaWrite("/tmp/lept/recog/digits/bootnum1.pa", pixa1); + pix1 = pixaDisplayTiledWithText(pixa1, 1500, 1.0, 10, 2, 6, 0xff000000); + pixDisplay(pix1, 100, 0); + pixDestroy(&pix1); + pixaDestroy(&pixa1); + + /* Generate the code to make the bootnum1 pixa. + * Note: the actual code we use is in bootnumgen1.c, and + * has already been compiled into the library. */ + strc = strcodeCreate(101); /* arbitrary integer */ + strcodeGenerate(strc, "/tmp/lept/recog/digits/bootnum1.pa", "PIXA"); + strcodeFinalize(&strc, "/tmp/lept/auto"); + lept_free(strc); + + /* Generate the bootnum1 pixa from the generated code */ + pixa1 = l_bootnum_gen1(); + pix1 = pixaDisplayTiledWithText(pixa1, 1500, 1.0, 10, 2, 6, 0xff000000); +/* pix1 = pixaDisplayTiled(pixa1, 1500, 0, 30); */ + pixDisplay(pix1, 100, 0); + pixDestroy(&pix1); + + /* Extend the bootnum1 pixa by erosion */ + pixa3 = pixaExtendByMorph(pixa1, L_MORPH_ERODE, 2, NULL, 1); + pix1 = pixaDisplayTiledWithText(pixa3, 1500, 1.0, 10, 2, 6, 0xff000000); + pixDisplay(pix1, 100, 0); + pixDestroy(&pix1); + pixaDestroy(&pixa1); + pixaDestroy(&pixa3); + + /* ----------------------- Bootnum 2 --------------------- */ + /* Read bootnum 2 */ + pixa2 = pixaRead("recog/digits/bootnum2.pa"); + pixaWrite("/tmp/lept/recog/digits/bootnum2.pa", pixa2); + pix1 = pixaDisplayTiledWithText(pixa2, 1500, 1.0, 10, 2, 6, 0xff000000); + pixDisplay(pix1, 100, 700); + pixDestroy(&pix1); + pixaDestroy(&pixa2); + + /* Generate the code to make the bootnum2 pixa. + * Note: the actual code we use is in bootnumgen2.c. */ + strc = strcodeCreate(102); /* another arbitrary integer */ + strcodeGenerate(strc, "/tmp/lept/recog/digits/bootnum2.pa", "PIXA"); + strcodeFinalize(&strc, "/tmp/lept/auto"); + lept_free(strc); + + /* Generate the bootnum2 pixa from the generated code */ + pixa2 = l_bootnum_gen2(); +/* pix1 = pixaDisplayTiled(pixa2, 1500, 0, 30); */ + pix1 = pixaDisplayTiledWithText(pixa2, 1500, 1.0, 10, 2, 6, 0xff000000); + pixDisplay(pix1, 100, 700); + pixDestroy(&pix1); + pixaDestroy(&pixa2); + + /* ----------------------- Bootnum 3 --------------------- */ + /* Read bootnum 3 */ + pixa1 = pixaRead("recog/digits/bootnum3.pa"); + pix1 = pixaDisplayTiledWithText(pixa1, 1500, 1.0, 10, 2, 6, 0xff000000); + pixDisplay(pix1, 1000, 0); + pixDestroy(&pix1); + pixaDestroy(&pixa1); + + /* Generate the code that, when deserializes, gives you bootnum3.pa. + * Note: the actual code we use is in bootnumgen3.c, and + * has already been compiled into the library. */ + strc = strcodeCreate(103); /* arbitrary integer */ + strcodeGenerate(strc, "recog/digits/bootnum3.pa", "PIXA"); + strcodeFinalize(&strc, "/tmp/lept/auto"); + lept_free(strc); + + /* Generate the bootnum3 pixa from the generated code */ + pixa1 = l_bootnum_gen3(); + pix1 = pixaDisplayTiledWithText(pixa1, 1500, 1.0, 10, 2, 6, 0xff000000); + pixDisplay(pix1, 1000, 0); + pixDestroy(&pix1); + + /* Extend the bootnum3 pixa twice by erosion */ + pixa3 = pixaExtendByMorph(pixa1, L_MORPH_ERODE, 2, NULL, 1); + pix1 = pixaDisplayTiledWithText(pixa3, 1500, 1.0, 10, 2, 6, 0xff000000); + pixDisplay(pix1, 1000, 0); + pixDestroy(&pix1); + pixaDestroy(&pixa1); + pixaDestroy(&pixa3); + +#if 0 + pixa1 = l_bootnum_gen1(); +/* pixa1 = pixaRead("recog/digits/bootnum1.pa"); */ + pixaWrite("/tmp/lept/junk.pa", pixa1); + pixa2 = pixaRead("/tmp/lept/junk.pa"); + pixaWrite("/tmp/lept/junk1.pa", pixa2); + pixa3 = pixaRead("/tmp/lept/junk1.pa"); + n = pixaGetCount(pixa3); + for (i = 0; i < n; i++) { + pix = pixaGetPix(pixa3, i, L_CLONE); + lept_stderr("i = %d, text = %s\n", i, pixGetText(pix)); + pixDestroy(&pix); + } + pixaDestroy(&pixa1); + pixaDestroy(&pixa2); + pixaDestroy(&pixa3); +#endif + + return 0; +} + + +PIXA *MakeBootnum1(void) +{ +const char *str; +PIXA *pixa1, *pixa2, *pixa3; + + pixa1 = pixaRead("recog/digits/digit_set02.pa"); + str = "10, 27, 35, 45, 48, 74, 79, 97, 119, 124, 148"; + pixa3 = pixaSelectWithString(pixa1, str, NULL); + pixaDestroy(&pixa1); + + pixa1 = pixaRead("recog/digits/digit_set03.pa"); + str = "2, 15, 30, 50, 60, 75, 95, 105, 121, 135"; + pixa2 = pixaSelectWithString(pixa1, str, NULL); + pixaJoin(pixa3, pixa2, 0, -1); + pixaDestroy(&pixa1); + pixaDestroy(&pixa2); + + pixa1 = pixaRead("recog/digits/digit_set05.pa"); + str = "0, 15, 30, 49, 60, 75, 90, 105, 120, 135"; + pixa2 = pixaSelectWithString(pixa1, str, NULL); + pixaJoin(pixa3, pixa2, 0, -1); + pixaDestroy(&pixa1); + pixaDestroy(&pixa2); + + pixa1 = pixaRead("recog/digits/digit_set06.pa"); + str = "4, 15, 30, 48, 60, 78, 90, 105, 120, 135"; + pixa2 = pixaSelectWithString(pixa1, str, NULL); + pixaJoin(pixa3, pixa2, 0, -1); + pixaDestroy(&pixa1); + pixaDestroy(&pixa2); + + pixa1 = pixaRead("recog/digits/digit_set07.pa"); + str = "3, 15, 30, 45, 60, 77, 78, 91, 105, 120, 149"; + pixa2 = pixaSelectWithString(pixa1, str, NULL); + pixaJoin(pixa3, pixa2, 0, -1); + pixaDestroy(&pixa1); + pixaDestroy(&pixa2); + + pixa1 = pixaRead("recog/digits/digit_set08.pa"); + str = "0, 20, 30, 45, 60, 75, 90, 106, 121, 135"; + pixa2 = pixaSelectWithString(pixa1, str, NULL); + pixaJoin(pixa3, pixa2, 0, -1); + pixaDestroy(&pixa1); + pixaDestroy(&pixa2); + + pixa1 = pixaRead("recog/digits/digit_set09.pa"); + str = "0, 20, 32, 47, 54, 63, 75, 91, 105, 125, 136"; + pixa2 = pixaSelectWithString(pixa1, str, NULL); + pixaJoin(pixa3, pixa2, 0, -1); + pixaDestroy(&pixa1); + pixaDestroy(&pixa2); + + pixa1 = pixaRead("recog/digits/digit_set11.pa"); + str = "0, 15, 36, 46, 62, 63, 76, 91, 106, 123, 135"; + pixa2 = pixaSelectWithString(pixa1, str, NULL); + pixaJoin(pixa3, pixa2, 0, -1); + pixaDestroy(&pixa1); + pixaDestroy(&pixa2); + + pixa1 = pixaRead("recog/digits/digit_set12.pa"); + str = "1, 20, 31, 45, 61, 75, 95, 107, 120, 135"; + pixa2 = pixaSelectWithString(pixa1, str, NULL); + pixaJoin(pixa3, pixa2, 0, -1); + pixaDestroy(&pixa1); + pixaDestroy(&pixa2); + + pixa1 = pixaRead("recog/digits/digit_set13.pa"); + str = "1, 16, 31, 48, 63, 78, 98, 105, 123, 136"; + pixa2 = pixaSelectWithString(pixa1, str, NULL); + pixaJoin(pixa3, pixa2, 0, -1); + pixaDestroy(&pixa1); + pixaDestroy(&pixa2); + + pixa1 = pixaRead("recog/digits/digit_set14.pa"); + str = "1, 14, 24, 37, 53, 62, 74, 83, 98, 114"; + pixa2 = pixaSelectWithString(pixa1, str, NULL); + pixaJoin(pixa3, pixa2, 0, -1); + pixaDestroy(&pixa1); + pixaDestroy(&pixa2); + + pixa1 = pixaRead("recog/digits/digit_set15.pa"); + str = "0, 1, 3, 5, 7, 8, 13, 25, 35"; + pixa2 = pixaSelectWithString(pixa1, str, NULL); + pixaJoin(pixa3, pixa2, 0, -1); + pixaDestroy(&pixa1); + pixaDestroy(&pixa2); + + return pixa3; +} + + +PIXA *MakeBootnum2(void) +{ +char *fname; +l_int32 i, n, w, h; +BOX *box; +PIX *pix; +PIXA *pixa; +L_RECOG *recog; +SARRAY *sa; + + /* Phase 1: generate recog from the digit data */ + recog = recogCreate(0, 40, 0, 128, 1); + sa = getSortedPathnamesInDirectory("recog/bootnums", "png", 0, 0); + n = sarrayGetCount(sa); + for (i = 0; i < n; i++) { + /* Read each pix: grayscale, multi-character, labelled */ + fname = sarrayGetString(sa, i, L_NOCOPY); + if ((pix = pixRead(fname)) == NULL) { + lept_stderr("Can't read %s\n", fname); + continue; + } + + /* Convert to a set of 1 bpp, single character, labelled */ + pixGetDimensions(pix, &w, &h, NULL); + box = boxCreate(0, 0, w, h); + recogTrainLabeled(recog, pix, box, NULL, 0); + pixDestroy(&pix); + boxDestroy(&box); + } + recogTrainingFinished(&recog, 1, -1, -1.0); + sarrayDestroy(&sa); + + /* Phase 2: generate pixa consisting of 1 bpp, single character pix */ + pixa = recogExtractPixa(recog); + pixaWrite("/tmp/lept/recog/digits/bootnum2.pa", pixa); + recogDestroy(&recog); + return pixa; +} + + diff --git a/leptonica/prog/recog_bootnum2.c b/leptonica/prog/recog_bootnum2.c new file mode 100644 index 00000000..18dc3332 --- /dev/null +++ b/leptonica/prog/recog_bootnum2.c @@ -0,0 +1,183 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * recog_bootnum2.c + * + * This shows how to convert from a pixa of digit images to + * a very compressed representation, including a filtering step + * where selected pix are removed. This method was used to + * generate the recog/digits/digit*.comp.tif image mosaics. + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "string.h" +#include "allheaders.h" + +static const char *removeset = "4,7,9,21"; + +void ProcessDigits(l_int32 i); +void PixaDisplayNumbered(PIXA *pixa, const char *rootname); + +l_int32 main(int argc, + char **argv) +{ + setLeptDebugOK(1); + lept_mkdir("lept/digit"); + ProcessDigits(5); + return 0; +} + +/* ----------------------------------------------------- */ +void ProcessDigits(l_int32 index) +{ +char rootname[8] = "digit5"; +char buf[64]; +l_int32 i, nc, ns, same; +NUMA *na1; +PIX *pix1, *pix2, *pix3, *pix4, *pix5, *pix6; +PIXA *pixa1, *pixa2, *pixa3; + + /* Read the unfiltered, unscaled pixa of twenty-five 5s */ + snprintf(buf, sizeof(buf), "digits/%s.orig-25.pa", rootname); + pixa1 = pixaRead(buf); + + /* Number and show the input images */ + snprintf(buf, sizeof(buf), "/tmp/lept/digit/%s.orig-num", rootname); + PixaDisplayNumbered(pixa1, buf); + + /* Remove some of them */ + na1 = numaCreateFromString(removeset); + pixaRemoveSelected(pixa1, na1); + numaDestroy(&na1); + snprintf(buf, sizeof(buf), "/tmp/lept/digit/%s.filt.pa", rootname); + pixaWrite(buf, pixa1); + + /* Number and show the filtered images */ + snprintf(buf, sizeof(buf), "/tmp/lept/digit/%s.filt-num", rootname); + PixaDisplayNumbered(pixa1, buf); + + /* Extract the largest c.c., clip to the foreground, + * and scale the result to a fixed size. */ + nc = pixaGetCount(pixa1); + pixa2 = pixaCreate(nc); + for (i = 0; i < nc; i++) { + pix1 = pixaGetPix(pixa1, i, L_CLONE); + /* A threshold of 140 gives reasonable results */ + pix2 = pixThresholdToBinary(pix1, 140); + /* Join nearly touching pieces */ + pix3 = pixCloseSafeBrick(NULL, pix2, 5, 5); + /* Take the largest (by area) connected component */ + pix4 = pixFilterComponentBySize(pix3, 0, L_SELECT_BY_AREA, 8, NULL); + /* Extract the original 1 bpp pixels that have been + * covered by the closing operation */ + pixAnd(pix4, pix4, pix2); + /* Grab the result as an image with no surrounding whitespace */ + pixClipToForeground(pix4, &pix5, NULL); + /* Rescale the result to the canonical size */ + pix6 = pixScaleToSize(pix5, 20, 30); + pixaAddPix(pixa2, pix6, L_INSERT); + pixDestroy(&pix1); + pixDestroy(&pix2); + pixDestroy(&pix3); + pixDestroy(&pix4); + pixDestroy(&pix5); + } + + /* Add the index (a "5") in the text field of each pix; save pixa2 */ + snprintf(buf, sizeof(buf), "%d", index); + for (i = 0; i < nc; i++) { + pix1 = pixaGetPix(pixa2, i, L_CLONE); + pixSetText(pix1, buf); + pixDestroy(&pix1); + } + snprintf(buf, sizeof(buf), "/tmp/lept/digit/%s.comp.pa", rootname); + pixaWrite(buf, pixa2); + + /* Number and show the resulting binary templates */ + snprintf(buf, sizeof(buf), "/tmp/lept/digit/%s.comp-num", rootname); + PixaDisplayNumbered(pixa2, buf); + + /* Save the binary templates as a packed tiling (tiff g4). + * This is the most efficient way to represent the templates. */ + pix1 = pixaDisplayOnLattice(pixa2, 20, 30, NULL, NULL); + pixDisplay(pix1, 1000, 500); + snprintf(buf, sizeof(buf), "/tmp/lept/digit/%s.comp.tif", rootname); + pixWrite(buf, pix1, IFF_TIFF_G4); + + /* The number of templates is in the pix text string; check it. */ + pix2 = pixRead(buf); + if (sscanf(pixGetText(pix2), "n = %d", &ns) != 1) + lept_stderr("Failed to read the number of templates!\n"); + if (ns != nc) + lept_stderr("(stored = %d) != (actual number = %d)\n", ns, nc); + + /* Reconstruct the pixa of templates from the tiled compressed + * image, and verify that the resulting pixa is the same. */ + pixa3 = pixaMakeFromTiledPix(pix1, 20, 30, 0, 0, NULL); + pixaEqual(pixa2, pixa3, 0, NULL, &same); + if (!same) + lept_stderr("Pixa are not the same!\n"); + + pixDestroy(&pix1); + pixDestroy(&pix2); + pixaDestroy(&pixa1); + pixaDestroy(&pixa2); + pixaDestroy(&pixa3); +} + + +/* ----------------------------------------------------- */ +void PixaDisplayNumbered(PIXA *pixa, + const char *basename) +{ +char buf[64]; +l_int32 fill, color, d; +L_BMF *bmf; +PIX *pix1; +PIXA *pixa1, *pixa2; + + bmf = bmfCreate(NULL, 4); + pixaGetPixDimensions(pixa, 0, NULL, NULL, &d); + fill = (d == 8) ? 0xff : 0; + color = (d == 8) ? 0x00000000 : 0xffffff00; + pixa1 = pixaAddBorderGeneral(NULL, pixa, 10, 10, 0, 0, fill); + pixa2 = pixaAddTextNumber(pixa1, bmf, NULL, color, L_ADD_BELOW); + snprintf(buf, sizeof(buf), "%s.pa", basename); + pixaWrite(buf, pixa2); + pix1 = pixaDisplayTiledInColumns(pixa2, 20, 2.5, 15, 2); + snprintf(buf, sizeof(buf), "%s.png", basename); + pixWrite(buf, pix1, IFF_PNG); + pixDisplay(pix1, 500, 500); + pixDestroy(&pix1); + pixaDestroy(&pixa1); + pixaDestroy(&pixa2); + bmfDestroy(&bmf); +} + diff --git a/leptonica/prog/recog_bootnum3.c b/leptonica/prog/recog_bootnum3.c new file mode 100644 index 00000000..365d3f34 --- /dev/null +++ b/leptonica/prog/recog_bootnum3.c @@ -0,0 +1,90 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * recog_bootnum3.c + * + * This does two things. + * + * (1) It makes recog/digits/bootnum4.pa, a pixa of 100 samples + * from each of the 10 digits. These are stored as 10 mosaics + * where the 100 samples are packed in 20x30 pixel tiles. + * + * (2) It generates the code that is able to generate a pixa with + * any number from 1 to 100 of samples for each digit. This + * new pixa has one pix for each sample (the tiled pix in the + * input pixa have been split out), so it can have up to 1000 pix. + * The compressed string of data and the code for deserializing + * it are auto-generated with the stringcode utility. + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + +l_int32 main(int argc, + char **argv) +{ +char buf[64]; +l_int32 i; +PIX *pix1, *pix2; +PIXA *pixa1, *pixa2; +L_STRCODE *strc; + + if (argc != 1) { + lept_stderr(" Syntax: recog_bootnum3\n"); + return 1; + } + + setLeptDebugOK(1); + lept_mkdir("lept/digit"); + + /* Make a pixa of the first 100 samples for each digit. + * This will be saved to recog/digits/bootnum4.pa. */ + pixa1 = pixaCreate(10); + for (i = 0; i < 10; i++) { + snprintf(buf, sizeof(buf), "recog/digits/digit%d.comp.tif", i); + pix1 = pixRead(buf); + pixa2 = pixaMakeFromTiledPix(pix1, 20, 30, 0, 100, NULL); + pix2 = pixaDisplayOnLattice(pixa2, 20, 30, NULL, NULL); + pixaAddPix(pixa1, pix2, L_INSERT); + pixDestroy(&pix1); + pixaDestroy(&pixa2); + } + /* Write it out (and copy to recog/digits/bootnum4.pa) */ + pixaWrite("/tmp/lept/digit/bootnum4.pa", pixa1); + pixaDestroy(&pixa1); + + /* Generate the stringcode in two files for this pixa. + * Both files are then assempled into the source file + * bootnumgen4.c, which is compiled into the library. */ + strc = strcodeCreate(212); // arbitrary integer + strcodeGenerate(strc, "/tmp/lept/digit/bootnum4.pa", "PIXA"); + strcodeFinalize(&strc, "."); + return 0; +} diff --git a/leptonica/prog/recogsort.c b/leptonica/prog/recogsort.c new file mode 100644 index 00000000..00233763 --- /dev/null +++ b/leptonica/prog/recogsort.c @@ -0,0 +1,124 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * recogsort.c + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "string.h" +#include "allheaders.h" + + +l_int32 main(int argc, + char **argv) +{ +char *boxatxt; +l_int32 i; +BOXA *boxa1, *boxa2, *boxa3; +BOXAA *baa, *baa1; +NUMAA *naa1; +PIX *pixdb, *pix1, *pix2, *pix3, *pix4; +PIXA *pixa1, *pixa2, *pixa3, *pixat; +L_RECOG *recog; +SARRAY *sa1; + + /* ----- Example identifying samples using training data ----- */ + + setLeptDebugOK(1); + lept_mkdir("lept/recog"); + + /* Read the training data */ + pixat = pixaRead("recog/sets/train06.pa"); + recog = recogCreateFromPixa(pixat, 0, 0, 0, 128, 1); + recogAverageSamples(&recog, 0); /* required for splitting characters */ + pix1 = pixaDisplayTiledWithText(pixat, 1500, 1.0, 10, 1, 8, 0xff000000); + pixDisplay(pix1, 0, 0); + pixDestroy(&pix1); + pixaDestroy(&pixat); + + /* Read the data from all samples */ + pix1 = pixRead("recog/sets/samples06.png"); + boxatxt = pixGetText(pix1); + lept_stderr("%s\n", boxatxt); + boxa1 = boxaReadMem((l_uint8 *)boxatxt, strlen(boxatxt)); + pixa1 = pixaCreateFromBoxa(pix1, boxa1, 0, 0, NULL); + pixDestroy(&pix1); /* destroys boxa1 */ + + /* Identify components in the sample data */ + pixa2 = pixaCreate(0); + pixa3 = pixaCreate(0); + for (i = 0; i < 9; i++) { +/* if (i != 4) continue; */ /* dots form separate boxa */ +/* if (i != 8) continue; */ /* broken 2 in '24' */ + if (i != 8) continue; + pix1 = pixaGetPix(pixa1, i, L_CLONE); + + /* Show the 2d box data in the sample */ + boxa2 = pixConnComp(pix1, NULL, 8); + baa = boxaSort2d(boxa2, NULL, 6, 6, 5); + pix2 = boxaaDisplay(pix1, baa, 3, 1, 0xff000000, 0x00ff0000, 0, 0); + pixaAddPix(pixa3, pix2, L_INSERT); + boxaaDestroy(&baa); + boxaDestroy(&boxa2); + + /* Get the numbers in the sample */ + recogIdentifyMultiple(recog, pix1, 0, 0, &boxa3, NULL, &pixdb, 0); + sa1 = recogExtractNumbers(recog, boxa3, 0.7, -1, &baa1, &naa1); + sarrayWriteStream(stderr, sa1); + boxaaWriteStream(stderr, baa1); + numaaWriteStream(stderr, naa1); + pixaAddPix(pixa2, pixdb, L_INSERT); +/* pixaWrite("/tmp/pixa.pa", pixa2); */ + pixDestroy(&pix1); + boxaWriteStream(stderr, boxa3); + boxaDestroy(&boxa3); + boxaaDestroy(&baa1); + numaaDestroy(&naa1); + sarrayDestroy(&sa1); + } + + pix3 = pixaDisplayLinearly(pixa2, L_VERT, 1.0, 0, 20, 1, NULL); + pixWrite("/tmp/lept/recog/pix3.png", pix3, IFF_PNG); + pix4 = pixaDisplayTiledInRows(pixa3, 32, 1500, 1.0, 0, 20, 2); + pixDisplay(pix4, 500, 0); + pixWrite("/tmp/lept/recog/pix4.png", pix4, IFF_PNG); + pixaDestroy(&pixa2); + pixaDestroy(&pixa3); + pixDestroy(&pix1); + pixDestroy(&pix3); + pixDestroy(&pix4); + pixaDestroy(&pixa1); + boxaDestroy(&boxa1); + recogDestroy(&recog); + + return 0; +} + + diff --git a/leptonica/prog/recogtest1.c b/leptonica/prog/recogtest1.c new file mode 100644 index 00000000..1d36cf4f --- /dev/null +++ b/leptonica/prog/recogtest1.c @@ -0,0 +1,176 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * recogtest1.c + * + * Tests the recog utility using the bootstrap number set, + * for both training and identification + * + * An example of greedy splitting of touching characters is given. + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "string.h" +#include "allheaders.h" + +static const l_int32 scaledw = 0; +static const l_int32 scaledh = 40; + +static const l_float32 MinScore[] = {0.6f, 0.7f, 0.9f}; +static const l_int32 MinTarget[] = {4, 5, 4}; +static const l_int32 MinSize[] = {3, 2, 3}; + +l_int32 main(int argc, + char **argv) +{ +l_int32 i, linew, same; +BOXA *boxat; +PIX *pixd, *pix1, *pix2, *pixdb; +PIXA *pixa1, *pixa2, *pixa3; +L_RECOG *recog1, *recog2; + + if (argc != 1) { + lept_stderr(" Syntax: recogtest1\n"); + return 1; + } + + setLeptDebugOK(1); + lept_mkdir("lept/digits"); + recog1 = NULL; + recog2 = NULL; + +#if 0 + linew = 5; /* for lines */ +#else + linew = 0; /* scanned image */ +#endif + +#if 1 + pixa1 = pixaRead("recog/digits/bootnum1.pa"); + recog1 = recogCreateFromPixa(pixa1, scaledw, scaledh, linew, 120, 1); + pix1 = pixaDisplayTiledWithText(pixa1, 1400, 1.0, 10, 2, 6, 0xff000000); + pixWrite("/tmp/lept/digits/bootnum1.png", pix1, IFF_PNG); + pixDisplay(pix1, 800, 800); + pixDestroy(&pix1); + pixaDestroy(&pixa1); +#endif + +#if 1 + lept_stderr("Print Stats 1\n"); + recogShowContent(stderr, recog1, 1, 1); +#endif + +#if 1 + lept_stderr("AverageSamples\n"); + recogAverageSamples(&recog1, 1); + recogShowAverageTemplates(recog1); + pix1 = pixaGetPix(recog1->pixadb_ave, 0, L_CLONE); + pixWrite("/tmp/lept/digits/unscaled_ave.png", pix1, IFF_PNG); + pixDestroy(&pix1); + pix1 = pixaGetPix(recog1->pixadb_ave, 1, L_CLONE); + pixWrite("/tmp/lept/digits/scaled_ave.png", pix1, IFF_PNG); + pixDestroy(&pix1); +#endif + +#if 1 + recogDebugAverages(&recog1, 0); + recogShowMatchesInRange(recog1, recog1->pixa_tr, 0.65, 1.0, 0); + pixWrite("/tmp/lept/digits/match_ave1.png", recog1->pixdb_range, IFF_PNG); + recogShowMatchesInRange(recog1, recog1->pixa_tr, 0.0, 1.0, 0); + pixWrite("/tmp/lept/digits/match_ave2.png", recog1->pixdb_range, IFF_PNG); +#endif + +#if 1 + lept_stderr("Print stats 2\n"); + recogShowContent(stderr, recog1, 2, 1); + recogWrite("/tmp/lept/digits/rec1.rec", recog1); + recog2 = recogRead("/tmp/lept/digits/rec1.rec"); + recogShowContent(stderr, recog2, 3, 1); + recogWrite("/tmp/lept/digits/rec2.rec", recog2); + filesAreIdentical("/tmp/lept/digits/rec1.rec", + "/tmp/lept/digits/rec2.rec", &same); + if (!same) + lept_stderr("Error in serialization!\n"); + recogDestroy(&recog2); +#endif + +#if 1 + /* Three sets of parameters: + * 0.6, 0.3 : removes a few poor matches + * 0.8, 0.2 : remove many based on matching; remove some based on + * requiring retention of 20% of templates in each class + * 0.9, 0.01 : remove most based on matching; saved 1 in each class */ + lept_stderr("Remove outliers\n"); + pixa2 = recogExtractPixa(recog1); + for (i = 0; i < 3; i++) { + pixa3 = pixaRemoveOutliers1(pixa2, MinScore[i], MinTarget[i], + MinSize[i], &pix1, &pix2); + pixDisplay(pix1, 900, 250 * i); + pixDisplay(pix2, 1300, 250 * i); + pixDestroy(&pix1); + pixDestroy(&pix2); + pixaDestroy(&pixa3); + } + pixaDestroy(&pixa2); +#endif + +#if 1 + /* Split touching characters */ + lept_stderr("Split touching\n"); + pixd = pixRead("recog/digits/page.590.png"); /* 590 or 306 */ + recogIdentifyMultiple(recog1, pixd, 0, 0, &boxat, &pixa2, &pixdb, 1); + pixDisplay(pixdb, 800, 800); + boxaWriteStream(stderr, boxat); + pix1 = pixaDisplay(pixa2, 0, 0); + pixDisplay(pix1, 1200, 800); + pixDestroy(&pixdb); + pixDestroy(&pix1); + pixDestroy(&pixd); + pixaDestroy(&pixa2); + boxaDestroy(&boxat); +#endif + +#if 1 + lept_stderr("Reading new training set and computing averages\n"); + lept_stderr("Print stats 3\n"); + pixa1 = pixaRead("recog/sets/train03.pa"); + recog2 = recogCreateFromPixa(pixa1, 0, 40, 0, 128, 1); + recogShowContent(stderr, recog2, 3, 1); + recogDebugAverages(&recog2, 3); + pixWrite("/tmp/lept/digits/averages.png", recog2->pixdb_ave, IFF_PNG); + recogShowAverageTemplates(recog2); + pixaDestroy(&pixa1); + recogDestroy(&recog2); +#endif + + recogDestroy(&recog1); + recogDestroy(&recog2); + return 0; +} diff --git a/leptonica/prog/recogtest2.c b/leptonica/prog/recogtest2.c new file mode 100644 index 00000000..3e7c2342 --- /dev/null +++ b/leptonica/prog/recogtest2.c @@ -0,0 +1,193 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * recogtest2.c + * + * Test bootstrap recognizer (BSR) to train a book-adapted + * recognizer (BAR), starting with unlabeled bitmaps from the book. + * + * Several BSRs are used. + * The BAR images are taken from recog/sets/train*.pa. We really + * know their classes, but pretend we don't, by erasing the labels. + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "string.h" +#include "allheaders.h" + + /* Sets for training using boot recognizers */ +static char trainset1[] = "recog/sets/train04.pa"; /* partial set */ +static char trainset2[] = "recog/sets/train05.pa"; /* full set */ + + /* Use scanned images or width-normalized lines */ +#if 1 +static const l_int32 linew = 0; /* use scanned bitmaps */ +#else +static const l_int32 linew = 5; /* use generated lines */ +#endif + +l_int32 main(int argc, + char **argv) +{ +char *fname; +l_int32 i; +BOXA *boxa1; +BOXAA *baa; +NUMAA *naa; +PIX *pix1, *pix2, *pix3; +PIXA *pixa1, *pixa2, *pixa3; +L_RECOG *recogboot, *recog1; +SARRAY *sa; + + if (argc != 1) { + lept_stderr(" Syntax: recogtest2\n"); + return 1; + } + + setLeptDebugOK(1); + lept_mkdir("lept/recog"); + + /* Files with 'unlabeled' templates from book */ + sa = sarrayCreate(2); + sarrayAddString(sa, trainset1, L_COPY); + sarrayAddString(sa, trainset2, L_COPY); + + /* ----------------------------------------------------------- */ + /* Do operations with a simple bootstrap recognizer */ + /* ----------------------------------------------------------- */ + + /* Generate a BSR (boot-strap recog), and show the unscaled + * and scaled versions of the templates */ + pixa1 = (PIXA *)l_bootnum_gen1(); /* from recog/digits/bootnum1.pa */ + recogboot = recogCreateFromPixa(pixa1, 0, 40, linew, 128, 1); + recogWrite("/tmp/lept/recog/boot1.rec", recogboot); + recogShowContent(stderr, recogboot, 1, 1); + pixaDestroy(&pixa1); + + /* Generate a BAR (book-adapted recog) for a set of images from + * one book. Select a set of digit images. These happen to + * be labeled, so we clear the text field from each pix before + * running it through the boot recognizer. */ + for (i = 0; i < 2; i++) { + fname = sarrayGetString(sa, i, L_NOCOPY); + pixa2 = pixaRead(fname); + pixaSetText(pixa2, NULL, NULL); + + /* Train a new recognizer from the boot and unlabeled samples */ + pixa3 = recogTrainFromBoot(recogboot, pixa2, 0.65, 128, 1); + recog1 = recogCreateFromPixa(pixa3, 0, 40, linew, 128, 1); + recogShowContent(stderr, recog1, 2, 1); + if (i == 0) + recogWrite("/tmp/lept/recog/recog1.rec", recog1); + else /* i == 1 */ + recogWrite("/tmp/lept/recog/recog2.rec", recog1); + pixaDestroy(&pixa2); + pixaDestroy(&pixa3); + recogDestroy(&recog1); + } + recogDestroy(&recogboot); + + /* ----------------------------------------------------------- */ + /* Do operations with a larger bootstrap recognizer */ + /* ----------------------------------------------------------- */ + + /* Generate the boot recog, and show the unscaled and scaled + * versions of the templates */ + recogboot = recogMakeBootDigitRecog(0, 40, linew, 1, 1); + recogWrite("/tmp/lept/recog/boot2.rec", recogboot); + recogShowContent(stderr, recogboot, 3, 1); + + /* Generate a BAR for a set of images from one book. + * Select a set of digit images and erase the text field. */ + for (i = 0; i < 2; i++) { + fname = sarrayGetString(sa, i, L_NOCOPY); + pixa2 = pixaRead(fname); + pixaSetText(pixa2, NULL, NULL); + + /* Train a new recognizer from the boot and unlabeled samples */ + pixa3 = recogTrainFromBoot(recogboot, pixa2, 0.65, 128, 1); + recog1 = recogCreateFromPixa(pixa3, 0, 40, linew, 128, 1); + recogShowContent(stderr, recog1, 4, 1); + if (i == 0) + recogWrite("/tmp/lept/recog/recog3.rec", recog1); + else if (i == 1) + recogWrite("/tmp/lept/recog/recog4.rec", recog1); + pixaDestroy(&pixa2); + pixaDestroy(&pixa3); + recogDestroy(&recog1); + } + recogDestroy(&recogboot); + sarrayDestroy(&sa); + +#if 0 + recogShowMatchesInRange(recog, recog->pixa_tr, 0.0, 1.0, 1); + recogShowContent(stderr, recog, 1); + + /* Now use minscore = 0.75 to remove the outliers in the BAR, + * and show what is left. */ + lept_stderr("initial size: %d\n", recog->num_samples); + pix1 = pix2 = NULL; + recogRemoveOutliers1(&recog, 0.75, 5, 3, &pix1, &pix2); + pixDisplay(pix1, 500, 0); + pixDisplay(pix2, 500, 500); + pixDestroy(&pix1); + pixDestroy(&pix2); + lept_stderr("final size: %d\n", recog->num_samples); + recogDebugAverages(&recog, 1); + recogShowContent(stderr, recog, 1); + recogShowMatchesInRange(recog, recog->pixa_tr, 0.75, 1.0, 1); + pixWrite("/tmp/lept/recog/range.png", recog->pixdb_range, IFF_PNG); +#endif + + /* ----------------------------------------------------------- */ + /* Show operation of the default bootstrap recognizer */ + /* ----------------------------------------------------------- */ + + recog1 = recogMakeBootDigitRecog(0, 40, 0, 1, 0); + pix1 = pixRead("test-87220.59.png"); + recogIdentifyMultiple(recog1, pix1, 0, 1, &boxa1, NULL, NULL, 0); + sa = recogExtractNumbers(recog1, boxa1, 0.75, -1, &baa, &naa); + pixa1 = showExtractNumbers(pix1, sa, baa, naa, &pix3); + pix2 = pixaDisplayTiledInRows(pixa1, 32, 600, 1.0, 0, 20, 2); + pixDisplay(pix2, 0, 1000); + pixDisplay(pix3, 600, 1000); + pixWrite("/tmp/lept/recog/extract.png", pix3, IFF_PNG); + pixDestroy(&pix1); + pixDestroy(&pix2); + pixDestroy(&pix3); + pixaDestroy(&pixa1); + sarrayDestroy(&sa); + boxaDestroy(&boxa1); + boxaaDestroy(&baa); + numaaDestroy(&naa); + recogDestroy(&recog1); + + return 0; +} diff --git a/leptonica/prog/recogtest3.c b/leptonica/prog/recogtest3.c new file mode 100644 index 00000000..c54be397 --- /dev/null +++ b/leptonica/prog/recogtest3.c @@ -0,0 +1,182 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * recogtest3.c + * + * Test padding of book-adapted recognizer (BAR) using templates + * from a bootstrap recognizer (BSR) to identify unlabeled samples + * from the book. + * + * Terminology note: + * templates: labeled character images that can be inserted + * into a recognizer. + * samples: unlabeled character images that must be labeled by + * a recognizer before they can be used as templates. + * + * This demonstrates the following operations: + * (1) Making a BAR from labeled book templates (as a pixa). + * (2) Making a hybrid BAR/BSR from scaled templates in the BAR, + * supplemented with similarly scaled bootstrap templates for those + * classes where the BAR templates are either missing or not + * of sufficient quantity. + * (3) Using the BAR/BSR to label unlabeled book sampless. + * (4) Adding the pixa of the original set of labeled book + * templates to the pixa of the newly labeled templates, and + * making a BAR from the joined pixa. The BAR would then + * work to identify unscaled samples from the book. + * (5) Removing outliers from the BAR. + * + * Note that if this final BAR were not to have a sufficient number + * of templates in each class, it can again be augmented with BSR + * templates, and the hybrid BAR/BSR would be the final recognizer + * that is used to identify unknown (scaled) samples. + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "string.h" +#include "allheaders.h" + + +l_int32 main(int argc, + char **argv) +{ +char *text; +l_int32 histo[10]; +l_int32 i, n, ival, same; +PIX *pix1, *pix2; +PIXA *pixa1, *pixa2, *pixa3, *pixa4; +L_RECOG *recog1, *recog2, *recog3; + + if (argc != 1) { + lept_stderr(" Syntax: recogtest3\n"); + return 1; + } + + setLeptDebugOK(1); + lept_mkdir("lept/recog"); + + /* Read templates and split them into two sets. Use one to + * make a BAR recog that needs padding; use the other with a + * hybrid BAR/BSR to make more labeled templates to augment + * the BAR */ + pixa1 = pixaRead("recog/sets/train05.pa"); + pixa2 = pixaCreate(0); /* to generate a small BAR */ + pixa3 = pixaCreate(0); /* for templates to be labeled and + * added to the BAR */ + n = pixaGetCount(pixa1); + for (i = 0; i < 10; i++) + histo[i] = 0; + for (i = 0; i < n; i++) { + pix1 = pixaGetPix(pixa1, i, L_COPY); + text = pixGetText(pix1); + ival = text[0] - '0'; + /* remove all 4's, and all but 2 7's and 9's */ + if (ival == 4 || (ival == 7 && histo[7] == 2) || + (ival == 9 && histo[9] == 2)) { + pixaAddPix(pixa3, pix1, L_INSERT); + } else { + pixaAddPix(pixa2, pix1, L_INSERT); + histo[ival]++; + } + } + pix1 = pixaDisplayTiledWithText(pixa3, 1500, 1.0, 15, 2, 6, 0xff000000); + pixDisplay(pix1, 500, 0); + pixDestroy(&pix1); + + /* Make a BAR from the small set */ + recog1 = recogCreateFromPixa(pixa2, 0, 40, 0, 128, 1); + recogShowContent(stderr, recog1, 0, 1); + + /* Pad with BSR templates to make a hybrid BAR/BSR */ + recogPadDigitTrainingSet(&recog1, 40, 0); + recogShowContent(stderr, recog1, 1, 1); + + /* Use the BAR/BSR to label the left-over templates from the book */ + pixa4 = recogTrainFromBoot(recog1, pixa3, 0.75, 128, 1); + + /* Join the two sets */ + pixaJoin(pixa1, pixa4, 0, 0); + pixaDestroy(&pixa4); + + /* Make a new BAR that uses unscaled templates. + * This now has all the templates from pixa1, before deletions */ + recog2 = recogCreateFromPixa(pixa1, 0, 0, 5, 128, 1); + recogShowContent(stderr, recog2, 2, 1); + + /* Test recog serialization */ + recogWrite("/tmp/lept/recog/recog2.rec", recog2); + recog3 = recogRead("/tmp/lept/recog/recog2.rec"); + recogWrite("/tmp/lept/recog/recog3.rec", recog3); + filesAreIdentical("/tmp/lept/recog/recog2.rec", + "/tmp/lept/recog/recog3.rec", &same); + if (!same) + lept_stderr("Error in serialization!\n"); + recogDestroy(&recog3); + + /* Remove outliers: method 1 */ + pixa4 = pixaRemoveOutliers1(pixa1, 0.8, 4, 3, &pix1, &pix2); + pixDisplay(pix1, 500, 0); + pixDisplay(pix2, 500, 500); + pixDestroy(&pix1); + pixDestroy(&pix2); + recog3 = recogCreateFromPixa(pixa4, 0, 0, 0, 128, 1); + recogShowContent(stderr, recog3, 3, 1); + pixaDestroy(&pixa4); + recogDestroy(&recog3); + + /* Relabel a few templates to put them in the wrong classes */ + pix1 = pixaGetPix(pixa1, 7, L_CLONE); + pixSetText(pix1, "4"); + pixDestroy(&pix1); + pix1 = pixaGetPix(pixa1, 38, L_CLONE); + pixSetText(pix1, "9"); + pixDestroy(&pix1); + pix1 = pixaGetPix(pixa1, 61, L_CLONE); + pixSetText(pix1, "2"); + pixDestroy(&pix1); + + /* Remove outliers: method 2 */ + pixa4 = pixaRemoveOutliers2(pixa1, 0.65, 3, &pix1, &pix2); + pixDisplay(pix1, 900, 0); + pixDisplay(pix2, 900, 500); + pixDestroy(&pix1); + pixDestroy(&pix2); + recog3 = recogCreateFromPixa(pixa4, 0, 0, 0, 128, 1); + recogShowContent(stderr, recog3, 3, 1); + pixaDestroy(&pixa4); + recogDestroy(&recog3); + + recogDestroy(&recog1); + recogDestroy(&recog2); + pixaDestroy(&pixa1); + pixaDestroy(&pixa2); + pixaDestroy(&pixa3); + return 0; +} diff --git a/leptonica/prog/recogtest4.c b/leptonica/prog/recogtest4.c new file mode 100644 index 00000000..594fe025 --- /dev/null +++ b/leptonica/prog/recogtest4.c @@ -0,0 +1,131 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * recogtest4.c + * + * Test document image decoding (DID) approach to splitting characters + * This tests the low-level recogDecode() function. + * Splitting succeeds for both with and without character height scaling. + * + * But cf. recogtest5.c. Note that recogIdentifyMultiple(), which + * does prefiltering and splitting before character identification, + * does not accept input that has been scaled. That is because + * the only reason for scaling the templates is that the recognizer + * is a hybrid BAR/BSR, where we've used a mixture of templates from + * a single source and bootstrap templates from many sources. + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "string.h" +#include "allheaders.h" + +static PIX *GetBigComponent(PIX *pixs); + + +l_int32 main(int argc, + char **argv) +{ +char buf[256]; +l_int32 i, item; +l_int32 example[6] = {17, 20, 21, 22, 23, 24}; /* for decoding */ +BOXA *boxa; +PIX *pix1, *pix2, *pixdb; +PIXA *pixa1, *pixa2; +L_RECOG *recog; + + if (argc != 1) { + lept_stderr(" Syntax: recogtest4\n"); + return 1; + } + + setLeptDebugOK(1); + lept_mkdir("lept/recog"); + + /* Generate the recognizer */ + pixa1 = pixaRead("recog/sets/train01.pa"); +#if 1 /* scale to fixed height */ + recog = recogCreateFromPixa(pixa1, 0, 40, 0, 128, 1); +#else /* no scaling */ + recog = recogCreateFromPixa(pixa1, 0, 0, 0, 128, 1); +#endif + recogAverageSamples(&recog, 1); + recogWrite("/tmp/lept/recog/rec1.rec", recog); + + /* Show the templates */ + recogDebugAverages(&recog, 1); + if (!recog) { + lept_stderr("Averaging failed!!\n"); + return 1; + } + recogShowMatchesInRange(recog, recog->pixa_tr, 0.0, 1.0, 1); + + /* Get a set of problem images to decode */ + pixa2 = pixaRead("recog/sets/test01.pa"); + + + /* Decode a subset of them. It takes about 1 ms to decode a + * 4 digit number, with both Viterbi and rescoring (debug off). */ + for (i = 0; i < 6; i++) { +/* if (i != 3) continue; */ /* remove this comment to do all 6 */ + item = example[i]; + pix1 = pixaGetPix(pixa2, item, L_CLONE); + pixDisplay(pix1, 100, 100); + pix2 = GetBigComponent(pix1); + boxa = recogDecode(recog, pix2, 2, &pixdb); + pixDisplay(pixdb, 300, 100); + snprintf(buf, sizeof(buf), "/tmp/lept/recog/did-%d.png", item); + pixWrite(buf, pixdb, IFF_PNG); + pixDestroy(&pixdb); + boxaDestroy(&boxa); + pixDestroy(&pix1); + pixDestroy(&pix2); + } + + pixaDestroy(&pixa1); + pixaDestroy(&pixa2); + recogDestroy(&recog); + return 0; +} + +static PIX * +GetBigComponent(PIX *pixs) +{ +BOX *box; +PIX *pix1, *pixd; + + pix1 = pixMorphSequence(pixs, "c40.7 + o20.15 + d25.1", 0); + pixClipToForeground(pix1, NULL, &box); + pixd = pixClipRectangle(pixs, box, NULL); + pixDestroy(&pix1); + boxDestroy(&box); + return pixd; +} + + diff --git a/leptonica/prog/recogtest5.c b/leptonica/prog/recogtest5.c new file mode 100644 index 00000000..6f46c6a9 --- /dev/null +++ b/leptonica/prog/recogtest5.c @@ -0,0 +1,115 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * recogtest5.c + * + * Test document image decoding (DID) approach to splitting characters + * + * This uses recogIdentifyMultiple() to first split the touching + * characters and then do the identification on the resulting + * single characters. Compare with recogtest4.c. + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "string.h" +#include "allheaders.h" + +static PIX *GetBigComponent(PIX *pixs); + + +l_int32 main(int argc, + char **argv) +{ +l_int32 i, item; +l_int32 example[6] = {17, 20, 21, 22, 23, 24}; /* for decoding */ +PIX *pix1, *pix2, *pix3; +PIXA *pixa1, *pixa2, *pixa3; +L_RECOG *recog; + + if (argc != 1) { + lept_stderr(" Syntax: recogtest5\n"); + return 1; + } + + setLeptDebugOK(1); + lept_mkdir("lept/recog"); + + /* Generate the recognizer */ + pixa1 = pixaRead("recog/sets/train01.pa"); + recog = recogCreateFromPixa(pixa1, 0, 0, 0, 128, 1); /* no scaling */ + recogAverageSamples(&recog, 1); + recogWrite("/tmp/lept/recog/rec1.rec", recog); + + /* Show the templates */ + recogDebugAverages(&recog, 1); + recogShowMatchesInRange(recog, recog->pixa_tr, 0.0, 1.0, 1); + + /* Get a set of problem images to decode */ + pixa2 = pixaRead("recog/sets/test01.pa"); + + /* Decode a subset of them. It takes about 2 ms to decode a + * 4 digit number (Viterbi for splitting; identification against + * all templates; debug off. */ + for (i = 0; i < 6; i++) { +/* if (i != 3) continue; */ /* remove this comment to do all 6 */ + item = example[i]; + pix1 = pixaGetPix(pixa2, item, L_CLONE); + pixDisplay(pix1, 100, 100); + pix2 = GetBigComponent(pix1); + recogIdentifyMultiple(recog, pix2, 0, 0, NULL, &pixa3, NULL, 1); + pix3 = pixaDisplayTiledInColumns(pixa3, 1, 1.0, 20, 2); + pixDisplay(pix3, 800, 100); + pixDestroy(&pix1); + pixDestroy(&pix2); + pixDestroy(&pix3); + pixaDestroy(&pixa3); + } + + pixaDestroy(&pixa1); + pixaDestroy(&pixa2); + recogDestroy(&recog); + return 0; +} + +static PIX * +GetBigComponent(PIX *pixs) +{ +BOX *box; +PIX *pix1, *pixd; + + pix1 = pixMorphSequence(pixs, "c40.7 + o20.15 + d25.1", 0); + pixClipToForeground(pix1, NULL, &box); + pixd = pixClipRectangle(pixs, box, NULL); + pixDestroy(&pix1); + boxDestroy(&box); + return pixd; +} + + diff --git a/leptonica/prog/recogtest6.c b/leptonica/prog/recogtest6.c new file mode 100644 index 00000000..9efcc9ec --- /dev/null +++ b/leptonica/prog/recogtest6.c @@ -0,0 +1,134 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * recogtest6.c + * + * Another test of character splitting. This will test both DID + * and greedy splitting. To test greedy splitting, in recogident.c, + * #define SPLIT_WITH_DID 0 + * + * The timing info is used to measure the time to split touching + * characters and identify them. One set of 4 digits takes about 1 ms + * with DID and 7 ms with greedy splitting. Because DID is about + * 5x faster than greedy splitting, DID is the default that is used. + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "string.h" +#include "allheaders.h" + +static PIX *GetBigComponent(PIX *pixs); + + +l_int32 main(int argc, + char **argv) +{ +l_int32 item, debug, i; +l_int32 example[6] = {17, 20, 21, 22, 23, 24}; /* for decoding */ +BOXA *boxa; +NUMA *nascore; +PIX *pix1, *pix2, *pix3, *pixdb; +PIXA *pixa1, *pixa2; +L_RECOG *recog; + + if (argc != 1) { + lept_stderr(" Syntax: recogtest6\n"); + return 1; + } + + setLeptDebugOK(1); + lept_mkdir("lept/recog"); + + /* Generate the recognizer */ + pixa1 = pixaRead("recog/sets/train01.pa"); + recog = recogCreateFromPixa(pixa1, 0, 0, 0, 128, 1); + recogAverageSamples(&recog, 0); + + /* Show the templates */ + recogDebugAverages(&recog, 1); + recogShowMatchesInRange(recog, recog->pixa_tr, 0.0, 1.0, 1); + + /* Get a set of problem images to decode */ + pixa2 = pixaRead("recog/sets/test01.pa"); + + /* Decode a subset of them */ + debug = 1; + for (i = 0; i < 6; i++) { +/* if (i != 3) continue; */ + item = example[i]; + pix1 = pixaGetPix(pixa2, item, L_CLONE); + pixDisplay(pix1, 100, 100); + pix2 = GetBigComponent(pix1); + if (debug) { + recogIdentifyMultiple(recog, pix2, 0, 0, &boxa, NULL, &pixdb, 1); + rchaExtract(recog->rcha, NULL, &nascore, NULL, NULL, + NULL, NULL, NULL); + pixDisplay(pixdb, 300, 500); + boxaWriteStream(stderr, boxa); + numaWriteStream(stderr, nascore); + numaDestroy(&nascore); + pixDestroy(&pixdb); + } else { /* just get the timing */ + startTimer(); + recogIdentifyMultiple(recog, pix2, 0, 0, &boxa, NULL, NULL, 0); + lept_stderr("Time: %5.3f\n", stopTimer()); + } + pixDestroy(&pix1); + pixDestroy(&pix2); + boxaDestroy(&boxa); + } + if (debug) { + pix3 = pixaDisplayTiledInRows(recog->pixadb_split, 1, 200, + 1.0, 0, 20, 3); + pixDisplay(pix3, 0, 0); + pixDestroy(&pix3); + } + + pixaDestroy(&pixa1); + pixaDestroy(&pixa2); + recogDestroy(&recog); + return 0; +} + + +static PIX * +GetBigComponent(PIX *pixs) +{ +BOX *box; +PIX *pix1, *pixd; + + pix1 = pixMorphSequence(pixs, "c40.7 + o20.15 + d25.1", 0); + pixClipToForeground(pix1, NULL, &box); + pixd = pixClipRectangle(pixs, box, NULL); + pixDestroy(&pix1); + boxDestroy(&box); + return pixd; +} + diff --git a/leptonica/prog/recogtest7.c b/leptonica/prog/recogtest7.c new file mode 100644 index 00000000..575aae36 --- /dev/null +++ b/leptonica/prog/recogtest7.c @@ -0,0 +1,144 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * recogtest7.c + * + * Tests the boot recog utility using the bootstrap templates + * from the mosaics (bootnum4.pa) and from the stringcode version + * (bootnumgen4.c). + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "string.h" +#include "allheaders.h" + + /* All input templates are scaled to 20x30. Here, we rescale the + * height to 45 and let the width scale isotropically. */ +static const l_int32 scaledw = 0; +static const l_int32 scaledh = 45; + +l_int32 main(int argc, + char **argv) +{ +l_int32 same; +PIX *pix1, *pix2, *pix3; +PIXA *pixa1, *pixa2, *pixa3; +L_RECOG *recog1, *recog2; + + PROCNAME("recogtest7"); + + if (argc != 1) { + lept_stderr(" Syntax: recogtest7\n"); + return 1; + } + + setLeptDebugOK(1); + lept_mkdir("lept/digits"); + recog1 = NULL; + recog2 = NULL; + +#if 1 + pixa1 = pixaRead("recog/digits/bootnum4.pa"); + pixa2 = pixaMakeFromTiledPixa(pixa1, 0, 0, 100); + pixa3 = l_bootnum_gen4(100); + pixaEqual(pixa2, pixa3, 0, NULL, &same); + if (!same) L_ERROR("Bad! The pixa differ!\n", procName); + pix1 = pixaDisplayTiledWithText(pixa1, 1400, 1.0, 10, 2, 6, 0xff000000); + pixDisplay(pix1, 100, 100); + pix2 = pixaDisplayTiledWithText(pixa2, 1400, 1.0, 10, 2, 6, 0xff000000); + pix3 = pixaDisplayTiledWithText(pixa3, 1400, 1.0, 10, 2, 6, 0xff000000); + pixEqual(pix2, pix3, &same); + if (!same) L_ERROR("Bad! The displayed pix differ!\n", procName); + pixWrite("/tmp/lept/digits/pix1.png", pix1, IFF_PNG); + pixWrite("/tmp/lept/digits/bootnum4.png", pix1, IFF_PNG); + pixaDestroy(&pixa1); + pixaDestroy(&pixa2); + pixDestroy(&pix1); + pixDestroy(&pix2); + pixDestroy(&pix3); +#endif + +#if 1 + lept_stderr("Show recog content\n"); + recog1 = recogCreateFromPixa(pixa3, scaledw, scaledh, 0, 120, 1); + recogShowContent(stderr, recog1, 1, 1); + pixaDestroy(&pixa3); +#endif + +#if 1 + lept_stderr("\nShow averaged samples\n"); + recogAverageSamples(&recog1, 1); + recogShowAverageTemplates(recog1); + pix1 = pixaGetPix(recog1->pixadb_ave, 0, L_CLONE); + pixWrite("/tmp/lept/digits/unscaled_ave.png", pix1, IFF_PNG); + pixDestroy(&pix1); + pix1 = pixaGetPix(recog1->pixadb_ave, 1, L_CLONE); + pixWrite("/tmp/lept/digits/scaled_ave.png", pix1, IFF_PNG); + pixDestroy(&pix1); + recogDestroy(&recog1); +#endif + +#if 1 + /* Make a tiny recognizer and test it against itself */ + pixa1 = l_bootnum_gen4(5); + pix1 = pixaDisplayTiledWithText(pixa1, 1400, 1.0, 10, 2, 6, 0xff000000); + pixDisplay(pix1, 1000, 100); + pixDestroy(&pix1); + recog1 = recogCreateFromPixa(pixa1, scaledw, scaledh, 0, 120, 1); + lept_stderr("\nShow matches against all inputs for given range\n"); + recogDebugAverages(&recog1, 0); + recogShowMatchesInRange(recog1, recog1->pixa_tr, 0.85, 1.00, 1); + pixWrite("/tmp/lept/digits/match_input.png", recog1->pixdb_range, IFF_PNG); + lept_stderr("\nShow best match against average template\n"); + recogShowMatchesInRange(recog1, recog1->pixa_u, 0.65, 1.00, 1); + pixWrite("/tmp/lept/digits/match_ave.png", recog1->pixdb_range, IFF_PNG); + pixaDestroy(&pixa1); +#endif + +#if 1 + lept_stderr("\nContents of recog before write/read:\n"); + recogShowContent(stderr, recog1, 2, 1); + + lept_stderr("\nTest serialization\n"); + recogWrite("/tmp/lept/digits/rec1.rec", recog1); + recog2 = recogRead("/tmp/lept/digits/rec1.rec"); + lept_stderr("Contents of recog after write/read:\n"); + recogShowContent(stderr, recog2, 3, 1); + recogWrite("/tmp/lept/digits/rec2.rec", recog2); + filesAreIdentical("/tmp/lept/digits/rec1.rec", + "/tmp/lept/digits/rec2.rec", &same); + if (!same) + lept_stderr("Error in serialization!\n"); + recogDestroy(&recog1); + recogDestroy(&recog2); +#endif + + return 0; +} diff --git a/leptonica/prog/rectangle_reg.c b/leptonica/prog/rectangle_reg.c new file mode 100644 index 00000000..cfbdcb24 --- /dev/null +++ b/leptonica/prog/rectangle_reg.c @@ -0,0 +1,182 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * rectangle_reg.c + * + * Tests the largest rectangle in bg or fg. + * + * Also tests finding rectangles associated with single + * connected components. + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include <string.h> +#include "allheaders.h" + +static const l_int32 NBoxes = 20; +static const l_int32 Polarity = 0; /* background */ + +int main(int argc, + char **argv) +{ +char buf[64]; +char *newpath; +l_int32 i, bx, by, bw, bh, index, rval, gval, bval; +BOX *box1, *box2; +BOXA *boxa; +PIX *pixs, *pix1, *pix2, *pix3; +PIXCMAP *cmap; +L_REGPARAMS *rp; + + if (regTestSetup(argc, argv, &rp)) + return 1; + + /* ---------------- Largest rectangles in image ---------------- */ + pixs = pixRead("test1.png"); + pix1 = pixConvertTo8(pixs, FALSE); + cmap = pixcmapCreateRandom(8, 1, 1); + pixSetColormap(pix1, cmap); + + boxa = boxaCreate(0); + for (i = 0; i < NBoxes; i++) { + pixFindLargestRectangle(pixs, Polarity, &box1, NULL); + boxGetGeometry(box1, &bx, &by, &bw, &bh); + pixSetInRect(pixs, box1); + if (rp->display) + lept_stderr("bx = %5d, by = %5d, bw = %5d, bh = %5d, area = %d\n", + bx, by, bw, bh, bw * bh); + boxaAddBox(boxa, box1, L_INSERT); + } + + for (i = 0; i < NBoxes; i++) { + index = 32 + (i & 254); + pixcmapGetColor(cmap, index, &rval, &gval, &bval); + box1 = boxaGetBox(boxa, i, L_CLONE); + pixRenderHashBoxArb(pix1, box1, 6, 2, L_NEG_SLOPE_LINE, 1, + rval, gval, bval); + boxDestroy(&box1); + } + pix2 = pixAddBorder(pix1, 2, 0x0); + pix3 = pixAddBorder(pix2, 20, 0xffffff00); + regTestWritePixAndCheck(rp, pix3, IFF_PNG); /* 0 */ + pixDisplayWithTitle(pix3, 0, 0, NULL, rp->display); + pixDestroy(&pixs); + pixDestroy(&pix1); + pixDestroy(&pix2); + pixDestroy(&pix3); + boxaDestroy(&boxa); + + /* ----------- Rectangle(s) from connected component ----------- */ + pixs = pixRead("singlecc.tif"); + pix1 = pixScale(pixs, 0.5, 0.5); + boxa = pixConnCompBB(pix1, 8); + box1 = boxaGetBox(boxa, 0, L_COPY); + + /* Do 4 cases with vertical scan */ + box2 = pixFindRectangleInCC(pix1, box1, 0.75, L_SCAN_VERTICAL, + L_GEOMETRIC_UNION, TRUE); + boxDestroy(&box2); + snprintf(buf, sizeof(buf), "rectangle.%02d.png", 2); + lept_cp("/tmp/lept/rect/fitrect.png", "lept/regout", buf, &newpath); + regTestCheckFile(rp, newpath); /* 1 */ + if (rp->display) l_fileDisplay(newpath, 0, 500, 0.4); + lept_free(newpath); + + box2 = pixFindRectangleInCC(pix1, box1, 0.75, L_SCAN_VERTICAL, + L_GEOMETRIC_INTERSECTION, TRUE); + boxDestroy(&box2); + snprintf(buf, sizeof(buf), "rectangle.%02d.png", 3); + lept_cp("/tmp/lept/rect/fitrect.png", "lept/regout", buf, &newpath); + regTestCheckFile(rp, newpath); /* 2 */ + if (rp->display) l_fileDisplay(newpath, 200, 500, 0.4); + lept_free(newpath); + + box2 = pixFindRectangleInCC(pix1, box1, 0.75, L_SCAN_VERTICAL, + L_LARGEST_AREA, TRUE); + boxDestroy(&box2); + snprintf(buf, sizeof(buf), "rectangle.%02d.png", 4); + lept_cp("/tmp/lept/rect/fitrect.png", "lept/regout", buf, &newpath); + regTestCheckFile(rp, newpath); /* 3 */ + if (rp->display) l_fileDisplay(newpath, 400, 500, 0.4); + lept_free(newpath); + + box2 = pixFindRectangleInCC(pix1, box1, 0.75, L_SCAN_VERTICAL, + L_SMALLEST_AREA, TRUE); + boxDestroy(&box2); + snprintf(buf, sizeof(buf), "rectangle.%02d.png", 5); + lept_cp("/tmp/lept/rect/fitrect.png", "lept/regout", buf, &newpath); + regTestCheckFile(rp, newpath); /* 4 */ + if (rp->display) l_fileDisplay(newpath, 600, 500, 0.4); + lept_free(newpath); + + /* Do 4 cases with horizontal scan */ + box2 = pixFindRectangleInCC(pix1, box1, 0.75, L_SCAN_HORIZONTAL, + L_GEOMETRIC_UNION, TRUE); + boxDestroy(&box2); + snprintf(buf, sizeof(buf), "rectangle.%02d.png", 6); + lept_cp("/tmp/lept/rect/fitrect.png", "lept/regout", buf, &newpath); + regTestCheckFile(rp, newpath); /* 5 */ + if (rp->display) l_fileDisplay(newpath, 800, 500, 0.4); + lept_free(newpath); + + box2 = pixFindRectangleInCC(pix1, box1, 0.75, L_SCAN_HORIZONTAL, + L_GEOMETRIC_INTERSECTION, TRUE); + boxDestroy(&box2); + snprintf(buf, sizeof(buf), "rectangle.%02d.png", 7); + lept_cp("/tmp/lept/rect/fitrect.png", "lept/regout", buf, &newpath); + regTestCheckFile(rp, newpath); /* 6 */ + if (rp->display) l_fileDisplay(newpath, 1000, 500, 0.4); + lept_free(newpath); + + box2 = pixFindRectangleInCC(pix1, box1, 0.75, L_SCAN_HORIZONTAL, + L_LARGEST_AREA, TRUE); + boxDestroy(&box2); + snprintf(buf, sizeof(buf), "rectangle.%02d.png", 8); + lept_cp("/tmp/lept/rect/fitrect.png", "lept/regout", buf, &newpath); + regTestCheckFile(rp, newpath); /* 7 */ + if (rp->display) l_fileDisplay(newpath, 1200, 500, 0.4); + lept_free(newpath); + + box2 = pixFindRectangleInCC(pix1, box1, 0.75, L_SCAN_HORIZONTAL, + L_SMALLEST_AREA, TRUE); + boxDestroy(&box2); + snprintf(buf, sizeof(buf), "rectangle.%02d.png", 9); + lept_cp("/tmp/lept/rect/fitrect.png", "lept/regout", buf, &newpath); + regTestCheckFile(rp, newpath); /* 8 */ + if (rp->display) l_fileDisplay(newpath, 1400, 500, 0.4); + lept_free(newpath); + + boxDestroy(&box1); + pixDestroy(&pixs); + pixDestroy(&pix1); + boxaDestroy(&boxa); + return regTestCleanup(rp); +} + diff --git a/leptonica/prog/redcover.jpg b/leptonica/prog/redcover.jpg Binary files differnew file mode 100644 index 00000000..5628ee9e --- /dev/null +++ b/leptonica/prog/redcover.jpg diff --git a/leptonica/prog/reducetest.c b/leptonica/prog/reducetest.c new file mode 100644 index 00000000..7e60d64f --- /dev/null +++ b/leptonica/prog/reducetest.c @@ -0,0 +1,75 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * reducetest.c + * + * Carries out a rank binary cascade of up to four 2x reductions. + * This requires all four rank levels to be input; to stop the + * cascade, use 0 for the final rank level(s). + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + +int main(int argc, + char **argv) +{ +PIX *pixs, *pixd; +l_int32 level1, level2, level3, level4; +char *filein, *fileout; +static char mainName[] = "reducetest"; + + if (argc != 7) + return ERROR_INT(" Syntax: reducetest filein fileout l1 l2 l3 l4", + mainName, 1); + filein = argv[1]; + fileout = argv[2]; + level1 = atoi(argv[3]); + level2 = atoi(argv[4]); + level3 = atoi(argv[5]); + level4 = atoi(argv[6]); + setLeptDebugOK(1); + + if ((pixs = pixRead(filein)) == NULL) + return ERROR_INT("pixs not made", mainName, 1); + +#if 1 + pixd = pixReduceRankBinaryCascade(pixs, level1, level2, level3, level4); +#endif + +#if 0 + pixd = pixReduce2(pixs, NULL); +#endif + + pixWrite(fileout, pixd, IFF_PNG); + + return 0; +} + diff --git a/leptonica/prog/reg_wrapper.sh b/leptonica/prog/reg_wrapper.sh new file mode 100755 index 00000000..38502f5b --- /dev/null +++ b/leptonica/prog/reg_wrapper.sh @@ -0,0 +1,48 @@ +#!/bin/sh +# +# This testing wrapper was written by James Le Cuirot. +# +# It runs all the programs in AUTO_REG_PROGS in Makefile.am +# when the command 'make check' is invoked. This same set can +# be run by doing: +# alltests_reg generate +# alltests_reg compare +# +# Some of the tests require gnuplot. These tests, listed below, +# are skipped if gnuplot is not available. You can determine if a +# test requires gnuplot, if any of these situations is true: +# * a function starting with "gplot" is called +# * a function starting with "boxaPlot" is called +# * a function starting with "pixCompare" is called +# * the function pixItalicWords() is called +# * the function pixWordMaskByDilation() is called +# +# The wrapper receives several parameters in this form: +# path/to/source/config/test-driver <TEST DRIVER ARGS> -- ./foo_reg +# +# Shell trickery is used to strip off the final parameter and +# transform the invocation into this. +# path/to/source/config/test-driver <TEST DRIVER ARGS> +# -- /bin/sh -c "cd \"path/to/source/prog\" && +# \"path/to/build/prog/\"./foo_reg generate && +# \"path/to/build/prog/\"./foo_reg compare" +# +# This also allows testing when you build in a different directory +# from the install directory, and the logs still get written to +# the build directory. + +eval TEST=\${${#}} + +TEST_NAME="${TEST##*/}" +TEST_NAME="${TEST_NAME%_reg*}" + +case "${TEST_NAME}" in + baseline|boxa[1234]|colormask|colorspace|crop|dna|enhance|extrema|fpix1|hash|italic|kernel|nearline|numa[123]|pixa1|projection|rank|rankbin|rankhisto|wordboxes) + GNUPLOT=$(which gnuplot || which wgnuplot) + + if [ -z "${GNUPLOT}" ] || ! "${GNUPLOT}" -e "set terminal png" 2>/dev/null ; then + exec ${@%${TEST}} /bin/sh -c "exit 77" + fi +esac + +exec ${@%${TEST}} /bin/sh -c "cd \"${srcdir}\" && \"${PWD}/\"${TEST} generate && \"${PWD}/\"${TEST} compare" diff --git a/leptonica/prog/removecmap.c b/leptonica/prog/removecmap.c new file mode 100644 index 00000000..7244da5d --- /dev/null +++ b/leptonica/prog/removecmap.c @@ -0,0 +1,80 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * removecmap.c + * + * removecmap filein type fileout + * + * type: 1 for conversion to 8 bpp gray + * 2 for conversion to 24 bpp full color + * 3 for conversion depending on src + * + * Removes the colormap and does the conversion + * Works on palette images of 2, 4 and 8 bpp + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + +int main(int argc, + char **argv) +{ +char *filein, *fileout; +l_int32 type, numcolors; +PIX *pixs, *pixd; +PIXCMAP *cmap; +static char mainName[] = "removecmap"; + + if (argc != 4) + return ERROR_INT("Syntax: removecmap filein type fileout", + mainName, 1); + filein = argv[1]; + type = atoi(argv[2]); + fileout = argv[3]; + setLeptDebugOK(1); + + if ((pixs = pixRead(filein)) == NULL) + return ERROR_INT("pixs not made", mainName, 1); + + lept_stderr(" depth = %d\n", pixGetDepth(pixs)); + if ((cmap = pixGetColormap(pixs)) != NULL) { + numcolors = pixcmapGetCount(cmap); + pixcmapWriteStream(stderr, cmap); + lept_stderr(" colormap found; num colors = %d\n", numcolors); + } else { + lept_stderr(" no colormap\n"); + } + + pixd = pixRemoveColormap(pixs, type); + pixWrite(fileout, pixd, IFF_PNG); + pixDestroy(&pixs); + pixDestroy(&pixd); + return 0; +} diff --git a/leptonica/prog/renderfonts.c b/leptonica/prog/renderfonts.c new file mode 100644 index 00000000..f73f6451 --- /dev/null +++ b/leptonica/prog/renderfonts.c @@ -0,0 +1,103 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * renderfonts.c + * + * This tests the font rendering functions + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + +#define DIRECTORY "./fonts" + +int main(int argc, + char **argv) +{ +char *textstr; +l_int32 width, wtext, overflow; +L_BMF *bmf; +PIX *pixs, *pix; +static char mainName[] = "renderfonts"; + + if (argc != 1) + return ERROR_INT("Syntax: renderfonts", mainName, 1); + + setLeptDebugOK(1); + lept_mkdir("lept/render"); + + /* Render a character of text */ + bmf = bmfCreate(DIRECTORY, 20); + pixs = pixRead("dreyfus8.png"); + lept_stderr("n = %d\n", pixaGetCount(bmf->pixa)); + pix = pixaGetPix(bmf->pixa, 6, L_CLONE); + pixSetMaskedGeneral(pixs, pix, 0x45, 140, 165); + pixWrite("/tmp/lept/render/char.png", pixs, IFF_PNG); + pixDisplay(pixs, 0, 0); + pixDestroy(&pix); + pixDestroy(&pixs); + bmfDestroy(&bmf); + + /* Render a line of text */ + bmf = bmfCreate(DIRECTORY, 8); + pixs = pixRead("marge.jpg"); + bmfGetStringWidth(bmf, "This is a funny cat!", &width); + lept_stderr("String width: %d pixels\n", width); + + pixSetTextline(pixs, bmf, "This is a funny cat!", 0x4080ff00, 50, 250, + &width, &overflow); + pixWrite("/tmp/lept/render/line.png", pixs, IFF_JFIF_JPEG); + pixDisplay(pixs, 450, 0); + lept_stderr("Text width = %d\n", width); + if (overflow) + lept_stderr("Text overflow beyond image boundary\n"); + pixDestroy(&pixs); + bmfDestroy(&bmf); + + /* Render a block of text */ + bmf = bmfCreate(DIRECTORY, 10); + pixs = pixRead("marge.jpg"); + textstr = stringNew("This is a cat! This is a funny cat! " + "This is a funny funny cat! This is a " + "funny funny funny cat!"); + + wtext = pixGetWidth(pixs) - 70; + pixSetTextblock(pixs, bmf, textstr, 0x90804000, 50, 50, wtext, + 1, &overflow); + pixWrite("/tmp/lept/render/block.png", pixs, IFF_JFIF_JPEG); + pixDisplay(pixs, 0, 500); + if (overflow) + lept_stderr("Text overflow beyond image boundary\n"); + lept_free(textstr); + pixDestroy(&pixs); + bmfDestroy(&bmf); + return 0; +} + diff --git a/leptonica/prog/replacebytes.c b/leptonica/prog/replacebytes.c new file mode 100644 index 00000000..6e993e30 --- /dev/null +++ b/leptonica/prog/replacebytes.c @@ -0,0 +1,82 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * replacebytes.c + * + * Replaces the specified set of bytes in a file by the bytes in + * the input string. The general invocation is: + * relacebytes <filein> <start> <nbytes> <string> <fileout> + * where <start> is the start location in the file to begin replacing, + * <nbytes> is the number of bytes to be removed from the input, + * beginning at the start location, and + * <string> is the replacement string. + * + * To simply remove <nbytes> without replacing: + * relacebytes <filein> <start> <nbytes> <fileout> + * + * One use of the general case is for replacing the date/time in a + * pdf file by a string of 12 '0's. This removes the date without + * invalidating the byte counters: + * replacebytes <filein.pdf> 86 12 000000000000 <outfile.pdf> + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" +#include "string.h" + +int main(int argc, + char **argv) +{ +l_int32 start, nbytes; +char *filein, *fileout, *newstr; +static char mainName[] = "replacebytes"; + + if (argc != 5 && argc != 6) + return ERROR_INT( + "syntax: replacebytes filein start nbytes [string] fileout", + mainName, 1); + filein = argv[1]; + start = atof(argv[2]); + nbytes = atof(argv[3]); + if (argc == 5) { + fileout = argv[4]; + } else { + newstr = argv[4]; + fileout = argv[5]; + } + + if (argc == 5) { + return fileReplaceBytes(filein, start, nbytes, NULL, 0, fileout); + } else { /* argc == 6 */ + return fileReplaceBytes(filein, start, nbytes, (l_uint8 *)newstr, + strlen(newstr), fileout); + } +} + diff --git a/leptonica/prog/rgb16.tif b/leptonica/prog/rgb16.tif Binary files differnew file mode 100644 index 00000000..8b4e4e0f --- /dev/null +++ b/leptonica/prog/rgb16.tif diff --git a/leptonica/prog/rock.png b/leptonica/prog/rock.png Binary files differnew file mode 100644 index 00000000..e7c084eb --- /dev/null +++ b/leptonica/prog/rock.png diff --git a/leptonica/prog/rotate1_reg.c b/leptonica/prog/rotate1_reg.c new file mode 100644 index 00000000..536e0ee0 --- /dev/null +++ b/leptonica/prog/rotate1_reg.c @@ -0,0 +1,195 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * rotate1_reg.c + * + * Regression test for rotation by shear and area mapping. + * Displays results when images are rotated sequentially multiple times. + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + +#define BINARY_IMAGE "test1.png" +#define TWO_BPP_IMAGE "weasel2.4c.png" +#define FOUR_BPP_IMAGE1 "weasel4.11c.png" +#define FOUR_BPP_IMAGE2 "weasel4.16g.png" +#define EIGHT_BPP_IMAGE "test8.jpg" +#define EIGHT_BPP_CMAP_IMAGE1 "dreyfus8.png" +#define EIGHT_BPP_CMAP_IMAGE2 "test24.jpg" +#define RGB_IMAGE "marge.jpg" + +static const l_int32 MODSIZE = 11; /* set to 11 for display */ + +static const l_float32 ANGLE1 = 3.14159265 / 12.; +static const l_float32 ANGLE2 = 3.14159265 / 120.; +static const l_int32 NTIMES = 24; + +static void RotateTest(PIX *pixs, l_float32 scale, L_REGPARAMS *rp); + + +l_int32 main(int argc, + char **argv) +{ +PIX *pixs, *pixd; +L_REGPARAMS *rp; + + if (regTestSetup(argc, argv, &rp)) + return 1; + + lept_stderr("Test binary image:\n"); + pixs = pixRead(BINARY_IMAGE); + RotateTest(pixs, 1.0, rp); + pixDestroy(&pixs); + + lept_stderr("Test 2 bpp cmapped image with filled cmap:\n"); + pixs = pixRead(TWO_BPP_IMAGE); + RotateTest(pixs, 1.0, rp); + pixDestroy(&pixs); + + lept_stderr("Test 4 bpp cmapped image with unfilled cmap:\n"); + pixs = pixRead(FOUR_BPP_IMAGE1); + RotateTest(pixs, 1.0, rp); + pixDestroy(&pixs); + + lept_stderr("Test 4 bpp cmapped image with filled cmap:\n"); + pixs = pixRead(FOUR_BPP_IMAGE2); + RotateTest(pixs, 1.0, rp); + pixDestroy(&pixs); + + lept_stderr("Test 8 bpp grayscale image:\n"); + pixs = pixRead(EIGHT_BPP_IMAGE); + RotateTest(pixs, 1.0, rp); + pixDestroy(&pixs); + + lept_stderr("Test 8 bpp grayscale cmap image:\n"); + pixs = pixRead(EIGHT_BPP_CMAP_IMAGE1); + RotateTest(pixs, 1.0, rp); + pixDestroy(&pixs); + + lept_stderr("Test 8 bpp color cmap image:\n"); + pixs = pixRead(EIGHT_BPP_CMAP_IMAGE2); + pixd = pixOctreeColorQuant(pixs, 200, 0); + RotateTest(pixs, 0.25, rp); + pixDestroy(&pixs); + pixDestroy(&pixd); + + lept_stderr("Test rgb image:\n"); + pixs = pixRead(RGB_IMAGE); + RotateTest(pixs, 1.0, rp); + pixDestroy(&pixs); + + return regTestCleanup(rp); +} + + +static void +RotateTest(PIX *pixs, + l_float32 scale, + L_REGPARAMS *rp) +{ +l_int32 w, h, d, i, outformat; +PIX *pixt, *pixd; +PIXA *pixa; + + pixa = pixaCreate(0); + pixGetDimensions(pixs, &w, &h, &d); + outformat = (d == 8 || d == 32) ? IFF_JFIF_JPEG : IFF_PNG; + pixd = pixRotate(pixs, ANGLE1, L_ROTATE_SHEAR, L_BRING_IN_WHITE, w, h); + for (i = 1; i < NTIMES; i++) { + if ((i % MODSIZE) == 0) { + pixaAddPix(pixa, pixd, L_COPY); + regTestWritePixAndCheck(rp, pixd, outformat); + } + pixt = pixRotate(pixd, ANGLE1, L_ROTATE_SHEAR, + L_BRING_IN_WHITE, w, h); + pixDestroy(&pixd); + pixd = pixt; + } + pixDestroy(&pixd); + + pixd = pixRotate(pixs, ANGLE1, L_ROTATE_SAMPLING, L_BRING_IN_WHITE, w, h); + for (i = 1; i < NTIMES; i++) { + if ((i % MODSIZE) == 0) { + pixaAddPix(pixa, pixd, L_COPY); + regTestWritePixAndCheck(rp, pixd, outformat); + } + pixt = pixRotate(pixd, ANGLE1, L_ROTATE_SAMPLING, + L_BRING_IN_WHITE, w, h); + pixDestroy(&pixd); + pixd = pixt; + } + pixDestroy(&pixd); + + pixd = pixRotate(pixs, ANGLE1, L_ROTATE_AREA_MAP, L_BRING_IN_WHITE, w, h); + for (i = 1; i < NTIMES; i++) { + if ((i % MODSIZE) == 0) { + pixaAddPix(pixa, pixd, L_COPY); + regTestWritePixAndCheck(rp, pixd, outformat); + } + pixt = pixRotate(pixd, ANGLE1, L_ROTATE_AREA_MAP, + L_BRING_IN_WHITE, w, h); + pixDestroy(&pixd); + pixd = pixt; + } + pixDestroy(&pixd); + + pixd = pixRotateAMCorner(pixs, ANGLE2, L_BRING_IN_WHITE); + for (i = 1; i < NTIMES; i++) { + if ((i % MODSIZE) == 0) { + pixaAddPix(pixa, pixd, L_COPY); + regTestWritePixAndCheck(rp, pixd, outformat); + } + pixt = pixRotateAMCorner(pixd, ANGLE2, L_BRING_IN_WHITE); + pixDestroy(&pixd); + pixd = pixt; + } + pixDestroy(&pixd); + + if (d == 32) { + pixd = pixRotateAMColorFast(pixs, ANGLE1, 0xb0ffb000); + for (i = 1; i < NTIMES; i++) { + if ((i % MODSIZE) == 0) { + pixaAddPix(pixa, pixd, L_COPY); + regTestWritePixAndCheck(rp, pixd, outformat); + } + pixt = pixRotateAMColorFast(pixd, ANGLE1, 0xb0ffb000); + pixDestroy(&pixd); + pixd = pixt; + } + } + pixDestroy(&pixd); + + pixd = pixaDisplayTiledInColumns(pixa, 2, scale, 20, 0); + pixDisplayWithTitle(pixd, 100, 100, NULL, rp->display); + pixDestroy(&pixd); + pixaDestroy(&pixa); + return; +} diff --git a/leptonica/prog/rotate2_reg.c b/leptonica/prog/rotate2_reg.c new file mode 100644 index 00000000..7e6b4865 --- /dev/null +++ b/leptonica/prog/rotate2_reg.c @@ -0,0 +1,175 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * rotate2_reg.c + * + * Regression test for rotation by shear, sampling and area mapping. + * Displays results from all the various types of rotations. + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + +#define BINARY_IMAGE "test1.png" +#define TWO_BPP_IMAGE "weasel2.4c.png" +#define FOUR_BPP_IMAGE1 "weasel4.11c.png" +#define FOUR_BPP_IMAGE2 "weasel4.16g.png" +#define EIGHT_BPP_IMAGE "test8.jpg" +#define EIGHT_BPP_CMAP_IMAGE1 "dreyfus8.png" +#define EIGHT_BPP_CMAP_IMAGE2 "test24.jpg" +#define RGB_IMAGE "marge.jpg" + +static const l_float32 ANGLE1 = 3.14159265 / 30.; +static const l_float32 ANGLE2 = 3.14159265 / 7.; + +void RotateTest(PIX *pixs, l_float32 scale, L_REGPARAMS *rp); + + +int main(int argc, + char **argv) +{ +PIX *pixs, *pixd; +L_REGPARAMS *rp; + + if (regTestSetup(argc, argv, &rp)) + return 1; + + lept_stderr("Test binary image:\n"); + pixs = pixRead(BINARY_IMAGE); + RotateTest(pixs, 1.0, rp); + pixDestroy(&pixs); + + lept_stderr("Test 2 bpp cmapped image with filled cmap:\n"); + pixs = pixRead(TWO_BPP_IMAGE); + RotateTest(pixs, 1.0, rp); + pixDestroy(&pixs); + + lept_stderr("Test 4 bpp cmapped image with unfilled cmap:\n"); + pixs = pixRead(FOUR_BPP_IMAGE1); + RotateTest(pixs, 1.0, rp); + pixDestroy(&pixs); + + lept_stderr("Test 4 bpp cmapped image with filled cmap:\n"); + pixs = pixRead(FOUR_BPP_IMAGE2); + RotateTest(pixs, 1.0, rp); + pixDestroy(&pixs); + + lept_stderr("Test 8 bpp grayscale image:\n"); + pixs = pixRead(EIGHT_BPP_IMAGE); + RotateTest(pixs, 1.0, rp); + pixDestroy(&pixs); + + lept_stderr("Test 8 bpp grayscale cmap image:\n"); + pixs = pixRead(EIGHT_BPP_CMAP_IMAGE1); + RotateTest(pixs, 1.0, rp); + pixDestroy(&pixs); + + lept_stderr("Test 8 bpp color cmap image:\n"); + pixs = pixRead(EIGHT_BPP_CMAP_IMAGE2); + pixd = pixOctreeColorQuant(pixs, 200, 0); + RotateTest(pixd, 0.5, rp); + pixDestroy(&pixs); + pixDestroy(&pixd); + + lept_stderr("Test rgb image:\n"); + pixs = pixRead(RGB_IMAGE); + RotateTest(pixs, 0.25, rp); + pixDestroy(&pixs); + + return regTestCleanup(rp); +} + + +void +RotateTest(PIX *pixs, + l_float32 scale, + L_REGPARAMS *rp) +{ +l_int32 w, h, d, outformat; +PIX *pix1, *pix2, *pix3, *pixd; +PIXA *pixa; + + pixGetDimensions(pixs, &w, &h, &d); + outformat = (d == 8 || d == 32) ? IFF_JFIF_JPEG : IFF_PNG; + + pixa = pixaCreate(0); + pix1 = pixRotate(pixs, ANGLE1, L_ROTATE_SHEAR, L_BRING_IN_WHITE, w, h); + pixaAddPix(pixa, pix1, L_INSERT); + pix2 = pixRotate(pixs, ANGLE1, L_ROTATE_SHEAR, L_BRING_IN_BLACK, w, h); + pixaAddPix(pixa, pix2, L_INSERT); + pix1 = pixRotate(pixs, ANGLE1, L_ROTATE_SHEAR, L_BRING_IN_WHITE, 0, 0); + pixaAddPix(pixa, pix1, L_INSERT); + pix2 = pixRotate(pixs, ANGLE1, L_ROTATE_SHEAR, L_BRING_IN_BLACK, 0, 0); + pixaAddPix(pixa, pix2, L_INSERT); + pix1 = pixRotate(pixs, ANGLE2, L_ROTATE_SHEAR, L_BRING_IN_WHITE, w, h); + pixaAddPix(pixa, pix1, L_INSERT); + pix2 = pixRotate(pixs, ANGLE2, L_ROTATE_SHEAR, L_BRING_IN_BLACK, w, h); + pixaAddPix(pixa, pix2, L_INSERT); + pix1 = pixRotate(pixs, ANGLE2, L_ROTATE_SHEAR, L_BRING_IN_WHITE, 0, 0); + pixaAddPix(pixa, pix1, L_INSERT); + pix2 = pixRotate(pixs, ANGLE2, L_ROTATE_SHEAR, L_BRING_IN_BLACK, 0, 0); + pixaAddPix(pixa, pix2, L_INSERT); + pixd = pixaDisplayTiledInColumns(pixa, 2, scale, 20, 0); + regTestWritePixAndCheck(rp, pixd, outformat); + pixDisplayWithTitle(pixd, 100, 100, NULL, rp->display); + pixDestroy(&pixd); + pixaDestroy(&pixa); + + pixa = pixaCreate(0); + pix1 = pixRotate(pixs, ANGLE2, L_ROTATE_SAMPLING, L_BRING_IN_WHITE, w, h); + pixaAddPix(pixa, pix1, L_INSERT); + pix2 = pixRotate(pixs, ANGLE2, L_ROTATE_SAMPLING, L_BRING_IN_BLACK, w, h); + pixaAddPix(pixa, pix2, L_INSERT); + pix1 = pixRotate(pixs, ANGLE2, L_ROTATE_SAMPLING, L_BRING_IN_WHITE, 0, 0); + pixaAddPix(pixa, pix1, L_INSERT); + pix2 = pixRotate(pixs, ANGLE2, L_ROTATE_SAMPLING, L_BRING_IN_BLACK, 0, 0); + pixaAddPix(pixa, pix2, L_INSERT); + + if (pixGetDepth(pixs) == 1) + pix1 = pixScaleToGray2(pixs); + else + pix1 = pixClone(pixs); + pix2 = pixRotate(pix1, ANGLE2, L_ROTATE_AREA_MAP, L_BRING_IN_WHITE, w, h); + pixaAddPix(pixa, pix2, L_INSERT); + pix3 = pixRotate(pix1, ANGLE2, L_ROTATE_AREA_MAP, L_BRING_IN_BLACK, w, h); + pixaAddPix(pixa, pix3, L_INSERT); + pix2 = pixRotate(pix1, ANGLE2, L_ROTATE_AREA_MAP, L_BRING_IN_WHITE, 0, 0); + pixaAddPix(pixa, pix2, L_INSERT); + pix3 = pixRotate(pix1, ANGLE2, L_ROTATE_AREA_MAP, L_BRING_IN_BLACK, 0, 0); + pixaAddPix(pixa, pix3, L_INSERT); + pixDestroy(&pix1); + pixd = pixaDisplayTiledInColumns(pixa, 2, scale, 20, 0); + regTestWritePixAndCheck(rp, pixd, outformat); + pixDisplayWithTitle(pixd, 600, 100, NULL, rp->display); + pixDestroy(&pixd); + pixaDestroy(&pixa); + + return; +} diff --git a/leptonica/prog/rotate_it.c b/leptonica/prog/rotate_it.c new file mode 100644 index 00000000..37ff3bc6 --- /dev/null +++ b/leptonica/prog/rotate_it.c @@ -0,0 +1,113 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * rotate_it.c + * + * rotate_it filein angle fileout [type incolor] + * + * where: + * angle: in degrees; use 90, 180, 270 for orthogonal rotation + * type: "areamap", "shear", "sampling" + * incolor: "black", "white" + * + * If 'type' and 'incolor' are omitted, by default we use: + * type: sampling for 1 bpp; areamap for bpp > 1 + * incolor: white + * + * If angle is in {90.0, 180.0, 270.0}, this does an orthogonal + * rotation. Args 'type' and 'incolor' can be omitted. + * + * This writes the output file in the same encoded format as + * the input file. If the input file is jpeg, the output file + * is written with default quality factor 75. + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include <string.h> +#include "allheaders.h" + +int main(int argc, + char **argv) +{ +l_int32 icolor, itype, format, quads; +l_float32 angle, deg2rad, anglerad; +char *filein, *fileout, *type, *incolor; +PIX *pixs, *pixd; +static char mainName[] = "rotate_it"; + + if (argc != 4 && argc != 6) + return ERROR_INT( + "\n Syntax: rotate_it filein angle fileout [type incolor]", + mainName, 1); + filein = argv[1]; + angle = atof(argv[2]); + fileout = argv[3]; + if (argc == 6) { + type = argv[4]; + incolor = argv[5]; + } + + setLeptDebugOK(1); + deg2rad = 3.1415926535 / 180.; + + if ((pixs = pixRead(filein)) == NULL) + return ERROR_INT("pixs not made", mainName, 1); + format = pixGetInputFormat(pixs); + if (format == IFF_UNKNOWN) format = IFF_PNG; + + if (angle == 90.0 || angle == 180.0 || angle == 270.0) { + quads = (l_int32)((angle + 0.5) / 90.0); + pixd = pixRotateOrth(pixs, quads); + pixWrite(fileout, pixd, format); + pixDestroy(&pixs); + pixDestroy(&pixd); + return 0; + } + + anglerad = deg2rad * angle; + icolor = L_BRING_IN_WHITE; + itype = L_ROTATE_AREA_MAP; + if (argc == 6) { + icolor = (!strcmp(incolor, "white")) ? L_BRING_IN_WHITE + : L_BRING_IN_BLACK; + if (!strcmp(type, "areamap")) + itype = L_ROTATE_AREA_MAP; + else if (!strcmp(type, "shear")) + itype = L_ROTATE_SHEAR; + else + itype = L_ROTATE_SAMPLING; + } + + pixd = pixRotate(pixs, anglerad, itype, icolor, 0, 0); + pixWrite(fileout, pixd, format); + pixDestroy(&pixs); + pixDestroy(&pixd); + return 0; +} diff --git a/leptonica/prog/rotatefastalt.c b/leptonica/prog/rotatefastalt.c new file mode 100644 index 00000000..6dbda05d --- /dev/null +++ b/leptonica/prog/rotatefastalt.c @@ -0,0 +1,351 @@ +/*====================================================================* + - 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. + *====================================================================*/ + + +/* + * rotatefastalt.c + * + * Alternative (slightly slower) method for rotating color images, + * with antialiasing. This is here just for comparison with + * the better methods in the library. + * + * Includes these functions: + * pixRotateAMColorFast2() + * pixShiftRGB258() + * rotateAMColorFastLow2() + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include <string.h> +#include <math.h> /* required for sin and tan */ +#include "allheaders.h" + +static const l_float32 VERY_SMALL_ANGLE = 0.001; /* radians; ~0.06 degrees */ + +static PIX *pixRotateAMColorFast2(PIX *pixs, l_float32 angle, l_uint8 grayval); +static PIX *pixShiftRGB258(PIX *pixs); +static void rotateAMColorFastLow2(l_uint32 *datad, l_int32 w, l_int32 h, + l_int32 wpld, l_uint32 *datas, + l_int32 wpls, l_float32 angle, + l_uint8 grayval); + +int main(int argc, + char **argv) +{ +char *filein, *fileout; +l_float32 angle, deg2rad; +PIX *pixs, *pixd; +static char mainName[] = "rotatefastalt"; + + if (argc != 4) + return ERROR_INT("Syntax: rotatefastalt filein angle fileout", + mainName, 1); + filein = argv[1]; + angle = atof(argv[2]); + fileout = argv[3]; + + setLeptDebugOK(1); + deg2rad = 3.1415926535 / 180.; + if ((pixs = pixRead(filein)) == NULL) + return ERROR_INT("pixs not read", mainName, 1); + + startTimer(); + pixd = pixRotateAMColorFast2(pixs, deg2rad * angle, 255); + lept_stderr("Time for rotation: %7.3f sec\n", stopTimer()); + pixWrite(fileout, pixd, IFF_JFIF_JPEG); + + pixDestroy(&pixs); + pixDestroy(&pixd); + return 0; +} + + +/*! + * pixRotateAMColorFast2() + * + * Input: pixs + * angle (radians; clockwise is positive) + * grayval (0 to bring in BLACK, 255 for WHITE) + * Return: pixd, or null on error + * + * Notes: + * - This rotates a color image about the image center. + * A positive angle gives a clockwise rotation. + * - It uses area mapping, dividing each pixel into + * 16 subpixels. + * - It creates a temporary 32-bit color image. + * - It is slightly slower than pixRotateAMColorFast(), + * which uses less memory because it does not create + * a temporary image. + * + * *** Warning: implicit assumption about RGB component ordering *** + */ +PIX * +pixRotateAMColorFast2(PIX *pixs, + l_float32 angle, + l_uint8 grayval) +{ +l_int32 w, h, wpls, wpld; +l_uint32 *datas, *datad; +PIX *pixshft, *pixd; + + PROCNAME("pixRotateAMColorFast2"); + + if (!pixs) + return (PIX *)ERROR_PTR("pixs not defined", procName, NULL); + if (pixGetDepth(pixs) != 32) + return (PIX *)ERROR_PTR("pixs must be 32 bpp", procName, NULL); + + if (L_ABS(angle) < VERY_SMALL_ANGLE) + return pixClone(pixs); + + if ((pixshft = pixShiftRGB258(pixs)) == NULL) + return (PIX *)ERROR_PTR("pixshft not defined", procName, NULL); + + w = pixGetWidth(pixshft); + h = pixGetHeight(pixshft); + datas = pixGetData(pixshft); + wpls = pixGetWpl(pixshft); + pixd = pixCreateTemplate(pixshft); + datad = pixGetData(pixd); + wpld = pixGetWpl(pixd); + rotateAMColorFastLow2(datad, w, h, wpld, datas, wpls, angle, grayval); + + pixDestroy(&pixshft); + return pixd; +} + + +/*! + * pixShiftRGB258() + * + * Makes a new 32 bpp image with the R, G and B components + * right-shifted by 2, 5 and 8 bits, respectively. + */ +PIX * +pixShiftRGB258(PIX *pixs) +{ +l_int32 w, h, wpls, wpld, i, j; +l_uint32 word; +l_uint32 *datas, *datad, *lines, *lined; +PIX *pixd; + + PROCNAME("pixShift258"); + + if (!pixs) + return (PIX *)ERROR_PTR("pixs not defined", procName, NULL); + if (pixGetDepth(pixs) != 32) + return (PIX *)ERROR_PTR("depth not 32 bpp", procName, NULL); + w = pixGetWidth(pixs); + h = pixGetHeight(pixs); + wpls = pixGetWpl(pixs); + datas = pixGetData(pixs); + + if ((pixd = pixCreate(w, h, 32)) == NULL) + return (PIX *)ERROR_PTR("pixd not made", procName, NULL); + wpld = pixGetWpl(pixd); + datad = pixGetData(pixd); + + for (i = 0; i < h; i++) { + lines = datas + i * wpls; + lined = datad + i * wpld; + for (j = 0; j < w; j++) { + word = *(lines + j); + *(lined + j) = ((word & 0xff000000) >> 2) | + ((word & 0x00ff0000) >> 5) | + ((word & 0x0000ff00) >> 8); + } + } + + return pixd; +} + + +/*! + * rotateAMColorFastLow2() + * + * Alternative version for fast color rotation + * + * *** Warning: explicit assumption about RGB component ordering *** + */ +void +rotateAMColorFastLow2(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls, + l_float32 angle, + l_uint8 grayval) +{ +l_int32 i, j, xcen, ycen, wm2, hm2; +l_int32 xdif, ydif, xpm, ypm, xp, yp, xf, yf; +l_uint32 edgeval, word; +l_uint32 *pword, *lines, *lined; +l_float32 sina, cosa; + + xcen = w / 2; + wm2 = w - 2; + ycen = h / 2; + hm2 = h - 2; + sina = 4. * sin(angle); + cosa = 4. * cos(angle); + + edgeval = (grayval << 24) | (grayval << 16) | (grayval << 8); + for (i = 0; i < h; i++) { + ydif = ycen - i; + lined = datad + i * wpld; + for (j = 0; j < w; j++) { + xdif = xcen - j; + xpm = (l_int32)(-xdif * cosa - ydif * sina + 0.5); + ypm = (l_int32)(-ydif * cosa + xdif * sina + 0.5); + xp = xcen + (xpm >> 2); + yp = ycen + (ypm >> 2); + xf = xpm & 0x03; + yf = ypm & 0x03; + + /* if off the edge, write the input grayval */ + if (xp < 0 || yp < 0 || xp > wm2 || yp > hm2) { + *(lined + j) = edgeval; + continue; + } + + lines = datas + yp * wpls; + pword = lines + xp; + + switch (xf + 4 * yf) + { + case 0: + word = *pword; + *(lined + j) = ((word & 0x3fc00000) << 2) | + ((word & 0x0007f800) << 5) | + ((word & 0x000000ff) << 8); + break; + case 1: + word = 3 * (*pword) + *(pword + 1); + *(lined + j) = (word & 0xff000000) | + ((word & 0x001fe000) << 3) | + ((word & 0x000003fc) << 6); + break; + case 2: + word = *pword + *(pword + 1); + *(lined + j) = ((word & 0x7f800000) << 1) | + ((word & 0x000ff000) << 4) | + ((word & 0x000001fe) << 7); + break; + case 3: + word = *pword + 3 * (*(pword + 1)); + *(lined + j) = (word & 0xff000000) | + ((word & 0x001fe000) << 3) | + ((word & 0x000003fc) << 6); + break; + case 4: + word = 3 * (*pword) + *(pword + wpls); + *(lined + j) = (word & 0xff000000) | + ((word & 0x001fe000) << 3) | + ((word & 0x000003fc) << 6); + break; + case 5: + word = 2 * (*pword) + *(pword + 1) + *(pword + wpls); + *(lined + j) = (word & 0xff000000) | + ((word & 0x001fe000) << 3) | + ((word & 0x000003fc) << 6); + break; + case 6: + word = *pword + *(pword + 1); + *(lined + j) = ((word & 0x7f800000) << 1) | + ((word & 0x000ff000) << 4) | + ((word & 0x000001fe) << 7); + break; + case 7: + word = *pword + 2 * (*(pword + 1)) + *(pword + wpls + 1); + *(lined + j) = (word & 0xff000000) | + ((word & 0x001fe000) << 3) | + ((word & 0x000003fc) << 6); + break; + case 8: + word = *pword + *(pword + wpls); + *(lined + j) = ((word & 0x7f800000) << 1) | + ((word & 0x000ff000) << 4) | + ((word & 0x000001fe) << 7); + break; + case 9: + word = *pword + *(pword + wpls); + *(lined + j) = ((word & 0x7f800000) << 1) | + ((word & 0x000ff000) << 4) | + ((word & 0x000001fe) << 7); + break; + case 10: + word = *pword + *(pword + 1) + *(pword + wpls) + + *(pword + wpls + 1); + *(lined + j) = (word & 0xff000000) | + ((word & 0x001fe000) << 3) | + ((word & 0x000003fc) << 6); + break; + case 11: + word = *(pword + 1) + *(pword + wpls + 1); + *(lined + j) = ((word & 0x7f800000) << 1) | + ((word & 0x000ff000) << 4) | + ((word & 0x000001fe) << 7); + break; + case 12: + word = *pword + 3 * (*(pword + wpls)); + *(lined + j) = (word & 0xff000000) | + ((word & 0x001fe000) << 3) | + ((word & 0x000003fc) << 6); + break; + case 13: + word = *pword + 2 * (*(pword + wpls)) + *(pword + wpls + 1); + *(lined + j) = (word & 0xff000000) | + ((word & 0x001fe000) << 3) | + ((word & 0x000003fc) << 6); + break; + case 14: + word = *(pword + wpls) + *(pword + wpls + 1); + *(lined + j) = ((word & 0x7f800000) << 1) | + ((word & 0x000ff000) << 4) | + ((word & 0x000001fe) << 7); + break; + case 15: + word = *(pword + 1) + *(pword + wpls) + + 2 * (*(pword + wpls + 1)); + *(lined + j) = (word & 0xff000000) | + ((word & 0x001fe000) << 3) | + ((word & 0x000003fc) << 6); + break; + default: /* for testing only; no interpolation, no shift */ + lept_stderr("shouldn't get here\n"); + *(lined + j) = *pword; + break; + } + } + } + + return; +} diff --git a/leptonica/prog/rotateorth_reg.c b/leptonica/prog/rotateorth_reg.c new file mode 100644 index 00000000..01bc5eb2 --- /dev/null +++ b/leptonica/prog/rotateorth_reg.c @@ -0,0 +1,146 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * rotateorth_reg.c + * + * Regression test for all rotateorth functions + */ + +#include "allheaders.h" + +#define BINARY_IMAGE "test1.png" +#define FOUR_BPP_IMAGE "weasel4.8g.png" +#define GRAYSCALE_IMAGE "test8.jpg" +#define COLORMAP_IMAGE "dreyfus8.png" +#define RGB_IMAGE "marge.jpg" + +void RotateOrthTest(PIX *pix, L_REGPARAMS *rp); + + +int main(int argc, + char **argv) +{ +PIX *pixs; +L_REGPARAMS *rp; + + if (regTestSetup(argc, argv, &rp)) + return 1; + + lept_stderr("\nTest binary image:\n"); + pixs = pixRead(BINARY_IMAGE); + RotateOrthTest(pixs, rp); + pixDestroy(&pixs); + lept_stderr("\nTest 4 bpp colormapped image:\n"); + pixs = pixRead(FOUR_BPP_IMAGE); + RotateOrthTest(pixs, rp); + pixDestroy(&pixs); + lept_stderr("\nTest grayscale image:\n"); + pixs = pixRead(GRAYSCALE_IMAGE); + RotateOrthTest(pixs, rp); + pixDestroy(&pixs); + lept_stderr("\nTest colormap image:\n"); + pixs = pixRead(COLORMAP_IMAGE); + RotateOrthTest(pixs, rp); + pixDestroy(&pixs); + lept_stderr("\nTest rgb image:\n"); + pixs = pixRead(RGB_IMAGE); + RotateOrthTest(pixs, rp); + pixDestroy(&pixs); + + return regTestCleanup(rp); +} + + +void +RotateOrthTest(PIX *pixs, + L_REGPARAMS *rp) +{ +l_int32 zero, count; +PIX *pixt, *pixd; + + /* Test 4 successive 90 degree rotations */ + pixt = pixRotate90(pixs, 1); + pixd = pixRotate90(pixt, 1); + pixDestroy(&pixt); + pixt = pixRotate90(pixd, 1); + pixDestroy(&pixd); + pixd = pixRotate90(pixt, 1); + pixDestroy(&pixt); + regTestComparePix(rp, pixs, pixd); + pixXor(pixd, pixd, pixs); + pixZero(pixd, &zero); + if (zero) { + lept_stderr("OK. Four 90-degree rotations gives I\n"); + } else { + pixCountPixels(pixd, &count, NULL); + lept_stderr("Failure for four 90-degree rots; count = %d\n", count); + } + pixDestroy(&pixd); + + /* Test 2 successive 180 degree rotations */ + pixt = pixRotate180(NULL, pixs); + pixRotate180(pixt, pixt); + regTestComparePix(rp, pixs, pixt); + pixXor(pixt, pixt, pixs); + pixZero(pixt, &zero); + if (zero) { + lept_stderr("OK. Two 180-degree rotations gives I\n"); + } else { + pixCountPixels(pixt, &count, NULL); + lept_stderr("Failure for two 180-degree rots; count = %d\n", count); + } + pixDestroy(&pixt); + + /* Test 2 successive LR flips */ + pixt = pixFlipLR(NULL, pixs); + pixFlipLR(pixt, pixt); + regTestComparePix(rp, pixs, pixt); + pixXor(pixt, pixt, pixs); + pixZero(pixt, &zero); + if (zero) { + lept_stderr("OK. Two LR flips gives I\n"); + } else { + pixCountPixels(pixt, &count, NULL); + lept_stderr("Failure for two LR flips; count = %d\n", count); + } + pixDestroy(&pixt); + + /* Test 2 successive TB flips */ + pixt = pixFlipTB(NULL, pixs); + pixFlipTB(pixt, pixt); + regTestComparePix(rp, pixs, pixt); + pixXor(pixt, pixt, pixs); + pixZero(pixt, &zero); + if (zero) { + lept_stderr("OK. Two TB flips gives I\n"); + } else { + pixCountPixels(pixt, &count, NULL); + lept_stderr("Failure for two TB flips; count = %d\n", count); + } + pixDestroy(&pixt); + return; +} diff --git a/leptonica/prog/rotateorthtest1.c b/leptonica/prog/rotateorthtest1.c new file mode 100644 index 00000000..ac79d31b --- /dev/null +++ b/leptonica/prog/rotateorthtest1.c @@ -0,0 +1,145 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * rotateorthtest1.c + * + * Tests and timings for 90 and 180 degree rotations + * rotateorthtest1 filein fileout [direction] + * where + * direction = 1 for cw; -1 for ccw + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + +#define NTIMES 10 + + +int main(int argc, + char **argv) +{ +l_int32 dir; +PIX *pixs, *pixd, *pixt; +l_float32 pops; +char *filein, *fileout; +static char mainName[] = "rotateorthtest1"; + + if (argc != 3 && argc != 4) + return ERROR_INT(" Syntax: rotateorthtest1 filein fileout [direction]", + mainName, 1); + filein = argv[1]; + fileout = argv[2]; + if (argc == 4) + dir = atoi(argv[3]); + else + dir = 1; + setLeptDebugOK(1); + + if ((pixs = pixRead(filein)) == NULL) + return ERROR_INT("pix not made", mainName, 1); + + /* Do a single operation */ +#if 1 + pixd = pixRotate90(pixs, dir); +#elif 0 + pixd = pixRotate180(NULL, pixs); +#elif 0 + pixd = pixRotateLR(NULL, pixs); +#elif 0 + pixd = pixRotateTB(NULL, pixs); +#endif + + /* Time rotate 90, allocating & destroying each time */ +#if 0 + startTimer(); + w = pixGetWidth(pixs); + h = pixGetHeight(pixs); + for (i = 0; i < NTIMES; i++) { + pixd = pixRotate90(pixs, dir); + pixDestroy(&pixd); + } + pops = (l_float32)(w * h * NTIMES) / stopTimer(); + lept_stderr("MPops for 90 rotation: %7.3f\n", pops / 1000000.); + pixd = pixRotate90(pixs, dir); +#endif + + /* Time rotate 180, with no alloc/destroy */ +#if 0 + startTimer(); + w = pixGetWidth(pixs); + h = pixGetHeight(pixs); + pixd = pixCreateTemplate(pixs); + for (i = 0; i < NTIMES; i++) + pixRotate180(pixd, pixs); + pops = (l_float32)(w * h * NTIMES) / stopTimer(); + lept_stderr("MPops for 180 rotation: %7.3f\n", pops / 1000000.); +#endif + + + /* Test rotate 180 not in-place */ +#if 0 + pixt = pixRotate180(NULL, pixs); + pixd = pixRotate180(NULL, pixt); + pixEqual(pixs, pixd, &eq); + if (eq) lept_stderr("2 rots gives I\n"); + else lept_stderr("2 rots fail to give I\n"); + pixDestroy(&pixt); +#endif + + /* Test rotate 180 in-place */ +#if 0 + pixd = pixCopy(NULL, pixs); + pixRotate180(pixd, pixd); + pixRotate180(pixd, pixd); + pixEqual(pixs, pixd, &eq); + if (eq) lept_stderr("2 rots gives I\n"); + else lept_stderr("2 rots fail to give I\n"); +#endif + + /* Mix rotate 180 with LR/TB */ +#if 0 + pixd = pixRotate180(NULL, pixs); + pixRotateLR(pixd, pixd); + pixRotateTB(pixd, pixd); + pixEqual(pixs, pixd, &eq); + if (eq) lept_stderr("180 rot OK\n"); + else lept_stderr("180 rot error\n"); +#endif + + if (pixGetDepth(pixd) < 8) + pixWrite(fileout, pixd, IFF_PNG); + else + pixWrite(fileout, pixd, IFF_JFIF_JPEG); + + pixDestroy(&pixs); + pixDestroy(&pixd); + return 0; +} + diff --git a/leptonica/prog/rotatetest1.c b/leptonica/prog/rotatetest1.c new file mode 100644 index 00000000..18c6c109 --- /dev/null +++ b/leptonica/prog/rotatetest1.c @@ -0,0 +1,224 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * rotatetest1.c + * + * rotatetest1 filein angle(in degrees) fileout + */ + +#include "allheaders.h" + +#define NTIMES 180 +#define NITERS 3 + +int main(int argc, + char **argv) +{ +l_int32 i, w, h, d, rotflag; +PIX *pixs, *pixt, *pixd; +l_float32 angle, deg2rad, ang; +char *filein, *fileout; +static char mainName[] = "rotatetest1"; + + if (argc != 4) + return ERROR_INT(" Syntax: rotatetest1 filein angle fileout", + mainName, 1); + filein = argv[1]; + angle = atof(argv[2]); + fileout = argv[3]; + + setLeptDebugOK(1); + lept_mkdir("lept/rotate"); + + deg2rad = 3.1415926535 / 180.; + if ((pixs = pixRead(filein)) == NULL) + return ERROR_INT("pix not made", mainName, 1); + if (pixGetDepth(pixs) == 1) { + pixt = pixScaleToGray3(pixs); + pixDestroy(&pixs); + pixs = pixAddBorderGeneral(pixt, 1, 0, 1, 0, 255); + pixDestroy(&pixt); + } + + pixGetDimensions(pixs, &w, &h, &d); + lept_stderr("w = %d, h = %d\n", w, h); + +#if 0 + /* repertory of rotation operations to choose from */ + pixd = pixRotateAM(pixs, deg2rad * angle, L_BRING_IN_WHITE); + pixd = pixRotateAMColor(pixs, deg2rad * angle, 0xffffff00); + pixd = pixRotateAMColorFast(pixs, deg2rad * angle, 255); + pixd = pixRotateAMCorner(pixs, deg2rad * angle, L_BRING_IN_WHITE); + pixd = pixRotateShear(pixs, w /2, h / 2, deg2rad * angle, + L_BRING_IN_WHITE); + pixd = pixRotate3Shear(pixs, w /2, h / 2, deg2rad * angle, + L_BRING_IN_WHITE); + pixRotateShearIP(pixs, w / 2, h / 2, deg2rad * angle); pixd = pixs; +#endif + +#if 0 + /* timing of shear rotation */ + for (i = 0; i < NITERS; i++) { + pixd = pixRotateShear(pixs, (i * w) / NITERS, + (i * h) / NITERS, deg2rad * angle, + L_BRING_IN_WHITE); + pixDisplay(pixd, 100 + 20 * i, 100 + 20 * i); + pixDestroy(&pixd); + } +#endif + +#if 0 + /* timing of in-place shear rotation */ + for (i = 0; i < NITERS; i++) { + pixRotateShearIP(pixs, w/2, h/2, deg2rad * angle, L_BRING_IN_WHITE); +/* pixRotateShearCenterIP(pixs, deg2rad * angle, L_BRING_IN_WHITE); */ + pixDisplay(pixs, 100 + 20 * i, 100 + 20 * i); + } + pixd = pixs; + if (pixGetDepth(pixd) == 1) + pixWrite(fileout, pixd, IFF_PNG); + else + pixWrite(fileout, pixd, IFF_JFIF_JPEG); + pixDestroy(&pixs); +#endif + +#if 0 +{ + l_float32 pops; + + /* timing of various rotation operations (choose) */ + startTimer(); + w = pixGetWidth(pixs); + h = pixGetHeight(pixs); + for (i = 0; i < NTIMES; i++) { + pixd = pixRotateShearCenter(pixs, deg2rad * angle, L_BRING_IN_WHITE); + pixDestroy(&pixd); + } + pops = (l_float32)(w * h * NTIMES / 1000000.) / stopTimer(); + lept_stderr("vers. 1, mpops: %f\n", pops); + startTimer(); + w = pixGetWidth(pixs); + h = pixGetHeight(pixs); + for (i = 0; i < NTIMES; i++) { + pixRotateShearIP(pixs, w/2, h/2, deg2rad * angle, L_BRING_IN_WHITE); + } + pops = (l_float32)(w * h * NTIMES / 1000000.) / stopTimer(); + lept_stderr("shear, mpops: %f\n", pops); + pixWrite(fileout, pixs, IFF_PNG); + for (i = 0; i < NTIMES; i++) { + pixRotateShearIP(pixs, w/2, h/2, -deg2rad * angle, L_BRING_IN_WHITE); + } + pixWrite("/usr/tmp/junkout", pixs, IFF_PNG); +} +#endif + +#if 0 + /* area-mapping rotation operations */ + pixd = pixRotateAM(pixs, deg2rad * angle, L_BRING_IN_WHITE); +/* pixd = pixRotateAMColorFast(pixs, deg2rad * angle, 255); */ + if (pixGetDepth(pixd) == 1) + pixWrite(fileout, pixd, IFF_PNG); + else + pixWrite(fileout, pixd, IFF_JFIF_JPEG); +#endif + +#if 0 + /* compare the standard area-map color rotation with + * the fast area-map color rotation, on a pixel basis */ + { + PIX *pix1, *pix2; + NUMA *nar, *nag, *nab, *naseq; + GPLOT *gplot; + + startTimer(); + pix1 = pixRotateAMColor(pixs, 0.12, 0xffffff00); + lept_stderr(" standard color rotate: %7.2f sec\n", stopTimer()); + pixWrite("/tmp/lept/rotate/color1.jpg", pix1, IFF_JFIF_JPEG); + startTimer(); + pix2 = pixRotateAMColorFast(pixs, 0.12, 0xffffff00); + lept_stderr(" fast color rotate: %7.2f sec\n", stopTimer()); + pixWrite("/tmp/lept/rotate/color2.jpg", pix2, IFF_JFIF_JPEG); + pixd = pixAbsDifference(pix1, pix2); + pixGetColorHistogram(pixd, 1, &nar, &nag, &nab); + naseq = numaMakeSequence(0., 1., 256); + gplot = gplotCreate("/tmp/lept/rotate/absdiff", GPLOT_PNG, + "Number vs diff", "diff", "number"); + gplotAddPlot(gplot, naseq, nar, GPLOT_POINTS, "red"); + gplotAddPlot(gplot, naseq, nag, GPLOT_POINTS, "green"); + gplotAddPlot(gplot, naseq, nab, GPLOT_POINTS, "blue"); + gplotMakeOutput(gplot); + l_fileDisplay("/tmp/lept/rotate/absdiff.png", 100, 100, 1.0); + pixDestroy(&pix1); + pixDestroy(&pix2); + pixDestroy(&pixd); + numaDestroy(&nar); + numaDestroy(&nag); + numaDestroy(&nab); + numaDestroy(&naseq); + gplotDestroy(&gplot); + } +#endif + + /* Do a succession of 180 7-degree rotations in a cw + * direction, and unwind the result with another set in + * a ccw direction. Although there is a considerable amount + * of distortion after successive rotations, after all + * 360 rotations, the resulting image is restored to + * its original pristine condition! */ +#if 1 + rotflag = L_ROTATE_AREA_MAP; +/* rotflag = L_ROTATE_SHEAR; */ +/* rotflag = L_ROTATE_SAMPLING; */ + ang = 7.0 * deg2rad; + pixGetDimensions(pixs, &w, &h, NULL); + pixd = pixRotate(pixs, ang, rotflag, L_BRING_IN_WHITE, w, h); + pixWrite("/tmp/lept/rotate/rot7.png", pixd, IFF_PNG); + for (i = 1; i < 180; i++) { + pixs = pixd; + pixd = pixRotate(pixs, ang, rotflag, L_BRING_IN_WHITE, w, h); + if ((i % 30) == 0) pixDisplay(pixd, 600, 0); + pixDestroy(&pixs); + } + + pixWrite("/tmp/lept/rotate/spin.png", pixd, IFF_PNG); + pixDisplay(pixd, 0, 0); + + for (i = 0; i < 180; i++) { + pixs = pixd; + pixd = pixRotate(pixs, -ang, rotflag, L_BRING_IN_WHITE, w, h); + if (i && (i % 30) == 0) pixDisplay(pixd, 600, 500); + pixDestroy(&pixs); + } + + pixWrite("/tmp/lept/rotate/unspin.png", pixd, IFF_PNG); + pixDisplay(pixd, 0, 500); + pixDestroy(&pixd); +#endif + + return 0; +} + diff --git a/leptonica/prog/runlengthtest.c b/leptonica/prog/runlengthtest.c new file mode 100644 index 00000000..427dfcb7 --- /dev/null +++ b/leptonica/prog/runlengthtest.c @@ -0,0 +1,106 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * runlengthtest.c + * + * Set 1 tests the runlength and 1-component dynamic range transform. + * Set 2 tests the 3-component (rgb) dynamic range transform. + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + +int main(int argc, + char **argv) +{ +l_float32 avediff, rmsdiff; +PIX *pix1, *pix2, *pix3, *pix4, *pix5, *pix6, *pix7; +static char mainName[] = "runlengthtest"; + + if (argc != 1) + return ERROR_INT(" Syntax: runlengthtest", mainName, 1); + + setLeptDebugOK(1); + lept_mkdir("lept/run"); + + /* Set 1 */ + startTimer(); + pix1 = pixRead("rabi.png"); + pix2 = pixRunlengthTransform(pix1, 0, L_HORIZONTAL_RUNS, 8); + pix3 = pixRunlengthTransform(pix1, 0, L_VERTICAL_RUNS, 8); + pix4 = pixMinOrMax(NULL, pix2, pix3, L_CHOOSE_MIN); + pix5 = pixMaxDynamicRange(pix4, L_LOG_SCALE); + pix6 = pixMinOrMax(NULL, pix2, pix3, L_CHOOSE_MAX); + pix7 = pixMaxDynamicRange(pix6, L_LOG_SCALE); + lept_stderr("Time for set 1: %7.3f sec\n", stopTimer()); + pixDisplay(pix2, 0, 0); + pixDisplay(pix3, 600, 0); + pixDisplay(pix4, 1200, 0); + pixDisplay(pix5, 1800, 0); + pixDisplay(pix6, 1200, 0); + pixDisplay(pix7, 1800, 0); + pixWrite("/tmp/lept/run/pixh.png", pix2, IFF_PNG); + pixWrite("/tmp/lept/run/pixv.png", pix3, IFF_PNG); + pixWrite("/tmp/lept/run/pixmin.png", pix4, IFF_PNG); + pixWrite("/tmp/lept/run/pixminlog.png", pix5, IFF_PNG); + pixWrite("/tmp/lept/run/pixmax.png", pix6, IFF_PNG); + pixWrite("/tmp/lept/run/pixmaxlog.png", pix7, IFF_PNG); + pixDestroy(&pix1); + pixDestroy(&pix2); + pixDestroy(&pix3); + pixDestroy(&pix4); + pixDestroy(&pix5); + pixDestroy(&pix6); + pixDestroy(&pix7); + + /* Set 2 */ + startTimer(); + pix1 = pixRead("test24.jpg"); + pixWriteJpeg("/tmp/lept/run/junk24.jpg", pix1, 5, 0); + pix2 = pixRead("/tmp/lept/run/junk24.jpg"); + pixCompareGrayOrRGB(pix1, pix2, L_COMPARE_ABS_DIFF, GPLOT_PNG, + NULL, &avediff, &rmsdiff, &pix3); + lept_stderr("Ave diff = %6.3f, RMS diff = %6.3f\n", avediff, rmsdiff); + pix4 = pixMaxDynamicRangeRGB(pix3, L_LINEAR_SCALE); + pix5 = pixMaxDynamicRangeRGB(pix3, L_LOG_SCALE); + lept_stderr("Time for set 2: %7.3f sec\n", stopTimer()); + pixDisplay(pix4, 0, 800); + pixDisplay(pix5, 1000, 800); + pixWrite("/tmp/lept/run/linear.png", pix4, IFF_PNG); + pixWrite("/tmp/lept/run/log.png", pix5, IFF_PNG); + + pixDestroy(&pix1); + pixDestroy(&pix2); + pixDestroy(&pix3); + pixDestroy(&pix4); + pixDestroy(&pix5); + + return 0; +} diff --git a/leptonica/prog/scale_it.c b/leptonica/prog/scale_it.c new file mode 100644 index 00000000..f9db6ec7 --- /dev/null +++ b/leptonica/prog/scale_it.c @@ -0,0 +1,143 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * scale_it.c + * + * scale_it filein scalex scaley fileout lossless [sharpen antialias togray] + * + * where + * scalex: floating pt input + * scaley: ditto + * lossless: (for bpp >= 8) 1 to output jpeg; 0 to output png + * sharpen : (for bpp > 1; scale factor in [0.2 ... 1.4]): + * 1 to sharpen; 0 not to sharpen + * antialias: (for bpp > 1): 1 to use area-mapping or linear + * interpolation; 0 for sampling. + * togray: (for bpp == 1, reduction): 1 for scale-to-gray; + * 0 for sampling + * + * The choice of writing lossless (png) or lossy (jpeg) only applies + * for bpp >= 8. Otherwise: + * bpp == 1 --> tiffg4 + * bpp == 2 --> png + * bpp == 4 --> png + * + * Sharpening: no sharpening is done for scale factors < 0.2 or > 1.4. + * Sharpening increases the saliency of edges, making the scaled image + * look less fuzzy. It is much slower than scaling without sharpening. + * The default is to sharpen. + * + * Antialias: area-mapping and linear interpolation give higher + * quality results with bpp > 1. Sampling is faster, but shows + * artifacts, such as pixel-sized steps in lines. The default is + * to use antialiasing. + * + * ScaleToGray: for bpp == 1, downscaling to gray gives a better appearance + * than subsampling. The default is to scale-to-gray. + * + * The defaults are all intended to improve the quality of the result. + * The quality can be degraded, with faster processing, by setting + * some of the three optional inputs to 0. + * + * Note that the short form: + * scale_it filein scalex scaley fileout lossless + * is equivalent to + * scale_it filein scalex scaley fileout lossless 1 1 1 + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + +int main(int argc, + char **argv) +{ +char *filein, *fileout; +l_int32 sharpen, antialias, togray, format, lossless, d; +l_float32 scalex, scaley; +PIX *pixs, *pixd; +static char mainName[] = "scale_it"; + + if (argc != 6 && argc != 9) + return ERROR_INT( + "\n Syntax: scale_it filein scalex scaley fileout lossless " + "[sharpen antialias togray]", + mainName, 1); + + filein = argv[1]; + scalex = atof(argv[2]); + scaley = atof(argv[3]); + fileout = argv[4]; + lossless = atoi(argv[5]); + sharpen = antialias = togray = 1; + if (argc == 9) { + sharpen = atoi(argv[6]); + antialias = atoi(argv[7]); + togray = atoi(argv[8]); + } + if (scalex <= 0 || scaley <= 0) + return ERROR_INT("invalid scale factor; must be > 0.0", mainName, 1); + setLeptDebugOK(1); + + if ((pixs = pixRead(filein)) == NULL) + return ERROR_INT("pixs not made", mainName, 1); + d = pixGetDepth(pixs); + if (d == 1) { + if (togray && scalex < 1.0) + pixd = pixScaleToGray(pixs, scalex); + else /* this will just scale by sampling */ + pixd = pixScaleBinary(pixs, scalex, scaley); + } else { + if (antialias == 0) { + pixd = pixScaleBySampling(pixs, scalex, scaley); + } else if (sharpen == 0) { + pixd = pixScaleGeneral(pixs, scalex, scaley, 0.0, 0); + } else { /* antialias == 1, sharpen == 1 */ + pixd = pixScale(pixs, scalex, scaley); + } + } + if (!pixd) + return ERROR_INT("pixd not made", mainName, 1); + + d = pixGetDepth(pixd); + if (d == 1) + pixWrite(fileout, pixd, IFF_TIFF_G4); + else if (d == 2 || d == 4) + pixWrite(fileout, pixd, IFF_PNG); + else { /* d >= 8 */ + if (lossless) + pixWrite(fileout, pixd, IFF_PNG); + else + pixWrite(fileout, pixd, IFF_JFIF_JPEG); + } + + pixDestroy(&pixs); + pixDestroy(&pixd); + return 0; +} diff --git a/leptonica/prog/scale_reg.c b/leptonica/prog/scale_reg.c new file mode 100644 index 00000000..84b099ae --- /dev/null +++ b/leptonica/prog/scale_reg.c @@ -0,0 +1,307 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * scale_reg.c + * + * This tests a number of scaling operations, through the pixScale() + * interface. + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + +static const char *image[10] = {"feyn-fract.tif", /* 1 bpp */ + "weasel2.png", /* 2 bpp; no cmap */ + "weasel2.4c.png", /* 2 bpp; cmap */ + "weasel4.png", /* 4 bpp; no cmap */ + "weasel4.16c.png", /* 4 bpp; cmap */ + "weasel8.png", /* 8 bpp; no cmap */ + "weasel8.240c.png", /* 8 bpp; cmap */ + "test16.png", /* 16 bpp rgb */ + "marge.jpg", /* 32 bpp rgb */ + "test24.jpg"}; /* 32 bpp rgb */ + + +static const l_int32 SPACE = 30; +static const l_int32 WIDTH = 300; +static const l_float32 FACTOR[5] = {2.3f, 1.5f, 1.1f, 0.6f, 0.3f}; + +static void AddScaledImages(PIXA *pixa, const char *fname, l_int32 width); +static void PixaSaveDisplay(PIXA *pixa, L_REGPARAMS *rp); +static void TestSmoothScaling(const char *fname, L_REGPARAMS *rp); + +int main(int argc, + char **argv) +{ +l_int32 i; +PIX *pixs, *pixc; +PIXA *pixa; +L_REGPARAMS *rp; + + if (regTestSetup(argc, argv, &rp)) + return 1; + + /* Test 1 bpp */ + lept_stderr("\n-------------- Testing 1 bpp ----------\n"); + pixa = pixaCreate(0); + pixs = pixRead(image[0]); + pixc = pixScale(pixs, 0.32, 0.32); + regTestWritePixAndCheck(rp, pixc, IFF_PNG); /* 0 */ + pixaAddPix(pixa, pixc, L_INSERT); + + pixc = pixScaleToGray3(pixs); + regTestWritePixAndCheck(rp, pixc, IFF_PNG); /* 1 */ + pixaAddPix(pixa, pixc, L_INSERT); + + pixc = pixScaleToGray4(pixs); + regTestWritePixAndCheck(rp, pixc, IFF_PNG); /* 2 */ + pixaAddPix(pixa, pixc, L_INSERT); + + pixc = pixScaleToGray6(pixs); + regTestWritePixAndCheck(rp, pixc, IFF_PNG); /* 3 */ + pixaAddPix(pixa, pixc, L_INSERT); + + pixc = pixScaleToGray8(pixs); + regTestWritePixAndCheck(rp, pixc, IFF_PNG); /* 4 */ + pixaAddPix(pixa, pixc, L_INSERT); + + pixc = pixScaleToGray16(pixs); + regTestWritePixAndCheck(rp, pixc, IFF_PNG); /* 5 */ + pixaAddPix(pixa, pixc, L_INSERT); + PixaSaveDisplay(pixa, rp); /* 6 */ + + for (i = 1; i < 10; i++) { + pixa = pixaCreate(0); + AddScaledImages(pixa, image[i], WIDTH); + PixaSaveDisplay(pixa, rp); /* 7 - 15 */ + } + pixDestroy(&pixs); + + /* Test 2 bpp without colormap */ + lept_stderr("\n-------------- Testing 2 bpp without cmap ----------\n"); + pixa = pixaCreate(0); + pixs = pixRead(image[1]); + pixaAddPix(pixa, pixs, L_INSERT); + pixc = pixScale(pixs, 2.25, 2.25); + regTestWritePixAndCheck(rp, pixc, IFF_JFIF_JPEG); /* 16 */ + pixaAddPix(pixa, pixc, L_INSERT); + pixc = pixScale(pixs, 0.85, 0.85); + regTestWritePixAndCheck(rp, pixc, IFF_JFIF_JPEG); /* 17 */ + pixaAddPix(pixa, pixc, L_INSERT); + pixc = pixScale(pixs, 0.65, 0.65); + regTestWritePixAndCheck(rp, pixc, IFF_JFIF_JPEG); /* 18 */ + pixaAddPix(pixa, pixc, L_INSERT); + PixaSaveDisplay(pixa, rp); /* 19 */ + + /* Test 2 bpp with colormap */ + lept_stderr("\n-------------- Testing 2 bpp with cmap ----------\n"); + pixa = pixaCreate(0); + pixs = pixRead(image[2]); + pixaAddPix(pixa, pixs, L_INSERT); + pixc = pixScale(pixs, 2.25, 2.25); + regTestWritePixAndCheck(rp, pixc, IFF_PNG); /* 20 */ + pixaAddPix(pixa, pixc, L_INSERT); + pixc = pixScale(pixs, 0.85, 0.85); + regTestWritePixAndCheck(rp, pixc, IFF_PNG); /* 21 */ + pixaAddPix(pixa, pixc, L_INSERT); + pixc = pixScale(pixs, 0.65, 0.65); + regTestWritePixAndCheck(rp, pixc, IFF_PNG); /* 22 */ + pixaAddPix(pixa, pixc, L_INSERT); + PixaSaveDisplay(pixa, rp); /* 23 */ + + /* Test 4 bpp without colormap */ + lept_stderr("\n-------------- Testing 4 bpp without cmap ----------\n"); + pixa = pixaCreate(0); + pixs = pixRead(image[3]); + pixaAddPix(pixa, pixs, L_INSERT); + pixc = pixScale(pixs, 1.72, 1.72); + regTestWritePixAndCheck(rp, pixc, IFF_PNG); /* 24 */ + pixaAddPix(pixa, pixc, L_INSERT); + pixc = pixScale(pixs, 0.85, 0.85); + regTestWritePixAndCheck(rp, pixc, IFF_PNG); /* 25 */ + pixaAddPix(pixa, pixc, L_INSERT); + pixc = pixScale(pixs, 0.65, 0.65); + regTestWritePixAndCheck(rp, pixc, IFF_PNG); /* 26 */ + pixaAddPix(pixa, pixc, L_INSERT); + PixaSaveDisplay(pixa, rp); /* 27 */ + + /* Test 4 bpp with colormap */ + lept_stderr("\n-------------- Testing 4 bpp with cmap ----------\n"); + pixa = pixaCreate(0); + pixs = pixRead(image[4]); + pixaAddPix(pixa, pixs, L_INSERT); + pixc = pixScale(pixs, 1.72, 1.72); + regTestWritePixAndCheck(rp, pixc, IFF_PNG); /* 28 */ + pixaAddPix(pixa, pixc, L_INSERT); + pixc = pixScale(pixs, 0.85, 0.85); + regTestWritePixAndCheck(rp, pixc, IFF_PNG); /* 29 */ + pixaAddPix(pixa, pixc, L_INSERT); + pixc = pixScale(pixs, 0.65, 0.65); + regTestWritePixAndCheck(rp, pixc, IFF_PNG); /* 30 */ + pixaAddPix(pixa, pixc, L_INSERT); + PixaSaveDisplay(pixa, rp); /* 31 */ + + /* Test 8 bpp without colormap */ + lept_stderr("\n-------------- Testing 8 bpp without cmap ----------\n"); + pixa = pixaCreate(0); + pixs = pixRead(image[5]); + pixaAddPix(pixa, pixs, L_INSERT); + pixc = pixScale(pixs, 1.92, 1.92); + regTestWritePixAndCheck(rp, pixc, IFF_JFIF_JPEG); /* 32 */ + pixaAddPix(pixa, pixc, L_INSERT); + pixc = pixScale(pixs, 0.85, 0.85); + regTestWritePixAndCheck(rp, pixc, IFF_JFIF_JPEG); /* 33 */ + pixaAddPix(pixa, pixc, L_INSERT); + pixc = pixScale(pixs, 0.65, 0.65); + regTestWritePixAndCheck(rp, pixc, IFF_JFIF_JPEG); /* 34 */ + pixaAddPix(pixa, pixc, L_INSERT); + pixs = pixRead("graytext.png"); + pixc = pixScaleToSize(pixs, 0, 32); /* uses fast unsharp masking */ + regTestWritePixAndCheck(rp, pixc, IFF_PNG); /* 35 */ + pixaAddPix(pixa, pixc, L_INSERT); + PixaSaveDisplay(pixa, rp); /* 36 */ + pixDestroy(&pixs); + + /* Test 8 bpp with colormap */ + lept_stderr("\n-------------- Testing 8 bpp with cmap ----------\n"); + pixa = pixaCreate(0); + pixs = pixRead(image[6]); + pixaAddPix(pixa, pixs, L_INSERT); + pixc = pixScale(pixs, 1.92, 1.92); + regTestWritePixAndCheck(rp, pixc, IFF_JFIF_JPEG); /* 37 */ + pixaAddPix(pixa, pixc, L_INSERT); + pixc = pixScale(pixs, 0.85, 0.85); + regTestWritePixAndCheck(rp, pixc, IFF_JFIF_JPEG); /* 38 */ + pixaAddPix(pixa, pixc, L_INSERT); + pixc = pixScale(pixs, 0.65, 0.65); + regTestWritePixAndCheck(rp, pixc, IFF_JFIF_JPEG); /* 39 */ + pixaAddPix(pixa, pixc, L_INSERT); + PixaSaveDisplay(pixa, rp); /* 40 */ + + /* Test 16 bpp */ + lept_stderr("\n-------------- Testing 16 bpp ------------\n"); + pixa = pixaCreate(0); + pixs = pixRead(image[7]); + pixaAddPix(pixa, pixs, L_INSERT); + pixc = pixScale(pixs, 1.92, 1.92); + regTestWritePixAndCheck(rp, pixc, IFF_JFIF_JPEG); /* 41 */ + pixaAddPix(pixa, pixc, L_INSERT); + pixc = pixScale(pixs, 0.85, 0.85); + regTestWritePixAndCheck(rp, pixc, IFF_JFIF_JPEG); /* 42 */ + pixaAddPix(pixa, pixc, L_INSERT); + pixc = pixScale(pixs, 0.65, 0.65); + regTestWritePixAndCheck(rp, pixc, IFF_JFIF_JPEG); /* 43 */ + pixaAddPix(pixa, pixc, L_INSERT); + PixaSaveDisplay(pixa, rp); /* 44 */ + + /* Test 32 bpp */ + lept_stderr("\n-------------- Testing 32 bpp ------------\n"); + pixa = pixaCreate(0); + pixs = pixRead(image[8]); + pixaAddPix(pixa, pixs, L_INSERT); + pixc = pixScale(pixs, 1.42, 1.42); + regTestWritePixAndCheck(rp, pixc, IFF_JFIF_JPEG); /* 45 */ + pixaAddPix(pixa, pixc, L_INSERT); + pixc = pixScale(pixs, 0.85, 0.85); + regTestWritePixAndCheck(rp, pixc, IFF_JFIF_JPEG); /* 46 */ + pixaAddPix(pixa, pixc, L_INSERT); + pixc = pixScale(pixs, 0.65, 0.65); + regTestWritePixAndCheck(rp, pixc, IFF_JFIF_JPEG); /* 47 */ + pixaAddPix(pixa, pixc, L_INSERT); + PixaSaveDisplay(pixa, rp); /* 48 */ + + /* Test 32 bpp low-pass filtered smooth scaling */ + TestSmoothScaling("test24.jpg", rp); /* 49 */ + return regTestCleanup(rp); +} + +static void +AddScaledImages(PIXA *pixa, + const char *fname, + l_int32 width) +{ +l_int32 i, w; +l_float32 scalefactor; +PIX *pixs, *pix1, *pix2, *pix3; + + pixs = pixRead(fname); + w = pixGetWidth(pixs); + for (i = 0; i < 5; i++) { + scalefactor = (l_float32)width / (FACTOR[i] * (l_float32)w); + pix1 = pixScale(pixs, FACTOR[i], FACTOR[i]); + pix2 = pixScale(pix1, scalefactor, scalefactor); + pix3 = pixConvertTo32(pix2); + pixaAddPix(pixa, pix3, L_INSERT); + pixDestroy(&pix1); + pixDestroy(&pix2); + } + pixDestroy(&pixs); +} + +static void +PixaSaveDisplay(PIXA *pixa, L_REGPARAMS *rp) +{ +PIX *pixd; + + pixd = pixaDisplayTiledInRows(pixa, 32, 3000, 1.0, 0, SPACE, 2); + regTestWritePixAndCheck(rp, pixd, IFF_JFIF_JPEG); + pixDisplayWithTitle(pixd, 100, 100, NULL, rp->display); + pixDestroy(&pixd); + pixaDestroy(&pixa); +} + +static void +TestSmoothScaling(const char *fname, L_REGPARAMS *rp) +{ +l_int32 i; +l_float32 scale, upscale; +PIX *pix1, *pix2, *pix3; +PIXA *pixa; + + pix1 = pixRead(fname); + pixa = pixaCreate(12); + scale = 0.5; + for (i = 0; i < 12; i++) { + scale *= 0.7; + upscale = 0.25 / scale; + if (rp->display) lept_stderr("scale = %5.3f\n", scale); + pix2 = pixScaleSmooth(pix1, scale, scale); + pix3 = pixScale(pix2, upscale, upscale); + pixaAddPix(pixa, pix3, L_INSERT); + pixDestroy(&pix2); + } + pix2 = pixaDisplayTiledInColumns(pixa, 3, 1.0, 10, 2); + regTestWritePixAndCheck(rp, pix2, IFF_PNG); + pixDisplayWithTitle(pix2, 0, 300, NULL, rp->display); + pixaDestroy(&pixa); + pixDestroy(&pix1); + pixDestroy(&pix2); +} + diff --git a/leptonica/prog/scaleandtile.c b/leptonica/prog/scaleandtile.c new file mode 100644 index 00000000..d4b2608a --- /dev/null +++ b/leptonica/prog/scaleandtile.c @@ -0,0 +1,103 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * scaleandtile.c + * + * Generates a single image tiling of all images in a directory + * whose filename contains a given substring. The filenames + * are filtered and sorted, and read into a pixa, which is + * then tiled into a pix at a specified depth, and finally + * written out to file. + * + * Input: dirin: directory that has image files + * depth (output depth: 1, 8 or 32; use 32 for RGB) + * width (of each tile; all pix are scaled to the same width) + * ncols (number of tiles in each row) + * background (0 for white, 1 for black) + * fileout: output tiled image file + * + * Note: this program is Unix only; it will not compile under cygwin. + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include <string.h> +#include "allheaders.h" + + /* Change these and recompile if necessary */ +static const l_int32 BACKGROUND_COLOR = 0; +static const l_int32 SPACING = 25; /* between images and on outside */ +static const l_int32 BLACK_BORDER = 2; /* surrounding each image */ + + +int main(int argc, + char **argv) +{ +char *dirin, *substr, *fileout; +l_int32 depth, width, ncols; +PIX *pixd; +PIXA *pixa; +static char mainName[] = "scaleandtile"; + + if (argc != 7) + return ERROR_INT( + "Syntax: scaleandtile dirin substr depth width ncols fileout", + mainName, 1); + dirin = argv[1]; + substr = argv[2]; + depth = atoi(argv[3]); + width = atoi(argv[4]); + ncols = atoi(argv[5]); + fileout = argv[6]; + setLeptDebugOK(1); + + /* Avoid division by zero if ncols == 0 and require a positive value. */ + if (ncols <= 0) + return ERROR_INT("Expected a positive value for ncols", mainName, 1); + + /* Read the specified images from file */ + if ((pixa = pixaReadFiles(dirin, substr)) == NULL) + return ERROR_INT("safiles not made", mainName, 1); + lept_stderr("Number of pix: %d\n", pixaGetCount(pixa)); + + /* Tile them */ + pixd = pixaDisplayTiledAndScaled(pixa, depth, width, ncols, + BACKGROUND_COLOR, SPACING, BLACK_BORDER); + + if (depth < 8) + pixWrite(fileout, pixd, IFF_PNG); + else + pixWrite(fileout, pixd, IFF_JFIF_JPEG); + + pixaDestroy(&pixa); + pixDestroy(&pixd); + return 0; +} + + diff --git a/leptonica/prog/scaletest1.c b/leptonica/prog/scaletest1.c new file mode 100644 index 00000000..0525832a --- /dev/null +++ b/leptonica/prog/scaletest1.c @@ -0,0 +1,92 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * scaletest1.c + * + * scaletest1 filein scalex scaley fileout + * where + * scalex, scaley are floating point input + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + +int main(int argc, + char **argv) +{ +char *filein, *fileout; +l_int32 d; +l_float32 scalex, scaley; +PIX *pixs, *pixd; +static char mainName[] = "scaletest1"; + + if (argc != 5) + return ERROR_INT(" Syntax: scaletest1 filein scalex scaley fileout", + mainName, 1); + filein = argv[1]; + scalex = atof(argv[2]); + scaley = atof(argv[3]); + fileout = argv[4]; + setLeptDebugOK(1); + + if ((pixs = pixRead(filein)) == NULL) + return ERROR_INT("pixs not made", mainName, 1); + + /* choose type of scaling operation */ +#if 1 + pixd = pixScale(pixs, scalex, scaley); +#elif 0 + pixd = pixScaleLI(pixs, scalex, scaley); +#elif 0 + pixd = pixScaleSmooth(pixs, scalex, scaley); +#elif 0 + pixd = pixScaleAreaMap(pixs, scalex, scaley); +#elif 0 + pixd = pixScaleBySampling(pixs, scalex, scaley); +#else + pixd = pixScaleToGray(pixs, scalex); +#endif + + d = pixGetDepth(pixd); + +#if 1 + if (d <= 8) + pixWrite(fileout, pixd, IFF_PNG); + else + pixWrite(fileout, pixd, IFF_JFIF_JPEG); +#else + pixWrite(fileout, pixd, IFF_PNG); +#endif + + pixDestroy(&pixs); + pixDestroy(&pixd); + return 0; +} + diff --git a/leptonica/prog/scaletest2.c b/leptonica/prog/scaletest2.c new file mode 100644 index 00000000..2aefa8c3 --- /dev/null +++ b/leptonica/prog/scaletest2.c @@ -0,0 +1,363 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * scaletest2.c + * + * Tests scale-to-gray, unsharp masking, smoothing, and color scaling + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + +#define DISPLAY 0 /* set to 1 to see the results */ + +int main(int argc, + char **argv) +{ +PIX *pixs; +l_int32 d; +static char mainName[] = "scaletest2"; + + if (argc != 2) + return ERROR_INT(" Syntax: scaletest2 filein", mainName, 1); + + setLeptDebugOK(1); + lept_mkdir("lept/scale"); + + if ((pixs = pixRead(argv[1])) == NULL) + return ERROR_INT("pixs not made", mainName, 1); + d = pixGetDepth(pixs); + +#if 1 + /* Integer scale-to-gray functions */ + if (d == 1) { + PIX *pixd; + + pixd = pixScaleToGray2(pixs); + pixWrite("/tmp/lept/scale/s2g_2x", pixd, IFF_PNG); + pixDestroy(&pixd); + pixd = pixScaleToGray3(pixs); + pixWrite("/tmp/lept/scale/s2g_3x", pixd, IFF_PNG); + pixDestroy(&pixd); + pixd = pixScaleToGray4(pixs); + pixWrite("/tmp/lept/scale/s2g_4x", pixd, IFF_PNG); + pixDestroy(&pixd); + pixd = pixScaleToGray6(pixs); + pixWrite("/tmp/lept/scale/s2g_6x", pixd, IFF_PNG); + pixDestroy(&pixd); + pixd = pixScaleToGray8(pixs); + pixWrite("/tmp/lept/scale/s2g_8x", pixd, IFF_PNG); + pixDestroy(&pixd); + pixd = pixScaleToGray16(pixs); + pixWrite("/tmp/lept/scale/s2g_16x", pixd, IFF_PNG); + pixDestroy(&pixd); + } +#endif + +#if 1 + /* Various non-integer scale-to-gray, compared with + * with different ways of getting similar results */ + if (d == 1) { + PIX *pixt, *pixd; + + pixd = pixScaleToGray8(pixs); + pixWrite("/tmp/lept/scale/s2g_8.png", pixd, IFF_PNG); + pixDestroy(&pixd); + + pixd = pixScaleToGray(pixs, 0.124); + pixWrite("/tmp/lept/scale/s2g_124.png", pixd, IFF_PNG); + pixDestroy(&pixd); + + pixd = pixScaleToGray(pixs, 0.284); + pixWrite("/tmp/lept/scale/s2g_284.png", pixd, IFF_PNG); + pixDestroy(&pixd); + + pixt = pixScaleToGray4(pixs); + pixd = pixScaleBySampling(pixt, 284./250., 284./250.); + pixWrite("/tmp/lept/scale/s2g_284.2.png", pixd, IFF_PNG); + pixDestroy(&pixt); + pixDestroy(&pixd); + + pixt = pixScaleToGray4(pixs); + pixd = pixScaleGrayLI(pixt, 284./250., 284./250.); + pixWrite("/tmp/lept/scale/s2g_284.3.png", pixd, IFF_PNG); + pixDestroy(&pixt); + pixDestroy(&pixd); + + pixt = pixScaleBinary(pixs, 284./250., 284./250.); + pixd = pixScaleToGray4(pixt); + pixWrite("/tmp/lept/scale/s2g_284.4.png", pixd, IFF_PNG); + pixDestroy(&pixt); + pixDestroy(&pixd); + + pixt = pixScaleToGray4(pixs); + pixd = pixScaleGrayLI(pixt, 0.49, 0.49); + pixWrite("/tmp/lept/scale/s2g_42.png", pixd, IFF_PNG); + pixDestroy(&pixt); + pixDestroy(&pixd); + + pixt = pixScaleToGray4(pixs); + pixd = pixScaleSmooth(pixt, 0.49, 0.49); + pixWrite("/tmp/lept/scale/s2g_4sm.png", pixd, IFF_PNG); + pixDestroy(&pixt); + pixDestroy(&pixd); + + pixt = pixScaleBinary(pixs, .16/.125, .16/.125); + pixd = pixScaleToGray8(pixt); + pixWrite("/tmp/lept/scale/s2g_16.png", pixd, IFF_PNG); + pixDestroy(&pixt); + pixDestroy(&pixd); + + pixd = pixScaleToGray(pixs, .16); + pixWrite("/tmp/lept/scale/s2g_16.2.png", pixd, IFF_PNG); + pixDestroy(&pixd); + } +#endif + +#if 1 + /* Antialiased (smoothed) reduction, along with sharpening */ + if (d != 1) { + PIX *pixt1, *pixt2; + + startTimer(); + pixt1 = pixScaleSmooth(pixs, 0.154, 0.154); + lept_stderr("fast scale: %5.3f sec\n", stopTimer()); + pixDisplayWithTitle(pixt1, 0, 0, "smooth scaling", DISPLAY); + pixWrite("/tmp/lept/scale/smooth1.png", pixt1, IFF_PNG); + pixt2 = pixUnsharpMasking(pixt1, 1, 0.3); + pixWrite("/tmp/lept/scale/smooth2.png", pixt2, IFF_PNG); + pixDisplayWithTitle(pixt2, 200, 0, "sharp scaling", DISPLAY); + pixDestroy(&pixt1); + pixDestroy(&pixt2); + } +#endif + + +#if 1 + /* Test a large range of scale-to-gray reductions */ + if (d == 1) { + l_int32 i; + l_float32 scale; + PIX *pixd; + + for (i = 2; i < 15; i++) { + scale = 1. / (l_float32)i; + startTimer(); + pixd = pixScaleToGray(pixs, scale); + lept_stderr("Time for scale %7.3f: %7.3f sec\n", + scale, stopTimer()); + pixDisplayWithTitle(pixd, 75 * i, 100, "scaletogray", DISPLAY); + pixDestroy(&pixd); + } + for (i = 8; i < 14; i++) { + scale = 1. / (l_float32)(2 * i); + startTimer(); + pixd = pixScaleToGray(pixs, scale); + lept_stderr("Time for scale %7.3f: %7.3f sec\n", + scale, stopTimer()); + pixDisplayWithTitle(pixd, 100 * i, 600, "scaletogray", DISPLAY); + pixDestroy(&pixd); + } + } +#endif + + +#if 1 + /* Test the same range of scale-to-gray mipmap reductions */ + if (d == 1) { + l_int32 i; + l_float32 scale; + PIX *pixd; + + for (i = 2; i < 15; i++) { + scale = 1. / (l_float32)i; + startTimer(); + pixd = pixScaleToGrayMipmap(pixs, scale); + lept_stderr("Time for scale %7.3f: %7.3f sec\n", + scale, stopTimer()); + pixDisplayWithTitle(pixd, 75 * i, 100, "scale mipmap", DISPLAY); + pixDestroy(&pixd); + } + for (i = 8; i < 12; i++) { + scale = 1. / (l_float32)(2 * i); + startTimer(); + pixd = pixScaleToGrayMipmap(pixs, scale); + lept_stderr("Time for scale %7.3f: %7.3f sec\n", + scale, stopTimer()); + pixDisplayWithTitle(pixd, 100 * i, 600, "scale mipmap", DISPLAY); + pixDestroy(&pixd); + } + } +#endif + +#if 1 + /* Test several methods for antialiased reduction, + * along with sharpening */ + if (d != 1) { + PIX *pixt1, *pixt2, *pixt3, *pixt4, *pixt5, *pixt6, *pixt7; + l_float32 SCALING = 0.27; + l_int32 SIZE = 7; + l_int32 smooth; + l_float32 FRACT = 1.0; + + smooth = SIZE / 2; + + startTimer(); + pixt1 = pixScaleSmooth(pixs, SCALING, SCALING); + lept_stderr("fast scale: %5.3f sec\n", stopTimer()); + pixDisplayWithTitle(pixt1, 0, 0, "smooth scaling", DISPLAY); + pixWrite("/tmp/lept/scale/sm_1.png", pixt1, IFF_PNG); + pixt2 = pixUnsharpMasking(pixt1, 1, 0.3); + pixDisplayWithTitle(pixt2, 150, 0, "sharpened scaling", DISPLAY); + + startTimer(); + pixt3 = pixBlockconv(pixs, smooth, smooth); + pixt4 = pixScaleBySampling(pixt3, SCALING, SCALING); + lept_stderr("slow scale: %5.3f sec\n", stopTimer()); + pixDisplayWithTitle(pixt4, 200, 200, "sampled scaling", DISPLAY); + pixWrite("/tmp/lept/scale/sm_2.png", pixt4, IFF_PNG); + + startTimer(); + pixt5 = pixUnsharpMasking(pixs, smooth, FRACT); + pixt6 = pixBlockconv(pixt5, smooth, smooth); + pixt7 = pixScaleBySampling(pixt6, SCALING, SCALING); + lept_stderr("very slow scale + sharp: %5.3f sec\n", stopTimer()); + pixDisplayWithTitle(pixt7, 500, 200, "sampled scaling", DISPLAY); + pixWrite("/tmp/lept/scale/sm_3.jpg", pixt7, IFF_JFIF_JPEG); + + pixDestroy(&pixt1); + pixDestroy(&pixt2); + pixDestroy(&pixt3); + pixDestroy(&pixt4); + pixDestroy(&pixt5); + pixDestroy(&pixt6); + pixDestroy(&pixt7); + } +#endif + + +#if 1 + /* Test the color scaling function, comparing the + * special case of scaling factor 2.0 with the + * general case. */ + if (d == 32) { + PIX *pix1, *pix2, *pixd; + NUMA *nar, *nag, *nab, *naseq; + GPLOT *gplot; + + startTimer(); + pix1 = pixScaleColorLI(pixs, 2.00001, 2.0); + lept_stderr(" Time with regular LI: %7.3f\n", stopTimer()); + pixWrite("/tmp/lept/scale/color1.jpg", pix1, IFF_JFIF_JPEG); + startTimer(); + pix2 = pixScaleColorLI(pixs, 2.0, 2.0); + lept_stderr(" Time with 2x LI: %7.3f\n", stopTimer()); + pixWrite("/tmp/lept/scale/color2.jpg", pix2, IFF_JFIF_JPEG); + + pixd = pixAbsDifference(pix1, pix2); + pixGetColorHistogram(pixd, 1, &nar, &nag, &nab); + naseq = numaMakeSequence(0., 1., 256); + gplot = gplotCreate("/tmp/lept/scale/c_absdiff", GPLOT_PNG, + "Number vs diff", "diff", "number"); + gplotSetScaling(gplot, GPLOT_LOG_SCALE_Y); + gplotAddPlot(gplot, naseq, nar, GPLOT_POINTS, "red"); + gplotAddPlot(gplot, naseq, nag, GPLOT_POINTS, "green"); + gplotAddPlot(gplot, naseq, nab, GPLOT_POINTS, "blue"); + gplotMakeOutput(gplot); + l_fileDisplay("/tmp/lept/scale/c_absdiff.png", 0, 100, 1.0); + pixDestroy(&pix1); + pixDestroy(&pix2); + pixDestroy(&pixd); + numaDestroy(&naseq); + numaDestroy(&nar); + numaDestroy(&nag); + numaDestroy(&nab); + gplotDestroy(&gplot); + } +#endif + + +#if 1 + /* Test the gray LI scaling function, comparing the + * special cases of scaling factor 2.0 and 4.0 with the + * general case */ + if (d == 8 || d == 32) { + PIX *pixt, *pix0, *pix1, *pix2, *pixd; + NUMA *nagray, *naseq; + GPLOT *gplot; + + if (d == 8) + pixt = pixClone(pixs); + else + pixt = pixConvertRGBToGray(pixs, 0.33, 0.34, 0.33); + pix0 = pixScaleGrayLI(pixt, 0.5, 0.5); + +#if 1 + startTimer(); + pix1 = pixScaleGrayLI(pix0, 2.00001, 2.0); + lept_stderr(" Time with regular LI 2x: %7.3f\n", stopTimer()); + startTimer(); + pix2 = pixScaleGrayLI(pix0, 2.0, 2.0); + lept_stderr(" Time with 2x LI: %7.3f\n", stopTimer()); +#else + startTimer(); + pix1 = pixScaleGrayLI(pix0, 4.00001, 4.0); + lept_stderr(" Time with regular LI 4x: %7.3f\n", stopTimer()); + startTimer(); + pix2 = pixScaleGrayLI(pix0, 4.0, 4.0); + lept_stderr(" Time with 2x LI: %7.3f\n", stopTimer()); +#endif + pixWrite("/tmp/lept/scale/gray1", pix1, IFF_JFIF_JPEG); + pixWrite("/tmp/lept/scale/gray2", pix2, IFF_JFIF_JPEG); + + pixd = pixAbsDifference(pix1, pix2); + nagray = pixGetGrayHistogram(pixd, 1); + naseq = numaMakeSequence(0., 1., 256); + gplot = gplotCreate("/tmp/lept/scale/g_absdiff", GPLOT_PNG, + "Number vs diff", "diff", "number"); + gplotSetScaling(gplot, GPLOT_LOG_SCALE_Y); + gplotAddPlot(gplot, naseq, nagray, GPLOT_POINTS, "gray"); + gplotMakeOutput(gplot); + l_fileDisplay("/tmp/lept/scale/g_absdiff.png", 750, 100, 1.0); + pixDestroy(&pixt); + pixDestroy(&pix0); + pixDestroy(&pix1); + pixDestroy(&pix2); + pixDestroy(&pixd); + numaDestroy(&naseq); + numaDestroy(&nagray); + gplotDestroy(&gplot); + } +#endif + + pixDestroy(&pixs); + return 0; +} + diff --git a/leptonica/prog/scots-frag.tif b/leptonica/prog/scots-frag.tif Binary files differnew file mode 100644 index 00000000..f030ebf9 --- /dev/null +++ b/leptonica/prog/scots-frag.tif diff --git a/leptonica/prog/seedfilltest.c b/leptonica/prog/seedfilltest.c new file mode 100644 index 00000000..8249bffc --- /dev/null +++ b/leptonica/prog/seedfilltest.c @@ -0,0 +1,170 @@ +/*====================================================================* + - 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. + *====================================================================*/ + + +/* + * seedfilltest.c + * + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + +#define NTIMES 5 +#define CONNECTIVITY 8 +#define XS 150 +#define YS 150 +#define DFLAG 1 + +int main(int argc, + char **argv) +{ +char *filein, *fileout; +l_int32 i; +l_uint32 val; +l_float32 size; +PIX *pixs, *pixd, *pixm, *pixmi, *pixt1, *pixt2, *pixt3; +static char mainName[] = "seedfilltest"; + + if (argc != 3) + return ERROR_INT(" Syntax: seedfilltest filein fileout", mainName, 1); + filein = argv[1]; + fileout = argv[2]; + pixd = NULL; + setLeptDebugOK(1); + + if ((pixm = pixRead(filein)) == NULL) + return ERROR_INT("pixm not made", mainName, 1); + pixmi = pixInvert(NULL, pixm); + + size = pixGetWidth(pixm) * pixGetHeight(pixm); + pixs = pixCreateTemplate(pixm); + for (i = 0; i < 100; i++) { + pixGetPixel(pixm, XS + 5 * i, YS + 5 * i, &val); + if (val == 0) break; + } + if (i == 100) + return ERROR_INT("no seed pixel found", mainName, 1); + pixSetPixel(pixs, XS + 5 * i, YS + 5 * i, 1); + +#if 0 + /* hole filling; use "hole-filler.png" */ + pixt1 = pixHDome(pixmi, 100, 4); + pixt2 = pixThresholdToBinary(pixt1, 10); +/* pixInvert(pixt1, pixt1); */ + pixDisplay(pixt1, 100, 500); + pixDisplay(pixt2, 600, 500); + pixt3 = pixHolesByFilling(pixt2, 4); + pixDilateBrick(pixt3, pixt3, 7, 7); + pixd = pixConvertTo8(pixt3, FALSE); + pixDisplay(pixd, 0, 100); + pixSeedfillGray(pixd, pixmi, CONNECTIVITY); + pixInvert(pixd, pixd); + pixDisplay(pixmi, 500, 100); + pixDisplay(pixd, 1000, 100); + pixWrite("/tmp/junkpixm.png", pixmi, IFF_PNG); + pixWrite("/tmp/junkpixd.png", pixd, IFF_PNG); +#endif + +#if 0 + /* hole filling; use "hole-filler.png" */ + pixt1 = pixThresholdToBinary(pixm, 110); + pixInvert(pixt1, pixt1); + pixDisplay(pixt1, 100, 500); + pixt2 = pixHolesByFilling(pixt1, 4); + pixd = pixConvertTo8(pixt2, FALSE); + pixDisplay(pixd, 0, 100); + pixSeedfillGray(pixd, pixmi, CONNECTIVITY); + pixInvert(pixd, pixd); + pixDisplay(pixmi, 500, 100); + pixDisplay(pixd, 1000, 100); + pixWrite("/tmp/junkpixm.png", pixmi, IFF_PNG); + pixWrite("/tmp/junkpixd.png", pixd, IFF_PNG); +#endif + +#if 0 + /* hole filling; use "hole-filler.png" */ + pixd = pixInvert(NULL, pixm); + pixAddConstantGray(pixd, -50); + pixDisplay(pixd, 0, 100); +/* pixt1 = pixThresholdToBinary(pixd, 20); + pixDisplayWithTitle(pixt1, 600, 600, "pixt1", DFLAG); */ + pixSeedfillGray(pixd, pixmi, CONNECTIVITY); +/* pixInvert(pixd, pixd); */ + pixDisplay(pixmi, 500, 100); + pixDisplay(pixd, 1000, 100); + pixWrite("/tmp/junkpixm.png", pixmi, IFF_PNG); + pixWrite("/tmp/junkpixd.png", pixd, IFF_PNG); +#endif + +#if 0 + /* test in-place seedfill for speed */ + pixd = pixClone(pixs); + startTimer(); + pixSeedfillBinary(pixs, pixs, pixmi, CONNECTIVITY); + lept_stderr("Filling rate: %7.4f Mpix/sec\n", + (size/1000000.) / stopTimer()); + + pixWrite(fileout, pixd, IFF_PNG); + pixOr(pixd, pixd, pixm); + pixWrite("/tmp/junkout1.png", pixd, IFF_PNG); +#endif + +#if 0 + /* test seedfill to dest for speed */ + pixd = pixCreateTemplate(pixm); + startTimer(); + for (i = 0; i < NTIMES; i++) { + pixSeedfillBinary(pixd, pixs, pixmi, CONNECTIVITY); + } + lept_stderr("Filling rate: %7.4f Mpix/sec\n", + (size/1000000.) * NTIMES / stopTimer()); + + pixWrite(fileout, pixd, IFF_PNG); + pixOr(pixd, pixd, pixm); + pixWrite("/tmp/junkout1.png", pixd, IFF_PNG); +#endif + + /* use same connectivity to compare with the result of the + * slow parallel operation */ +#if 1 + pixDestroy(&pixd); + pixd = pixSeedfillMorph(pixs, pixmi, 100, CONNECTIVITY); + pixOr(pixd, pixd, pixm); + pixWrite("/tmp/junkout2.png", pixd, IFF_PNG); +#endif + + pixDestroy(&pixs); + pixDestroy(&pixm); + pixDestroy(&pixmi); + pixDestroy(&pixd); + return 0; +} + + diff --git a/leptonica/prog/seedspread_reg.c b/leptonica/prog/seedspread_reg.c new file mode 100644 index 00000000..20038ceb --- /dev/null +++ b/leptonica/prog/seedspread_reg.c @@ -0,0 +1,160 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * seedspread_reg.c + * + * Tests the seedspreading (voronoi finding & filling) function + * for both 4 and 8 connectivity. + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + +static const l_int32 scalefact = 1.0; + +int main(int argc, + char **argv) +{ +l_int32 i, j, x, y, val; +PIX *pixsq, *pixs, *pixc, *pixd; +PIXA *pixa; +L_REGPARAMS *rp; + + if (regTestSetup(argc, argv, &rp)) + return 1; + + pixsq = pixCreate(3, 3, 32); + pixSetAllArbitrary(pixsq, 0x00ff0000); + pixa = pixaCreate(6); + + /* Moderately dense */ + pixs = pixCreate(300, 300, 8); + for (i = 0; i < 100; i++) { + x = (153 * i * i * i + 59) % 299; + y = (117 * i * i * i + 241) % 299; + val = (97 * i + 74) % 256; + pixSetPixel(pixs, x, y, val); + } + + pixd = pixSeedspread(pixs, 4); /* 4-cc */ + pixc = pixConvertTo32(pixd); + for (i = 0; i < 100; i++) { + x = (153 * i * i * i + 59) % 299; + y = (117 * i * i * i + 241) % 299; + pixRasterop(pixc, x - 1, y - 1, 3, 3, PIX_SRC, pixsq, 0, 0); + } + pixaAddPix(pixa, pixc, L_INSERT); + regTestWritePixAndCheck(rp, pixc, IFF_PNG); /* 0 */ + pixDisplayWithTitle(pixc, 100, 100, "4-cc", rp->display); + pixDestroy(&pixd); + + pixd = pixSeedspread(pixs, 8); /* 8-cc */ + pixc = pixConvertTo32(pixd); + for (i = 0; i < 100; i++) { + x = (153 * i * i * i + 59) % 299; + y = (117 * i * i * i + 241) % 299; + pixRasterop(pixc, x - 1, y - 1, 3, 3, PIX_SRC, pixsq, 0, 0); + } + pixaAddPix(pixa, pixc, L_INSERT); + regTestWritePixAndCheck(rp, pixc, IFF_PNG); /* 1 */ + pixDisplayWithTitle(pixc, 410, 100, "8-cc", rp->display); + pixDestroy(&pixd); + pixDestroy(&pixs); + + /* Regular lattice */ + pixs = pixCreate(200, 200, 8); + for (i = 5; i <= 195; i += 10) { + for (j = 5; j <= 195; j += 10) { + pixSetPixel(pixs, i, j, (7 * i + 17 * j) % 255); + } + } + pixd = pixSeedspread(pixs, 4); /* 4-cc */ + pixc = pixConvertTo32(pixd); + for (i = 5; i <= 195; i += 10) { + for (j = 5; j <= 195; j += 10) { + pixRasterop(pixc, j - 1, i - 1, 3, 3, PIX_SRC, pixsq, 0, 0); + } + } + pixaAddPix(pixa, pixc, L_INSERT); + regTestWritePixAndCheck(rp, pixc, IFF_PNG); /* 2 */ + pixDisplayWithTitle(pixc, 100, 430, "4-cc", rp->display); + pixDestroy(&pixd); + + pixd = pixSeedspread(pixs, 8); /* 8-cc */ + pixc = pixConvertTo32(pixd); + for (i = 5; i <= 195; i += 10) { + for (j = 5; j <= 195; j += 10) { + pixRasterop(pixc, j - 1, i - 1, 3, 3, PIX_SRC, pixsq, 0, 0); + } + } + pixaAddPix(pixa, pixc, L_INSERT); + regTestWritePixAndCheck(rp, pixc, IFF_PNG); /* 3 */ + pixDisplayWithTitle(pixc, 310, 430, "8-cc", rp->display); + pixDestroy(&pixd); + pixDestroy(&pixs); + + /* Very sparse points */ + pixs = pixCreate(200, 200, 8); + pixSetPixel(pixs, 60, 20, 90); + pixSetPixel(pixs, 160, 40, 130); + pixSetPixel(pixs, 80, 80, 205); + pixSetPixel(pixs, 40, 160, 115); + pixd = pixSeedspread(pixs, 4); /* 4-cc */ + pixc = pixConvertTo32(pixd); + pixRasterop(pixc, 60 - 1, 20 - 1, 3, 3, PIX_SRC, pixsq, 0, 0); + pixRasterop(pixc, 160 - 1, 40 - 1, 3, 3, PIX_SRC, pixsq, 0, 0); + pixRasterop(pixc, 80 - 1, 80 - 1, 3, 3, PIX_SRC, pixsq, 0, 0); + pixRasterop(pixc, 40 - 1, 160 - 1, 3, 3, PIX_SRC, pixsq, 0, 0); + pixaAddPix(pixa, pixc, L_INSERT); + regTestWritePixAndCheck(rp, pixc, IFF_PNG); /* 4 */ + pixDisplayWithTitle(pixc, 100, 600, "4-cc", rp->display); + pixDestroy(&pixd); + + pixd = pixSeedspread(pixs, 8); /* 8-cc */ + pixc = pixConvertTo32(pixd); + pixRasterop(pixc, 60 - 1, 20 - 1, 3, 3, PIX_SRC, pixsq, 0, 0); + pixRasterop(pixc, 160 - 1, 40 - 1, 3, 3, PIX_SRC, pixsq, 0, 0); + pixRasterop(pixc, 80 - 1, 80 - 1, 3, 3, PIX_SRC, pixsq, 0, 0); + pixRasterop(pixc, 40 - 1, 160 - 1, 3, 3, PIX_SRC, pixsq, 0, 0); + pixaAddPix(pixa, pixc, L_INSERT); + regTestWritePixAndCheck(rp, pixc, IFF_PNG); /* 5 */ + pixDisplayWithTitle(pixc, 310, 660, "8-cc", rp->display); + pixDestroy(&pixd); + pixDestroy(&pixs); + pixDestroy(&pixsq); + + pixd = pixaDisplayTiledInColumns(pixa, 2, scalefact, 20, 0); + regTestWritePixAndCheck(rp, pixd, IFF_PNG); /* 6 */ + pixDisplayWithTitle(pixd, 720, 100, "Final", rp->display); + + pixaDestroy(&pixa); + pixDestroy(&pixd); + return regTestCleanup(rp); +} diff --git a/leptonica/prog/selio_reg.c b/leptonica/prog/selio_reg.c new file mode 100644 index 00000000..4b920322 --- /dev/null +++ b/leptonica/prog/selio_reg.c @@ -0,0 +1,133 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * selio_reg.c + * + * Runs a number of tests on reading and writing of Sels + * + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include <string.h> +#include "allheaders.h" + +static const char *textsel1 = "x oo " + "x oOo " + "x o " + "x " + "xxxxxx"; +static const char *textsel2 = " oo x" + " oOo x" + " o x" + " x" + "xxxxxx"; +static const char *textsel3 = "xxxxxx" + "x " + "x o " + "x oOo " + "x oo "; +static const char *textsel4 = "xxxxxx" + " x" + " o x" + " oOo x" + " oo x"; +static const char *textsel5 = "xxxxxx" + " x" + " o x" + " ooo x" + " oo x"; +static const char *textsel6 = "xxXxxx" + " x" + " o x" + " oOo x" + " oo x"; + + +int main(int argc, + char **argv) +{ +l_float32 val; +PIX *pix; +SEL *sel; +SELA *sela1, *sela2; +L_REGPARAMS *rp; + + if (regTestSetup(argc, argv, &rp)) + return 1; + + /* selaRead() / selaWrite() */ + sela1 = selaAddBasic(NULL); + selaWrite("/tmp/lept/regout/sel.0.sela", sela1); + regTestCheckFile(rp, "/tmp/lept/regout/sel.0.sela"); /* 0 */ + sela2 = selaRead("/tmp/lept/regout/sel.0.sela"); + selaWrite("/tmp/lept/regout/sel.1.sela", sela2); + regTestCheckFile(rp, "/tmp/lept/regout/sel.1.sela"); /* 1 */ + regTestCompareFiles(rp, 0, 1); /* 2 */ + selaDestroy(&sela1); + selaDestroy(&sela2); + + /* Create from file and display result */ + sela1 = selaCreateFromFile("flipsels.txt"); + pix = selaDisplayInPix(sela1, 31, 3, 15, 4); + regTestWritePixAndCheck(rp, pix, IFF_PNG); /* 3 */ + pixDisplayWithTitle(pix, 100, 100, NULL, rp->display); + selaWrite("/tmp/lept/regout/sel.3.sela", sela1); + regTestCheckFile(rp, "/tmp/lept/regout/sel.3.sela"); /* 4 */ + pixDestroy(&pix); + selaDestroy(&sela1); + + /* Create the same set of Sels from compiled strings and compare */ + sela2 = selaCreate(4); + sel = selCreateFromString(textsel1, 5, 6, "textsel1"); + selaAddSel(sela2, sel, NULL, 0); + sel = selCreateFromString(textsel2, 5, 6, "textsel2"); + selaAddSel(sela2, sel, NULL, 0); + sel = selCreateFromString(textsel3, 5, 6, "textsel3"); + selaAddSel(sela2, sel, NULL, 0); + sel = selCreateFromString(textsel4, 5, 6, "textsel4"); + selaAddSel(sela2, sel, NULL, 0); + selaWrite("/tmp/lept/regout/sel.4.sela", sela2); + regTestCheckFile(rp, "/tmp/lept/regout/sel.4.sela"); /* 5 */ + regTestCompareFiles(rp, 4, 5); /* 6 */ + selaDestroy(&sela2); + + /* Attempt to create sels from invalid strings (0 or 2 origins) */ + lept_stderr("******************************************************\n"); + lept_stderr("* The next 2 error messages are intentional *\n"); + sel = selCreateFromString(textsel5, 5, 6, "textsel5"); + val = (sel) ? 1.0 : 0.0; + regTestCompareValues(rp, val, 0.0, 0.0); /* 6 */ + sel = selCreateFromString(textsel6, 5, 6, "textsel6"); + val = (sel) ? 1.0 : 0.0; + regTestCompareValues(rp, val, 0.0, 0.0); /* 7 */ + lept_stderr("******************************************************\n"); + + return regTestCleanup(rp); +} diff --git a/leptonica/prog/settest.c b/leptonica/prog/settest.c new file mode 100644 index 00000000..dac1f7ac --- /dev/null +++ b/leptonica/prog/settest.c @@ -0,0 +1,146 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * settest.c + * + * Tests set function for RGB (uint32) keys. + * + * We take a colormapped image and use the set to find the unique + * colors in the image. These are stored as 32-bit rgb keys. + * Also test the iterator on the set. + * + * For a more complete set of tests, see the operations tested in maptest.c. + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + +static L_ASET *BuildSet(PIX *pix, l_int32 factor, l_int32 print); +static void TestSetIterator(L_ASET *s, l_int32 print); + + +l_int32 main(int argc, + char **argv) +{ +L_ASET *s; +PIX *pix; + + setLeptDebugOK(1); + pix = pixRead("weasel8.240c.png"); + + /* Build the set from all the pixels. */ + s = BuildSet(pix, 1, FALSE); + TestSetIterator(s, FALSE); + l_asetDestroy(&s); + + /* Ditto, but just with a few pixels */ + s = BuildSet(pix, 10, TRUE); + TestSetIterator(s, TRUE); + l_asetDestroy(&s); + pixDestroy(&pix); + + pix = pixRead("marge.jpg"); + startTimer(); + s = BuildSet(pix, 1, FALSE); + lept_stderr("Time (250K pixels): %7.3f sec\n", stopTimer()); + TestSetIterator(s, FALSE); + l_asetDestroy(&s); + pixDestroy(&pix); + return 0; +} + +static L_ASET * +BuildSet(PIX *pix, + l_int32 factor, + l_int32 print) +{ +l_int32 i, j, w, h, wpl, val; +l_uint32 val32; +l_uint32 *data, *line; +L_ASET *s; +PIXCMAP *cmap; +RB_TYPE key; +RB_TYPE *pval; + + lept_stderr("\n --------------- Begin building set --------------\n"); + s = l_asetCreate(L_UINT_TYPE); + data = pixGetData(pix); + wpl = pixGetWpl(pix); + cmap = pixGetColormap(pix); + pixGetDimensions(pix, &w, &h, NULL); + for (i = 0; i < h; i += factor) { + line = data + i * wpl; + for (j = 0; j < w; j += factor) { + if (cmap) { + val = GET_DATA_BYTE(line, j); + pixcmapGetColor32(cmap, val, &val32); + key.utype = val32; + } else { + key.utype = line[j]; + } + pval = l_asetFind(s, key); + if (pval && print) + lept_stderr("key = %llx\n", key.utype); + l_asetInsert(s, key); + } + } + lept_stderr("Size: %d\n", l_asetSize(s)); + if (print) + l_rbtreePrint(stderr, s); + lept_stderr(" ----------- End Building set -----------------\n"); + + return s; +} + +static void +TestSetIterator(L_ASET *s, + l_int32 print) +{ +l_int32 count; +L_ASET_NODE *n; + + n = l_asetGetFirst(s); + count = 0; + lept_stderr("\n --------------- Begin iter listing --------------\n"); + while (n) { + count++; + if (print) +#if 0 + lept_stderr("key = %x\n", n->key.utype); +#else + lept_stderr("key = %llx\n", n->key.utype); +#endif + n = l_asetGetNext(n); + } + lept_stderr("Count from iterator: %d\n", count); + lept_stderr(" --------------- End iter listing --------------\n"); + return; +} + diff --git a/leptonica/prog/sevens.tif b/leptonica/prog/sevens.tif Binary files differnew file mode 100644 index 00000000..46d7e4f4 --- /dev/null +++ b/leptonica/prog/sevens.tif diff --git a/leptonica/prog/sharptest.c b/leptonica/prog/sharptest.c new file mode 100644 index 00000000..a4ea764c --- /dev/null +++ b/leptonica/prog/sharptest.c @@ -0,0 +1,70 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * sharptest.c + * + * sharptest filein smooth fract fileout + * + * (1) Use smooth = 1 for 3x3 smoothing filter + * smooth = 2 for 5x5 smoothing filter, etc. + * (2) Use fract in typical range (0.2 - 0.7) + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + +int main(int argc, + char **argv) +{ +PIX *pixs, *pixd; +l_int32 smooth; +l_float32 fract; +char *filein, *fileout; +static char mainName[] = "sharptest"; + + if (argc != 5) + return ERROR_INT(" Syntax: sharptest filein smooth fract fileout", + mainName, 1); + filein = argv[1]; + smooth = atoi(argv[2]); + fract = atof(argv[3]); + fileout = argv[4]; + setLeptDebugOK(1); + + if ((pixs = pixRead(filein)) == NULL) + return ERROR_INT("pixs not made", mainName, 1); + + pixd = pixUnsharpMasking(pixs, smooth, fract); + pixWrite(fileout, pixd, IFF_JFIF_JPEG); + pixDestroy(&pixs); + pixDestroy(&pixd); + return 0; +} + diff --git a/leptonica/prog/shear1_reg.c b/leptonica/prog/shear1_reg.c new file mode 100644 index 00000000..ec319923 --- /dev/null +++ b/leptonica/prog/shear1_reg.c @@ -0,0 +1,283 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * shear1_reg.c + * + * Regression test for shear, both IP and to new pix. + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + +#define BINARY_IMAGE "test1.png" +#define TWO_BPP_IMAGE "weasel2.4c.png" +#define FOUR_BPP_IMAGE1 "weasel4.11c.png" +#define FOUR_BPP_IMAGE2 "weasel4.16g.png" +#define EIGHT_BPP_IMAGE "test8.jpg" +#define EIGHT_BPP_CMAP_IMAGE1 "dreyfus8.png" +#define EIGHT_BPP_CMAP_IMAGE2 "test24.jpg" +#define RGB_IMAGE "marge.jpg" + +static PIX *shearTest1(PIX *pixs, l_float32 scale); +static PIX *shearTest2(PIX *pixs, L_REGPARAMS *rp); + +static const l_float32 ANGLE1 = 3.14159265 / 12.; + +l_int32 main(int argc, + char **argv) +{ +l_int32 index; +PIX *pixs, *pix1, *pixc, *pixd; +PIXCMAP *cmap; +L_REGPARAMS *rp; + + if (regTestSetup(argc, argv, &rp)) + return 1; + + lept_stderr("Test binary image:\n"); + pixs = pixRead(BINARY_IMAGE); + pixd = shearTest1(pixs, 1.0); + regTestWritePixAndCheck(rp, pixd, IFF_PNG); /* 0 */ + pixDisplayWithTitle(pixd, 100, 100, NULL, rp->display); + pixDestroy(&pixs); + pixDestroy(&pixd); + + /* We change the black to dark red so that we can see + * that the IP shear does brings in that color. It + * can't bring in black because the cmap is filled. */ + lept_stderr("Test 2 bpp cmapped image with filled cmap:\n"); + pixs = pixRead(TWO_BPP_IMAGE); + cmap = pixGetColormap(pixs); + pixcmapGetIndex(cmap, 40, 44, 40, &index); + pixcmapResetColor(cmap, index, 100, 0, 0); + pixd = shearTest1(pixs, 1.0); + regTestWritePixAndCheck(rp, pixd, IFF_PNG); /* 1 */ + pixDisplayWithTitle(pixd, 100, 100, NULL, rp->display); + pixDestroy(&pixs); + pixDestroy(&pixd); + + lept_stderr("Test 4 bpp cmapped image with unfilled cmap:\n"); + pixs = pixRead(FOUR_BPP_IMAGE1); + pixd = shearTest1(pixs, 1.0); + regTestWritePixAndCheck(rp, pixd, IFF_PNG); /* 2 */ + pixDisplayWithTitle(pixd, 100, 100, NULL, rp->display); + pixDestroy(&pixs); + pixDestroy(&pixd); + + lept_stderr("Test 4 bpp cmapped image with filled cmap:\n"); + pixs = pixRead(FOUR_BPP_IMAGE2); + pixd = shearTest1(pixs, 1.0); + regTestWritePixAndCheck(rp, pixd, IFF_PNG); /* 3 */ + pixDisplayWithTitle(pixd, 100, 100, NULL, rp->display); + pixDestroy(&pixs); + pixDestroy(&pixd); + + lept_stderr("Test 8 bpp grayscale image:\n"); + pixs = pixRead(EIGHT_BPP_IMAGE); + pix1 = pixScale(pixs, 0.5, 0.5); + pixd = shearTest1(pixs, 1.0); + regTestWritePixAndCheck(rp, pixd, IFF_JFIF_JPEG); /* 4 */ + pixDisplayWithTitle(pixd, 100, 100, NULL, rp->display); + pixDestroy(&pixs); + pixDestroy(&pix1); + pixDestroy(&pixd); + + lept_stderr("Test 8 bpp grayscale cmap image:\n"); + pixs = pixRead(EIGHT_BPP_CMAP_IMAGE1); + pixd = shearTest1(pixs, 1.0); + regTestWritePixAndCheck(rp, pixd, IFF_PNG); /* 5 */ + pixDisplayWithTitle(pixd, 100, 100, NULL, rp->display); + pixDestroy(&pixs); + pixDestroy(&pixd); + + lept_stderr("Test 8 bpp color cmap image:\n"); + pixs = pixRead(EIGHT_BPP_CMAP_IMAGE2); + pix1 = pixScale(pixs, 0.3, 0.3); + pixd = pixOctreeColorQuant(pix1, 200, 0); + pixc = shearTest1(pixd, 1.0); + regTestWritePixAndCheck(rp, pixc, IFF_JFIF_JPEG); /* 6 */ + pixDisplayWithTitle(pixc, 100, 100, NULL, rp->display); + pixDestroy(&pixs); + pixDestroy(&pix1); + pixDestroy(&pixd); + pixDestroy(&pixc); + + lept_stderr("Test rgb image:\n"); + pixs = pixRead(RGB_IMAGE); + pix1 = pixScale(pixs, 0.3, 0.3); + pixd = shearTest1(pix1, 1.0); + regTestWritePixAndCheck(rp, pixd, IFF_JFIF_JPEG); /* 7 */ + pixDisplayWithTitle(pixd, 100, 100, NULL, rp->display); + pixDestroy(&pixs); + pixDestroy(&pix1); + pixDestroy(&pixd); + +#if 1 + lept_stderr("Test in-place shear on 4 bpp cmapped image:\n"); + pixs = pixRead(FOUR_BPP_IMAGE1); + pixd = shearTest2(pixs, rp); + regTestWritePixAndCheck(rp, pixd, IFF_PNG); /* 12 */ + pixDisplayWithTitle(pixd, 800, 100, NULL, rp->display); + pixDestroy(&pixs); + pixDestroy(&pixd); +#endif + + return regTestCleanup(rp); +} + +/* ------------------------------------------------------------- */ +static PIX * +shearTest1(PIX *pixs, + l_float32 scale) +{ +l_int32 w, h, d; +PIX *pix1, *pix2, *pixd; +PIXA *pixa; + + pixa = pixaCreate(0); + pixGetDimensions(pixs, &w, &h, &d); + + pix1 = pixHShear(NULL, pixs, 0, ANGLE1, L_BRING_IN_WHITE); + pixaAddPix(pixa, pix1, L_INSERT); + pix2 = pixHShear(NULL, pixs, h / 2, ANGLE1, L_BRING_IN_WHITE); + pixaAddPix(pixa, pix2, L_INSERT); + pix1 = pixHShear(NULL, pixs, 0, ANGLE1, L_BRING_IN_BLACK); + pixaAddPix(pixa, pix1, L_INSERT); + pix2 = pixHShear(NULL, pixs, h / 2, ANGLE1, L_BRING_IN_BLACK); + pixaAddPix(pixa, pix2, L_INSERT); + + if (!pixGetColormap(pixs)) { + pix1 = pixCopy(NULL, pixs); + pixHShearIP(pix1, 0, ANGLE1, L_BRING_IN_WHITE); + pixaAddPix(pixa, pix1, L_INSERT); + pix2 = pixCopy(NULL, pixs); + pixHShearIP(pix2, h / 2, ANGLE1, L_BRING_IN_WHITE); + pixaAddPix(pixa, pix2, L_INSERT); + pix1 = pixCopy(NULL, pixs); + pixHShearIP(pix1, 0, ANGLE1, L_BRING_IN_BLACK); + pixaAddPix(pixa, pix1, L_INSERT); + pix2 = pixCopy(NULL, pixs); + pixHShearIP(pix2, h / 2, ANGLE1, L_BRING_IN_BLACK); + pixaAddPix(pixa, pix2, L_INSERT); + } + + if (d == 8 || d == 32 || pixGetColormap(pixs)) { + pix1 = pixHShearLI(pixs, 0, ANGLE1, L_BRING_IN_WHITE); + pixaAddPix(pixa, pix1, L_INSERT); + pix2 = pixHShearLI(pixs, w / 2, ANGLE1, L_BRING_IN_WHITE); + pixaAddPix(pixa, pix2, L_INSERT); + pix1 = pixHShearLI(pixs, 0, ANGLE1, L_BRING_IN_BLACK); + pixaAddPix(pixa, pix1, L_INSERT); + pix2 = pixHShearLI(pixs, w / 2, ANGLE1, L_BRING_IN_BLACK); + pixaAddPix(pixa, pix2, L_INSERT); + } + + pix1 = pixVShear(NULL, pixs, 0, ANGLE1, L_BRING_IN_WHITE); + pixaAddPix(pixa, pix1, L_INSERT); + pix2 = pixVShear(NULL, pixs, w / 2, ANGLE1, L_BRING_IN_WHITE); + pixaAddPix(pixa, pix2, L_INSERT); + pix1 = pixVShear(NULL, pixs, 0, ANGLE1, L_BRING_IN_BLACK); + pixaAddPix(pixa, pix1, L_INSERT); + pix2 = pixVShear(NULL, pixs, w / 2, ANGLE1, L_BRING_IN_BLACK); + pixaAddPix(pixa, pix2, L_INSERT); + + if (!pixGetColormap(pixs)) { + pix1 = pixCopy(NULL, pixs); + pixVShearIP(pix1, 0, ANGLE1, L_BRING_IN_WHITE); + pixaAddPix(pixa, pix1, L_INSERT); + pix2 = pixCopy(NULL, pixs); + pixVShearIP(pix2, w / 2, ANGLE1, L_BRING_IN_WHITE); + pixaAddPix(pixa, pix2, L_INSERT); + pix1 = pixCopy(NULL, pixs); + pixVShearIP(pix1, 0, ANGLE1, L_BRING_IN_BLACK); + pixaAddPix(pixa, pix1, L_INSERT); + pix2 = pixCopy(NULL, pixs); + pixVShearIP(pix2, w / 2, ANGLE1, L_BRING_IN_BLACK); + pixaAddPix(pixa, pix2, L_INSERT); + } + + if (d == 8 || d == 32 || pixGetColormap(pixs)) { + pix1 = pixVShearLI(pixs, 0, ANGLE1, L_BRING_IN_WHITE); + pixaAddPix(pixa, pix1, L_INSERT); + pix2 = pixVShearLI(pixs, w / 2, ANGLE1, L_BRING_IN_WHITE); + pixaAddPix(pixa, pix2, L_INSERT); + pix1 = pixVShearLI(pixs, 0, ANGLE1, L_BRING_IN_BLACK); + pixaAddPix(pixa, pix1, L_INSERT); + pix2 = pixVShearLI(pixs, w / 2, ANGLE1, L_BRING_IN_BLACK); + pixaAddPix(pixa, pix2, L_INSERT); + } + + pixd = pixaDisplayTiledInColumns(pixa, 4, scale, 20, 0); + pixaDestroy(&pixa); + return pixd; +} + +/* ------------------------------------------------------------- */ +static PIX * +shearTest2(PIX *pixs, + L_REGPARAMS *rp) +{ +l_int32 w, h; +PIX *pix1, *pix2, *pixd; +PIXA *pixa; + + pixa = pixaCreate(0); + pixGetDimensions(pixs, &w, &h, NULL); + + pix1 = pixHShear(NULL, pixs, h / 2, ANGLE1, L_BRING_IN_WHITE); + pixaAddPix(pixa, pix1, L_INSERT); + pix2 = pixCopy(NULL, pixs); + pixHShear(pix2, pix2, h / 2, ANGLE1, L_BRING_IN_WHITE); + pixaAddPix(pixa, pix2, L_INSERT); + regTestComparePix(rp, pix1, pix2); /* 8 */ + pix1 = pixHShear(NULL, pixs, h / 2, ANGLE1, L_BRING_IN_BLACK); + pixaAddPix(pixa, pix1, L_INSERT); + pix2 = pixCopy(NULL, pixs); + pixHShear(pix2, pix2, h / 2, ANGLE1, L_BRING_IN_BLACK); + pixaAddPix(pixa, pix2, L_INSERT); + regTestComparePix(rp, pix1, pix2); /* 9 */ + + pix1 = pixVShear(NULL, pixs, w / 2, ANGLE1, L_BRING_IN_WHITE); + pixaAddPix(pixa, pix1, L_INSERT); + pix2 = pixCopy(NULL, pixs); + pixVShear(pix2, pix2, w / 2, ANGLE1, L_BRING_IN_WHITE); + pixaAddPix(pixa, pix2, L_INSERT); + regTestComparePix(rp, pix1, pix2); /* 10 */ + pix1 = pixVShear(NULL, pixs, w / 2, ANGLE1, L_BRING_IN_BLACK); + pixaAddPix(pixa, pix1, L_INSERT); + pix2 = pixCopy(NULL, pixs); + pixVShear(pix2, pix2, w / 2, ANGLE1, L_BRING_IN_BLACK); + pixaAddPix(pixa, pix2, L_INSERT); + regTestComparePix(rp, pix1, pix2); /* 11 */ + + pixd = pixaDisplayTiledInColumns(pixa, 2, 1.0, 20, 0); + pixaDestroy(&pixa); + return pixd; +} diff --git a/leptonica/prog/shear2_reg.c b/leptonica/prog/shear2_reg.c new file mode 100644 index 00000000..1922e59e --- /dev/null +++ b/leptonica/prog/shear2_reg.c @@ -0,0 +1,185 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * shear2_reg.c + * + * Regression test for quadratic shear, both sampled and interpolated. + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + +void PixSave(PIX **ppixs, PIXA *pixa, l_int32 newrow, + L_BMF *bmf, const char *textstr); + + +l_int32 main(int argc, + char **argv) +{ +L_BMF *bmf; +PIX *pixs1, *pixs2, *pixg, *pixt, *pixd; +PIXA *pixa; +L_REGPARAMS *rp; + +#if !defined(HAVE_LIBPNG) + L_ERROR("This test requires libpng to run.\n", "shear2_reg"); + exit(77); +#endif + + if (regTestSetup(argc, argv, &rp)) + return 1; + + bmf = bmfCreate("./fonts", 8); + pixs1 = pixCreate(301, 301, 32); + pixs2 = pixCreate(601, 601, 32); + pixSetAll(pixs1); + pixSetAll(pixs2); + pixRenderLineArb(pixs1, 0, 20, 300, 20, 5, 0, 0, 255); + pixRenderLineArb(pixs1, 0, 70, 300, 70, 5, 0, 255, 0); + pixRenderLineArb(pixs1, 0, 120, 300, 120, 5, 0, 255, 255); + pixRenderLineArb(pixs1, 0, 170, 300, 170, 5, 255, 0, 0); + pixRenderLineArb(pixs1, 0, 220, 300, 220, 5, 255, 0, 255); + pixRenderLineArb(pixs1, 0, 270, 300, 270, 5, 255, 255, 0); + pixRenderLineArb(pixs2, 0, 20, 300, 20, 5, 0, 0, 255); + pixRenderLineArb(pixs2, 0, 70, 300, 70, 5, 0, 255, 0); + pixRenderLineArb(pixs2, 0, 120, 300, 120, 5, 0, 255, 255); + pixRenderLineArb(pixs2, 0, 170, 300, 170, 5, 255, 0, 0); + pixRenderLineArb(pixs2, 0, 220, 300, 220, 5, 255, 0, 255); + pixRenderLineArb(pixs2, 0, 270, 300, 270, 5, 255, 255, 0); + + /* Color, small pix */ + pixa = pixaCreate(0); + pixt = pixQuadraticVShear(pixs1, L_WARP_TO_LEFT, + 60, -20, L_SAMPLED, L_BRING_IN_WHITE); + PixSave(&pixt, pixa, 1, bmf, "sampled-left"); + pixt = pixQuadraticVShear(pixs1, L_WARP_TO_RIGHT, + 60, -20, L_SAMPLED, L_BRING_IN_WHITE); + PixSave(&pixt, pixa, 0, bmf, "sampled-right"); + pixt = pixQuadraticVShear(pixs1, L_WARP_TO_LEFT, + 60, -20, L_INTERPOLATED, L_BRING_IN_WHITE); + PixSave(&pixt, pixa, 1, bmf, "interpolated-left"); + pixt = pixQuadraticVShear(pixs1, L_WARP_TO_RIGHT, + 60, -20, L_INTERPOLATED, L_BRING_IN_WHITE); + PixSave(&pixt, pixa, 0, bmf, "interpolated-right"); + pixd = pixaDisplayTiledInColumns(pixa, 2, 1.0, 20, 0); + regTestWritePixAndCheck(rp, pixd, IFF_PNG); + pixDisplayWithTitle(pixd, 50, 50, NULL, rp->display); + pixDestroy(&pixd); + pixaDestroy(&pixa); + + /* Grayscale, small pix */ + pixg = pixConvertTo8(pixs1, 0); + pixa = pixaCreate(0); + pixt = pixQuadraticVShear(pixg, L_WARP_TO_LEFT, + 60, -20, L_SAMPLED, L_BRING_IN_WHITE); + PixSave(&pixt, pixa, 1, bmf, "sampled-left"); + pixt = pixQuadraticVShear(pixg, L_WARP_TO_RIGHT, + 60, -20, L_SAMPLED, L_BRING_IN_WHITE); + PixSave(&pixt, pixa, 0, bmf, "sampled-right"); + pixt = pixQuadraticVShear(pixg, L_WARP_TO_LEFT, + 60, -20, L_INTERPOLATED, L_BRING_IN_WHITE); + PixSave(&pixt, pixa, 1, bmf, "interpolated-left"); + pixt = pixQuadraticVShear(pixg, L_WARP_TO_RIGHT, + 60, -20, L_INTERPOLATED, L_BRING_IN_WHITE); + PixSave(&pixt, pixa, 0, bmf, "interpolated-right"); + pixd = pixaDisplayTiledInColumns(pixa, 2, 1.0, 20, 0); + regTestWritePixAndCheck(rp, pixd, IFF_PNG); + pixDisplayWithTitle(pixd, 250, 50, NULL, rp->display); + pixDestroy(&pixg); + pixDestroy(&pixd); + pixaDestroy(&pixa); + + /* Color, larger pix */ + pixa = pixaCreate(0); + pixt = pixQuadraticVShear(pixs2, L_WARP_TO_LEFT, + 120, -40, L_SAMPLED, L_BRING_IN_WHITE); + PixSave(&pixt, pixa, 1, bmf, "sampled-left"); + pixt = pixQuadraticVShear(pixs2, L_WARP_TO_RIGHT, + 120, -40, L_SAMPLED, L_BRING_IN_WHITE); + PixSave(&pixt, pixa, 0, bmf, "sampled-right"); + pixt = pixQuadraticVShear(pixs2, L_WARP_TO_LEFT, + 120, -40, L_INTERPOLATED, L_BRING_IN_WHITE); + PixSave(&pixt, pixa, 1, bmf, "interpolated-left"); + pixt = pixQuadraticVShear(pixs2, L_WARP_TO_RIGHT, + 120, -40, L_INTERPOLATED, L_BRING_IN_WHITE); + PixSave(&pixt, pixa, 0, bmf, "interpolated-right"); + pixd = pixaDisplayTiledInColumns(pixa, 2, 1.0, 20, 0); + regTestWritePixAndCheck(rp, pixd, IFF_PNG); + pixDisplayWithTitle(pixd, 550, 50, NULL, rp->display); + pixDestroy(&pixd); + pixaDestroy(&pixa); + + /* Grayscale, larger pix */ + pixg = pixConvertTo8(pixs2, 0); + pixa = pixaCreate(0); + pixt = pixQuadraticVShear(pixg, L_WARP_TO_LEFT, + 60, -20, L_SAMPLED, L_BRING_IN_WHITE); + PixSave(&pixt, pixa, 1, bmf, "sampled-left"); + pixt = pixQuadraticVShear(pixg, L_WARP_TO_RIGHT, + 60, -20, L_SAMPLED, L_BRING_IN_WHITE); + PixSave(&pixt, pixa, 0, bmf, "sampled-right"); + pixt = pixQuadraticVShear(pixg, L_WARP_TO_LEFT, + 60, -20, L_INTERPOLATED, L_BRING_IN_WHITE); + PixSave(&pixt, pixa, 1, bmf, "interpolated-left"); + pixt = pixQuadraticVShear(pixg, L_WARP_TO_RIGHT, + 60, -20, L_INTERPOLATED, L_BRING_IN_WHITE); + PixSave(&pixt, pixa, 0, bmf, "interpolated-right"); + pixd = pixaDisplayTiledInColumns(pixa, 2, 1.0, 20, 0); + regTestWritePixAndCheck(rp, pixd, IFF_PNG); + pixDisplayWithTitle(pixd, 850, 50, NULL, rp->display); + pixDestroy(&pixg); + pixDestroy(&pixd); + pixaDestroy(&pixa); + + pixDestroy(&pixs1); + pixDestroy(&pixs2); + bmfDestroy(&bmf); + return regTestCleanup(rp); +} + + +void +PixSave(PIX **ppixs, + PIXA *pixa, + l_int32 newrow, + L_BMF *bmf, + const char *textstr) +{ +PIX *pix1, *pix2, *pix3; + + pix1 = pixConvertTo32(*ppixs); + pix2 = pixAddBorder(pix1, 3, 0); + pix3 = pixAddSingleTextblock(pix2, bmf, textstr, 0xff000000, L_ADD_BELOW, + NULL); + pixaAddPix(pixa, pix3, L_INSERT); + pixDestroy(&pix1); + pixDestroy(&pix2); + pixDestroy(ppixs); +} diff --git a/leptonica/prog/shearer.148.tif b/leptonica/prog/shearer.148.tif Binary files differnew file mode 100644 index 00000000..b619ea25 --- /dev/null +++ b/leptonica/prog/shearer.148.tif diff --git a/leptonica/prog/sheartest.c b/leptonica/prog/sheartest.c new file mode 100644 index 00000000..3dc691c1 --- /dev/null +++ b/leptonica/prog/sheartest.c @@ -0,0 +1,169 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * sheartest.c + * + * sheartest filein angle fileout + * + * where angle is expressed in degrees + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + +#define NTIMES 10 + +int main(int argc, + char **argv) +{ +char *filein, *fileout; +l_int32 i, w, h, liney, linex, same; +l_float32 angle, deg2rad; +PIX *pixt1, *pixt2, *pixs, *pixd; +static char mainName[] = "sheartest"; + + if (argc != 4) + return ERROR_INT(" Syntax: sheartest filein angle fileout", + mainName, 1); + + setLeptDebugOK(1); + + /* Compare in-place H shear with H shear to a new pix */ + pixt1 = pixRead("marge.jpg"); + pixGetDimensions(pixt1, &w, &h, NULL); + pixt2 = pixHShear(NULL, pixt1, (l_int32)(0.3 * h), 0.17, L_BRING_IN_WHITE); + pixHShearIP(pixt1, (l_int32)(0.3 * h), 0.17, L_BRING_IN_WHITE); + pixEqual(pixt1, pixt2, &same); + if (same) + lept_stderr("Correct for H shear\n"); + else + lept_stderr("Error for H shear\n"); + pixDestroy(&pixt1); + pixDestroy(&pixt2); + + /* Compare in-place V shear with V shear to a new pix */ + pixt1 = pixRead("marge.jpg"); + pixGetDimensions(pixt1, &w, &h, NULL); + pixt2 = pixVShear(NULL, pixt1, (l_int32)(0.3 * w), 0.17, L_BRING_IN_WHITE); + pixVShearIP(pixt1, (l_int32)(0.3 * w), 0.17, L_BRING_IN_WHITE); + pixEqual(pixt1, pixt2, &same); + if (same) + lept_stderr("Correct for V shear\n"); + else + lept_stderr("Error for V shear\n"); + pixDestroy(&pixt1); + pixDestroy(&pixt2); + + filein = argv[1]; + angle = atof(argv[2]); + fileout = argv[3]; + deg2rad = 3.1415926535 / 180.; + + if ((pixs = pixRead(filein)) == NULL) + return ERROR_INT("pix not made", mainName, 1); + + pixGetDimensions(pixs, &w, &h, NULL); + +#if 0 + /* Select an operation from this list ... + * ------------------------------------------ + pixd = pixHShear(NULL, pixs, liney, deg2rad * angle, L_BRING_IN_WHITE); + pixd = pixVShear(NULL, pixs, linex, deg2rad * angle, L_BRING_IN_WHITE); + pixd = pixHShearCorner(NULL, pixs, deg2rad * angle, L_BRING_IN_WHITE); + pixd = pixVShearCorner(NULL, pixs, deg2rad * angle, L_BRING_IN_WHITE); + pixd = pixHShearCenter(NULL, pixs, deg2rad * angle, L_BRING_IN_WHITE); + pixd = pixVShearCenter(NULL, pixs, deg2rad * angle, L_BRING_IN_WHITE); + pixHShearIP(pixs, liney, deg2rad * angle, L_BRING_IN_WHITE); pixd = pixs; + pixVShearIP(pixs, linex, deg2rad * angle, L_BRING_IN_WHITE); pixd = pixs; + pixRasteropHip(pixs, 0, h/3, -50, L_BRING_IN_WHITE); pixd = pixs; + pixRasteropVip(pixs, 0, w/3, -50, L_BRING_IN_WHITE); pixd = pixs; + * ------------------------------------------ + * ... and use it in the following: */ + pixd = pixHShear(NULL, pixs, liney, deg2rad * angle, L_BRING_IN_WHITE); + pixWrite(fileout, pixd, IFF_PNG); + pixDisplay(pixd, 50, 50); + pixDestroy(&pixd); +#endif + +#if 0 + /* Do a horizontal shear about a line */ + for (i = 0; i < NTIMES; i++) { + liney = i * h / (NTIMES - 1); + if (liney >= h) + liney = h - 1; + pixd = pixHShear(NULL, pixs, liney, deg2rad * angle, L_BRING_IN_WHITE); + pixDisplay(pixd, 50 + 10 * i, 50 + 10 * i); + pixDestroy(&pixd); + } +#endif + +#if 0 + /* Do a vertical shear about a line */ + for (i = 0; i < NTIMES; i++) { + linex = i * w / (NTIMES - 1); + if (linex >= w) + linex = w - 1; + pixd = pixVShear(NULL, pixs, linex, deg2rad * angle, L_BRING_IN_WHITE); + pixDisplay(pixd, 50 + 10 * i, 50 + 10 * i); + pixDestroy(&pixd); + } +#endif + +#if 0 + /* Do a horizontal in-place shear about a line */ + pixSetPadBits(pixs, 0); + for (i = 0; i < NTIMES; i++) { + pixd = pixCopy(NULL, pixs); + liney = i * h / (NTIMES - 1); + if (liney >= h) + liney = h - 1; + pixHShearIP(pixd, liney, deg2rad * angle, L_BRING_IN_WHITE); + pixDisplay(pixd, 50 + 10 * i, 50 + 10 * i); + pixDestroy(&pixd); + } +#endif + +#if 0 + /* Do a vertical in-place shear about a line */ + for (i = 0; i < NTIMES; i++) { + pixd = pixCopy(NULL, pixs); + linex = i * w / (NTIMES - 1); + if (linex >= w) + linex = w - 1; + pixVShearIP(pixd, linex, deg2rad * angle, L_BRING_IN_WHITE); + pixDisplay(pixd, 50 + 10 * i, 50 + 10 * i); + pixDestroy(&pixd); + } +#endif + + pixDestroy(&pixs); + return 0; +} + diff --git a/leptonica/prog/showboxes.pac b/leptonica/prog/showboxes.pac Binary files differnew file mode 100644 index 00000000..39b18ea7 --- /dev/null +++ b/leptonica/prog/showboxes.pac diff --git a/leptonica/prog/showboxes1.baa b/leptonica/prog/showboxes1.baa new file mode 100644 index 00000000..efe2ceb0 --- /dev/null +++ b/leptonica/prog/showboxes1.baa @@ -0,0 +1,27 @@ + +Boxaa Version 3 +Number of boxa = 2 + +Boxa[0] extent: x = 16, y = 6, w = 318, h = 228 +Boxa Version 2 +Number of boxes = 8 + Box[0]: x = 44, y = 8, w = 289, h = 226 + Box[1]: x = 44, y = 6, w = 288, h = 228 + Box[2]: x = 42, y = 11, w = 292, h = 223 + Box[3]: x = 16, y = 18, w = 297, h = 216 + Box[4]: x = 42, y = 10, w = 292, h = 224 + Box[5]: x = 42, y = 11, w = 291, h = 223 + Box[6]: x = 42, y = 10, w = 291, h = 224 + Box[7]: x = 43, y = 9, w = 291, h = 225 + +Boxa[1] extent: x = 22, y = 9, w = 309, h = 212 +Boxa Version 2 +Number of boxes = 8 + Box[0]: x = 53, y = 12, w = 277, h = 209 + Box[1]: x = 51, y = 22, w = 278, h = 162 + Box[2]: x = 51, y = 11, w = 280, h = 187 + Box[3]: x = 22, y = 21, w = 287, h = 198 + Box[4]: x = 50, y = 10, w = 281, h = 196 + Box[5]: x = 50, y = 11, w = 280, h = 184 + Box[6]: x = 50, y = 10, w = 280, h = 186 + Box[7]: x = 50, y = 9, w = 280, h = 192 diff --git a/leptonica/prog/showboxes2.baa b/leptonica/prog/showboxes2.baa new file mode 100644 index 00000000..c8a1b93f --- /dev/null +++ b/leptonica/prog/showboxes2.baa @@ -0,0 +1,51 @@ + +Boxaa Version 3 +Number of boxa = 8 + +Boxa[0] extent: x = 44, y = 8, w = 289, h = 226 +Boxa Version 2 +Number of boxes = 2 + Box[0]: x = 44, y = 8, w = 289, h = 226 + Box[1]: x = 53, y = 12, w = 277, h = 209 + +Boxa[1] extent: x = 44, y = 6, w = 288, h = 228 +Boxa Version 2 +Number of boxes = 2 + Box[0]: x = 44, y = 6, w = 288, h = 228 + Box[1]: x = 51, y = 22, w = 278, h = 162 + +Boxa[2] extent: x = 42, y = 11, w = 292, h = 223 +Boxa Version 2 +Number of boxes = 2 + Box[0]: x = 42, y = 11, w = 292, h = 223 + Box[1]: x = 51, y = 11, w = 280, h = 187 + +Boxa[3] extent: x = 16, y = 18, w = 297, h = 216 +Boxa Version 2 +Number of boxes = 2 + Box[0]: x = 16, y = 18, w = 297, h = 216 + Box[1]: x = 22, y = 21, w = 287, h = 198 + +Boxa[4] extent: x = 42, y = 10, w = 292, h = 224 +Boxa Version 2 +Number of boxes = 2 + Box[0]: x = 42, y = 10, w = 292, h = 224 + Box[1]: x = 50, y = 10, w = 281, h = 196 + +Boxa[5] extent: x = 42, y = 11, w = 291, h = 223 +Boxa Version 2 +Number of boxes = 2 + Box[0]: x = 42, y = 11, w = 291, h = 223 + Box[1]: x = 50, y = 11, w = 280, h = 184 + +Boxa[6] extent: x = 42, y = 10, w = 291, h = 224 +Boxa Version 2 +Number of boxes = 2 + Box[0]: x = 42, y = 10, w = 291, h = 224 + Box[1]: x = 50, y = 10, w = 280, h = 186 + +Boxa[7] extent: x = 43, y = 9, w = 291, h = 225 +Boxa Version 2 +Number of boxes = 2 + Box[0]: x = 43, y = 9, w = 291, h = 225 + Box[1]: x = 50, y = 9, w = 280, h = 192 diff --git a/leptonica/prog/showedges.c b/leptonica/prog/showedges.c new file mode 100644 index 00000000..9ee7ee84 --- /dev/null +++ b/leptonica/prog/showedges.c @@ -0,0 +1,71 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * showedges.c + * + * Uses computation of half edge function, along with thresholding. + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + +#define SMOOTH_WIDTH_1 2 /* must be smaller */ +#define SMOOTH_WIDTH_2 4 /* must be larger */ +#define THRESHOLD 5 /* low works best */ + + +int main(int argc, + char **argv) +{ +char *infile, *outfile; +l_int32 d; +PIX *pixs, *pixgr, *pixb; +static char mainName[] = "showedges"; + + if (argc != 3) + return ERROR_INT(" Syntax: showedges infile outfile", mainName, 1); + infile = argv[1]; + outfile = argv[2]; + setLeptDebugOK(1); + + pixs = pixRead(infile); + d = pixGetDepth(pixs); + if (d != 8 && d != 32) + return ERROR_INT("d not 8 or 32 bpp", mainName, 1); + + pixgr = pixHalfEdgeByBandpass(pixs, SMOOTH_WIDTH_1, SMOOTH_WIDTH_1, + SMOOTH_WIDTH_2, SMOOTH_WIDTH_2); + pixb = pixThresholdToBinary(pixgr, THRESHOLD); + pixInvert(pixb, pixb); +/* pixWrite("junkpixgr", pixgr, IFF_JFIF_JPEG); */ + pixWrite(outfile, pixb, IFF_PNG); + return 0; +} + diff --git a/leptonica/prog/singlecc.tif b/leptonica/prog/singlecc.tif Binary files differnew file mode 100644 index 00000000..cee282b4 --- /dev/null +++ b/leptonica/prog/singlecc.tif diff --git a/leptonica/prog/skew_reg.c b/leptonica/prog/skew_reg.c new file mode 100644 index 00000000..ede0cb6e --- /dev/null +++ b/leptonica/prog/skew_reg.c @@ -0,0 +1,132 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * skew_reg.c + * + * Regression test for skew detection. + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + + /* deskew */ +#define DESKEW_REDUCTION 4 /* 1, 2 or 4 */ + + /* sweep only */ +#define SWEEP_RANGE 5. /* degrees */ +#define SWEEP_DELTA 0.2 /* degrees */ +#define SWEEP_REDUCTION 2 /* 1, 2, 4 or 8 */ + + /* sweep and search */ +#define SWEEP_RANGE2 5. /* degrees */ +#define SWEEP_DELTA2 1. /* degrees */ +#define SWEEP_REDUCTION2 2 /* 1, 2, 4 or 8 */ +#define SEARCH_REDUCTION 2 /* 1, 2, 4 or 8 */ +#define SEARCH_MIN_DELTA 0.01 /* degrees */ + +static const l_int32 BORDER = 150; + + +int main(int argc, + char **argv) +{ +l_int32 w, h, wd, hd; +l_float32 deg2rad, angle, conf; +PIX *pixs, *pixb1, *pixb2, *pixr, *pixf, *pixd, *pixc; +PIXA *pixa; +L_REGPARAMS *rp; + + if (regTestSetup(argc, argv, &rp)) + return 1; + + deg2rad = 3.1415926535 / 180.; + + pixa = pixaCreate(0); + pixs = pixRead("feyn.tif"); + pixSetOrClearBorder(pixs, 100, 250, 100, 0, PIX_CLR); + pixb1 = pixReduceRankBinaryCascade(pixs, 2, 2, 0, 0); + regTestWritePixAndCheck(rp, pixb1, IFF_PNG); /* 0 */ + pixDisplayWithTitle(pixb1, 0, 100, NULL, rp->display); + + /* Add a border and locate and deskew a 40 degree rotation */ + pixb2 = pixAddBorder(pixb1, BORDER, 0); + pixGetDimensions(pixb2, &w, &h, NULL); + pixaAddPix(pixa, pixb2, L_COPY); + pixr = pixRotateBySampling(pixb2, w / 2, h / 2, + deg2rad * 40., L_BRING_IN_WHITE); + regTestWritePixAndCheck(rp, pixr, IFF_PNG); /* 1 */ + pixaAddPix(pixa, pixr, L_INSERT); + pixFindSkewSweepAndSearchScorePivot(pixr, &angle, &conf, NULL, 1, 1, + 0.0, 45.0, 2.0, 0.03, + L_SHEAR_ABOUT_CENTER); + lept_stderr("Should be 40 degrees: angle = %7.3f, conf = %7.3f\n", + angle, conf); + pixf = pixRotateBySampling(pixr, w / 2, h / 2, + deg2rad * angle, L_BRING_IN_WHITE); + pixd = pixRemoveBorder(pixf, BORDER); + regTestWritePixAndCheck(rp, pixd, IFF_PNG); /* 2 */ + pixaAddPix(pixa, pixd, L_INSERT); + pixDestroy(&pixf); + + /* Do a rotation larger than 90 degrees using embedding; + * Use 2 sets of measurements at 90 degrees to scan the + * full range of possible rotation angles. */ + pixGetDimensions(pixb1, &w, &h, NULL); + pixr = pixRotate(pixb1, deg2rad * 37., L_ROTATE_SAMPLING, + L_BRING_IN_WHITE, w, h); + regTestWritePixAndCheck(rp, pixr, IFF_PNG); /* 3 */ + pixaAddPix(pixa, pixr, L_INSERT); + startTimer(); + pixFindSkewOrthogonalRange(pixr, &angle, &conf, 2, 1, + 47.0, 1.0, 0.03, 0.0); + lept_stderr("Orth search time: %7.3f sec\n", stopTimer()); + lept_stderr("Should be about -128 degrees: angle = %7.3f\n", angle); + pixd = pixRotate(pixr, deg2rad * angle, L_ROTATE_SAMPLING, + L_BRING_IN_WHITE, w, h); + regTestWritePixAndCheck(rp, pixd, IFF_PNG); /* 4 */ + pixGetDimensions(pixd, &wd, &hd, NULL); + pixc = pixCreate(w, h, 1); + pixRasterop(pixc, 0, 0, w, h, PIX_SRC, pixd, (wd - w) / 2, (hd - h) / 2); + regTestWritePixAndCheck(rp, pixc, IFF_PNG); /* 5 */ + pixaAddPix(pixa, pixc, L_INSERT); + pixDestroy(&pixf); + pixDestroy(&pixd); + + pixd = pixaDisplayTiledInColumns(pixa, 3, 0.5, 20, 3); + regTestWritePixAndCheck(rp, pixd, IFF_PNG); /* 6 */ + pixDisplayWithTitle(pixd, 100, 100, NULL, rp->display); + pixDestroy(&pixd); + + pixDestroy(&pixs); + pixDestroy(&pixb1); + pixDestroy(&pixb2); + pixaDestroy(&pixa); + return regTestCleanup(rp); +} diff --git a/leptonica/prog/skewtest.c b/leptonica/prog/skewtest.c new file mode 100644 index 00000000..65866f92 --- /dev/null +++ b/leptonica/prog/skewtest.c @@ -0,0 +1,192 @@ +/*====================================================================* + - 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. + *====================================================================*/ + + +/* + * skewtest.c + * + * Tests various skew finding methods, optionally deskewing + * the input (binary) image. The best version does a linear + * sweep followed by a binary (angle-splitting) search. + * The basic method is to find the vertical shear angle such + * that the differential variance of ON pixels between each + * line and it's neighbor, when summed over all lines, is + * maximized. + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + + /* binarization threshold */ +#define BIN_THRESHOLD 130 + + /* deskew */ +#define DESKEW_REDUCTION 2 /* 1, 2 or 4 */ + + /* sweep only */ +#define SWEEP_RANGE 10. /* degrees */ +#define SWEEP_DELTA 0.2 /* degrees */ +#define SWEEP_REDUCTION 2 /* 1, 2, 4 or 8 */ + + /* sweep and search */ +#define SWEEP_RANGE2 10. /* degrees */ +#define SWEEP_DELTA2 1. /* degrees */ +#define SWEEP_REDUCTION2 2 /* 1, 2, 4 or 8 */ +#define SEARCH_REDUCTION 2 /* 1, 2, 4 or 8 */ +#define SEARCH_MIN_DELTA 0.01 /* degrees */ + + +int main(int argc, + char **argv) +{ +char *filein; +l_int32 ret; +l_float32 deg2rad; +l_float32 angle, conf, score, endscore; +PIX *pix, *pixs, *pixd; +static char mainName[] = "skewtest"; + + if (argc != 2) + return ERROR_INT(" Syntax: skewtest filein", mainName, 1); + filein = argv[1]; + + setLeptDebugOK(1); + lept_rmdir("lept/deskew"); + lept_mkdir("lept/deskew"); + pixd = NULL; + deg2rad = 3.1415926535 / 180.; + + if ((pixs = pixRead(filein)) == NULL) + return ERROR_INT("pixs not made", mainName, 1); + + /* Find the skew angle various ways */ + pix = pixConvertTo1(pixs, BIN_THRESHOLD); + pixWrite("/tmp/lept/deskew/binarized.tif", pix, IFF_TIFF_G4); + pixFindSkew(pix, &angle, &conf); + lept_stderr("pixFindSkew():\n" + " conf = %5.3f, angle = %7.3f degrees\n", conf, angle); + + pixFindSkewSweepAndSearchScorePivot(pix, &angle, &conf, &score, + SWEEP_REDUCTION2, SEARCH_REDUCTION, + 0.0, SWEEP_RANGE2, SWEEP_DELTA2, + SEARCH_MIN_DELTA, + L_SHEAR_ABOUT_CORNER); + lept_stderr("pixFind...Pivot(about corner):\n" + " conf = %5.3f, angle = %7.3f degrees, score = %.0f\n", + conf, angle, score); + + pixFindSkewSweepAndSearchScorePivot(pix, &angle, &conf, &score, + SWEEP_REDUCTION2, SEARCH_REDUCTION, + 0.0, SWEEP_RANGE2, SWEEP_DELTA2, + SEARCH_MIN_DELTA, + L_SHEAR_ABOUT_CENTER); + lept_stderr("pixFind...Pivot(about center):\n" + " conf = %5.3f, angle = %7.3f degrees, score = %.0f\n", + conf, angle, score); + + /* Use top-level */ + pixd = pixDeskew(pixs, 0); + pixWriteImpliedFormat("/tmp/lept/deskew/result1", pixd, 0, 0); + pixDestroy(&pix); + pixDestroy(&pixd); + +#if 1 + /* Do skew finding and rotation separately. This fails if + * the skew angle is outside the range. */ + pix = pixConvertTo1(pixs, BIN_THRESHOLD); + if (pixGetDepth(pixs) == 1) { + pixd = pixDeskew(pix, DESKEW_REDUCTION); + pixWrite("/tmp/lept/deskew/result2", pixd, IFF_PNG); + } + else { + ret = pixFindSkewSweepAndSearch(pix, &angle, &conf, SWEEP_REDUCTION2, + SEARCH_REDUCTION, SWEEP_RANGE2, + SWEEP_DELTA2, SEARCH_MIN_DELTA); + if (ret) + L_WARNING("skew angle not valid\n", mainName); + else { + lept_stderr("conf = %5.3f, angle = %7.3f degrees\n", conf, angle); + if (conf > 2.5) + pixd = pixRotate(pixs, angle * deg2rad, L_ROTATE_AREA_MAP, + L_BRING_IN_WHITE, 0, 0); + else + pixd = pixClone(pixs); + pixWrite("/tmp/lept/deskew/result2", pixd, IFF_PNG); + pixDestroy(&pixd); + } + } + pixDestroy(&pix); +#endif + +#if 1 + pixFindSkewSweepAndSearchScore(pixs, &angle, &conf, &endscore, + 4, 2, 0.0, 5.0, 1.0, 0.01); + lept_stderr("angle = %8.4f, conf = %8.4f, endscore = %.0f\n", + angle, conf, endscore); + startTimer(); + pixd = pixDeskew(pixs, DESKEW_REDUCTION); + lept_stderr("Time to deskew = %7.4f sec\n", stopTimer()); + pixWrite("/tmp/lept/deskew/result3", pixd, IFF_PNG); + pixDestroy(&pixd); +#endif + +#if 1 + ret = pixFindSkew(pixs, &angle, &conf); + lept_stderr("angle = %8.4f, conf = %8.4f\n", angle, conf); + if (ret) { + L_WARNING("skew angle not valid\n", mainName); + return 1; + } +#endif + +#if 1 + ret = pixFindSkewSweep(pixs, &angle, SWEEP_REDUCTION, + SWEEP_RANGE, SWEEP_DELTA); + lept_stderr("angle = %8.4f, conf = %8.4f\n", angle, conf); + if (ret) { + L_WARNING("skew angle not valid\n", mainName); + return 1; + } +#endif + +#if 1 + ret = pixFindSkewSweepAndSearch(pixs, &angle, &conf, + SWEEP_REDUCTION2, SEARCH_REDUCTION, + SWEEP_RANGE2, SWEEP_DELTA2, + SEARCH_MIN_DELTA); + lept_stderr("angle = %8.4f, conf = %8.4f\n", angle, conf); + if (ret) { + L_WARNING("skew angle not valid\n", mainName); + return 1; + } +#endif + + pixDestroy(&pixs); + return 0; +} diff --git a/leptonica/prog/smallpix_reg.c b/leptonica/prog/smallpix_reg.c new file mode 100644 index 00000000..4c2f2d90 --- /dev/null +++ b/leptonica/prog/smallpix_reg.c @@ -0,0 +1,231 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * smallpix_reg.c + * + * This is a regression test for scaling and rotation. + * + * The question to be answered is: in the quantization, where, if + * anywhere, do we add 0.5? + * + * The answer is that it should usually, but not always, be omitted. + * To see this, we operate on a very small pix and for visualization, + * scale up with replication to avoid aliasing and shifting. + * + * To determine that the current implementations in scalelow.c, + * rotate.c and rotateamlow.c are better, change the specific + * implementations and re-run. + * + * In all cases here, the pix to be operated on is of odd size + * so that the center pixel is symmetrically located, and there + * are a couple of black pixels outside the pattern so that edge + * effects (e.g., in pixScaleSmooth()) do not affect the results. + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + +void SaveAndDisplayPix(L_REGPARAMS *rp, PIXA **ppixa, l_int32 x, l_int32 y); + +int main(int argc, + char **argv) +{ +l_int32 i; +l_float32 pi, scale, angle; +PIX *pixc, *pixm, *pix1, *pix2, *pix3; +PIXA *pixa; +PTA *pta1, *pta2, *pta3, *pta4; +L_REGPARAMS *rp; + + if (regTestSetup(argc, argv, &rp)) + return 1; + + /* Make a small test image, the hard way! */ + pi = 3.1415926535; + pixc = pixCreate(9, 9, 32); + pixm = pixCreate(9, 9, 1); + pta1 = generatePtaLineFromPt(4, 4, 3.1, 0.0); + pta2 = generatePtaLineFromPt(4, 4, 3.1, 0.5 * pi); + pta3 = generatePtaLineFromPt(4, 4, 3.1, pi); + pta4 = generatePtaLineFromPt(4, 4, 3.1, 1.5 * pi); + ptaJoin(pta1, pta2, 0, -1); + ptaJoin(pta1, pta3, 0, -1); + ptaJoin(pta1, pta4, 0, -1); + pixRenderPta(pixm, pta1, L_SET_PIXELS); + pixPaintThroughMask(pixc, pixm, 0, 0, 0x00ff0000); + ptaDestroy(&pta1); + ptaDestroy(&pta2); + ptaDestroy(&pta3); + ptaDestroy(&pta4); + pixDestroy(&pixm); + + /* Results differ for scaleSmoothLow() w/ and w/out + 0.5. + * Neither is properly symmetric (with symm pattern on odd-sized + * pix, because the smoothing is destroying the symmetry. */ + pixa = pixaCreate(11); + pix1 = pixExpandReplicate(pixc, 2); + for (i = 0; i < 11; i++) { + scale = 0.30 + 0.035 * (l_float32)i; + pix2 = pixScaleSmooth(pix1, scale, scale); + pix3 = pixExpandReplicate(pix2, 6); + pixaAddPix(pixa, pix3, L_INSERT); + pixDestroy(&pix2); + } + pixDestroy(&pix1); + SaveAndDisplayPix(rp, &pixa, 100, 100); /* 0 */ + + /* Results same for pixScaleAreaMap w/ and w/out + 0.5 */ + pixa = pixaCreate(11); + pix1 = pixExpandReplicate(pixc, 2); + for (i = 0; i < 11; i++) { + scale = 0.30 + 0.035 * (l_float32)i; + pix2 = pixScaleAreaMap(pix1, scale, scale); + pix3 = pixExpandReplicate(pix2, 6); + pixaAddPix(pixa, pix3, L_INSERT); + pixDestroy(&pix2); + } + pixDestroy(&pix1); + SaveAndDisplayPix(rp, &pixa, 100, 200); /* 1 */ + + /* Results better for pixScaleBySampling with + 0.5, for small, + * odd-dimension pix. */ + pixa = pixaCreate(11); + pix1 = pixExpandReplicate(pixc, 2); + for (i = 0; i < 11; i++) { + scale = 0.30 + 0.035 * (l_float32)i; + pix2 = pixScaleBySampling(pix1, scale, scale); + pix3 = pixExpandReplicate(pix2, 6); + pixaAddPix(pixa, pix3, L_INSERT); + pixDestroy(&pix2); + } + pixDestroy(&pix1); + SaveAndDisplayPix(rp, &pixa, 100, 300); /* 2 */ + + /* Results same for pixRotateAM w/ and w/out + 0.5 */ + pixa = pixaCreate(11); + pix1 = pixExpandReplicate(pixc, 1); + for (i = 0; i < 11; i++) { + angle = 0.10 + 0.05 * (l_float32)i; + pix2 = pixRotateAM(pix1, angle, L_BRING_IN_BLACK); + pix3 = pixExpandReplicate(pix2, 8); + pixaAddPix(pixa, pix3, L_INSERT); + pixDestroy(&pix2); + } + pixDestroy(&pix1); + SaveAndDisplayPix(rp, &pixa, 100, 400); /* 3 */ + + /* If the size is odd, we express the center exactly, and the + * results are better for pixRotateBySampling() w/out 0.5 + * However, if the size is even, the center value is not + * exact, and if we choose it 0.5 smaller than the actual + * center, we get symmetrical results with +0.5. + * So we choose not to include + 0.5. */ + pixa = pixaCreate(11); + pix1 = pixExpandReplicate(pixc, 1); + for (i = 0; i < 11; i++) { + angle = 0.10 + 0.05 * (l_float32)i; + pix2 = pixRotateBySampling(pix1, 4, 4, angle, L_BRING_IN_BLACK); + pix3 = pixExpandReplicate(pix2, 8); + pixaAddPix(pixa, pix3, L_INSERT); + pixDestroy(&pix2); + } + pixDestroy(&pix1); + SaveAndDisplayPix(rp, &pixa, 100, 500); /* 4 */ + + /* Results same for pixRotateAMCorner w/ and w/out + 0.5 */ + pixa = pixaCreate(11); + pix1 = pixExpandReplicate(pixc, 1); + for (i = 0; i < 11; i++) { + angle = 0.10 + 0.05 * (l_float32)i; + pix2 = pixRotateAMCorner(pix1, angle, L_BRING_IN_BLACK); + pix3 = pixExpandReplicate(pix2, 8); + pixaAddPix(pixa, pix3, L_INSERT); + pixDestroy(&pix2); + } + pixDestroy(&pix1); + SaveAndDisplayPix(rp, &pixa, 100, 600); /* 5 */ + + /* Results better for pixRotateAMColorFast without + 0.5 */ + pixa = pixaCreate(11); + pix1 = pixExpandReplicate(pixc, 1); + for (i = 0; i < 11; i++) { + angle = 0.10 + 0.05 * (l_float32)i; + pix2 = pixRotateAMColorFast(pix1, angle, 0); + pix3 = pixExpandReplicate(pix2, 8); + pixaAddPix(pixa, pix3, L_INSERT); + pixDestroy(&pix2); + } + pixDestroy(&pix1); + SaveAndDisplayPix(rp, &pixa, 100, 700); /* 6 */ + + /* Results slightly better for pixScaleColorLI() w/out + 0.5 */ + pixa = pixaCreate(11); + pix1 = pixExpandReplicate(pixc, 1); + for (i = 0; i < 11; i++) { + scale = 1.0 + 0.2 * (l_float32)i; + pix2 = pixScaleColorLI(pix1, scale, scale); + pix3 = pixExpandReplicate(pix2, 4); + pixaAddPix(pixa, pix3, L_INSERT); + pixDestroy(&pix2); + } + pixDestroy(&pix1); + SaveAndDisplayPix(rp, &pixa, 100, 800); /* 7 */ + + /* Results slightly better for pixScaleColorLI() w/out + 0.5 */ + pixa = pixaCreate(11); + pix1 = pixExpandReplicate(pixc, 1); + for (i = 0; i < 11; i++) { + scale = 1.0 + 0.2 * (l_float32)i; + pix2 = pixScaleLI(pix1, scale, scale); + pix3 = pixExpandReplicate(pix2, 4); + pixaAddPix(pixa, pix3, L_INSERT); + pixDestroy(&pix2); + } + pixDestroy(&pix1); + SaveAndDisplayPix(rp, &pixa, 100, 940); /* 8 */ + + pixDestroy(&pixc); + return regTestCleanup(rp); +} + +void +SaveAndDisplayPix(L_REGPARAMS *rp, + PIXA **ppixa, + l_int32 x, + l_int32 y) +{ +PIX *pix1; + + pix1 = pixaDisplayTiledInColumns(*ppixa, 12, 1.0, 20, 0); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); + pixDisplayWithTitle(pix1, x, y, NULL, rp->display); + pixaDestroy(ppixa); + pixDestroy(&pix1); +} diff --git a/leptonica/prog/smoothedge_reg.c b/leptonica/prog/smoothedge_reg.c new file mode 100644 index 00000000..61b875ee --- /dev/null +++ b/leptonica/prog/smoothedge_reg.c @@ -0,0 +1,100 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * smoothedge_reg.c + * + * Analyzes edges of a 1 bpp (connected component) image for smoothness. + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + +static l_int32 MIN_JUMP = 2; +static l_int32 MIN_REVERSAL = 3; + +void PixAddEdgeData(PIXA *pixa, PIX *pixs, l_int32 side, l_int32 minjump, + l_int32 minreversal); + + +int main(int argc, + char **argv) +{ +l_int32 w; +PIX *pixs, *pixt, *pixd; +PIXA *pixa; + + pixs = pixRead("raggededge.png"); + w = pixGetWidth(pixs); + pixa = pixaCreate(0); + PixAddEdgeData(pixa, pixs, L_FROM_RIGHT, MIN_JUMP, MIN_REVERSAL); + PixAddEdgeData(pixa, pixs, L_FROM_LEFT, MIN_JUMP, MIN_REVERSAL); + pixt = pixRotateOrth(pixs, 1); + PixAddEdgeData(pixa, pixt, L_FROM_BOT, MIN_JUMP, MIN_REVERSAL); + PixAddEdgeData(pixa, pixt, L_FROM_TOP, MIN_JUMP, MIN_REVERSAL); + pixDestroy(&pixt); + pixt = pixRotateOrth(pixs, 2); + PixAddEdgeData(pixa, pixt, L_FROM_LEFT, MIN_JUMP, MIN_REVERSAL); + PixAddEdgeData(pixa, pixt, L_FROM_RIGHT, MIN_JUMP, MIN_REVERSAL); + pixDestroy(&pixt); + pixt = pixRotateOrth(pixs, 3); + PixAddEdgeData(pixa, pixt, L_FROM_TOP, MIN_JUMP, MIN_REVERSAL); + PixAddEdgeData(pixa, pixt, L_FROM_BOT, MIN_JUMP, MIN_REVERSAL); + pixDestroy(&pixt); + pixDestroy(&pixs); + + /* Display at 2x scaling */ + pixd = pixaDisplayTiledAndScaled(pixa, 32, 2 * (w + 10), 2, 0, 25, 2); + pixWrite("/tmp/junkpixd.png", pixd, IFF_PNG); + pixDestroy(&pixd); + pixaDestroy(&pixa); + return 0; +} + + +void PixAddEdgeData(PIXA *pixa, + PIX *pixs, + l_int32 side, + l_int32 minjump, + l_int32 minreversal) +{ +l_float32 jpl, jspl, rpl; +PIX *pixt1, *pixt2; + + pixMeasureEdgeSmoothness(pixs, side, minjump, minreversal, &jpl, + &jspl, &rpl, "/tmp/junkedge.png"); + lept_stderr("side = %d: jpl = %6.3f, jspl = %6.3f, rpl = %6.3f\n", + side, jpl, jspl, rpl); + pixt1 = pixRead("/tmp/junkedge.png"); + pixt2 = pixAddBorder(pixt1, 10, 0); /* 10 pixel white border */ + pixaAddPix(pixa, pixt2, L_INSERT); + pixDestroy(&pixt1); + return; +} + diff --git a/leptonica/prog/sorttest.c b/leptonica/prog/sorttest.c new file mode 100644 index 00000000..64e67a9c --- /dev/null +++ b/leptonica/prog/sorttest.c @@ -0,0 +1,100 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * sorttest.c + * + * Tests sorting of connected components by various attributes, + * in increasing or decreasing order. + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + +int main(int argc, + char **argv) +{ +char *filein; +l_int32 i, n, ns; +BOXA *boxa; +PIX *pixs, *pixt; +PIXA *pixa, *pixas, *pixas2; +static char mainName[] = "sorttest"; + + if (argc != 2) + return ERROR_INT(" Syntax: sorttest filein", mainName, 1); + + filein = argv[1]; + if ((pixs = pixRead(filein)) == NULL) + return ERROR_INT("pixs not made", mainName, 1); + +#if 0 + boxa = pixConnComp(pixs, NULL, 8); + n = boxaGetCount(boxa); + + boxas = boxaSort(boxa, L_SORT_BY_PERIMETER, L_SORT_DECREASING, NULL); + ns = boxaGetCount(boxas); + lept_stderr("Number of cc: n = %d, ns = %d\n", n, ns); + boxaWrite("/tmp/junkboxa.ba", boxas); + + for (i = 0; i < n; i++) { + box = boxaGetBox(boxas, i, L_CLONE); + pixRenderBox(pixs, box, 2, L_FLIP_PIXELS); + boxDestroy(&box); + } + pixWrite("/tmp/junkout.png", pixs, IFF_PNG); + boxaDestroy(&boxa); + boxaDestroy(&boxas); +#endif + + +#if 1 + boxa = pixConnComp(pixs, &pixa, 8); + n = pixaGetCount(pixa); + + pixas = pixaSort(pixa, L_SORT_BY_Y, L_SORT_INCREASING, NULL, L_CLONE); + ns = pixaGetCount(pixas); + lept_stderr("Number of cc: n = %d, ns = %d\n", n, ns); + pixaWrite("/tmp/pixa.pa", pixas); + pixas2 = pixaRead("/tmp/pixa.pa"); + pixaWrite("/tmp/pixa2.pa", pixas2); + + pixt = pixaDisplayOnLattice(pixas, 100, 100, NULL, NULL); + pixWrite("/tmp/sorted.png", pixt, IFF_PNG); + boxaWrite("/tmp/boxa.ba", pixas->boxa); + pixDestroy(&pixt); + pixaDestroy(&pixa); + pixaDestroy(&pixas); + pixaDestroy(&pixas2); + boxaDestroy(&boxa); +#endif + + pixDestroy(&pixs); + return 0; +} diff --git a/leptonica/prog/speckle.png b/leptonica/prog/speckle.png Binary files differnew file mode 100644 index 00000000..fe390fac --- /dev/null +++ b/leptonica/prog/speckle.png diff --git a/leptonica/prog/speckle2.png b/leptonica/prog/speckle2.png Binary files differnew file mode 100644 index 00000000..f019cebf --- /dev/null +++ b/leptonica/prog/speckle2.png diff --git a/leptonica/prog/speckle4.png b/leptonica/prog/speckle4.png Binary files differnew file mode 100644 index 00000000..5f12c42b --- /dev/null +++ b/leptonica/prog/speckle4.png diff --git a/leptonica/prog/speckle_reg.c b/leptonica/prog/speckle_reg.c new file mode 100644 index 00000000..00e58667 --- /dev/null +++ b/leptonica/prog/speckle_reg.c @@ -0,0 +1,119 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * speckle_reg.c + * + * Image normalization to get an image with speckle background + * noise, followed by attempts to remove some of the speckle. + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + + /* HMT (with just misses) for speckle up to 2x2 */ +static const char *selstr2 = "oooo" + "oC o" + "o o" + "oooo"; + /* HMT (with just misses) for speckle up to 3x3 */ +static const char *selstr3 = "ooooo" + "oC o" + "o o" + "o o" + "ooooo"; + +int main(int argc, + char **argv) +{ +PIX *pixs, *pix1, *pix2, *pix3, *pix4, *pix5; +PIX *pix6, *pix7, *pix8, *pix9, *pix10; +PIXA *pixa1; +SEL *sel1, *sel2, *sel3, *sel4; +L_REGPARAMS *rp; + + if (regTestSetup(argc, argv, &rp)) + return 1; + + /* Normalize for rapidly varying background */ + pixa1 = pixaCreate(0); + pixs = pixRead("w91frag.jpg"); + pixaAddPix(pixa1, pixs, L_INSERT); + regTestWritePixAndCheck(rp, pixs, IFF_JFIF_JPEG); /* 0 */ + pix1 = pixBackgroundNormFlex(pixs, 7, 7, 1, 1, 10); + pixaAddPix(pixa1, pix1, L_INSERT); + regTestWritePixAndCheck(rp, pix1, IFF_JFIF_JPEG); /* 1 */ + + /* Remove the background */ + pix2 = pixGammaTRCMasked(NULL, pix1, NULL, 1.0, 100, 175); + regTestWritePixAndCheck(rp, pix2, IFF_JFIF_JPEG); /* 2 */ + + /* Binarize */ + pix3 = pixThresholdToBinary(pix2, 180); + pixaAddPix(pixa1, pix3, L_INSERT); + regTestWritePixAndCheck(rp, pix3, IFF_PNG); /* 3 */ + + /* Remove the speckle noise up to 2x2 */ + sel1 = selCreateFromString(selstr2, 4, 4, "speckle2"); + pix4 = pixHMT(NULL, pix3, sel1); + pixaAddPix(pixa1, pix4, L_INSERT); + sel2 = selCreateBrick(2, 2, 0, 0, SEL_HIT); + pix5 = pixDilate(NULL, pix4, sel2); + pixaAddPix(pixa1, pix5, L_INSERT); + regTestWritePixAndCheck(rp, pix5, IFF_PNG); /* 4 */ + pix6 = pixSubtract(NULL, pix3, pix5); + pixaAddPix(pixa1, pix6, L_INSERT); + regTestWritePixAndCheck(rp, pix6, IFF_PNG); /* 5 */ + + /* Remove the speckle noise up to 3x3 */ + sel3 = selCreateFromString(selstr3, 5, 5, "speckle3"); + pix7 = pixHMT(NULL, pix3, sel3); + pixaAddPix(pixa1, pix7, L_INSERT); + sel4 = selCreateBrick(3, 3, 0, 0, SEL_HIT); + pix8 = pixDilate(NULL, pix7, sel4); + pixaAddPix(pixa1, pix8, L_INSERT); + regTestWritePixAndCheck(rp, pix8, IFF_PNG); /* 6 */ + pix9 = pixSubtract(NULL, pix3, pix8); + pixaAddPix(pixa1, pix9, L_INSERT); + regTestWritePixAndCheck(rp, pix9, IFF_PNG); /* 7 */ + + pix10 = pixaDisplayTiledInColumns(pixa1, 3, 1.0, 30, 2); + pixDisplayWithTitle(pix10, 0, 0, NULL, rp->display); + regTestWritePixAndCheck(rp, pix10, IFF_JFIF_JPEG); /* 8 */ + selDestroy(&sel1); + selDestroy(&sel2); + selDestroy(&sel3); + selDestroy(&sel4); + pixDestroy(&pix2); + pixDestroy(&pix10); + pixaDestroy(&pixa1); + return regTestCleanup(rp); +} + + diff --git a/leptonica/prog/splitcomp_reg.c b/leptonica/prog/splitcomp_reg.c new file mode 100644 index 00000000..faa49415 --- /dev/null +++ b/leptonica/prog/splitcomp_reg.c @@ -0,0 +1,158 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * splitcomp_reg.c + * + * Regression test for splittings of a single component and for an image + * composed of several components, using different components and + * parameters. Note that: + * (1) All coverings must cover the fg of the mask. + * (2) The first set of parameters is small and generates + * a proper tiling, covering ONLY the mask fg. + * (3) The tilings generated on 90 degree rotated components + * are identical (rotated) to those on un-rotated components. + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + +int main(int argc, + char **argv) +{ +l_int32 i, j, w, h; +l_int32 minsum[5] = { 2, 40, 50, 50, 70}; +l_int32 skipdist[5] = { 5, 5, 10, 10, 30}; +l_int32 delta[5] = { 2, 10, 10, 25, 40}; +l_int32 maxbg[5] = {10, 15, 10, 20, 40}; +BOX *box1, *box2, *box3, *box4; +BOXA *boxa; +PIX *pixs, *pixc, *pixt, *pixd, *pix32; +PIXA *pixas, *pixad; +L_REGPARAMS *rp; + + if (regTestSetup(argc, argv, &rp)) + return 1; + + /* Generate and save 1 bpp masks */ + pixas = pixaCreate(0); + pixs = pixCreate(300, 250, 1); + pixSetAll(pixs); + box1 = boxCreate(50, 0, 140, 25); + box2 = boxCreate(120, 100, 100, 25); + box3 = boxCreate(75, 170, 80, 20); + box4 = boxCreate(150, 80, 25, 70); + + pixClearInRect(pixs, box1); + pixaAddPix(pixas, pixs, L_COPY); + pixt = pixRotateOrth(pixs, 1); + pixaAddPix(pixas, pixt, L_INSERT); + + pixClearInRect(pixs, box2); + pixaAddPix(pixas, pixs, L_COPY); + pixt = pixRotateOrth(pixs, 1); + pixaAddPix(pixas, pixt, L_INSERT); + + pixClearInRect(pixs, box3); + pixaAddPix(pixas, pixs, L_COPY); + pixt = pixRotateOrth(pixs, 1); + pixaAddPix(pixas, pixt, L_INSERT); + + pixClearInRect(pixs, box4); + pixaAddPix(pixas, pixs, L_COPY); + pixt = pixRotateOrth(pixs, 1); + pixaAddPix(pixas, pixt, L_INSERT); + + boxDestroy(&box1); + boxDestroy(&box2); + boxDestroy(&box3); + boxDestroy(&box4); + pixDestroy(&pixs); + + /* Do 5 splittings on each of the 8 masks */ + pixad = pixaCreate(0); + for (j = 0; j < 8; j++) { + pixt = pixaGetPix(pixas, j, L_CLONE); + pixGetDimensions(pixt, &w, &h, NULL); + pix32 = pixCreate(w, h, 32); + pixSetAll(pix32); + pixPaintThroughMask(pix32, pixt, 0, 0, 0xc0c0c000); + pixaAddPix(pixad, pix32, L_INSERT); + for (i = 0; i < 5; i++) { + pixc = pixCopy(NULL, pix32); + boxa = pixSplitComponentIntoBoxa(pixt, NULL, minsum[i], skipdist[i], + delta[i], maxbg[i], 0, 1); +/* boxaWriteStream(stderr, boxa); */ + pixd = pixBlendBoxaRandom(pixc, boxa, 0.4); + pixRenderBoxaArb(pixd, boxa, 2, 255, 0, 0); + pixaAddPix(pixad, pixd, L_INSERT); + pixDestroy(&pixc); + boxaDestroy(&boxa); + } + pixDestroy(&pixt); + } + + /* Display results */ + pixd = pixaDisplayTiledInColumns(pixad, 6, 1.0, 30, 0); + regTestWritePixAndCheck(rp, pixd, IFF_PNG); /* 0 */ + pixDisplayWithTitle(pixd, 100, 100, NULL, rp->display); + pixDestroy(&pixd); + pixaDestroy(&pixad); + + /* Put the 8 masks all together, and split 5 ways */ + pixad = pixaCreate(0); + pixs = pixaDisplayOnLattice(pixas, 325, 325, NULL, NULL); + pixGetDimensions(pixs, &w, &h, NULL); + pix32 = pixCreate(w, h, 32); + pixSetAll(pix32); + pixPaintThroughMask(pix32, pixs, 0, 0, 0xc0c0c000); + pixaAddPix(pixad, pix32, L_INSERT); + for (i = 0; i < 5; i++) { + pixc = pixCopy(NULL, pix32); + boxa = pixSplitIntoBoxa(pixs, minsum[i], skipdist[i], + delta[i], maxbg[i], 0, 1); +/* boxaWriteStream(stderr, boxa); */ + pixd = pixBlendBoxaRandom(pixc, boxa, 0.4); + pixRenderBoxaArb(pixd, boxa, 2, 255, 0, 0); + pixaAddPix(pixad, pixd, L_INSERT); + pixDestroy(&pixc); + boxaDestroy(&boxa); + } + pixDestroy(&pixs); + + /* Display results */ + pixd = pixaDisplayTiledInColumns(pixad, 6, 1.0, 30, 0); + regTestWritePixAndCheck(rp, pixd, IFF_PNG); /* 1 */ + pixDisplayWithTitle(pixd, 600, 100, NULL, rp->display); + pixDestroy(&pixd); + pixaDestroy(&pixad); + + pixaDestroy(&pixas); + return regTestCleanup(rp); +} diff --git a/leptonica/prog/splitimage2pdf.c b/leptonica/prog/splitimage2pdf.c new file mode 100644 index 00000000..7e4dc367 --- /dev/null +++ b/leptonica/prog/splitimage2pdf.c @@ -0,0 +1,71 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * splitimage2pdf.c + * + * Syntax: splitimage2pdf filein nx ny fileout + * + * nx = number of horizontal tiles + * ny = number of vertical tiles + * + * Simple program to generate a pdf of image tiles. + * To print the tiles, one page per tile, use printsplitimage. + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + +int main(int argc, + char **argv) +{ +char *filein, *fileout; +l_int32 nx, ny; +PIX *pixs; +PIXA *pixa; +static char mainName[] = "splitimage2pdf"; + + if (argc != 5) + return ERROR_INT(" Syntax: splitimage2pdf filein nx ny fileout", + mainName, 1); + filein = argv[1]; + nx = atoi(argv[2]); + ny = atoi(argv[3]); + fileout = argv[4]; + if ((pixs = pixRead(filein)) == NULL) + return ERROR_INT("pixs not made", mainName, 1); + + pixa = pixaSplitPix(pixs, nx, ny, 0, 0); + pixaConvertToPdf(pixa, 300, 1.0, 0, 0, NULL, fileout); + + pixDestroy(&pixs); + pixaDestroy(&pixa); + return 0; +} + diff --git a/leptonica/prog/stampede2.jpg b/leptonica/prog/stampede2.jpg Binary files differnew file mode 100644 index 00000000..62539612 --- /dev/null +++ b/leptonica/prog/stampede2.jpg diff --git a/leptonica/prog/string_reg.c b/leptonica/prog/string_reg.c new file mode 100644 index 00000000..acfbd03e --- /dev/null +++ b/leptonica/prog/string_reg.c @@ -0,0 +1,229 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * string_reg.c + * + * This tests: + * * search/replace for strings and arrays + * * sarray generation and flattening + * * sarray serialization + * * file splitting + * * sarray splitting + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include <string.h> +#include "allheaders.h" + +char strs[32] = "This is a gooood test!"; +char substr1[2] = "o"; +char substr2[4] = "00"; + +int main(int argc, + char **argv) +{ +l_int32 i, loc, count; +size_t size1, size2; +char *str0, *str1, *str2, *str3, *str4, *str5, *str6; +char fname[128]; +l_uint8 *data1, *data2; +L_DNA *da; +SARRAY *sa1, *sa2, *sa3, *sa4, *sa5; +L_REGPARAMS *rp; + + if (regTestSetup(argc, argv, &rp)) + return 1; + + lept_mkdir("lept/string"); + + /* Finding all substrings */ + da = stringFindEachSubstr(strs, substr1); + regTestCompareValues(rp, 4, l_dnaGetCount(da), 0.0); /* 0 */ + l_dnaDestroy(&da); + + /* Replacing a substring */ + loc = 0; + str1 = stringReplaceSubstr(strs, "his", "hers", &loc, NULL); + regTestCompareValues(rp, 5, loc, 0.0); /* 1 */ + regTestCompareStrings(rp, (l_uint8 *)"Thers is a gooood test!", 23, + (l_uint8 *)str1, strlen(str1)); /* 2 */ + lept_free(str1); + + /* Replacing all substrings */ + str1 = stringReplaceEachSubstr(strs, substr1, substr2, &count); + regTestCompareValues(rp, 4, count, 0.0); /* 3 */ + regTestCompareStrings(rp, (l_uint8 *)"This is a g00000000d test!", 26, + (l_uint8 *)str1, strlen(str1)); /* 4 */ + lept_free(str1); + + str1 = stringReplaceEachSubstr(strs, substr1, "", &count); + regTestCompareValues(rp, 4, count, 0.0); /* 5 */ + regTestCompareStrings(rp, (l_uint8 *)"This is a gd test!", 18, + (l_uint8 *)str1, strlen(str1)); /* 6 */ + lept_free(str1); + + /* Finding all sequences */ + str1 = (char *)l_binaryRead("kernel_reg.c", &size1); + da = arrayFindEachSequence((l_uint8 *)str1, size1, + (l_uint8 *)"Destroy", 7); + regTestCompareValues(rp, 35, l_dnaGetCount(da), 0.0); /* 7 */ + l_dnaDestroy(&da); + lept_free(str1); + + /* Replacing all sequences */ + str1 = (char *)l_binaryRead("kernel_reg.c", &size1); + data1 = arrayReplaceEachSequence((l_uint8 *)str1, size1, + (l_uint8 *)"Destroy", 7, + (l_uint8 *)"####", 4, &size2, &count); + l_binaryWrite("/tmp/lept/string/string1.txt", "w", data1, size2); + regTestCheckFile(rp, "/tmp/lept/string/string1.txt"); /* 8 */ + regTestCompareValues(rp, 35, count, 0.0); /* 9 */ + data2 = arrayReplaceEachSequence((l_uint8 *)str1, size1, + (l_uint8 *)"Destroy", 7, + NULL, 0, &size2, &count); + l_binaryWrite("/tmp/lept/string/string2.txt", "w", data2, size2); + regTestCheckFile(rp, "/tmp/lept/string/string2.txt"); /* 10 */ + regTestCompareValues(rp, 35, count, 0.0); /* 11 */ + lept_free(data1); + lept_free(data2); + lept_free(str1); + + /* Generating sarray from strings, and v.v */ + str0 = (char *)l_binaryRead("kernel_reg.c", &size1); + str0[2500] = '\0'; + sa1 = sarrayCreateWordsFromString(str0 + 2000); + sa2 = sarrayCreateLinesFromString(str0 + 2000, 0); + sa3 = sarrayCreateLinesFromString(str0 + 2000, 1); + str1 = sarrayToString(sa1, 0); + str2 = sarrayToString(sa1, 1); + str3 = sarrayToString(sa2, 0); + str4 = sarrayToString(sa2, 1); + str5 = sarrayToString(sa3, 0); + str6 = sarrayToString(sa3, 1); + l_binaryWrite("/tmp/lept/string/test1.txt", "w", str1, strlen(str1)); + l_binaryWrite("/tmp/lept/string/test2.txt", "w", str2, strlen(str2)); + l_binaryWrite("/tmp/lept/string/test3.txt", "w", str3, strlen(str3)); + l_binaryWrite("/tmp/lept/string/test4.txt", "w", str4, strlen(str4)); + l_binaryWrite("/tmp/lept/string/test5.txt", "w", str5, strlen(str5)); + l_binaryWrite("/tmp/lept/string/test6.txt", "w", str6, strlen(str6)); + regTestCheckFile(rp, "/tmp/lept/string/test1.txt"); /* 12 */ + regTestCheckFile(rp, "/tmp/lept/string/test2.txt"); /* 13 */ + regTestCheckFile(rp, "/tmp/lept/string/test3.txt"); /* 14 */ + regTestCheckFile(rp, "/tmp/lept/string/test4.txt"); /* 15 */ + regTestCheckFile(rp, "/tmp/lept/string/test5.txt"); /* 16 */ + regTestCheckFile(rp, "/tmp/lept/string/test6.txt"); /* 17 */ + regTestCompareFiles(rp, 14, 16); /* 18 */ + lept_free(str0); + lept_free(str1); + lept_free(str2); + lept_free(str3); + lept_free(str4); + lept_free(str5); + lept_free(str6); + sarrayDestroy(&sa1); + sarrayDestroy(&sa2); + sarrayDestroy(&sa3); + + /* Test sarray serialization */ + str1 = (char *)l_binaryRead("kernel_reg.c", &size1); + sa1 = sarrayCreateLinesFromString(str1, 0); + sarrayWrite("/tmp/lept/string/test7.txt", sa1); + sa2 = sarrayRead("/tmp/lept/string/test7.txt"); + sarrayWrite("/tmp/lept/string/test8.txt", sa2); + regTestCheckFile(rp, "/tmp/lept/string/test7.txt"); /* 19 */ + regTestCheckFile(rp, "/tmp/lept/string/test8.txt"); /* 20 */ + regTestCompareFiles(rp, 19, 20); /* 21 */ + lept_free(str1); + sarrayDestroy(&sa1); + sarrayDestroy(&sa2); + + /* Test byte replacement in a file: + * - replace 200 bytes by 10 bytes + * - remove the 10 bytes + * - recover the 200 bytes and insert back */ + fileReplaceBytes("kernel_reg.c", 100, 200, (l_uint8 *)"abcdefghij", + sizeof("abcdefghij"), "/tmp/lept/string/junk1.txt"); + str1 = (char *)l_binaryRead("kernel_reg.c", &size1); + fileReplaceBytes("/tmp/lept/string/junk1.txt", 100, sizeof("abcdefghij"), + NULL, 0, "/tmp/lept/string/junk2.txt"); + str2 = stringCopySegment(str1, 100, 200); + fileReplaceBytes("/tmp/lept/string/junk2.txt", 100, 0, (l_uint8 *)str2, + strlen(str2), "/tmp/lept/string/junk3.txt"); + str3 = (char *)l_binaryRead("/tmp/lept/string/junk3.txt", &size2); + regTestCompareStrings(rp, (l_uint8 *)str1, size1, (l_uint8 *)str3, size2); + /* 22 */ + lept_free(str1); + lept_free(str2); + lept_free(str3); + + /* File splitting by lines */ + str1 = (char *)l_binaryRead("kernel_reg.c", &size1); + fileSplitLinesUniform("kernel_reg.c", 3, 1, "/tmp/lept/string/split", + ".txt"); + str2 = NULL; + for (i = 0; i < 3; i++) { /* put the pieces back together */ + snprintf(fname, sizeof(fname), "/tmp/lept/string/split_%d.txt", i); + str3 = (char *)l_binaryRead(fname, &size2); + stringJoinIP(&str2, str3); + lept_free(str3); + } + regTestCompareStrings(rp, (l_uint8 *)str1, size1, + (l_uint8 *)str2, strlen(str2)); /* 23 */ + lept_free(str1); + lept_free(str2); + + /* Sarray splitting by lines */ + str1 = (char *)l_binaryRead("kernel_reg.c", &size1); + sa1 = sarrayCreateLinesFromString(str1, 0); + sa2 = sarrayConcatUniformly(sa1, 6, 0); /* into 6 strings */ + sa3 = sarrayCreate(0); + for (i = 0; i < 6; i++) { + str2 = sarrayGetString(sa2, i, L_NOCOPY); + sa4 = sarrayCreateLinesFromString(str2, 0); + sarrayJoin(sa3, sa4); + sarrayDestroy(&sa4); + } + sa5 = sarrayConcatUniformly(sa3, 6, 0); /* same as sa2 ? */ + sarrayWriteMem((l_uint8 **)&str3, &size1, sa2); + sarrayWriteMem((l_uint8 **)&str4, &size2, sa5); + regTestWriteDataAndCheck(rp, str3, size1, ".sa"); /* 24 */ + regTestWriteDataAndCheck(rp, str4, size2, ".sa"); /* 25 */ + regTestCompareFiles(rp, 24, 25); /* 26 */ + sarrayDestroy(&sa1); + sarrayDestroy(&sa2); + sarrayDestroy(&sa3); + sarrayDestroy(&sa4); + sarrayDestroy(&sa5); + lept_free(str1); + lept_free(str3); + lept_free(str4); + + return regTestCleanup(rp); +} diff --git a/leptonica/prog/stringtemplate1.txt b/leptonica/prog/stringtemplate1.txt new file mode 100644 index 00000000..aea771f9 --- /dev/null +++ b/leptonica/prog/stringtemplate1.txt @@ -0,0 +1,96 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* +--- * autogen.*.c + * + * Automatically generated code for deserializing data from + * compiled strings. + * + * Index Type Deserializer Filename + * ----- ---- ------------ -------- +--- * 0 PIXA pixaRead chars-6.pa +--- * 1 PIXA pixaRead chars-10.pa + */ + +#include <string.h> +#include "allheaders.h" +--- #include "autogen.*.h" + +/*---------------------------------------------------------------------*/ +/* Auto-generated deserializers */ +/*---------------------------------------------------------------------*/ +/*! +--- * \brief l_autodecode_*() + * + * \param[in] index into array of functions + * \return data struct e.g., pixa, in memory + */ +void * +--- l_autodecode_*(l_int32 index) +{ +l_uint8 *data1, *data2; +l_int32 size1; +size_t size2; +void *result = NULL; +--- l_int32 nfunc = 2; +--- +--- PROCNAME("l_autodecode_*"); + + if (index < 0 || index >= nfunc) { + L_ERROR("invalid index = %d; must be less than %d\n", procName, + index, nfunc); + return NULL; + } + + lept_mkdir("lept/auto"); + + /* Unencode the selected string, uncompress it, and read it */ + switch (index) { +--- case 0: +--- data1 = decodeBase64(l_strdata_0, strlen(l_strdata_0), &size1); +--- data2 = zlibUncompress(data1, size1, &size2); +--- l_binaryWrite("/tmp/lept/auto/data.bin", "w", data2, size2); +--- result = (void *)pixaRead("/tmp/lept/auto/data.bin"); +--- lept_free(data1); +--- lept_free(data2); +--- break; +--- case 1: +--- data1 = decodeBase64(l_strdata_1, strlen(l_strdata_1), &size1); +--- data2 = zlibUncompress(data1, size1, &size2); +--- l_binaryWrite("/tmp/lept/auto/data.bin", "w", data2, size2); +--- result = (void *)pixaRead("/tmp/lept/auto/data.bin"); +--- lept_free(data1); +--- lept_free(data2); +--- break; + default: + L_ERROR("invalid index", procName); + } + + return result; +} + + diff --git a/leptonica/prog/stringtemplate2.txt b/leptonica/prog/stringtemplate2.txt new file mode 100644 index 00000000..20c853ad --- /dev/null +++ b/leptonica/prog/stringtemplate2.txt @@ -0,0 +1,61 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* +--- * autogen.*.h + * + * Automatically generated function prototype and associated + * encoded serialized strings. + */ + +--- #ifndef LEPTONICA_AUTOGEN_*_H +--- #define LEPTONICA_AUTOGEN_*_H + +/*---------------------------------------------------------------------*/ +/* Function prototype */ +/*---------------------------------------------------------------------*/ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +--- void *l_autodecode_*(l_int32 index); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +/*---------------------------------------------------------------------*/ +/* Serialized strings */ +/*---------------------------------------------------------------------*/ +--- static const char *l_strdata_0 = +--- "..."; +--- static const char *l_strdata_1 = +--- "..."; +--- [etc] +--- +---#endif /* LEPTONICA_AUTOGEN_*_H */ + diff --git a/leptonica/prog/subpixel_reg.c b/leptonica/prog/subpixel_reg.c new file mode 100644 index 00000000..49acf80a --- /dev/null +++ b/leptonica/prog/subpixel_reg.c @@ -0,0 +1,209 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * subpixel_reg.c + * + * Regression test for subpixel scaling. + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + +void AddTextAndSave(PIXA *pixa, PIX *pixs, + L_BMF *bmf, const char *textstr, + l_int32 location, l_uint32 val); + +const char *textstr[] = + {"Downscaled with sharpening", + "Subpixel scaling; horiz R-G-B", + "Subpixel scaling; horiz B-G-R", + "Subpixel scaling; vert R-G-B", + "Subpixel scaling; vert B-G-R"}; + +int main(int argc, + char **argv) +{ +l_float32 scalefact; +L_BMF *bmf, *bmftop; +L_KERNEL *kel, *kelx, *kely; +PIX *pixs, *pixg, *pixt, *pixd; +PIX *pix1, *pix2, *pix3, *pix4, *pix5, *pix6, *pix7, *pix8; +PIXA *pixa; +L_REGPARAMS *rp; + +#if !defined(HAVE_LIBPNG) + L_ERROR("This test requires libpng to run.\n", "subpixel_reg"); + exit(77); +#endif + + if (regTestSetup(argc, argv, &rp)) + return 1; + + /* ----------------- Test on 8 bpp grayscale ---------------------*/ + pixa = pixaCreate(5); + bmf = bmfCreate("./fonts", 6); + bmftop = bmfCreate("./fonts", 10); + pixs = pixRead("lucasta.047.jpg"); + pixg = pixScale(pixs, 0.4, 0.4); /* 8 bpp grayscale */ + pix1 = pixConvertTo32(pixg); /* 32 bpp rgb */ + AddTextAndSave(pixa, pix1, bmf, textstr[0], L_ADD_BELOW, 0xff000000); + pix2 = pixConvertGrayToSubpixelRGB(pixs, 0.4, 0.4, L_SUBPIXEL_ORDER_RGB); + AddTextAndSave(pixa, pix2, bmf, textstr[1], L_ADD_BELOW, 0x00ff0000); + pix3 = pixConvertGrayToSubpixelRGB(pixs, 0.4, 0.4, L_SUBPIXEL_ORDER_BGR); + AddTextAndSave(pixa, pix3, bmf, textstr[2], L_ADD_BELOW, 0x0000ff00); + pix4 = pixConvertGrayToSubpixelRGB(pixs, 0.4, 0.4, L_SUBPIXEL_ORDER_VRGB); + AddTextAndSave(pixa, pix4, bmf, textstr[3], L_ADD_BELOW, 0x00ff0000); + pix5 = pixConvertGrayToSubpixelRGB(pixs, 0.4, 0.4, L_SUBPIXEL_ORDER_VBGR); + AddTextAndSave(pixa, pix5, bmf, textstr[4], L_ADD_BELOW, 0x0000ff00); + + pixt = pixaDisplayTiledInColumns(pixa, 5, 1.0, 30, 2); + pixd = pixAddSingleTextblock(pixt, bmftop, + "Regression test for subpixel scaling: gray", + 0xff00ff00, L_ADD_ABOVE, NULL); + regTestWritePixAndCheck(rp, pixd, IFF_JFIF_JPEG); /* 0 */ + pixDisplayWithTitle(pixd, 50, 50, NULL, rp->display); + pixaDestroy(&pixa); + pixDestroy(&pixs); + pixDestroy(&pixg); + pixDestroy(&pixt); + pixDestroy(&pixd); + pixDestroy(&pix1); + pixDestroy(&pix2); + pixDestroy(&pix3); + pixDestroy(&pix4); + pixDestroy(&pix5); + + + /* ----------------- Test on 32 bpp rgb ---------------------*/ + pixa = pixaCreate(5); + pixs = pixRead("fish24.jpg"); + pix1 = pixScale(pixs, 0.4, 0.4); + AddTextAndSave(pixa, pix1, bmf, textstr[0], L_ADD_BELOW, 0xff000000); + pix2 = pixConvertToSubpixelRGB(pixs, 0.4, 0.4, L_SUBPIXEL_ORDER_RGB); + AddTextAndSave(pixa, pix2, bmf, textstr[1], L_ADD_BELOW, 0x00ff0000); + pix3 = pixConvertToSubpixelRGB(pixs, 0.4, 0.35, L_SUBPIXEL_ORDER_BGR); + AddTextAndSave(pixa, pix3, bmf, textstr[2], L_ADD_BELOW, 0x0000ff00); + pix4 = pixConvertToSubpixelRGB(pixs, 0.4, 0.45, L_SUBPIXEL_ORDER_VRGB); + AddTextAndSave(pixa, pix4, bmf, textstr[3], L_ADD_BELOW, 0x00ff0000); + pix5 = pixConvertToSubpixelRGB(pixs, 0.4, 0.4, L_SUBPIXEL_ORDER_VBGR); + AddTextAndSave(pixa, pix5, bmf, textstr[4], L_ADD_BELOW, 0x0000ff00); + + pixt = pixaDisplayTiledInColumns(pixa, 5, 1.0, 30, 2); + pixd = pixAddSingleTextblock(pixt, bmftop, + "Regression test for subpixel scaling: color", + 0xff00ff00, L_ADD_ABOVE, NULL); + regTestWritePixAndCheck(rp, pixd, IFF_JFIF_JPEG); /* 1 */ + pixDisplayWithTitle(pixd, 50, 350, NULL, rp->display); + pixaDestroy(&pixa); + pixDestroy(&pixs); + pixDestroy(&pixt); + pixDestroy(&pixd); + pixDestroy(&pix1); + pixDestroy(&pix2); + pixDestroy(&pix3); + pixDestroy(&pix4); + pixDestroy(&pix5); + bmfDestroy(&bmf); + bmfDestroy(&bmftop); + + + /* --------------- Test on images that are initially 1 bpp ------------*/ + /* For these, it is better to apply a lowpass filter before scaling */ + /* Normal scaling of 8 bpp grayscale */ + scalefact = 800. / 2320.; + pixs = pixRead("patent.png"); /* sharp, 300 ppi, 1 bpp image */ + pix1 = pixConvertTo8(pixs, FALSE); /* use 8 bpp input */ + pix2 = pixScale(pix1, scalefact, scalefact); + regTestWritePixAndCheck(rp, pix2, IFF_PNG); /* 2 */ + + /* Subpixel scaling; bad because there is very little aliasing. */ + pix3 = pixConvertToSubpixelRGB(pix1, scalefact, scalefact, + L_SUBPIXEL_ORDER_RGB); + regTestWritePixAndCheck(rp, pix3, IFF_PNG); /* 3 */ + + /* Get same (bad) result doing subpixel rendering on RGB input */ + pix4 = pixConvertTo32(pixs); + pix5 = pixConvertToSubpixelRGB(pix4, scalefact, scalefact, + L_SUBPIXEL_ORDER_RGB); + regTestComparePix(rp, pix3, pix5); /* 4 */ + regTestWritePixAndCheck(rp, pix5, IFF_PNG); /* 5 */ + + /* Now apply a small lowpass filter before scaling. */ + makeGaussianKernelSep(2, 2, 1.0, 1.0, &kelx, &kely); + startTimer(); + pix6 = pixConvolveSep(pix1, kelx, kely, 8, 1); /* normalized */ + lept_stderr("Time sep: %7.3f\n", stopTimer()); + regTestWritePixAndCheck(rp, pix6, IFF_PNG); /* 6 */ + + /* Get same lowpass result with non-separated convolution */ + kel = makeGaussianKernel(2, 2, 1.0, 1.0); + startTimer(); + pix7 = pixConvolve(pix1, kel, 8, 1); /* normalized */ + lept_stderr("Time non-sep: %7.3f\n", stopTimer()); + regTestComparePix(rp, pix6, pix7); /* 7 */ + + /* Now do the subpixel scaling on this slightly blurred image */ + pix8 = pixConvertToSubpixelRGB(pix6, scalefact, scalefact, + L_SUBPIXEL_ORDER_RGB); + regTestWritePixAndCheck(rp, pix8, IFF_PNG); /* 8 */ + + kernelDestroy(&kelx); + kernelDestroy(&kely); + kernelDestroy(&kel); + pixDestroy(&pixs); + pixDestroy(&pix1); + pixDestroy(&pix2); + pixDestroy(&pix3); + pixDestroy(&pix4); + pixDestroy(&pix5); + pixDestroy(&pix6); + pixDestroy(&pix7); + pixDestroy(&pix8); + return regTestCleanup(rp); +} + + +void +AddTextAndSave(PIXA *pixa, + PIX *pixs, + L_BMF *bmf, + const char *textstr, + l_int32 location, + l_uint32 val) +{ +l_int32 n, ovf; +PIX *pixt; + + pixt = pixAddSingleTextblock(pixs, bmf, textstr, val, location, &ovf); + n = pixaGetCount(pixa); + pixaAddPix(pixa, pixt, L_INSERT); + if (ovf) lept_stderr("Overflow writing text in image %d\n", n + 1); + return; +} diff --git a/leptonica/prog/sudoku1.dat b/leptonica/prog/sudoku1.dat new file mode 100644 index 00000000..b9e0a62a --- /dev/null +++ b/leptonica/prog/sudoku1.dat @@ -0,0 +1,12 @@ +# sudoku1.dat +# 5 star puzzle +# Requires: 1.0M guesses, 0.1 sec +3 8 0 2 0 0 0 9 0 +2 0 0 0 9 1 0 0 7 +0 4 0 0 3 0 0 0 0 +0 2 0 0 0 0 0 0 0 +0 1 6 0 0 0 2 5 0 +0 0 0 0 0 0 0 1 0 +0 0 0 0 8 0 0 6 0 +4 0 0 6 7 0 0 0 8 +0 5 0 0 0 3 0 7 1 diff --git a/leptonica/prog/sudoku2.dat b/leptonica/prog/sudoku2.dat new file mode 100644 index 00000000..9c9c6a9d --- /dev/null +++ b/leptonica/prog/sudoku2.dat @@ -0,0 +1,11 @@ +# sudoku2.dat +# 3 stars +0 1 0 0 6 0 0 2 4 +7 0 0 0 0 3 0 0 0 +5 6 0 0 9 0 3 0 0 +0 5 4 1 0 0 8 7 0 +0 0 0 0 0 0 0 0 0 +0 8 7 0 0 9 2 4 0 +0 0 5 0 3 0 0 9 8 +0 0 0 8 0 0 0 0 3 +8 3 0 0 7 0 0 6 0 diff --git a/leptonica/prog/sudoku3.dat b/leptonica/prog/sudoku3.dat new file mode 100644 index 00000000..c4210e96 --- /dev/null +++ b/leptonica/prog/sudoku3.dat @@ -0,0 +1,14 @@ +# sudoku3.dat +# "Near worst case" sudoku for brute force, +# Req: 623M guesses, 70 sec +# (Rotating by 180, it only requires: 4.7M guesses, 0.6 sec) +# from http://en.wikipedia.org/wiki/Algorithmics_of_sudoku +0 0 0 0 0 0 0 0 0 +0 0 0 0 0 3 0 8 5 +0 0 1 0 2 0 0 0 0 +0 0 0 5 0 7 0 0 0 +0 0 4 0 0 0 1 0 0 +0 9 0 0 0 0 0 0 0 +5 0 0 0 0 0 0 7 3 +0 0 2 0 1 0 0 0 0 +0 0 0 0 4 0 0 0 9 diff --git a/leptonica/prog/sudoku4.dat b/leptonica/prog/sudoku4.dat new file mode 100644 index 00000000..5893814e --- /dev/null +++ b/leptonica/prog/sudoku4.dat @@ -0,0 +1,13 @@ +# sudoku4.dat +# Easter Monster (rating 99408 -- whatever that is) +# Req: 2.4M guesses, about 0.7 sec +# from http://en.wikipedia.org/wiki/Algorithmics_of_sudoku +1 0 0 0 0 0 0 0 2 +0 9 0 4 0 0 0 5 0 +0 0 6 0 0 0 7 0 0 +0 5 0 9 0 3 0 0 0 +0 0 0 0 7 0 0 0 0 +0 0 0 8 5 0 0 4 0 +7 0 0 0 0 0 6 0 0 +0 3 0 0 0 9 0 8 0 +0 0 2 0 0 0 0 0 1 diff --git a/leptonica/prog/sudoku5.dat b/leptonica/prog/sudoku5.dat new file mode 100644 index 00000000..ca5c8ddc --- /dev/null +++ b/leptonica/prog/sudoku5.dat @@ -0,0 +1,14 @@ +# sudoku5.dat +# tarek071223170000052Easter Monster (rating 99408 -- whatever that is) +# rating: 4m19s@2 GHz (by tarek) +# Actual solution requires: Req: 18.1M guesses, about 2.1 sec +# from http://en.wikipedia.org/wiki/Algorithmics_of_sudoku +0 0 1 0 0 4 0 0 0 +0 0 0 0 6 0 3 0 5 +0 0 0 9 0 0 0 0 0 +8 0 0 0 0 0 7 0 3 +0 0 0 0 0 0 0 2 8 +5 0 0 0 7 0 6 0 0 +3 0 0 0 8 0 0 0 6 +0 0 9 2 0 0 0 0 0 +0 4 0 0 0 1 0 0 0 diff --git a/leptonica/prog/sudoku6.dat b/leptonica/prog/sudoku6.dat new file mode 100644 index 00000000..20f11576 --- /dev/null +++ b/leptonica/prog/sudoku6.dat @@ -0,0 +1,11 @@ +# sudoku6.dat +# 6 star sudoku (Jackson Hole daily) +7 8 0 0 0 6 3 0 0 +0 0 0 9 8 0 5 0 4 +0 0 0 0 3 0 0 8 0 +3 0 8 4 0 0 0 0 0 +0 0 0 5 7 1 0 0 0 +0 0 0 0 0 8 9 0 1 +0 6 0 0 2 0 0 0 0 +9 0 7 0 1 3 0 0 0 +0 0 3 6 0 0 0 2 7 diff --git a/leptonica/prog/sudoku7.dat b/leptonica/prog/sudoku7.dat new file mode 100644 index 00000000..7a55b454 --- /dev/null +++ b/leptonica/prog/sudoku7.dat @@ -0,0 +1,11 @@ +# sudoku7.dat +# 4 star sudoku (Jackson Hole daily) +7 8 6 0 0 0 5 0 3 +0 0 0 0 0 8 0 6 2 +0 0 0 0 5 0 0 4 0 +3 4 0 0 8 0 0 0 0 +0 0 5 0 0 0 4 0 0 +0 0 0 0 6 0 0 3 5 +0 3 0 0 1 0 0 0 0 +6 9 0 8 0 0 0 0 0 +8 0 4 0 0 0 1 7 9 diff --git a/leptonica/prog/sudokutest.c b/leptonica/prog/sudokutest.c new file mode 100644 index 00000000..9949ff41 --- /dev/null +++ b/leptonica/prog/sudokutest.c @@ -0,0 +1,93 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * sudokutest.c + * + * Tests sudoku solver and generator. + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + +static const char *startsol = "3 8 7 2 6 4 1 9 5 " + "2 6 5 8 9 1 4 3 7 " + "1 4 9 5 3 7 6 8 2 " + "5 2 3 7 1 6 8 4 9 " + "7 1 6 9 4 8 2 5 3 " + "8 9 4 3 5 2 7 1 6 " + "9 7 2 1 8 5 3 6 4 " + "4 3 1 6 7 9 5 2 8 " + "6 5 8 4 2 3 9 7 1"; + +int main(int argc, + char **argv) +{ +l_int32 unique; +l_int32 *array; +L_SUDOKU *sud; +static char mainName[] = "sudokutest"; + + if (argc != 1 && argc != 2) + return ERROR_INT(" Syntax: sudokutest [filein]", mainName, 1); + + setLeptDebugOK(1); + if (argc == 1) { + /* Generate a new sudoku by element elimination */ + array = sudokuReadString(startsol); + sud = sudokuGenerate(array, 3693, 28, 7); + sudokuDestroy(&sud); + lept_free(array); + return 0; + } + + /* Solve the input sudoku */ + if ((array = sudokuReadFile(argv[1])) == NULL) + return ERROR_INT("invalid input", mainName, 1); + if ((sud = sudokuCreate(array)) == NULL) + return ERROR_INT("sud not made", mainName, 1); + sudokuOutput(sud, L_SUDOKU_INIT); + startTimer(); + sudokuSolve(sud); + lept_stderr("Time: %7.3f sec\n", stopTimer()); + sudokuOutput(sud, L_SUDOKU_STATE); + sudokuDestroy(&sud); + + /* Test for uniqueness */ + sudokuTestUniqueness(array, &unique); + if (unique) + lept_stderr("Sudoku is unique\n"); + else + lept_stderr("Sudoku is NOT unique\n"); + lept_free(array); + + return 0; +} + + diff --git a/leptonica/prog/table.15.tif b/leptonica/prog/table.15.tif Binary files differnew file mode 100644 index 00000000..2e1e673c --- /dev/null +++ b/leptonica/prog/table.15.tif diff --git a/leptonica/prog/table.150.png b/leptonica/prog/table.150.png Binary files differnew file mode 100644 index 00000000..85b62f67 --- /dev/null +++ b/leptonica/prog/table.150.png diff --git a/leptonica/prog/table.27.tif b/leptonica/prog/table.27.tif Binary files differnew file mode 100644 index 00000000..f8e0ba70 --- /dev/null +++ b/leptonica/prog/table.27.tif diff --git a/leptonica/prog/test-1bit-alpha.png b/leptonica/prog/test-1bit-alpha.png Binary files differnew file mode 100644 index 00000000..03daf0b1 --- /dev/null +++ b/leptonica/prog/test-1bit-alpha.png diff --git a/leptonica/prog/test-87220.59.png b/leptonica/prog/test-87220.59.png Binary files differnew file mode 100644 index 00000000..8c7ceb14 --- /dev/null +++ b/leptonica/prog/test-87220.59.png diff --git a/leptonica/prog/test-cmap-alpha.png b/leptonica/prog/test-cmap-alpha.png Binary files differnew file mode 100644 index 00000000..26bf281f --- /dev/null +++ b/leptonica/prog/test-cmap-alpha.png diff --git a/leptonica/prog/test-cmap-alpha2.png b/leptonica/prog/test-cmap-alpha2.png Binary files differnew file mode 100644 index 00000000..26cfb819 --- /dev/null +++ b/leptonica/prog/test-cmap-alpha2.png diff --git a/leptonica/prog/test-fulltrans-alpha.png b/leptonica/prog/test-fulltrans-alpha.png Binary files differnew file mode 100644 index 00000000..9b69daa8 --- /dev/null +++ b/leptonica/prog/test-fulltrans-alpha.png diff --git a/leptonica/prog/test-gray-alpha.png b/leptonica/prog/test-gray-alpha.png Binary files differnew file mode 100644 index 00000000..3d49f3a1 --- /dev/null +++ b/leptonica/prog/test-gray-alpha.png diff --git a/leptonica/prog/test1.bmp b/leptonica/prog/test1.bmp Binary files differnew file mode 100644 index 00000000..d13002de --- /dev/null +++ b/leptonica/prog/test1.bmp diff --git a/leptonica/prog/test1.png b/leptonica/prog/test1.png Binary files differnew file mode 100644 index 00000000..402fb2dc --- /dev/null +++ b/leptonica/prog/test1.png diff --git a/leptonica/prog/test16.png b/leptonica/prog/test16.png Binary files differnew file mode 100644 index 00000000..54e9c370 --- /dev/null +++ b/leptonica/prog/test16.png diff --git a/leptonica/prog/test16.tif b/leptonica/prog/test16.tif Binary files differnew file mode 100644 index 00000000..36c0aa32 --- /dev/null +++ b/leptonica/prog/test16.tif diff --git a/leptonica/prog/test24.jpg b/leptonica/prog/test24.jpg Binary files differnew file mode 100644 index 00000000..6c5aff53 --- /dev/null +++ b/leptonica/prog/test24.jpg diff --git a/leptonica/prog/test32-alpha.png b/leptonica/prog/test32-alpha.png Binary files differnew file mode 100644 index 00000000..252171af --- /dev/null +++ b/leptonica/prog/test32-alpha.png diff --git a/leptonica/prog/test8.jpg b/leptonica/prog/test8.jpg Binary files differnew file mode 100644 index 00000000..11863a6b --- /dev/null +++ b/leptonica/prog/test8.jpg diff --git a/leptonica/prog/testangle.na b/leptonica/prog/testangle.na new file mode 100644 index 00000000..dcf6934b --- /dev/null +++ b/leptonica/prog/testangle.na @@ -0,0 +1,19 @@ + +Numa Version 1 +Number of numbers = 15 + [0] = -1.000000 + [1] = -2.000000 + [2] = 0.000000 + [3] = -1.500000 + [4] = -0.500000 + [5] = -1.250000 + [6] = -0.750000 + [7] = -1.125000 + [8] = -0.875000 + [9] = -1.062500 + [10] = -0.937500 + [11] = -0.968750 + [12] = -0.906250 + [13] = -0.953125 + [14] = -0.921875 + diff --git a/leptonica/prog/testbuffer.tif b/leptonica/prog/testbuffer.tif Binary files differnew file mode 100644 index 00000000..213ac806 --- /dev/null +++ b/leptonica/prog/testbuffer.tif diff --git a/leptonica/prog/testfile1.pdf b/leptonica/prog/testfile1.pdf Binary files differnew file mode 100644 index 00000000..ade4373e --- /dev/null +++ b/leptonica/prog/testfile1.pdf diff --git a/leptonica/prog/testfile2.pdf b/leptonica/prog/testfile2.pdf Binary files differnew file mode 100644 index 00000000..8389a3bb --- /dev/null +++ b/leptonica/prog/testfile2.pdf diff --git a/leptonica/prog/testscore.na b/leptonica/prog/testscore.na new file mode 100644 index 00000000..e4b20f37 --- /dev/null +++ b/leptonica/prog/testscore.na @@ -0,0 +1,19 @@ + +Numa Version 1 +Number of numbers = 15 + [0] = 9090650.000000 + [1] = 1837561.000000 + [2] = 1648841.000000 + [3] = 3320445.000000 + [4] = 2573805.000000 + [5] = 4926207.000000 + [6] = 6150297.000000 + [7] = 7065168.000000 + [8] = 8679735.000000 + [9] = 8093272.000000 + [10] = 9742700.000000 + [11] = 9711060.000000 + [12] = 9275647.000000 + [13] = 9825966.000000 + [14] = 9559469.000000 + diff --git a/leptonica/prog/tetons.jpg b/leptonica/prog/tetons.jpg Binary files differnew file mode 100644 index 00000000..9c60b88b --- /dev/null +++ b/leptonica/prog/tetons.jpg diff --git a/leptonica/prog/textorient.c b/leptonica/prog/textorient.c new file mode 100644 index 00000000..bde2abaf --- /dev/null +++ b/leptonica/prog/textorient.c @@ -0,0 +1,95 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * textorient.c + * + * This attempts to identify the orientation of text in the image. + * If text is found, it is rotated by a multiple of 90 degrees + * to make it right-side up. It is not further deskewed. + * This works for roman mixed-case text. It will not work if the + * image has all caps or all numbers. It has not been tested on + * other scripts. + + * Usage: + * textorient filein minupconf minratio fileout + * + * You can use minupconf = 0.0, minratio = 0.0 for default values, + * which are: + * minupconf = 8.0, minratio = 2.5 + * fileout is the output file name, without the extension, which is + * added here depending on the encoding chosen for the output pix. + * + * Example on 1 bpp image: + * textorient feyn.tif 0.0 0.0 feyn.oriented + * which generates the file + * feyn.oriented.tif + * + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + +#define BUF_SIZE 512 + +LEPT_DLL extern const char *ImageFileFormatExtensions[]; + +int main(int argc, + char **argv) +{ +char buf[BUF_SIZE]; +const char *filein, *fileout; +l_int32 pixformat; +l_float32 minupconf, minratio; +PIX *pixs, *pixd; +static char mainName[] = "textorient"; + + if (argc != 5) { + return ERROR_INT( + "Syntax: textorient filein minupconf minratio, fileout", + mainName, 1); + } + filein = argv[1]; + minupconf = atof(argv[2]); + minratio = atof(argv[3]); + fileout = argv[4]; + setLeptDebugOK(1); + + pixs = pixRead(filein); + pixd = pixOrientCorrect(pixs, minupconf, minratio, NULL, NULL, NULL, 1); + + pixformat = pixChooseOutputFormat(pixd); + snprintf(buf, BUF_SIZE, "%s.%s", fileout, + ImageFileFormatExtensions[pixformat]); + pixWrite(buf, pixd, pixformat); + pixDestroy(&pixs); + pixDestroy(&pixd); + return 0; +} + diff --git a/leptonica/prog/texturefill_reg.c b/leptonica/prog/texturefill_reg.c new file mode 100644 index 00000000..a4d59b4b --- /dev/null +++ b/leptonica/prog/texturefill_reg.c @@ -0,0 +1,194 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * texturefill_reg.c + * + * This demonstrates a method for filling in a region using nearby + * patches and mirrored tiling to generate the texture. + * + * For each of a set of possible tiles to use, convert to gray + * and compute the mean and standard deviation of the intensity. + * Then determine the specific tile to use for filling by selecting + * the one that (1) has a mean value within 1.0 stdev of the median + * of average intensities, and (2) of that set has the smallest + * standard deviation of intensity. + * + * We can choose tiles looking either horizontally or vertically + * away from the region to be textured, or both. If both, the + * selected tiles are blended before painting the resulting + * texture through a mask. + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + + /* Designed to work with amoris.2.150.jpg */ +static PIX *MakeReplacementMask(PIX *pixs); + +l_int32 main(int argc, + char **argv) +{ +l_int32 bx, by, bw, bh; +l_uint32 pixval; +BOX *box1, *box2; +BOXA *boxa; +PIX *pixs, *pixm, *pixd; +PIX *pix0, *pix1, *pix2, *pix3, *pix4, *pix5, *pix6; +L_REGPARAMS *rp; + + if (regTestSetup(argc, argv, &rp)) + return 1; + + /* Find a mask for repainting pixels */ + pixs = pixRead("amoris.2.150.jpg"); + pix1 = MakeReplacementMask(pixs); + boxa = pixConnCompBB(pix1, 8); + box1 = boxaGetBox(boxa, 0, L_COPY); + boxaDestroy(&boxa); + + /*--------------------------------------------------------* + * Show the individual steps * + *--------------------------------------------------------*/ + /* Locate a good tile to use */ + pixFindRepCloseTile(pixs, box1, L_VERT, 20, 30, 7, &box2, 1); + pix0 = pixCopy(NULL, pix1); + pixRenderBox(pix0, box2, 2, L_SET_PIXELS); + + /* Make a patch using this tile */ + boxGetGeometry(box1, &bx, &by, &bw, &bh); + pix2 = pixClipRectangle(pixs, box2, NULL); + regTestWritePixAndCheck(rp, pix2, IFF_PNG); /* 0 */ + pixDisplayWithTitle(pix2, 400, 100, NULL, rp->display); + pix3 = pixMirroredTiling(pix2, bw, bh); + regTestWritePixAndCheck(rp, pix3, IFF_PNG); /* 1 */ + pixDisplayWithTitle(pix3, 1000, 0, NULL, rp->display); + + /* Paint the patch through the mask */ + pixd = pixCopy(NULL, pixs); + pixm = pixClipRectangle(pix1, box1, NULL); + pixCombineMaskedGeneral(pixd, pix3, pixm, bx, by); + regTestWritePixAndCheck(rp, pixd, IFF_JFIF_JPEG); /* 2 */ + pixDisplayWithTitle(pixd, 0, 0, NULL, rp->display); + boxDestroy(&box2); + pixDestroy(&pixm); + pixDestroy(&pixd); + pixDestroy(&pix2); + + /* Blend two patches and then overlay. Use the previous + * tile found vertically and a new one found horizontally. */ + pixFindRepCloseTile(pixs, box1, L_HORIZ, 20, 30, 7, &box2, 1); + pixRenderBox(pix0, box2, 2, L_SET_PIXELS); + regTestWritePixAndCheck(rp, pix0, IFF_TIFF_G4); /* 3 */ + pixDisplayWithTitle(pix0, 100, 100, NULL, rp->display); + pix2 = pixClipRectangle(pixs, box2, NULL); + pix4 = pixMirroredTiling(pix2, bw, bh); + regTestWritePixAndCheck(rp, pix4, IFF_PNG); /* 4 */ + pixDisplayWithTitle(pix4, 1100, 0, NULL, rp->display); + pix5 = pixBlend(pix3, pix4, 0, 0, 0.5); + regTestWritePixAndCheck(rp, pix5, IFF_PNG); /* 5 */ + pixDisplayWithTitle(pix5, 1200, 0, NULL, rp->display); + pix6 = pixClipRectangle(pix1, box1, NULL); + pixd = pixCopy(NULL, pixs); + pixCombineMaskedGeneral(pixd, pix5, pix6, bx, by); + regTestWritePixAndCheck(rp, pixd, IFF_JFIF_JPEG); /* 6 */ + pixDisplayWithTitle(pixd, 700, 200, NULL, rp->display); + boxDestroy(&box2); + pixDestroy(&pixd); + pixDestroy(&pix0); + pixDestroy(&pix2); + pixDestroy(&pix3); + pixDestroy(&pix4); + pixDestroy(&pix5); + pixDestroy(&pix6); + + /*--------------------------------------------------------* + * Show painting from a color near region * + *--------------------------------------------------------*/ + pix2 = pixCopy(NULL, pixs); + pixGetColorNearMaskBoundary(pix2, pix1, box1, 20, &pixval, 0); + pix3 = pixClipRectangle(pix1, box1, NULL); + boxGetGeometry(box1, &bx, &by, NULL, NULL); + pixSetMaskedGeneral(pix2, pix3, pixval, bx, by); + regTestWritePixAndCheck(rp, pix2, IFF_JFIF_JPEG); /* 7 */ + pixDisplayWithTitle(pix2, 0, 0, NULL, rp->display); + boxDestroy(&box1); + pixDestroy(&pix2); + pixDestroy(&pix3); + + /*--------------------------------------------------------* + * Use the higher-level function * + *--------------------------------------------------------*/ + /* Use various tile selections and tile blending with one component */ + pix2 = pixCopy(NULL, pixs); + pix3 = pixCopy(NULL, pixs); + pix4 = pixCopy(NULL, pixs); + pixPaintSelfThroughMask(pix2, pix1, 0, 0, L_HORIZ, 30, 50, 5, 10); + pixPaintSelfThroughMask(pix3, pix1, 0, 0, L_VERT, 30, 50, 5, 0); + pixPaintSelfThroughMask(pixs, pix1, 0, 0, L_BOTH_DIRECTIONS, 30, 50, 5, 20); + regTestWritePixAndCheck(rp, pix2, IFF_JFIF_JPEG); /* 8 */ + regTestWritePixAndCheck(rp, pix3, IFF_JFIF_JPEG); /* 9 */ + regTestWritePixAndCheck(rp, pixs, IFF_JFIF_JPEG); /* 10 */ + pixDisplayWithTitle(pix2, 300, 0, NULL, rp->display); + pixDisplayWithTitle(pix3, 500, 0, NULL, rp->display); + pixDisplayWithTitle(pixs, 700, 0, NULL, rp->display); + + /* Test with two components; */ + pix5 = pixFlipLR(NULL, pix1); + pixOr(pix5, pix5, pix1); + pixPaintSelfThroughMask(pix4, pix5, 0, 0, L_BOTH_DIRECTIONS, 50, 100, 5, 9); + regTestWritePixAndCheck(rp, pix4, IFF_JFIF_JPEG); /* 11 */ + pixDisplayWithTitle(pix4, 900, 0, NULL, rp->display); + pixDestroy(&pixs); + pixDestroy(&pix1); + pixDestroy(&pix2); + pixDestroy(&pix3); + pixDestroy(&pix4); + pixDestroy(&pix5); + + return regTestCleanup(rp); +} + + +PIX * +MakeReplacementMask(PIX *pixs) +{ +PIX *pix1, *pix2, *pix3, *pix4; + + pix1 = pixMaskOverColorPixels(pixs, 95, 3); + pix2 = pixMorphSequence(pix1, "o15.15", 0); + pixSeedfillBinary(pix2, pix2, pix1, 8); + pix3 = pixMorphSequence(pix2, "c15.15 + d61.31", 0); + pix4 = pixRemoveBorderConnComps(pix3, 8); + pixXor(pix4, pix4, pix3); + pixDestroy(&pix1); + pixDestroy(&pix2); + pixDestroy(&pix3); + return pix4; +} diff --git a/leptonica/prog/threshnorm_reg.c b/leptonica/prog/threshnorm_reg.c new file mode 100644 index 00000000..09f04635 --- /dev/null +++ b/leptonica/prog/threshnorm_reg.c @@ -0,0 +1,105 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * threshnorm__reg.c + * + * Regression test for adaptive threshold normalization. + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include <string.h> +#include "allheaders.h" + +static void AddTestSet(PIXA *pixa, PIX *pixs, + l_int32 filtertype, l_int32 edgethresh, + l_int32 smoothx, l_int32 smoothy, + l_float32 gamma, l_int32 minval, + l_int32 maxval, l_int32 targetthresh); + +int main(int argc, + char **argv) +{ +PIX *pixs, *pixd; +PIXA *pixa; +L_REGPARAMS *rp; + + if (regTestSetup(argc, argv, &rp)) + return 1; + + pixs = pixRead("stampede2.jpg"); + pixa = pixaCreate(0); + + AddTestSet(pixa, pixs, L_SOBEL_EDGE, 18, 40, 40, 0.7, -25, 280, 128); + AddTestSet(pixa, pixs, L_TWO_SIDED_EDGE, 18, 40, 40, 0.7, -25, 280, 128); + AddTestSet(pixa, pixs, L_SOBEL_EDGE, 10, 40, 40, 0.7, -15, 305, 128); + AddTestSet(pixa, pixs, L_TWO_SIDED_EDGE, 10, 40, 40, 0.7, -15, 305, 128); + AddTestSet(pixa, pixs, L_SOBEL_EDGE, 15, 40, 40, 0.6, -45, 285, 158); + AddTestSet(pixa, pixs, L_TWO_SIDED_EDGE, 15, 40, 40, 0.6, -45, 285, 158); + + pixDestroy(&pixs); + pixd = pixaDisplayTiledInColumns(pixa, 6, 1.0, 20, 0); + regTestWritePixAndCheck(rp, pixd, IFF_JFIF_JPEG); /* 0 */ + pixDisplayWithTitle(pixd, 100, 100, NULL, rp->display); + + pixDestroy(&pixd); + pixaDestroy(&pixa); + return regTestCleanup(rp); +} + + +void +AddTestSet(PIXA *pixa, + PIX *pixs, + l_int32 filtertype, + l_int32 edgethresh, + l_int32 smoothx, + l_int32 smoothy, + l_float32 gamma, + l_int32 minval, + l_int32 maxval, + l_int32 targetthresh) +{ +PIX *pix1, *pix2, *pix3; + + pixThresholdSpreadNorm(pixs, filtertype, edgethresh, + smoothx, smoothy, gamma, minval, + maxval, targetthresh, &pix1, NULL, &pix2); + pixaAddPix(pixa, pix1, L_INSERT); + pixaAddPix(pixa, pix2, L_INSERT); + pix3 = pixThresholdToBinary(pix2, targetthresh - 20); + pixaAddPix(pixa, pix3, L_INSERT); + pix3 = pixThresholdToBinary(pix2, targetthresh); + pixaAddPix(pixa, pix3, L_INSERT); + pix3 = pixThresholdToBinary(pix2, targetthresh + 20); + pixaAddPix(pixa, pix3, L_INSERT); + pix3 = pixThresholdToBinary(pix2, targetthresh + 40); + pixaAddPix(pixa, pix3, L_INSERT); + return; +} diff --git a/leptonica/prog/tickets.tif b/leptonica/prog/tickets.tif Binary files differnew file mode 100644 index 00000000..8609af28 --- /dev/null +++ b/leptonica/prog/tickets.tif diff --git a/leptonica/prog/tiffpdftest.c b/leptonica/prog/tiffpdftest.c new file mode 100644 index 00000000..bb710be4 --- /dev/null +++ b/leptonica/prog/tiffpdftest.c @@ -0,0 +1,142 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * tiffpdftest.c + * + * Generates pdf wrappers for tiff images, with both min_is_black + * and min_is_white. Demonstrates that multiple cycles using + * pdftoppm preserve photometry. + * + * Note: this test requires poppler pdf utilities, so it cannot + * be part of the alltests_reg regression test suite. + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + +int main(int argc, + char **argv) +{ +char buf[256]; +l_int32 ret; +l_float32 fract; +PIX *pix1, *pix2, *pix3, *pix4; +PIXA *pixa1, *pixa2, *pixa3; + +#if !defined(HAVE_LIBTIFF) + L_ERROR("This test requires libtiff to run.\n", "tiffpdf_reg"); + exit(77); +#endif + + setLeptDebugOK(1); + l_pdfSetDateAndVersion(0); + lept_mkdir("lept/tiffpdf"); + + /* Wrap min-is-white and min-is-black */ + pix1 = pixRead("miniswhite.tif"); + pix2 = pixRead("minisblack.tif"); + pixCompareBinary(pix1, pix2, L_COMPARE_XOR, &fract, NULL); + lept_stderr("Compare input: %5.3f percent different\n", fract); + pixa1 = pixaCreate(2); + pixaAddPix(pixa1, pix1, L_INSERT); + pixaAddPix(pixa1, pix2, L_INSERT); + lept_stderr("Writing /tmp/lept/tiffpdf/set1.pdf\n"); + pixaConvertToPdf(pixa1, 100, 1.0, L_G4_ENCODE, 0, NULL, + "/tmp/lept/tiffpdf/set1.pdf"); + + /* Extract the images */ + lept_rmdir("lept/tmp"); + lept_mkdir("lept/tmp"); + snprintf(buf, sizeof(buf), + "pdftoppm -r 300 /tmp/lept/tiffpdf/set1.pdf /tmp/lept/tmp/sevens"); + ret = system(buf); + + /* Re-wrap them */ + pix1 = pixRead("/tmp/lept/tmp/sevens-1.ppm"); + pix2 = pixRead("/tmp/lept/tmp/sevens-2.ppm"); + pix3 = pixConvertTo1(pix1, 160); + pix4 = pixConvertTo1(pix2, 160); + pixCompareBinary(pix3, pix4, L_COMPARE_XOR, &fract, NULL); + lept_stderr("Compare after first extraction: " + "%5.3f percent different\n", fract); + pixa2 = pixaCreate(2); + pixaAddPix(pixa2, pix3, L_INSERT); + pixaAddPix(pixa2, pix4, L_INSERT); + lept_stderr("Writing /tmp/lept/tiffpdf/set2.pdf\n"); + pixaConvertToPdf(pixa2, 300, 1.0, L_G4_ENCODE, 0, NULL, + "/tmp/lept/tiffpdf/set2.pdf"); + pixDestroy(&pix1); + pixDestroy(&pix2); + + /* Extract the images again */ + lept_rmdir("lept/tmp"); + lept_mkdir("lept/tmp"); + snprintf(buf, sizeof(buf), + "pdftoppm -r 300 /tmp/lept/tiffpdf/set2.pdf /tmp/lept/tmp/sevens"); + ret = system(buf); + + /* And wrap them up again */ + pix1 = pixRead("/tmp/lept/tmp/sevens-1.ppm"); + pix2 = pixRead("/tmp/lept/tmp/sevens-2.ppm"); + pix3 = pixConvertTo1(pix1, 160); + pix4 = pixConvertTo1(pix2, 160); + pixCompareBinary(pix3, pix4, L_COMPARE_XOR, &fract, NULL); + lept_stderr("Compare after second extraction: " + "%5.3f percent different\n", fract); + pixa3 = pixaCreate(2); + pixaAddPix(pixa3, pix3, L_INSERT); + pixaAddPix(pixa3, pix4, L_INSERT); + lept_stderr("Writing /tmp/lept/tiffpdf/set3.pdf\n"); + pixaConvertToPdf(pixa3, 300, 1.0, L_G4_ENCODE, 0, NULL, + "/tmp/lept/tiffpdf/set3.pdf"); + pixDestroy(&pix1); + pixDestroy(&pix2); + + pix1 = pixaGetPix(pixa2, 0, L_COPY); + pix2 = pixaGetPix(pixa3, 0, L_COPY); + pixCompareBinary(pix1, pix2, L_COMPARE_XOR, &fract, NULL); + lept_stderr("Compare between first and second extraction: " + "%5.3f percent different\n", fract); + pixDestroy(&pix1); + pixDestroy(&pix2); + + /* Show the six images */ + pixaJoin(pixa1, pixa2, 0, -1); + pixaJoin(pixa1, pixa3, 0, -1); + pix1 = pixaDisplayTiledInColumns(pixa1, 6, 1.0, 30, 2); + pixDisplay(pix1, 100, 100); + pixDestroy(&pix1); + pixaDestroy(&pixa1); + pixaDestroy(&pixa2); + pixaDestroy(&pixa3); + return 0; +} + + diff --git a/leptonica/prog/toc.99.tif b/leptonica/prog/toc.99.tif Binary files differnew file mode 100644 index 00000000..98d07cf6 --- /dev/null +++ b/leptonica/prog/toc.99.tif diff --git a/leptonica/prog/topotest.png b/leptonica/prog/topotest.png Binary files differnew file mode 100644 index 00000000..3bc5509e --- /dev/null +++ b/leptonica/prog/topotest.png diff --git a/leptonica/prog/translate_reg.c b/leptonica/prog/translate_reg.c new file mode 100644 index 00000000..bf1c0262 --- /dev/null +++ b/leptonica/prog/translate_reg.c @@ -0,0 +1,163 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * translate_reg.c + * + * Regression test for in-place translation + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + +#define BINARY_IMAGE "test1.png" +#define GRAYSCALE_IMAGE "test8.jpg" +#define FOUR_BPP_IMAGE "weasel4.8g.png" +#define COLORMAP_IMAGE "dreyfus8.png" +#define RGB_IMAGE "marge.jpg" + +void TranslateAndSave1(PIXA *pixa, l_int32 depth, PIX *pix, + l_int32 xshift, l_int32 yshift); + +void TranslateAndSave2(PIXA *pixa, PIX *pix, l_int32 xshift, l_int32 yshift); + + +int main(int argc, + char **argv) +{ +BOX *box; +PIX *pixs, *pixd; +PIX *pix1, *pix2, *pix3, *pix4, *pix5, *pix6, *pix7; +PIXA *pixa; +L_REGPARAMS *rp; + + if (regTestSetup(argc, argv, &rp)) + return 1; + + /* Set up images */ + pix1 = pixRead("weasel2.4c.png"); + pix2 = pixScaleBySampling(pix1, 3.0, 3.0); + box = boxCreate(0, 0, 209, 214); + pixs = pixClipRectangle(pix2, box, NULL); + pixDestroy(&pix1); + pixDestroy(&pix2); + boxDestroy(&box); + pix1 = pixRemoveColormap(pixs, REMOVE_CMAP_TO_GRAYSCALE); + pix2 = pixRemoveColormap(pixs, REMOVE_CMAP_TO_FULL_COLOR); + pix3 = pixConvertTo1(pixs, 128); + pix4 = pixRotateAM(pix1, 0.25, L_BRING_IN_BLACK); + pix5 = pixRotateAM(pix1, -0.25, L_BRING_IN_WHITE); + pix6 = pixRotateAM(pix2, -0.15, L_BRING_IN_BLACK); + pix7 = pixRotateAM(pix2, +0.15, L_BRING_IN_WHITE); + + pixa = pixaCreate(0); + TranslateAndSave1(pixa, 32, pixs, 30, 30); + TranslateAndSave1(pixa, 32, pix1, 35, 20); + TranslateAndSave1(pixa, 32, pix2, 20, 35); + TranslateAndSave1(pixa, 32, pix3, 20, 35); + pixd = pixaDisplayTiledInColumns(pixa, 4, 1.0, 30, 3); + regTestWritePixAndCheck(rp, pixd, IFF_PNG); /* 0 */ + pixDisplayWithTitle(pixd, 0, 0, "trans0", rp->display); + pixDestroy(&pixd); + pixaDestroy(&pixa); + + pixa = pixaCreate(0); + TranslateAndSave1(pixa, 8, pix1, 35, 20); + TranslateAndSave1(pixa, 8, pix4, 35, 20); + pixd = pixaDisplayTiledInColumns(pixa, 4, 1.0, 30, 3); + regTestWritePixAndCheck(rp, pixd, IFF_PNG); /* 1 */ + pixDisplayWithTitle(pixd, 250, 0, "trans1", rp->display); + pixDestroy(&pixd); + pixaDestroy(&pixa); + + pixa = pixaCreate(0); + TranslateAndSave2(pixa, pixs, 30, 30); + TranslateAndSave2(pixa, pix1, 30, 30); + TranslateAndSave2(pixa, pix2, 35, 20); + TranslateAndSave2(pixa, pix3, 20, 35); + TranslateAndSave2(pixa, pix4, 25, 25); + TranslateAndSave2(pixa, pix5, 25, 25); + TranslateAndSave2(pixa, pix6, 25, 25); + TranslateAndSave2(pixa, pix7, 25, 25); + pixd = pixaDisplayTiledInColumns(pixa, 4, 1.0, 30, 3); + regTestWritePixAndCheck(rp, pixd, IFF_PNG); /* 2 */ + pixDisplayWithTitle(pixd, 500, 0, "trans2", rp->display); + pixDestroy(&pixd); + pixaDestroy(&pixa); + + pixDestroy(&pixs); + pixDestroy(&pix1); + pixDestroy(&pix2); + pixDestroy(&pix3); + pixDestroy(&pix4); + pixDestroy(&pix5); + pixDestroy(&pix6); + pixDestroy(&pix7); + return regTestCleanup(rp); +} + + +void +TranslateAndSave1(PIXA *pixa, + l_int32 depth, + PIX *pix, + l_int32 xshift, + l_int32 yshift) +{ +PIX *pix1, *pix2, *pix3, *pix4; + + pix1 = pixTranslate(NULL, pix, xshift, yshift, L_BRING_IN_WHITE); + pix2 = pixTranslate(NULL, pix, xshift, yshift, L_BRING_IN_BLACK); + pix3 = pixTranslate(NULL, pix, -xshift, -yshift, L_BRING_IN_WHITE); + pix4 = pixTranslate(NULL, pix, -xshift, -yshift, L_BRING_IN_BLACK); + pixaAddPix(pixa, pix1, L_INSERT); + pixaAddPix(pixa, pix2, L_INSERT); + pixaAddPix(pixa, pix3, L_INSERT); + pixaAddPix(pixa, pix4, L_INSERT); + return; +} + +void +TranslateAndSave2(PIXA *pixa, + PIX *pix, + l_int32 xshift, + l_int32 yshift) +{ +PIX *pix1, *pix2, *pix3, *pix4; + + pix1 = pixTranslate(NULL, pix, xshift, yshift, L_BRING_IN_WHITE); + pix2 = pixTranslate(NULL, pix, xshift, yshift, L_BRING_IN_BLACK); + pix3 = pixTranslate(NULL, pix, -xshift, -yshift, L_BRING_IN_WHITE); + pix4 = pixTranslate(NULL, pix, -xshift, -yshift, L_BRING_IN_BLACK); + pixaAddPix(pixa, pix1, L_INSERT); + pixaAddPix(pixa, pix2, L_INSERT); + pixaAddPix(pixa, pix3, L_INSERT); + pixaAddPix(pixa, pix4, L_INSERT); + return; +} diff --git a/leptonica/prog/trctest.c b/leptonica/prog/trctest.c new file mode 100644 index 00000000..bd12d481 --- /dev/null +++ b/leptonica/prog/trctest.c @@ -0,0 +1,66 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * trctest.c + * + * Example: trctest wet-day.jpg 3.1 50 160 /tmp/junk.png + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + +int main(int argc, + char **argv) +{ +PIX *pixs, *pixd; +l_int32 minval, maxval; +l_float32 gamma; +char *filein, *fileout; +static char mainName[] = "trctest"; + + if (argc != 6) + return ERROR_INT(" Syntax: trctest filein gamma minval maxval fileout", + mainName, 1); + filein = argv[1]; + gamma = atof(argv[2]); + minval = atoi(argv[3]); + maxval = atoi(argv[4]); + fileout = argv[5]; + setLeptDebugOK(1); + + if ((pixs = pixRead(filein)) == NULL) + return ERROR_INT("pixs not made", mainName, 1); + pixd = pixGammaTRC(NULL, pixs, gamma, minval, maxval); + pixWrite(fileout, pixd, IFF_PNG); + pixDestroy(&pixs); + pixDestroy(&pixd); + return 0; +} + diff --git a/leptonica/prog/tribune-page-4x.png b/leptonica/prog/tribune-page-4x.png Binary files differnew file mode 100644 index 00000000..fd551727 --- /dev/null +++ b/leptonica/prog/tribune-page-4x.png diff --git a/leptonica/prog/tribune-t.png b/leptonica/prog/tribune-t.png Binary files differnew file mode 100644 index 00000000..fb939dbf --- /dev/null +++ b/leptonica/prog/tribune-t.png diff --git a/leptonica/prog/tribune-word.png b/leptonica/prog/tribune-word.png Binary files differnew file mode 100644 index 00000000..02a6b53d --- /dev/null +++ b/leptonica/prog/tribune-word.png diff --git a/leptonica/prog/turingtest.png b/leptonica/prog/turingtest.png Binary files differnew file mode 100644 index 00000000..5ecce26b --- /dev/null +++ b/leptonica/prog/turingtest.png diff --git a/leptonica/prog/two-peak-histo.na b/leptonica/prog/two-peak-histo.na new file mode 100644 index 00000000..7ae1cdf6 --- /dev/null +++ b/leptonica/prog/two-peak-histo.na @@ -0,0 +1,260 @@ + +Numa Version 1 +Number of numbers = 256 + [0] = 5485.000000 + [1] = 1064.000000 + [2] = 542.000000 + [3] = 531.000000 + [4] = 588.000000 + [5] = 462.000000 + [6] = 600.000000 + [7] = 798.000000 + [8] = 838.000000 + [9] = 769.000000 + [10] = 669.000000 + [11] = 599.000000 + [12] = 1238.000000 + [13] = 892.000000 + [14] = 798.000000 + [15] = 2891.000000 + [16] = 4042.000000 + [17] = 1296.000000 + [18] = 3049.000000 + [19] = 4714.000000 + [20] = 4046.000000 + [21] = 2449.000000 + [22] = 2385.000000 + [23] = 1245.000000 + [24] = 926.000000 + [25] = 1198.000000 + [26] = 2606.000000 + [27] = 867.000000 + [28] = 580.000000 + [29] = 542.000000 + [30] = 540.000000 + [31] = 400.000000 + [32] = 367.000000 + [33] = 437.000000 + [34] = 417.000000 + [35] = 345.000000 + [36] = 228.000000 + [37] = 211.000000 + [38] = 215.000000 + [39] = 145.000000 + [40] = 98.000000 + [41] = 112.000000 + [42] = 80.000000 + [43] = 89.000000 + [44] = 97.000000 + [45] = 84.000000 + [46] = 83.000000 + [47] = 43.000000 + [48] = 35.000000 + [49] = 66.000000 + [50] = 66.000000 + [51] = 50.000000 + [52] = 60.000000 + [53] = 40.000000 + [54] = 42.000000 + [55] = 39.000000 + [56] = 53.000000 + [57] = 47.000000 + [58] = 55.000000 + [59] = 57.000000 + [60] = 71.000000 + [61] = 38.000000 + [62] = 52.000000 + [63] = 41.000000 + [64] = 43.000000 + [65] = 39.000000 + [66] = 35.000000 + [67] = 24.000000 + [68] = 27.000000 + [69] = 24.000000 + [70] = 25.000000 + [71] = 19.000000 + [72] = 16.000000 + [73] = 36.000000 + [74] = 21.000000 + [75] = 24.000000 + [76] = 11.000000 + [77] = 18.000000 + [78] = 17.000000 + [79] = 17.000000 + [80] = 11.000000 + [81] = 14.000000 + [82] = 11.000000 + [83] = 11.000000 + [84] = 21.000000 + [85] = 15.000000 + [86] = 9.000000 + [87] = 9.000000 + [88] = 22.000000 + [89] = 9.000000 + [90] = 11.000000 + [91] = 6.000000 + [92] = 16.000000 + [93] = 16.000000 + [94] = 9.000000 + [95] = 10.000000 + [96] = 10.000000 + [97] = 12.000000 + [98] = 9.000000 + [99] = 9.000000 + [100] = 6.000000 + [101] = 7.000000 + [102] = 8.000000 + [103] = 11.000000 + [104] = 6.000000 + [105] = 4.000000 + [106] = 4.000000 + [107] = 5.000000 + [108] = 10.000000 + [109] = 8.000000 + [110] = 13.000000 + [111] = 6.000000 + [112] = 7.000000 + [113] = 8.000000 + [114] = 10.000000 + [115] = 11.000000 + [116] = 17.000000 + [117] = 12.000000 + [118] = 6.000000 + [119] = 7.000000 + [120] = 10.000000 + [121] = 10.000000 + [122] = 15.000000 + [123] = 11.000000 + [124] = 10.000000 + [125] = 16.000000 + [126] = 20.000000 + [127] = 14.000000 + [128] = 16.000000 + [129] = 19.000000 + [130] = 18.000000 + [131] = 13.000000 + [132] = 15.000000 + [133] = 27.000000 + [134] = 15.000000 + [135] = 15.000000 + [136] = 16.000000 + [137] = 20.000000 + [138] = 21.000000 + [139] = 20.000000 + [140] = 29.000000 + [141] = 24.000000 + [142] = 24.000000 + [143] = 25.000000 + [144] = 29.000000 + [145] = 30.000000 + [146] = 25.000000 + [147] = 30.000000 + [148] = 36.000000 + [149] = 44.000000 + [150] = 43.000000 + [151] = 40.000000 + [152] = 36.000000 + [153] = 51.000000 + [154] = 56.000000 + [155] = 33.000000 + [156] = 40.000000 + [157] = 51.000000 + [158] = 39.000000 + [159] = 32.000000 + [160] = 28.000000 + [161] = 28.000000 + [162] = 24.000000 + [163] = 23.000000 + [164] = 24.000000 + [165] = 22.000000 + [166] = 19.000000 + [167] = 34.000000 + [168] = 26.000000 + [169] = 39.000000 + [170] = 45.000000 + [171] = 47.000000 + [172] = 45.000000 + [173] = 55.000000 + [174] = 42.000000 + [175] = 68.000000 + [176] = 78.000000 + [177] = 147.000000 + [178] = 237.000000 + [179] = 395.000000 + [180] = 407.000000 + [181] = 387.000000 + [182] = 377.000000 + [183] = 381.000000 + [184] = 405.000000 + [185] = 370.000000 + [186] = 360.000000 + [187] = 353.000000 + [188] = 376.000000 + [189] = 325.000000 + [190] = 363.000000 + [191] = 332.000000 + [192] = 358.000000 + [193] = 400.000000 + [194] = 436.000000 + [195] = 451.000000 + [196] = 533.000000 + [197] = 580.000000 + [198] = 582.000000 + [199] = 631.000000 + [200] = 709.000000 + [201] = 708.000000 + [202] = 638.000000 + [203] = 621.000000 + [204] = 687.000000 + [205] = 677.000000 + [206] = 691.000000 + [207] = 715.000000 + [208] = 845.000000 + [209] = 995.000000 + [210] = 1156.000000 + [211] = 1250.000000 + [212] = 1174.000000 + [213] = 1080.000000 + [214] = 1246.000000 + [215] = 1239.000000 + [216] = 1385.000000 + [217] = 1536.000000 + [218] = 1553.000000 + [219] = 1525.000000 + [220] = 1595.000000 + [221] = 1527.000000 + [222] = 1465.000000 + [223] = 1391.000000 + [224] = 1786.000000 + [225] = 2353.000000 + [226] = 2480.000000 + [227] = 1712.000000 + [228] = 890.000000 + [229] = 379.000000 + [230] = 155.000000 + [231] = 31.000000 + [232] = 15.000000 + [233] = 3.000000 + [234] = 3.000000 + [235] = 0.000000 + [236] = 0.000000 + [237] = 0.000000 + [238] = 0.000000 + [239] = 0.000000 + [240] = 0.000000 + [241] = 0.000000 + [242] = 0.000000 + [243] = 0.000000 + [244] = 0.000000 + [245] = 0.000000 + [246] = 0.000000 + [247] = 0.000000 + [248] = 0.000000 + [249] = 0.000000 + [250] = 0.000000 + [251] = 0.000000 + [252] = 0.000000 + [253] = 0.000000 + [254] = 0.000000 + [255] = 0.000000 + diff --git a/leptonica/prog/underline1.jpg b/leptonica/prog/underline1.jpg Binary files differnew file mode 100644 index 00000000..20b976a5 --- /dev/null +++ b/leptonica/prog/underline1.jpg diff --git a/leptonica/prog/underline2.jpg b/leptonica/prog/underline2.jpg Binary files differnew file mode 100644 index 00000000..515a618f --- /dev/null +++ b/leptonica/prog/underline2.jpg diff --git a/leptonica/prog/underline3.jpg b/leptonica/prog/underline3.jpg Binary files differnew file mode 100644 index 00000000..fa17d3ab --- /dev/null +++ b/leptonica/prog/underline3.jpg diff --git a/leptonica/prog/underline4.jpg b/leptonica/prog/underline4.jpg Binary files differnew file mode 100644 index 00000000..dcfd0da4 --- /dev/null +++ b/leptonica/prog/underline4.jpg diff --git a/leptonica/prog/underline5.jpg b/leptonica/prog/underline5.jpg Binary files differnew file mode 100644 index 00000000..04031abf --- /dev/null +++ b/leptonica/prog/underline5.jpg diff --git a/leptonica/prog/underline6.jpg b/leptonica/prog/underline6.jpg Binary files differnew file mode 100644 index 00000000..2a3fb7d0 --- /dev/null +++ b/leptonica/prog/underline6.jpg diff --git a/leptonica/prog/underline7.jpg b/leptonica/prog/underline7.jpg Binary files differnew file mode 100644 index 00000000..f909be6c --- /dev/null +++ b/leptonica/prog/underline7.jpg diff --git a/leptonica/prog/underlinetest.c b/leptonica/prog/underlinetest.c new file mode 100644 index 00000000..42b1bf8f --- /dev/null +++ b/leptonica/prog/underlinetest.c @@ -0,0 +1,95 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * underlinetest.c + * + * Example program for removing lines under text + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + +static const char *files[] = {"underline1.jpg", "underline2.jpg", + "underline3.jpg", "underline4.jpg", + "underline5.jpg", "underline6.jpg", + "underline7.jpg"}; + +int main(int argc, + char **argv) +{ +l_int32 i; +PIX *pixs, *pixg, *pixg2, *pixb, *pixm, *pixsd, *pixsdd, *pixt, *pixd; +PIXA *pixa; + + setLeptDebugOK(1); + lept_mkdir("lept/underline"); + + pixa = pixaCreate(0); + for (i = 0; i < 7; i++) { + lept_stderr("%d...", i + 1); + pixs = pixRead(files[i]); + pixg = pixConvertTo8(pixs, 0); + pixg2 = pixBackgroundNorm(pixg, NULL, NULL, 15, 15, 70, 105, 200, 5, 5); + pixSauvolaBinarizeTiled(pixg2, 8, 0.34, 1, 1, NULL, &pixb); + pixaAddPix(pixa, pixg, L_INSERT); + pixaAddPix(pixa, pixb, L_INSERT); + pixDestroy(&pixs); + pixDestroy(&pixg2); + + /* Get a seed image; try to have at least one pixel + * in each underline c.c */ + pixsd = pixMorphSequence(pixb, "c3.1 + o60.1", 0); + + /* Get a mask image for the underlines. + * The o30.1 tries to remove accidental connections to text. */ + pixm = pixMorphSequence(pixb, "c7.1 + o30.1", 0); + + /* Fill into the seed, clipping to the mask */ + pixSeedfillBinary(pixsd, pixsd, pixm, 8); + pixDestroy(&pixm); + + /* Small vertical dilation for better removal */ + pixsdd = pixMorphSequence(pixsd, "d1.3", 0); + pixaAddPix(pixa, pixsdd, L_INSERT); + pixDestroy(&pixsd); + + /* Subtracat to get text without underlines */ + pixt = pixSubtract(NULL, pixb, pixsdd); + pixaAddPix(pixa, pixt, L_INSERT); + } + lept_stderr("\n"); + + pixd = pixaDisplayTiledInColumns(pixa, 4, 0.6, 20, 2); + pixWrite("/tmp/lept/underline/result.png", pixd, IFF_PNG); + pixDisplay(pixd, 100, 100); + pixaDestroy(&pixa); + pixDestroy(&pixd); + return 0; +} diff --git a/leptonica/prog/w91frag.jpg b/leptonica/prog/w91frag.jpg Binary files differnew file mode 100644 index 00000000..7cfdc279 --- /dev/null +++ b/leptonica/prog/w91frag.jpg diff --git a/leptonica/prog/warped_paper.jpg b/leptonica/prog/warped_paper.jpg Binary files differnew file mode 100644 index 00000000..44701cca --- /dev/null +++ b/leptonica/prog/warped_paper.jpg diff --git a/leptonica/prog/warped_sudoku.jpg b/leptonica/prog/warped_sudoku.jpg Binary files differnew file mode 100644 index 00000000..4c6c79f5 --- /dev/null +++ b/leptonica/prog/warped_sudoku.jpg diff --git a/leptonica/prog/warper_reg.c b/leptonica/prog/warper_reg.c new file mode 100644 index 00000000..0e796996 --- /dev/null +++ b/leptonica/prog/warper_reg.c @@ -0,0 +1,138 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * warper_reg.c + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include <math.h> +#include "allheaders.h" + +static void DisplayResult(PIXA *pixac, PIX **ppixd, l_int32 newline); +static void DisplayCaptcha(PIXA *pixac, PIX *pixs, l_int32 nterms, + l_uint32 seed, l_int32 newline); + +static const l_int32 size = 4; +static const l_float32 xmag[] = {3.0f, 4.0f, 5.0f, 7.0f}; +static const l_float32 ymag[] = {5.0f, 6.0f, 8.0f, 10.0f}; +static const l_float32 xfreq[] = {0.11f, 0.10f, 0.10f, 0.12f}; +static const l_float32 yfreq[] = {0.11f, 0.13f, 0.13f, 0.15f}; +static const l_int32 nx[] = {4, 3, 2, 1}; +static const l_int32 ny[] = {4, 3, 2, 1}; + + +int main(int argc, + char **argv) +{ +l_int32 i, k, newline; +PIX *pixs, *pixt, *pixg, *pixd; +PIXA *pixac; +L_REGPARAMS *rp; + + if (regTestSetup(argc, argv, &rp)) + return 1; + + pixs = pixRead("feyn-word.tif"); + pixt = pixAddBorder(pixs, 25, 0); + pixg = pixConvertTo8(pixt, 0); + + for (k = 0; k < size; k++) { + pixac = pixaCreate(0); + for (i = 0; i < 50; i++) { + pixd = pixRandomHarmonicWarp(pixg, xmag[k], ymag[k], xfreq[k], + yfreq[k], nx[k], ny[k], 7 * i, 255); + newline = (i % 10 == 0) ? 1 : 0; + DisplayResult(pixac, &pixd, newline); + } + pixd = pixaDisplayTiledInColumns(pixac, 10, 1.0, 20, 0); + regTestWritePixAndCheck(rp, pixd, IFF_PNG); + pixDisplayWithTitle(pixd, 100, 100, NULL, rp->display); + pixaDestroy(&pixac); + pixDestroy(&pixd); + } + + pixDestroy(&pixt); + pixDestroy(&pixg); + + for (k = 1; k <= 4; k++) { + pixac = pixaCreate(0); + for (i = 0; i < 50; i++) { + newline = (i % 10 == 0) ? 1 : 0; + DisplayCaptcha(pixac, pixs, k, 7 * i, newline); + } + pixd = pixaDisplayTiledInColumns(pixac, 10, 1.0, 20, 0); + regTestWritePixAndCheck(rp, pixd, IFF_PNG); + pixDisplayWithTitle(pixd, 100, 100, NULL, rp->display); + pixaDestroy(&pixac); + pixDestroy(&pixd); + } + + pixDestroy(&pixs); + return regTestCleanup(rp); +} + + +static void +DisplayResult(PIXA *pixac, + PIX **ppixd, + l_int32 newline) +{ +l_uint32 color; +PIX *pix1; + + color = 0; + color = ((rand() >> 16) & 0xff) << L_RED_SHIFT | + ((rand() >> 16) & 0xff) << L_GREEN_SHIFT | + ((rand() >> 16) & 0xff) << L_BLUE_SHIFT; + pix1 = pixColorizeGray(*ppixd, color, 0); + pixaAddPix(pixac, pix1, L_INSERT); + pixDestroy(ppixd); + return; +} + + +static void +DisplayCaptcha(PIXA *pixac, + PIX *pixs, + l_int32 nterms, + l_uint32 seed, + l_int32 newline) +{ +l_uint32 color; +PIX *pixd; + + color = 0; + color = ((rand() >> 16) & 0xff) << L_RED_SHIFT | + ((rand() >> 16) & 0xff) << L_GREEN_SHIFT | + ((rand() >> 16) & 0xff) << L_BLUE_SHIFT; + pixd = pixSimpleCaptcha(pixs, 25, nterms, seed, color, 0); + pixaAddPix(pixac, pixd, L_INSERT); + return; +} diff --git a/leptonica/prog/warpertest.c b/leptonica/prog/warpertest.c new file mode 100644 index 00000000..62b9e363 --- /dev/null +++ b/leptonica/prog/warpertest.c @@ -0,0 +1,256 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * warpertest.c + * + * Tests stereoscopic warp and associated shear and stretching functions. + * + * Puts output to both a tiled image and pdf. The pdf is useful for + * visualizing the difference between sampling and interpolation. + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + +static const char *opstr[3] = {"", "interpolated", "sampled"}; +static const char *dirstr[3] = {"", "to left", "to right"}; + +#define RUN_WARP 1 +#define RUN_QUAD_VERT_SHEAR 1 +#define RUN_LIN_HORIZ_STRETCH 1 +#define RUN_QUAD_HORIZ_STRETCH 1 +#define RUN_HORIZ_SHEAR 1 +#define RUN_VERT_SHEAR 1 + +int main(int argc, + char **argv) +{ +char buf[256]; +l_int32 w, h, i, j, k, index, op, dir, stretch; +l_float32 del, angle, angledeg; +BOX *box; +L_BMF *bmf; +PIX *pixs, *pix1, *pix2, *pixd; +PIXA *pixa; +static char mainName[] = "warpertest"; + + if (argc != 1) + return ERROR_INT("syntax: warpertest", mainName, 1); + + setLeptDebugOK(1); + lept_mkdir("lept/warp"); + bmf = bmfCreate(NULL, 6); + + /* -------- Stereoscopic warping --------------*/ +#if RUN_WARP + pixs = pixRead("german.png"); + pixGetDimensions(pixs, &w, &h, NULL); + pixa = pixaCreate(50); + for (i = 0; i < 50; i++) { /* need to test > 2 widths ! */ + j = 7 * i; + box = boxCreate(0, 0, w - j, h - j); + pix1 = pixClipRectangle(pixs, box, NULL); + pixd = pixWarpStereoscopic(pix1, 15, 22, 8, 30, -20, 1); + pixSetChromaSampling(pixd, 0); + pixaAddPix(pixa, pixd, L_INSERT); + pixDestroy(&pix1); + boxDestroy(&box); + } + pixDestroy(&pixs); + + pixaConvertToPdf(pixa, 100, 1.0, L_JPEG_ENCODE, 0, "warp.pdf", + "/tmp/lept/warp/warp.pdf"); + pixd = pixaDisplayTiledInRows(pixa, 32, 2000, 1.0, 0, 20, 2); + pixWrite("/tmp/lept/warp/warp.jpg", pixd, IFF_JFIF_JPEG); + pixaDestroy(&pixa); + pixDestroy(&pixd); +#endif + + /* -------- Quadratic Vertical Shear --------------*/ +#if RUN_QUAD_VERT_SHEAR + pixs = pixCreate(501, 501, 32); + pixGetDimensions(pixs, &w, &h, NULL); + pixSetAll(pixs); + pixRenderLineArb(pixs, 0, 30, 500, 30, 5, 0, 0, 255); + pixRenderLineArb(pixs, 0, 110, 500, 110, 5, 0, 255, 0); + pixRenderLineArb(pixs, 0, 190, 500, 190, 5, 0, 255, 255); + pixRenderLineArb(pixs, 0, 270, 500, 270, 5, 255, 0, 0); + pixRenderLineArb(pixs, 0, 360, 500, 360, 5, 255, 0, 255); + pixRenderLineArb(pixs, 0, 450, 500, 450, 5, 255, 255, 0); + pixa = pixaCreate(50); + for (i = 0; i < 50; i++) { + j = 3 * i; + dir = ((i / 2) & 1) ? L_WARP_TO_RIGHT : L_WARP_TO_LEFT; + op = (i & 1) ? L_INTERPOLATED : L_SAMPLED; + box = boxCreate(0, 0, w - j, h - j); + pix1 = pixClipRectangle(pixs, box, NULL); + pix2 = pixQuadraticVShear(pix1, dir, 60, -20, op, L_BRING_IN_WHITE); + + snprintf(buf, sizeof(buf), "%s, %s", dirstr[dir], opstr[op]); + pixd = pixAddSingleTextblock(pix2, bmf, buf, 0xff000000, + L_ADD_BELOW, 0); + pixaAddPix(pixa, pixd, L_INSERT); + pixDestroy(&pix1); + pixDestroy(&pix2); + boxDestroy(&box); + } + pixDestroy(&pixs); + + pixaConvertToPdf(pixa, 100, 1.0, L_FLATE_ENCODE, 0, "quad_vshear.pdf", + "/tmp/lept/warp/quad_vshear.pdf"); + pixd = pixaDisplayTiledInRows(pixa, 32, 2000, 1.0, 0, 20, 2); + pixWrite("/tmp/lept/warp/quad_vshear.jpg", pixd, IFF_PNG); + pixaDestroy(&pixa); + pixDestroy(&pixd); +#endif + + /* -------- Linear Horizontal stretching --------------*/ +#if RUN_LIN_HORIZ_STRETCH + pixs = pixRead("german.png"); + pixa = pixaCreate(50); + for (k = 0; k < 2; k++) { + for (i = 0; i < 25; i++) { + index = 25 * k + i; + stretch = 10 + 4 * i; + if (k == 0) stretch = -stretch; + dir = (k == 1) ? L_WARP_TO_RIGHT : L_WARP_TO_LEFT; + op = (i & 1) ? L_INTERPOLATED : L_SAMPLED; + pix1 = pixStretchHorizontal(pixs, dir, L_LINEAR_WARP, + stretch, op, L_BRING_IN_WHITE); + snprintf(buf, sizeof(buf), "%s, %s", dirstr[dir], opstr[op]); + pixd = pixAddSingleTextblock(pix1, bmf, buf, 0xff000000, + L_ADD_BELOW, 0); + pixaAddPix(pixa, pixd, L_INSERT); + pixDestroy(&pix1); + } + } + pixDestroy(&pixs); + + pixaConvertToPdf(pixa, 100, 1.0, L_JPEG_ENCODE, 0, "linear_hstretch.pdf", + "/tmp/lept/warp/linear_hstretch.pdf"); + pixd = pixaDisplayTiledInRows(pixa, 32, 2500, 1.0, 0, 20, 2); + pixWrite("/tmp/lept/warp/linear_hstretch.jpg", pixd, IFF_JFIF_JPEG); + pixaDestroy(&pixa); + pixDestroy(&pixd); +#endif + + /* -------- Quadratic Horizontal stretching --------------*/ +#if RUN_QUAD_HORIZ_STRETCH + pixs = pixRead("german.png"); + pixa = pixaCreate(50); + for (k = 0; k < 2; k++) { + for (i = 0; i < 25; i++) { + index = 25 * k + i; + stretch = 10 + 4 * i; + if (k == 0) stretch = -stretch; + dir = (k == 1) ? L_WARP_TO_RIGHT : L_WARP_TO_LEFT; + op = (i & 1) ? L_INTERPOLATED : L_SAMPLED; + pix1 = pixStretchHorizontal(pixs, dir, L_QUADRATIC_WARP, + stretch, op, L_BRING_IN_WHITE); + snprintf(buf, sizeof(buf), "%s, %s", dirstr[dir], opstr[op]); + pixd = pixAddSingleTextblock(pix1, bmf, buf, 0xff000000, + L_ADD_BELOW, 0); + pixaAddPix(pixa, pixd, L_INSERT); + pixDestroy(&pix1); + } + } + pixDestroy(&pixs); + + pixaConvertToPdf(pixa, 100, 1.0, L_JPEG_ENCODE, 0, "quad_hstretch.pdf", + "/tmp/lept/warp/quad_hstretch.pdf"); + pixd = pixaDisplayTiledInRows(pixa, 32, 2500, 1.0, 0, 20, 2); + pixWrite("/tmp/lept/warp/quad_hstretch.jpg", pixd, IFF_JFIF_JPEG); + pixaDestroy(&pixa); + pixDestroy(&pixd); +#endif + + /* -------- Horizontal Shear --------------*/ +#if RUN_HORIZ_SHEAR + pixs = pixRead("german.png"); + pixGetDimensions(pixs, &w, &h, NULL); + pixa = pixaCreate(50); + for (i = 0; i < 25; i++) { + del = 0.2 / 12.; + angle = -0.2 + (i - (i & 1)) * del; + angledeg = 180. * angle / 3.14159265; + op = (i & 1) ? L_INTERPOLATED : L_SAMPLED; + if (op == L_SAMPLED) + pix1 = pixHShear(NULL, pixs, h / 2, angle, L_BRING_IN_WHITE); + else + pix1 = pixHShearLI(pixs, h / 2, angle, L_BRING_IN_WHITE); + snprintf(buf, sizeof(buf), "%6.2f degree, %s", angledeg, opstr[op]); + pixd = pixAddSingleTextblock(pix1, bmf, buf, 0xff000000, + L_ADD_BELOW, 0); + pixaAddPix(pixa, pixd, L_INSERT); + pixDestroy(&pix1); + } + pixDestroy(&pixs); + + pixaConvertToPdf(pixa, 100, 1.0, L_JPEG_ENCODE, 0, "hshear.pdf", + "/tmp/lept/warp/hshear.pdf"); + pixd = pixaDisplayTiledInRows(pixa, 32, 2500, 1.0, 0, 20, 2); + pixWrite("/tmp/lept/warp/hshear.jpg", pixd, IFF_JFIF_JPEG); + pixaDestroy(&pixa); + pixDestroy(&pixd); +#endif + + /* -------- Vertical Shear --------------*/ +#if RUN_VERT_SHEAR + pixs = pixRead("german.png"); + pixGetDimensions(pixs, &w, &h, NULL); + pixa = pixaCreate(50); + for (i = 0; i < 25; i++) { + del = 0.2 / 12.; + angle = -0.2 + (i - (i & 1)) * del; + angledeg = 180. * angle / 3.14159265; + op = (i & 1) ? L_INTERPOLATED : L_SAMPLED; + if (op == L_SAMPLED) + pix1 = pixVShear(NULL, pixs, w / 2, angle, L_BRING_IN_WHITE); + else + pix1 = pixVShearLI(pixs, w / 2, angle, L_BRING_IN_WHITE); + snprintf(buf, sizeof(buf), "%6.2f degree, %s", angledeg, opstr[op]); + pixd = pixAddSingleTextblock(pix1, bmf, buf, 0xff000000, + L_ADD_BELOW, 0); + pixaAddPix(pixa, pixd, L_INSERT); + pixDestroy(&pix1); + } + + pixDestroy(&pixs); + pixaConvertToPdf(pixa, 100, 1.0, L_JPEG_ENCODE, 0, "vshear.pdf", + "/tmp/lept/warp/vshear.pdf"); + pixd = pixaDisplayTiledInRows(pixa, 32, 2500, 1.0, 0, 20, 2); + pixWrite("/tmp/lept/warp/vshear.jpg", pixd, IFF_JFIF_JPEG); + pixaDestroy(&pixa); + pixDestroy(&pixd); +#endif + + bmfDestroy(&bmf); + return 0; +} diff --git a/leptonica/prog/watershed_reg.c b/leptonica/prog/watershed_reg.c new file mode 100644 index 00000000..f09fb44d --- /dev/null +++ b/leptonica/prog/watershed_reg.c @@ -0,0 +1,157 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * watershed_reg.c + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include <math.h> +#include "allheaders.h" + +void DoWatershed(L_REGPARAMS *rp, PIX *pixs); + +int main(int argc, + char **argv) +{ +l_int32 i, j; +l_float32 f; +PIX *pix1, *pix2; +L_REGPARAMS *rp; + + if (regTestSetup(argc, argv, &rp)) + return 1; + + pix1 = pixCreate(500, 500, 8); + pix2 = pixCreate(500, 500, 8); + for (i = 0; i < 500; i++) { + for (j = 0; j < 500; j++) { + f = 128.0 + 26.3 * sin(0.0438 * (l_float32)i); + f += 33.4 * cos(0.0712 * (l_float32)i); + f += 18.6 * sin(0.0561 * (l_float32)j); + f += 23.6 * cos(0.0327 * (l_float32)j); + pixSetPixel(pix1, j, i, (l_int32)f); + f = 128.0 + 26.3 * sin(0.0238 * (l_float32)i); + f += 33.4 * cos(0.0312 * (l_float32)i); + f += 18.6 * sin(0.0261 * (l_float32)j); + f += 23.6 * cos(0.0207 * (l_float32)j); + pixSetPixel(pix2, j, i, (l_int32)f); + } + } + DoWatershed(rp, pix1); /* 0 - 11 */ + DoWatershed(rp, pix2); /* 12 - 23 */ + pixDestroy(&pix1); + pixDestroy(&pix2); + return regTestCleanup(rp); +} + + +void +DoWatershed(L_REGPARAMS *rp, + PIX *pixs) +{ +l_uint8 *data; +size_t size; +l_int32 w, h, empty; +l_uint32 redval, greenval; +L_WSHED *wshed; +PIX *pixc, *pix1, *pix2, *pix3, *pix4, *pix5, *pix6, *pix7, *pix8, *pix9; +PIXA *pixa; +PTA *pta; + + /* Find local extrema */ + pixa = pixaCreate(0); + pixGetDimensions(pixs, &w, &h, NULL); + regTestWritePixAndCheck(rp, pixs, IFF_PNG); /* 0 */ + pixaAddPix(pixa, pixs, L_COPY); + startTimer(); + pixLocalExtrema(pixs, 0, 0, &pix1, &pix2); + lept_stderr("Time for extrema: %7.3f\n", stopTimer()); + pixSetOrClearBorder(pix1, 2, 2, 2, 2, PIX_CLR); + composeRGBPixel(255, 0, 0, &redval); + composeRGBPixel(0, 255, 0, &greenval); + pixc = pixConvertTo32(pixs); + pixPaintThroughMask(pixc, pix2, 0, 0, greenval); + pixPaintThroughMask(pixc, pix1, 0, 0, redval); + regTestWritePixAndCheck(rp, pixc, IFF_PNG); /* 1 */ + pixaAddPix(pixa, pixc, L_INSERT); + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 2 */ + pixaAddPix(pixa, pix1, L_COPY); + + /* Generate seeds for watershed */ + pixSelectMinInConnComp(pixs, pix1, &pta, NULL); + pix3 = pixGenerateFromPta(pta, w, h); + regTestWritePixAndCheck(rp, pix3, IFF_PNG); /* 3 */ + pixaAddPix(pixa, pix3, L_COPY); + pix4 = pixConvertTo32(pixs); + pixPaintThroughMask(pix4, pix3, 0, 0, greenval); + regTestWritePixAndCheck(rp, pix4, IFF_PNG); /* 4 */ + pixaAddPix(pixa, pix4, L_COPY); + pix5 = pixRemoveSeededComponents(NULL, pix3, pix1, 8, 2); + regTestWritePixAndCheck(rp, pix5, IFF_PNG); /* 5 */ + pixaAddPix(pixa, pix5, L_COPY); + pixZero(pix5, &empty); + regTestCompareValues(rp, 1, empty, 0.0); /* 6 */ + + /* Make and display watershed */ + wshed = wshedCreate(pixs, pix3, 10, 0); + startTimer(); + wshedApply(wshed); + lept_stderr("Time for wshed: %7.3f\n", stopTimer()); + pix6 = pixaDisplayRandomCmap(wshed->pixad, w, h); + regTestWritePixAndCheck(rp, pix6, IFF_PNG); /* 7 */ + pixaAddPix(pixa, pix6, L_COPY); + numaWriteMem(&data, &size, wshed->nalevels); + regTestWriteDataAndCheck(rp, data, size, "na"); /* 8 */ + pix7 = wshedRenderFill(wshed); + regTestWritePixAndCheck(rp, pix7, IFF_PNG); /* 9 */ + pixaAddPix(pixa, pix7, L_COPY); + pix8 = wshedRenderColors(wshed); + regTestWritePixAndCheck(rp, pix8, IFF_PNG); /* 10 */ + pixaAddPix(pixa, pix8, L_COPY); + wshedDestroy(&wshed); + + pix9 = pixaDisplayTiledInColumns(pixa, 3, 1.0, 20, 0); + regTestWritePixAndCheck(rp, pix9, IFF_PNG); /* 11 */ + pixDisplayWithTitle(pix9, 100, 100, NULL, rp->display); + + lept_free(data); + pixDestroy(&pix1); + pixDestroy(&pix2); + pixDestroy(&pix3); + pixDestroy(&pix4); + pixDestroy(&pix5); + pixDestroy(&pix6); + pixDestroy(&pix7); + pixDestroy(&pix8); + pixDestroy(&pix9); + pixaDestroy(&pixa); + ptaDestroy(&pta); +} + diff --git a/leptonica/prog/weasel-113c.png b/leptonica/prog/weasel-113c.png Binary files differnew file mode 100644 index 00000000..2fb7877d --- /dev/null +++ b/leptonica/prog/weasel-113c.png diff --git a/leptonica/prog/weasel-44c.png b/leptonica/prog/weasel-44c.png Binary files differnew file mode 100644 index 00000000..69752534 --- /dev/null +++ b/leptonica/prog/weasel-44c.png diff --git a/leptonica/prog/weasel-4c.2.png b/leptonica/prog/weasel-4c.2.png Binary files differnew file mode 100644 index 00000000..4bd031fd --- /dev/null +++ b/leptonica/prog/weasel-4c.2.png diff --git a/leptonica/prog/weasel-64g.png b/leptonica/prog/weasel-64g.png Binary files differnew file mode 100644 index 00000000..3ff8bd21 --- /dev/null +++ b/leptonica/prog/weasel-64g.png diff --git a/leptonica/prog/weasel-8g.png b/leptonica/prog/weasel-8g.png Binary files differnew file mode 100644 index 00000000..504d15bd --- /dev/null +++ b/leptonica/prog/weasel-8g.png diff --git a/leptonica/prog/weasel2.4c.bmp b/leptonica/prog/weasel2.4c.bmp Binary files differnew file mode 100644 index 00000000..aa45a96f --- /dev/null +++ b/leptonica/prog/weasel2.4c.bmp diff --git a/leptonica/prog/weasel2.4c.png b/leptonica/prog/weasel2.4c.png Binary files differnew file mode 100644 index 00000000..c7c1c440 --- /dev/null +++ b/leptonica/prog/weasel2.4c.png diff --git a/leptonica/prog/weasel2.4g.png b/leptonica/prog/weasel2.4g.png Binary files differnew file mode 100644 index 00000000..2ccbb370 --- /dev/null +++ b/leptonica/prog/weasel2.4g.png diff --git a/leptonica/prog/weasel2.png b/leptonica/prog/weasel2.png Binary files differnew file mode 100644 index 00000000..fc7c87dc --- /dev/null +++ b/leptonica/prog/weasel2.png diff --git a/leptonica/prog/weasel32.png b/leptonica/prog/weasel32.png Binary files differnew file mode 100644 index 00000000..f4509d25 --- /dev/null +++ b/leptonica/prog/weasel32.png diff --git a/leptonica/prog/weasel4.11c.png b/leptonica/prog/weasel4.11c.png Binary files differnew file mode 100644 index 00000000..c8b23e15 --- /dev/null +++ b/leptonica/prog/weasel4.11c.png diff --git a/leptonica/prog/weasel4.16c.png b/leptonica/prog/weasel4.16c.png Binary files differnew file mode 100644 index 00000000..95d7ff28 --- /dev/null +++ b/leptonica/prog/weasel4.16c.png diff --git a/leptonica/prog/weasel4.16g.png b/leptonica/prog/weasel4.16g.png Binary files differnew file mode 100644 index 00000000..8310c464 --- /dev/null +++ b/leptonica/prog/weasel4.16g.png diff --git a/leptonica/prog/weasel4.5g.png b/leptonica/prog/weasel4.5g.png Binary files differnew file mode 100644 index 00000000..4689622d --- /dev/null +++ b/leptonica/prog/weasel4.5g.png diff --git a/leptonica/prog/weasel4.8g.png b/leptonica/prog/weasel4.8g.png Binary files differnew file mode 100644 index 00000000..c13f4962 --- /dev/null +++ b/leptonica/prog/weasel4.8g.png diff --git a/leptonica/prog/weasel4.png b/leptonica/prog/weasel4.png Binary files differnew file mode 100644 index 00000000..d1261e6d --- /dev/null +++ b/leptonica/prog/weasel4.png diff --git a/leptonica/prog/weasel8.149g.png b/leptonica/prog/weasel8.149g.png Binary files differnew file mode 100644 index 00000000..79ceaa57 --- /dev/null +++ b/leptonica/prog/weasel8.149g.png diff --git a/leptonica/prog/weasel8.16g.nocmap.png b/leptonica/prog/weasel8.16g.nocmap.png Binary files differnew file mode 100644 index 00000000..e6c2365d --- /dev/null +++ b/leptonica/prog/weasel8.16g.nocmap.png diff --git a/leptonica/prog/weasel8.16g.png b/leptonica/prog/weasel8.16g.png Binary files differnew file mode 100644 index 00000000..f4bd13eb --- /dev/null +++ b/leptonica/prog/weasel8.16g.png diff --git a/leptonica/prog/weasel8.240c.png b/leptonica/prog/weasel8.240c.png Binary files differnew file mode 100644 index 00000000..a1fed2c0 --- /dev/null +++ b/leptonica/prog/weasel8.240c.png diff --git a/leptonica/prog/weasel8.5g.nocmap.png b/leptonica/prog/weasel8.5g.nocmap.png Binary files differnew file mode 100644 index 00000000..03e61cad --- /dev/null +++ b/leptonica/prog/weasel8.5g.nocmap.png diff --git a/leptonica/prog/weasel8.5g.png b/leptonica/prog/weasel8.5g.png Binary files differnew file mode 100644 index 00000000..145a84e1 --- /dev/null +++ b/leptonica/prog/weasel8.5g.png diff --git a/leptonica/prog/weasel8.png b/leptonica/prog/weasel8.png Binary files differnew file mode 100644 index 00000000..a01dfad6 --- /dev/null +++ b/leptonica/prog/weasel8.png diff --git a/leptonica/prog/webpanimio_reg.c b/leptonica/prog/webpanimio_reg.c new file mode 100644 index 00000000..63769c68 --- /dev/null +++ b/leptonica/prog/webpanimio_reg.c @@ -0,0 +1,96 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * webpanimio_reg.c + * + * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + * This is the Leptonica regression test for animated webp + * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + * + * This tests writing animated webp files from a pixa of images. + * + * webp supports 32 bpp rgb and rgba. + * Lossy writing is slow; reading is fast, comparable to reading jpeg files. + * Lossless writing is extremely slow. + * + * Use webpinfo to inspect the contents of an animated webp file. + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + +int main(int argc, + char **argv) +{ +l_int32 niters, duration; +PIX *pix1, *pix2; +PIXA *pixa; +L_REGPARAMS *rp; + + if (regTestSetup(argc, argv, &rp)) + return 1; + +#if !HAVE_LIBJPEG + lept_stderr("libjpeg is required for webpanimio_reg\n\n"); + regTestCleanup(rp); + return 0; +#endif /* abort */ + +#if !HAVE_LIBWEBP || !HAVE_LIBWEBP_ANIM + lept_stderr("webp and webpanim are not enabled\n" + "See environ.h:\n" + " #define HAVE_LIBWEBP\n" + " #define HAVE_LIBWEBP_ANIM\n" + "See prog/Makefile:\n" + " link in -lwebp\n" + " link in -lwebpmux\n\n"); + regTestCleanup(rp); + return 0; +#endif /* abort */ + + lept_rmdir("lept/webpanim"); + lept_mkdir("lept/webpanim"); + + niters = 5; + duration = 250; /* ms */ + pix1 = pixRead("marge.jpg"); + pix2 = pixRotate180(NULL, pix1); + pixa = pixaCreate(6); + pixaAddPix(pixa, pix1, L_COPY); + pixaAddPix(pixa, pix2, L_COPY); + pixaWriteWebPAnim("/tmp/lept/webpanim/margeanim.webp", pixa, niters, + duration, 80, 0); + regTestCheckFile(rp, "/tmp/lept/webpanim/margeanim.webp"); + pixaDestroy(&pixa); + pixDestroy(&pix1); + pixDestroy(&pix2); + + return regTestCleanup(rp); +} diff --git a/leptonica/prog/webpio_reg.c b/leptonica/prog/webpio_reg.c new file mode 100644 index 00000000..43a583f4 --- /dev/null +++ b/leptonica/prog/webpio_reg.c @@ -0,0 +1,147 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * webpio_reg.c + * + * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + * This is the Leptonica regression test for lossy read/write + * I/O in webp format. + * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + * + * This tests reading and writing of images in webp format. + * + * webp supports 32 bpp rgb and rgba. + * Lossy writing is slow; reading is fast, comparable to reading jpeg files. + * Lossless writing is extremely slow. + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" +#include <math.h> + +void DoWebpTest1(L_REGPARAMS *rp, const char *fname); +void DoWebpTest2(L_REGPARAMS *rp, const char *fname, l_int32 quality, + l_int32 lossless, l_float32 expected, l_float32 delta); + + +int main(int argc, + char **argv) +{ +L_REGPARAMS *rp; + + if (regTestSetup(argc, argv, &rp)) + return 1; + +#if !HAVE_LIBJPEG + lept_stderr("libjpeg is required for webpio_reg\n\n"); + regTestCleanup(rp); + return 0; +#endif /* abort */ + +#if !HAVE_LIBWEBP + lept_stderr("webpio is not enabled\n" + "libwebp is required for webpio_reg\n" + "See environ.h: #define HAVE_LIBWEBP\n" + "See prog/Makefile: link in -lwebp\n\n"); + regTestCleanup(rp); + return 0; +#endif /* abort */ + + lept_rmdir("lept/webp"); + lept_mkdir("lept/webp"); + + DoWebpTest1(rp, "weasel2.4c.png"); + DoWebpTest1(rp, "weasel8.240c.png"); + DoWebpTest1(rp, "karen8.jpg"); + DoWebpTest1(rp, "test24.jpg"); + + DoWebpTest2(rp, "test24.jpg", 50, 0, 43.50, 1.0); + DoWebpTest2(rp, "test24.jpg", 75, 0, 46.07, 1.0); + DoWebpTest2(rp, "test24.jpg", 90, 0, 51.09, 2.0); + DoWebpTest2(rp, "test24.jpg", 100, 0, 54.979, 5.0); + DoWebpTest2(rp, "test24.jpg", 0, 1, 1000.0, 0.1); + + return regTestCleanup(rp); +} + + +void DoWebpTest1(L_REGPARAMS *rp, + const char *fname) +{ +char buf[256]; +PIX *pixs, *pix1, *pix2; + + startTimer(); + pixs = pixRead(fname); + lept_stderr("Time to read jpg: %7.3f\n", stopTimer()); + startTimer(); + snprintf(buf, sizeof(buf), "/tmp/lept/webp/webpio.%d.webp", rp->index + 1); + pixWrite(buf, pixs, IFF_WEBP); + lept_stderr("Time to write webp: %7.3f\n", stopTimer()); + regTestCheckFile(rp, buf); + startTimer(); + pix1 = pixRead(buf); + lept_stderr("Time to read webp: %7.3f\n", stopTimer()); + pix2 = pixConvertTo32(pixs); + regTestCompareSimilarPix(rp, pix1, pix2, 20, 0.1, 0); + pixDisplayWithTitle(pix1, 100, 100, "pix1", rp->display); + pixDestroy(&pixs); + pixDestroy(&pix1); + pixDestroy(&pix2); + return; +} + +void DoWebpTest2(L_REGPARAMS *rp, + const char *fname, + l_int32 quality, + l_int32 lossless, + l_float32 expected, + l_float32 delta) +{ +char buf[256]; +l_float32 psnr; +PIX *pixs, *pix1; + + pixs = pixRead(fname); + snprintf(buf, sizeof(buf), "/tmp/lept/webp/webpio.%d.webp", rp->index + 1); + if (lossless) startTimer(); + pixWriteWebP("/tmp/lept/webp/junk.webp", pixs, quality, lossless); + if (lossless) lept_stderr("Lossless write: %7.3f sec\n", stopTimer()); + pix1 = pixRead("/tmp/lept/webp/junk.webp"); + pixGetPSNR(pixs, pix1, 4, &psnr); + if (lossless) + lept_stderr("lossless; psnr should be 1000: psnr = %7.3f\n", psnr); + else + lept_stderr("qual = %d, psnr = %7.3f\n", quality, psnr); + regTestCompareValues(rp, expected, psnr, delta); + pixDestroy(&pixs); + pixDestroy(&pix1); + return; +} diff --git a/leptonica/prog/wet-day.jpg b/leptonica/prog/wet-day.jpg Binary files differnew file mode 100644 index 00000000..b1d299b4 --- /dev/null +++ b/leptonica/prog/wet-day.jpg diff --git a/leptonica/prog/witten.tif b/leptonica/prog/witten.tif Binary files differnew file mode 100644 index 00000000..29685d94 --- /dev/null +++ b/leptonica/prog/witten.tif diff --git a/leptonica/prog/wordboxes_reg.c b/leptonica/prog/wordboxes_reg.c new file mode 100644 index 00000000..a75a2185 --- /dev/null +++ b/leptonica/prog/wordboxes_reg.c @@ -0,0 +1,288 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * wordboxes_reg.c + * + * This tests: + * - functions that make word boxes + * - the function that finds the nearest box to a given box in a boxa + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + +void MakeWordBoxes1(PIX *pixs, l_float32 scalefact, l_int32 thresh, + l_int32 index, L_REGPARAMS *rp); +void MakeWordBoxes2(PIX *pixs, l_float32 scalefact, l_int32 thresh, + L_REGPARAMS *rp); +void TestBoxaAdjacency(PIX *pixs, L_REGPARAMS *rp); + +#define DO_ALL 1 + +int main(int argc, + char **argv) +{ +BOX *box1, *box2; +BOXA *boxa1; +BOXAA *boxaa1; +PIX *pix1, *pix2, *pix3, *pix4; +L_REGPARAMS *rp; + + if (regTestSetup(argc, argv, &rp)) + return 1; + +#if DO_ALL + /* Make word boxes using pixWordMaskByDilation() */ + pix1 = pixRead("lucasta.150.jpg"); + MakeWordBoxes1(pix1, 1.0, 140, 0, rp); /* 0 */ + MakeWordBoxes1(pix1, 0.6, 140, 1, rp); /* 1 */ + pixDestroy(&pix1); +#endif + +#if DO_ALL + pix1 = pixRead("zanotti-78.jpg"); + MakeWordBoxes1(pix1, 1.0, 140, 2, rp); /* 2 */ + MakeWordBoxes1(pix1, 0.6, 140, 3, rp); /* 3 */ + pixDestroy(&pix1); +#endif + +#if DO_ALL + pix1 = pixRead("words.15.tif"); + MakeWordBoxes1(pix1, 1.0, 140, 4, rp); /* 4 */ + MakeWordBoxes1(pix1, 0.6, 140, 5, rp); /* 5 */ + pixDestroy(&pix1); +#endif + +#if DO_ALL + pix1 = pixRead("words.44.tif"); + MakeWordBoxes1(pix1, 1.0, 140, 6, rp); /* 6 */ + MakeWordBoxes1(pix1, 0.6, 140, 7, rp); /* 7 */ + pixDestroy(&pix1); +#endif + +#if DO_ALL + /* Make word boxes using the higher-level functions + * pixGetWordsInTextlines() and pixGetWordBoxesInTextlines() */ + + pix1 = pixRead("lucasta.150.jpg"); + MakeWordBoxes2(pix1, 0.7, 140, rp); /* 8, 9 */ + pixDestroy(&pix1); +#endif + +#if DO_ALL + pix1 = pixRead("zanotti-78.jpg"); + MakeWordBoxes2(pix1, 0.7, 140, rp); /* 10, 11 */ + pixDestroy(&pix1); +#endif + +#if DO_ALL + /* Test boxa adjacency function */ + pix1 = pixRead("lucasta.150.jpg"); + TestBoxaAdjacency(pix1, rp); /* 12 - 15 */ + pixDestroy(&pix1); +#endif + +#if DO_ALL + /* Test word and character box finding */ + pix1 = pixRead("zanotti-78.jpg"); + box1 = boxCreate(0, 0, 1500, 700); + pix2 = pixClipRectangle(pix1, box1, NULL); + box2 = boxCreate(150, 130, 1500, 355); + pixFindWordAndCharacterBoxes(pix2, box2, 130, &boxa1, &boxaa1, + "/tmp/lept/testboxes"); + pix3 = pixRead("/tmp/lept/testboxes/words.png"); + pix4 = pixRead("/tmp/lept/testboxes/chars.png"); + regTestWritePixAndCheck(rp, pix3, IFF_PNG); /* 16 */ + regTestWritePixAndCheck(rp, pix4, IFF_PNG); /* 17 */ + pixDisplayWithTitle(pix3, 200, 1000, NULL, rp->display); + pixDisplayWithTitle(pix4, 200, 100, NULL, rp->display); + pixDestroy(&pix1); + pixDestroy(&pix2); + pixDestroy(&pix3); + pixDestroy(&pix4); + boxDestroy(&box1); + boxDestroy(&box2); + boxaDestroy(&boxa1); + boxaaDestroy(&boxaa1); +#endif + + return regTestCleanup(rp); +} + +void +MakeWordBoxes1(PIX *pixs, + l_float32 scalefact, + l_int32 thresh, + l_int32 index, + L_REGPARAMS *rp) +{ +BOXA *boxa1, *boxa2; +PIX *pix1, *pix2, *pix3, *pix4, *pix5; +PIXA *pixa1; + + pix1 = pixScale(pixs, scalefact, scalefact); + pix2 = pixConvertTo1(pix1, thresh); + pixa1 = pixaCreate(3); + pixWordMaskByDilation(pix2, &pix3, NULL, pixa1); + pix4 = NULL; + if (pix3) { + boxa1 = pixConnComp(pix3, NULL, 8); + boxa2 = boxaTransform(boxa1, 0, 0, 1.0/scalefact, 1.0/scalefact); + pix4 = pixConvertTo32(pixs); + pixRenderBoxaArb(pix4, boxa2, 2, 255, 0, 0); + pix5 = pixaDisplayTiledInColumns(pixa1, 1, 1.0, 25, 2); + pixDisplayWithTitle(pix5, 200 * index, 0, NULL, rp->display); + boxaDestroy(&boxa1); + boxaDestroy(&boxa2); + pixDestroy(&pix3); + pixDestroy(&pix5); + } + regTestWritePixAndCheck(rp, pix4, IFF_JFIF_JPEG); + pixDisplayWithTitle(pix4, 200 * index, 800, NULL, rp->display); + pixDestroy(&pix1); + pixDestroy(&pix2); + pixDestroy(&pix4); + pixaDestroy(&pixa1); +} + +void +MakeWordBoxes2(PIX *pixs, + l_float32 scalefact, + l_int32 thresh, + L_REGPARAMS *rp) +{ +l_int32 default_minwidth = 10; +l_int32 default_minheight = 10; +l_int32 default_maxwidth = 400; +l_int32 default_maxheight = 70; +l_int32 minwidth, minheight, maxwidth, maxheight; +BOXA *boxa1, *boxa2; +NUMA *na; +PIX *pix1, *pix2, *pix3, *pix4; +PIXA *pixa; + + minwidth = scalefact * default_minwidth; + minheight = scalefact * default_minheight; + maxwidth = scalefact * default_maxwidth; + maxheight = scalefact * default_maxheight; + + /* Get the word boxes */ + pix1 = pixScale(pixs, scalefact, scalefact); + pix2 = pixConvertTo1(pix1, thresh); + pixGetWordsInTextlines(pix2, minwidth, minheight, + maxwidth, maxheight, &boxa1, &pixa, &na); + pixaDestroy(&pixa); + numaDestroy(&na); + boxa2 = boxaTransform(boxa1, 0, 0, 1.0 / scalefact, 1.0 / scalefact); + pix3 = pixConvertTo32(pixs); + pixRenderBoxaArb(pix3, boxa2, 2, 255, 0, 0); + regTestWritePixAndCheck(rp, pix3, IFF_JFIF_JPEG); + pixDisplayWithTitle(pix3, 900, 0, NULL, rp->display); + boxaDestroy(&boxa1); + boxaDestroy(&boxa2); + + /* Do it again with this interface. The result should be the same. */ + pixGetWordBoxesInTextlines(pix2, minwidth, minheight, + maxwidth, maxheight, &boxa1, NULL); + boxa2 = boxaTransform(boxa1, 0, 0, 1.0 / scalefact, 1.0 / scalefact); + pix4 = pixConvertTo32(pixs); + pixRenderBoxaArb(pix4, boxa2, 2, 255, 0, 0); + if (regTestComparePix(rp, pix3, pix4)) { + L_ERROR("pix not the same", "MakeWordBoxes2"); + pixDisplayWithTitle(pix4, 1200, 0, NULL, rp->display); + } + pixDestroy(&pix1); + pixDestroy(&pix2); + pixDestroy(&pix3); + pixDestroy(&pix4); + boxaDestroy(&boxa1); + boxaDestroy(&boxa2); +} + +void +TestBoxaAdjacency(PIX *pixs, + L_REGPARAMS *rp) +{ +l_int32 i, j, k, n; +BOX *box1, *box2; +BOXA *boxa0, *boxa1, *boxa2; +PIX *pix0, *pix1, *pix2, *pix3; +NUMAA *naai, *naad; + + pix0 = pixConvertTo1(pixs, 140); + + /* Make a word mask and remove small components */ + pixWordMaskByDilation(pix0, &pix1, NULL, NULL); + boxa0 = pixConnComp(pix1, NULL, 8); + boxa1 = boxaSelectBySize(boxa0, 8, 8, L_SELECT_IF_BOTH, + L_SELECT_IF_GT, NULL); + pix2 = pixConvertTo32(pixs); + pixRenderBoxaArb(pix2, boxa1, 2, 255, 0, 0); + regTestWritePixAndCheck(rp, pix2, IFF_JFIF_JPEG); + pixDisplayWithTitle(pix2, 600, 700, NULL, rp->display); + pixDestroy(&pix1); + + /* Find the adjacent boxes and their distances */ + boxaFindNearestBoxes(boxa1, L_NON_NEGATIVE, 0, &naai, &naad); + numaaWrite("/tmp/lept/regout/index.naa", naai); + regTestCheckFile(rp, "/tmp/lept/regout/index.naa"); + numaaWrite("/tmp/lept/regout/dist.naa", naad); + regTestCheckFile(rp, "/tmp/lept/regout/dist.naa"); + + /* For a few boxes, show the (up to 4) adjacent boxes */ + n = boxaGetCount(boxa1); + pix3 = pixConvertTo32(pixs); + for (i = 10; i < n; i += 25) { + box1 = boxaGetBox(boxa1, i, L_COPY); + pixRenderBoxArb(pix3, box1, 2, 255, 0, 0); + boxa2 = boxaCreate(4); + for (j = 0; j < 4; j++) { + numaaGetValue(naai, i, j, NULL, &k); + if (k >= 0) { + box2 = boxaGetBox(boxa1, k, L_COPY); + boxaAddBox(boxa2, box2, L_INSERT); + } + } + pixRenderBoxaArb(pix3, boxa2, 2, 0, 255, 0); + boxDestroy(&box1); + boxaDestroy(&boxa2); + } + regTestWritePixAndCheck(rp, pix3, IFF_JFIF_JPEG); + pixDisplayWithTitle(pix3, 1100, 700, NULL, rp->display); + + pixDestroy(&pix0); + pixDestroy(&pix2); + pixDestroy(&pix3); + boxaDestroy(&boxa0); + boxaDestroy(&boxa1); + numaaDestroy(&naai); + numaaDestroy(&naad); +} + diff --git a/leptonica/prog/words.15.tif b/leptonica/prog/words.15.tif Binary files differnew file mode 100644 index 00000000..6a3ed9bf --- /dev/null +++ b/leptonica/prog/words.15.tif diff --git a/leptonica/prog/words.44.tif b/leptonica/prog/words.44.tif Binary files differnew file mode 100644 index 00000000..4e593543 --- /dev/null +++ b/leptonica/prog/words.44.tif diff --git a/leptonica/prog/wordsinorder.c b/leptonica/prog/wordsinorder.c new file mode 100644 index 00000000..14eb4d87 --- /dev/null +++ b/leptonica/prog/wordsinorder.c @@ -0,0 +1,145 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * wordsinorder.c + * + * wordsinorder dirin rootname [firstpage npages] + * + * dirin: directory of input pages + * rootname: used for naming the two output files (templates + * and c.c. data) + * firstpage: <optional> 0-based; default is 0 + * npages: <optional> use 0 for all pages; default is 0 + * + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + + /* Input variables */ +static const l_int32 MIN_WORD_WIDTH = 6; +static const l_int32 MIN_WORD_HEIGHT = 4; +static const l_int32 MAX_WORD_WIDTH = 500; +static const l_int32 MAX_WORD_HEIGHT = 100; + +#define BUF_SIZE 512 +#define RENDER_PAGES 1 + +int main(int argc, + char **argv) +{ +char filename[BUF_SIZE]; +char *dirin, *rootname, *fname; +l_int32 i, j, w, h, firstpage, npages, nfiles, ncomp; +l_int32 index, ival, rval, gval, bval; +BOX *box; +BOXA *boxa; +BOXAA *baa; +NUMA *nai; +NUMAA *naa; +SARRAY *safiles; +PIX *pixs, *pix1, *pix2, *pixd; +PIXCMAP *cmap; +static char mainName[] = "wordsinorder"; + + if (argc != 3 && argc != 5) + return ERROR_INT( + " Syntax: wordsinorder dirin rootname [firstpage, npages]", + mainName, 1); + dirin = argv[1]; + rootname = argv[2]; + if (argc == 3) { + firstpage = 0; + npages = 0; + } + else { + firstpage = atoi(argv[3]); + npages = atoi(argv[4]); + } + setLeptDebugOK(1); + + /* Compute the word bounding boxes at 2x reduction, along with + * the textlines that they are in. */ + safiles = getSortedPathnamesInDirectory(dirin, NULL, firstpage, npages); + nfiles = sarrayGetCount(safiles); + baa = boxaaCreate(nfiles); + naa = numaaCreate(nfiles); + for (i = 0; i < nfiles; i++) { + fname = sarrayGetString(safiles, i, L_NOCOPY); + if ((pixs = pixRead(fname)) == NULL) { + L_WARNING("image file %d not read\n", mainName, i); + continue; + } + pix1 = pixReduceRankBinary2(pixs, 1, NULL); + pixGetWordBoxesInTextlines(pix1, MIN_WORD_WIDTH, MIN_WORD_HEIGHT, + MAX_WORD_WIDTH, MAX_WORD_HEIGHT, + &boxa, &nai); + boxaaAddBoxa(baa, boxa, L_INSERT); + numaaAddNuma(naa, nai, L_INSERT); + pixDestroy(&pix1); + +#if RENDER_PAGES + /* Show the results on a 2x reduced image, where each + * word is outlined and the color of the box depends on the + * computed textline. */ + pix1 = pixReduceRankBinary2(pixs, 2, NULL); + pixGetDimensions(pix1, &w, &h, NULL); + pixd = pixCreate(w, h, 8); + cmap = pixcmapCreateRandom(8, 1, 1); /* first color is black */ + pixSetColormap(pixd, cmap); + + pix2 = pixUnpackBinary(pix1, 8, 1); + pixRasterop(pixd, 0, 0, w, h, PIX_SRC | PIX_DST, pix2, 0, 0); + ncomp = boxaGetCount(boxa); + for (j = 0; j < ncomp; j++) { + box = boxaGetBox(boxa, j, L_CLONE); + numaGetIValue(nai, j, &ival); + index = 1 + (ival % 254); /* omit black and white */ + pixcmapGetColor(cmap, index, &rval, &gval, &bval); + pixRenderBoxArb(pixd, box, 2, rval, gval, bval); + boxDestroy(&box); + } + + snprintf(filename, BUF_SIZE, "%s.%05d", rootname, i); + lept_stderr("filename: %s\n", filename); + pixWrite(filename, pixd, IFF_PNG); + pixDestroy(&pix1); + pixDestroy(&pix2); + pixDestroy(&pixs); + pixDestroy(&pixd); +#endif /* RENDER_PAGES */ + } + + boxaaDestroy(&baa); + numaaDestroy(&naa); + sarrayDestroy(&safiles); + return 0; +} + diff --git a/leptonica/prog/writemtiff.c b/leptonica/prog/writemtiff.c new file mode 100644 index 00000000..32f7bae6 --- /dev/null +++ b/leptonica/prog/writemtiff.c @@ -0,0 +1,61 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * writemtiff.c + * + * Writes all matched files into a multipage tiff + * + * Usage: + * (1) To write all files in <dirin>: + * writemtiff <dirin> <fileout> + * (2) To write files in <dirin> matching a given <pattern>: + * writemtiff <dirin> <pattern> <fileout> + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + +int main(int argc, + char **argv) +{ +static char mainName[] = "writemtiff"; + + if (argc != 3 && argc != 4) + return ERROR_INT(" Syntax: writemtiff dirin [pattern] fileout", + mainName, 1); + + setLeptDebugOK(1); + if (argc == 3) + writeMultipageTiff(argv[1], NULL, argv[2]); + else /* argc == 4 */ + writeMultipageTiff(argv[1], argv[2], argv[3]); + return 0; +} + diff --git a/leptonica/prog/writetext_reg.c b/leptonica/prog/writetext_reg.c new file mode 100644 index 00000000..ca75f2d8 --- /dev/null +++ b/leptonica/prog/writetext_reg.c @@ -0,0 +1,177 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * writetext_reg.c + * + * Regression test for writing a block of text in one of 4 locations + * relative to a pix. This tests writing on 8 different types of images. + * Output is written to /tmp/lept/regout/pixd[1,2,3,4].png + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + +void AddTextAndSave(PIXA *pixa, PIX *pixs, L_BMF *bmf, const char *textstr, + l_int32 location, l_uint32 val); + +const char *textstr[] = + {"This is a simple test of text writing: 8 bpp", + "This is a simple test of text writing: 32 bpp", + "This is a simple test of text writing: 8 bpp cmapped", + "This is a simple test of text writing: 4 bpp cmapped", + "This is a simple test of text writing: 4 bpp", + "This is a simple test of text writing: 2 bpp cmapped", + "This is a simple test of text writing: 2 bpp", + "This is a simple test of text writing: 1 bpp"}; + +const char *topstr[] = + {"Text is added above each image", + "Text is added over the top of each image", + "Text is added over the bottom of each image", + "Text is added below each image"}; + +const l_int32 loc[] = {1, 5, 6, 2}; + +const l_uint32 colors[6] = {0x4090e000, 0x40e09000, 0x9040e000, 0x90e04000, + 0xe0409000, 0xe0904000}; + + +int main(int argc, + char **argv) +{ +char buf[512]; +l_int32 i; +L_BMF *bmf, *bmftop; +PIX *pixs, *pixt, *pixd; +PIX *pix1, *pix2, *pix3, *pix4, *pix5, *pix6, *pix7, *pix8; +PIXA *pixa; +L_REGPARAMS *rp; +SARRAY *sa; + +#if !defined(HAVE_LIBPNG) + L_ERROR("This test requires libpng to run.\n", "writetext_reg"); + exit(77); +#endif + + if (regTestSetup(argc, argv, &rp)) + return 1; + + bmf = bmfCreate("./fonts", 6); + bmftop = bmfCreate("./fonts", 10); + pixs = pixRead("lucasta.047.jpg"); + pix1 = pixScale(pixs, 0.4, 0.4); /* 8 bpp grayscale */ + pix2 = pixConvertTo32(pix1); /* 32 bpp rgb */ + pix3 = pixThresholdOn8bpp(pix1, 12, 1); /* 8 bpp cmapped */ + pix4 = pixThresholdTo4bpp(pix1, 10, 1); /* 4 bpp cmapped */ + pix5 = pixThresholdTo4bpp(pix1, 10, 0); /* 4 bpp not cmapped */ + pix6 = pixThresholdTo2bpp(pix1, 3, 1); /* 2 bpp cmapped */ + pix7 = pixThresholdTo2bpp(pix1, 3, 0); /* 2 bpp not cmapped */ + pix8 = pixThresholdToBinary(pix1, 160); /* 1 bpp */ + + for (i = 0; i < 4; i++) { + pixa = pixaCreate(0); + AddTextAndSave(pixa, pix1, bmf, textstr[0], loc[i], 800); + AddTextAndSave(pixa, pix2, bmf, textstr[1], loc[i], 0xff000000); + AddTextAndSave(pixa, pix3, bmf, textstr[2], loc[i], 0x00ff0000); + AddTextAndSave(pixa, pix4, bmf, textstr[3], loc[i], 0x0000ff00); + AddTextAndSave(pixa, pix5, bmf, textstr[4], loc[i], 800); + AddTextAndSave(pixa, pix6, bmf, textstr[5], loc[i], 0xff000000); + AddTextAndSave(pixa, pix7, bmf, textstr[6], loc[i], 800); + AddTextAndSave(pixa, pix8, bmf, textstr[7], loc[i], 800); + pixt = pixaDisplayTiledInColumns(pixa, 4, 1.0, 30, 2); + pixd = pixAddSingleTextblock(pixt, bmftop, topstr[i], + 0xff00ff00, L_ADD_ABOVE, NULL); + regTestWritePixAndCheck(rp, pixd, IFF_PNG); /* 0 - 4 */ + pixDisplayWithTitle(pixd, 50 * i, 50, NULL, rp->display); + pixDestroy(&pixt); + pixDestroy(&pixd); + pixaDestroy(&pixa); + } + + pixDestroy(&pixs); + pixDestroy(&pix1); + pixDestroy(&pix2); + pixDestroy(&pix3); + pixDestroy(&pix4); + pixDestroy(&pix5); + pixDestroy(&pix6); + pixDestroy(&pix7); + pixDestroy(&pix8); + bmfDestroy(&bmf); + bmfDestroy(&bmftop); + + /* Write multiple lines in different colors, filling up + * the colormap and requesting even more colors. */ + pixs = pixRead("weasel4.11c.png"); + pix1 = pixConvertTo8(pixs, 0); + pix2 = pixScale(pixs, 8.0, 8.0); + pix3 = pixQuantFromCmap(pix2, pixGetColormap(pixs), 4, 5, + L_EUCLIDEAN_DISTANCE); + regTestWritePixAndCheck(rp, pix3, IFF_PNG); /* 5 */ + pixDisplayWithTitle(pix3, 0, 500, NULL, rp->display); + bmf = bmfCreate("fonts", 10); + sa = sarrayCreate(6); + for (i = 0; i < 6; i++) { + snprintf(buf, sizeof(buf), "This is textline %d\n", i); + sarrayAddString(sa, buf, L_COPY); + } + for (i = 0; i < 6; i++) { + pixSetTextline(pix3, bmf, sarrayGetString(sa, i, L_NOCOPY), + colors[i], 50, 120 + 60 * i, NULL, NULL); + } + regTestWritePixAndCheck(rp, pix3, IFF_PNG); /* 6 */ + pixDisplayWithTitle(pix3, 600, 500, NULL, rp->display); + pixDestroy(&pixs); + pixDestroy(&pix1); + pixDestroy(&pix2); + pixDestroy(&pix3); + bmfDestroy(&bmf); + sarrayDestroy(&sa); + return regTestCleanup(rp); +} + + +void +AddTextAndSave(PIXA *pixa, + PIX *pixs, + L_BMF *bmf, + const char *textstr, + l_int32 location, + l_uint32 val) +{ +l_int32 n, newrow, ovf; +PIX *pix1; + + pix1 = pixAddSingleTextblock(pixs, bmf, textstr, val, location, &ovf); + n = pixaGetCount(pixa); + newrow = (n % 4) ? 0 : 1; + pixaAddPix(pixa, pix1, L_INSERT); + if (ovf) lept_stderr("Overflow writing text in image %d\n", n + 1); +} diff --git a/leptonica/prog/wyom.jpg b/leptonica/prog/wyom.jpg Binary files differnew file mode 100644 index 00000000..9a06cadd --- /dev/null +++ b/leptonica/prog/wyom.jpg diff --git a/leptonica/prog/xformbox_reg.c b/leptonica/prog/xformbox_reg.c new file mode 100644 index 00000000..8c92997b --- /dev/null +++ b/leptonica/prog/xformbox_reg.c @@ -0,0 +1,325 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * xformbox_reg.c + * + * Tests ordered box transforms (rotation, scaling, translation). + * Also tests the various box hashing graphics operations. + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + + /* Consts for second set */ +static const l_int32 SHIFTX_2 = 50; +static const l_int32 SHIFTY_2 = 70; +static const l_float32 SCALEX_2 = 1.17; +static const l_float32 SCALEY_2 = 1.13; +static const l_float32 ROTATION_2 = 0.10; /* radian */ + + /* Consts for third set */ +static const l_int32 SHIFTX_3 = 44; +static const l_int32 SHIFTY_3 = 39; +static const l_float32 SCALEX_3 = 0.83; +static const l_float32 SCALEY_3 = 0.78; +static const l_float32 ROTATION_3 = 0.11; /* radian */ + + +l_int32 RenderTransformedBoxa(PIX *pixt, BOXA *boxa, l_int32 i); + + +int main(int argc, + char **argv) +{ +l_int32 i, n, ws, hs, w, h, rval, gval, bval, order; +l_float32 *mat1, *mat2, *mat3; +l_float32 matd[9]; +BOX *box, *boxt; +BOXA *boxa, *boxat, *boxa1, *boxa2, *boxa3, *boxa4, *boxa5; +PIX *pix, *pixs, *pixc, *pixt, *pix1, *pix2, *pix3; +PIXA *pixa; +L_REGPARAMS *rp; + + if (regTestSetup(argc, argv, &rp)) + return 1; + + /* ----------------------------------------------------------- * + * Test hash rendering in 3 modes * + * ----------------------------------------------------------- */ + pixs = pixRead("feyn.tif"); + box = boxCreate(461, 429, 1393, 342); + pix1 = pixClipRectangle(pixs, box, NULL); + boxa = pixConnComp(pix1, NULL, 8); + n = boxaGetCount(boxa); + pix2 = pixConvertTo8(pix1, 1); + pix3 = pixConvertTo32(pix1); + for (i = 0; i < n; i++) { + boxt = boxaGetBox(boxa, i, L_CLONE); + rval = (1413 * (i + 1)) % 256; + gval = (4917 * (i + 1)) % 256; + bval = (7341 * (i + 1)) % 256; + pixRenderHashBox(pix1, boxt, 8, 2, i % 4, 1, L_SET_PIXELS); + pixRenderHashBoxArb(pix2, boxt, 7, 2, i % 4, 1, rval, gval, bval); + pixRenderHashBoxBlend(pix3, boxt, 7, 2, i % 4, 1, + rval, gval, bval, 0.5); + boxDestroy(&boxt); + } + regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 0 */ + regTestWritePixAndCheck(rp, pix2, IFF_PNG); /* 1 */ + regTestWritePixAndCheck(rp, pix3, IFF_PNG); /* 2 */ + pixDisplayWithTitle(pix1, 0, 0, NULL, rp->display); + pixDisplayWithTitle(pix2, 0, 300, NULL, rp->display); + pixDisplayWithTitle(pix3, 0, 570, NULL, rp->display); + boxaDestroy(&boxa); + boxDestroy(&box); + pixDestroy(&pixs); + pixDestroy(&pix1); + pixDestroy(&pix2); + pixDestroy(&pix3); + + /* ----------------------------------------------------------- * + * Test orthogonal box rotation and hash rendering * + * ----------------------------------------------------------- */ + pixs = pixRead("feyn.tif"); + box = boxCreate(461, 429, 1393, 342); + pix1 = pixClipRectangle(pixs, box, NULL); + pixc = pixConvertTo32(pix1); + pixGetDimensions(pix1, &w, &h, NULL); + boxa1 = pixConnComp(pix1, NULL, 8); + pixa = pixaCreate(4); + for (i = 0; i < 4; i++) { + pix2 = pixRotateOrth(pixc, i); + boxa2 = boxaRotateOrth(boxa1, w, h, i); + rval = (1413 * (i + 4)) % 256; + gval = (4917 * (i + 4)) % 256; + bval = (7341 * (i + 4)) % 256; + pixRenderHashBoxaArb(pix2, boxa2, 10, 3, i, 1, rval, gval, bval); + pixaAddPix(pixa, pix2, L_INSERT); + boxaDestroy(&boxa2); + } + pix3 = pixaDisplayTiledInRows(pixa, 32, 1200, 0.7, 0, 30, 3); + regTestWritePixAndCheck(rp, pix3, IFF_PNG); /* 3 */ + pixDisplayWithTitle(pix3, 0, 800, NULL, rp->display); + boxDestroy(&box); + pixDestroy(&pixs); + pixDestroy(&pix1); + pixDestroy(&pix3); + pixDestroy(&pixc); + boxaDestroy(&boxa1); + pixaDestroy(&pixa); + + /* ----------------------------------------------------------- * + * Test box transforms with either translation or scaling * + * combined with rotation, using the simple 'ordered' * + * function. Show that the order of the operations does * + * not matter; different hashing schemes end up in the * + * identical boxes. * + * ----------------------------------------------------------- */ + pix = pixRead("feyn.tif"); + box = boxCreate(420, 360, 1500, 465); + pixt = pixClipRectangle(pix, box, NULL); + pixs = pixAddBorderGeneral(pixt, 0, 200, 0, 0, 0); + boxDestroy(&box); + pixDestroy(&pix); + pixDestroy(&pixt); + boxa = pixConnComp(pixs, NULL, 8); + n = boxaGetCount(boxa); + pixa = pixaCreate(0); + + pixt = pixConvertTo32(pixs); + for (i = 0; i < 3; i++) { + if (i == 0) + order = L_TR_SC_RO; + else if (i == 1) + order = L_TR_RO_SC; + else + order = L_SC_TR_RO; + boxat = boxaTransformOrdered(boxa, SHIFTX_2, SHIFTY_2, 1.0, 1.0, + 450, 250, ROTATION_2, order); + RenderTransformedBoxa(pixt, boxat, i); + boxaDestroy(&boxat); + } + pixaAddPix(pixa, pixt, L_INSERT); + + pixt = pixConvertTo32(pixs); + for (i = 0; i < 3; i++) { + if (i == 0) + order = L_RO_TR_SC; + else if (i == 1) + order = L_RO_SC_TR; + else + order = L_SC_RO_TR; + boxat = boxaTransformOrdered(boxa, SHIFTX_2, SHIFTY_2, 1.0, 1.0, + 450, 250, ROTATION_2, order); + RenderTransformedBoxa(pixt, boxat, i + 4); + boxaDestroy(&boxat); + } + pixaAddPix(pixa, pixt, L_INSERT); + + pixt = pixConvertTo32(pixs); + for (i = 0; i < 3; i++) { + if (i == 0) + order = L_TR_SC_RO; + else if (i == 1) + order = L_SC_RO_TR; + else + order = L_SC_TR_RO; + boxat = boxaTransformOrdered(boxa, 0, 0, SCALEX_2, SCALEY_2, + 450, 250, ROTATION_2, order); + RenderTransformedBoxa(pixt, boxat, i + 8); + boxaDestroy(&boxat); + } + pixaAddPix(pixa, pixt, L_INSERT); + + pixt = pixConvertTo32(pixs); + for (i = 0; i < 3; i++) { + if (i == 0) + order = L_RO_TR_SC; + else if (i == 1) + order = L_RO_SC_TR; + else + order = L_TR_RO_SC; + boxat = boxaTransformOrdered(boxa, 0, 0, SCALEX_2, SCALEY_2, + 450, 250, ROTATION_2, order); + RenderTransformedBoxa(pixt, boxat, i + 12); + boxaDestroy(&boxat); + } + pixaAddPix(pixa, pixt, L_INSERT); + + pixt = pixaDisplayTiledInColumns(pixa, 1, 0.5, 20, 0); + regTestWritePixAndCheck(rp, pixt, IFF_PNG); /* 4 */ + pixDisplayWithTitle(pixt, 1000, 0, NULL, rp->display); + pixDestroy(&pixt); + pixDestroy(&pixs); + boxaDestroy(&boxa); + pixaDestroy(&pixa); + + + /* ----------------------------------------------------------- * + * Do more testing of box and pta transforms. Show that * + * resulting boxes are identical by three methods. * + * ----------------------------------------------------------- */ + /* Set up pix and boxa */ + pixa = pixaCreate(0); + pix = pixRead("lucasta.1.300.tif"); + pixTranslate(pix, pix, 70, 0, L_BRING_IN_WHITE); + pixt = pixCloseBrick(NULL, pix, 14, 5); + pixOpenBrick(pixt, pixt, 1, 2); + boxa = pixConnComp(pixt, NULL, 8); + pixs = pixConvertTo32(pix); + pixc = pixCopy(NULL, pixs); + RenderTransformedBoxa(pixc, boxa, 113); + pixaAddPix(pixa, pixc, L_INSERT); + pixDestroy(&pix); + pixDestroy(&pixt); + + /* (a) Do successive discrete operations: shift, scale, rotate */ + pix1 = pixTranslate(NULL, pixs, SHIFTX_3, SHIFTY_3, L_BRING_IN_WHITE); + boxa1 = boxaTranslate(boxa, SHIFTX_3, SHIFTY_3); + pixc = pixCopy(NULL, pix1); + RenderTransformedBoxa(pixc, boxa1, 213); + pixaAddPix(pixa, pixc, L_INSERT); + + pix2 = pixScale(pix1, SCALEX_3, SCALEY_3); + boxa2 = boxaScale(boxa1, SCALEX_3, SCALEY_3); + pixc = pixCopy(NULL, pix2); + RenderTransformedBoxa(pixc, boxa2, 313); + pixaAddPix(pixa, pixc, L_INSERT); + + pixGetDimensions(pix2, &w, &h, NULL); + pix3 = pixRotateAM(pix2, ROTATION_3, L_BRING_IN_WHITE); + boxa3 = boxaRotate(boxa2, w / 2, h / 2, ROTATION_3); + pixc = pixCopy(NULL, pix3); + RenderTransformedBoxa(pixc, boxa3, 413); + pixaAddPix(pixa, pixc, L_INSERT); + + /* (b) Set up and use the composite transform */ + mat1 = createMatrix2dTranslate(SHIFTX_3, SHIFTY_3); + mat2 = createMatrix2dScale(SCALEX_3, SCALEY_3); + mat3 = createMatrix2dRotate(w / 2, h / 2, ROTATION_3); + l_productMat3(mat3, mat2, mat1, matd, 3); + boxa4 = boxaAffineTransform(boxa, matd); + pixc = pixCopy(NULL, pix3); + RenderTransformedBoxa(pixc, boxa4, 513); + pixaAddPix(pixa, pixc, L_INSERT); + + /* (c) Use the special 'ordered' function */ + pixGetDimensions(pixs, &ws, &hs, NULL); + boxa5 = boxaTransformOrdered(boxa, SHIFTX_3, SHIFTY_3, + SCALEX_3, SCALEY_3, + ws / 2, hs / 2, ROTATION_3, L_TR_SC_RO); + pixc = pixCopy(NULL, pix3); + RenderTransformedBoxa(pixc, boxa5, 613); + pixaAddPix(pixa, pixc, L_INSERT); + pixDestroy(&pix1); + pixDestroy(&pix2); + pixDestroy(&pix3); + boxaDestroy(&boxa1); + boxaDestroy(&boxa2); + boxaDestroy(&boxa3); + boxaDestroy(&boxa4); + boxaDestroy(&boxa5); + lept_free(mat1); + lept_free(mat2); + lept_free(mat3); + + pixt = pixaDisplayTiledInColumns(pixa, 2, 0.5, 20, 0); + regTestWritePixAndCheck(rp, pixt, IFF_PNG); /* 5 */ + pixDisplayWithTitle(pixt, 1000, 300, NULL, rp->display); + pixDestroy(&pixt); + pixDestroy(&pixs); + boxaDestroy(&boxa); + pixaDestroy(&pixa); + return regTestCleanup(rp); +} + + +l_int32 +RenderTransformedBoxa(PIX *pixt, + BOXA *boxa, + l_int32 i) +{ +l_int32 j, n, rval, gval, bval; +BOX *box; + + n = boxaGetCount(boxa); + rval = (1413 * i) % 256; + gval = (4917 * i) % 256; + bval = (7341 * i) % 256; + for (j = 0; j < n; j++) { + box = boxaGetBox(boxa, j, L_CLONE); + pixRenderHashBoxArb(pixt, box, 10, 3, i % 4, 1, rval, gval, bval); + boxDestroy(&box); + } + return 0; +} + + + diff --git a/leptonica/prog/xtractprotos.c b/leptonica/prog/xtractprotos.c new file mode 100644 index 00000000..9781b1c5 --- /dev/null +++ b/leptonica/prog/xtractprotos.c @@ -0,0 +1,263 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * xtractprotos.c + * + * This program accepts a list of C files on the command line + * and outputs the C prototypes to stdout. It uses cpp to + * handle the preprocessor macros, and then parses the cpp output. + * In leptonica, it is used to make allheaders.h (and optionally + * leptprotos.h, which contains just the function prototypes.) + * In leptonica, only the file allheaders.h is included with + * source files. + * + * An optional 'prestring' can be prepended to each declaration. + * And the function prototypes can either be sent to stdout, written + * to a named file, or placed in-line within allheaders.h. + * + * The signature is: + * + * xtractprotos [-prestring=<string>] [-protos=<where>] [list of C files] + * + * Without -protos, the prototypes are written to stdout. + * With -protos, allheaders.h is rewritten: + * * if you use -protos=inline, the prototypes are placed within + * allheaders.h. + * * if you use -protos=leptprotos.h, the prototypes written to + * the file leptprotos.h, and alltypes.h has + * #include "leptprotos.h" + * + * For constructing allheaders.h, two text files are provided: + * allheaders_top.txt + * allheaders_bot.txt + * The former contains the leptonica version number, so it must + * be updated when a new version is made. + * + * For simple C prototype extraction, xtractprotos has essentially + * the same functionality as Adam Bryant's cextract, but the latter + * has not been officially supported for over 15 years, has been + * patched numerous times, and doesn't work with sys/sysmacros.h + * for 64 bit architecture. + * + * This is used to extract all prototypes in liblept. + * The function that does all the work is parseForProtos(), + * which takes as input the output from cpp. + * + * xtractprotos can run in leptonica to do an 'ab initio' generation + * of allheaders.h; that is, it can make allheaders.h without + * leptprotos.h and with an allheaders.h file of 0 length. + * Of course, the usual situation is to run it with a valid allheaders.h, + * which includes all the function prototypes. To avoid including + * all the prototypes in the input for each file, cpp runs here + * with -DNO_PROTOS, so the prototypes are not included -- this is + * much faster. + * + * The xtractprotos version number, defined below, is incremented + * whenever a new version is made. + * + * Note: this uses cpp to preprocess the input. (The name of the cpp + * tempfile is constructed below. It has a "." in the tail, which + * Cygwin needs to prevent it from appending ".exe" to the filename.) + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include <string.h> +#include "allheaders.h" + +#define L_BUFSIZE 512 /* hardcoded below in sscanf() */ +static const char *version = "1.5"; + + +int main(int argc, + char **argv) +{ +char *filein, *str, *tempfile, *prestring, *outprotos, *protostr; +char buf[L_BUFSIZE]; +l_int32 i, maxindex, in_line, nflags, protos_added, firstfile, len, ret; +size_t nbytes; +L_BYTEA *ba, *ba2; +SARRAY *sa; +static char mainName[] = "xtractprotos"; + + if (argc == 1) { + lept_stderr( + "xtractprotos [-prestring=<string>] [-protos=<where>] " + "[list of C files]\n" + "where the prestring is prepended to each prototype, and \n" + "protos can be either 'inline' or the name of an output " + "prototype file\n"); + return 1; + } + + setLeptDebugOK(1); + + /* ---------------------------------------------------------------- */ + /* Parse input flags and find prestring and outprotos, if requested */ + /* ---------------------------------------------------------------- */ + prestring = outprotos = NULL; + in_line = FALSE; + nflags = 0; + maxindex = L_MIN(3, argc); + for (i = 1; i < maxindex; i++) { + if (argv[i][0] == '-') { + if (!strncmp(argv[i], "-prestring", 10)) { + nflags++; + ret = sscanf(argv[i] + 1, "prestring=%490s", buf); + if (ret != 1) { + lept_stderr("parse failure for prestring\n"); + return 1; + } + if ((len = strlen(buf)) > L_BUFSIZE - 3) { + L_WARNING("prestring too large; omitting!\n", mainName); + } else { + buf[len] = ' '; + buf[len + 1] = '\0'; + prestring = stringNew(buf); + } + } else if (!strncmp(argv[i], "-protos", 7)) { + nflags++; + ret = sscanf(argv[i] + 1, "protos=%490s", buf); + if (ret != 1) { + lept_stderr("parse failure for protos\n"); + return 1; + } + outprotos = stringNew(buf); + if (!strncmp(outprotos, "inline", 7)) + in_line = TRUE; + } + } + } + + if (argc - nflags < 2) { + lept_stderr("no files specified!\n"); + return 1; + } + + + /* ---------------------------------------------------------------- */ + /* Generate the prototype string */ + /* ---------------------------------------------------------------- */ + ba = l_byteaCreate(500); + + /* First the extern C head */ + sa = sarrayCreate(0); + sarrayAddString(sa, "/*", L_COPY); + snprintf(buf, L_BUFSIZE, + " * These prototypes were autogen'd by xtractprotos, v. %s", + version); + sarrayAddString(sa, buf, L_COPY); + sarrayAddString(sa, " */", L_COPY); + sarrayAddString(sa, "#ifdef __cplusplus", L_COPY); + sarrayAddString(sa, "extern \"C\" {", L_COPY); + sarrayAddString(sa, "#endif /* __cplusplus */\n", L_COPY); + str = sarrayToString(sa, 1); + l_byteaAppendString(ba, str); + lept_free(str); + sarrayDestroy(&sa); + + /* Then the prototypes */ + firstfile = 1 + nflags; + protos_added = FALSE; + if ((tempfile = l_makeTempFilename()) == NULL) { + lept_stderr("failure to make a writeable temp file\n"); + return 1; + } + for (i = firstfile; i < argc; i++) { + filein = argv[i]; + len = strlen(filein); + if (filein[len - 1] == 'h') /* skip .h files */ + continue; + snprintf(buf, L_BUFSIZE, "cpp -ansi -DNO_PROTOS %s %s", + filein, tempfile); + ret = system(buf); /* cpp */ + if (ret) { + lept_stderr("cpp failure for %s; continuing\n", filein); + continue; + } + + if ((str = parseForProtos(tempfile, prestring)) == NULL) { + lept_stderr("parse failure for %s; continuing\n", filein); + continue; + } + if (strlen(str) > 1) { /* strlen(str) == 1 is a file without protos */ + l_byteaAppendString(ba, str); + protos_added = TRUE; + } + lept_free(str); + } + lept_rmfile(tempfile); + lept_free(tempfile); + + /* Lastly the extern C tail */ + sa = sarrayCreate(0); + sarrayAddString(sa, "\n#ifdef __cplusplus", L_COPY); + sarrayAddString(sa, "}", L_COPY); + sarrayAddString(sa, "#endif /* __cplusplus */", L_COPY); + str = sarrayToString(sa, 1); + l_byteaAppendString(ba, str); + lept_free(str); + sarrayDestroy(&sa); + + protostr = (char *)l_byteaCopyData(ba, &nbytes); + l_byteaDestroy(&ba); + + + /* ---------------------------------------------------------------- */ + /* Generate the output */ + /* ---------------------------------------------------------------- */ + if (!outprotos) { /* just write to stdout */ + lept_stderr("%s\n", protostr); + lept_free(protostr); + return 0; + } + + /* If no protos were found, do nothing further */ + if (!protos_added) { + lept_stderr("No protos found\n"); + lept_free(protostr); + return 1; + } + + /* Make the output files */ + ba = l_byteaInitFromFile("allheaders_top.txt"); + if (!in_line) { + snprintf(buf, sizeof(buf), "#include \"%s\"\n", outprotos); + l_byteaAppendString(ba, buf); + l_binaryWrite(outprotos, "w", protostr, nbytes); + } else { + l_byteaAppendString(ba, protostr); + } + ba2 = l_byteaInitFromFile("allheaders_bot.txt"); + l_byteaJoin(ba, &ba2); + l_byteaWrite("allheaders.h", ba, 0, 0); + l_byteaDestroy(&ba); + lept_free(protostr); + return 0; +} diff --git a/leptonica/prog/yuvtest.c b/leptonica/prog/yuvtest.c new file mode 100644 index 00000000..da6ecaa1 --- /dev/null +++ b/leptonica/prog/yuvtest.c @@ -0,0 +1,221 @@ +/*====================================================================* + - 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. + *====================================================================*/ + +/* + * yuvtest.c + * + * Test the yuv to rgb conversion. + * + * Note that the yuv gamut is greater than rgb, so although any + * rgb image can be converted to yuv (and back), any possible + * yuv value does not necessarily represent a valid rgb value. + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include "allheaders.h" + +void AddTransformsRGB(PIXA *pixa, L_BMF *bmf, l_int32 gval); +void AddTransformsYUV(PIXA *pixa, L_BMF *bmf, l_int32 yval); + + +l_int32 main(int argc, + char **argv) +{ +l_int32 i, rval, gval, bval, yval, uval, vval; +l_float32 *a[3], b[3]; +L_BMF *bmf; +PIX *pixd; +PIXA *pixa; + + setLeptDebugOK(1); + lept_mkdir("lept/yuv"); + + /* Explore the range of rgb --> yuv transforms. All rgb + * values transform to a valid value of yuv, so when transforming + * back we get the same rgb values that we started with. */ + pixa = pixaCreate(0); + bmf = bmfCreate("fonts", 6); + for (gval = 0; gval <= 255; gval += 20) + AddTransformsRGB(pixa, bmf, gval); + + pixd = pixaDisplayTiledAndScaled(pixa, 32, 755, 1, 0, 20, 2); + pixDisplay(pixd, 100, 0); + pixWrite("/tmp/lept/yuv/yuv1.png", pixd, IFF_PNG); + pixDestroy(&pixd); + pixaDestroy(&pixa); + + /* Now start with all "valid" yuv values, not all of which are + * related to a valid rgb value. Our yuv --> rgb transform + * clips the rgb components to [0 ... 255], so when transforming + * back we get different values whenever the initial yuv + * value is out of the rgb gamut. */ + pixa = pixaCreate(0); + for (yval = 16; yval <= 235; yval += 16) + AddTransformsYUV(pixa, bmf, yval); + + pixd = pixaDisplayTiledAndScaled(pixa, 32, 755, 1, 0, 20, 2); + pixDisplay(pixd, 600, 0); + pixWrite("/tmp/lept/yuv/yuv2.png", pixd, IFF_PNG); + pixDestroy(&pixd); + pixaDestroy(&pixa); + bmfDestroy(&bmf); + + + /* --------- Try out a special case by hand, and show that --------- * + * ------- the transform matrices we are using are inverses ---------*/ + + /* First, use our functions for the transform */ + lept_stderr("Start with: yval = 143, uval = 79, vval = 103\n"); + convertYUVToRGB(143, 79, 103, &rval, &gval, &bval); + lept_stderr(" ==> rval = %d, gval = %d, bval = %d\n", rval, gval, bval); + convertRGBToYUV(rval, gval, bval, &yval, &uval, &vval); + lept_stderr(" ==> yval = %d, uval = %d, vval = %d\n", yval, uval, vval); + + /* Next, convert yuv --> rbg by solving for rgb --> yuv transform. + * [ a00 a01 a02 ] r = b0 (y - 16) + * [ a10 a11 a12 ] * g = b1 (u - 128) + * [ a20 a21 a22 ] b = b2 (v - 128) + */ + b[0] = 143.0 - 16.0; /* y - 16 */ + b[1] = 79.0 - 128.0; /* u - 128 */ + b[2] = 103.0 - 128.0; /* v - 128 */ + for (i = 0; i < 3; i++) + a[i] = (l_float32 *)lept_calloc(3, sizeof(l_float32)); + a[0][0] = 65.738 / 256.0; + a[0][1] = 129.057 / 256.0; + a[0][2] = 25.064 / 256.0; + a[1][0] = -37.945 / 256.0; + a[1][1] = -74.494 / 256.0; + a[1][2] = 112.439 / 256.0; + a[2][0] = 112.439 / 256.0; + a[2][1] = -94.154 / 256.0; + a[2][2] = -18.285 / 256.0; + lept_stderr("Here's the original matrix: yuv --> rgb:\n"); + for (i = 0; i < 3; i++) + lept_stderr(" %7.3f %7.3f %7.3f\n", 256.0 * a[i][0], + 256.0 * a[i][1], 256.0 * a[i][2]); + gaussjordan(a, b, 3); + lept_stderr("\nInput (yuv) = (143,79,103); solve for rgb:\n" + "rval = %7.3f, gval = %7.3f, bval = %7.3f\n", b[0], b[1], b[2]); + lept_stderr("Here's the inverse matrix: rgb --> yuv:\n"); + for (i = 0; i < 3; i++) + lept_stderr(" %7.3f %7.3f %7.3f\n", 256.0 * a[i][0], + 256.0 * a[i][1], 256.0 * a[i][2]); + + /* Now, convert back: rgb --> yuv; + * Do this by solving for yuv --> rgb transform. + * Use the b[] found previously (the rgb values), and + * the a[][] which now holds the rgb --> yuv transform. */ + gaussjordan(a, b, 3); + lept_stderr("\nInput rgb; solve for yuv:\n" + "yval = %7.3f, uval = %7.3f, vval = %7.3f\n", + b[0] + 16.0, b[1] + 128.0, b[2] + 128.0); + lept_stderr("Inverting the matrix again: yuv --> rgb:\n"); + for (i = 0; i < 3; i++) + lept_stderr(" %7.3f %7.3f %7.3f\n", 256.0 * a[i][0], + 256.0 * a[i][1], 256.0 * a[i][2]); + + for (i = 0; i < 3; i++) lept_free(a[i]); + return 0; +} + + +void +AddTransformsRGB(PIXA *pixa, + L_BMF *bmf, + l_int32 gval) +{ +char textbuf[256]; +l_int32 i, j, wpls; +l_uint32 *datas, *lines; +PIX *pixs, *pixt1, *pixt2, *pixt3, *pixt4; +PIXA *pixat; + + pixs = pixCreate(255, 255, 32); + wpls = pixGetWpl(pixs); + datas = pixGetData(pixs); + for (i = 0; i < 255; i++) { /* r */ + lines = datas + i * wpls; + for (j = 0; j < 255; j++) /* b */ + composeRGBPixel(i, gval, j, lines + j); + } + + pixat = pixaCreate(3); + pixaAddPix(pixat, pixs, L_INSERT); + pixt1 = pixConvertRGBToYUV(NULL, pixs); + pixaAddPix(pixat, pixt1, L_INSERT); + pixt2 = pixConvertYUVToRGB(NULL, pixt1); + pixaAddPix(pixat, pixt2, L_INSERT); + pixt3 = pixaDisplayTiledAndScaled(pixat, 32, 255, 3, 0, 20, 2); + snprintf(textbuf, sizeof(textbuf), "gval = %d", gval); + pixt4 = pixAddSingleTextblock(pixt3, bmf, textbuf, 0xff000000, + L_ADD_BELOW, NULL); + pixaAddPix(pixa, pixt4, L_INSERT); + pixDestroy(&pixt3); + pixaDestroy(&pixat); + return; +} + + +void +AddTransformsYUV(PIXA *pixa, + L_BMF *bmf, + l_int32 yval) +{ +char textbuf[256]; +l_int32 i, j, wpls; +l_uint32 *datas, *lines; +PIX *pixs, *pixt1, *pixt2, *pixt3, *pixt4; +PIXA *pixat; + + pixs = pixCreate(225, 225, 32); + wpls = pixGetWpl(pixs); + datas = pixGetData(pixs); + for (i = 0; i < 225; i++) { /* v */ + lines = datas + i * wpls; + for (j = 0; j < 225; j++) /* u */ + composeRGBPixel(yval + 16, j + 16, i + 16, lines + j); + } + + pixat = pixaCreate(3); + pixaAddPix(pixat, pixs, L_INSERT); + pixt1 = pixConvertYUVToRGB(NULL, pixs); + pixaAddPix(pixat, pixt1, L_INSERT); + pixt2 = pixConvertRGBToYUV(NULL, pixt1); + pixaAddPix(pixat, pixt2, L_INSERT); + pixt3 = pixaDisplayTiledAndScaled(pixat, 32, 225, 3, 0, 20, 2); + snprintf(textbuf, sizeof(textbuf), "yval = %d", yval); + pixt4 = pixAddSingleTextblock(pixt3, bmf, textbuf, 0xff000000, + L_ADD_BELOW, NULL); + pixaAddPix(pixa, pixt4, L_INSERT); + pixDestroy(&pixt3); + pixaDestroy(&pixat); + return; +} + diff --git a/leptonica/prog/zanotti-78.jpg b/leptonica/prog/zanotti-78.jpg Binary files differnew file mode 100644 index 00000000..a2924414 --- /dev/null +++ b/leptonica/prog/zanotti-78.jpg diff --git a/leptonica/prog/zier.jpg b/leptonica/prog/zier.jpg Binary files differnew file mode 100644 index 00000000..bd00825e --- /dev/null +++ b/leptonica/prog/zier.jpg |