contrek 1.0.4 → 1.0.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (107) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +4 -3
  3. data/CHANGELOG.md +21 -0
  4. data/Gemfile.lock +4 -4
  5. data/README.md +34 -30
  6. data/Rakefile +3 -0
  7. data/contrek.gemspec +7 -4
  8. data/ext/cpp_polygon_finder/PolygonFinder/Makefile +44 -0
  9. data/ext/cpp_polygon_finder/PolygonFinder/images/sample_10240x10240.png +0 -0
  10. data/ext/cpp_polygon_finder/PolygonFinder/src/Main.cpp +14 -5
  11. data/ext/cpp_polygon_finder/PolygonFinder/src/Tests.cpp +136 -15
  12. data/ext/cpp_polygon_finder/PolygonFinder/src/Tests.h +5 -4
  13. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/CpuTimer.h +44 -0
  14. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/bitmaps/Bitmap.cpp +8 -0
  15. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/bitmaps/Bitmap.h +3 -4
  16. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/bitmaps/FastPngBitmap.cpp +63 -573
  17. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/bitmaps/FastPngBitmap.h +17 -18
  18. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/bitmaps/RemoteFastPngBitmap.cpp +22 -5
  19. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/bitmaps/RemoteFastPngBitmap.h +4 -8
  20. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/bitmaps/spng.c +6980 -0
  21. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/bitmaps/spng.h +537 -0
  22. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/FinderUtils.cpp +101 -0
  23. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/FinderUtils.h +16 -0
  24. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/List.cpp +0 -3
  25. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/List.h +4 -7
  26. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/Lists.cpp +13 -13
  27. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/Lists.h +5 -7
  28. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/Node.cpp +47 -41
  29. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/Node.h +15 -10
  30. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/NodeCluster.cpp +181 -178
  31. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/NodeCluster.h +19 -20
  32. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/Polygon.h +20 -0
  33. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/PolygonFinder.cpp +52 -137
  34. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/PolygonFinder.h +85 -16
  35. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/RectBounds.h +39 -0
  36. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/ClippedPolygonFinder.cpp +14 -0
  37. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/ClippedPolygonFinder.h +17 -0
  38. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Cluster.cpp +117 -0
  39. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Cluster.h +32 -0
  40. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Cursor.cpp +344 -0
  41. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Cursor.h +46 -0
  42. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/EndPoint.cpp +14 -0
  43. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/EndPoint.h +22 -0
  44. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/FakeCluster.cpp +13 -0
  45. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/FakeCluster.h +17 -0
  46. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Finder.cpp +138 -0
  47. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Finder.h +52 -0
  48. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Hub.cpp +23 -0
  49. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Hub.h +40 -0
  50. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Part.cpp +70 -0
  51. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Part.h +47 -0
  52. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/PartPool.cpp +24 -0
  53. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/PartPool.h +23 -0
  54. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Partitionable.cpp +182 -0
  55. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Partitionable.h +30 -0
  56. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Polyline.cpp +108 -0
  57. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Polyline.h +52 -0
  58. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Poolable.cpp +59 -0
  59. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Poolable.h +52 -0
  60. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Position.cpp +31 -0
  61. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Position.h +25 -0
  62. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Queue.h +36 -0
  63. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Queueable.h +230 -0
  64. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Sequence.cpp +35 -0
  65. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Sequence.h +20 -0
  66. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Shape.cpp +26 -0
  67. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Shape.h +23 -0
  68. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Tile.cpp +105 -0
  69. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Tile.h +56 -0
  70. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/matchers/Matcher.cpp +3 -3
  71. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/matchers/Matcher.h +5 -8
  72. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/matchers/RGBMatcher.h +3 -7
  73. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/matchers/RGBNotMatcher.cpp +2 -2
  74. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/matchers/RGBNotMatcher.h +4 -8
  75. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/matchers/ValueNotMatcher.cpp +2 -2
  76. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/matchers/ValueNotMatcher.h +3 -7
  77. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/reducers/LinearReducer.cpp +23 -15
  78. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/reducers/LinearReducer.h +6 -8
  79. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/reducers/Reducer.cpp +2 -5
  80. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/reducers/Reducer.h +4 -8
  81. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/reducers/UniqReducer.cpp +9 -12
  82. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/reducers/UniqReducer.h +3 -7
  83. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/reducers/VisvalingamReducer.cpp +26 -27
  84. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/reducers/VisvalingamReducer.h +76 -87
  85. data/ext/cpp_polygon_finder/cpp_polygon_finder.cpp +64 -32
  86. data/ext/cpp_polygon_finder/extconf.rb +14 -0
  87. data/lib/contrek/bitmaps/sample_generator.rb +56 -0
  88. data/lib/contrek/cpp/cpp_concurrent_finder.rb +9 -0
  89. data/lib/contrek/finder/bounds.rb +17 -0
  90. data/lib/contrek/finder/concurrent/cluster.rb +2 -2
  91. data/lib/contrek/finder/concurrent/cursor.rb +8 -8
  92. data/lib/contrek/finder/concurrent/finder.rb +10 -9
  93. data/lib/contrek/finder/concurrent/part.rb +2 -2
  94. data/lib/contrek/finder/concurrent/partitionable.rb +1 -1
  95. data/lib/contrek/finder/concurrent/polyline.rb +17 -15
  96. data/lib/contrek/finder/concurrent/sequence.rb +11 -0
  97. data/lib/contrek/finder/concurrent/tile.rb +3 -3
  98. data/lib/contrek/finder/node_cluster.rb +16 -8
  99. data/lib/contrek/finder/polygon_finder.rb +1 -4
  100. data/lib/contrek/version.rb +1 -1
  101. data/lib/contrek.rb +9 -1
  102. metadata +62 -15
  103. data/ext/cpp_polygon_finder/PolygonFinder/.cproject +0 -136
  104. data/ext/cpp_polygon_finder/PolygonFinder/.project +0 -27
  105. data/ext/cpp_polygon_finder/PolygonFinder/.settings/org.eclipse.ltk.core.refactoring.prefs +0 -2
  106. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/bitmaps/PngBitmap.cpp +0 -48
  107. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/bitmaps/PngBitmap.h +0 -32
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d96b6c7ae60aefc5e7afed98c4619cf4e77cd0a226f2994d4dbc4f91952b315c
4
- data.tar.gz: 336e0c2ca0f36f4608fd1547bdbcb27b5d78624a288d329a003e54412d6ce287
3
+ metadata.gz: 9a9bb4f4ff327f04f6877b024c533c8d6d7b6f0ecfc7ad0ae51e6ad05a84438c
4
+ data.tar.gz: 9bf8394de257d8a3832400936992d5f848e015d10e389ce986347668d4f53b23
5
5
  SHA512:
6
- metadata.gz: 615ae9e725c5fa149bb3f9f30be365863d348962f26fbda8610285a8e096b80dc6d564438480a8b783dc607c5bc4b3c66bb9bc5ca808d2783c494b74e3b3b7be
7
- data.tar.gz: 1d2fc4088a58c1ffe2dbe46c08b67a728bf3eacce02ead907aa7b871565982e3161681205930de777bc7af3e702310dd3030fb961c0cbd71fb15280704e37da3
6
+ metadata.gz: c9640a27737904a3ab5eb4b4f1357262ba05dac579c743ba653ef9be0ed73a90648adc5af0d3c5ff9629f04aa12ca27b5f7e703855805488690d604dd7a82572
7
+ data.tar.gz: 656e58e008e3a6b912f5b99ed1b90dbe9b673dab08815177d14ec5d3de3a9380359b70d259517bdd2278b5f327db86bb448293d72555534205751e04a49378b1
data/.gitignore CHANGED
@@ -3,9 +3,10 @@
3
3
  # rspec failure tracking
4
4
  .rspec_status
5
5
 
6
- /ext/cpp_polygon_finder/PolygonFinder/Debug/*
7
- /ext/cpp_polygon_finder/.metadata/
8
- /ext/cpp_polygon_finder/RemoteSystemsTempFiles/
6
+ /ext/cpp_polygon_finder/PolygonFinder/build/
7
+ /ext/cpp_polygon_finder/PolygonFinder/contrek
8
+ /ext/cpp_polygon_finder/PolygonFinder/build/*.o
9
+ /ext/cpp_polygon_finder/PolygonFinder/build/*.d
9
10
  /ext/cpp_polygon_finder/Makefile
10
11
  /ext/cpp_polygon_finder/cpp_polygon_finder.o
11
12
  /ext/cpp_polygon_finder/cpp_polygon_finder.so
data/CHANGELOG.md ADDED
@@ -0,0 +1,21 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ ## [1.0.1] - 2025-05-18
6
+ ### Added
7
+ - The project is made available as a Ruby gem
8
+
9
+ ## [1.0.3] - 2025-11-15
10
+ ### Changed
11
+ - Minor changes
12
+
13
+ ## [1.0.5] - 2025-11-16
14
+ ### Added
15
+ - Added ruby side multithreading supports
16
+
17
+ ## [1.0.6] - 2026-01-06
18
+ ### Added
19
+ - Added C++ multithreading supports
20
+ - Optimized old just present C++ code
21
+ - Removed Png++ dependency in place of libspn
data/Gemfile.lock CHANGED
@@ -1,10 +1,10 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- contrek (1.0.4)
4
+ contrek (1.0.5)
5
5
  chunky_png (~> 1.4)
6
6
  concurrent-ruby (~> 1.3.5)
7
- rice (~> 4.5)
7
+ rice (= 4.5.0)
8
8
 
9
9
  GEM
10
10
  remote: https://rubygems.org/
@@ -83,9 +83,9 @@ PLATFORMS
83
83
 
84
84
  DEPENDENCIES
85
85
  contrek!
86
- curses (>= 1.5.3)
86
+ curses (~> 1.5, >= 1.5.3)
87
87
  rspec (~> 3.12)
88
- ruby-prof (>= 1.7.2)
88
+ ruby-prof (~> 1.7, >= 1.7.2)
89
89
  standard (~> 1.51)
90
90
 
91
91
  BUNDLED WITH
data/README.md CHANGED
@@ -1,8 +1,8 @@
1
1
  # Contrek
2
- Contrek is a Ruby library (C++ powered) to trace png bitmap areas polygonal contours. Manages png images usign png++ and picoPNG (version 20101224) libraries and may work multithreading.
2
+ Contrek is a Ruby library (C++ powered) to trace png bitmap areas polygonal contours. Manages png images usign libspng (version 0.7.4) library. May work multithreading.
3
3
 
4
4
  ## About Contrek library
5
- Contrek (**con**tour **trek**king) simply scans your png bitmap and returns shape contour as close polygonal lines, both for the external and internal sides. It can compute the nesting level of the polygons found with a tree structure. It supports various levels and modes of compression and approximation of the found coordinates. It is capable of multithreaded processing (currently only on the Ruby side), splitting the image into vertical strips and recombining the coordinates in pairs.
5
+ Contrek (**con**tour **trek**king) simply scans your png bitmap and returns shape contour as close polygonal lines, both for the external and internal sides. It can compute the nesting level of the polygons found with a tree structure. It supports various levels and modes of compression and approximation of the found coordinates. It is capable of multithreaded processing, splitting the image into vertical strips and recombining the coordinates in pairs.
6
6
 
7
7
  In the following image all the non-white pixels have been examined and the result is the red polygon for the outer contour and the green one for the inner one
8
8
  ![alt text](contrek.png "Contour tracing")
@@ -19,21 +19,7 @@ And then execute:
19
19
 
20
20
  bundle install
21
21
 
22
- This will install the gem and compile the native extensions. If you get
23
- `fatal error: png++/png.hpp: No such file or directory`
24
-
25
- means that you have to install png++ on your system which Contrek C++ code depends on; visit http://download.savannah.nongnu.org/releases/pngpp/
26
- Grab the lattest file (here 0.2.9)
27
- Go to download directory. Extract to /usr/src with
28
-
29
- sudo tar -zxf png++-0.2.9.tar.gz -C /usr/src
30
- Change directory to
31
-
32
- cd /usr/src/png++-0.2.9/
33
- Do make and make install
34
-
35
- make
36
- make install
22
+ This will install the gem and compile the native extensions.
37
23
 
38
24
  ## Usage
39
25
  In this example we are asking to examine any pixel that does not have the red color.
@@ -88,8 +74,6 @@ png_bitmap = CPPRemotePngBitMap.new("iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcS
88
74
 
89
75
  Multithreaded contour processing is supported. However, on Ruby MRI (the standard Ruby implementation, at least up to 3.x), the Global Interpreter Lock (GIL) prevents more than one thread from executing Ruby code simultaneously. As a consequence, execution remains effectively serialized even on multicore systems, unless the gem is used under JRuby or TruffleRuby (not tested).
90
76
 
91
- The actual multithreaded implementation effort is therefore focused on the native C++ component, which is currently under development and is expected to provide substantially higher performance.
92
-
93
77
  ```ruby
94
78
  result = Contrek.contour!(
95
79
  png_file_path: "./spec/files/images/rectangle_8x8.png",
@@ -114,7 +98,26 @@ Regarding multithreading:
114
98
 
115
99
  - The treemap option is currently ignored (multithreaded treemap support will be introduced in upcoming revisions).
116
100
 
101
+ By not declaring native option CPP Multithreading optimized code is used. In the above example a [105 MP image](spec/files/images/sample_10240x10240.png) is examined by 2 thread working on 2 tiles (total compute time about 2 secs).
117
102
 
103
+ ```ruby
104
+ result = Contrek.contour!(
105
+ png_file_path: "./spec/files/images/sample_10240x10240.png",
106
+ options: {
107
+ number_of_threads: 2,
108
+ class: "value_not_matcher",
109
+ color: {r: 255, g: 255, b: 255, a: 255},
110
+ finder: {number_of_tiles: 2, compress: {uniq: true}}
111
+ }
112
+ )
113
+ puts result[:benchmarks].inspect
114
+
115
+ {"compress"=>14.596786999999999,
116
+ "init"=>2078.745861,
117
+ "inner"=>1183.143734,
118
+ "outer"=>118.94489599999999,
119
+ "total"=>2093.342648}
120
+ ```
118
121
  ## Multithreaded approach
119
122
 
120
123
  The multithreaded contour-tracing implementation operates as follows:
@@ -151,22 +154,23 @@ This process is applied recursively, merging bands until a single final band rem
151
154
  One of the most complex test you can find under the spec folder is named "scans poly 1200x800", scans this [image](spec/files/images/sample_1200x800.png) computing coordinates to draw polygons drawn in this [result](spec/files/stored_samples/sample_1200x800.png).
152
155
  On pure ruby implementation kept time
153
156
  ```ruby
154
- { :scan=>1063.146,
155
- :build_tangs_sequence=>287.114,
156
- :plot=>79.329,
157
- :compress=>0.001,
158
- :total=>1429.59}
157
+ { :scan=>801.494,
158
+ :build_tangs_sequence=>160.491,
159
+ :plot=>86.633,
160
+ :compress=>0.002,
161
+ :total=>1048.62}
159
162
  ```
160
163
  This the one for the native C++
161
164
  ```ruby
162
- { :scan=>43.521,
163
- :build_tangs_sequence=>44.105,
164
- :plot=>35.718,
165
- :compress=>0.001,
166
- :total=>123.34500000000001}
165
+ { scan: 7.1146329999999995,
166
+ build_tangs_sequence: 3.063812,
167
+ plot: 4.474851999999999,
168
+ compress: 0.0031999999999999997
169
+ total: 14.656496999999998
170
+ }
167
171
  ```
168
172
 
169
- About 10 x faster. Times are in microseconds; system: AMD Ryzen 7 3700X 8-Core Processor (BogoMIPS: 7199,99).
173
+ About 75x faster. Times are in microseconds; system: AMD Ryzen 7 3700X 8-Core Processor (BogoMIPS: 7199,99) on Ubuntu distro.
170
174
 
171
175
  ## License
172
176
 
data/Rakefile CHANGED
@@ -3,8 +3,11 @@ require "rake"
3
3
  desc "compiles c++ extension"
4
4
  task :compile do |t|
5
5
  Dir.chdir("ext/cpp_polygon_finder") do
6
+ Dir.glob("**/*.o").each { |f| File.delete(f) }
7
+ File.delete("Makefile") if File.exist?("Makefile")
6
8
  system "ruby", "extconf.rb"
7
9
  system "make", "-B"
10
+ Dir.glob("**/*.o").each { |f| File.delete(f) }
8
11
  system "cp cpp_polygon_finder.so ./../../lib"
9
12
  end
10
13
  end
data/contrek.gemspec CHANGED
@@ -4,8 +4,8 @@ require "contrek/version"
4
4
  Gem::Specification.new do |s|
5
5
  s.name = "contrek"
6
6
  s.version = Contrek::VERSION
7
- s.summary = "Png image shapes contour finder"
8
- s.description = "Contrek is a Ruby library (C++ powered) to trace png bitmap areas polygonal contours."
7
+ s.summary = "Fast PNG contour tracing and shape detection for Ruby"
8
+ s.description = "Contrek is a Ruby gem with a C++ core for fast contour tracing and edge detection in PNG images. It extracts polygonal contours from bitmap shapes, enabling image processing, shape analysis, and raster-to-vector workflows such as PNG to SVG conversion."
9
9
  s.authors = ["Emanuele Cesaroni"]
10
10
  s.email = "cesaroni.emanuele77@gmail.com"
11
11
  s.homepage = "https://github.com/runout77/contrek"
@@ -14,7 +14,10 @@ Gem::Specification.new do |s|
14
14
  `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(pkg|spec)/}) }
15
15
  end
16
16
  s.metadata = {
17
- "homepage_uri" => "https://github.com/runout77/contrek"
17
+ "homepage_uri" => "https://github.com/runout77/contrek",
18
+ "source_code_uri" => "https://github.com/runout77/contrek",
19
+ "documentation_uri" => "https://github.com/runout77/contrek#readme",
20
+ "changelog_uri" => "https://github.com/runout77/contrek/blob/main/CHANGELOG.md"
18
21
  }
19
22
 
20
23
  s.add_development_dependency "rspec", "~> 3.12"
@@ -24,7 +27,7 @@ Gem::Specification.new do |s|
24
27
 
25
28
  s.add_dependency "chunky_png", "~> 1.4"
26
29
  s.add_dependency "concurrent-ruby", "~> 1.3.5"
27
- s.add_dependency "rice", "~> 4.5"
30
+ s.add_dependency "rice", "= 4.5.0"
28
31
 
29
32
  s.required_ruby_version = ">= 3.0.0"
30
33
 
@@ -0,0 +1,44 @@
1
+ CXX = g++
2
+ CXXFLAGS = -Wall -Wextra -std=c++17 -Isrc -MMD -MP -pthread -g \
3
+ -fno-omit-frame-pointer -fsanitize=address,undefined \
4
+ -O0
5
+ LDFLAGS = -lpng -pthread -lz -fsanitize=address,undefined
6
+
7
+ # valgrinf or perf setup
8
+ #CXXFLAGS = -Wall -Wextra -std=c++17 -Isrc -MMD -MP -pthread -g -fno-omit-frame-pointer -march=native -DNDEBUG -O3
9
+ #LDFLAGS = -lpng -pthread -lz
10
+
11
+ # best performances
12
+ CXXFLAGS = -Wall -Wextra -std=c++17 -Isrc -MMD -MP -pthread -g -march=native -DNDEBUG -Ofast -flto
13
+ LDFLAGS = -lpng -pthread -lz -flto=auto
14
+
15
+ SRC = $(shell find src -name '*.cpp')
16
+ C_SRC = $(shell find src -name 'spng.c')
17
+
18
+ OBJ = $(patsubst src/%.cpp, build/%.o, $(SRC))
19
+ OBJ += $(patsubst src/%.c, build/%.o, $(C_SRC))
20
+
21
+ DEPS = $(OBJ:.o=.d)
22
+
23
+ EXEC = contrek
24
+
25
+ all: $(EXEC)
26
+
27
+ $(EXEC): $(OBJ)
28
+ $(CXX) $(CXXFLAGS) $(OBJ) -o $@ -Wl,--no-as-needed $(LDFLAGS)
29
+
30
+ build/%.o: src/%.cpp
31
+ @mkdir -p $(dir $@)
32
+ $(CXX) $(CXXFLAGS) -c $< -o $@
33
+
34
+ build/%.o: src/%.c
35
+ @mkdir -p $(dir $@)
36
+ $(CC) -O3 -march=native -fPIC -c $< -o $@
37
+
38
+ -include $(DEPS)
39
+
40
+ clean:
41
+ rm -rf build $(EXEC)
42
+
43
+ run: all
44
+ ./$(EXEC)
@@ -6,14 +6,13 @@
6
6
  // Description :
7
7
  //============================================================================
8
8
 
9
- #include <iostream>
10
9
  #include <string.h>
10
+ #include <iostream>
11
11
  #include <list>
12
12
  #include <map>
13
13
  #include <string>
14
14
  #include "polygon/finder/PolygonFinder.h"
15
15
  #include "polygon/bitmaps/Bitmap.h"
16
- #include "polygon/bitmaps/PngBitmap.h"
17
16
  #include "polygon/bitmaps/FastPngBitmap.h"
18
17
  #include "polygon/bitmaps/RemoteFastPngBitmap.h"
19
18
  #include "polygon/matchers/Matcher.h"
@@ -22,12 +21,21 @@
22
21
  #include "polygon/matchers/ValueNotMatcher.h"
23
22
  #include "polygon/finder/optionparser.h"
24
23
  #include "Tests.h"
25
- using namespace std;
24
+ #include "polygon/CpuTimer.h"
26
25
 
27
26
  int main() {
28
- Tests *test_suite = new Tests;
29
- test_suite->test_a();
27
+ CpuTimer cpu_timer;
28
+ Tests test_suite;
29
+ cpu_timer.start();
30
+
31
+ // test_suite.test_a();
32
+ // test_suite.test_b();
33
+ // test_suite.test_c();
34
+ // test_suite.test_d();
35
+ test_suite.test_e();
36
+ std::cout << "compute time =" << cpu_timer.stop() << std::endl;
30
37
 
38
+ /*
31
39
  FastPngBitmap png_bitmap("images/labyrinth.png");
32
40
  std::cout << "image_w=" << png_bitmap.w() << " image_h=" << png_bitmap.h() << std::endl;
33
41
  std::cout << "load_error=" << png_bitmap.error() << std::endl;
@@ -37,5 +45,6 @@ int main() {
37
45
  RemoteFastPngBitmap bitmap(&data_url);
38
46
  std::cout << "image_w=" << bitmap.w() << " image_h=" << bitmap.h() << std::endl;
39
47
  std::cout << "load_error=" << bitmap.error() << std::endl;
48
+ */
40
49
  return 0;
41
50
  }
@@ -7,15 +7,15 @@
7
7
  */
8
8
 
9
9
  #include "Tests.h"
10
- #include <iostream>
11
10
  #include <string.h>
11
+ #include <iostream>
12
12
  #include <list>
13
13
  #include <map>
14
14
  #include <vector>
15
15
  #include <string>
16
16
  #include "polygon/finder/PolygonFinder.h"
17
+ #include "polygon/finder/concurrent/ClippedPolygonFinder.h"
17
18
  #include "polygon/bitmaps/Bitmap.h"
18
- #include "polygon/bitmaps/PngBitmap.h"
19
19
  #include "polygon/bitmaps/FastPngBitmap.h"
20
20
  #include "polygon/bitmaps/RemoteFastPngBitmap.h"
21
21
  #include "polygon/matchers/Matcher.h"
@@ -23,7 +23,10 @@
23
23
  #include "polygon/matchers/RGBNotMatcher.h"
24
24
  #include "polygon/matchers/ValueNotMatcher.h"
25
25
  #include "polygon/finder/optionparser.h"
26
- using namespace std;
26
+ #include "polygon/finder/concurrent/Finder.h"
27
+ #include "polygon/finder/concurrent/Sequence.h"
28
+ #include "polygon/finder/concurrent/Position.h"
29
+ #include "polygon/finder/Polygon.h"
27
30
 
28
31
  Tests::Tests() {
29
32
  }
@@ -32,7 +35,7 @@ Tests::~Tests() {
32
35
  }
33
36
 
34
37
  void Tests::test_a()
35
- { string chunk =
38
+ { std::string chunk =
36
39
  "0000000000000000"\
37
40
  "00000000000B0000"\
38
41
  "000000AAAAAA0000"\
@@ -49,21 +52,139 @@ void Tests::test_a()
49
52
  std::vector<int> outer_array{11, 1, 6, 2, 6, 3, 6, 4, 6, 5, 11, 5, 11, 4, 11, 3, 11, 2, 11, 1};
50
53
  std::vector<int> inner_array{7, 3, 10, 3, 10, 4, 7, 4};
51
54
  std::vector<int> array_compare;
52
- for (std::list<std::map<std::string, std::list<std::list<Point*>*>>>::iterator x = o->polygons.begin(); x != o->polygons.end(); ++x)
53
- { for (std::list<Point*>::iterator y = (*x)["outer"].front()->begin(); y != (*x)["outer"].front()->end(); ++y)
54
- { array_compare.push_back((*y)->x);
55
- array_compare.push_back((*y)->y);
55
+
56
+ for (const auto& x : o->polygons)
57
+ { for (const Point* p : x.outer) {
58
+ array_compare.push_back(p->x);
59
+ array_compare.push_back(p->y);
56
60
  }
57
- if (outer_array != array_compare) throw;
61
+ if (outer_array != array_compare) throw std::runtime_error("Wrong OUTER results!");
58
62
  array_compare.clear();
59
-
60
- for (std::list<std::list<Point*>*>::iterator z = (*x)["inner"].begin(); z != (*x)["inner"].end(); ++z)
61
- { for (std::list<Point*>::iterator y = (*z)->begin(); y != (*z)->end(); ++y)
62
- { array_compare.push_back((*y)->x);
63
- array_compare.push_back((*y)->y);
63
+ for (const auto& z : x.inner)
64
+ { for (const Point* y : z)
65
+ { array_compare.push_back(y->x);
66
+ array_compare.push_back(y->y);
64
67
  }
65
68
  }
66
- if (inner_array != array_compare) throw;
69
+ if (inner_array != array_compare) throw std::runtime_error("Wrong INNER results!");
67
70
  }
71
+ delete o;
72
+ }
73
+
74
+ void Tests::test_b()
75
+ { std::string chunk =
76
+ // "0123456789012345"
77
+ " XXXXXXXXXXX "\
78
+ " XX XX "\
79
+ " XX XX "\
80
+ " XX XX "\
81
+ " XXXXXXXXXXX ";
82
+ // "0123456789012345"
83
+ /*chunk = " XXXXXXXXXXX "\
84
+ " XX XX XX "\
85
+ " XX XX XX "\
86
+ " XX XX XX "\
87
+ " XXXXXXXXXXX ";*/
88
+
89
+ std::vector<std::string> arguments = {"--versus=o", "--number_of_tiles=2", "--compress_uniq", "--compress_linear", "--treemap"};
90
+ ValueNotMatcher matcher(' ');
91
+ Bitmap b(chunk, 16);
92
+
93
+ /*ClippedPolygonFinder pl(&b, &matcher, 0, 16, &arguments);
94
+ ProcessResult *pr = pl.process_info();
95
+ pr->print_polygons();
96
+ delete pr;*/
97
+
98
+ Finder concurrentFinder(2, &b, &matcher, &arguments);
99
+ ProcessResult *pro = concurrentFinder.process_info();
100
+ pro->print_polygons();
101
+ delete pro;
102
+ }
103
+
104
+ void Tests::test_c()
105
+ { Sequence sequence;
106
+ Point* p1 = new Point({1, 1});
107
+ Point* p2 = new Point({2, 2});
108
+ Point* p3 = new Point({3, 3});
109
+
110
+ Hub* hub = new Hub(4, 4); // coordinate 0 -> 3 sia x che y, matrice di 4 * 4
111
+
112
+ Position* pos1 = new Position(hub, p1);
113
+ Position* pos2 = new Position(hub, p2);
114
+ Position* pos3 = new Position(hub, p3);
115
+
116
+ if (sequence.size != 0) throw std::runtime_error("Wrong initial sequence size");
117
+ sequence.add(pos1);
118
+ sequence.add(pos2);
119
+ sequence.add(pos3);
120
+ if (sequence.size != 3) throw std::runtime_error("Wrong sequence size");
121
+
122
+ // iterator() initially gives head
123
+ Point* head = sequence.head->payload;
124
+ if (head != p1) throw std::runtime_error("Wrong head");
125
+ if (sequence.iterator()->payload != p1) throw std::runtime_error("Wrong iterator to head");
126
+ if (sequence.iterator() != pos1) throw std::runtime_error("Wrong iterator to head");
127
+ // forward!
128
+ sequence.forward();
129
+ if (sequence.iterator()->payload != p2) throw std::runtime_error("Wrong iterator to position 2");
130
+ if (sequence.iterator() != pos2) throw std::runtime_error("Wrong iterator to position 2");
131
+ // forward!
132
+ sequence.forward();
133
+ if (sequence.iterator()->payload != p3) throw std::runtime_error("Wrong iterator to position 3");
134
+ if (sequence.iterator() != pos3) throw std::runtime_error("Wrong iterator to position 3");
135
+
136
+ // forward returns nullptr when no more items are present
137
+ sequence.forward();
138
+ if (sequence.iterator() != nullptr) throw std::runtime_error("Wrong iterator to end of list");
139
+
140
+ // rewind
141
+ sequence.rewind();
142
+ if (sequence.iterator()->payload != p1) throw std::runtime_error("Wrong iterator to head");
143
+
144
+ delete p1;
145
+ delete p2;
146
+ delete p3;
147
+
148
+ delete hub;
149
+
150
+ delete pos1;
151
+ delete pos2;
152
+ delete pos3;
68
153
  }
69
154
 
155
+ void Tests::test_d()
156
+ { CpuTimer cpu_timer;
157
+ cpu_timer.start();
158
+ FastPngBitmap png_bitmap("images/sample_10240x10240.png");
159
+ // FastPngBitmap png_bitmap("images/labyrinth.png");
160
+ std::cout << "image_w=" << png_bitmap.w() << " image_h=" << png_bitmap.h() << std::endl;
161
+ std::cout << "immagine =" << cpu_timer.stop() << std::endl;
162
+
163
+ int color = png_bitmap.value_at(0, 0);
164
+ std::cout << "color =" << color << std::endl;
165
+ RGBNotMatcher not_matcher(color);
166
+
167
+ std::vector<std::string> arguments = {"--versus=a", "--compress_uniq"};
168
+ PolygonFinder pl(&png_bitmap, &not_matcher, nullptr, &arguments);
169
+ ProcessResult *o = pl.process_info();
170
+ o->print_info();
171
+ delete o;
172
+ }
173
+
174
+ void Tests::test_e()
175
+ { CpuTimer cpu_timer;
176
+ cpu_timer.start();
177
+ FastPngBitmap png_bitmap("images/sample_10240x10240.png");
178
+ // FastPngBitmap png_bitmap("images/sample_1024x1024.png");
179
+ std::cout << "immagine =" << cpu_timer.stop() << std::endl;
180
+
181
+ int color = png_bitmap.value_at(0, 0);
182
+ std::cout << "color =" << color << std::endl;
183
+ RGBNotMatcher not_matcher(color);
184
+
185
+ std::vector<std::string> arguments = {"--versus=a", "--compress_uniq", "--number_of_tiles=2"};
186
+ Finder pl(2, &png_bitmap, &not_matcher, &arguments);
187
+ ProcessResult *o = pl.process_info();
188
+ o->print_info();
189
+ delete o;
190
+ }
@@ -6,14 +6,15 @@
6
6
  * Copyright 2025 Emanuele Cesaroni
7
7
  */
8
8
 
9
- #ifndef TESTS_H_
10
- #define TESTS_H_
9
+ #pragma once
11
10
 
12
11
  class Tests {
13
12
  public:
14
13
  Tests();
15
14
  virtual ~Tests();
16
15
  virtual void test_a();
16
+ virtual void test_b();
17
+ virtual void test_c();
18
+ virtual void test_d();
19
+ virtual void test_e();
17
20
  };
18
-
19
- #endif /* TESTS_H_ */
@@ -0,0 +1,44 @@
1
+ /*
2
+ * CpuTimer.h
3
+ *
4
+ * Created on: 23 nov 2025
5
+ * Author: ema
6
+ * Copyright 2025 Emanuele Cesaroni
7
+ */
8
+
9
+ #pragma once
10
+ #include <chrono>
11
+
12
+ class CpuTimer {
13
+ using Clock = std::chrono::steady_clock;
14
+ std::chrono::time_point<Clock> _start;
15
+ bool _running = false;
16
+
17
+ public:
18
+ void start() {
19
+ _start = Clock::now();
20
+ _running = true;
21
+ }
22
+
23
+ double stop() {
24
+ if (!_running) return 0.0;
25
+ auto duration = elapsed_ms();
26
+ _running = false;
27
+ return duration;
28
+ }
29
+
30
+ double elapsed_ms() const {
31
+ if (!_running) return 0.0;
32
+ auto end = Clock::now();
33
+ std::chrono::duration<double, std::milli> diff = end - _start;
34
+ return diff.count();
35
+ }
36
+
37
+ void reset() {
38
+ _running = false;
39
+ }
40
+
41
+ bool is_running() const {
42
+ return _running;
43
+ }
44
+ };
@@ -50,3 +50,11 @@ bool Bitmap::pixel_match(int x, int y, Matcher *matcher)
50
50
  void Bitmap::clear(char value = '0')
51
51
  { for (unsigned int i = 0; i < raw.length(); i++) raw[i] = value;
52
52
  }
53
+
54
+ const unsigned char* Bitmap::get_row_ptr(int y) const {
55
+ return reinterpret_cast<const unsigned char*>(raw.data()) + (y * module);
56
+ }
57
+
58
+ int Bitmap::get_bytes_per_pixel() const {
59
+ return 1;
60
+ }
@@ -6,8 +6,7 @@
6
6
  * Copyright 2025 Emanuele Cesaroni
7
7
  */
8
8
 
9
- #ifndef POLYGON_BITMAPS_BITMAP_H_
10
- #define POLYGON_BITMAPS_BITMAP_H_
9
+ #pragma once
11
10
  #include <string>
12
11
 
13
12
  class Matcher;
@@ -27,6 +26,6 @@ class Bitmap {
27
26
  void print();
28
27
  void clear(char value);
29
28
  virtual bool pixel_match(int x, int y, Matcher *matcher);
29
+ virtual const unsigned char* get_row_ptr(int y) const;
30
+ virtual int get_bytes_per_pixel() const;
30
31
  };
31
-
32
- #endif /* POLYGON_BITMAPS_BITMAP_H_ */