summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Deutschmann <whissi@gentoo.org>2021-03-30 10:59:39 +0200
committerThomas Deutschmann <whissi@gentoo.org>2021-04-01 00:04:14 +0200
commit5ff1d6955496b3cf9a35042c9ac35db43bc336b1 (patch)
tree6d470f7eb448f59f53e8df1010aec9dad8ce1f72 /leptonica/prog
parentImport Ghostscript 9.53.1 (diff)
downloadghostscript-gpl-patches-5ff1d6955496b3cf9a35042c9ac35db43bc336b1.tar.gz
ghostscript-gpl-patches-5ff1d6955496b3cf9a35042c9ac35db43bc336b1.tar.bz2
ghostscript-gpl-patches-5ff1d6955496b3cf9a35042c9ac35db43bc336b1.zip
Import Ghostscript 9.54ghostscript-9.54
Signed-off-by: Thomas Deutschmann <whissi@gentoo.org>
Diffstat (limited to 'leptonica/prog')
-rw-r--r--leptonica/prog/1555.003.jpgbin0 -> 198621 bytes
-rw-r--r--leptonica/prog/1555.007.jpgbin0 -> 209558 bytes
-rw-r--r--leptonica/prog/19-colors.pngbin0 -> 627 bytes
-rw-r--r--leptonica/prog/CMakeLists.txt322
-rw-r--r--leptonica/prog/Leptonica.jpgbin0 -> 6723 bytes
-rw-r--r--leptonica/prog/Makefile.am138
-rw-r--r--leptonica/prog/adaptmap_dark.c198
-rw-r--r--leptonica/prog/adaptmap_reg.c208
-rw-r--r--leptonica/prog/adaptnorm_reg.c154
-rw-r--r--leptonica/prog/affine_reg.c425
-rw-r--r--leptonica/prog/alltests_reg.c282
-rw-r--r--leptonica/prog/alphaops_reg.c337
-rw-r--r--leptonica/prog/alphaxform_reg.c230
-rw-r--r--leptonica/prog/amoris.2.150.jpgbin0 -> 256907 bytes
-rw-r--r--leptonica/prog/aneurisms8.jpgbin0 -> 13702 bytes
-rw-r--r--leptonica/prog/arabic.pngbin0 -> 128175 bytes
-rw-r--r--leptonica/prog/arabic2.pngbin0 -> 107581 bytes
-rw-r--r--leptonica/prog/arabic_lines.c166
-rw-r--r--leptonica/prog/arithtest.c83
-rw-r--r--leptonica/prog/autogen.137.c98
-rw-r--r--leptonica/prog/autogen.137.h306
-rw-r--r--leptonica/prog/autogentest1.c80
-rw-r--r--leptonica/prog/autogentest2.c69
-rw-r--r--leptonica/prog/barcode-128-300.pngbin0 -> 2667 bytes
-rw-r--r--leptonica/prog/barcode-2of5-300.pngbin0 -> 2446 bytes
-rw-r--r--leptonica/prog/barcode-39-300.pngbin0 -> 3608 bytes
-rw-r--r--leptonica/prog/barcode-93-300.pngbin0 -> 2405 bytes
-rw-r--r--leptonica/prog/barcode-codabar-300.pngbin0 -> 2929 bytes
-rw-r--r--leptonica/prog/barcode-digits.pngbin0 -> 619 bytes
-rw-r--r--leptonica/prog/barcode-i2of5-300.pngbin0 -> 2325 bytes
-rw-r--r--leptonica/prog/barcode-upc-300.pngbin0 -> 5351 bytes
-rw-r--r--leptonica/prog/barcodetest.c90
-rw-r--r--leptonica/prog/barcodetest1.jpgbin0 -> 19862 bytes
-rw-r--r--leptonica/prog/barcodetest2.jpgbin0 -> 8320 bytes
-rw-r--r--leptonica/prog/baseline_reg.c135
-rw-r--r--leptonica/prog/bigweasel2.4c.pngbin0 -> 1206 bytes
-rw-r--r--leptonica/prog/bilateral1_reg.c136
-rw-r--r--leptonica/prog/bilateral2_reg.c105
-rw-r--r--leptonica/prog/bilinear_reg.c263
-rw-r--r--leptonica/prog/binarize_reg.c180
-rw-r--r--leptonica/prog/binarize_set.c177
-rw-r--r--leptonica/prog/binarizefiles.c120
-rw-r--r--leptonica/prog/bincompare.c98
-rw-r--r--leptonica/prog/binding-example.45.jpgbin0 -> 73283 bytes
-rw-r--r--leptonica/prog/binmorph1_reg.c578
-rw-r--r--leptonica/prog/binmorph2_reg.c227
-rw-r--r--leptonica/prog/binmorph3_reg.c404
-rw-r--r--leptonica/prog/binmorph4_reg.c544
-rw-r--r--leptonica/prog/binmorph5_reg.c329
-rw-r--r--leptonica/prog/binmorph6_reg.c89
-rw-r--r--leptonica/prog/blackwhite_reg.c114
-rw-r--r--leptonica/prog/blend-green1.jpgbin0 -> 13979 bytes
-rw-r--r--leptonica/prog/blend-green2.pngbin0 -> 7770 bytes
-rw-r--r--leptonica/prog/blend-green3.pngbin0 -> 4570 bytes
-rw-r--r--leptonica/prog/blend-orange.jpgbin0 -> 15094 bytes
-rw-r--r--leptonica/prog/blend-red.pngbin0 -> 3945 bytes
-rw-r--r--leptonica/prog/blend-yellow.jpgbin0 -> 17918 bytes
-rw-r--r--leptonica/prog/blend1_reg.c328
-rw-r--r--leptonica/prog/blend2_reg.c182
-rw-r--r--leptonica/prog/blend3_reg.c216
-rw-r--r--leptonica/prog/blend4_reg.c102
-rw-r--r--leptonica/prog/blend5_reg.c182
-rw-r--r--leptonica/prog/blendcmaptest.c112
-rw-r--r--leptonica/prog/blender1.tifbin0 -> 496 bytes
-rw-r--r--leptonica/prog/blender8.pngbin0 -> 1811 bytes
-rw-r--r--leptonica/prog/blendtext.tifbin0 -> 496 bytes
-rw-r--r--leptonica/prog/bois-2.tifbin0 -> 31732 bytes
-rw-r--r--leptonica/prog/bois-3.tifbin0 -> 40290 bytes
-rw-r--r--leptonica/prog/bois-4.tifbin0 -> 48922 bytes
-rw-r--r--leptonica/prog/bois-5.tifbin0 -> 48784 bytes
-rw-r--r--leptonica/prog/books_logo.pngbin0 -> 23078 bytes
-rw-r--r--leptonica/prog/boxa1.ba47
-rw-r--r--leptonica/prog/boxa1_reg.c161
-rw-r--r--leptonica/prog/boxa2.ba379
-rw-r--r--leptonica/prog/boxa2_reg.c196
-rw-r--r--leptonica/prog/boxa3.ba379
-rw-r--r--leptonica/prog/boxa3_reg.c202
-rw-r--r--leptonica/prog/boxa4.ba55
-rw-r--r--leptonica/prog/boxa4_reg.c226
-rw-r--r--leptonica/prog/boxa5.ba21
-rw-r--r--leptonica/prog/boxap1.ba129
-rw-r--r--leptonica/prog/boxap2.ba303
-rw-r--r--leptonica/prog/boxap3.ba15
-rw-r--r--leptonica/prog/boxap4.ba53
-rw-r--r--leptonica/prog/boxap5.ba553
-rw-r--r--leptonica/prog/boxedpage.jpgbin0 -> 61244 bytes
-rw-r--r--leptonica/prog/brev.06.75.jpgbin0 -> 33364 bytes
-rw-r--r--leptonica/prog/brev.10.75.jpgbin0 -> 42274 bytes
-rw-r--r--leptonica/prog/brev.14.75.jpgbin0 -> 37460 bytes
-rw-r--r--leptonica/prog/brev.20.75.jpgbin0 -> 38733 bytes
-rw-r--r--leptonica/prog/brev.36.75.jpgbin0 -> 41245 bytes
-rw-r--r--leptonica/prog/brev.53.75.jpgbin0 -> 28953 bytes
-rw-r--r--leptonica/prog/brev.56.75.jpgbin0 -> 41320 bytes
-rw-r--r--leptonica/prog/breviar.38.150.jpgbin0 -> 146456 bytes
-rw-r--r--leptonica/prog/brothers.150.jpgbin0 -> 81310 bytes
-rw-r--r--leptonica/prog/buffertest.c114
-rw-r--r--leptonica/prog/bytea_reg.c180
-rw-r--r--leptonica/prog/candelabrum.011.jpgbin0 -> 59408 bytes
-rw-r--r--leptonica/prog/cat-and-mouse.pngbin0 -> 15550 bytes
-rw-r--r--leptonica/prog/cat.007.jpgbin0 -> 139783 bytes
-rw-r--r--leptonica/prog/cat.035.jpgbin0 -> 140334 bytes
-rw-r--r--leptonica/prog/cavalerie.11.jpgbin0 -> 240511 bytes
-rw-r--r--leptonica/prog/cavalerie.29.jpgbin0 -> 198691 bytes
-rw-r--r--leptonica/prog/ccbord_reg.c231
-rw-r--r--leptonica/prog/ccbordtest.c246
-rw-r--r--leptonica/prog/cctest1.c125
-rw-r--r--leptonica/prog/ccthin1_reg.c202
-rw-r--r--leptonica/prog/ccthin2_reg.c192
-rw-r--r--leptonica/prog/char.tifbin0 -> 232 bytes
-rw-r--r--leptonica/prog/chars-10.tifbin0 -> 2788 bytes
-rw-r--r--leptonica/prog/chars-12.tifbin0 -> 3250 bytes
-rw-r--r--leptonica/prog/chars-14.tifbin0 -> 3612 bytes
-rw-r--r--leptonica/prog/chars-16.tifbin0 -> 4066 bytes
-rw-r--r--leptonica/prog/chars-18.tifbin0 -> 4530 bytes
-rw-r--r--leptonica/prog/chars-20.tifbin0 -> 5004 bytes
-rw-r--r--leptonica/prog/chars-4.tifbin0 -> 1446 bytes
-rw-r--r--leptonica/prog/chars-6.tifbin0 -> 1860 bytes
-rw-r--r--leptonica/prog/chars-8.tifbin0 -> 2340 bytes
-rw-r--r--leptonica/prog/checkerboard1.tifbin0 -> 1228 bytes
-rw-r--r--leptonica/prog/checkerboard2.tifbin0 -> 3086 bytes
-rw-r--r--leptonica/prog/checkerboard_reg.c94
-rw-r--r--leptonica/prog/church.pngbin0 -> 65442 bytes
-rw-r--r--leptonica/prog/circle_reg.c140
-rw-r--r--leptonica/prog/circles.pabin0 -> 4334 bytes
-rw-r--r--leptonica/prog/cleanpdf.c278
-rw-r--r--leptonica/prog/cmapquant_reg.c136
-rw-r--r--leptonica/prog/coffeebeans.pngbin0 -> 2449 bytes
-rw-r--r--leptonica/prog/color-wheel-hue.jpgbin0 -> 7684 bytes
-rw-r--r--leptonica/prog/colorcontent_reg.c170
-rw-r--r--leptonica/prog/colorfill_reg.c167
-rw-r--r--leptonica/prog/coloring_reg.c158
-rw-r--r--leptonica/prog/colorize_reg.c290
-rw-r--r--leptonica/prog/colormask_reg.c158
-rw-r--r--leptonica/prog/colormorph_reg.c101
-rw-r--r--leptonica/prog/colorpage.030.jpgbin0 -> 57025 bytes
-rw-r--r--leptonica/prog/colorquant_reg.c241
-rw-r--r--leptonica/prog/colorseg.jpgbin0 -> 55238 bytes
-rw-r--r--leptonica/prog/colorseg_reg.c113
-rw-r--r--leptonica/prog/colorsegtest.c109
-rw-r--r--leptonica/prog/colorspace_reg.c208
-rw-r--r--leptonica/prog/comap.063.jpgbin0 -> 34357 bytes
-rw-r--r--leptonica/prog/comap.068.jpgbin0 -> 30426 bytes
-rw-r--r--leptonica/prog/comap.073.jpgbin0 -> 29973 bytes
-rw-r--r--leptonica/prog/comap.100.jpgbin0 -> 38859 bytes
-rw-r--r--leptonica/prog/comap.110.jpgbin0 -> 47121 bytes
-rw-r--r--leptonica/prog/comap.118.jpgbin0 -> 42039 bytes
-rw-r--r--leptonica/prog/compare_reg.c143
-rw-r--r--leptonica/prog/comparepages.c116
-rw-r--r--leptonica/prog/comparepixa.c101
-rw-r--r--leptonica/prog/comparetest.c159
-rw-r--r--leptonica/prog/compfilter_reg.c346
-rw-r--r--leptonica/prog/concatpdf.c177
-rw-r--r--leptonica/prog/conncomp_reg.c163
-rw-r--r--leptonica/prog/contrast-orig-60.jpgbin0 -> 107226 bytes
-rw-r--r--leptonica/prog/contrast1.jpgbin0 -> 23371 bytes
-rw-r--r--leptonica/prog/contrasttest.c94
-rw-r--r--leptonica/prog/conversion_reg.c424
-rw-r--r--leptonica/prog/convertfilestopdf.c109
-rw-r--r--leptonica/prog/convertfilestops.c85
-rw-r--r--leptonica/prog/convertformat.c181
-rw-r--r--leptonica/prog/convertsegfilestopdf.c162
-rw-r--r--leptonica/prog/convertsegfilestops.c137
-rw-r--r--leptonica/prog/converttogray.c123
-rw-r--r--leptonica/prog/converttopdf.c78
-rw-r--r--leptonica/prog/converttops.c68
-rw-r--r--leptonica/prog/convolve_reg.c211
-rw-r--r--leptonica/prog/cootoots.pngbin0 -> 12806 bytes
-rw-r--r--leptonica/prog/copernicus.pngbin0 -> 53027 bytes
-rw-r--r--leptonica/prog/cornertest.c104
-rw-r--r--leptonica/prog/corrupttest.c271
-rw-r--r--leptonica/prog/crop_reg.c320
-rw-r--r--leptonica/prog/croptext.c99
-rw-r--r--leptonica/prog/dave-orig.pngbin0 -> 188112 bytes
-rw-r--r--leptonica/prog/deskew_it.c140
-rw-r--r--leptonica/prog/dewarp_reg.c211
-rw-r--r--leptonica/prog/dewarprules.c176
-rw-r--r--leptonica/prog/dewarptest1.c182
-rw-r--r--leptonica/prog/dewarptest2.c123
-rw-r--r--leptonica/prog/dewarptest3.c167
-rw-r--r--leptonica/prog/dewarptest4.c123
-rw-r--r--leptonica/prog/dewarptest5.c140
-rw-r--r--leptonica/prog/digitprep1.c106
-rw-r--r--leptonica/prog/dinos.pacbin0 -> 244424 bytes
-rw-r--r--leptonica/prog/displayboxa.c91
-rw-r--r--leptonica/prog/displayboxes_on_pixa.c98
-rw-r--r--leptonica/prog/displaypix.c61
-rw-r--r--leptonica/prog/displaypixa.c176
-rw-r--r--leptonica/prog/distance_reg.c158
-rw-r--r--leptonica/prog/dither_reg.c86
-rw-r--r--leptonica/prog/dna_reg.c123
-rw-r--r--leptonica/prog/dreyfus1.pngbin0 -> 10341 bytes
-rw-r--r--leptonica/prog/dreyfus2.pngbin0 -> 17827 bytes
-rw-r--r--leptonica/prog/dreyfus4.pngbin0 -> 22525 bytes
-rw-r--r--leptonica/prog/dreyfus8.pngbin0 -> 34971 bytes
-rw-r--r--leptonica/prog/dwalinear.3.c343
-rw-r--r--leptonica/prog/dwalineargen.c79
-rw-r--r--leptonica/prog/dwalinearlow.3.c16986
-rw-r--r--leptonica/prog/dwamorph1_reg.c244
-rw-r--r--leptonica/prog/dwamorph2_reg.c321
-rw-r--r--leptonica/prog/edge_reg.c90
-rw-r--r--leptonica/prog/encoding_reg.c107
-rw-r--r--leptonica/prog/enhance_reg.c298
-rw-r--r--leptonica/prog/equal_reg.c139
-rw-r--r--leptonica/prog/expand_reg.c165
-rw-r--r--leptonica/prog/extrema_reg.c102
-rw-r--r--leptonica/prog/falsecolor_reg.c93
-rw-r--r--leptonica/prog/fcombautogen.c80
-rw-r--r--leptonica/prog/feyn-fract.tifbin0 -> 11520 bytes
-rw-r--r--leptonica/prog/feyn-fract2.tifbin0 -> 4952 bytes
-rw-r--r--leptonica/prog/feyn-word.tifbin0 -> 426 bytes
-rw-r--r--leptonica/prog/feyn.tifbin0 -> 104796 bytes
-rw-r--r--leptonica/prog/feynman-stamp.jpgbin0 -> 14394 bytes
-rw-r--r--leptonica/prog/fhmtauto_reg.c90
-rw-r--r--leptonica/prog/fhmtautogen.c74
-rw-r--r--leptonica/prog/fileinfo.c52
-rw-r--r--leptonica/prog/files_reg.c290
-rw-r--r--leptonica/prog/find_colorregions.c343
-rw-r--r--leptonica/prog/findbinding.c164
-rw-r--r--leptonica/prog/findcorners_reg.c210
-rw-r--r--leptonica/prog/findpattern1.c145
-rw-r--r--leptonica/prog/findpattern2.c161
-rw-r--r--leptonica/prog/findpattern3.c160
-rw-r--r--leptonica/prog/findpattern_reg.c173
-rw-r--r--leptonica/prog/fish24.jpgbin0 -> 103695 bytes
-rw-r--r--leptonica/prog/flipdetect_reg.c119
-rw-r--r--leptonica/prog/flipselgen.c.notused124
-rw-r--r--leptonica/prog/flipsels.txt35
-rw-r--r--leptonica/prog/fmorphauto_reg.c163
-rw-r--r--leptonica/prog/fmorphautogen.c74
-rw-r--r--leptonica/prog/fonts/chars-10.pabin0 -> 17399 bytes
-rw-r--r--leptonica/prog/fonts/chars-10.ps21
-rw-r--r--leptonica/prog/fonts/chars-10.tifbin0 -> 2858 bytes
-rw-r--r--leptonica/prog/fonts/chars-12.pabin0 -> 18554 bytes
-rw-r--r--leptonica/prog/fonts/chars-12.ps21
-rw-r--r--leptonica/prog/fonts/chars-12.tifbin0 -> 3342 bytes
-rw-r--r--leptonica/prog/fonts/chars-14.pabin0 -> 19414 bytes
-rw-r--r--leptonica/prog/fonts/chars-14.ps21
-rw-r--r--leptonica/prog/fonts/chars-14.tifbin0 -> 3680 bytes
-rw-r--r--leptonica/prog/fonts/chars-16.pabin0 -> 20343 bytes
-rw-r--r--leptonica/prog/fonts/chars-16.ps21
-rw-r--r--leptonica/prog/fonts/chars-16.tifbin0 -> 4142 bytes
-rw-r--r--leptonica/prog/fonts/chars-18.pabin0 -> 21457 bytes
-rw-r--r--leptonica/prog/fonts/chars-18.ps21
-rw-r--r--leptonica/prog/fonts/chars-18.tifbin0 -> 4606 bytes
-rw-r--r--leptonica/prog/fonts/chars-20.pabin0 -> 22376 bytes
-rw-r--r--leptonica/prog/fonts/chars-20.ps21
-rw-r--r--leptonica/prog/fonts/chars-20.tifbin0 -> 5070 bytes
-rw-r--r--leptonica/prog/fonts/chars-4.pabin0 -> 13693 bytes
-rw-r--r--leptonica/prog/fonts/chars-4.ps21
-rw-r--r--leptonica/prog/fonts/chars-4.tifbin0 -> 1508 bytes
-rw-r--r--leptonica/prog/fonts/chars-6.pabin0 -> 14988 bytes
-rw-r--r--leptonica/prog/fonts/chars-6.ps21
-rw-r--r--leptonica/prog/fonts/chars-6.tifbin0 -> 1928 bytes
-rw-r--r--leptonica/prog/fonts/chars-8.pabin0 -> 16217 bytes
-rw-r--r--leptonica/prog/fonts/chars-8.ps21
-rw-r--r--leptonica/prog/fonts/chars-8.tifbin0 -> 2416 bytes
-rw-r--r--leptonica/prog/form1.tifbin0 -> 6074 bytes
-rw-r--r--leptonica/prog/form2.tifbin0 -> 5116 bytes
-rw-r--r--leptonica/prog/fpix1_reg.c364
-rw-r--r--leptonica/prog/fpix2_reg.c116
-rw-r--r--leptonica/prog/fpixcontours.c76
-rw-r--r--leptonica/prog/fuzzing/README.md25
-rw-r--r--leptonica/prog/fuzzing/adaptmap_fuzzer.cc75
-rw-r--r--leptonica/prog/fuzzing/affine_fuzzer.cc40
-rw-r--r--leptonica/prog/fuzzing/barcode_fuzzer.cc22
-rw-r--r--leptonica/prog/fuzzing/barcode_fuzzer_seed_corpus.zipbin0 -> 51247 bytes
-rw-r--r--leptonica/prog/fuzzing/baseline_fuzzer.cc24
-rw-r--r--leptonica/prog/fuzzing/bilateral_fuzzer.cc25
-rw-r--r--leptonica/prog/fuzzing/bilinear_fuzzer.cc37
-rw-r--r--leptonica/prog/fuzzing/binarize_fuzzer.cc55
-rw-r--r--leptonica/prog/fuzzing/blend_fuzzer.cc93
-rw-r--r--leptonica/prog/fuzzing/boxfunc3_fuzzer.cc107
-rw-r--r--leptonica/prog/fuzzing/boxfunc4_fuzzer.cc39
-rw-r--r--leptonica/prog/fuzzing/boxfunc5_fuzzer.cc51
-rw-r--r--leptonica/prog/fuzzing/boxfunc_fuzzer.cc23
-rw-r--r--leptonica/prog/fuzzing/ccbord_fuzzer.cc27
-rw-r--r--leptonica/prog/fuzzing/ccthin_fuzzer.cc28
-rw-r--r--leptonica/prog/fuzzing/checkerboard_fuzzer.cc25
-rw-r--r--leptonica/prog/fuzzing/classapp_fuzzer.cc24
-rw-r--r--leptonica/prog/fuzzing/colorfill_fuzzer.cc17
-rw-r--r--leptonica/prog/fuzzing/colorquant_fuzzer.cc83
-rw-r--r--leptonica/prog/fuzzing/compare_fuzzer.cc49
-rw-r--r--leptonica/prog/fuzzing/dewarp_fuzzer.cc29
-rw-r--r--leptonica/prog/fuzzing/edge_fuzzer.cc18
-rw-r--r--leptonica/prog/fuzzing/enhance_fuzzer.cc101
-rw-r--r--leptonica/prog/fuzzing/fhmtgen_fuzzer.cc33
-rw-r--r--leptonica/prog/fuzzing/finditalic_fuzzer.cc18
-rw-r--r--leptonica/prog/fuzzing/flipdetect_fuzzer.cc31
-rw-r--r--leptonica/prog/fuzzing/fpix2_fuzzer.cc111
-rw-r--r--leptonica/prog/fuzzing/general_corpus.zipbin0 -> 99986 bytes
-rw-r--r--leptonica/prog/fuzzing/graphics_fuzzer.cc81
-rw-r--r--leptonica/prog/fuzzing/graymorph_fuzzer.cc36
-rw-r--r--leptonica/prog/fuzzing/grayquant_fuzzer.cc47
-rw-r--r--leptonica/prog/fuzzing/jpegiostub_fuzzer.cc15
-rw-r--r--leptonica/prog/fuzzing/kernel_fuzzer.cc16
-rw-r--r--leptonica/prog/fuzzing/leptfuzz.h16
-rw-r--r--leptonica/prog/fuzzing/mask_fuzzer.cc42
-rw-r--r--leptonica/prog/fuzzing/maze_fuzzer.cc24
-rw-r--r--leptonica/prog/fuzzing/morph_fuzzer.cc48
-rw-r--r--leptonica/prog/fuzzing/morphapp_fuzzer.cc65
-rwxr-xr-xleptonica/prog/fuzzing/oss-fuzz-build.sh128
-rw-r--r--leptonica/prog/fuzzing/pageseg_fuzzer.cc42
-rw-r--r--leptonica/prog/fuzzing/paintcmap_fuzzer.cc27
-rw-r--r--leptonica/prog/fuzzing/pix1_fuzzer.cc19
-rw-r--r--leptonica/prog/fuzzing/pix3_fuzzer.cc133
-rw-r--r--leptonica/prog/fuzzing/pix4_fuzzer.cc109
-rw-r--r--leptonica/prog/fuzzing/pixMirrorDetectDwa_fuzzer.cc20
-rw-r--r--leptonica/prog/fuzzing/pix_orient_fuzzer.cc19
-rw-r--r--leptonica/prog/fuzzing/pix_rotate_shear_fuzzer.cc67
-rw-r--r--leptonica/prog/fuzzing/pixa_recog_fuzzer.cc49
-rw-r--r--leptonica/prog/fuzzing/pixa_recog_fuzzer_seed_corpus.zipbin0 -> 43179 bytes
-rw-r--r--leptonica/prog/fuzzing/pixconv_fuzzer.cc23
-rw-r--r--leptonica/prog/fuzzing/recog_basic_fuzzer.cc25
-rw-r--r--leptonica/prog/gammatest.c98
-rw-r--r--leptonica/prog/genfonts_reg.c173
-rw-r--r--leptonica/prog/german.pngbin0 -> 46306 bytes
-rw-r--r--leptonica/prog/gifio_reg.c232
-rw-r--r--leptonica/prog/google-searchbox.pngbin0 -> 3456 bytes
-rw-r--r--leptonica/prog/gplotdata.example82
-rw-r--r--leptonica/prog/graphicstest.c100
-rw-r--r--leptonica/prog/gray-alpha.tifbin0 -> 410 bytes
-rw-r--r--leptonica/prog/grayfill_reg.c207
-rw-r--r--leptonica/prog/graymorph1_reg.c332
-rw-r--r--leptonica/prog/graymorph2_reg.c153
-rw-r--r--leptonica/prog/graymorphtest.c103
-rw-r--r--leptonica/prog/grayquant_reg.c398
-rw-r--r--leptonica/prog/graytext.pngbin0 -> 4071 bytes
-rw-r--r--leptonica/prog/greencover.jpgbin0 -> 21727 bytes
-rw-r--r--leptonica/prog/hardlight1_1.jpgbin0 -> 2932 bytes
-rw-r--r--leptonica/prog/hardlight1_2.jpgbin0 -> 1731 bytes
-rw-r--r--leptonica/prog/hardlight2_1.jpgbin0 -> 2967 bytes
-rw-r--r--leptonica/prog/hardlight2_2.jpgbin0 -> 3475 bytes
-rw-r--r--leptonica/prog/hardlight_reg.c140
-rw-r--r--leptonica/prog/harmoniam-11.tifbin0 -> 35522 bytes
-rw-r--r--leptonica/prog/harmoniam100-11.pngbin0 -> 72398 bytes
-rw-r--r--leptonica/prog/hash_reg.c471
-rw-r--r--leptonica/prog/heap_reg.c155
-rw-r--r--leptonica/prog/histoduptest.c267
-rw-r--r--leptonica/prog/histotest.c102
-rw-r--r--leptonica/prog/hmttemplate1.txt170
-rw-r--r--leptonica/prog/hmttemplate2.txt103
-rw-r--r--leptonica/prog/hole-filler.pngbin0 -> 30776 bytes
-rw-r--r--leptonica/prog/htmlviewer.c286
-rw-r--r--leptonica/prog/imagetops.c101
-rw-r--r--leptonica/prog/insert_reg.c163
-rw-r--r--leptonica/prog/invertedtext.tifbin0 -> 694 bytes
-rw-r--r--leptonica/prog/ioformats_reg.c921
-rw-r--r--leptonica/prog/iomisc_reg.c300
-rw-r--r--leptonica/prog/italic.pngbin0 -> 20761 bytes
-rw-r--r--leptonica/prog/italic_reg.c116
-rw-r--r--leptonica/prog/jbclass_reg.c211
-rw-r--r--leptonica/prog/jbcorrelation.c226
-rw-r--r--leptonica/prog/jbrankhaus.c224
-rw-r--r--leptonica/prog/jbwords.c135
-rw-r--r--leptonica/prog/jp2kio_reg.c184
-rw-r--r--leptonica/prog/jpeg-coded.tifbin0 -> 7064 bytes
-rw-r--r--leptonica/prog/jpegio_reg.c265
-rw-r--r--leptonica/prog/juditharismax.jpgbin0 -> 149756 bytes
-rw-r--r--leptonica/prog/karen8.jpgbin0 -> 15966 bytes
-rw-r--r--leptonica/prog/kernel_reg.c356
-rw-r--r--leptonica/prog/keystone.pngbin0 -> 39141 bytes
-rw-r--r--leptonica/prog/label_reg.c220
-rw-r--r--leptonica/prog/lapide.052.100.jpgbin0 -> 289835 bytes
-rw-r--r--leptonica/prog/leptonica-license.txt26
-rw-r--r--leptonica/prog/lightcolortest.c128
-rw-r--r--leptonica/prog/lighttext.jpgbin0 -> 82345 bytes
-rw-r--r--leptonica/prog/lineremoval_reg.c124
-rw-r--r--leptonica/prog/lion-mask.00010.tifbin0 -> 422 bytes
-rw-r--r--leptonica/prog/lion-mask.00016.tifbin0 -> 410 bytes
-rw-r--r--leptonica/prog/lion-page.00010.jpgbin0 -> 53313 bytes
-rw-r--r--leptonica/prog/lion-page.00011.pngbin0 -> 18202 bytes
-rw-r--r--leptonica/prog/lion-page.00012.pngbin0 -> 3489 bytes
-rw-r--r--leptonica/prog/lion-page.00013.pngbin0 -> 15806 bytes
-rw-r--r--leptonica/prog/lion-page.00016.jpgbin0 -> 49650 bytes
-rw-r--r--leptonica/prog/lion-page.00017.pngbin0 -> 19845 bytes
-rw-r--r--leptonica/prog/listtest.c279
-rw-r--r--leptonica/prog/livre_adapt.c105
-rw-r--r--leptonica/prog/livre_hmt.c151
-rw-r--r--leptonica/prog/livre_makefigs.c107
-rw-r--r--leptonica/prog/livre_orient.c94
-rw-r--r--leptonica/prog/livre_pageseg.c311
-rw-r--r--leptonica/prog/livre_seedgen.c75
-rw-r--r--leptonica/prog/livre_tophat.c75
-rw-r--r--leptonica/prog/locminmax_reg.c102
-rw-r--r--leptonica/prog/logicops_reg.c178
-rw-r--r--leptonica/prog/lowaccess_reg.c304
-rw-r--r--leptonica/prog/lowsat_reg.c107
-rw-r--r--leptonica/prog/lucasta-frag.jpgbin0 -> 54841 bytes
-rw-r--r--leptonica/prog/lucasta.047.jpgbin0 -> 240757 bytes
-rw-r--r--leptonica/prog/lucasta.1.300.tifbin0 -> 28952 bytes
-rw-r--r--leptonica/prog/lucasta.150.jpgbin0 -> 103707 bytes
-rw-r--r--leptonica/prog/lyra.005.jpgbin0 -> 103429 bytes
-rw-r--r--leptonica/prog/lyra.036.jpgbin0 -> 122737 bytes
-rw-r--r--leptonica/prog/lyra.5.na725
-rw-r--r--leptonica/prog/makefile.static1236
-rw-r--r--leptonica/prog/maketile.c118
-rw-r--r--leptonica/prog/map.057.jpgbin0 -> 45042 bytes
-rw-r--r--leptonica/prog/map1.jpgbin0 -> 118180 bytes
-rw-r--r--leptonica/prog/maptest.c426
-rw-r--r--leptonica/prog/marge.jpgbin0 -> 33094 bytes
-rw-r--r--leptonica/prog/maze_reg.c110
-rw-r--r--leptonica/prog/messagetest.c181
-rw-r--r--leptonica/prog/minisblack.tifbin0 -> 746 bytes
-rw-r--r--leptonica/prog/miniswhite.tifbin0 -> 742 bytes
-rw-r--r--leptonica/prog/misctest1.c331
-rw-r--r--leptonica/prog/modifyhuesat.c107
-rw-r--r--leptonica/prog/morphseq_reg.c121
-rw-r--r--leptonica/prog/morphtemplate1.txt224
-rw-r--r--leptonica/prog/morphtemplate2.txt104
-rw-r--r--leptonica/prog/morphtest1.c140
-rw-r--r--leptonica/prog/mtiff_reg.c378
-rw-r--r--leptonica/prog/multitype_reg.c483
-rw-r--r--leptonica/prog/nearline_reg.c189
-rw-r--r--leptonica/prog/newspaper_reg.c171
-rw-r--r--leptonica/prog/numa1_reg.c321
-rw-r--r--leptonica/prog/numa2_reg.c490
-rw-r--r--leptonica/prog/numa3_reg.c215
-rw-r--r--leptonica/prog/numaranktest.c97
-rw-r--r--leptonica/prog/ortiz-02.tifbin0 -> 59428 bytes
-rw-r--r--leptonica/prog/ortiz-03.tifbin0 -> 68303 bytes
-rw-r--r--leptonica/prog/ortiz-04.tifbin0 -> 67339 bytes
-rw-r--r--leptonica/prog/ortiz-05.tifbin0 -> 69301 bytes
-rw-r--r--leptonica/prog/otsutest1.c161
-rw-r--r--leptonica/prog/otsutest2.c129
-rw-r--r--leptonica/prog/overlap_reg.c261
-rw-r--r--leptonica/prog/pageseg1.tifbin0 -> 133362 bytes
-rw-r--r--leptonica/prog/pageseg2-mask.pngbin0 -> 36764 bytes
-rw-r--r--leptonica/prog/pageseg2-seed.pngbin0 -> 2352 bytes
-rw-r--r--leptonica/prog/pageseg2.tifbin0 -> 258864 bytes
-rw-r--r--leptonica/prog/pageseg3.tifbin0 -> 122112 bytes
-rw-r--r--leptonica/prog/pageseg4.tifbin0 -> 114878 bytes
-rw-r--r--leptonica/prog/pageseg_reg.c237
-rw-r--r--leptonica/prog/pagesegtest1.c71
-rw-r--r--leptonica/prog/pagesegtest2.c131
-rw-r--r--leptonica/prog/paint_reg.c364
-rw-r--r--leptonica/prog/paintmask_reg.c215
-rw-r--r--leptonica/prog/pancrazi.15.jpgbin0 -> 91677 bytes
-rw-r--r--leptonica/prog/partifytest.c53
-rw-r--r--leptonica/prog/partitiontest.c177
-rw-r--r--leptonica/prog/patent.pngbin0 -> 75966 bytes
-rw-r--r--leptonica/prog/pdf2jpeg58
-rwxr-xr-xleptonica/prog/pdf2mtiff51
-rw-r--r--leptonica/prog/pdf2png46
-rw-r--r--leptonica/prog/pdf2png-binary38
-rw-r--r--leptonica/prog/pdf2png-color46
-rw-r--r--leptonica/prog/pdf2png-gray46
-rw-r--r--leptonica/prog/pdf2tiff47
-rw-r--r--leptonica/prog/pdfio1_reg.c318
-rw-r--r--leptonica/prog/pdfio2_reg.c376
-rw-r--r--leptonica/prog/pdfseg_reg.c183
-rw-r--r--leptonica/prog/pedante.079.jpgbin0 -> 70343 bytes
-rw-r--r--leptonica/prog/percolate-4cc.pngbin0 -> 5844 bytes
-rw-r--r--leptonica/prog/percolate-8cc.pngbin0 -> 5571 bytes
-rw-r--r--leptonica/prog/percolatetest.c322
-rw-r--r--leptonica/prog/pixa1_reg.c170
-rw-r--r--leptonica/prog/pixa2_reg.c121
-rw-r--r--leptonica/prog/pixaatest.c109
-rw-r--r--leptonica/prog/pixadisp_reg.c166
-rw-r--r--leptonica/prog/pixafileinfo.c82
-rw-r--r--leptonica/prog/pixalloc_reg.c208
-rw-r--r--leptonica/prog/pixcomp_reg.c236
-rw-r--r--leptonica/prog/pixmem_reg.c152
-rw-r--r--leptonica/prog/pixserial_reg.c142
-rw-r--r--leptonica/prog/pixtile_reg.c105
-rw-r--r--leptonica/prog/plottest.c156
-rw-r--r--leptonica/prog/pngio_reg.c477
-rw-r--r--leptonica/prog/pnmio_reg.c183
-rw-r--r--leptonica/prog/printimage.c158
-rw-r--r--leptonica/prog/printsplitimage.c150
-rw-r--r--leptonica/prog/printtiff.c98
-rw-r--r--leptonica/prog/projection_reg.c155
-rw-r--r--leptonica/prog/projectionstats.jpgbin0 -> 3315 bytes
-rw-r--r--leptonica/prog/projective_reg.c234
-rw-r--r--leptonica/prog/ps2jpeg32
-rw-r--r--leptonica/prog/ps2png43
-rw-r--r--leptonica/prog/ps2png-binary35
-rw-r--r--leptonica/prog/ps2png-color33
-rw-r--r--leptonica/prog/ps2png-gray33
-rw-r--r--leptonica/prog/ps2tiff42
-rw-r--r--leptonica/prog/psio_reg.c250
-rw-r--r--leptonica/prog/psioseg_reg.c174
-rw-r--r--leptonica/prog/pta_reg.c228
-rw-r--r--leptonica/prog/ptra1_reg.c488
-rw-r--r--leptonica/prog/ptra2_reg.c266
-rw-r--r--leptonica/prog/quadtree_reg.c141
-rw-r--r--leptonica/prog/rabi-tiny.pngbin0 -> 2408 bytes
-rw-r--r--leptonica/prog/rabi.pngbin0 -> 232718 bytes
-rw-r--r--leptonica/prog/raggededge.pngbin0 -> 452 bytes
-rw-r--r--leptonica/prog/rank_reg.c226
-rw-r--r--leptonica/prog/rankbin_reg.c204
-rw-r--r--leptonica/prog/rankhisto_reg.c135
-rw-r--r--leptonica/prog/rasterop_reg.c103
-rw-r--r--leptonica/prog/rasteropip_reg.c81
-rw-r--r--leptonica/prog/rasteroptest.c143
-rw-r--r--leptonica/prog/rbtreetest.c111
-rw-r--r--leptonica/prog/recog/digits/bootnum1.pabin0 -> 25134 bytes
-rw-r--r--leptonica/prog/recog/digits/bootnum2.pabin0 -> 24608 bytes
-rw-r--r--leptonica/prog/recog/digits/bootnum3.pabin0 -> 31903 bytes
-rw-r--r--leptonica/prog/recog/digits/bootnum4.pabin0 -> 39338 bytes
-rw-r--r--leptonica/prog/recog/digits/digit0.comp.tifbin0 -> 6354 bytes
-rw-r--r--leptonica/prog/recog/digits/digit1.comp.tifbin0 -> 4266 bytes
-rw-r--r--leptonica/prog/recog/digits/digit2.comp.tifbin0 -> 7370 bytes
-rw-r--r--leptonica/prog/recog/digits/digit3.comp.tifbin0 -> 7638 bytes
-rw-r--r--leptonica/prog/recog/digits/digit4.comp.tifbin0 -> 6154 bytes
-rw-r--r--leptonica/prog/recog/digits/digit5.comp.tifbin0 -> 7240 bytes
-rw-r--r--leptonica/prog/recog/digits/digit5.orig-25.pabin0 -> 13207 bytes
-rw-r--r--leptonica/prog/recog/digits/digit6.comp.tifbin0 -> 7748 bytes
-rw-r--r--leptonica/prog/recog/digits/digit7.comp.tifbin0 -> 5354 bytes
-rw-r--r--leptonica/prog/recog/digits/digit8.comp.tifbin0 -> 8310 bytes
-rw-r--r--leptonica/prog/recog/digits/digit9.comp.tifbin0 -> 7840 bytes
-rw-r--r--leptonica/prog/recog/digits/digit_set01.pabin0 -> 31628 bytes
-rw-r--r--leptonica/prog/recog/digits/digit_set02.pabin0 -> 27769 bytes
-rw-r--r--leptonica/prog/recog/digits/digit_set03.pabin0 -> 30837 bytes
-rw-r--r--leptonica/prog/recog/digits/digit_set04.pabin0 -> 30919 bytes
-rw-r--r--leptonica/prog/recog/digits/digit_set05.pabin0 -> 31727 bytes
-rw-r--r--leptonica/prog/recog/digits/digit_set06.pabin0 -> 31833 bytes
-rw-r--r--leptonica/prog/recog/digits/digit_set07.pabin0 -> 30147 bytes
-rw-r--r--leptonica/prog/recog/digits/digit_set08.pabin0 -> 31465 bytes
-rw-r--r--leptonica/prog/recog/digits/digit_set09.pabin0 -> 31646 bytes
-rw-r--r--leptonica/prog/recog/digits/digit_set10.pabin0 -> 31606 bytes
-rw-r--r--leptonica/prog/recog/digits/digit_set11.pabin0 -> 30785 bytes
-rw-r--r--leptonica/prog/recog/digits/digit_set12.pabin0 -> 28035 bytes
-rw-r--r--leptonica/prog/recog/digits/digit_set13.pabin0 -> 29991 bytes
-rw-r--r--leptonica/prog/recog/digits/digit_set14.pabin0 -> 22769 bytes
-rw-r--r--leptonica/prog/recog/digits/digit_set15.pabin0 -> 9339 bytes
-rw-r--r--leptonica/prog/recog/digits/page.306.pngbin0 -> 1673 bytes
-rw-r--r--leptonica/prog/recog/digits/page.590.pngbin0 -> 4181 bytes
-rw-r--r--leptonica/prog/recog/sets/samples06.pngbin0 -> 17243 bytes
-rw-r--r--leptonica/prog/recog/sets/test01.pabin0 -> 176457 bytes
-rw-r--r--leptonica/prog/recog/sets/test02.pabin0 -> 162495 bytes
-rw-r--r--leptonica/prog/recog/sets/test03.pabin0 -> 11701 bytes
-rw-r--r--leptonica/prog/recog/sets/test05.pabin0 -> 100922 bytes
-rw-r--r--leptonica/prog/recog/sets/test06.pabin0 -> 82665 bytes
-rw-r--r--leptonica/prog/recog/sets/train01.pabin0 -> 7199 bytes
-rw-r--r--leptonica/prog/recog/sets/train02.pabin0 -> 25789 bytes
-rw-r--r--leptonica/prog/recog/sets/train03.pabin0 -> 30837 bytes
-rw-r--r--leptonica/prog/recog/sets/train04.pabin0 -> 41903 bytes
-rw-r--r--leptonica/prog/recog/sets/train05.pabin0 -> 30785 bytes
-rw-r--r--leptonica/prog/recog/sets/train06.pabin0 -> 31423 bytes
-rw-r--r--leptonica/prog/recog_bootnum1.c320
-rw-r--r--leptonica/prog/recog_bootnum2.c183
-rw-r--r--leptonica/prog/recog_bootnum3.c90
-rw-r--r--leptonica/prog/recogsort.c124
-rw-r--r--leptonica/prog/recogtest1.c176
-rw-r--r--leptonica/prog/recogtest2.c193
-rw-r--r--leptonica/prog/recogtest3.c182
-rw-r--r--leptonica/prog/recogtest4.c131
-rw-r--r--leptonica/prog/recogtest5.c115
-rw-r--r--leptonica/prog/recogtest6.c134
-rw-r--r--leptonica/prog/recogtest7.c144
-rw-r--r--leptonica/prog/rectangle_reg.c182
-rw-r--r--leptonica/prog/redcover.jpgbin0 -> 21690 bytes
-rw-r--r--leptonica/prog/reducetest.c75
-rwxr-xr-xleptonica/prog/reg_wrapper.sh48
-rw-r--r--leptonica/prog/removecmap.c80
-rw-r--r--leptonica/prog/renderfonts.c103
-rw-r--r--leptonica/prog/replacebytes.c82
-rw-r--r--leptonica/prog/rgb16.tifbin0 -> 64396 bytes
-rw-r--r--leptonica/prog/rock.pngbin0 -> 84115 bytes
-rw-r--r--leptonica/prog/rotate1_reg.c195
-rw-r--r--leptonica/prog/rotate2_reg.c175
-rw-r--r--leptonica/prog/rotate_it.c113
-rw-r--r--leptonica/prog/rotatefastalt.c351
-rw-r--r--leptonica/prog/rotateorth_reg.c146
-rw-r--r--leptonica/prog/rotateorthtest1.c145
-rw-r--r--leptonica/prog/rotatetest1.c224
-rw-r--r--leptonica/prog/runlengthtest.c106
-rw-r--r--leptonica/prog/scale_it.c143
-rw-r--r--leptonica/prog/scale_reg.c307
-rw-r--r--leptonica/prog/scaleandtile.c103
-rw-r--r--leptonica/prog/scaletest1.c92
-rw-r--r--leptonica/prog/scaletest2.c363
-rw-r--r--leptonica/prog/scots-frag.tifbin0 -> 210976 bytes
-rw-r--r--leptonica/prog/seedfilltest.c170
-rw-r--r--leptonica/prog/seedspread_reg.c160
-rw-r--r--leptonica/prog/selio_reg.c133
-rw-r--r--leptonica/prog/settest.c146
-rw-r--r--leptonica/prog/sevens.tifbin0 -> 742 bytes
-rw-r--r--leptonica/prog/sharptest.c70
-rw-r--r--leptonica/prog/shear1_reg.c283
-rw-r--r--leptonica/prog/shear2_reg.c185
-rw-r--r--leptonica/prog/shearer.148.tifbin0 -> 81910 bytes
-rw-r--r--leptonica/prog/sheartest.c169
-rw-r--r--leptonica/prog/showboxes.pacbin0 -> 153286 bytes
-rw-r--r--leptonica/prog/showboxes1.baa27
-rw-r--r--leptonica/prog/showboxes2.baa51
-rw-r--r--leptonica/prog/showedges.c71
-rw-r--r--leptonica/prog/singlecc.tifbin0 -> 398 bytes
-rw-r--r--leptonica/prog/skew_reg.c132
-rw-r--r--leptonica/prog/skewtest.c192
-rw-r--r--leptonica/prog/smallpix_reg.c231
-rw-r--r--leptonica/prog/smoothedge_reg.c100
-rw-r--r--leptonica/prog/sorttest.c100
-rw-r--r--leptonica/prog/speckle.pngbin0 -> 358 bytes
-rw-r--r--leptonica/prog/speckle2.pngbin0 -> 482 bytes
-rw-r--r--leptonica/prog/speckle4.pngbin0 -> 1319 bytes
-rw-r--r--leptonica/prog/speckle_reg.c119
-rw-r--r--leptonica/prog/splitcomp_reg.c158
-rw-r--r--leptonica/prog/splitimage2pdf.c71
-rw-r--r--leptonica/prog/stampede2.jpgbin0 -> 75390 bytes
-rw-r--r--leptonica/prog/string_reg.c229
-rw-r--r--leptonica/prog/stringtemplate1.txt96
-rw-r--r--leptonica/prog/stringtemplate2.txt61
-rw-r--r--leptonica/prog/subpixel_reg.c209
-rw-r--r--leptonica/prog/sudoku1.dat12
-rw-r--r--leptonica/prog/sudoku2.dat11
-rw-r--r--leptonica/prog/sudoku3.dat14
-rw-r--r--leptonica/prog/sudoku4.dat13
-rw-r--r--leptonica/prog/sudoku5.dat14
-rw-r--r--leptonica/prog/sudoku6.dat11
-rw-r--r--leptonica/prog/sudoku7.dat11
-rw-r--r--leptonica/prog/sudokutest.c93
-rw-r--r--leptonica/prog/table.15.tifbin0 -> 24694 bytes
-rw-r--r--leptonica/prog/table.150.pngbin0 -> 18003 bytes
-rw-r--r--leptonica/prog/table.27.tifbin0 -> 25888 bytes
-rw-r--r--leptonica/prog/test-1bit-alpha.pngbin0 -> 16598 bytes
-rw-r--r--leptonica/prog/test-87220.59.pngbin0 -> 7039 bytes
-rw-r--r--leptonica/prog/test-cmap-alpha.pngbin0 -> 830 bytes
-rw-r--r--leptonica/prog/test-cmap-alpha2.pngbin0 -> 557 bytes
-rw-r--r--leptonica/prog/test-fulltrans-alpha.pngbin0 -> 260 bytes
-rw-r--r--leptonica/prog/test-gray-alpha.pngbin0 -> 561 bytes
-rw-r--r--leptonica/prog/test1.bmpbin0 -> 30734 bytes
-rw-r--r--leptonica/prog/test1.pngbin0 -> 14824 bytes
-rw-r--r--leptonica/prog/test16.pngbin0 -> 25630 bytes
-rw-r--r--leptonica/prog/test16.tifbin0 -> 23570 bytes
-rw-r--r--leptonica/prog/test24.jpgbin0 -> 248613 bytes
-rw-r--r--leptonica/prog/test32-alpha.pngbin0 -> 1284 bytes
-rw-r--r--leptonica/prog/test8.jpgbin0 -> 55081 bytes
-rw-r--r--leptonica/prog/testangle.na19
-rw-r--r--leptonica/prog/testbuffer.tifbin0 -> 14570 bytes
-rw-r--r--leptonica/prog/testfile1.pdfbin0 -> 1735 bytes
-rw-r--r--leptonica/prog/testfile2.pdfbin0 -> 2396 bytes
-rw-r--r--leptonica/prog/testscore.na19
-rw-r--r--leptonica/prog/tetons.jpgbin0 -> 30174 bytes
-rw-r--r--leptonica/prog/textorient.c95
-rw-r--r--leptonica/prog/texturefill_reg.c194
-rw-r--r--leptonica/prog/threshnorm_reg.c105
-rw-r--r--leptonica/prog/tickets.tifbin0 -> 138180 bytes
-rw-r--r--leptonica/prog/tiffpdftest.c142
-rw-r--r--leptonica/prog/toc.99.tifbin0 -> 7776 bytes
-rw-r--r--leptonica/prog/topotest.pngbin0 -> 22899 bytes
-rw-r--r--leptonica/prog/translate_reg.c163
-rw-r--r--leptonica/prog/trctest.c66
-rw-r--r--leptonica/prog/tribune-page-4x.pngbin0 -> 84393 bytes
-rw-r--r--leptonica/prog/tribune-t.pngbin0 -> 1793 bytes
-rw-r--r--leptonica/prog/tribune-word.pngbin0 -> 7015 bytes
-rw-r--r--leptonica/prog/turingtest.pngbin0 -> 13930 bytes
-rw-r--r--leptonica/prog/two-peak-histo.na260
-rw-r--r--leptonica/prog/underline1.jpgbin0 -> 33885 bytes
-rw-r--r--leptonica/prog/underline2.jpgbin0 -> 27295 bytes
-rw-r--r--leptonica/prog/underline3.jpgbin0 -> 31659 bytes
-rw-r--r--leptonica/prog/underline4.jpgbin0 -> 25106 bytes
-rw-r--r--leptonica/prog/underline5.jpgbin0 -> 18646 bytes
-rw-r--r--leptonica/prog/underline6.jpgbin0 -> 21221 bytes
-rw-r--r--leptonica/prog/underline7.jpgbin0 -> 33031 bytes
-rw-r--r--leptonica/prog/underlinetest.c95
-rw-r--r--leptonica/prog/w91frag.jpgbin0 -> 137531 bytes
-rw-r--r--leptonica/prog/warped_paper.jpgbin0 -> 84631 bytes
-rw-r--r--leptonica/prog/warped_sudoku.jpgbin0 -> 49133 bytes
-rw-r--r--leptonica/prog/warper_reg.c138
-rw-r--r--leptonica/prog/warpertest.c256
-rw-r--r--leptonica/prog/watershed_reg.c157
-rw-r--r--leptonica/prog/weasel-113c.pngbin0 -> 2470 bytes
-rw-r--r--leptonica/prog/weasel-44c.pngbin0 -> 1540 bytes
-rw-r--r--leptonica/prog/weasel-4c.2.pngbin0 -> 571 bytes
-rw-r--r--leptonica/prog/weasel-64g.pngbin0 -> 2387 bytes
-rw-r--r--leptonica/prog/weasel-8g.pngbin0 -> 1066 bytes
-rw-r--r--leptonica/prog/weasel2.4c.bmpbin0 -> 3414 bytes
-rw-r--r--leptonica/prog/weasel2.4c.pngbin0 -> 965 bytes
-rw-r--r--leptonica/prog/weasel2.4g.pngbin0 -> 744 bytes
-rw-r--r--leptonica/prog/weasel2.pngbin0 -> 720 bytes
-rw-r--r--leptonica/prog/weasel32.pngbin0 -> 3383 bytes
-rw-r--r--leptonica/prog/weasel4.11c.pngbin0 -> 985 bytes
-rw-r--r--leptonica/prog/weasel4.16c.pngbin0 -> 1559 bytes
-rw-r--r--leptonica/prog/weasel4.16g.pngbin0 -> 1524 bytes
-rw-r--r--leptonica/prog/weasel4.5g.pngbin0 -> 852 bytes
-rw-r--r--leptonica/prog/weasel4.8g.pngbin0 -> 1028 bytes
-rw-r--r--leptonica/prog/weasel4.pngbin0 -> 1461 bytes
-rw-r--r--leptonica/prog/weasel8.149g.pngbin0 -> 3117 bytes
-rw-r--r--leptonica/prog/weasel8.16g.nocmap.pngbin0 -> 1601 bytes
-rw-r--r--leptonica/prog/weasel8.16g.pngbin0 -> 1539 bytes
-rw-r--r--leptonica/prog/weasel8.240c.pngbin0 -> 3628 bytes
-rw-r--r--leptonica/prog/weasel8.5g.nocmap.pngbin0 -> 1083 bytes
-rw-r--r--leptonica/prog/weasel8.5g.pngbin0 -> 927 bytes
-rw-r--r--leptonica/prog/weasel8.pngbin0 -> 1593 bytes
-rw-r--r--leptonica/prog/webpanimio_reg.c96
-rw-r--r--leptonica/prog/webpio_reg.c147
-rw-r--r--leptonica/prog/wet-day.jpgbin0 -> 192734 bytes
-rw-r--r--leptonica/prog/witten.tifbin0 -> 108326 bytes
-rw-r--r--leptonica/prog/wordboxes_reg.c288
-rw-r--r--leptonica/prog/words.15.tifbin0 -> 14630 bytes
-rw-r--r--leptonica/prog/words.44.tifbin0 -> 19040 bytes
-rw-r--r--leptonica/prog/wordsinorder.c145
-rw-r--r--leptonica/prog/writemtiff.c61
-rw-r--r--leptonica/prog/writetext_reg.c177
-rw-r--r--leptonica/prog/wyom.jpgbin0 -> 122842 bytes
-rw-r--r--leptonica/prog/xformbox_reg.c325
-rw-r--r--leptonica/prog/xtractprotos.c263
-rw-r--r--leptonica/prog/yuvtest.c221
-rw-r--r--leptonica/prog/zanotti-78.jpgbin0 -> 154657 bytes
-rw-r--r--leptonica/prog/zier.jpgbin0 -> 25502 bytes
701 files changed, 80567 insertions, 0 deletions
diff --git a/leptonica/prog/1555.003.jpg b/leptonica/prog/1555.003.jpg
new file mode 100644
index 00000000..e35fa013
--- /dev/null
+++ b/leptonica/prog/1555.003.jpg
Binary files differ
diff --git a/leptonica/prog/1555.007.jpg b/leptonica/prog/1555.007.jpg
new file mode 100644
index 00000000..c00c18b8
--- /dev/null
+++ b/leptonica/prog/1555.007.jpg
Binary files differ
diff --git a/leptonica/prog/19-colors.png b/leptonica/prog/19-colors.png
new file mode 100644
index 00000000..5555d569
--- /dev/null
+++ b/leptonica/prog/19-colors.png
Binary files differ
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
new file mode 100644
index 00000000..676f46f1
--- /dev/null
+++ b/leptonica/prog/Leptonica.jpg
Binary files differ
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
new file mode 100644
index 00000000..0e251068
--- /dev/null
+++ b/leptonica/prog/amoris.2.150.jpg
Binary files differ
diff --git a/leptonica/prog/aneurisms8.jpg b/leptonica/prog/aneurisms8.jpg
new file mode 100644
index 00000000..97432588
--- /dev/null
+++ b/leptonica/prog/aneurisms8.jpg
Binary files differ
diff --git a/leptonica/prog/arabic.png b/leptonica/prog/arabic.png
new file mode 100644
index 00000000..2cd43f35
--- /dev/null
+++ b/leptonica/prog/arabic.png
Binary files differ
diff --git a/leptonica/prog/arabic2.png b/leptonica/prog/arabic2.png
new file mode 100644
index 00000000..80180539
--- /dev/null
+++ b/leptonica/prog/arabic2.png
Binary files differ
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
new file mode 100644
index 00000000..a3548236
--- /dev/null
+++ b/leptonica/prog/barcode-128-300.png
Binary files differ
diff --git a/leptonica/prog/barcode-2of5-300.png b/leptonica/prog/barcode-2of5-300.png
new file mode 100644
index 00000000..6e52537c
--- /dev/null
+++ b/leptonica/prog/barcode-2of5-300.png
Binary files differ
diff --git a/leptonica/prog/barcode-39-300.png b/leptonica/prog/barcode-39-300.png
new file mode 100644
index 00000000..dcdb841f
--- /dev/null
+++ b/leptonica/prog/barcode-39-300.png
Binary files differ
diff --git a/leptonica/prog/barcode-93-300.png b/leptonica/prog/barcode-93-300.png
new file mode 100644
index 00000000..f202be10
--- /dev/null
+++ b/leptonica/prog/barcode-93-300.png
Binary files differ
diff --git a/leptonica/prog/barcode-codabar-300.png b/leptonica/prog/barcode-codabar-300.png
new file mode 100644
index 00000000..8f599cae
--- /dev/null
+++ b/leptonica/prog/barcode-codabar-300.png
Binary files differ
diff --git a/leptonica/prog/barcode-digits.png b/leptonica/prog/barcode-digits.png
new file mode 100644
index 00000000..bb3af672
--- /dev/null
+++ b/leptonica/prog/barcode-digits.png
Binary files differ
diff --git a/leptonica/prog/barcode-i2of5-300.png b/leptonica/prog/barcode-i2of5-300.png
new file mode 100644
index 00000000..79ccd4cd
--- /dev/null
+++ b/leptonica/prog/barcode-i2of5-300.png
Binary files differ
diff --git a/leptonica/prog/barcode-upc-300.png b/leptonica/prog/barcode-upc-300.png
new file mode 100644
index 00000000..02e2a94e
--- /dev/null
+++ b/leptonica/prog/barcode-upc-300.png
Binary files differ
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
new file mode 100644
index 00000000..2a813734
--- /dev/null
+++ b/leptonica/prog/barcodetest1.jpg
Binary files differ
diff --git a/leptonica/prog/barcodetest2.jpg b/leptonica/prog/barcodetest2.jpg
new file mode 100644
index 00000000..fe361690
--- /dev/null
+++ b/leptonica/prog/barcodetest2.jpg
Binary files differ
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
new file mode 100644
index 00000000..ce2e27e1
--- /dev/null
+++ b/leptonica/prog/bigweasel2.4c.png
Binary files differ
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
new file mode 100644
index 00000000..c6f3b68c
--- /dev/null
+++ b/leptonica/prog/binding-example.45.jpg
Binary files differ
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
new file mode 100644
index 00000000..4f45cca9
--- /dev/null
+++ b/leptonica/prog/blend-green1.jpg
Binary files differ
diff --git a/leptonica/prog/blend-green2.png b/leptonica/prog/blend-green2.png
new file mode 100644
index 00000000..bc0e7ec0
--- /dev/null
+++ b/leptonica/prog/blend-green2.png
Binary files differ
diff --git a/leptonica/prog/blend-green3.png b/leptonica/prog/blend-green3.png
new file mode 100644
index 00000000..36acd8d6
--- /dev/null
+++ b/leptonica/prog/blend-green3.png
Binary files differ
diff --git a/leptonica/prog/blend-orange.jpg b/leptonica/prog/blend-orange.jpg
new file mode 100644
index 00000000..c4f229a7
--- /dev/null
+++ b/leptonica/prog/blend-orange.jpg
Binary files differ
diff --git a/leptonica/prog/blend-red.png b/leptonica/prog/blend-red.png
new file mode 100644
index 00000000..6656e0ce
--- /dev/null
+++ b/leptonica/prog/blend-red.png
Binary files differ
diff --git a/leptonica/prog/blend-yellow.jpg b/leptonica/prog/blend-yellow.jpg
new file mode 100644
index 00000000..a65678d0
--- /dev/null
+++ b/leptonica/prog/blend-yellow.jpg
Binary files differ
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
new file mode 100644
index 00000000..b570706d
--- /dev/null
+++ b/leptonica/prog/blender1.tif
Binary files differ
diff --git a/leptonica/prog/blender8.png b/leptonica/prog/blender8.png
new file mode 100644
index 00000000..122802ca
--- /dev/null
+++ b/leptonica/prog/blender8.png
Binary files differ
diff --git a/leptonica/prog/blendtext.tif b/leptonica/prog/blendtext.tif
new file mode 100644
index 00000000..b570706d
--- /dev/null
+++ b/leptonica/prog/blendtext.tif
Binary files differ
diff --git a/leptonica/prog/bois-2.tif b/leptonica/prog/bois-2.tif
new file mode 100644
index 00000000..c6820674
--- /dev/null
+++ b/leptonica/prog/bois-2.tif
Binary files differ
diff --git a/leptonica/prog/bois-3.tif b/leptonica/prog/bois-3.tif
new file mode 100644
index 00000000..fc85fd94
--- /dev/null
+++ b/leptonica/prog/bois-3.tif
Binary files differ
diff --git a/leptonica/prog/bois-4.tif b/leptonica/prog/bois-4.tif
new file mode 100644
index 00000000..9cef270f
--- /dev/null
+++ b/leptonica/prog/bois-4.tif
Binary files differ
diff --git a/leptonica/prog/bois-5.tif b/leptonica/prog/bois-5.tif
new file mode 100644
index 00000000..b6314233
--- /dev/null
+++ b/leptonica/prog/bois-5.tif
Binary files differ
diff --git a/leptonica/prog/books_logo.png b/leptonica/prog/books_logo.png
new file mode 100644
index 00000000..92f901d9
--- /dev/null
+++ b/leptonica/prog/books_logo.png
Binary files differ
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
new file mode 100644
index 00000000..1b7030f1
--- /dev/null
+++ b/leptonica/prog/boxedpage.jpg
Binary files differ
diff --git a/leptonica/prog/brev.06.75.jpg b/leptonica/prog/brev.06.75.jpg
new file mode 100644
index 00000000..03ec00bf
--- /dev/null
+++ b/leptonica/prog/brev.06.75.jpg
Binary files differ
diff --git a/leptonica/prog/brev.10.75.jpg b/leptonica/prog/brev.10.75.jpg
new file mode 100644
index 00000000..af809928
--- /dev/null
+++ b/leptonica/prog/brev.10.75.jpg
Binary files differ
diff --git a/leptonica/prog/brev.14.75.jpg b/leptonica/prog/brev.14.75.jpg
new file mode 100644
index 00000000..955e5045
--- /dev/null
+++ b/leptonica/prog/brev.14.75.jpg
Binary files differ
diff --git a/leptonica/prog/brev.20.75.jpg b/leptonica/prog/brev.20.75.jpg
new file mode 100644
index 00000000..b2c22f5b
--- /dev/null
+++ b/leptonica/prog/brev.20.75.jpg
Binary files differ
diff --git a/leptonica/prog/brev.36.75.jpg b/leptonica/prog/brev.36.75.jpg
new file mode 100644
index 00000000..8f7e3cc2
--- /dev/null
+++ b/leptonica/prog/brev.36.75.jpg
Binary files differ
diff --git a/leptonica/prog/brev.53.75.jpg b/leptonica/prog/brev.53.75.jpg
new file mode 100644
index 00000000..134bccb9
--- /dev/null
+++ b/leptonica/prog/brev.53.75.jpg
Binary files differ
diff --git a/leptonica/prog/brev.56.75.jpg b/leptonica/prog/brev.56.75.jpg
new file mode 100644
index 00000000..53ad703a
--- /dev/null
+++ b/leptonica/prog/brev.56.75.jpg
Binary files differ
diff --git a/leptonica/prog/breviar.38.150.jpg b/leptonica/prog/breviar.38.150.jpg
new file mode 100644
index 00000000..0a564e59
--- /dev/null
+++ b/leptonica/prog/breviar.38.150.jpg
Binary files differ
diff --git a/leptonica/prog/brothers.150.jpg b/leptonica/prog/brothers.150.jpg
new file mode 100644
index 00000000..74fb9bf0
--- /dev/null
+++ b/leptonica/prog/brothers.150.jpg
Binary files differ
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
new file mode 100644
index 00000000..a4b26bf5
--- /dev/null
+++ b/leptonica/prog/candelabrum.011.jpg
Binary files differ
diff --git a/leptonica/prog/cat-and-mouse.png b/leptonica/prog/cat-and-mouse.png
new file mode 100644
index 00000000..6c292b06
--- /dev/null
+++ b/leptonica/prog/cat-and-mouse.png
Binary files differ
diff --git a/leptonica/prog/cat.007.jpg b/leptonica/prog/cat.007.jpg
new file mode 100644
index 00000000..00466c36
--- /dev/null
+++ b/leptonica/prog/cat.007.jpg
Binary files differ
diff --git a/leptonica/prog/cat.035.jpg b/leptonica/prog/cat.035.jpg
new file mode 100644
index 00000000..82428395
--- /dev/null
+++ b/leptonica/prog/cat.035.jpg
Binary files differ
diff --git a/leptonica/prog/cavalerie.11.jpg b/leptonica/prog/cavalerie.11.jpg
new file mode 100644
index 00000000..68375b0b
--- /dev/null
+++ b/leptonica/prog/cavalerie.11.jpg
Binary files differ
diff --git a/leptonica/prog/cavalerie.29.jpg b/leptonica/prog/cavalerie.29.jpg
new file mode 100644
index 00000000..00169630
--- /dev/null
+++ b/leptonica/prog/cavalerie.29.jpg
Binary files differ
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
new file mode 100644
index 00000000..de2511d6
--- /dev/null
+++ b/leptonica/prog/char.tif
Binary files differ
diff --git a/leptonica/prog/chars-10.tif b/leptonica/prog/chars-10.tif
new file mode 100644
index 00000000..76a0855b
--- /dev/null
+++ b/leptonica/prog/chars-10.tif
Binary files differ
diff --git a/leptonica/prog/chars-12.tif b/leptonica/prog/chars-12.tif
new file mode 100644
index 00000000..db791955
--- /dev/null
+++ b/leptonica/prog/chars-12.tif
Binary files differ
diff --git a/leptonica/prog/chars-14.tif b/leptonica/prog/chars-14.tif
new file mode 100644
index 00000000..98508874
--- /dev/null
+++ b/leptonica/prog/chars-14.tif
Binary files differ
diff --git a/leptonica/prog/chars-16.tif b/leptonica/prog/chars-16.tif
new file mode 100644
index 00000000..2b8bbf75
--- /dev/null
+++ b/leptonica/prog/chars-16.tif
Binary files differ
diff --git a/leptonica/prog/chars-18.tif b/leptonica/prog/chars-18.tif
new file mode 100644
index 00000000..3c101bec
--- /dev/null
+++ b/leptonica/prog/chars-18.tif
Binary files differ
diff --git a/leptonica/prog/chars-20.tif b/leptonica/prog/chars-20.tif
new file mode 100644
index 00000000..fba7b5f2
--- /dev/null
+++ b/leptonica/prog/chars-20.tif
Binary files differ
diff --git a/leptonica/prog/chars-4.tif b/leptonica/prog/chars-4.tif
new file mode 100644
index 00000000..b535b368
--- /dev/null
+++ b/leptonica/prog/chars-4.tif
Binary files differ
diff --git a/leptonica/prog/chars-6.tif b/leptonica/prog/chars-6.tif
new file mode 100644
index 00000000..27679b40
--- /dev/null
+++ b/leptonica/prog/chars-6.tif
Binary files differ
diff --git a/leptonica/prog/chars-8.tif b/leptonica/prog/chars-8.tif
new file mode 100644
index 00000000..76e08b90
--- /dev/null
+++ b/leptonica/prog/chars-8.tif
Binary files differ
diff --git a/leptonica/prog/checkerboard1.tif b/leptonica/prog/checkerboard1.tif
new file mode 100644
index 00000000..64e0b545
--- /dev/null
+++ b/leptonica/prog/checkerboard1.tif
Binary files differ
diff --git a/leptonica/prog/checkerboard2.tif b/leptonica/prog/checkerboard2.tif
new file mode 100644
index 00000000..8d0cb9e2
--- /dev/null
+++ b/leptonica/prog/checkerboard2.tif
Binary files differ
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
new file mode 100644
index 00000000..ebe64c96
--- /dev/null
+++ b/leptonica/prog/church.png
Binary files differ
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
new file mode 100644
index 00000000..c638ce20
--- /dev/null
+++ b/leptonica/prog/circles.pa
Binary files differ
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
new file mode 100644
index 00000000..489b7b01
--- /dev/null
+++ b/leptonica/prog/coffeebeans.png
Binary files differ
diff --git a/leptonica/prog/color-wheel-hue.jpg b/leptonica/prog/color-wheel-hue.jpg
new file mode 100644
index 00000000..e00bbf6a
--- /dev/null
+++ b/leptonica/prog/color-wheel-hue.jpg
Binary files differ
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
new file mode 100644
index 00000000..fef4c12d
--- /dev/null
+++ b/leptonica/prog/colorpage.030.jpg
Binary files differ
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
new file mode 100644
index 00000000..ef502eff
--- /dev/null
+++ b/leptonica/prog/colorseg.jpg
Binary files differ
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
new file mode 100644
index 00000000..cda10e35
--- /dev/null
+++ b/leptonica/prog/comap.063.jpg
Binary files differ
diff --git a/leptonica/prog/comap.068.jpg b/leptonica/prog/comap.068.jpg
new file mode 100644
index 00000000..c8e64a4c
--- /dev/null
+++ b/leptonica/prog/comap.068.jpg
Binary files differ
diff --git a/leptonica/prog/comap.073.jpg b/leptonica/prog/comap.073.jpg
new file mode 100644
index 00000000..ec28b4fa
--- /dev/null
+++ b/leptonica/prog/comap.073.jpg
Binary files differ
diff --git a/leptonica/prog/comap.100.jpg b/leptonica/prog/comap.100.jpg
new file mode 100644
index 00000000..fdf65952
--- /dev/null
+++ b/leptonica/prog/comap.100.jpg
Binary files differ
diff --git a/leptonica/prog/comap.110.jpg b/leptonica/prog/comap.110.jpg
new file mode 100644
index 00000000..fdda284a
--- /dev/null
+++ b/leptonica/prog/comap.110.jpg
Binary files differ
diff --git a/leptonica/prog/comap.118.jpg b/leptonica/prog/comap.118.jpg
new file mode 100644
index 00000000..96ae6f26
--- /dev/null
+++ b/leptonica/prog/comap.118.jpg
Binary files differ
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
new file mode 100644
index 00000000..a9772c50
--- /dev/null
+++ b/leptonica/prog/contrast-orig-60.jpg
Binary files differ
diff --git a/leptonica/prog/contrast1.jpg b/leptonica/prog/contrast1.jpg
new file mode 100644
index 00000000..a185e686
--- /dev/null
+++ b/leptonica/prog/contrast1.jpg
Binary files differ
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
new file mode 100644
index 00000000..4daabf99
--- /dev/null
+++ b/leptonica/prog/cootoots.png
Binary files differ
diff --git a/leptonica/prog/copernicus.png b/leptonica/prog/copernicus.png
new file mode 100644
index 00000000..1c1cb6f9
--- /dev/null
+++ b/leptonica/prog/copernicus.png
Binary files differ
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
new file mode 100644
index 00000000..7948cb5a
--- /dev/null
+++ b/leptonica/prog/dave-orig.png
Binary files differ
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
new file mode 100644
index 00000000..42ba57d0
--- /dev/null
+++ b/leptonica/prog/dinos.pac
Binary files differ
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
new file mode 100644
index 00000000..72f770af
--- /dev/null
+++ b/leptonica/prog/dreyfus1.png
Binary files differ
diff --git a/leptonica/prog/dreyfus2.png b/leptonica/prog/dreyfus2.png
new file mode 100644
index 00000000..aa12421e
--- /dev/null
+++ b/leptonica/prog/dreyfus2.png
Binary files differ
diff --git a/leptonica/prog/dreyfus4.png b/leptonica/prog/dreyfus4.png
new file mode 100644
index 00000000..40184316
--- /dev/null
+++ b/leptonica/prog/dreyfus4.png
Binary files differ
diff --git a/leptonica/prog/dreyfus8.png b/leptonica/prog/dreyfus8.png
new file mode 100644
index 00000000..8e7fe0af
--- /dev/null
+++ b/leptonica/prog/dreyfus8.png
Binary files differ
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
new file mode 100644
index 00000000..25f140a4
--- /dev/null
+++ b/leptonica/prog/feyn-fract.tif
Binary files differ
diff --git a/leptonica/prog/feyn-fract2.tif b/leptonica/prog/feyn-fract2.tif
new file mode 100644
index 00000000..4f92259f
--- /dev/null
+++ b/leptonica/prog/feyn-fract2.tif
Binary files differ
diff --git a/leptonica/prog/feyn-word.tif b/leptonica/prog/feyn-word.tif
new file mode 100644
index 00000000..f1be2a97
--- /dev/null
+++ b/leptonica/prog/feyn-word.tif
Binary files differ
diff --git a/leptonica/prog/feyn.tif b/leptonica/prog/feyn.tif
new file mode 100644
index 00000000..6fd17e40
--- /dev/null
+++ b/leptonica/prog/feyn.tif
Binary files differ
diff --git a/leptonica/prog/feynman-stamp.jpg b/leptonica/prog/feynman-stamp.jpg
new file mode 100644
index 00000000..4a9c22b6
--- /dev/null
+++ b/leptonica/prog/feynman-stamp.jpg
Binary files differ
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
new file mode 100644
index 00000000..eba97436
--- /dev/null
+++ b/leptonica/prog/fish24.jpg
Binary files differ
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
new file mode 100644
index 00000000..fd3d93a7
--- /dev/null
+++ b/leptonica/prog/fonts/chars-10.pa
Binary files differ
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
new file mode 100644
index 00000000..a6e36520
--- /dev/null
+++ b/leptonica/prog/fonts/chars-10.tif
Binary files differ
diff --git a/leptonica/prog/fonts/chars-12.pa b/leptonica/prog/fonts/chars-12.pa
new file mode 100644
index 00000000..f7159865
--- /dev/null
+++ b/leptonica/prog/fonts/chars-12.pa
Binary files differ
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
new file mode 100644
index 00000000..f53304f4
--- /dev/null
+++ b/leptonica/prog/fonts/chars-12.tif
Binary files differ
diff --git a/leptonica/prog/fonts/chars-14.pa b/leptonica/prog/fonts/chars-14.pa
new file mode 100644
index 00000000..1b0ede1e
--- /dev/null
+++ b/leptonica/prog/fonts/chars-14.pa
Binary files differ
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
new file mode 100644
index 00000000..ff47cb5b
--- /dev/null
+++ b/leptonica/prog/fonts/chars-14.tif
Binary files differ
diff --git a/leptonica/prog/fonts/chars-16.pa b/leptonica/prog/fonts/chars-16.pa
new file mode 100644
index 00000000..32c9bd2f
--- /dev/null
+++ b/leptonica/prog/fonts/chars-16.pa
Binary files differ
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
new file mode 100644
index 00000000..4d6a5d2f
--- /dev/null
+++ b/leptonica/prog/fonts/chars-16.tif
Binary files differ
diff --git a/leptonica/prog/fonts/chars-18.pa b/leptonica/prog/fonts/chars-18.pa
new file mode 100644
index 00000000..c1941d4d
--- /dev/null
+++ b/leptonica/prog/fonts/chars-18.pa
Binary files differ
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
new file mode 100644
index 00000000..3eb9d9d5
--- /dev/null
+++ b/leptonica/prog/fonts/chars-18.tif
Binary files differ
diff --git a/leptonica/prog/fonts/chars-20.pa b/leptonica/prog/fonts/chars-20.pa
new file mode 100644
index 00000000..63244baa
--- /dev/null
+++ b/leptonica/prog/fonts/chars-20.pa
Binary files differ
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
new file mode 100644
index 00000000..53841dd5
--- /dev/null
+++ b/leptonica/prog/fonts/chars-20.tif
Binary files differ
diff --git a/leptonica/prog/fonts/chars-4.pa b/leptonica/prog/fonts/chars-4.pa
new file mode 100644
index 00000000..e347faaa
--- /dev/null
+++ b/leptonica/prog/fonts/chars-4.pa
Binary files differ
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
new file mode 100644
index 00000000..096caa61
--- /dev/null
+++ b/leptonica/prog/fonts/chars-4.tif
Binary files differ
diff --git a/leptonica/prog/fonts/chars-6.pa b/leptonica/prog/fonts/chars-6.pa
new file mode 100644
index 00000000..d720f517
--- /dev/null
+++ b/leptonica/prog/fonts/chars-6.pa
Binary files differ
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
new file mode 100644
index 00000000..2839a445
--- /dev/null
+++ b/leptonica/prog/fonts/chars-6.tif
Binary files differ
diff --git a/leptonica/prog/fonts/chars-8.pa b/leptonica/prog/fonts/chars-8.pa
new file mode 100644
index 00000000..fee467f6
--- /dev/null
+++ b/leptonica/prog/fonts/chars-8.pa
Binary files differ
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
new file mode 100644
index 00000000..74f35f59
--- /dev/null
+++ b/leptonica/prog/fonts/chars-8.tif
Binary files differ
diff --git a/leptonica/prog/form1.tif b/leptonica/prog/form1.tif
new file mode 100644
index 00000000..0a98e205
--- /dev/null
+++ b/leptonica/prog/form1.tif
Binary files differ
diff --git a/leptonica/prog/form2.tif b/leptonica/prog/form2.tif
new file mode 100644
index 00000000..32893cc5
--- /dev/null
+++ b/leptonica/prog/form2.tif
Binary files differ
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
new file mode 100644
index 00000000..81199be2
--- /dev/null
+++ b/leptonica/prog/fuzzing/barcode_fuzzer_seed_corpus.zip
Binary files differ
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
new file mode 100644
index 00000000..61a08f0d
--- /dev/null
+++ b/leptonica/prog/fuzzing/general_corpus.zip
Binary files differ
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
new file mode 100644
index 00000000..b3eabdd8
--- /dev/null
+++ b/leptonica/prog/fuzzing/pixa_recog_fuzzer_seed_corpus.zip
Binary files differ
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
new file mode 100644
index 00000000..ad1c1c5b
--- /dev/null
+++ b/leptonica/prog/german.png
Binary files differ
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
new file mode 100644
index 00000000..c9c549c4
--- /dev/null
+++ b/leptonica/prog/google-searchbox.png
Binary files differ
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
new file mode 100644
index 00000000..199d30a0
--- /dev/null
+++ b/leptonica/prog/gray-alpha.tif
Binary files differ
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
new file mode 100644
index 00000000..0839d7c9
--- /dev/null
+++ b/leptonica/prog/graytext.png
Binary files differ
diff --git a/leptonica/prog/greencover.jpg b/leptonica/prog/greencover.jpg
new file mode 100644
index 00000000..dd320d48
--- /dev/null
+++ b/leptonica/prog/greencover.jpg
Binary files differ
diff --git a/leptonica/prog/hardlight1_1.jpg b/leptonica/prog/hardlight1_1.jpg
new file mode 100644
index 00000000..8c355404
--- /dev/null
+++ b/leptonica/prog/hardlight1_1.jpg
Binary files differ
diff --git a/leptonica/prog/hardlight1_2.jpg b/leptonica/prog/hardlight1_2.jpg
new file mode 100644
index 00000000..68086611
--- /dev/null
+++ b/leptonica/prog/hardlight1_2.jpg
Binary files differ
diff --git a/leptonica/prog/hardlight2_1.jpg b/leptonica/prog/hardlight2_1.jpg
new file mode 100644
index 00000000..8692dcbc
--- /dev/null
+++ b/leptonica/prog/hardlight2_1.jpg
Binary files differ
diff --git a/leptonica/prog/hardlight2_2.jpg b/leptonica/prog/hardlight2_2.jpg
new file mode 100644
index 00000000..41dabea6
--- /dev/null
+++ b/leptonica/prog/hardlight2_2.jpg
Binary files differ
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
new file mode 100644
index 00000000..427f1360
--- /dev/null
+++ b/leptonica/prog/harmoniam-11.tif
Binary files differ
diff --git a/leptonica/prog/harmoniam100-11.png b/leptonica/prog/harmoniam100-11.png
new file mode 100644
index 00000000..ba3f575e
--- /dev/null
+++ b/leptonica/prog/harmoniam100-11.png
Binary files differ
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
new file mode 100644
index 00000000..e5e5532b
--- /dev/null
+++ b/leptonica/prog/hole-filler.png
Binary files differ
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
new file mode 100644
index 00000000..3861864f
--- /dev/null
+++ b/leptonica/prog/invertedtext.tif
Binary files differ
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
new file mode 100644
index 00000000..7fdc9fc2
--- /dev/null
+++ b/leptonica/prog/italic.png
Binary files differ
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
new file mode 100644
index 00000000..d4bfb3f7
--- /dev/null
+++ b/leptonica/prog/jpeg-coded.tif
Binary files differ
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
new file mode 100644
index 00000000..f1a510d8
--- /dev/null
+++ b/leptonica/prog/juditharismax.jpg
Binary files differ
diff --git a/leptonica/prog/karen8.jpg b/leptonica/prog/karen8.jpg
new file mode 100644
index 00000000..e9627d5b
--- /dev/null
+++ b/leptonica/prog/karen8.jpg
Binary files differ
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
new file mode 100644
index 00000000..7b88eb6f
--- /dev/null
+++ b/leptonica/prog/keystone.png
Binary files differ
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
new file mode 100644
index 00000000..ca3fbf17
--- /dev/null
+++ b/leptonica/prog/lapide.052.100.jpg
Binary files differ
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
new file mode 100644
index 00000000..c5205275
--- /dev/null
+++ b/leptonica/prog/lighttext.jpg
Binary files differ
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
new file mode 100644
index 00000000..e66122a6
--- /dev/null
+++ b/leptonica/prog/lion-mask.00010.tif
Binary files differ
diff --git a/leptonica/prog/lion-mask.00016.tif b/leptonica/prog/lion-mask.00016.tif
new file mode 100644
index 00000000..d524a80c
--- /dev/null
+++ b/leptonica/prog/lion-mask.00016.tif
Binary files differ
diff --git a/leptonica/prog/lion-page.00010.jpg b/leptonica/prog/lion-page.00010.jpg
new file mode 100644
index 00000000..41113342
--- /dev/null
+++ b/leptonica/prog/lion-page.00010.jpg
Binary files differ
diff --git a/leptonica/prog/lion-page.00011.png b/leptonica/prog/lion-page.00011.png
new file mode 100644
index 00000000..f6252728
--- /dev/null
+++ b/leptonica/prog/lion-page.00011.png
Binary files differ
diff --git a/leptonica/prog/lion-page.00012.png b/leptonica/prog/lion-page.00012.png
new file mode 100644
index 00000000..28cf2deb
--- /dev/null
+++ b/leptonica/prog/lion-page.00012.png
Binary files differ
diff --git a/leptonica/prog/lion-page.00013.png b/leptonica/prog/lion-page.00013.png
new file mode 100644
index 00000000..b41b0a99
--- /dev/null
+++ b/leptonica/prog/lion-page.00013.png
Binary files differ
diff --git a/leptonica/prog/lion-page.00016.jpg b/leptonica/prog/lion-page.00016.jpg
new file mode 100644
index 00000000..25427dc3
--- /dev/null
+++ b/leptonica/prog/lion-page.00016.jpg
Binary files differ
diff --git a/leptonica/prog/lion-page.00017.png b/leptonica/prog/lion-page.00017.png
new file mode 100644
index 00000000..c7b1c0f3
--- /dev/null
+++ b/leptonica/prog/lion-page.00017.png
Binary files differ
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
new file mode 100644
index 00000000..5df491b5
--- /dev/null
+++ b/leptonica/prog/lucasta-frag.jpg
Binary files differ
diff --git a/leptonica/prog/lucasta.047.jpg b/leptonica/prog/lucasta.047.jpg
new file mode 100644
index 00000000..58328b10
--- /dev/null
+++ b/leptonica/prog/lucasta.047.jpg
Binary files differ
diff --git a/leptonica/prog/lucasta.1.300.tif b/leptonica/prog/lucasta.1.300.tif
new file mode 100644
index 00000000..b086ce19
--- /dev/null
+++ b/leptonica/prog/lucasta.1.300.tif
Binary files differ
diff --git a/leptonica/prog/lucasta.150.jpg b/leptonica/prog/lucasta.150.jpg
new file mode 100644
index 00000000..baf70b1f
--- /dev/null
+++ b/leptonica/prog/lucasta.150.jpg
Binary files differ
diff --git a/leptonica/prog/lyra.005.jpg b/leptonica/prog/lyra.005.jpg
new file mode 100644
index 00000000..70b15f84
--- /dev/null
+++ b/leptonica/prog/lyra.005.jpg
Binary files differ
diff --git a/leptonica/prog/lyra.036.jpg b/leptonica/prog/lyra.036.jpg
new file mode 100644
index 00000000..8c52244f
--- /dev/null
+++ b/leptonica/prog/lyra.036.jpg
Binary files differ
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
new file mode 100644
index 00000000..7681e0c4
--- /dev/null
+++ b/leptonica/prog/map.057.jpg
Binary files differ
diff --git a/leptonica/prog/map1.jpg b/leptonica/prog/map1.jpg
new file mode 100644
index 00000000..09fb85ec
--- /dev/null
+++ b/leptonica/prog/map1.jpg
Binary files differ
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
new file mode 100644
index 00000000..2a14582e
--- /dev/null
+++ b/leptonica/prog/marge.jpg
Binary files differ
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
new file mode 100644
index 00000000..1db57855
--- /dev/null
+++ b/leptonica/prog/minisblack.tif
Binary files differ
diff --git a/leptonica/prog/miniswhite.tif b/leptonica/prog/miniswhite.tif
new file mode 100644
index 00000000..46d7e4f4
--- /dev/null
+++ b/leptonica/prog/miniswhite.tif
Binary files differ
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
new file mode 100644
index 00000000..0609c118
--- /dev/null
+++ b/leptonica/prog/ortiz-02.tif
Binary files differ
diff --git a/leptonica/prog/ortiz-03.tif b/leptonica/prog/ortiz-03.tif
new file mode 100644
index 00000000..50a28f08
--- /dev/null
+++ b/leptonica/prog/ortiz-03.tif
Binary files differ
diff --git a/leptonica/prog/ortiz-04.tif b/leptonica/prog/ortiz-04.tif
new file mode 100644
index 00000000..1c57a2d1
--- /dev/null
+++ b/leptonica/prog/ortiz-04.tif
Binary files differ
diff --git a/leptonica/prog/ortiz-05.tif b/leptonica/prog/ortiz-05.tif
new file mode 100644
index 00000000..98bfa062
--- /dev/null
+++ b/leptonica/prog/ortiz-05.tif
Binary files differ
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
new file mode 100644
index 00000000..901950bc
--- /dev/null
+++ b/leptonica/prog/pageseg1.tif
Binary files differ
diff --git a/leptonica/prog/pageseg2-mask.png b/leptonica/prog/pageseg2-mask.png
new file mode 100644
index 00000000..051b8dcb
--- /dev/null
+++ b/leptonica/prog/pageseg2-mask.png
Binary files differ
diff --git a/leptonica/prog/pageseg2-seed.png b/leptonica/prog/pageseg2-seed.png
new file mode 100644
index 00000000..ff5cc907
--- /dev/null
+++ b/leptonica/prog/pageseg2-seed.png
Binary files differ
diff --git a/leptonica/prog/pageseg2.tif b/leptonica/prog/pageseg2.tif
new file mode 100644
index 00000000..30a60a26
--- /dev/null
+++ b/leptonica/prog/pageseg2.tif
Binary files differ
diff --git a/leptonica/prog/pageseg3.tif b/leptonica/prog/pageseg3.tif
new file mode 100644
index 00000000..d70f46c7
--- /dev/null
+++ b/leptonica/prog/pageseg3.tif
Binary files differ
diff --git a/leptonica/prog/pageseg4.tif b/leptonica/prog/pageseg4.tif
new file mode 100644
index 00000000..a34683fd
--- /dev/null
+++ b/leptonica/prog/pageseg4.tif
Binary files differ
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
new file mode 100644
index 00000000..5bfdd594
--- /dev/null
+++ b/leptonica/prog/pancrazi.15.jpg
Binary files differ
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
new file mode 100644
index 00000000..bcb3cc43
--- /dev/null
+++ b/leptonica/prog/patent.png
Binary files differ
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
new file mode 100644
index 00000000..30aae0da
--- /dev/null
+++ b/leptonica/prog/pedante.079.jpg
Binary files differ
diff --git a/leptonica/prog/percolate-4cc.png b/leptonica/prog/percolate-4cc.png
new file mode 100644
index 00000000..c5392e0c
--- /dev/null
+++ b/leptonica/prog/percolate-4cc.png
Binary files differ
diff --git a/leptonica/prog/percolate-8cc.png b/leptonica/prog/percolate-8cc.png
new file mode 100644
index 00000000..a1cfd91a
--- /dev/null
+++ b/leptonica/prog/percolate-8cc.png
Binary files differ
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
new file mode 100644
index 00000000..0d9f23cd
--- /dev/null
+++ b/leptonica/prog/projectionstats.jpg
Binary files differ
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
new file mode 100644
index 00000000..faf2b35d
--- /dev/null
+++ b/leptonica/prog/rabi-tiny.png
Binary files differ
diff --git a/leptonica/prog/rabi.png b/leptonica/prog/rabi.png
new file mode 100644
index 00000000..b4e41a10
--- /dev/null
+++ b/leptonica/prog/rabi.png
Binary files differ
diff --git a/leptonica/prog/raggededge.png b/leptonica/prog/raggededge.png
new file mode 100644
index 00000000..d4c134fa
--- /dev/null
+++ b/leptonica/prog/raggededge.png
Binary files differ
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
new file mode 100644
index 00000000..cd3579ba
--- /dev/null
+++ b/leptonica/prog/recog/digits/bootnum1.pa
Binary files differ
diff --git a/leptonica/prog/recog/digits/bootnum2.pa b/leptonica/prog/recog/digits/bootnum2.pa
new file mode 100644
index 00000000..f3bb0cd0
--- /dev/null
+++ b/leptonica/prog/recog/digits/bootnum2.pa
Binary files differ
diff --git a/leptonica/prog/recog/digits/bootnum3.pa b/leptonica/prog/recog/digits/bootnum3.pa
new file mode 100644
index 00000000..61880ce6
--- /dev/null
+++ b/leptonica/prog/recog/digits/bootnum3.pa
Binary files differ
diff --git a/leptonica/prog/recog/digits/bootnum4.pa b/leptonica/prog/recog/digits/bootnum4.pa
new file mode 100644
index 00000000..06996917
--- /dev/null
+++ b/leptonica/prog/recog/digits/bootnum4.pa
Binary files differ
diff --git a/leptonica/prog/recog/digits/digit0.comp.tif b/leptonica/prog/recog/digits/digit0.comp.tif
new file mode 100644
index 00000000..091e617c
--- /dev/null
+++ b/leptonica/prog/recog/digits/digit0.comp.tif
Binary files differ
diff --git a/leptonica/prog/recog/digits/digit1.comp.tif b/leptonica/prog/recog/digits/digit1.comp.tif
new file mode 100644
index 00000000..32db55da
--- /dev/null
+++ b/leptonica/prog/recog/digits/digit1.comp.tif
Binary files differ
diff --git a/leptonica/prog/recog/digits/digit2.comp.tif b/leptonica/prog/recog/digits/digit2.comp.tif
new file mode 100644
index 00000000..4a1391ee
--- /dev/null
+++ b/leptonica/prog/recog/digits/digit2.comp.tif
Binary files differ
diff --git a/leptonica/prog/recog/digits/digit3.comp.tif b/leptonica/prog/recog/digits/digit3.comp.tif
new file mode 100644
index 00000000..ba4fd807
--- /dev/null
+++ b/leptonica/prog/recog/digits/digit3.comp.tif
Binary files differ
diff --git a/leptonica/prog/recog/digits/digit4.comp.tif b/leptonica/prog/recog/digits/digit4.comp.tif
new file mode 100644
index 00000000..c5c0129e
--- /dev/null
+++ b/leptonica/prog/recog/digits/digit4.comp.tif
Binary files differ
diff --git a/leptonica/prog/recog/digits/digit5.comp.tif b/leptonica/prog/recog/digits/digit5.comp.tif
new file mode 100644
index 00000000..f839cc9d
--- /dev/null
+++ b/leptonica/prog/recog/digits/digit5.comp.tif
Binary files differ
diff --git a/leptonica/prog/recog/digits/digit5.orig-25.pa b/leptonica/prog/recog/digits/digit5.orig-25.pa
new file mode 100644
index 00000000..19afb361
--- /dev/null
+++ b/leptonica/prog/recog/digits/digit5.orig-25.pa
Binary files differ
diff --git a/leptonica/prog/recog/digits/digit6.comp.tif b/leptonica/prog/recog/digits/digit6.comp.tif
new file mode 100644
index 00000000..d72570d0
--- /dev/null
+++ b/leptonica/prog/recog/digits/digit6.comp.tif
Binary files differ
diff --git a/leptonica/prog/recog/digits/digit7.comp.tif b/leptonica/prog/recog/digits/digit7.comp.tif
new file mode 100644
index 00000000..5bc50acb
--- /dev/null
+++ b/leptonica/prog/recog/digits/digit7.comp.tif
Binary files differ
diff --git a/leptonica/prog/recog/digits/digit8.comp.tif b/leptonica/prog/recog/digits/digit8.comp.tif
new file mode 100644
index 00000000..c3036215
--- /dev/null
+++ b/leptonica/prog/recog/digits/digit8.comp.tif
Binary files differ
diff --git a/leptonica/prog/recog/digits/digit9.comp.tif b/leptonica/prog/recog/digits/digit9.comp.tif
new file mode 100644
index 00000000..66a79d80
--- /dev/null
+++ b/leptonica/prog/recog/digits/digit9.comp.tif
Binary files differ
diff --git a/leptonica/prog/recog/digits/digit_set01.pa b/leptonica/prog/recog/digits/digit_set01.pa
new file mode 100644
index 00000000..e22b056e
--- /dev/null
+++ b/leptonica/prog/recog/digits/digit_set01.pa
Binary files differ
diff --git a/leptonica/prog/recog/digits/digit_set02.pa b/leptonica/prog/recog/digits/digit_set02.pa
new file mode 100644
index 00000000..a72e499f
--- /dev/null
+++ b/leptonica/prog/recog/digits/digit_set02.pa
Binary files differ
diff --git a/leptonica/prog/recog/digits/digit_set03.pa b/leptonica/prog/recog/digits/digit_set03.pa
new file mode 100644
index 00000000..22a9f424
--- /dev/null
+++ b/leptonica/prog/recog/digits/digit_set03.pa
Binary files differ
diff --git a/leptonica/prog/recog/digits/digit_set04.pa b/leptonica/prog/recog/digits/digit_set04.pa
new file mode 100644
index 00000000..42aa8c64
--- /dev/null
+++ b/leptonica/prog/recog/digits/digit_set04.pa
Binary files differ
diff --git a/leptonica/prog/recog/digits/digit_set05.pa b/leptonica/prog/recog/digits/digit_set05.pa
new file mode 100644
index 00000000..87f5d982
--- /dev/null
+++ b/leptonica/prog/recog/digits/digit_set05.pa
Binary files differ
diff --git a/leptonica/prog/recog/digits/digit_set06.pa b/leptonica/prog/recog/digits/digit_set06.pa
new file mode 100644
index 00000000..ef6aae7f
--- /dev/null
+++ b/leptonica/prog/recog/digits/digit_set06.pa
Binary files differ
diff --git a/leptonica/prog/recog/digits/digit_set07.pa b/leptonica/prog/recog/digits/digit_set07.pa
new file mode 100644
index 00000000..85b3d874
--- /dev/null
+++ b/leptonica/prog/recog/digits/digit_set07.pa
Binary files differ
diff --git a/leptonica/prog/recog/digits/digit_set08.pa b/leptonica/prog/recog/digits/digit_set08.pa
new file mode 100644
index 00000000..2a776ca7
--- /dev/null
+++ b/leptonica/prog/recog/digits/digit_set08.pa
Binary files differ
diff --git a/leptonica/prog/recog/digits/digit_set09.pa b/leptonica/prog/recog/digits/digit_set09.pa
new file mode 100644
index 00000000..cd1f4e6a
--- /dev/null
+++ b/leptonica/prog/recog/digits/digit_set09.pa
Binary files differ
diff --git a/leptonica/prog/recog/digits/digit_set10.pa b/leptonica/prog/recog/digits/digit_set10.pa
new file mode 100644
index 00000000..39078a84
--- /dev/null
+++ b/leptonica/prog/recog/digits/digit_set10.pa
Binary files differ
diff --git a/leptonica/prog/recog/digits/digit_set11.pa b/leptonica/prog/recog/digits/digit_set11.pa
new file mode 100644
index 00000000..19c21c08
--- /dev/null
+++ b/leptonica/prog/recog/digits/digit_set11.pa
Binary files differ
diff --git a/leptonica/prog/recog/digits/digit_set12.pa b/leptonica/prog/recog/digits/digit_set12.pa
new file mode 100644
index 00000000..53e29c46
--- /dev/null
+++ b/leptonica/prog/recog/digits/digit_set12.pa
Binary files differ
diff --git a/leptonica/prog/recog/digits/digit_set13.pa b/leptonica/prog/recog/digits/digit_set13.pa
new file mode 100644
index 00000000..a701c5a2
--- /dev/null
+++ b/leptonica/prog/recog/digits/digit_set13.pa
Binary files differ
diff --git a/leptonica/prog/recog/digits/digit_set14.pa b/leptonica/prog/recog/digits/digit_set14.pa
new file mode 100644
index 00000000..cff1b405
--- /dev/null
+++ b/leptonica/prog/recog/digits/digit_set14.pa
Binary files differ
diff --git a/leptonica/prog/recog/digits/digit_set15.pa b/leptonica/prog/recog/digits/digit_set15.pa
new file mode 100644
index 00000000..4bd753cb
--- /dev/null
+++ b/leptonica/prog/recog/digits/digit_set15.pa
Binary files differ
diff --git a/leptonica/prog/recog/digits/page.306.png b/leptonica/prog/recog/digits/page.306.png
new file mode 100644
index 00000000..a234783c
--- /dev/null
+++ b/leptonica/prog/recog/digits/page.306.png
Binary files differ
diff --git a/leptonica/prog/recog/digits/page.590.png b/leptonica/prog/recog/digits/page.590.png
new file mode 100644
index 00000000..5ae2edd6
--- /dev/null
+++ b/leptonica/prog/recog/digits/page.590.png
Binary files differ
diff --git a/leptonica/prog/recog/sets/samples06.png b/leptonica/prog/recog/sets/samples06.png
new file mode 100644
index 00000000..23b7df96
--- /dev/null
+++ b/leptonica/prog/recog/sets/samples06.png
Binary files differ
diff --git a/leptonica/prog/recog/sets/test01.pa b/leptonica/prog/recog/sets/test01.pa
new file mode 100644
index 00000000..d1e4161f
--- /dev/null
+++ b/leptonica/prog/recog/sets/test01.pa
Binary files differ
diff --git a/leptonica/prog/recog/sets/test02.pa b/leptonica/prog/recog/sets/test02.pa
new file mode 100644
index 00000000..79d7f506
--- /dev/null
+++ b/leptonica/prog/recog/sets/test02.pa
Binary files differ
diff --git a/leptonica/prog/recog/sets/test03.pa b/leptonica/prog/recog/sets/test03.pa
new file mode 100644
index 00000000..c9c7157b
--- /dev/null
+++ b/leptonica/prog/recog/sets/test03.pa
Binary files differ
diff --git a/leptonica/prog/recog/sets/test05.pa b/leptonica/prog/recog/sets/test05.pa
new file mode 100644
index 00000000..c8a93dd5
--- /dev/null
+++ b/leptonica/prog/recog/sets/test05.pa
Binary files differ
diff --git a/leptonica/prog/recog/sets/test06.pa b/leptonica/prog/recog/sets/test06.pa
new file mode 100644
index 00000000..09a55bd8
--- /dev/null
+++ b/leptonica/prog/recog/sets/test06.pa
Binary files differ
diff --git a/leptonica/prog/recog/sets/train01.pa b/leptonica/prog/recog/sets/train01.pa
new file mode 100644
index 00000000..ad0891a5
--- /dev/null
+++ b/leptonica/prog/recog/sets/train01.pa
Binary files differ
diff --git a/leptonica/prog/recog/sets/train02.pa b/leptonica/prog/recog/sets/train02.pa
new file mode 100644
index 00000000..807d7609
--- /dev/null
+++ b/leptonica/prog/recog/sets/train02.pa
Binary files differ
diff --git a/leptonica/prog/recog/sets/train03.pa b/leptonica/prog/recog/sets/train03.pa
new file mode 100644
index 00000000..22a9f424
--- /dev/null
+++ b/leptonica/prog/recog/sets/train03.pa
Binary files differ
diff --git a/leptonica/prog/recog/sets/train04.pa b/leptonica/prog/recog/sets/train04.pa
new file mode 100644
index 00000000..47373bc9
--- /dev/null
+++ b/leptonica/prog/recog/sets/train04.pa
Binary files differ
diff --git a/leptonica/prog/recog/sets/train05.pa b/leptonica/prog/recog/sets/train05.pa
new file mode 100644
index 00000000..19c21c08
--- /dev/null
+++ b/leptonica/prog/recog/sets/train05.pa
Binary files differ
diff --git a/leptonica/prog/recog/sets/train06.pa b/leptonica/prog/recog/sets/train06.pa
new file mode 100644
index 00000000..6c22bfb0
--- /dev/null
+++ b/leptonica/prog/recog/sets/train06.pa
Binary files differ
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
new file mode 100644
index 00000000..5628ee9e
--- /dev/null
+++ b/leptonica/prog/redcover.jpg
Binary files differ
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
new file mode 100644
index 00000000..8b4e4e0f
--- /dev/null
+++ b/leptonica/prog/rgb16.tif
Binary files differ
diff --git a/leptonica/prog/rock.png b/leptonica/prog/rock.png
new file mode 100644
index 00000000..e7c084eb
--- /dev/null
+++ b/leptonica/prog/rock.png
Binary files differ
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
new file mode 100644
index 00000000..f030ebf9
--- /dev/null
+++ b/leptonica/prog/scots-frag.tif
Binary files differ
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
new file mode 100644
index 00000000..46d7e4f4
--- /dev/null
+++ b/leptonica/prog/sevens.tif
Binary files differ
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
new file mode 100644
index 00000000..b619ea25
--- /dev/null
+++ b/leptonica/prog/shearer.148.tif
Binary files differ
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
new file mode 100644
index 00000000..39b18ea7
--- /dev/null
+++ b/leptonica/prog/showboxes.pac
Binary files differ
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
new file mode 100644
index 00000000..cee282b4
--- /dev/null
+++ b/leptonica/prog/singlecc.tif
Binary files differ
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
new file mode 100644
index 00000000..fe390fac
--- /dev/null
+++ b/leptonica/prog/speckle.png
Binary files differ
diff --git a/leptonica/prog/speckle2.png b/leptonica/prog/speckle2.png
new file mode 100644
index 00000000..f019cebf
--- /dev/null
+++ b/leptonica/prog/speckle2.png
Binary files differ
diff --git a/leptonica/prog/speckle4.png b/leptonica/prog/speckle4.png
new file mode 100644
index 00000000..5f12c42b
--- /dev/null
+++ b/leptonica/prog/speckle4.png
Binary files differ
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
new file mode 100644
index 00000000..62539612
--- /dev/null
+++ b/leptonica/prog/stampede2.jpg
Binary files differ
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
new file mode 100644
index 00000000..2e1e673c
--- /dev/null
+++ b/leptonica/prog/table.15.tif
Binary files differ
diff --git a/leptonica/prog/table.150.png b/leptonica/prog/table.150.png
new file mode 100644
index 00000000..85b62f67
--- /dev/null
+++ b/leptonica/prog/table.150.png
Binary files differ
diff --git a/leptonica/prog/table.27.tif b/leptonica/prog/table.27.tif
new file mode 100644
index 00000000..f8e0ba70
--- /dev/null
+++ b/leptonica/prog/table.27.tif
Binary files differ
diff --git a/leptonica/prog/test-1bit-alpha.png b/leptonica/prog/test-1bit-alpha.png
new file mode 100644
index 00000000..03daf0b1
--- /dev/null
+++ b/leptonica/prog/test-1bit-alpha.png
Binary files differ
diff --git a/leptonica/prog/test-87220.59.png b/leptonica/prog/test-87220.59.png
new file mode 100644
index 00000000..8c7ceb14
--- /dev/null
+++ b/leptonica/prog/test-87220.59.png
Binary files differ
diff --git a/leptonica/prog/test-cmap-alpha.png b/leptonica/prog/test-cmap-alpha.png
new file mode 100644
index 00000000..26bf281f
--- /dev/null
+++ b/leptonica/prog/test-cmap-alpha.png
Binary files differ
diff --git a/leptonica/prog/test-cmap-alpha2.png b/leptonica/prog/test-cmap-alpha2.png
new file mode 100644
index 00000000..26cfb819
--- /dev/null
+++ b/leptonica/prog/test-cmap-alpha2.png
Binary files differ
diff --git a/leptonica/prog/test-fulltrans-alpha.png b/leptonica/prog/test-fulltrans-alpha.png
new file mode 100644
index 00000000..9b69daa8
--- /dev/null
+++ b/leptonica/prog/test-fulltrans-alpha.png
Binary files differ
diff --git a/leptonica/prog/test-gray-alpha.png b/leptonica/prog/test-gray-alpha.png
new file mode 100644
index 00000000..3d49f3a1
--- /dev/null
+++ b/leptonica/prog/test-gray-alpha.png
Binary files differ
diff --git a/leptonica/prog/test1.bmp b/leptonica/prog/test1.bmp
new file mode 100644
index 00000000..d13002de
--- /dev/null
+++ b/leptonica/prog/test1.bmp
Binary files differ
diff --git a/leptonica/prog/test1.png b/leptonica/prog/test1.png
new file mode 100644
index 00000000..402fb2dc
--- /dev/null
+++ b/leptonica/prog/test1.png
Binary files differ
diff --git a/leptonica/prog/test16.png b/leptonica/prog/test16.png
new file mode 100644
index 00000000..54e9c370
--- /dev/null
+++ b/leptonica/prog/test16.png
Binary files differ
diff --git a/leptonica/prog/test16.tif b/leptonica/prog/test16.tif
new file mode 100644
index 00000000..36c0aa32
--- /dev/null
+++ b/leptonica/prog/test16.tif
Binary files differ
diff --git a/leptonica/prog/test24.jpg b/leptonica/prog/test24.jpg
new file mode 100644
index 00000000..6c5aff53
--- /dev/null
+++ b/leptonica/prog/test24.jpg
Binary files differ
diff --git a/leptonica/prog/test32-alpha.png b/leptonica/prog/test32-alpha.png
new file mode 100644
index 00000000..252171af
--- /dev/null
+++ b/leptonica/prog/test32-alpha.png
Binary files differ
diff --git a/leptonica/prog/test8.jpg b/leptonica/prog/test8.jpg
new file mode 100644
index 00000000..11863a6b
--- /dev/null
+++ b/leptonica/prog/test8.jpg
Binary files differ
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
new file mode 100644
index 00000000..213ac806
--- /dev/null
+++ b/leptonica/prog/testbuffer.tif
Binary files differ
diff --git a/leptonica/prog/testfile1.pdf b/leptonica/prog/testfile1.pdf
new file mode 100644
index 00000000..ade4373e
--- /dev/null
+++ b/leptonica/prog/testfile1.pdf
Binary files differ
diff --git a/leptonica/prog/testfile2.pdf b/leptonica/prog/testfile2.pdf
new file mode 100644
index 00000000..8389a3bb
--- /dev/null
+++ b/leptonica/prog/testfile2.pdf
Binary files differ
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
new file mode 100644
index 00000000..9c60b88b
--- /dev/null
+++ b/leptonica/prog/tetons.jpg
Binary files differ
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
new file mode 100644
index 00000000..8609af28
--- /dev/null
+++ b/leptonica/prog/tickets.tif
Binary files differ
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
new file mode 100644
index 00000000..98d07cf6
--- /dev/null
+++ b/leptonica/prog/toc.99.tif
Binary files differ
diff --git a/leptonica/prog/topotest.png b/leptonica/prog/topotest.png
new file mode 100644
index 00000000..3bc5509e
--- /dev/null
+++ b/leptonica/prog/topotest.png
Binary files differ
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
new file mode 100644
index 00000000..fd551727
--- /dev/null
+++ b/leptonica/prog/tribune-page-4x.png
Binary files differ
diff --git a/leptonica/prog/tribune-t.png b/leptonica/prog/tribune-t.png
new file mode 100644
index 00000000..fb939dbf
--- /dev/null
+++ b/leptonica/prog/tribune-t.png
Binary files differ
diff --git a/leptonica/prog/tribune-word.png b/leptonica/prog/tribune-word.png
new file mode 100644
index 00000000..02a6b53d
--- /dev/null
+++ b/leptonica/prog/tribune-word.png
Binary files differ
diff --git a/leptonica/prog/turingtest.png b/leptonica/prog/turingtest.png
new file mode 100644
index 00000000..5ecce26b
--- /dev/null
+++ b/leptonica/prog/turingtest.png
Binary files differ
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
new file mode 100644
index 00000000..20b976a5
--- /dev/null
+++ b/leptonica/prog/underline1.jpg
Binary files differ
diff --git a/leptonica/prog/underline2.jpg b/leptonica/prog/underline2.jpg
new file mode 100644
index 00000000..515a618f
--- /dev/null
+++ b/leptonica/prog/underline2.jpg
Binary files differ
diff --git a/leptonica/prog/underline3.jpg b/leptonica/prog/underline3.jpg
new file mode 100644
index 00000000..fa17d3ab
--- /dev/null
+++ b/leptonica/prog/underline3.jpg
Binary files differ
diff --git a/leptonica/prog/underline4.jpg b/leptonica/prog/underline4.jpg
new file mode 100644
index 00000000..dcfd0da4
--- /dev/null
+++ b/leptonica/prog/underline4.jpg
Binary files differ
diff --git a/leptonica/prog/underline5.jpg b/leptonica/prog/underline5.jpg
new file mode 100644
index 00000000..04031abf
--- /dev/null
+++ b/leptonica/prog/underline5.jpg
Binary files differ
diff --git a/leptonica/prog/underline6.jpg b/leptonica/prog/underline6.jpg
new file mode 100644
index 00000000..2a3fb7d0
--- /dev/null
+++ b/leptonica/prog/underline6.jpg
Binary files differ
diff --git a/leptonica/prog/underline7.jpg b/leptonica/prog/underline7.jpg
new file mode 100644
index 00000000..f909be6c
--- /dev/null
+++ b/leptonica/prog/underline7.jpg
Binary files differ
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
new file mode 100644
index 00000000..7cfdc279
--- /dev/null
+++ b/leptonica/prog/w91frag.jpg
Binary files differ
diff --git a/leptonica/prog/warped_paper.jpg b/leptonica/prog/warped_paper.jpg
new file mode 100644
index 00000000..44701cca
--- /dev/null
+++ b/leptonica/prog/warped_paper.jpg
Binary files differ
diff --git a/leptonica/prog/warped_sudoku.jpg b/leptonica/prog/warped_sudoku.jpg
new file mode 100644
index 00000000..4c6c79f5
--- /dev/null
+++ b/leptonica/prog/warped_sudoku.jpg
Binary files differ
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
new file mode 100644
index 00000000..2fb7877d
--- /dev/null
+++ b/leptonica/prog/weasel-113c.png
Binary files differ
diff --git a/leptonica/prog/weasel-44c.png b/leptonica/prog/weasel-44c.png
new file mode 100644
index 00000000..69752534
--- /dev/null
+++ b/leptonica/prog/weasel-44c.png
Binary files differ
diff --git a/leptonica/prog/weasel-4c.2.png b/leptonica/prog/weasel-4c.2.png
new file mode 100644
index 00000000..4bd031fd
--- /dev/null
+++ b/leptonica/prog/weasel-4c.2.png
Binary files differ
diff --git a/leptonica/prog/weasel-64g.png b/leptonica/prog/weasel-64g.png
new file mode 100644
index 00000000..3ff8bd21
--- /dev/null
+++ b/leptonica/prog/weasel-64g.png
Binary files differ
diff --git a/leptonica/prog/weasel-8g.png b/leptonica/prog/weasel-8g.png
new file mode 100644
index 00000000..504d15bd
--- /dev/null
+++ b/leptonica/prog/weasel-8g.png
Binary files differ
diff --git a/leptonica/prog/weasel2.4c.bmp b/leptonica/prog/weasel2.4c.bmp
new file mode 100644
index 00000000..aa45a96f
--- /dev/null
+++ b/leptonica/prog/weasel2.4c.bmp
Binary files differ
diff --git a/leptonica/prog/weasel2.4c.png b/leptonica/prog/weasel2.4c.png
new file mode 100644
index 00000000..c7c1c440
--- /dev/null
+++ b/leptonica/prog/weasel2.4c.png
Binary files differ
diff --git a/leptonica/prog/weasel2.4g.png b/leptonica/prog/weasel2.4g.png
new file mode 100644
index 00000000..2ccbb370
--- /dev/null
+++ b/leptonica/prog/weasel2.4g.png
Binary files differ
diff --git a/leptonica/prog/weasel2.png b/leptonica/prog/weasel2.png
new file mode 100644
index 00000000..fc7c87dc
--- /dev/null
+++ b/leptonica/prog/weasel2.png
Binary files differ
diff --git a/leptonica/prog/weasel32.png b/leptonica/prog/weasel32.png
new file mode 100644
index 00000000..f4509d25
--- /dev/null
+++ b/leptonica/prog/weasel32.png
Binary files differ
diff --git a/leptonica/prog/weasel4.11c.png b/leptonica/prog/weasel4.11c.png
new file mode 100644
index 00000000..c8b23e15
--- /dev/null
+++ b/leptonica/prog/weasel4.11c.png
Binary files differ
diff --git a/leptonica/prog/weasel4.16c.png b/leptonica/prog/weasel4.16c.png
new file mode 100644
index 00000000..95d7ff28
--- /dev/null
+++ b/leptonica/prog/weasel4.16c.png
Binary files differ
diff --git a/leptonica/prog/weasel4.16g.png b/leptonica/prog/weasel4.16g.png
new file mode 100644
index 00000000..8310c464
--- /dev/null
+++ b/leptonica/prog/weasel4.16g.png
Binary files differ
diff --git a/leptonica/prog/weasel4.5g.png b/leptonica/prog/weasel4.5g.png
new file mode 100644
index 00000000..4689622d
--- /dev/null
+++ b/leptonica/prog/weasel4.5g.png
Binary files differ
diff --git a/leptonica/prog/weasel4.8g.png b/leptonica/prog/weasel4.8g.png
new file mode 100644
index 00000000..c13f4962
--- /dev/null
+++ b/leptonica/prog/weasel4.8g.png
Binary files differ
diff --git a/leptonica/prog/weasel4.png b/leptonica/prog/weasel4.png
new file mode 100644
index 00000000..d1261e6d
--- /dev/null
+++ b/leptonica/prog/weasel4.png
Binary files differ
diff --git a/leptonica/prog/weasel8.149g.png b/leptonica/prog/weasel8.149g.png
new file mode 100644
index 00000000..79ceaa57
--- /dev/null
+++ b/leptonica/prog/weasel8.149g.png
Binary files differ
diff --git a/leptonica/prog/weasel8.16g.nocmap.png b/leptonica/prog/weasel8.16g.nocmap.png
new file mode 100644
index 00000000..e6c2365d
--- /dev/null
+++ b/leptonica/prog/weasel8.16g.nocmap.png
Binary files differ
diff --git a/leptonica/prog/weasel8.16g.png b/leptonica/prog/weasel8.16g.png
new file mode 100644
index 00000000..f4bd13eb
--- /dev/null
+++ b/leptonica/prog/weasel8.16g.png
Binary files differ
diff --git a/leptonica/prog/weasel8.240c.png b/leptonica/prog/weasel8.240c.png
new file mode 100644
index 00000000..a1fed2c0
--- /dev/null
+++ b/leptonica/prog/weasel8.240c.png
Binary files differ
diff --git a/leptonica/prog/weasel8.5g.nocmap.png b/leptonica/prog/weasel8.5g.nocmap.png
new file mode 100644
index 00000000..03e61cad
--- /dev/null
+++ b/leptonica/prog/weasel8.5g.nocmap.png
Binary files differ
diff --git a/leptonica/prog/weasel8.5g.png b/leptonica/prog/weasel8.5g.png
new file mode 100644
index 00000000..145a84e1
--- /dev/null
+++ b/leptonica/prog/weasel8.5g.png
Binary files differ
diff --git a/leptonica/prog/weasel8.png b/leptonica/prog/weasel8.png
new file mode 100644
index 00000000..a01dfad6
--- /dev/null
+++ b/leptonica/prog/weasel8.png
Binary files differ
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
new file mode 100644
index 00000000..b1d299b4
--- /dev/null
+++ b/leptonica/prog/wet-day.jpg
Binary files differ
diff --git a/leptonica/prog/witten.tif b/leptonica/prog/witten.tif
new file mode 100644
index 00000000..29685d94
--- /dev/null
+++ b/leptonica/prog/witten.tif
Binary files differ
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
new file mode 100644
index 00000000..6a3ed9bf
--- /dev/null
+++ b/leptonica/prog/words.15.tif
Binary files differ
diff --git a/leptonica/prog/words.44.tif b/leptonica/prog/words.44.tif
new file mode 100644
index 00000000..4e593543
--- /dev/null
+++ b/leptonica/prog/words.44.tif
Binary files differ
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
new file mode 100644
index 00000000..9a06cadd
--- /dev/null
+++ b/leptonica/prog/wyom.jpg
Binary files differ
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
new file mode 100644
index 00000000..a2924414
--- /dev/null
+++ b/leptonica/prog/zanotti-78.jpg
Binary files differ
diff --git a/leptonica/prog/zier.jpg b/leptonica/prog/zier.jpg
new file mode 100644
index 00000000..bd00825e
--- /dev/null
+++ b/leptonica/prog/zier.jpg
Binary files differ