pyisyntax 0.1.3__tar.gz → 0.1.4__tar.gz
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.
- {pyisyntax-0.1.3 → pyisyntax-0.1.4}/CHANGELOG.md +13 -1
- {pyisyntax-0.1.3/pyisyntax.egg-info → pyisyntax-0.1.4}/PKG-INFO +6 -6
- {pyisyntax-0.1.3 → pyisyntax-0.1.4}/isyntax/lowlevel/libisyntax.py +4 -0
- {pyisyntax-0.1.3 → pyisyntax-0.1.4}/isyntax/wrapper.py +4 -0
- {pyisyntax-0.1.3 → pyisyntax-0.1.4}/isyntax_build/vendor/libisyntax/src/examples/isyntax_to_tiff.c +4 -3
- {pyisyntax-0.1.3 → pyisyntax-0.1.4}/isyntax_build/vendor/libisyntax/src/isyntax/isyntax.c +180 -87
- {pyisyntax-0.1.3 → pyisyntax-0.1.4}/isyntax_build/vendor/libisyntax/src/isyntax/isyntax.h +11 -2
- {pyisyntax-0.1.3 → pyisyntax-0.1.4}/isyntax_build/vendor/libisyntax/src/isyntax/isyntax_streamer.c +77 -23
- {pyisyntax-0.1.3 → pyisyntax-0.1.4}/isyntax_build/vendor/libisyntax/src/libisyntax.c +4 -0
- {pyisyntax-0.1.3 → pyisyntax-0.1.4}/isyntax_build/vendor/libisyntax/src/libisyntax.h +2 -1
- {pyisyntax-0.1.3 → pyisyntax-0.1.4}/isyntax_build/vendor/libisyntax/src/third_party/ltalloc.cc +12 -3
- {pyisyntax-0.1.3 → pyisyntax-0.1.4}/isyntax_build/vendor/libisyntax/src/utils/mathutils.c +5 -3
- {pyisyntax-0.1.3 → pyisyntax-0.1.4}/isyntax_build/vendor/libisyntax/src/utils/mathutils.h +14 -7
- {pyisyntax-0.1.3 → pyisyntax-0.1.4}/isyntax_build/vendor/libisyntax/src/utils/stringutils.c +2 -2
- {pyisyntax-0.1.3 → pyisyntax-0.1.4/pyisyntax.egg-info}/PKG-INFO +6 -6
- {pyisyntax-0.1.3 → pyisyntax-0.1.4}/pyproject.toml +9 -6
- {pyisyntax-0.1.3 → pyisyntax-0.1.4}/tests/test_lowlevel.py +5 -0
- {pyisyntax-0.1.3 → pyisyntax-0.1.4}/tests/test_wrapper.py +4 -0
- {pyisyntax-0.1.3 → pyisyntax-0.1.4}/LICENSE +0 -0
- {pyisyntax-0.1.3 → pyisyntax-0.1.4}/MANIFEST.in +0 -0
- {pyisyntax-0.1.3 → pyisyntax-0.1.4}/README.md +0 -0
- {pyisyntax-0.1.3 → pyisyntax-0.1.4}/isyntax/__init__.py +0 -0
- {pyisyntax-0.1.3 → pyisyntax-0.1.4}/isyntax/lowlevel/__init__.py +0 -0
- {pyisyntax-0.1.3 → pyisyntax-0.1.4}/isyntax/lowlevel/io_management.py +0 -0
- {pyisyntax-0.1.3 → pyisyntax-0.1.4}/isyntax_build/__init__.py +0 -0
- {pyisyntax-0.1.3 → pyisyntax-0.1.4}/isyntax_build/builder.py +0 -0
- {pyisyntax-0.1.3 → pyisyntax-0.1.4}/isyntax_build/pyisyntax.c +0 -0
- {pyisyntax-0.1.3 → pyisyntax-0.1.4}/isyntax_build/src/python_platform_utils.c +0 -0
- {pyisyntax-0.1.3 → pyisyntax-0.1.4}/isyntax_build/src/python_platform_utils.h +0 -0
- {pyisyntax-0.1.3 → pyisyntax-0.1.4}/isyntax_build/src/win32_utils.c +0 -0
- {pyisyntax-0.1.3 → pyisyntax-0.1.4}/isyntax_build/vendor/libisyntax/LICENSE.txt +0 -0
- {pyisyntax-0.1.3 → pyisyntax-0.1.4}/isyntax_build/vendor/libisyntax/README.md +0 -0
- {pyisyntax-0.1.3 → pyisyntax-0.1.4}/isyntax_build/vendor/libisyntax/src/examples/isyntax_example.c +0 -0
- {pyisyntax-0.1.3 → pyisyntax-0.1.4}/isyntax_build/vendor/libisyntax/src/isyntax/isyntax_dwt.c +0 -0
- {pyisyntax-0.1.3 → pyisyntax-0.1.4}/isyntax_build/vendor/libisyntax/src/isyntax/isyntax_reader.c +0 -0
- {pyisyntax-0.1.3 → pyisyntax-0.1.4}/isyntax_build/vendor/libisyntax/src/isyntax/isyntax_reader.h +0 -0
- {pyisyntax-0.1.3 → pyisyntax-0.1.4}/isyntax_build/vendor/libisyntax/src/isyntax/isyntax_streamer.h +0 -0
- {pyisyntax-0.1.3 → pyisyntax-0.1.4}/isyntax_build/vendor/libisyntax/src/platform/arena.h +0 -0
- {pyisyntax-0.1.3 → pyisyntax-0.1.4}/isyntax_build/vendor/libisyntax/src/platform/common.h +0 -0
- {pyisyntax-0.1.3 → pyisyntax-0.1.4}/isyntax_build/vendor/libisyntax/src/platform/intrinsics.h +0 -0
- {pyisyntax-0.1.3 → pyisyntax-0.1.4}/isyntax_build/vendor/libisyntax/src/platform/linux_platform.c +0 -0
- {pyisyntax-0.1.3 → pyisyntax-0.1.4}/isyntax_build/vendor/libisyntax/src/platform/linux_utils.c +0 -0
- {pyisyntax-0.1.3 → pyisyntax-0.1.4}/isyntax_build/vendor/libisyntax/src/platform/platform.c +0 -0
- {pyisyntax-0.1.3 → pyisyntax-0.1.4}/isyntax_build/vendor/libisyntax/src/platform/platform.h +0 -0
- {pyisyntax-0.1.3 → pyisyntax-0.1.4}/isyntax_build/vendor/libisyntax/src/platform/win32_utils.c +0 -0
- {pyisyntax-0.1.3 → pyisyntax-0.1.4}/isyntax_build/vendor/libisyntax/src/platform/win32_utils.h +0 -0
- {pyisyntax-0.1.3 → pyisyntax-0.1.4}/isyntax_build/vendor/libisyntax/src/platform/work_queue.c +0 -0
- {pyisyntax-0.1.3 → pyisyntax-0.1.4}/isyntax_build/vendor/libisyntax/src/platform/work_queue.h +0 -0
- {pyisyntax-0.1.3 → pyisyntax-0.1.4}/isyntax_build/vendor/libisyntax/src/third_party/ltalloc.h +0 -0
- {pyisyntax-0.1.3 → pyisyntax-0.1.4}/isyntax_build/vendor/libisyntax/src/third_party/stb_ds.h +0 -0
- {pyisyntax-0.1.3 → pyisyntax-0.1.4}/isyntax_build/vendor/libisyntax/src/third_party/stb_image.h +0 -0
- {pyisyntax-0.1.3 → pyisyntax-0.1.4}/isyntax_build/vendor/libisyntax/src/third_party/stb_image_write.h +0 -0
- {pyisyntax-0.1.3 → pyisyntax-0.1.4}/isyntax_build/vendor/libisyntax/src/third_party/stb_sprintf.h +0 -0
- {pyisyntax-0.1.3 → pyisyntax-0.1.4}/isyntax_build/vendor/libisyntax/src/third_party/yxml.c +0 -0
- {pyisyntax-0.1.3 → pyisyntax-0.1.4}/isyntax_build/vendor/libisyntax/src/third_party/yxml.h +0 -0
- {pyisyntax-0.1.3 → pyisyntax-0.1.4}/isyntax_build/vendor/libisyntax/src/utils/benaphore.c +0 -0
- {pyisyntax-0.1.3 → pyisyntax-0.1.4}/isyntax_build/vendor/libisyntax/src/utils/benaphore.h +0 -0
- {pyisyntax-0.1.3 → pyisyntax-0.1.4}/isyntax_build/vendor/libisyntax/src/utils/block_allocator.c +0 -0
- {pyisyntax-0.1.3 → pyisyntax-0.1.4}/isyntax_build/vendor/libisyntax/src/utils/block_allocator.h +0 -0
- {pyisyntax-0.1.3 → pyisyntax-0.1.4}/isyntax_build/vendor/libisyntax/src/utils/libtiff_api.h +0 -0
- {pyisyntax-0.1.3 → pyisyntax-0.1.4}/isyntax_build/vendor/libisyntax/src/utils/memrw.c +0 -0
- {pyisyntax-0.1.3 → pyisyntax-0.1.4}/isyntax_build/vendor/libisyntax/src/utils/memrw.h +0 -0
- {pyisyntax-0.1.3 → pyisyntax-0.1.4}/isyntax_build/vendor/libisyntax/src/utils/stringutils.h +0 -0
- {pyisyntax-0.1.3 → pyisyntax-0.1.4}/isyntax_build/vendor/libisyntax/src/utils/timerutils.c +0 -0
- {pyisyntax-0.1.3 → pyisyntax-0.1.4}/isyntax_build/vendor/libisyntax/src/utils/timerutils.h +0 -0
- {pyisyntax-0.1.3 → pyisyntax-0.1.4}/pyisyntax.egg-info/SOURCES.txt +0 -0
- {pyisyntax-0.1.3 → pyisyntax-0.1.4}/pyisyntax.egg-info/dependency_links.txt +0 -0
- {pyisyntax-0.1.3 → pyisyntax-0.1.4}/pyisyntax.egg-info/not-zip-safe +0 -0
- {pyisyntax-0.1.3 → pyisyntax-0.1.4}/pyisyntax.egg-info/requires.txt +0 -0
- {pyisyntax-0.1.3 → pyisyntax-0.1.4}/pyisyntax.egg-info/top_level.txt +0 -0
- {pyisyntax-0.1.3 → pyisyntax-0.1.4}/setup.cfg +0 -0
- {pyisyntax-0.1.3 → pyisyntax-0.1.4}/setup.py +0 -0
- {pyisyntax-0.1.3 → pyisyntax-0.1.4}/tests/__init__.py +0 -0
- {pyisyntax-0.1.3 → pyisyntax-0.1.4}/tests/conftest.py +0 -0
- {pyisyntax-0.1.3 → pyisyntax-0.1.4}/tests/data/DOWNLOAD.txt +0 -0
|
@@ -7,6 +7,17 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.1.4] - 2024-08-31
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
|
|
14
|
+
- Support for reading the slide barcode. The barcode string can be accessed via
|
|
15
|
+
the `barcode` property of an `ISyntax` instance.
|
|
16
|
+
|
|
17
|
+
### Changed
|
|
18
|
+
|
|
19
|
+
- Bump the `libisyntax` submodule commit.
|
|
20
|
+
|
|
10
21
|
## [0.1.3] - 2024-03-28
|
|
11
22
|
|
|
12
23
|
### Added
|
|
@@ -50,7 +61,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
50
61
|
|
|
51
62
|
- This is the initial release.
|
|
52
63
|
|
|
53
|
-
[unreleased]: https://github.com/anibali/pyisyntax/compare/v0.1.
|
|
64
|
+
[unreleased]: https://github.com/anibali/pyisyntax/compare/v0.1.4...HEAD
|
|
65
|
+
[0.1.4]: https://github.com/anibali/pyisyntax/compare/v0.1.3...v0.1.4
|
|
54
66
|
[0.1.3]: https://github.com/anibali/pyisyntax/compare/v0.1.2...v0.1.3
|
|
55
67
|
[0.1.2]: https://github.com/anibali/pyisyntax/compare/v0.1.1...v0.1.2
|
|
56
68
|
[0.1.1]: https://github.com/anibali/pyisyntax/compare/v0.1.0...v0.1.1
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: pyisyntax
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.4
|
|
4
4
|
Summary: Python bindings for libisyntax
|
|
5
5
|
Author-email: Aiden Nibali <dismaldenizen@gmail.com>
|
|
6
6
|
License: MIT
|
|
7
|
-
Project-URL:
|
|
8
|
-
Project-URL:
|
|
9
|
-
Project-URL:
|
|
10
|
-
Project-URL:
|
|
11
|
-
Project-URL:
|
|
7
|
+
Project-URL: Homepage, https://github.com/anibali/pyisyntax
|
|
8
|
+
Project-URL: Source, https://github.com/anibali/pyisyntax
|
|
9
|
+
Project-URL: Download, https://pypi.org/project/pyisyntax/#files
|
|
10
|
+
Project-URL: Tracker, https://github.com/anibali/pyisyntax/issues
|
|
11
|
+
Project-URL: Release notes, https://github.com/anibali/pyisyntax/blob/master/CHANGELOG.md
|
|
12
12
|
Requires-Python: >=3.10
|
|
13
13
|
Description-Content-Type: text/markdown
|
|
14
14
|
License-File: LICENSE
|
|
@@ -119,6 +119,10 @@ def get_macro_image(isyntax: ISyntaxPtr) -> ISyntaxImagePtr:
|
|
|
119
119
|
return lib.libisyntax_get_macro_image(isyntax)
|
|
120
120
|
|
|
121
121
|
|
|
122
|
+
def get_barcode(isyntax: ISyntaxPtr) -> bytes:
|
|
123
|
+
return ffi.string(lib.libisyntax_get_barcode(isyntax))
|
|
124
|
+
|
|
125
|
+
|
|
122
126
|
def image_get_level_count(wsi_image: ISyntaxImagePtr) -> int:
|
|
123
127
|
return lib.libisyntax_image_get_level_count(wsi_image)
|
|
124
128
|
|
|
@@ -178,6 +178,10 @@ class ISyntax:
|
|
|
178
178
|
except libisyntax.LibISyntaxFatalError:
|
|
179
179
|
return None
|
|
180
180
|
|
|
181
|
+
@property
|
|
182
|
+
def barcode(self) -> str:
|
|
183
|
+
return libisyntax.get_barcode(self.ptr).decode("ascii")
|
|
184
|
+
|
|
181
185
|
def read_icc_profile(self) -> memoryview | None:
|
|
182
186
|
"""Reads the ICC color profile for an image.
|
|
183
187
|
|
{pyisyntax-0.1.3 → pyisyntax-0.1.4}/isyntax_build/vendor/libisyntax/src/examples/isyntax_to_tiff.c
RENAMED
|
@@ -37,6 +37,7 @@
|
|
|
37
37
|
#endif
|
|
38
38
|
|
|
39
39
|
#include <stdint.h>
|
|
40
|
+
#include <inttypes.h>
|
|
40
41
|
#include <assert.h>
|
|
41
42
|
#include <stdlib.h>
|
|
42
43
|
#include <string.h>
|
|
@@ -221,7 +222,7 @@ uint64_t parse_cache_size(const char *size_str) {
|
|
|
221
222
|
uint64_t size;
|
|
222
223
|
char unit;
|
|
223
224
|
|
|
224
|
-
if (sscanf(size_str, "%
|
|
225
|
+
if (sscanf(size_str, "%"PRIu64"%c", &size, &unit) == 2) {
|
|
225
226
|
if (unit == 'M') {
|
|
226
227
|
if (size > INT64_MAX / (1024)) {
|
|
227
228
|
printf("Error: Cache size too large.\n");
|
|
@@ -238,7 +239,7 @@ uint64_t parse_cache_size(const char *size_str) {
|
|
|
238
239
|
printf("Error: Invalid unit for cache size. Use 'M' for megabytes or 'G' for gigabytes.\n");
|
|
239
240
|
return -1;
|
|
240
241
|
}
|
|
241
|
-
} else if (sscanf(size_str, "%
|
|
242
|
+
} else if (sscanf(size_str, "%"PRIu64, &size) != 1) {
|
|
242
243
|
printf("Error: Invalid cache size format.\n");
|
|
243
244
|
return -1;
|
|
244
245
|
}
|
|
@@ -426,7 +427,7 @@ int main(int argc, char **argv) {
|
|
|
426
427
|
|
|
427
428
|
isyntax_cache_t *isyntax_cache = NULL;
|
|
428
429
|
if (libisyntax_cache_create("isyntax-to-tiff cache", cache_size, &isyntax_cache) != LIBISYNTAX_OK) {
|
|
429
|
-
fprintf(stderr, "Failed to create iSyntax cache with size %
|
|
430
|
+
fprintf(stderr, "Failed to create iSyntax cache with size %"PRIu64".\n", cache_size);
|
|
430
431
|
libisyntax_close(isyntax);
|
|
431
432
|
return -1;
|
|
432
433
|
}
|
|
@@ -66,7 +66,7 @@
|
|
|
66
66
|
// Enable/disable debug routines for creating PNGs of IDWT steps
|
|
67
67
|
#define ISYNTAX_WANT_DEBUG_OUTPUT_PNG 0
|
|
68
68
|
#if ISYNTAX_WANT_DEBUG_OUTPUT_PNG
|
|
69
|
-
|
|
69
|
+
//#define STB_IMAGE_WRITE_IMPLEMENTATION
|
|
70
70
|
// stb_image_write.h provides its own crc32() implementation, so we need to prevent a conflict if we already have it
|
|
71
71
|
#define STBIW_CRC32 crc32
|
|
72
72
|
#include <stb_image_write.h>
|
|
@@ -74,8 +74,6 @@
|
|
|
74
74
|
|
|
75
75
|
#include <ctype.h>
|
|
76
76
|
|
|
77
|
-
// TODO: Add ICC profiles support
|
|
78
|
-
|
|
79
77
|
#define PER_LEVEL_PADDING 3
|
|
80
78
|
|
|
81
79
|
#include "isyntax_dwt.c"
|
|
@@ -157,6 +155,21 @@ unsigned char * base64_decode(const unsigned char *src, size_t len,
|
|
|
157
155
|
}
|
|
158
156
|
// end of base64 decoder.
|
|
159
157
|
|
|
158
|
+
// Wrapper for base64_decode, taking into account possible extra (invalid) characters at the end
|
|
159
|
+
u8* isyntax_base64_decode(const char* src, size_t len, size_t *out_len) {
|
|
160
|
+
char last_char = src[len-1];
|
|
161
|
+
if (last_char == '/') {
|
|
162
|
+
len--; // The last character may cause the base64 decoding to fail if invalid
|
|
163
|
+
last_char = src[len-1];
|
|
164
|
+
}
|
|
165
|
+
while (last_char == '\n' || last_char == '\r' || last_char == ' ') {
|
|
166
|
+
--len;
|
|
167
|
+
last_char = src[len-1];
|
|
168
|
+
}
|
|
169
|
+
u8* decoded = base64_decode((u8*)src, len, out_len);
|
|
170
|
+
return decoded;
|
|
171
|
+
}
|
|
172
|
+
|
|
160
173
|
// similar to atoi(), but also returning the string position so we can chain calls one after another.
|
|
161
174
|
static const char* atoi_and_advance(const char* str, i32* dest) {
|
|
162
175
|
i32 num = 0;
|
|
@@ -378,7 +391,14 @@ static void isyntax_parse_ufsimport_child_node(isyntax_t* isyntax, u32 group, u3
|
|
|
378
391
|
// Value will likely be "5.0" for v1 iSyntax files, "100.5" for v2 iSyntax files
|
|
379
392
|
isyntax->data_model_major_version = atoi(value);
|
|
380
393
|
} break;
|
|
381
|
-
case 0x1002: /*PIM_DP_UFS_BARCODE*/ {
|
|
394
|
+
case 0x1002: /*PIM_DP_UFS_BARCODE*/ {
|
|
395
|
+
size_t decoded_len = 0;
|
|
396
|
+
char* decoded = (char*) isyntax_base64_decode(value, value_len, &decoded_len);
|
|
397
|
+
if (decoded) {
|
|
398
|
+
memcpy(isyntax->barcode, decoded, MIN(decoded_len, sizeof(isyntax->barcode)-1));
|
|
399
|
+
free(decoded);
|
|
400
|
+
}
|
|
401
|
+
} break; // "<base64-encoded barcode value>"
|
|
382
402
|
case 0x1003: /*PIM_DP_SCANNED_IMAGES*/ {} break;
|
|
383
403
|
case 0x1010: /*PIM_DP_SCANNER_RACK_PRIORITY*/ {} break; // "<u16>"
|
|
384
404
|
}
|
|
@@ -532,9 +552,9 @@ static bool isyntax_parse_scannedimage_child_node(isyntax_t* isyntax, u32 group,
|
|
|
532
552
|
case 3: {
|
|
533
553
|
image->level_count = range.numsteps;
|
|
534
554
|
image->max_scale = range.numsteps - 1;
|
|
535
|
-
|
|
536
|
-
image->width = image->width_including_padding - 2 *
|
|
537
|
-
image->height = image->height_including_padding - 2 *
|
|
555
|
+
image->level0_padding = (PER_LEVEL_PADDING << range.numsteps) - PER_LEVEL_PADDING;
|
|
556
|
+
image->width = image->width_including_padding - 2 * image->level0_padding;
|
|
557
|
+
image->height = image->height_including_padding - 2 * image->level0_padding;
|
|
538
558
|
} break;
|
|
539
559
|
case 4: break; // always 4 wavelet coefficients ("LL" "LH" "HL" "HH"), no need to check
|
|
540
560
|
}
|
|
@@ -588,23 +608,13 @@ static bool isyntax_parse_scannedimage_child_node(isyntax_t* isyntax, u32 group,
|
|
|
588
608
|
case 0x2013: /*UFS_IMAGE_PIXEL_TRANSFORMATION_METHOD*/ {} break;
|
|
589
609
|
case 0x2014: { /*UFS_IMAGE_BLOCK_HEADER_TABLE*/ // data model <100
|
|
590
610
|
// NOTE: mutually exclusive with UFS_IMAGE_BLOCK_HEADERS (either one or the other must be present)
|
|
591
|
-
size_t decoded_capacity = value_len;
|
|
592
|
-
size_t decoded_len = 0;
|
|
593
|
-
i32 last_char = value[value_len-1];
|
|
594
611
|
/*
|
|
595
612
|
FILE* test_out = file_stream_open_for_writing("test_b64.out");
|
|
596
613
|
file_stream_write(value, value_len, test_out);
|
|
597
614
|
file_stream_close(test_out);
|
|
598
615
|
*/
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
last_char = value[value_len-1];
|
|
602
|
-
}
|
|
603
|
-
while (last_char == '\n' || last_char == '\r' || last_char == ' ') {
|
|
604
|
-
--value_len;
|
|
605
|
-
last_char = value[value_len-1];
|
|
606
|
-
}
|
|
607
|
-
u8* decoded = base64_decode((u8*)value, value_len, &decoded_len);
|
|
616
|
+
size_t decoded_len = 0;
|
|
617
|
+
u8* decoded = isyntax_base64_decode(value, value_len, &decoded_len);
|
|
608
618
|
if (decoded) {
|
|
609
619
|
|
|
610
620
|
u32 header_size = *(u32*) decoded + 0;
|
|
@@ -672,23 +682,13 @@ static bool isyntax_parse_scannedimage_child_node(isyntax_t* isyntax, u32 group,
|
|
|
672
682
|
case 0x2016: /*UFS_IMAGE_CLUSTER_HEADER_TEMPLATES*/ {} break; // data model >= 100
|
|
673
683
|
case 0x2017: /*UFS_IMAGE_DIMENSIONS_OVER_CLUSTER*/ {} break;
|
|
674
684
|
case 0x201F: /*UFS_IMAGE_CLUSTER_HEADER_TABLE*/ { // data model >= 100
|
|
675
|
-
size_t decoded_capacity = value_len;
|
|
676
|
-
size_t decoded_len = 0;
|
|
677
|
-
i32 last_char = value[value_len-1];
|
|
678
685
|
/*
|
|
679
686
|
FILE* test_out = file_stream_open_for_writing("test_b64.out");
|
|
680
687
|
file_stream_write(value, value_len, test_out);
|
|
681
688
|
file_stream_close(test_out);
|
|
682
689
|
*/
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
last_char = value[value_len-1];
|
|
686
|
-
}
|
|
687
|
-
while (last_char == '\n' || last_char == '\r' || last_char == ' ') {
|
|
688
|
-
--value_len;
|
|
689
|
-
last_char = value[value_len-1];
|
|
690
|
-
}
|
|
691
|
-
u8* decoded = base64_decode((u8*)value, value_len, &decoded_len);
|
|
690
|
+
size_t decoded_len = 0;
|
|
691
|
+
u8* decoded = isyntax_base64_decode(value, value_len, &decoded_len);
|
|
692
692
|
if (decoded) {
|
|
693
693
|
u8* decoded_end = decoded + decoded_len;
|
|
694
694
|
u32 header_size = *(u32*) decoded + 0;
|
|
@@ -701,7 +701,7 @@ static bool isyntax_parse_scannedimage_child_node(isyntax_t* isyntax, u32 group,
|
|
|
701
701
|
goto decoding_cluster_header_table_failed;
|
|
702
702
|
}
|
|
703
703
|
// pass 1: check how many clusters there are
|
|
704
|
-
i32 cluster_count =
|
|
704
|
+
i32 cluster_count = 1;
|
|
705
705
|
for (;;) {
|
|
706
706
|
u8* next_sequence_element_pos = pos + sizeof(isyntax_dicom_tag_header_t) + ((isyntax_dicom_tag_header_t*)pos)->size;
|
|
707
707
|
isyntax_dicom_tag_header_t* next_sequence_element = (isyntax_dicom_tag_header_t*)next_sequence_element_pos;
|
|
@@ -717,7 +717,9 @@ static bool isyntax_parse_scannedimage_child_node(isyntax_t* isyntax, u32 group,
|
|
|
717
717
|
image->data_chunk_count = cluster_count;
|
|
718
718
|
image->data_chunks = calloc(1, cluster_count * sizeof(isyntax_data_chunk_t));
|
|
719
719
|
}
|
|
720
|
-
|
|
720
|
+
if (image->number_of_blocks <= 0) { // sanity check
|
|
721
|
+
goto decoding_cluster_header_table_failed;
|
|
722
|
+
}
|
|
721
723
|
if (image->codeblocks == NULL) {
|
|
722
724
|
// NOTE: this value seems to be much larger than the actual number of codeblocks present in the file
|
|
723
725
|
image->codeblock_count = image->number_of_blocks; // from UFS_IMAGE_NUMBER_OF_BLOCKS attribute
|
|
@@ -868,8 +870,21 @@ static bool isyntax_parse_scannedimage_child_node(isyntax_t* isyntax, u32 group,
|
|
|
868
870
|
template->dimension_count = parse_up_to_five_integers(value, template->dimension_order);
|
|
869
871
|
} break; // data model >= 100
|
|
870
872
|
case 0x2023: /*UFS_IMAGE_VALID_DATA_ENVELOPES*/ {} break; // data model >= 100
|
|
871
|
-
case 0x2024: /*UFS_IMAGE_OPP_EXTREME_VERTICES*/ {
|
|
872
|
-
|
|
873
|
+
case 0x2024: /*UFS_IMAGE_OPP_EXTREME_VERTICES*/ { // data model >= 100
|
|
874
|
+
// increment envelope
|
|
875
|
+
} break;
|
|
876
|
+
case 0x2025: /*UFS_IMAGE_OPP_EXTREME_VERTEX*/ { // data model >= 100
|
|
877
|
+
if (isyntax->parser.data_object_flags & (ISYNTAX_OBJECT_UFSImageValidDataEnvelope)) {
|
|
878
|
+
isyntax_valid_data_envelope_t* envelope = isyntax->valid_data_envelopes + isyntax->parser.valid_data_envelope_index;
|
|
879
|
+
if (envelope->vertex_count < COUNT(envelope->vertices)) {
|
|
880
|
+
v2i vertex = {};
|
|
881
|
+
atoi_and_advance(atoi_and_advance(value, &vertex.x), &vertex.y); // parse two integers
|
|
882
|
+
envelope->vertices[envelope->vertex_count++] = vertex;
|
|
883
|
+
} else {
|
|
884
|
+
success = false; // out of bounds
|
|
885
|
+
}
|
|
886
|
+
}
|
|
887
|
+
} break; // data model >= 100
|
|
873
888
|
case 0x2026: /*UFS_IMAGE_VALID_ENVELOPE_DIMENSIONS*/ {} break; // data model >= 100
|
|
874
889
|
case 0x2027: /*UFS_IMAGE_DIMENSION_ORIGIN*/ {} break; // data model >= 100
|
|
875
890
|
case 0x2029: /*UFS_IMAGE_PIXEL_TRANSFORM_METHOD*/ {} break; // data model >= 100
|
|
@@ -887,7 +902,7 @@ static bool validate_dicom_attr(const char* expected, const char* observed) {
|
|
|
887
902
|
return ok;
|
|
888
903
|
}
|
|
889
904
|
|
|
890
|
-
void isyntax_xml_parser_init(isyntax_xml_parser_t* parser) {
|
|
905
|
+
static void isyntax_xml_parser_init(isyntax_xml_parser_t* parser) {
|
|
891
906
|
|
|
892
907
|
parser->initialized = true;
|
|
893
908
|
|
|
@@ -942,6 +957,27 @@ static void push_to_buffer_maybe_grow(u8** restrict dest, size_t* restrict dest_
|
|
|
942
957
|
*dest_len = new_len;
|
|
943
958
|
}
|
|
944
959
|
|
|
960
|
+
static bool isyntax_parse_xml_header_cleanup(isyntax_t* isyntax, bool success) {
|
|
961
|
+
isyntax_xml_parser_t* parser = &isyntax->parser;
|
|
962
|
+
if (parser->x) {
|
|
963
|
+
free(parser->x);
|
|
964
|
+
parser->x = NULL;
|
|
965
|
+
}
|
|
966
|
+
if (parser->attrbuf) {
|
|
967
|
+
free(parser->attrbuf);
|
|
968
|
+
parser->attrbuf = NULL;
|
|
969
|
+
}
|
|
970
|
+
if (parser->contentbuf) {
|
|
971
|
+
free(parser->contentbuf);
|
|
972
|
+
parser->contentbuf = NULL;
|
|
973
|
+
}
|
|
974
|
+
return success;
|
|
975
|
+
}
|
|
976
|
+
|
|
977
|
+
static inline bool isyntax_parse_xml_header_failure(isyntax_t* isyntax) {
|
|
978
|
+
return isyntax_parse_xml_header_cleanup(isyntax, false);
|
|
979
|
+
}
|
|
980
|
+
|
|
945
981
|
static bool isyntax_parse_xml_header(isyntax_t* isyntax, char* xml_header, i64 chunk_offset, i64 chunk_length, bool is_last_chunk) {
|
|
946
982
|
|
|
947
983
|
yxml_t* x = NULL;
|
|
@@ -956,35 +992,19 @@ static bool isyntax_parse_xml_header(isyntax_t* isyntax, char* xml_header, i64 c
|
|
|
956
992
|
}
|
|
957
993
|
x = parser->x;
|
|
958
994
|
|
|
959
|
-
if (0) { failed: cleanup:
|
|
960
|
-
if (parser->x) {
|
|
961
|
-
free(parser->x);
|
|
962
|
-
parser->x = NULL;
|
|
963
|
-
}
|
|
964
|
-
if (parser->attrbuf) {
|
|
965
|
-
free(parser->attrbuf);
|
|
966
|
-
parser->attrbuf = NULL;
|
|
967
|
-
}
|
|
968
|
-
if (parser->contentbuf) {
|
|
969
|
-
free(parser->contentbuf);
|
|
970
|
-
parser->contentbuf = NULL;
|
|
971
|
-
}
|
|
972
|
-
return success;
|
|
973
|
-
}
|
|
974
|
-
|
|
975
995
|
// parse XML byte for byte
|
|
976
996
|
char* doc = xml_header;
|
|
977
997
|
for (i64 remaining_length = chunk_length; remaining_length > 0; --remaining_length, ++doc) {
|
|
978
998
|
int c = *doc;
|
|
979
999
|
if (c == '\0') {
|
|
980
1000
|
// This should never trigger; iSyntax file is corrupt!
|
|
981
|
-
|
|
1001
|
+
return isyntax_parse_xml_header_failure(isyntax);
|
|
982
1002
|
}
|
|
983
1003
|
yxml_ret_t r = yxml_parse(x, c);
|
|
984
1004
|
if (r == YXML_OK) {
|
|
985
1005
|
continue; // nothing worthy of note has happened -> continue
|
|
986
1006
|
} else if (r < 0) {
|
|
987
|
-
|
|
1007
|
+
return isyntax_parse_xml_header_failure(isyntax);
|
|
988
1008
|
} else if (r > 0) {
|
|
989
1009
|
// token
|
|
990
1010
|
switch(r) {
|
|
@@ -1020,7 +1040,12 @@ static bool isyntax_parse_xml_header(isyntax_t* isyntax, char* xml_header, i64 c
|
|
|
1020
1040
|
case 0: flags |= ISYNTAX_OBJECT_DPUfsImport; break;
|
|
1021
1041
|
case PIM_DP_SCANNED_IMAGES: flags |= ISYNTAX_OBJECT_DPScannedImage; break;
|
|
1022
1042
|
case UFS_IMAGE_GENERAL_HEADERS: flags |= ISYNTAX_OBJECT_UFSImageGeneralHeader; break;
|
|
1023
|
-
case UFS_IMAGE_BLOCK_HEADER_TEMPLATES:
|
|
1043
|
+
case UFS_IMAGE_BLOCK_HEADER_TEMPLATES: {
|
|
1044
|
+
flags |= ISYNTAX_OBJECT_UFSImageBlockHeaderTemplate;
|
|
1045
|
+
if (isyntax->parser.block_header_template_index >= COUNT(isyntax->block_header_templates)) { // bounds check
|
|
1046
|
+
return isyntax_parse_xml_header_failure(isyntax);
|
|
1047
|
+
}
|
|
1048
|
+
} break;
|
|
1024
1049
|
case UFS_IMAGE_DIMENSIONS: flags |= ISYNTAX_OBJECT_UFSImageDimension; break;
|
|
1025
1050
|
case UFS_IMAGE_DIMENSION_RANGES: flags |= ISYNTAX_OBJECT_UFSImageDimensionRange; break;
|
|
1026
1051
|
case DP_COLOR_MANAGEMENT: flags |= ISYNTAX_OBJECT_DPColorManagement; break;
|
|
@@ -1029,8 +1054,20 @@ static bool isyntax_parse_xml_header(isyntax_t* isyntax, char* xml_header, i64 c
|
|
|
1029
1054
|
case DP_WAVELET_QUANTIZER_SETTINGS_PER_LEVEL: flags |= ISYNTAX_OBJECT_DPWaveletQuantizerSeetingsPerLevel; break;
|
|
1030
1055
|
case PIIM_PIXEL_DATA_REPRESENTATION_SEQUENCE: flags |= ISYNTAX_OBJECT_PixelDataRepresentation; break;
|
|
1031
1056
|
case UFS_IMAGE_BLOCK_HEADERS: flags |= ISYNTAX_OBJECT_UFSImageBlockHeader; break;
|
|
1032
|
-
case UFS_IMAGE_CLUSTER_HEADER_TEMPLATES:
|
|
1033
|
-
|
|
1057
|
+
case UFS_IMAGE_CLUSTER_HEADER_TEMPLATES: {
|
|
1058
|
+
flags |= ISYNTAX_OBJECT_UFSImageClusterHeaderTemplate;
|
|
1059
|
+
if (isyntax->parser.cluster_header_template_index >= COUNT(isyntax->cluster_header_templates)) { // bounds check
|
|
1060
|
+
return isyntax_parse_xml_header_failure(isyntax);
|
|
1061
|
+
}
|
|
1062
|
+
} break;
|
|
1063
|
+
case UFS_IMAGE_VALID_DATA_ENVELOPES: {
|
|
1064
|
+
// 'soft' bounds check: parsing these is not strictly needed so we don't need to fail if we don't get them all.
|
|
1065
|
+
if (isyntax->parser.valid_data_envelope_index < COUNT(isyntax->valid_data_envelopes)) {
|
|
1066
|
+
flags |= ISYNTAX_OBJECT_UFSImageValidDataEnvelope;
|
|
1067
|
+
} else {
|
|
1068
|
+
console_print("Warning: cannot read all UFSImageValidDataEnvelopes (out of bounds)\n");
|
|
1069
|
+
}
|
|
1070
|
+
} break;
|
|
1034
1071
|
case UFS_IMAGE_OPP_EXTREME_VERTICES: flags |= ISYNTAX_OBJECT_UFSImageOppExtremeVertex; break;
|
|
1035
1072
|
}
|
|
1036
1073
|
parser->data_object_flags = flags;
|
|
@@ -1160,7 +1197,9 @@ static bool isyntax_parse_xml_header(isyntax_t* isyntax, char* xml_header, i64 c
|
|
|
1160
1197
|
case UFS_IMAGE_BLOCK_HEADER_TEMPLATES: {
|
|
1161
1198
|
flags &= ~ISYNTAX_OBJECT_UFSImageBlockHeaderTemplate;
|
|
1162
1199
|
++parser->block_header_template_index;
|
|
1163
|
-
|
|
1200
|
+
if (isyntax->block_header_template_count < COUNT(isyntax->block_header_templates)) {
|
|
1201
|
+
++isyntax->block_header_template_count;
|
|
1202
|
+
}
|
|
1164
1203
|
parser->dimension_index = 0;
|
|
1165
1204
|
} break;
|
|
1166
1205
|
case UFS_IMAGE_DIMENSIONS: {
|
|
@@ -1181,14 +1220,14 @@ static bool isyntax_parse_xml_header(isyntax_t* isyntax, char* xml_header, i64 c
|
|
|
1181
1220
|
// NOTE: Within a UFSImageClusterHeaderTemplate, the UFSImageBlockHeader objects contain coordinate offset values that apply to that cluster template
|
|
1182
1221
|
// (Each UFSImageBlockHeader object corresponds to a codeblock in the cluster)
|
|
1183
1222
|
++parser->block_header_index_for_cluster;
|
|
1184
|
-
if (parser->block_header_index_for_cluster >= MAX_CODEBLOCKS_PER_CLUSTER) {
|
|
1185
|
-
|
|
1223
|
+
if (parser->block_header_index_for_cluster >= MAX_CODEBLOCKS_PER_CLUSTER) { // bounds check
|
|
1224
|
+
return isyntax_parse_xml_header_failure(isyntax);
|
|
1186
1225
|
}
|
|
1187
1226
|
}
|
|
1188
1227
|
} break;
|
|
1189
1228
|
case UFS_IMAGE_CLUSTER_HEADER_TEMPLATES: {
|
|
1190
1229
|
// Finalize cluster header template object: fix up relative codeblock coordinates within cluster
|
|
1191
|
-
// using the information from UFS_IMAGE_DIMENSION_RANGES (=base value)
|
|
1230
|
+
// using the information from UFS_IMAGE_DIMENSION_RANGES (=base value)
|
|
1192
1231
|
// combined with the UFS_IMAGE_BLOCK_COORDINATE values (=offsets) using the dimension ordering info provided by UFS_IMAGE_DIMENSIONS_IN_CLUSTER
|
|
1193
1232
|
isyntax_cluster_header_template_t* template = isyntax->cluster_header_templates + parser->cluster_header_template_index;
|
|
1194
1233
|
template->codeblock_in_cluster_count = parser->block_header_index_for_cluster;
|
|
@@ -1210,11 +1249,19 @@ static bool isyntax_parse_xml_header(isyntax_t* isyntax, char* xml_header, i64 c
|
|
|
1210
1249
|
// Pop flags and reset indices
|
|
1211
1250
|
flags &= ~ISYNTAX_OBJECT_UFSImageClusterHeaderTemplate;
|
|
1212
1251
|
++parser->cluster_header_template_index;
|
|
1213
|
-
|
|
1252
|
+
if (isyntax->cluster_header_template_count < COUNT(isyntax->cluster_header_templates)) {
|
|
1253
|
+
++isyntax->cluster_header_template_count;
|
|
1254
|
+
}
|
|
1214
1255
|
parser->dimension_index = 0;
|
|
1215
1256
|
parser->block_header_index_for_cluster = 0;
|
|
1216
1257
|
} break;
|
|
1217
|
-
case UFS_IMAGE_VALID_DATA_ENVELOPES:
|
|
1258
|
+
case UFS_IMAGE_VALID_DATA_ENVELOPES: {
|
|
1259
|
+
flags &= ~ISYNTAX_OBJECT_UFSImageValidDataEnvelope;
|
|
1260
|
+
++parser->valid_data_envelope_index;
|
|
1261
|
+
if (isyntax->valid_data_envelope_count < COUNT(isyntax->valid_data_envelopes)) {
|
|
1262
|
+
++isyntax->valid_data_envelope_count;
|
|
1263
|
+
}
|
|
1264
|
+
} break;
|
|
1218
1265
|
case UFS_IMAGE_OPP_EXTREME_VERTICES: flags &= ~ISYNTAX_OBJECT_UFSImageOppExtremeVertex; break;
|
|
1219
1266
|
}
|
|
1220
1267
|
parser->data_object_flags = flags;
|
|
@@ -1232,8 +1279,8 @@ static bool isyntax_parse_xml_header(isyntax_t* isyntax, char* xml_header, i64 c
|
|
|
1232
1279
|
parser->current_node_type = parser->node_stack[parser->node_stack_index].node_type;
|
|
1233
1280
|
parser->current_node_has_children = parser->node_stack[parser->node_stack_index].has_children;
|
|
1234
1281
|
} else {
|
|
1235
|
-
//TODO: handle error condition
|
|
1236
1282
|
console_print_error("iSyntax XML error: closing element without matching start\n");
|
|
1283
|
+
return isyntax_parse_xml_header_failure(isyntax);
|
|
1237
1284
|
}
|
|
1238
1285
|
|
|
1239
1286
|
} break;
|
|
@@ -1333,7 +1380,7 @@ static bool isyntax_parse_xml_header(isyntax_t* isyntax, char* xml_header, i64 c
|
|
|
1333
1380
|
break; // processing instructions (uninteresting, skip)
|
|
1334
1381
|
default: {
|
|
1335
1382
|
console_print_error("yxml_parse(): unrecognized token (%d)\n", r);
|
|
1336
|
-
|
|
1383
|
+
return isyntax_parse_xml_header_failure(isyntax);
|
|
1337
1384
|
}
|
|
1338
1385
|
}
|
|
1339
1386
|
}
|
|
@@ -1341,7 +1388,7 @@ static bool isyntax_parse_xml_header(isyntax_t* isyntax, char* xml_header, i64 c
|
|
|
1341
1388
|
|
|
1342
1389
|
success = true;
|
|
1343
1390
|
if (is_last_chunk) {
|
|
1344
|
-
|
|
1391
|
+
return isyntax_parse_xml_header_cleanup(isyntax, success);
|
|
1345
1392
|
} else {
|
|
1346
1393
|
return success; // no cleanup yet, we will still need resources until the last header chunk is reached.
|
|
1347
1394
|
}
|
|
@@ -1466,7 +1513,7 @@ static rgba_t ycocg_to_rgb(i32 Y, i32 Co, i32 Cg) {
|
|
|
1466
1513
|
i32 G = tmp + Cg;
|
|
1467
1514
|
i32 B = tmp - Co/2;
|
|
1468
1515
|
i32 R = B + Co;
|
|
1469
|
-
return (rgba_t){ATMOST(255, R), ATMOST(255, G), ATMOST(255, B), 255};
|
|
1516
|
+
return (rgba_t){{{ATMOST(255, R), ATMOST(255, G), ATMOST(255, B), 255}}};
|
|
1470
1517
|
}
|
|
1471
1518
|
|
|
1472
1519
|
static rgba_t ycocg_to_bgr(i32 Y, i32 Co, i32 Cg) {
|
|
@@ -1474,7 +1521,7 @@ static rgba_t ycocg_to_bgr(i32 Y, i32 Co, i32 Cg) {
|
|
|
1474
1521
|
i32 G = tmp + Cg;
|
|
1475
1522
|
i32 B = tmp - Co/2;
|
|
1476
1523
|
i32 R = B + Co;
|
|
1477
|
-
return (rgba_t){ATMOST(255, B), ATMOST(255, G), ATMOST(255, R), 255};
|
|
1524
|
+
return (rgba_t){{{ATMOST(255, B), ATMOST(255, G), ATMOST(255, R), 255}}};
|
|
1478
1525
|
}
|
|
1479
1526
|
|
|
1480
1527
|
static void convert_ycocg_to_bgra_block(icoeff_t* Y, icoeff_t* Co, icoeff_t* Cg, i32 width, i32 height, i32 stride, u32* out_bgra) {
|
|
@@ -1757,6 +1804,18 @@ u32 isyntax_get_adjacent_tiles_mask_only_existing(isyntax_level_t* level, i32 ti
|
|
|
1757
1804
|
return mask;
|
|
1758
1805
|
}
|
|
1759
1806
|
|
|
1807
|
+
bool isyntax_is_parent_tile_missing(isyntax_image_t* wsi, i32 scale, i32 tile_x, i32 tile_y) {
|
|
1808
|
+
// Some tiles may have a missing parent tile (from scale + 1).
|
|
1809
|
+
// In this case the LL coefficients are missing, but dummy coefficients can be safely used instead.
|
|
1810
|
+
if (scale < wsi->max_scale) {
|
|
1811
|
+
isyntax_level_t* parent_level = wsi->levels + scale + 1;
|
|
1812
|
+
isyntax_tile_t* parent_tile = parent_level->tiles + (tile_y/2) * parent_level->width_in_tiles + (tile_x/2);
|
|
1813
|
+
return !parent_tile->exists;
|
|
1814
|
+
} else {
|
|
1815
|
+
return false;
|
|
1816
|
+
}
|
|
1817
|
+
}
|
|
1818
|
+
|
|
1760
1819
|
u32 isyntax_idwt_tile_for_color_channel(isyntax_t* isyntax, isyntax_image_t* wsi, i32 scale, i32 tile_x, i32 tile_y, i32 color, icoeff_t* dest_buffer) {
|
|
1761
1820
|
isyntax_level_t* level = wsi->levels + scale;
|
|
1762
1821
|
ASSERT(tile_x >= 0 && tile_x < level->width_in_tiles);
|
|
@@ -1824,8 +1883,12 @@ u32 isyntax_idwt_tile_for_color_channel(isyntax_t* isyntax, isyntax_image_t* wsi
|
|
|
1824
1883
|
isyntax_tile_t* source_tile = level->tiles + (tile_y-1) * level->width_in_tiles + (tile_x-1);
|
|
1825
1884
|
if (source_tile->exists) {
|
|
1826
1885
|
isyntax_tile_channel_t* color_channel = source_tile->color_channels + color;
|
|
1827
|
-
if (!color_channel->coeff_ll
|
|
1828
|
-
|
|
1886
|
+
if (!color_channel->coeff_ll && !isyntax_is_parent_tile_missing(wsi, scale, tile_y-1, tile_x-1)) {
|
|
1887
|
+
invalid_neighbors_ll |= ISYNTAX_ADJ_TILE_TOP_LEFT;
|
|
1888
|
+
}
|
|
1889
|
+
if (!color_channel->coeff_h) {
|
|
1890
|
+
invalid_neighbors_h |= ISYNTAX_ADJ_TILE_TOP_LEFT;
|
|
1891
|
+
}
|
|
1829
1892
|
get_offsetted_coeff_blocks(ll_hl_lh_hh, (top_margin_source_y * source_stride) + left_margin_source_x,
|
|
1830
1893
|
color_channel, block_stride, h_dummy_coeff, ll_dummy_coeff);
|
|
1831
1894
|
for (i32 i = 0; i < 4; ++i) {
|
|
@@ -1844,8 +1907,12 @@ u32 isyntax_idwt_tile_for_color_channel(isyntax_t* isyntax, isyntax_image_t* wsi
|
|
|
1844
1907
|
isyntax_tile_t* source_tile = level->tiles + (tile_y-1) * level->width_in_tiles + tile_x;
|
|
1845
1908
|
if (source_tile->exists) {
|
|
1846
1909
|
isyntax_tile_channel_t* color_channel = source_tile->color_channels + color;
|
|
1847
|
-
if (!color_channel->coeff_ll
|
|
1848
|
-
|
|
1910
|
+
if (!color_channel->coeff_ll && !isyntax_is_parent_tile_missing(wsi, scale, tile_y-1, tile_x)) {
|
|
1911
|
+
invalid_neighbors_ll |= ISYNTAX_ADJ_TILE_TOP_CENTER;
|
|
1912
|
+
}
|
|
1913
|
+
if (!color_channel->coeff_h) {
|
|
1914
|
+
invalid_neighbors_h |= ISYNTAX_ADJ_TILE_TOP_CENTER;
|
|
1915
|
+
}
|
|
1849
1916
|
get_offsetted_coeff_blocks(ll_hl_lh_hh, (top_margin_source_y * source_stride),
|
|
1850
1917
|
source_tile->color_channels + color, block_stride, h_dummy_coeff, ll_dummy_coeff);
|
|
1851
1918
|
for (i32 i = 0; i < 4; ++i) {
|
|
@@ -1864,8 +1931,12 @@ u32 isyntax_idwt_tile_for_color_channel(isyntax_t* isyntax, isyntax_image_t* wsi
|
|
|
1864
1931
|
isyntax_tile_t* source_tile = level->tiles + (tile_y-1) * level->width_in_tiles + (tile_x+1);
|
|
1865
1932
|
if (source_tile->exists) {
|
|
1866
1933
|
isyntax_tile_channel_t* color_channel = source_tile->color_channels + color;
|
|
1867
|
-
if (!color_channel->coeff_ll
|
|
1868
|
-
|
|
1934
|
+
if (!color_channel->coeff_ll && !isyntax_is_parent_tile_missing(wsi, scale, tile_y-1, tile_x+1)) {
|
|
1935
|
+
invalid_neighbors_ll |= ISYNTAX_ADJ_TILE_TOP_RIGHT;
|
|
1936
|
+
}
|
|
1937
|
+
if (!color_channel->coeff_h) {
|
|
1938
|
+
invalid_neighbors_h |= ISYNTAX_ADJ_TILE_TOP_RIGHT;
|
|
1939
|
+
}
|
|
1869
1940
|
get_offsetted_coeff_blocks(ll_hl_lh_hh, (top_margin_source_y * source_stride),
|
|
1870
1941
|
source_tile->color_channels + color, block_stride, h_dummy_coeff, ll_dummy_coeff);
|
|
1871
1942
|
for (i32 i = 0; i < 4; ++i) {
|
|
@@ -1884,8 +1955,12 @@ u32 isyntax_idwt_tile_for_color_channel(isyntax_t* isyntax, isyntax_image_t* wsi
|
|
|
1884
1955
|
isyntax_tile_t* source_tile = level->tiles + (tile_y) * level->width_in_tiles + (tile_x-1);
|
|
1885
1956
|
if (source_tile->exists) {
|
|
1886
1957
|
isyntax_tile_channel_t* color_channel = source_tile->color_channels + color;
|
|
1887
|
-
if (!color_channel->coeff_ll
|
|
1888
|
-
|
|
1958
|
+
if (!color_channel->coeff_ll && !isyntax_is_parent_tile_missing(wsi, scale, tile_y, tile_x-1)) {
|
|
1959
|
+
invalid_neighbors_ll |= ISYNTAX_ADJ_TILE_CENTER_LEFT;
|
|
1960
|
+
}
|
|
1961
|
+
if (!color_channel->coeff_h) {
|
|
1962
|
+
invalid_neighbors_h |= ISYNTAX_ADJ_TILE_CENTER_LEFT;
|
|
1963
|
+
}
|
|
1889
1964
|
get_offsetted_coeff_blocks(ll_hl_lh_hh, left_margin_source_x,
|
|
1890
1965
|
source_tile->color_channels + color, block_stride, h_dummy_coeff, ll_dummy_coeff);
|
|
1891
1966
|
for (i32 i = 0; i < 4; ++i) {
|
|
@@ -1919,8 +1994,12 @@ u32 isyntax_idwt_tile_for_color_channel(isyntax_t* isyntax, isyntax_image_t* wsi
|
|
|
1919
1994
|
isyntax_tile_t* source_tile = level->tiles + (tile_y) * level->width_in_tiles + (tile_x+1);
|
|
1920
1995
|
if (source_tile->exists) {
|
|
1921
1996
|
isyntax_tile_channel_t* color_channel = source_tile->color_channels + color;
|
|
1922
|
-
if (!color_channel->coeff_ll
|
|
1923
|
-
|
|
1997
|
+
if (!color_channel->coeff_ll && !isyntax_is_parent_tile_missing(wsi, scale, tile_y, tile_x+1)) {
|
|
1998
|
+
invalid_neighbors_ll |= ISYNTAX_ADJ_TILE_CENTER_RIGHT;
|
|
1999
|
+
}
|
|
2000
|
+
if (!color_channel->coeff_h) {
|
|
2001
|
+
invalid_neighbors_h |= ISYNTAX_ADJ_TILE_CENTER_RIGHT;
|
|
2002
|
+
}
|
|
1924
2003
|
get_offsetted_coeff_blocks(ll_hl_lh_hh, 0,
|
|
1925
2004
|
source_tile->color_channels + color, block_stride, h_dummy_coeff, ll_dummy_coeff);
|
|
1926
2005
|
for (i32 i = 0; i < 4; ++i) {
|
|
@@ -1939,8 +2018,12 @@ u32 isyntax_idwt_tile_for_color_channel(isyntax_t* isyntax, isyntax_image_t* wsi
|
|
|
1939
2018
|
isyntax_tile_t* source_tile = level->tiles + (tile_y+1) * level->width_in_tiles + (tile_x-1);
|
|
1940
2019
|
if (source_tile->exists) {
|
|
1941
2020
|
isyntax_tile_channel_t* color_channel = source_tile->color_channels + color;
|
|
1942
|
-
if (!color_channel->coeff_ll
|
|
1943
|
-
|
|
2021
|
+
if (!color_channel->coeff_ll && !isyntax_is_parent_tile_missing(wsi, scale, tile_y+1, tile_x-1)) {
|
|
2022
|
+
invalid_neighbors_ll |= ISYNTAX_ADJ_TILE_BOTTOM_LEFT;
|
|
2023
|
+
}
|
|
2024
|
+
if (!color_channel->coeff_h) {
|
|
2025
|
+
invalid_neighbors_h |= ISYNTAX_ADJ_TILE_BOTTOM_LEFT;
|
|
2026
|
+
}
|
|
1944
2027
|
get_offsetted_coeff_blocks(ll_hl_lh_hh, left_margin_source_x,
|
|
1945
2028
|
source_tile->color_channels + color, block_stride, h_dummy_coeff, ll_dummy_coeff);
|
|
1946
2029
|
for (i32 i = 0; i < 4; ++i) {
|
|
@@ -1959,8 +2042,12 @@ u32 isyntax_idwt_tile_for_color_channel(isyntax_t* isyntax, isyntax_image_t* wsi
|
|
|
1959
2042
|
isyntax_tile_t* source_tile = level->tiles + (tile_y+1) * level->width_in_tiles + tile_x;
|
|
1960
2043
|
if (source_tile->exists) {
|
|
1961
2044
|
isyntax_tile_channel_t* color_channel = source_tile->color_channels + color;
|
|
1962
|
-
if (!color_channel->coeff_ll
|
|
1963
|
-
|
|
2045
|
+
if (!color_channel->coeff_ll && !isyntax_is_parent_tile_missing(wsi, scale, tile_y+1, tile_x)) {
|
|
2046
|
+
invalid_neighbors_ll |= ISYNTAX_ADJ_TILE_BOTTOM_CENTER;
|
|
2047
|
+
}
|
|
2048
|
+
if (!color_channel->coeff_h) {
|
|
2049
|
+
invalid_neighbors_h |= ISYNTAX_ADJ_TILE_BOTTOM_CENTER;
|
|
2050
|
+
}
|
|
1964
2051
|
get_offsetted_coeff_blocks(ll_hl_lh_hh, 0,
|
|
1965
2052
|
source_tile->color_channels + color, block_stride, h_dummy_coeff, ll_dummy_coeff);
|
|
1966
2053
|
for (i32 i = 0; i < 4; ++i) {
|
|
@@ -1979,8 +2066,12 @@ u32 isyntax_idwt_tile_for_color_channel(isyntax_t* isyntax, isyntax_image_t* wsi
|
|
|
1979
2066
|
isyntax_tile_t* source_tile = level->tiles + (tile_y+1) * level->width_in_tiles + (tile_x+1);
|
|
1980
2067
|
if (source_tile->exists) {
|
|
1981
2068
|
isyntax_tile_channel_t* color_channel = source_tile->color_channels + color;
|
|
1982
|
-
if (!color_channel->coeff_ll
|
|
1983
|
-
|
|
2069
|
+
if (!color_channel->coeff_ll && !isyntax_is_parent_tile_missing(wsi, scale, tile_y+1, tile_x+1)) {
|
|
2070
|
+
invalid_neighbors_ll |= ISYNTAX_ADJ_TILE_BOTTOM_RIGHT;
|
|
2071
|
+
}
|
|
2072
|
+
if (!color_channel->coeff_h) {
|
|
2073
|
+
invalid_neighbors_h |= ISYNTAX_ADJ_TILE_BOTTOM_RIGHT;
|
|
2074
|
+
}
|
|
1984
2075
|
get_offsetted_coeff_blocks(ll_hl_lh_hh, 0,
|
|
1985
2076
|
source_tile->color_channels + color, block_stride, h_dummy_coeff, ll_dummy_coeff);
|
|
1986
2077
|
for (i32 i = 0; i < 4; ++i) {
|
|
@@ -2181,9 +2272,9 @@ void isyntax_load_tile(isyntax_t* isyntax, isyntax_image_t* wsi, i32 scale, i32
|
|
|
2181
2272
|
// float elapsed_rgb = get_seconds_elapsed(start, get_clock());
|
|
2182
2273
|
// console_print_verbose("load: scale=%d x=%d y=%d idwt time =%g rgb transform time=%g malloc time=%g\n", scale, tile_x, tile_y, elapsed_idwt, elapsed_rgb, elapsed_malloc);
|
|
2183
2274
|
|
|
2184
|
-
|
|
2185
|
-
stbi_write_png("debug_dwt_output.png", tile_width, tile_height, 4,
|
|
2186
|
-
}
|
|
2275
|
+
// if (scale == wsi->max_scale-1 && tile_x == 5 && tile_y == 0) {
|
|
2276
|
+
// stbi_write_png("debug_dwt_output.png", tile_width, tile_height, 4, out_buffer_or_null, tile_width * 4);
|
|
2277
|
+
// }
|
|
2187
2278
|
|
|
2188
2279
|
release_temp_memory(&temp_memory); // free Y, Co and Cg
|
|
2189
2280
|
}
|
|
@@ -3295,6 +3386,8 @@ bool isyntax_open(isyntax_t* isyntax, const char* filename, bool init_allocators
|
|
|
3295
3386
|
|
|
3296
3387
|
}
|
|
3297
3388
|
|
|
3389
|
+
// isyntax_dump_block_header(wsi_image, "test_block_header.csv");
|
|
3390
|
+
|
|
3298
3391
|
parse_ticks_elapsed += (get_clock() - parse_begin);
|
|
3299
3392
|
// console_print("iSyntax: the seektable is %u bytes, or %g%% of the total file size\n", seektable_size, (float)((float)seektable_size * 100.0f) / isyntax->filesize);
|
|
3300
3393
|
// console_print(" I/O time: %g seconds\n", get_seconds_elapsed(0, io_ticks_elapsed));
|