Skip to content

Commit 52814b0

Browse files
committed
feat(heif): Add IOProxy for input and output
Add IOProxy support similar to other file formats. MyHeifWriter was renamed for consistency with other code. Signed-off-by: Brecht Van Lommel <brecht@blender.org>
1 parent bdb4208 commit 52814b0

File tree

3 files changed

+68
-27
lines changed

3 files changed

+68
-27
lines changed

src/doc/builtinplugins.rst

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -806,6 +806,10 @@ attributes are supported:
806806
having Orientation 1). If zero, then libheif will not reorient the
807807
image and the Orientation metadata will be set to reflect the camera
808808
orientation.
809+
* - ``oiio:ioproxy``
810+
- ptr
811+
- Pointer to a ``Filesystem::IOProxy`` that will handle the I/O, for
812+
example by reading from memory rather than the file system.
809813

810814
**Configuration settings for HEIF output**
811815

@@ -824,6 +828,10 @@ control aspects of the writing itself:
824828
- If supplied, can be ``"heic"`` or ``"avif"``, but may optionally have a
825829
quality value appended, like ``"heic:90"``. Quality can be 1-100, with
826830
100 meaning lossless. The default is 75.
831+
* - ``oiio:ioproxy``
832+
- ptr
833+
- Pointer to a ``Filesystem::IOProxy`` that will handle the I/O, for
834+
example by writing to memory rather than the file system.
827835

828836

829837

src/heif.imageio/heifinput.cpp

Lines changed: 43 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -32,20 +32,49 @@
3232

3333
OIIO_PLUGIN_NAMESPACE_BEGIN
3434

35+
36+
class HeifReader final : public heif::Context::Reader {
37+
public:
38+
HeifReader(Filesystem::IOProxy* ioproxy)
39+
: m_ioproxy(ioproxy)
40+
{
41+
m_ioproxy->seek(0);
42+
}
43+
int64_t get_position() const override { return m_ioproxy->tell(); }
44+
int read(void* data, size_t size) override
45+
{
46+
return m_ioproxy->read(data, size) == size ? 0 : -1;
47+
}
48+
int seek(int64_t position) override
49+
{
50+
return m_ioproxy->seek(position) ? 0 : -1;
51+
}
52+
heif_reader_grow_status wait_for_file_size(int64_t target_size) override
53+
{
54+
return target_size <= int64_t(m_ioproxy->size())
55+
? heif_reader_grow_status_size_reached
56+
: heif_reader_grow_status_size_beyond_eof;
57+
}
58+
59+
private:
60+
Filesystem::IOProxy* m_ioproxy;
61+
};
62+
63+
3564
class HeifInput final : public ImageInput {
3665
public:
3766
HeifInput() {}
3867
~HeifInput() override { close(); }
3968
const char* format_name(void) const override { return "heif"; }
4069
int supports(string_view feature) const override
4170
{
42-
return feature == "exif"
71+
return feature == "exif" || feature == "ioproxy"
4372
#if LIBHEIF_HAVE_VERSION(1, 9, 0)
4473
|| feature == "cicp"
4574
#endif
4675
;
4776
}
48-
bool valid_file(const std::string& filename) const override;
77+
bool valid_file(Filesystem::IOProxy* ioproxy) const override;
4978
bool open(const std::string& name, ImageSpec& newspec) override;
5079
bool open(const std::string& name, ImageSpec& newspec,
5180
const ImageSpec& config) override;
@@ -67,14 +96,14 @@ class HeifInput final : public ImageInput {
6796
bool m_do_associate = false;
6897
bool m_reorient = true;
6998
std::unique_ptr<heif::Context> m_ctx;
99+
std::unique_ptr<HeifReader> m_reader;
70100
heif_item_id m_primary_id; // id of primary image
71101
std::vector<heif_item_id> m_item_ids; // ids of all other images
72102
heif::ImageHandle m_ihandle;
73103
heif::Image m_himage;
74104
};
75105

76106

77-
78107
void
79108
oiio_heif_init()
80109
{
@@ -111,10 +140,12 @@ OIIO_PLUGIN_EXPORTS_END
111140

112141

113142
bool
114-
HeifInput::valid_file(const std::string& filename) const
143+
HeifInput::valid_file(Filesystem::IOProxy* ioproxy) const
115144
{
145+
if (!ioproxy || ioproxy->mode() != Filesystem::IOProxy::Mode::Read)
146+
return false;
116147
uint8_t magic[12];
117-
if (Filesystem::read_bytes(filename, magic, sizeof(magic)) != sizeof(magic))
148+
if (ioproxy->pread(magic, sizeof(magic), 0) != sizeof(magic))
118149
return false;
119150
heif_filetype_result filetype_check = heif_check_filetype(magic,
120151
sizeof(magic));
@@ -141,7 +172,12 @@ HeifInput::open(const std::string& name, ImageSpec& newspec,
141172
m_filename = name;
142173
m_subimage = -1;
143174

175+
ioproxy_retrieve_from_config(config);
176+
if (!ioproxy_use_or_open(name))
177+
return false;
178+
144179
m_ctx.reset(new heif::Context);
180+
m_reader.reset(new HeifReader(ioproxy()));
145181
m_himage = heif::Image();
146182
m_ihandle = heif::ImageHandle();
147183

@@ -150,8 +186,7 @@ HeifInput::open(const std::string& name, ImageSpec& newspec,
150186
m_reorient = config.get_int_attribute("oiio:reorient", 1);
151187

152188
try {
153-
m_ctx->read_from_file(name);
154-
// FIXME: should someday be read_from_reader to give full flexibility
189+
m_ctx->read_from_reader(*m_reader);
155190

156191
m_item_ids = m_ctx->get_list_of_top_level_image_IDs();
157192
m_primary_id = m_ctx->get_primary_image_ID();
@@ -187,6 +222,7 @@ HeifInput::close()
187222
m_himage = heif::Image();
188223
m_ihandle = heif::ImageHandle();
189224
m_ctx.reset();
225+
m_reader.reset();
190226
m_subimage = -1;
191227
m_num_subimages = 0;
192228
m_associated_alpha = true;

src/heif.imageio/heifoutput.cpp

Lines changed: 17 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,8 @@ class HeifOutput final : public ImageOutput {
2929
const char* format_name(void) const override { return "heif"; }
3030
int supports(string_view feature) const override
3131
{
32-
return feature == "alpha" || feature == "exif" || feature == "tiles"
32+
return feature == "alpha" || feature == "exif" || feature == "ioproxy"
33+
|| feature == "tiles"
3334
#if LIBHEIF_HAVE_VERSION(1, 9, 0)
3435
|| feature == "cicp"
3536
#endif
@@ -58,12 +59,9 @@ class HeifOutput final : public ImageOutput {
5859
};
5960

6061

61-
62-
namespace {
63-
64-
class MyHeifWriter final : public heif::Context::Writer {
62+
class HeifWriter final : public heif::Context::Writer {
6563
public:
66-
MyHeifWriter(Filesystem::IOProxy* ioproxy)
64+
HeifWriter(Filesystem::IOProxy* ioproxy)
6765
: m_ioproxy(ioproxy)
6866
{
6967
}
@@ -84,9 +82,6 @@ class MyHeifWriter final : public heif::Context::Writer {
8482
Filesystem::IOProxy* m_ioproxy = nullptr;
8583
};
8684

87-
} // namespace
88-
89-
9085

9186
OIIO_PLUGIN_EXPORTS_BEGIN
9287

@@ -114,6 +109,11 @@ HeifOutput::open(const std::string& name, const ImageSpec& newspec,
114109

115110
m_filename = name;
116111

112+
ioproxy_retrieve_from_config(m_spec);
113+
if (!ioproxy_use_or_open(name)) {
114+
return false;
115+
}
116+
117117
m_bitdepth = m_spec.format.size() > TypeUInt8.size() ? 10 : 8;
118118
m_bitdepth = m_spec.get_int_attribute("oiio:BitsPerSample", m_bitdepth);
119119
if (m_bitdepth == 10 || m_bitdepth == 12) {
@@ -221,7 +221,9 @@ HeifOutput::write_tile(int x, int y, int z, TypeDesc format, const void* data,
221221
bool
222222
HeifOutput::close()
223223
{
224-
if (!m_ctx) { // already closed
224+
if (!m_ctx || !ioproxy_opened()) { // already closed
225+
m_ctx.reset();
226+
ioproxy_clear();
225227
return true;
226228
}
227229

@@ -286,25 +288,20 @@ HeifOutput::close()
286288
#endif
287289
}
288290
m_ctx->set_primary_image(m_ihandle);
289-
Filesystem::IOFile ioproxy(m_filename, Filesystem::IOProxy::Write);
290-
if (ioproxy.mode() != Filesystem::IOProxy::Write) {
291-
errorfmt("Could not open \"{}\"", m_filename);
292-
ok = false;
293-
} else {
294-
MyHeifWriter writer(&ioproxy);
295-
m_ctx->write(writer);
296-
}
291+
HeifWriter writer(ioproxy());
292+
m_ctx->write(writer);
297293
} catch (const heif::Error& err) {
298294
std::string e = err.get_message();
299295
errorfmt("{}", e.empty() ? "unknown exception" : e.c_str());
300-
return false;
296+
ok = false;
301297
} catch (const std::exception& err) {
302298
std::string e = err.what();
303299
errorfmt("{}", e.empty() ? "unknown exception" : e.c_str());
304-
return false;
300+
ok = false;
305301
}
306302

307303
m_ctx.reset();
304+
ioproxy_clear();
308305
return ok;
309306
}
310307

0 commit comments

Comments
 (0)