/src/gdal/frmts/zarr/zarr_v3_codec.h
Line | Count | Source |
1 | | /****************************************************************************** |
2 | | * |
3 | | * Project: GDAL |
4 | | * Purpose: Zarr driver |
5 | | * Author: Even Rouault <even dot rouault at spatialys.com> |
6 | | * |
7 | | ****************************************************************************** |
8 | | * Copyright (c) 2021, Even Rouault <even dot rouault at spatialys.com> |
9 | | * |
10 | | * SPDX-License-Identifier: MIT |
11 | | ****************************************************************************/ |
12 | | |
13 | | #ifndef ZARR_V3_CODEC_H |
14 | | #define ZARR_V3_CODEC_H |
15 | | |
16 | | #include "zarr.h" |
17 | | |
18 | | struct VSIVirtualHandle; |
19 | | |
20 | | /************************************************************************/ |
21 | | /* ZarrArrayMetadata */ |
22 | | /************************************************************************/ |
23 | | |
24 | | /** Array-related metadata needed for the good working of Zarr V3 codecs */ |
25 | | struct ZarrArrayMetadata |
26 | | { |
27 | | /** Data type of the array */ |
28 | | DtypeElt oElt{}; |
29 | | |
30 | | /** Shape of a block/chunk */ |
31 | | std::vector<size_t> anBlockSizes{}; |
32 | | |
33 | | /** No data value of the array. Empty or abyNoData.size() == oElt.nNativeSize */ |
34 | | std::vector<GByte> abyNoData{}; |
35 | | }; |
36 | | |
37 | | /************************************************************************/ |
38 | | /* ZarrV3Codec */ |
39 | | /************************************************************************/ |
40 | | |
41 | | /** Abstract class for a Zarr V3 codec */ |
42 | | class ZarrV3Codec CPL_NON_FINAL |
43 | | { |
44 | | protected: |
45 | | const std::string m_osName; |
46 | | CPLJSONObject m_oConfiguration{}; |
47 | | ZarrArrayMetadata m_oInputArrayMetadata{}; |
48 | | |
49 | | ZarrV3Codec(const std::string &osName); |
50 | | |
51 | | public: |
52 | | virtual ~ZarrV3Codec(); |
53 | | |
54 | | enum class IOType |
55 | | { |
56 | | BYTES, |
57 | | ARRAY |
58 | | }; |
59 | | |
60 | | virtual IOType GetInputType() const = 0; |
61 | | virtual IOType GetOutputType() const = 0; |
62 | | |
63 | | virtual bool InitFromConfiguration( |
64 | | const std::string &osArrayName, const CPLJSONObject &configuration, |
65 | | const ZarrArrayMetadata &oInputArrayMetadata, |
66 | | ZarrArrayMetadata &oOutputArrayMetadata, bool bEmitWarnings) = 0; |
67 | | |
68 | | virtual std::unique_ptr<ZarrV3Codec> Clone() const = 0; |
69 | | |
70 | | virtual bool IsNoOp() const |
71 | 0 | { |
72 | 0 | return false; |
73 | 0 | } |
74 | | |
75 | | virtual bool Encode(const ZarrByteVectorQuickResize &abySrc, |
76 | | ZarrByteVectorQuickResize &abyDst) const = 0; |
77 | | virtual bool Decode(const ZarrByteVectorQuickResize &abySrc, |
78 | | ZarrByteVectorQuickResize &abyDst) const = 0; |
79 | | |
80 | | /** Partial decoding. |
81 | | * anStartIdx[i]: coordinate in pixel, within the array of an outer chunk, |
82 | | * that is < m_oInputArrayMetadata.anBlockSizes[i] |
83 | | * anCount[i]: number of pixels to extract <= m_oInputArrayMetadata.anBlockSizes[i] |
84 | | */ |
85 | | virtual bool DecodePartial(VSIVirtualHandle *poFile, |
86 | | const ZarrByteVectorQuickResize &abySrc, |
87 | | ZarrByteVectorQuickResize &abyDst, |
88 | | std::vector<size_t> &anStartIdx, |
89 | | std::vector<size_t> &anCount); |
90 | | |
91 | | const std::string &GetName() const |
92 | 148 | { |
93 | 148 | return m_osName; |
94 | 148 | } |
95 | | |
96 | | const CPLJSONObject &GetConfiguration() const |
97 | 0 | { |
98 | 0 | return m_oConfiguration; |
99 | 0 | } |
100 | | |
101 | | virtual std::vector<size_t> |
102 | | GetInnerMostBlockSize(const std::vector<size_t> &input) const |
103 | 0 | { |
104 | 0 | return input; |
105 | 0 | } |
106 | | |
107 | | virtual void ChangeArrayShapeForward(std::vector<size_t> &anStartIdx, |
108 | | std::vector<size_t> &anCount) |
109 | 0 | { |
110 | 0 | (void)anStartIdx; |
111 | 0 | (void)anCount; |
112 | 0 | } |
113 | | }; |
114 | | |
115 | | /************************************************************************/ |
116 | | /* ZarrV3CodecAbstractCompressor */ |
117 | | /************************************************************************/ |
118 | | |
119 | | class ZarrV3CodecAbstractCompressor CPL_NON_FINAL : public ZarrV3Codec |
120 | | { |
121 | | protected: |
122 | | CPLStringList m_aosCompressorOptions{}; |
123 | | const CPLCompressor *m_pDecompressor = nullptr; |
124 | | const CPLCompressor *m_pCompressor = nullptr; |
125 | | |
126 | | explicit ZarrV3CodecAbstractCompressor(const std::string &osName); |
127 | | |
128 | | ZarrV3CodecAbstractCompressor(const ZarrV3CodecAbstractCompressor &) = |
129 | | delete; |
130 | | ZarrV3CodecAbstractCompressor & |
131 | | operator=(const ZarrV3CodecAbstractCompressor &) = delete; |
132 | | |
133 | | public: |
134 | | IOType GetInputType() const override |
135 | 0 | { |
136 | 0 | return IOType::BYTES; |
137 | 0 | } |
138 | | |
139 | | IOType GetOutputType() const override |
140 | 0 | { |
141 | 0 | return IOType::BYTES; |
142 | 0 | } |
143 | | |
144 | | bool Encode(const ZarrByteVectorQuickResize &abySrc, |
145 | | ZarrByteVectorQuickResize &abyDst) const override; |
146 | | bool Decode(const ZarrByteVectorQuickResize &abySrc, |
147 | | ZarrByteVectorQuickResize &abyDst) const override; |
148 | | }; |
149 | | |
150 | | /************************************************************************/ |
151 | | /* ZarrV3CodecGZip */ |
152 | | /************************************************************************/ |
153 | | |
154 | | // Implements https://zarr-specs.readthedocs.io/en/latest/v3/codecs/gzip/v1.0.html |
155 | | class ZarrV3CodecGZip final : public ZarrV3CodecAbstractCompressor |
156 | | { |
157 | | public: |
158 | | static constexpr const char *NAME = "gzip"; |
159 | | |
160 | | ZarrV3CodecGZip(); |
161 | | |
162 | | static CPLJSONObject GetConfiguration(int nLevel); |
163 | | |
164 | | bool InitFromConfiguration(const std::string &osArrayName, |
165 | | const CPLJSONObject &configuration, |
166 | | const ZarrArrayMetadata &oInputArrayMetadata, |
167 | | ZarrArrayMetadata &oOutputArrayMetadata, |
168 | | bool bEmitWarnings) override; |
169 | | |
170 | | std::unique_ptr<ZarrV3Codec> Clone() const override; |
171 | | }; |
172 | | |
173 | | /************************************************************************/ |
174 | | /* ZarrV3CodecBlosc */ |
175 | | /************************************************************************/ |
176 | | |
177 | | // Implements https://zarr-specs.readthedocs.io/en/latest/v3/codecs/blosc/v1.0.html |
178 | | class ZarrV3CodecBlosc final : public ZarrV3CodecAbstractCompressor |
179 | | { |
180 | | public: |
181 | | static constexpr const char *NAME = "blosc"; |
182 | | |
183 | | ZarrV3CodecBlosc(); |
184 | | |
185 | | static CPLJSONObject GetConfiguration(const char *cname, int clevel, |
186 | | const char *shuffle, int typesize, |
187 | | int blocksize); |
188 | | |
189 | | bool InitFromConfiguration(const std::string &osArrayName, |
190 | | const CPLJSONObject &configuration, |
191 | | const ZarrArrayMetadata &oInputArrayMetadata, |
192 | | ZarrArrayMetadata &oOutputArrayMetadata, |
193 | | bool bEmitWarnings) override; |
194 | | |
195 | | std::unique_ptr<ZarrV3Codec> Clone() const override; |
196 | | }; |
197 | | |
198 | | /************************************************************************/ |
199 | | /* ZarrV3CodecZstd */ |
200 | | /************************************************************************/ |
201 | | |
202 | | // Implements https://github.com/zarr-developers/zarr-specs/pull/256 |
203 | | class ZarrV3CodecZstd final : public ZarrV3CodecAbstractCompressor |
204 | | { |
205 | | public: |
206 | | static constexpr const char *NAME = "zstd"; |
207 | | |
208 | | ZarrV3CodecZstd(); |
209 | | |
210 | | static CPLJSONObject GetConfiguration(int level, bool checksum); |
211 | | |
212 | | bool InitFromConfiguration(const std::string &osArrayName, |
213 | | const CPLJSONObject &configuration, |
214 | | const ZarrArrayMetadata &oInputArrayMetadata, |
215 | | ZarrArrayMetadata &oOutputArrayMetadata, |
216 | | bool bEmitWarnings) override; |
217 | | |
218 | | std::unique_ptr<ZarrV3Codec> Clone() const override; |
219 | | }; |
220 | | |
221 | | /************************************************************************/ |
222 | | /* ZarrV3CodecBytes */ |
223 | | /************************************************************************/ |
224 | | |
225 | | // Implements https://zarr-specs.readthedocs.io/en/latest/v3/codecs/bytes/v1.0.html |
226 | | class ZarrV3CodecBytes final : public ZarrV3Codec |
227 | | { |
228 | | bool m_bLittle = true; |
229 | | |
230 | | public: |
231 | | static constexpr const char *NAME = "bytes"; |
232 | | |
233 | | ZarrV3CodecBytes(); |
234 | | |
235 | | IOType GetInputType() const override |
236 | 148 | { |
237 | 148 | return IOType::ARRAY; |
238 | 148 | } |
239 | | |
240 | | IOType GetOutputType() const override |
241 | 148 | { |
242 | 148 | return IOType::BYTES; |
243 | 148 | } |
244 | | |
245 | | static CPLJSONObject GetConfiguration(bool bLittle); |
246 | | |
247 | | bool InitFromConfiguration(const std::string &osArrayName, |
248 | | const CPLJSONObject &configuration, |
249 | | const ZarrArrayMetadata &oInputArrayMetadata, |
250 | | ZarrArrayMetadata &oOutputArrayMetadata, |
251 | | bool bEmitWarnings) override; |
252 | | |
253 | | bool IsLittle() const |
254 | 0 | { |
255 | 0 | return m_bLittle; |
256 | 0 | } |
257 | | |
258 | | bool IsNoOp() const override |
259 | 148 | { |
260 | | // Byte-oriented string types have no endianness concept |
261 | 148 | if (m_oInputArrayMetadata.oElt.nativeType == |
262 | 148 | DtypeElt::NativeType::STRING_ASCII) |
263 | 0 | return true; |
264 | | if constexpr (CPL_IS_LSB) |
265 | 148 | return m_oInputArrayMetadata.oElt.nativeSize == 1 || m_bLittle; |
266 | | else |
267 | | return m_oInputArrayMetadata.oElt.nativeSize == 1 || !m_bLittle; |
268 | 148 | } |
269 | | |
270 | | std::unique_ptr<ZarrV3Codec> Clone() const override; |
271 | | |
272 | | bool Encode(const ZarrByteVectorQuickResize &abySrc, |
273 | | ZarrByteVectorQuickResize &abyDst) const override; |
274 | | bool Decode(const ZarrByteVectorQuickResize &abySrc, |
275 | | ZarrByteVectorQuickResize &abyDst) const override; |
276 | | }; |
277 | | |
278 | | /************************************************************************/ |
279 | | /* ZarrV3CodecVLenUTF8 */ |
280 | | /************************************************************************/ |
281 | | |
282 | | /** Implements the vlen-utf8 array-to-bytes codec for variable-length |
283 | | * UTF-8 strings (zarr-extensions). |
284 | | * |
285 | | * Binary format (little-endian): |
286 | | * [u32 item_count] [u32 len_0][bytes_0] [u32 len_1][bytes_1] ... |
287 | | * |
288 | | * Decode produces a flat buffer of nElements * nativeSize bytes where |
289 | | * each slot is a null-padded string. Read-only for now. |
290 | | */ |
291 | | class ZarrV3CodecVLenUTF8 final : public ZarrV3Codec |
292 | | { |
293 | | public: |
294 | | static constexpr const char *NAME = "vlen-utf8"; |
295 | | |
296 | | ZarrV3CodecVLenUTF8(); |
297 | | |
298 | | IOType GetInputType() const override |
299 | 0 | { |
300 | 0 | return IOType::ARRAY; |
301 | 0 | } |
302 | | |
303 | | IOType GetOutputType() const override |
304 | 0 | { |
305 | 0 | return IOType::BYTES; |
306 | 0 | } |
307 | | |
308 | | bool InitFromConfiguration(const std::string &osArrayName, |
309 | | const CPLJSONObject &configuration, |
310 | | const ZarrArrayMetadata &oInputArrayMetadata, |
311 | | ZarrArrayMetadata &oOutputArrayMetadata, |
312 | | bool bEmitWarnings) override; |
313 | | |
314 | | std::unique_ptr<ZarrV3Codec> Clone() const override; |
315 | | |
316 | | bool Encode(const ZarrByteVectorQuickResize &abySrc, |
317 | | ZarrByteVectorQuickResize &abyDst) const override; |
318 | | bool Decode(const ZarrByteVectorQuickResize &abySrc, |
319 | | ZarrByteVectorQuickResize &abyDst) const override; |
320 | | }; |
321 | | |
322 | | /************************************************************************/ |
323 | | /* ZarrV3CodecTranspose */ |
324 | | /************************************************************************/ |
325 | | |
326 | | // Implements https://zarr-specs.readthedocs.io/en/latest/v3/codecs/transpose/v1.0.html |
327 | | class ZarrV3CodecTranspose final : public ZarrV3Codec |
328 | | { |
329 | | // m_anOrder is such that dest_shape[i] = source_shape[m_anOrder[i]] |
330 | | // where source_shape[] is the size of the array before the Encode() operation |
331 | | // and dest_shape[] its size after. |
332 | | // m_anOrder[] describes a bijection of [0,N-1] to [0,N-1] |
333 | | std::vector<int> m_anOrder{}; |
334 | | |
335 | | // m_anReverseOrder is such that m_anReverseOrder[m_anOrder[i]] = i |
336 | | std::vector<int> m_anReverseOrder{}; |
337 | | |
338 | | bool Transpose(const ZarrByteVectorQuickResize &abySrc, |
339 | | ZarrByteVectorQuickResize &abyDst, bool bEncodeDirection, |
340 | | const std::vector<size_t> &anForwardBlockSizes) const; |
341 | | |
342 | | public: |
343 | | static constexpr const char *NAME = "transpose"; |
344 | | |
345 | | ZarrV3CodecTranspose(); |
346 | | |
347 | | IOType GetInputType() const override |
348 | 0 | { |
349 | 0 | return IOType::ARRAY; |
350 | 0 | } |
351 | | |
352 | | IOType GetOutputType() const override |
353 | 0 | { |
354 | 0 | return IOType::ARRAY; |
355 | 0 | } |
356 | | |
357 | | static CPLJSONObject GetConfiguration(const std::vector<int> &anOrder); |
358 | | |
359 | | bool InitFromConfiguration(const std::string &osArrayName, |
360 | | const CPLJSONObject &configuration, |
361 | | const ZarrArrayMetadata &oInputArrayMetadata, |
362 | | ZarrArrayMetadata &oOutputArrayMetadata, |
363 | | bool bEmitWarnings) override; |
364 | | |
365 | | const std::vector<int> &GetOrder() const |
366 | 0 | { |
367 | 0 | return m_anOrder; |
368 | 0 | } |
369 | | |
370 | | bool IsNoOp() const override; |
371 | | |
372 | | std::unique_ptr<ZarrV3Codec> Clone() const override; |
373 | | |
374 | | bool Encode(const ZarrByteVectorQuickResize &abySrc, |
375 | | ZarrByteVectorQuickResize &abyDst) const override; |
376 | | bool Decode(const ZarrByteVectorQuickResize &abySrc, |
377 | | ZarrByteVectorQuickResize &abyDst) const override; |
378 | | |
379 | | bool DecodePartial(VSIVirtualHandle *poFile, |
380 | | const ZarrByteVectorQuickResize &abySrc, |
381 | | ZarrByteVectorQuickResize &abyDst, |
382 | | std::vector<size_t> &anStartIdx, |
383 | | std::vector<size_t> &anCount) override; |
384 | | |
385 | | std::vector<size_t> |
386 | | GetInnerMostBlockSize(const std::vector<size_t> &input) const override; |
387 | | |
388 | | template <class T> |
389 | | inline void Reorder1DForward(std::vector<T> &vector) const |
390 | 0 | { |
391 | 0 | std::vector<T> res; |
392 | 0 | for (int idx : m_anOrder) |
393 | 0 | res.push_back(vector[idx]); |
394 | 0 | vector = std::move(res); |
395 | 0 | } |
396 | | |
397 | | template <class T> |
398 | | inline void Reorder1DInverse(std::vector<T> &vector) const |
399 | 0 | { |
400 | 0 | std::vector<T> res; |
401 | 0 | for (int idx : m_anReverseOrder) |
402 | 0 | res.push_back(vector[idx]); |
403 | 0 | vector = std::move(res); |
404 | 0 | } |
405 | | |
406 | | void ChangeArrayShapeForward(std::vector<size_t> &anStartIdx, |
407 | | std::vector<size_t> &anCount) override |
408 | 0 | { |
409 | 0 | Reorder1DForward(anStartIdx); |
410 | 0 | Reorder1DForward(anCount); |
411 | 0 | } |
412 | | }; |
413 | | |
414 | | /************************************************************************/ |
415 | | /* ZarrV3CodecCRC32C */ |
416 | | /************************************************************************/ |
417 | | |
418 | | // Implements https://zarr-specs.readthedocs.io/en/latest/v3/codecs/crc32c/index.html |
419 | | class ZarrV3CodecCRC32C final : public ZarrV3Codec |
420 | | { |
421 | | bool m_bCheckCRC = true; |
422 | | |
423 | | public: |
424 | | static constexpr const char *NAME = "crc32c"; |
425 | | |
426 | | ZarrV3CodecCRC32C(); |
427 | | |
428 | | IOType GetInputType() const override |
429 | 0 | { |
430 | 0 | return IOType::BYTES; |
431 | 0 | } |
432 | | |
433 | | IOType GetOutputType() const override |
434 | 0 | { |
435 | 0 | return IOType::BYTES; |
436 | 0 | } |
437 | | |
438 | | bool InitFromConfiguration(const std::string &osArrayName, |
439 | | const CPLJSONObject &configuration, |
440 | | const ZarrArrayMetadata &oInputArrayMetadata, |
441 | | ZarrArrayMetadata &oOutputArrayMetadata, |
442 | | bool bEmitWarnings) override; |
443 | | |
444 | | std::unique_ptr<ZarrV3Codec> Clone() const override; |
445 | | |
446 | | bool Encode(const ZarrByteVectorQuickResize &abySrc, |
447 | | ZarrByteVectorQuickResize &abyDst) const override; |
448 | | bool Decode(const ZarrByteVectorQuickResize &abySrc, |
449 | | ZarrByteVectorQuickResize &abyDst) const override; |
450 | | }; |
451 | | |
452 | | /************************************************************************/ |
453 | | /* ZarrV3CodecShardingIndexed */ |
454 | | /************************************************************************/ |
455 | | |
456 | | class ZarrV3CodecSequence; |
457 | | |
458 | | // https://zarr-specs.readthedocs.io/en/latest/v3/codecs/sharding-indexed/index.html |
459 | | class ZarrV3CodecShardingIndexed final : public ZarrV3Codec |
460 | | { |
461 | | std::unique_ptr<ZarrV3CodecSequence> m_poCodecSequence{}; |
462 | | std::unique_ptr<ZarrV3CodecSequence> m_poIndexCodecSequence{}; |
463 | | bool m_bIndexLocationAtEnd = true; |
464 | | bool m_bIndexHasCRC32 = false; |
465 | | std::vector<size_t> m_anInnerBlockSize{}; |
466 | | |
467 | | struct Location |
468 | | { |
469 | | uint64_t nOffset; |
470 | | uint64_t nSize; |
471 | | }; |
472 | | |
473 | | public: |
474 | | static constexpr const char *NAME = "sharding_indexed"; |
475 | | |
476 | | ZarrV3CodecShardingIndexed(); |
477 | | |
478 | | IOType GetInputType() const override |
479 | 0 | { |
480 | 0 | return IOType::ARRAY; |
481 | 0 | } |
482 | | |
483 | | IOType GetOutputType() const override |
484 | 0 | { |
485 | 0 | return IOType::BYTES; |
486 | 0 | } |
487 | | |
488 | | bool InitFromConfiguration(const std::string &osArrayName, |
489 | | const CPLJSONObject &configuration, |
490 | | const ZarrArrayMetadata &oInputArrayMetadata, |
491 | | ZarrArrayMetadata &oOutputArrayMetadata, |
492 | | bool bEmitWarnings) override; |
493 | | |
494 | | std::unique_ptr<ZarrV3Codec> Clone() const override; |
495 | | |
496 | | bool Encode(const ZarrByteVectorQuickResize &abySrc, |
497 | | ZarrByteVectorQuickResize &abyDst) const override; |
498 | | bool Decode(const ZarrByteVectorQuickResize &abySrc, |
499 | | ZarrByteVectorQuickResize &abyDst) const override; |
500 | | |
501 | | bool DecodePartial(VSIVirtualHandle *poFile, |
502 | | const ZarrByteVectorQuickResize &abySrc, |
503 | | ZarrByteVectorQuickResize &abyDst, |
504 | | std::vector<size_t> &anStartIdx, |
505 | | std::vector<size_t> &anCount) override; |
506 | | |
507 | | /** Batch-read multiple inner chunks from the same shard via two |
508 | | * ReadMultiRange() passes (index entries, then data), then decode. |
509 | | * pszFilename is used as a cache key for the shard index; pass nullptr |
510 | | * to bypass the cache. |
511 | | */ |
512 | | bool BatchDecodePartial( |
513 | | VSIVirtualHandle *poFile, const char *pszFilename, |
514 | | const std::vector<std::pair<std::vector<size_t>, std::vector<size_t>>> |
515 | | &anRequests, |
516 | | std::vector<ZarrByteVectorQuickResize> &aResults); |
517 | | |
518 | | std::vector<size_t> |
519 | | GetInnerMostBlockSize(const std::vector<size_t> &input) const override; |
520 | | }; |
521 | | |
522 | | /************************************************************************/ |
523 | | /* ZarrV3CodecSequence */ |
524 | | /************************************************************************/ |
525 | | |
526 | | class ZarrV3CodecSequence |
527 | | { |
528 | | const ZarrArrayMetadata m_oInputArrayMetadata; |
529 | | std::vector<std::unique_ptr<ZarrV3Codec>> m_apoCodecs{}; |
530 | | CPLJSONObject m_oCodecArray{}; |
531 | | ZarrByteVectorQuickResize m_abyTmp{}; |
532 | | bool m_bPartialDecodingPossible = false; |
533 | | |
534 | | bool AllocateBuffer(ZarrByteVectorQuickResize &abyBuffer, size_t nEltCount); |
535 | | |
536 | | public: |
537 | | explicit ZarrV3CodecSequence(const ZarrArrayMetadata &oInputArrayMetadata) |
538 | 148 | : m_oInputArrayMetadata(oInputArrayMetadata) |
539 | 148 | { |
540 | 148 | } |
541 | | |
542 | | // This method is not thread safe due to cloning a JSON object |
543 | | std::unique_ptr<ZarrV3CodecSequence> Clone() const; |
544 | | |
545 | | bool InitFromJson(const std::string &osArrayName, |
546 | | const CPLJSONObject &oCodecs, |
547 | | ZarrArrayMetadata &oOutputArrayMetadata); |
548 | | |
549 | | const CPLJSONObject &GetJSon() const |
550 | 207 | { |
551 | 207 | return m_oCodecArray; |
552 | 207 | } |
553 | | |
554 | | const std::vector<std::unique_ptr<ZarrV3Codec>> &GetCodecs() const |
555 | 0 | { |
556 | 0 | return m_apoCodecs; |
557 | 0 | } |
558 | | |
559 | | bool SupportsPartialDecoding() const |
560 | 34.6k | { |
561 | 34.6k | return m_bPartialDecodingPossible; |
562 | 34.6k | } |
563 | | |
564 | | bool Encode(ZarrByteVectorQuickResize &abyBuffer); |
565 | | bool Decode(ZarrByteVectorQuickResize &abyBuffer); |
566 | | |
567 | | /** Partial decoding. |
568 | | * anStartIdx[i]: coordinate in pixel, within the array of an outer chunk, |
569 | | * that is < m_oInputArrayMetadata.anBlockSizes[i] |
570 | | * anCount[i]: number of pixels to extract <= m_oInputArrayMetadata.anBlockSizes[i] |
571 | | */ |
572 | | bool DecodePartial(VSIVirtualHandle *poFile, |
573 | | ZarrByteVectorQuickResize &abyBuffer, |
574 | | const std::vector<size_t> &anStartIdx, |
575 | | const std::vector<size_t> &anCount); |
576 | | |
577 | | /** Batch-read multiple inner chunks via ReadMultiRange(). |
578 | | * Delegates to the sharding codec if present, otherwise falls back |
579 | | * to sequential DecodePartial() calls. |
580 | | * pszFilename is forwarded to the sharding codec for index caching. |
581 | | */ |
582 | | bool BatchDecodePartial( |
583 | | VSIVirtualHandle *poFile, const char *pszFilename, |
584 | | const std::vector<std::pair<std::vector<size_t>, std::vector<size_t>>> |
585 | | &anRequests, |
586 | | std::vector<ZarrByteVectorQuickResize> &aResults); |
587 | | |
588 | | std::vector<size_t> |
589 | | GetInnerMostBlockSize(const std::vector<size_t> &anOuterBlockSize) const; |
590 | | }; |
591 | | |
592 | | /************************************************************************/ |
593 | | /* ZarrV3CodecPcodec */ |
594 | | /************************************************************************/ |
595 | | |
596 | | /** Non-standard "pcodec" (a.k.a. "pco") from https://github.com/pcodec/pcodec |
597 | | * |
598 | | * Also see https://numcodecs.readthedocs.io/en/stable/compression/pcodec.html |
599 | | */ |
600 | | class ZarrV3CodecPcodec /* final */ : public ZarrV3Codec |
601 | | { |
602 | | public: |
603 | | static constexpr const char *NAME = "numcodecs.pcodec"; |
604 | | |
605 | | explicit ZarrV3CodecPcodec(); |
606 | | ~ZarrV3CodecPcodec() override; |
607 | | |
608 | | IOType GetInputType() const override |
609 | 0 | { |
610 | 0 | return IOType::ARRAY; |
611 | 0 | } |
612 | | |
613 | | IOType GetOutputType() const override |
614 | 0 | { |
615 | 0 | return IOType::BYTES; |
616 | 0 | } |
617 | | |
618 | | bool InitFromConfiguration(const std::string &osArrayName, |
619 | | const CPLJSONObject &configuration, |
620 | | const ZarrArrayMetadata &oInputArrayMetadata, |
621 | | ZarrArrayMetadata &oOutputArrayMetadata, |
622 | | bool bEmitWarnings) override; |
623 | | |
624 | | std::unique_ptr<ZarrV3Codec> Clone() const override; |
625 | | |
626 | | bool Decode(const ZarrByteVectorQuickResize &abySrc, |
627 | | ZarrByteVectorQuickResize &abyDst) const override; |
628 | | |
629 | | bool Encode(const ZarrByteVectorQuickResize &abySrc, |
630 | | ZarrByteVectorQuickResize &abyDst) const override; |
631 | | }; |
632 | | |
633 | | #endif |