contrek 1.2.5 → 1.2.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +6 -0
- data/Gemfile.lock +1 -1
- data/ext/cpp_polygon_finder/PolygonFinder/src/Tests.cpp +20 -12
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/bitmaps/RawBitmap.cpp +4 -4
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/bitmaps/RawBitmap.h +1 -1
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/bitmaps/spng.c +17 -1
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/PolygonFinder.h +16 -29
- data/lib/contrek/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: ca0c4f7e37692b2d2e5b17556ed67bee4b624511ddf1dc3865ecf910e8f46aeb
|
|
4
|
+
data.tar.gz: 66b9af71020dc6a86da1abace1d0467807b9212e207b71a7f6337b2257a34192
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 63ba135c86c7849fda12e542af23a2746681f8aade888daa9269438c1601e8184215b3fe5081ee9caabce923e7dfafd8bcc3613fb06cf2ec9997193ff831e5c7
|
|
7
|
+
data.tar.gz: dd691e542a8722be9532d3c0f206d4b2a2499874f0be52786c99822036d3e0e463ffb6d301bceae44e8f487f434eeff98c9a931cffe27eab3ed5d249daf060e5
|
data/CHANGELOG.md
CHANGED
|
@@ -106,3 +106,9 @@ All notable changes to this project will be documented in this file.
|
|
|
106
106
|
## [1.2.5] - 2026-05-27
|
|
107
107
|
### Changed
|
|
108
108
|
- **Refactored `ProcessResult.clone()`:** Switched from fragmented dynamic allocation to a contiguous `std::vector` with explicit `.reserve()`. Eliminates heap fragmentation during high-res streaming.
|
|
109
|
+
|
|
110
|
+
## [1.2.6] - 2026-05-31
|
|
111
|
+
### Changed
|
|
112
|
+
- **Refactored `spng.c` function `rgb8_row_to_rgba8`:** Extended a loop counter to `size_t` (previously limited to `uint32_t`), which was causing segmentation faults when reading massive images (e.g., 81920x81920).
|
|
113
|
+
- **Refactored `RawBitmap.define` function:** Updated area and size calculations to use full 64-bit integers.
|
|
114
|
+
- **Refactored `PolygonFinder.to_svg_stream()` function:** Optimized performance to efficiently handle massive SVG streams of 2 GB and beyond.
|
data/Gemfile.lock
CHANGED
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
#include "Tests.h"
|
|
11
|
+
#include <sys/resource.h>
|
|
11
12
|
#include <string.h>
|
|
12
13
|
#include <iostream>
|
|
13
14
|
#include <list>
|
|
@@ -17,7 +18,6 @@
|
|
|
17
18
|
#include <cstring>
|
|
18
19
|
#include <algorithm>
|
|
19
20
|
#include <cstdio>
|
|
20
|
-
#include <sys/resource.h>
|
|
21
21
|
|
|
22
22
|
#include "polygon/finder/PolygonFinder.h"
|
|
23
23
|
#include "polygon/finder/concurrent/ClippedPolygonFinder.h"
|
|
@@ -279,7 +279,7 @@ double get_peak_rss() {
|
|
|
279
279
|
This approach allows for processing large PNG files on systems where memory
|
|
280
280
|
would otherwise be insufficient.
|
|
281
281
|
*/
|
|
282
|
-
void stream_png_image(const std::string& filepath, uint32_t stripe_height) {
|
|
282
|
+
void stream_png_image(const std::string& filepath, uint32_t stripe_height, bool generate_svg = false, bool generate_png = false) {
|
|
283
283
|
std::vector<ProcessResult*> result_clones;
|
|
284
284
|
std::vector<std::string> varguments = {};
|
|
285
285
|
VerticalMerger vmerger(0, &varguments);
|
|
@@ -305,6 +305,7 @@ void stream_png_image(const std::string& filepath, uint32_t stripe_height) {
|
|
|
305
305
|
|
|
306
306
|
// allocates stripe buffer
|
|
307
307
|
RawBitmap stripe_bitmap;
|
|
308
|
+
std::cout << total_width << " " << stripe_height << std::endl;
|
|
308
309
|
stripe_bitmap.define(total_width, stripe_height, 4, true);
|
|
309
310
|
RGBNotMatcher not_matcher(-1);
|
|
310
311
|
|
|
@@ -315,6 +316,7 @@ void stream_png_image(const std::string& filepath, uint32_t stripe_height) {
|
|
|
315
316
|
}
|
|
316
317
|
|
|
317
318
|
size_t row_size = static_cast<size_t>(total_width) * 4;
|
|
319
|
+
int stripe_count = 0;
|
|
318
320
|
// main stripes loop
|
|
319
321
|
for (uint32_t current_y_offset = 0; current_y_offset < total_height; current_y_offset += stripe_height) {
|
|
320
322
|
int uncovered_height = total_height - current_y_offset;
|
|
@@ -344,12 +346,13 @@ void stream_png_image(const std::string& filepath, uint32_t stripe_height) {
|
|
|
344
346
|
PolygonFinder polygon_finder(&stripe_bitmap, ¬_matcher, nullptr, &finder_arguments);
|
|
345
347
|
ProcessResult *result = polygon_finder.process_info();
|
|
346
348
|
if (result) {
|
|
347
|
-
std::cout << "
|
|
349
|
+
std::cout << "stripe " << stripe_count << ": found polygons " << result->groups << std::endl;
|
|
348
350
|
ProcessResult* safe_result = result->clone();
|
|
349
351
|
result_clones.push_back(safe_result);
|
|
350
352
|
vmerger.add_tile(*safe_result);
|
|
351
353
|
delete result;
|
|
352
354
|
}
|
|
355
|
+
stripe_count++;
|
|
353
356
|
}
|
|
354
357
|
|
|
355
358
|
std::cout << "Merging polygons ..." << std::endl;
|
|
@@ -357,15 +360,20 @@ void stream_png_image(const std::string& filepath, uint32_t stripe_height) {
|
|
|
357
360
|
|
|
358
361
|
if (merged_result) {
|
|
359
362
|
std::cout << "Founds total polygons: " << merged_result->groups << std::endl;
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
363
|
+
if (generate_png) {
|
|
364
|
+
RawBitmap full_bitmap;
|
|
365
|
+
full_bitmap.define(total_width, total_height, 4, true);
|
|
366
|
+
full_bitmap.fill(255, 255, 255);
|
|
367
|
+
merged_result->draw_on_bitmap(full_bitmap);
|
|
368
|
+
std::cout << "Saving whole png ..." << std::endl;
|
|
369
|
+
if (full_bitmap.save_to_png("whole.png")) {
|
|
370
|
+
std::cout << "Png saved!" << std::endl;
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
if (generate_svg) {
|
|
374
|
+
merged_result->save_svg("whole.svg");
|
|
375
|
+
std::cout << "Svg saved!" << std::endl;
|
|
376
|
+
}
|
|
369
377
|
}
|
|
370
378
|
delete merged_result;
|
|
371
379
|
// frees memory
|
|
@@ -56,16 +56,16 @@ void RawBitmap::draw_pixel(int x, int y, unsigned char r, unsigned char g, unsig
|
|
|
56
56
|
if (bpp > 3) p[3] = a;
|
|
57
57
|
}
|
|
58
58
|
|
|
59
|
-
|
|
60
|
-
{ this->width
|
|
59
|
+
size_t RawBitmap::define(uint width, uint height, int bytes_per_pixel, bool clear)
|
|
60
|
+
{ this->width = width;
|
|
61
61
|
this->height = height;
|
|
62
62
|
this->bpp = bytes_per_pixel;
|
|
63
|
-
|
|
63
|
+
size_t dimension = static_cast<size_t>(width) * static_cast<size_t>(height) * static_cast<size_t>(bytes_per_pixel);
|
|
64
64
|
this->image = std::make_unique<unsigned char[]>(dimension);
|
|
65
65
|
if (clear) {
|
|
66
66
|
std::fill(image.get(), image.get() + dimension, 0);
|
|
67
67
|
}
|
|
68
|
-
return dimension;
|
|
68
|
+
return static_cast<uint32_t>(dimension);
|
|
69
69
|
}
|
|
70
70
|
|
|
71
71
|
void RawBitmap::fill(unsigned char r, unsigned char g, unsigned char b, unsigned char a) {
|
|
@@ -25,7 +25,7 @@ class RawBitmap : public Bitmap {
|
|
|
25
25
|
unsigned int rgb_value_at(int x, int y);
|
|
26
26
|
const unsigned char* get_row_ptr(int y) const;
|
|
27
27
|
int get_bytes_per_pixel() const;
|
|
28
|
-
|
|
28
|
+
size_t define(uint width, uint height, int bytes_per_pixel, bool clear = false);
|
|
29
29
|
void draw_pixel(int x, int y, unsigned char r, unsigned char g, unsigned char b, unsigned char a = 255);
|
|
30
30
|
bool save_to_png(const std::string& filename);
|
|
31
31
|
void fill(unsigned char r, unsigned char g, unsigned char b, unsigned char a = 255);
|
|
@@ -534,7 +534,7 @@ static void u16_row_to_bigendian(void *row, size_t size)
|
|
|
534
534
|
write_u16(&px[i], px[i]);
|
|
535
535
|
}
|
|
536
536
|
}
|
|
537
|
-
|
|
537
|
+
/*
|
|
538
538
|
static void rgb8_row_to_rgba8(const unsigned char *row, unsigned char *out, uint32_t n)
|
|
539
539
|
{
|
|
540
540
|
uint32_t i;
|
|
@@ -543,6 +543,22 @@ static void rgb8_row_to_rgba8(const unsigned char *row, unsigned char *out, uint
|
|
|
543
543
|
memcpy(out + i * 4, row + i * 3, 3);
|
|
544
544
|
out[i*4+3] = 255;
|
|
545
545
|
}
|
|
546
|
+
}*/
|
|
547
|
+
|
|
548
|
+
/* Fix overflow Gigapixel images */
|
|
549
|
+
static void rgb8_row_to_rgba8(const unsigned char *row, unsigned char *out, uint32_t n)
|
|
550
|
+
{
|
|
551
|
+
size_t i;
|
|
552
|
+
for(i=0; i < n; i++)
|
|
553
|
+
{
|
|
554
|
+
out[0] = row[0];
|
|
555
|
+
out[1] = row[1];
|
|
556
|
+
out[2] = row[2];
|
|
557
|
+
out[3] = 255;
|
|
558
|
+
|
|
559
|
+
out += 4;
|
|
560
|
+
row += 3;
|
|
561
|
+
}
|
|
546
562
|
}
|
|
547
563
|
|
|
548
564
|
static unsigned num_channels(const struct spng_ihdr *ihdr)
|
|
@@ -147,50 +147,37 @@ struct ProcessResult {
|
|
|
147
147
|
return new_res;
|
|
148
148
|
}
|
|
149
149
|
|
|
150
|
-
std::
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
"<svg xmlns=\"http://www.w3.org/2000/svg\" "
|
|
154
|
-
"width=\"" + std::to_string(width) +
|
|
155
|
-
"\" height=\"" + std::to_string(height) + "\">");
|
|
150
|
+
void to_svg_stream(std::ostream& os) const {
|
|
151
|
+
os << "<svg xmlns=\"http://www.w3.org/2000/svg\" "
|
|
152
|
+
<< "width=\"" << width << "\" height=\"" << height << "\">\n";
|
|
156
153
|
for (const auto& poly : polygons) {
|
|
157
|
-
|
|
158
|
-
|
|
154
|
+
// --- OUTER (Red) ---
|
|
155
|
+
if (!poly.outer.empty()) {
|
|
156
|
+
os << "<polygon points=\"";
|
|
159
157
|
bool first = true;
|
|
160
158
|
for (const Point* p : poly.outer) {
|
|
161
159
|
if (!p) continue;
|
|
162
|
-
if (!first)
|
|
163
|
-
pts << " ";
|
|
160
|
+
if (!first) os << " ";
|
|
164
161
|
first = false;
|
|
165
|
-
|
|
162
|
+
os << p->x << "," << p->y;
|
|
166
163
|
}
|
|
167
|
-
|
|
168
|
-
"<polygon points=\"" + pts.str() +
|
|
169
|
-
"\" fill=\"none\" stroke=\"red\" stroke-width=\"1\"/>");
|
|
164
|
+
os << "\" fill=\"none\" stroke=\"red\" stroke-width=\"1\"/>\n";
|
|
170
165
|
}
|
|
171
|
-
//
|
|
166
|
+
// --- INNER (Green) ---
|
|
172
167
|
for (const auto& sequence : poly.inner) {
|
|
173
168
|
if (sequence.empty()) continue;
|
|
174
|
-
|
|
169
|
+
os << "<polygon points=\"";
|
|
175
170
|
bool first = true;
|
|
176
171
|
for (const Point* p : sequence) {
|
|
177
172
|
if (!p) continue;
|
|
178
|
-
if (!first)
|
|
173
|
+
if (!first) os << " ";
|
|
179
174
|
first = false;
|
|
180
|
-
|
|
175
|
+
os << p->x << "," << p->y;
|
|
181
176
|
}
|
|
182
|
-
|
|
183
|
-
"<polygon points=\"" + pts.str() +
|
|
184
|
-
"\" fill=\"none\" stroke=\"green\" stroke-width=\"1\"/>");
|
|
177
|
+
os << "\" fill=\"none\" stroke=\"green\" stroke-width=\"1\"/>\n";
|
|
185
178
|
}
|
|
186
179
|
}
|
|
187
|
-
|
|
188
|
-
std::ostringstream result;
|
|
189
|
-
for (size_t i = 0; i < lines.size(); ++i) {
|
|
190
|
-
result << lines[i];
|
|
191
|
-
if (i + 1 < lines.size()) result << "\n";
|
|
192
|
-
}
|
|
193
|
-
return result.str();
|
|
180
|
+
os << "</svg>";
|
|
194
181
|
}
|
|
195
182
|
|
|
196
183
|
void save_svg(const std::string& filename) const {
|
|
@@ -198,7 +185,7 @@ struct ProcessResult {
|
|
|
198
185
|
if (!file.is_open()) {
|
|
199
186
|
throw std::runtime_error("Unable to open SVG file: " + filename);
|
|
200
187
|
}
|
|
201
|
-
file
|
|
188
|
+
to_svg_stream(file);
|
|
202
189
|
file.close();
|
|
203
190
|
}
|
|
204
191
|
};
|
data/lib/contrek/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: contrek
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.2.
|
|
4
|
+
version: 1.2.6
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Emanuele Cesaroni
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-05-
|
|
11
|
+
date: 2026-05-31 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: rspec
|