Skip to content

Commit 602a0e8

Browse files
committed
Add missing API parts, use Numpy arrays for outputs
1 parent cc03f40 commit 602a0e8

File tree

5 files changed

+259
-189
lines changed

5 files changed

+259
-189
lines changed

example/example.py

+4-4
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
1+
from pywuffs import ImageDecoderType, PixelFormat
12
from pywuffs.aux import (
23
ImageDecoder,
34
ImageDecoderConfig,
4-
ImageDecoderType,
5-
ImageDecoderFlags,
6-
PixelFormat
5+
ImageDecoderFlags
76
)
87

98
config = ImageDecoderConfig()
@@ -15,4 +14,5 @@
1514

1615
decoding_result = decoder.decode("lena.png")
1716

18-
print(bytes(memoryview(decoding_result.decoded_data)))
17+
print(decoding_result.pixbuf.shape)
18+
print(decoding_result.pixbuf)

src/wuffs-aux-image-wrapper.h

+52-22
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
#pragma once
22

3+
#include <pybind11/numpy.h>
4+
5+
#include <c/wuffs-v0.3.c>
36
#include <string>
47
#include <unordered_set>
58
#include <utility>
@@ -97,6 +100,18 @@ enum class PixelBlend : uint32_t {
97100
SRC_OVER = WUFFS_BASE__PIXEL_BLEND__SRC_OVER
98101
};
99102

103+
enum class PixelSubsampling : uint32_t {
104+
NONE = WUFFS_BASE__PIXEL_SUBSAMPLING__NONE,
105+
#define PSE(ps) K##ps = WUFFS_BASE__PIXEL_SUBSAMPLING__##ps
106+
PSE(444),
107+
PSE(440),
108+
PSE(422),
109+
PSE(420),
110+
PSE(411),
111+
PSE(410)
112+
#undef PFE
113+
};
114+
100115
// This struct hosts wuffs_aux::DecodeImage arguments in more user- and
101116
// Python- friendly fashion
102117
struct ImageDecoderConfig {
@@ -122,10 +137,10 @@ struct ImageDecoderConfig {
122137
// input
123138
struct MetadataEntry {
124139
wuffs_base__more_information minfo{};
125-
std::vector<uint8_t> data;
140+
pybind11::array_t<uint8_t> data;
126141

127142
MetadataEntry(const wuffs_base__more_information& minfo,
128-
std::vector<uint8_t>&& data)
143+
pybind11::array_t<uint8_t>&& data)
129144
: minfo(minfo), data(std::move(data)) {}
130145

131146
MetadataEntry() : minfo(wuffs_base__empty_more_information()) {}
@@ -143,33 +158,37 @@ struct MetadataEntry {
143158
return *this;
144159
}
145160

146-
MetadataEntry(const wuffs_aux_wrap::MetadataEntry& other) = default;
147-
148-
MetadataEntry& operator=(const wuffs_aux_wrap::MetadataEntry& other) =
149-
default;
161+
MetadataEntry(const wuffs_aux_wrap::MetadataEntry& other) = delete;
162+
MetadataEntry& operator=(const wuffs_aux_wrap::MetadataEntry& other) = delete;
150163
};
151164

152165
struct ImageDecodingResult {
153-
std::vector<uint8_t> decoded_data;
166+
wuffs_base__pixel_config pixcfg = wuffs_base__null_pixel_config();
167+
pybind11::array_t<uint8_t> pixbuf;
154168
std::vector<MetadataEntry> reported_metadata;
155169
std::string error_message;
156170

157171
ImageDecodingResult() = default;
158172

159173
ImageDecodingResult(ImageDecodingResult&& other) noexcept {
160-
std::swap(decoded_data, other.decoded_data);
174+
std::swap(pixcfg, other.pixcfg);
175+
std::swap(pixbuf, other.pixbuf);
161176
std::swap(reported_metadata, other.reported_metadata);
162177
std::swap(error_message, other.error_message);
163178
}
164179

165180
ImageDecodingResult& operator=(ImageDecodingResult&& other) noexcept {
166181
if (this != &other) {
167-
std::swap(decoded_data, other.decoded_data);
182+
std::swap(pixcfg, other.pixcfg);
183+
std::swap(pixbuf, other.pixbuf);
168184
std::swap(reported_metadata, other.reported_metadata);
169185
std::swap(error_message, other.error_message);
170186
}
171187
return *this;
172188
}
189+
190+
ImageDecodingResult(ImageDecodingResult& other) = delete;
191+
ImageDecodingResult& operator=(ImageDecodingResult& other) = delete;
173192
};
174193

175194
struct ImageDecoderError {
@@ -182,6 +201,7 @@ struct ImageDecoderError {
182201
static const std::string UnsupportedPixelBlend;
183202
static const std::string UnsupportedPixelConfiguration;
184203
static const std::string UnsupportedPixelFormat;
204+
static const std::string FailedToOpenFile;
185205
};
186206

187207
const std::string ImageDecoderError::MaxInclDimensionExceeded =
@@ -202,8 +222,10 @@ const std::string ImageDecoderError::UnsupportedPixelConfiguration =
202222
wuffs_aux::DecodeImage_UnsupportedPixelConfiguration;
203223
const std::string ImageDecoderError::UnsupportedPixelFormat =
204224
wuffs_aux::DecodeImage_UnsupportedPixelFormat;
225+
const std::string ImageDecoderError::FailedToOpenFile =
226+
"wuffs_aux_wrap::ImageDecoder::Decode: failed to open file";
205227

206-
class ImageDecoder : public wuffs_aux::DecodeImageCallbacks {
228+
class ImageDecoder : public wuffs_aux::DecodeImageCallbacks {
207229
public:
208230
explicit ImageDecoder(const ImageDecoderConfig& config)
209231
: quirks_vector_({config.quirks.begin(), config.quirks.end()}),
@@ -238,8 +260,8 @@ class ImageDecoder : public wuffs_aux::DecodeImageCallbacks {
238260

239261
std::string HandleMetadata(const wuffs_base__more_information& minfo,
240262
wuffs_base__slice_u8 raw) override {
241-
decoding_result_.reported_metadata.push_back(
242-
{minfo, {raw.ptr, raw.ptr + raw.len}});
263+
decoding_result_.reported_metadata.emplace_back(
264+
minfo, pybind11::array(pybind11::dtype("uint8"), {raw.len}, raw.ptr));
243265
return "";
244266
}
245267

@@ -261,18 +283,18 @@ class ImageDecoder : public wuffs_aux::DecodeImageCallbacks {
261283
if (len == 0 || SIZE_MAX < len) {
262284
return {wuffs_aux::DecodeImage_UnsupportedPixelConfiguration};
263285
}
264-
if (allow_uninitialized_memory) {
265-
decoding_result_.decoded_data.resize(len);
266-
} else {
267-
decoding_result_.decoded_data.resize(len, 0);
286+
decoding_result_.pixbuf.resize({len});
287+
if (!allow_uninitialized_memory) {
288+
std::memset(decoding_result_.pixbuf.mutable_data(), 0,
289+
decoding_result_.pixbuf.size());
268290
}
269291
wuffs_base__pixel_buffer pixbuf;
270292
wuffs_base__status status = pixbuf.set_from_slice(
271293
&image_config.pixcfg,
272-
wuffs_base__make_slice_u8(decoding_result_.decoded_data.data(),
273-
decoding_result_.decoded_data.size()));
294+
wuffs_base__make_slice_u8(decoding_result_.pixbuf.mutable_data(),
295+
decoding_result_.pixbuf.size()));
274296
if (!status.is_ok()) {
275-
decoding_result_.decoded_data.clear();
297+
decoding_result_.pixbuf = {};
276298
return {status.message()};
277299
}
278300
return {wuffs_aux::MemOwner(nullptr, &free), pixbuf};
@@ -289,8 +311,7 @@ class ImageDecoder : public wuffs_aux::DecodeImageCallbacks {
289311
FILE* f = fopen(path_to_file.c_str(), "rb");
290312
if (!f) {
291313
ImageDecodingResult result;
292-
result.error_message =
293-
"wuffs_aux_wrap::ImageDecoder::Decode: failed to open file";
314+
result.error_message = ImageDecoderError::FailedToOpenFile;
294315
return result;
295316
}
296317
wuffs_aux::sync_io::FileInput input(f);
@@ -315,7 +336,16 @@ class ImageDecoder : public wuffs_aux::DecodeImageCallbacks {
315336
decoding_result_.error_message =
316337
std::move(decode_image_result.error_message);
317338
if (!decode_image_result.pixbuf.pixcfg.is_valid()) {
318-
decoding_result_.decoded_data.clear();
339+
decoding_result_.pixbuf = {};
340+
decoding_result_.pixcfg = wuffs_base__null_pixel_config();
341+
} else {
342+
decoding_result_.pixcfg = decode_image_result.pixbuf.pixcfg;
343+
decoding_result_.pixbuf =
344+
decoding_result_.pixbuf.reshape(std::vector<size_t>{
345+
decoding_result_.pixcfg.height(), decoding_result_.pixcfg.width(),
346+
decoding_result_.pixcfg.pixbuf_len() /
347+
(decoding_result_.pixcfg.width() *
348+
decoding_result_.pixcfg.height())});
319349
}
320350
return std::move(decoding_result_);
321351
}

0 commit comments

Comments
 (0)