kfbslide 0.2.0__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.
@@ -0,0 +1,68 @@
1
+ # Byte-compiled / optimized / DLL files
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+
6
+ # C extensions
7
+ *.so
8
+
9
+ # Distribution / packaging
10
+ .Python
11
+ build/
12
+ develop-eggs/
13
+ dist/
14
+ downloads/
15
+ eggs/
16
+ .eggs/
17
+ lib/
18
+ lib64/
19
+ parts/
20
+ sdist/
21
+ var/
22
+ wheels/
23
+ *.egg-info/
24
+ .installed.cfg
25
+ *.egg
26
+
27
+ # PyInstaller
28
+ *.manifest
29
+ *.spec
30
+
31
+ # Unit test / coverage reports
32
+ htmlcov/
33
+ .tox/
34
+ .nox/
35
+ .coverage
36
+ .coverage.*
37
+ .cache
38
+ nosetests.xml
39
+ coverage.xml
40
+ *.cover
41
+ .hypothesis/
42
+ .pytest_cache/
43
+
44
+ # Virtual environments
45
+ venv/
46
+ ENV/
47
+ env/
48
+ .venv
49
+
50
+ # IDEs
51
+ .vscode/
52
+ .idea/
53
+ *.swp
54
+ *.swo
55
+ *~
56
+
57
+ # OS
58
+ .DS_Store
59
+ Thumbs.db
60
+
61
+ # KFB test files (large binaries)
62
+ *.kfb
63
+ *.tif
64
+ *.svs
65
+ *.ndpi
66
+
67
+ # Test output cache
68
+ cache/
kfbslide-0.2.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Yifan Feng
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,246 @@
1
+ Metadata-Version: 2.4
2
+ Name: kfbslide
3
+ Version: 0.2.0
4
+ Summary: Pure Python KFB whole-slide image reader with OpenSlide-compatible API
5
+ Project-URL: Homepage, https://github.com/yifanfeng97/kfbslide
6
+ Project-URL: Documentation, https://github.com/yifanfeng97/kfbslide#readme
7
+ Project-URL: Repository, https://github.com/yifanfeng97/kfbslide
8
+ Project-URL: Issues, https://github.com/yifanfeng97/kfbslide/issues
9
+ Author-email: Yifan Feng <evanfeng97@gmail.com>
10
+ License-Expression: MIT
11
+ License-File: LICENSE
12
+ Keywords: digital-pathology,kfb,kfbio,openslide,pathology,whole-slide-image,wsi
13
+ Classifier: Development Status :: 4 - Beta
14
+ Classifier: Intended Audience :: Science/Research
15
+ Classifier: License :: OSI Approved :: MIT License
16
+ Classifier: Programming Language :: Python :: 3
17
+ Classifier: Programming Language :: Python :: 3.10
18
+ Classifier: Programming Language :: Python :: 3.11
19
+ Classifier: Programming Language :: Python :: 3.12
20
+ Classifier: Programming Language :: Python :: 3.13
21
+ Classifier: Topic :: Scientific/Engineering :: Image Processing
22
+ Classifier: Topic :: Scientific/Engineering :: Medical Science Apps.
23
+ Requires-Python: >=3.10
24
+ Requires-Dist: pillow>=9.0.0
25
+ Provides-Extra: dev
26
+ Requires-Dist: mypy; extra == 'dev'
27
+ Requires-Dist: pytest-cov; extra == 'dev'
28
+ Requires-Dist: pytest>=7.0; extra == 'dev'
29
+ Requires-Dist: ruff; extra == 'dev'
30
+ Description-Content-Type: text/markdown
31
+
32
+ <h1 align="center">KFBSlide</h1>
33
+
34
+ <p align="center">
35
+ <strong>A pure-Python KFB (KFBio) whole-slide image reader with an OpenSlide-compatible API</strong>
36
+ </p>
37
+
38
+ <p align="center">
39
+ <a href="README.md">English</a> |
40
+ <a href="README_zh.md">简体中文</a>
41
+ </p>
42
+
43
+ <p align="center">
44
+ <a href="https://pypi.org/project/kfbslide"><img src="https://img.shields.io/pypi/v/kfbslide?color=blue" alt="PyPI"></a>
45
+ <a href="https://pypi.org/project/kfbslide"><img src="https://img.shields.io/pypi/pyversions/kfbslide" alt="Python Versions"></a>
46
+ <a href="https://github.com/yifanfeng97/kfbslide/blob/main/LICENSE"><img src="https://img.shields.io/badge/license-MIT-green" alt="License"></a>
47
+ <a href="https://pypi.org/project/kfbslide"><img src="https://img.shields.io/pypi/dm/kfbslide?color=orange" alt="Downloads"></a>
48
+ <a href="https://github.com/yifanfeng97/kfbslide"><img src="https://img.shields.io/github/stars/yifanfeng97/kfbslide?style=social" alt="Stars"></a>
49
+ </p>
50
+
51
+ <p align="center">
52
+ <a href="#-features">✨ Features</a> •
53
+ <a href="#-installation">📦 Installation</a> •
54
+ <a href="#-quick-start">🚀 Quick Start</a> •
55
+ <a href="#-api-reference">📖 API</a> •
56
+ <a href="#-performance">⚡ Performance</a>
57
+ </p>
58
+
59
+ <p align="center">
60
+ <img src="docs/banner.png" alt="KFBSlide Banner" width="900">
61
+ </p>
62
+
63
+ ---
64
+
65
+ ## ✨ Features
66
+
67
+ - 🐍 **Pure Python** — Zero native dependencies, works out of the box on Windows / macOS / Linux
68
+ - 🔄 **OpenSlide-Compatible API** — Drop-in replacement for `openslide-python`, no code changes needed
69
+ - 🔺 **Multi-Level Pyramids** — Automatically parses 40× / 20× / 10× / 5× / 2.5× / 1.25× levels inside KFB
70
+ - 🖼️ **Associated Images** — Supports macro, label, and thumbnail
71
+ - ⚡ **Tile LRU Cache** — 10~20× speedup for repeated reads of the same region
72
+ - 📊 **Full Metadata** — MPP, objective power, tile size, and more
73
+
74
+ ---
75
+
76
+ ## 📦 Installation
77
+
78
+ ### Using uv (recommended)
79
+
80
+ ```bash
81
+ uv pip install kfbslide
82
+ ```
83
+
84
+ ### Using pip
85
+
86
+ ```bash
87
+ pip install kfbslide
88
+ ```
89
+
90
+ Only depends on Pillow — installs directly on any platform.
91
+
92
+ ---
93
+
94
+ ## 🚀 Quick Start
95
+
96
+ ### Drop-in replacement for OpenSlide
97
+
98
+ ```python
99
+ import kfbslide as openslide
100
+
101
+ slide = openslide.OpenSlide("path/to/sample.kfb")
102
+
103
+ print(f"Levels: {slide.level_count}")
104
+ print(f"Level 0 dimensions: {slide.dimensions}")
105
+ for i in range(slide.level_count):
106
+ print(f" Level {i}: {slide.level_dimensions[i]} "
107
+ f"downsample={slide.level_downsamples[i]}")
108
+
109
+ # Read a region (location in level-0 coordinates, returns RGBA)
110
+ img = slide.read_region((1000, 2000), 0, (256, 256))
111
+ img.save("region.png")
112
+
113
+ # Thumbnail
114
+ thumb = slide.get_thumbnail((512, 512))
115
+ thumb.save("thumbnail.png")
116
+
117
+ # Associated images
118
+ macro = slide.associated_images["macro"]
119
+ macro.save("macro.png")
120
+
121
+ # Property access
122
+ vendor = slide.properties[openslide.PROPERTY_NAME_VENDOR]
123
+ mpp_x = slide.properties[openslide.PROPERTY_NAME_MPP_X]
124
+
125
+ slide.close()
126
+ ```
127
+
128
+ ### Context manager
129
+
130
+ ```python
131
+ with openslide.OpenSlide("sample.kfb") as slide:
132
+ img = slide.read_region((0, 0), 0, (256, 256))
133
+ # Automatically closed
134
+ ```
135
+
136
+ ---
137
+
138
+ ## 📖 API Reference
139
+
140
+ ### `OpenSlide(filename)`
141
+
142
+ Open a KFB file.
143
+
144
+ ### Class methods
145
+
146
+ | Method | Description |
147
+ |--------|-------------|
148
+ | `OpenSlide.detect_format(filename)` | Detect file format, returns `"kfbio"` or `None` |
149
+
150
+ ### Properties
151
+
152
+ | Property | Type | Description |
153
+ |----------|------|-------------|
154
+ | `level_count` | `int` | Number of pyramid levels |
155
+ | `dimensions` | `(int, int)` | Level 0 dimensions (highest resolution) |
156
+ | `level_dimensions` | `Tuple[(w, h), ...]` | Dimensions of each level |
157
+ | `level_downsamples` | `Tuple[float, ...]` | Downsample factor for each level |
158
+ | `properties` | `Mapping[str, str]` | Metadata properties (read-only mapping) |
159
+ | `associated_images` | `Mapping[str, PIL.Image]` | Associated images: macro, label, thumbnail |
160
+ | `color_profile` | `object \| None` | ICC color profile (currently returns `None`) |
161
+
162
+ ### Methods
163
+
164
+ | Method | Description |
165
+ |--------|-------------|
166
+ | `read_region(location, level, size)` | Read a region, returns **RGBA** image |
167
+ | `get_best_level_for_downsample(downsample)` | Pick the best pyramid level for a given downsample factor |
168
+ | `get_thumbnail(size)` | Generate a thumbnail |
169
+ | `set_cache(cache)` | API-compatible no-op |
170
+ | `close()` | Close and release resources |
171
+
172
+ ### Property constants
173
+
174
+ ```python
175
+ from kfbslide import (
176
+ PROPERTY_NAME_VENDOR, # "openslide.vendor"
177
+ PROPERTY_NAME_MPP_X, # "openslide.mpp-x"
178
+ PROPERTY_NAME_MPP_Y, # "openslide.mpp-y"
179
+ PROPERTY_NAME_OBJECTIVE_POWER, # "openslide.objective-power"
180
+ )
181
+ ```
182
+
183
+ ---
184
+
185
+ ## ⚡ Performance
186
+
187
+ Benchmarked on `sample.kfb` (71,748 × 56,282, 82,595 tiles):
188
+
189
+ | Operation | Time | Note |
190
+ |-----------|------|------|
191
+ | First read of 256×256 region | ~2.1 ms | Pillow backend |
192
+ | Cache-hit read | **~0.10 ms** | 22× faster |
193
+ | Scan 20 adjacent regions (first time) | ~33 ms | 1.6 ms/region |
194
+ | Scan 20 adjacent regions (cached) | **~2.2 ms** | 0.11 ms/region, 15× faster |
195
+
196
+ > Test environment: Python 3.12, Pillow, SSD.
197
+
198
+ ---
199
+
200
+ ## 🏗️ Architecture
201
+
202
+ <p align="center">
203
+ <img src="docs/fw_en.png" alt="KFBSlide Architecture" width="800">
204
+ </p>
205
+
206
+ KFBSlide is implemented entirely in pure Python, reading images by directly parsing the KFB binary format:
207
+
208
+ - **No C/C++ extensions or system dynamic libraries required**
209
+ - **No dependency on OpenSlide, libtiff, libjpeg, or other external libraries**
210
+ - **Single-file deployable, suitable for servers, containers, and embedded environments**
211
+
212
+ ---
213
+
214
+ ## 📁 Project Structure
215
+
216
+ ```
217
+ kfbslide/
218
+ ├── src/kfbslide/
219
+ │ ├── __init__.py # Package entry point, exports OpenSlide API
220
+ │ ├── _slide.py # OpenSlide main class
221
+ │ ├── _kfbformat.py # KFB binary format parser
222
+ │ ├── _cache.py # LRU tile cache
223
+ │ └── _exceptions.py # OpenSlideError / compatibility exceptions
224
+ ├── tests/ # Tests (includes sample.kfb symlink)
225
+ ├── examples/ # Example scripts
226
+ ├── docs/ # Documentation images
227
+ ├── README.md
228
+ ├── LICENSE
229
+ └── pyproject.toml
230
+ ```
231
+
232
+ ---
233
+
234
+ ## ⚠️ Known Limitations
235
+
236
+ 1. **Read-only**: Writing to KFB files is not currently supported.
237
+ 2. **KFB v1.6**: Verified on version 1.6 files. Other versions may require adaptation.
238
+ 3. **JPEG decoding**: Uses Pillow for JPEG decoding, consistent across all platforms.
239
+
240
+ ---
241
+
242
+ ## 📄 License
243
+
244
+ [MIT](LICENSE)
245
+
246
+ Copyright (c) 2026 Yifan Feng
@@ -0,0 +1,215 @@
1
+ <h1 align="center">KFBSlide</h1>
2
+
3
+ <p align="center">
4
+ <strong>A pure-Python KFB (KFBio) whole-slide image reader with an OpenSlide-compatible API</strong>
5
+ </p>
6
+
7
+ <p align="center">
8
+ <a href="README.md">English</a> |
9
+ <a href="README_zh.md">简体中文</a>
10
+ </p>
11
+
12
+ <p align="center">
13
+ <a href="https://pypi.org/project/kfbslide"><img src="https://img.shields.io/pypi/v/kfbslide?color=blue" alt="PyPI"></a>
14
+ <a href="https://pypi.org/project/kfbslide"><img src="https://img.shields.io/pypi/pyversions/kfbslide" alt="Python Versions"></a>
15
+ <a href="https://github.com/yifanfeng97/kfbslide/blob/main/LICENSE"><img src="https://img.shields.io/badge/license-MIT-green" alt="License"></a>
16
+ <a href="https://pypi.org/project/kfbslide"><img src="https://img.shields.io/pypi/dm/kfbslide?color=orange" alt="Downloads"></a>
17
+ <a href="https://github.com/yifanfeng97/kfbslide"><img src="https://img.shields.io/github/stars/yifanfeng97/kfbslide?style=social" alt="Stars"></a>
18
+ </p>
19
+
20
+ <p align="center">
21
+ <a href="#-features">✨ Features</a> •
22
+ <a href="#-installation">📦 Installation</a> •
23
+ <a href="#-quick-start">🚀 Quick Start</a> •
24
+ <a href="#-api-reference">📖 API</a> •
25
+ <a href="#-performance">⚡ Performance</a>
26
+ </p>
27
+
28
+ <p align="center">
29
+ <img src="docs/banner.png" alt="KFBSlide Banner" width="900">
30
+ </p>
31
+
32
+ ---
33
+
34
+ ## ✨ Features
35
+
36
+ - 🐍 **Pure Python** — Zero native dependencies, works out of the box on Windows / macOS / Linux
37
+ - 🔄 **OpenSlide-Compatible API** — Drop-in replacement for `openslide-python`, no code changes needed
38
+ - 🔺 **Multi-Level Pyramids** — Automatically parses 40× / 20× / 10× / 5× / 2.5× / 1.25× levels inside KFB
39
+ - 🖼️ **Associated Images** — Supports macro, label, and thumbnail
40
+ - ⚡ **Tile LRU Cache** — 10~20× speedup for repeated reads of the same region
41
+ - 📊 **Full Metadata** — MPP, objective power, tile size, and more
42
+
43
+ ---
44
+
45
+ ## 📦 Installation
46
+
47
+ ### Using uv (recommended)
48
+
49
+ ```bash
50
+ uv pip install kfbslide
51
+ ```
52
+
53
+ ### Using pip
54
+
55
+ ```bash
56
+ pip install kfbslide
57
+ ```
58
+
59
+ Only depends on Pillow — installs directly on any platform.
60
+
61
+ ---
62
+
63
+ ## 🚀 Quick Start
64
+
65
+ ### Drop-in replacement for OpenSlide
66
+
67
+ ```python
68
+ import kfbslide as openslide
69
+
70
+ slide = openslide.OpenSlide("path/to/sample.kfb")
71
+
72
+ print(f"Levels: {slide.level_count}")
73
+ print(f"Level 0 dimensions: {slide.dimensions}")
74
+ for i in range(slide.level_count):
75
+ print(f" Level {i}: {slide.level_dimensions[i]} "
76
+ f"downsample={slide.level_downsamples[i]}")
77
+
78
+ # Read a region (location in level-0 coordinates, returns RGBA)
79
+ img = slide.read_region((1000, 2000), 0, (256, 256))
80
+ img.save("region.png")
81
+
82
+ # Thumbnail
83
+ thumb = slide.get_thumbnail((512, 512))
84
+ thumb.save("thumbnail.png")
85
+
86
+ # Associated images
87
+ macro = slide.associated_images["macro"]
88
+ macro.save("macro.png")
89
+
90
+ # Property access
91
+ vendor = slide.properties[openslide.PROPERTY_NAME_VENDOR]
92
+ mpp_x = slide.properties[openslide.PROPERTY_NAME_MPP_X]
93
+
94
+ slide.close()
95
+ ```
96
+
97
+ ### Context manager
98
+
99
+ ```python
100
+ with openslide.OpenSlide("sample.kfb") as slide:
101
+ img = slide.read_region((0, 0), 0, (256, 256))
102
+ # Automatically closed
103
+ ```
104
+
105
+ ---
106
+
107
+ ## 📖 API Reference
108
+
109
+ ### `OpenSlide(filename)`
110
+
111
+ Open a KFB file.
112
+
113
+ ### Class methods
114
+
115
+ | Method | Description |
116
+ |--------|-------------|
117
+ | `OpenSlide.detect_format(filename)` | Detect file format, returns `"kfbio"` or `None` |
118
+
119
+ ### Properties
120
+
121
+ | Property | Type | Description |
122
+ |----------|------|-------------|
123
+ | `level_count` | `int` | Number of pyramid levels |
124
+ | `dimensions` | `(int, int)` | Level 0 dimensions (highest resolution) |
125
+ | `level_dimensions` | `Tuple[(w, h), ...]` | Dimensions of each level |
126
+ | `level_downsamples` | `Tuple[float, ...]` | Downsample factor for each level |
127
+ | `properties` | `Mapping[str, str]` | Metadata properties (read-only mapping) |
128
+ | `associated_images` | `Mapping[str, PIL.Image]` | Associated images: macro, label, thumbnail |
129
+ | `color_profile` | `object \| None` | ICC color profile (currently returns `None`) |
130
+
131
+ ### Methods
132
+
133
+ | Method | Description |
134
+ |--------|-------------|
135
+ | `read_region(location, level, size)` | Read a region, returns **RGBA** image |
136
+ | `get_best_level_for_downsample(downsample)` | Pick the best pyramid level for a given downsample factor |
137
+ | `get_thumbnail(size)` | Generate a thumbnail |
138
+ | `set_cache(cache)` | API-compatible no-op |
139
+ | `close()` | Close and release resources |
140
+
141
+ ### Property constants
142
+
143
+ ```python
144
+ from kfbslide import (
145
+ PROPERTY_NAME_VENDOR, # "openslide.vendor"
146
+ PROPERTY_NAME_MPP_X, # "openslide.mpp-x"
147
+ PROPERTY_NAME_MPP_Y, # "openslide.mpp-y"
148
+ PROPERTY_NAME_OBJECTIVE_POWER, # "openslide.objective-power"
149
+ )
150
+ ```
151
+
152
+ ---
153
+
154
+ ## ⚡ Performance
155
+
156
+ Benchmarked on `sample.kfb` (71,748 × 56,282, 82,595 tiles):
157
+
158
+ | Operation | Time | Note |
159
+ |-----------|------|------|
160
+ | First read of 256×256 region | ~2.1 ms | Pillow backend |
161
+ | Cache-hit read | **~0.10 ms** | 22× faster |
162
+ | Scan 20 adjacent regions (first time) | ~33 ms | 1.6 ms/region |
163
+ | Scan 20 adjacent regions (cached) | **~2.2 ms** | 0.11 ms/region, 15× faster |
164
+
165
+ > Test environment: Python 3.12, Pillow, SSD.
166
+
167
+ ---
168
+
169
+ ## 🏗️ Architecture
170
+
171
+ <p align="center">
172
+ <img src="docs/fw_en.png" alt="KFBSlide Architecture" width="800">
173
+ </p>
174
+
175
+ KFBSlide is implemented entirely in pure Python, reading images by directly parsing the KFB binary format:
176
+
177
+ - **No C/C++ extensions or system dynamic libraries required**
178
+ - **No dependency on OpenSlide, libtiff, libjpeg, or other external libraries**
179
+ - **Single-file deployable, suitable for servers, containers, and embedded environments**
180
+
181
+ ---
182
+
183
+ ## 📁 Project Structure
184
+
185
+ ```
186
+ kfbslide/
187
+ ├── src/kfbslide/
188
+ │ ├── __init__.py # Package entry point, exports OpenSlide API
189
+ │ ├── _slide.py # OpenSlide main class
190
+ │ ├── _kfbformat.py # KFB binary format parser
191
+ │ ├── _cache.py # LRU tile cache
192
+ │ └── _exceptions.py # OpenSlideError / compatibility exceptions
193
+ ├── tests/ # Tests (includes sample.kfb symlink)
194
+ ├── examples/ # Example scripts
195
+ ├── docs/ # Documentation images
196
+ ├── README.md
197
+ ├── LICENSE
198
+ └── pyproject.toml
199
+ ```
200
+
201
+ ---
202
+
203
+ ## ⚠️ Known Limitations
204
+
205
+ 1. **Read-only**: Writing to KFB files is not currently supported.
206
+ 2. **KFB v1.6**: Verified on version 1.6 files. Other versions may require adaptation.
207
+ 3. **JPEG decoding**: Uses Pillow for JPEG decoding, consistent across all platforms.
208
+
209
+ ---
210
+
211
+ ## 📄 License
212
+
213
+ [MIT](LICENSE)
214
+
215
+ Copyright (c) 2026 Yifan Feng
@@ -0,0 +1,56 @@
1
+ """
2
+ Example: read regions from a KFB file using the OpenSlide-compatible API.
3
+
4
+ Usage:
5
+ python examples/read_region.py path/to/sample.kfb
6
+
7
+ Author: Yifan Feng <evanfeng97@gmail.com>
8
+ """
9
+
10
+ import sys
11
+
12
+ from kfbslide import OpenSlide, PROPERTY_NAME_VENDOR, PROPERTY_NAME_MPP_X
13
+
14
+
15
+ def main():
16
+ if len(sys.argv) < 2:
17
+ print(f"Usage: {sys.argv[0]} <path/to/sample.kfb>")
18
+ sys.exit(1)
19
+
20
+ path = sys.argv[1]
21
+
22
+ # OpenSlide-compatible usage
23
+ slide = OpenSlide(path)
24
+
25
+ print(f"level_count: {slide.level_count}")
26
+ print(f"dimensions (level 0): {slide.dimensions}")
27
+ for i in range(slide.level_count):
28
+ w, h = slide.level_dimensions[i]
29
+ ds = slide.level_downsamples[i]
30
+ print(f" Level {i}: {w}x{h}, downsample={ds}")
31
+
32
+ # Read a 256x256 region at level 0 (returns RGBA)
33
+ img = slide.read_region((0, 0), 0, (256, 256))
34
+ print(f"Region mode: {img.mode}")
35
+ img.save("region_0_0.png")
36
+
37
+ # Get thumbnail
38
+ thumb = slide.get_thumbnail((512, 512))
39
+ thumb.save("thumbnail.jpg")
40
+
41
+ # Access associated images lazily
42
+ for name in slide.associated_images.keys():
43
+ assoc_img = slide.associated_images[name]
44
+ assoc_img.save(f"{name}.jpg")
45
+ print(f"Saved {name}: {assoc_img.size} mode={assoc_img.mode}")
46
+
47
+ # Properties
48
+ props = slide.properties
49
+ print(f"Vendor: {props.get(PROPERTY_NAME_VENDOR)}")
50
+ print(f"MPP-X: {props.get(PROPERTY_NAME_MPP_X)}")
51
+
52
+ slide.close()
53
+
54
+
55
+ if __name__ == "__main__":
56
+ main()
@@ -0,0 +1,77 @@
1
+ [build-system]
2
+ requires = ["hatchling"]
3
+ build-backend = "hatchling.build"
4
+
5
+ [project]
6
+ name = "kfbslide"
7
+ version = "0.2.0"
8
+ description = "Pure Python KFB whole-slide image reader with OpenSlide-compatible API"
9
+ readme = "README.md"
10
+ license = "MIT"
11
+ requires-python = ">=3.10"
12
+ authors = [
13
+ { name = "Yifan Feng", email = "evanfeng97@gmail.com" },
14
+ ]
15
+ keywords = [
16
+ "kfb",
17
+ "whole-slide-image",
18
+ "openslide",
19
+ "pathology",
20
+ "wsi",
21
+ "kfbio",
22
+ "digital-pathology",
23
+ ]
24
+ classifiers = [
25
+ "Development Status :: 4 - Beta",
26
+ "Intended Audience :: Science/Research",
27
+ "License :: OSI Approved :: MIT License",
28
+ "Programming Language :: Python :: 3",
29
+ "Programming Language :: Python :: 3.10",
30
+ "Programming Language :: Python :: 3.11",
31
+ "Programming Language :: Python :: 3.12",
32
+ "Programming Language :: Python :: 3.13",
33
+ "Topic :: Scientific/Engineering :: Image Processing",
34
+ "Topic :: Scientific/Engineering :: Medical Science Apps.",
35
+ ]
36
+ dependencies = [
37
+ "Pillow>=9.0.0",
38
+ ]
39
+
40
+ [project.optional-dependencies]
41
+ dev = [
42
+ "pytest>=7.0",
43
+ "pytest-cov",
44
+ "ruff",
45
+ "mypy",
46
+ ]
47
+
48
+ [project.urls]
49
+ Homepage = "https://github.com/yifanfeng97/kfbslide"
50
+ Documentation = "https://github.com/yifanfeng97/kfbslide#readme"
51
+ Repository = "https://github.com/yifanfeng97/kfbslide"
52
+ Issues = "https://github.com/yifanfeng97/kfbslide/issues"
53
+
54
+ [tool.hatch.build.targets.wheel]
55
+ packages = ["src/kfbslide"]
56
+
57
+ [tool.hatch.build.targets.sdist]
58
+ include = [
59
+ "/src",
60
+ "/tests",
61
+ "/examples",
62
+ "/README.md",
63
+ "/LICENSE",
64
+ ]
65
+
66
+ [tool.ruff]
67
+ line-length = 100
68
+ select = ["E", "F", "I", "W"]
69
+
70
+ [tool.mypy]
71
+ python_version = "3.10"
72
+ warn_return_any = true
73
+ warn_unused_configs = true
74
+ disallow_untyped_defs = false
75
+
76
+ [tool.pytest.ini_options]
77
+ pythonpath = ["src"]