Skip to content

Commit 1a296d7

Browse files
committed
rebase copy_image implementation
Signed-off-by: Andy Chan <andychancse@gmail.com>
1 parent fd6a195 commit 1a296d7

File tree

7 files changed

+331
-180
lines changed

7 files changed

+331
-180
lines changed

src/cmake/testing.cmake

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -274,7 +274,7 @@ macro (oiio_add_all_tests)
274274
IMAGEDIR j2kp4files_v1_5
275275
URL http://www.itu.int/net/ITU-T/sigdb/speimage/ImageForm-s.aspx?val=10100803)
276276
set (all_openexr_tests
277-
openexr-suite openexr-multires openexr-chroma
277+
openexr-suite openexr-multires openexr-chroma openexr-copy
278278
openexr-v2 openexr-window perchannel oiiotool-deep)
279279
if (OpenEXR_VERSION VERSION_GREATER_EQUAL 3.1.10)
280280
# OpenEXR 3.1.10 is the first release where the exr core library

src/openexr.imageio/exr_pvt.h

Lines changed: 189 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,17 @@
55
#pragma once
66

77

8+
#include <OpenImageIO/filesystem.h>
89
#include <OpenImageIO/Imath.h>
10+
#include <OpenImageIO/imageio.h>
911
#include <OpenImageIO/platform.h>
1012
#include <OpenImageIO/string_view.h>
1113
#include <OpenImageIO/typedesc.h>
1214

15+
#include <OpenEXR/IexThrowErrnoExc.h>
1316
#include <OpenEXR/ImfChannelList.h>
17+
#include <OpenEXR/ImfIO.h>
18+
#include <ImathBox.h>
1419

1520
#ifdef OPENEXR_VERSION_MAJOR
1621
# define OPENEXR_CODED_VERSION \
@@ -65,4 +70,188 @@ split_name(string_view fullname, string_view& layer, string_view& suffix)
6570
}
6671

6772

73+
74+
// Custom file input stream, copying code from the class StdIFStream in OpenEXR,
75+
// which would have been used if we just provided a filename. The difference is
76+
// that this can handle UTF-8 file paths on all platforms.
77+
class OpenEXRInputStream final : public Imf::IStream {
78+
public:
79+
OpenEXRInputStream(const char* filename, Filesystem::IOProxy* io)
80+
: Imf::IStream(filename)
81+
, m_io(io)
82+
{
83+
if (!io || io->mode() != Filesystem::IOProxy::Read)
84+
throw Iex::IoExc("File input failed.");
85+
}
86+
bool read(char c[], int n) override
87+
{
88+
OIIO_DASSERT(m_io);
89+
if (m_io->read(c, n) != size_t(n))
90+
throw Iex::IoExc("Unexpected end of file.");
91+
return n;
92+
}
93+
#if OIIO_USING_IMATH >= 3
94+
uint64_t tellg() override { return m_io->tell(); }
95+
void seekg(uint64_t pos) override
96+
{
97+
if (!m_io->seek(pos))
98+
throw Iex::IoExc("File input failed.");
99+
}
100+
#else
101+
Imath::Int64 tellg() override { return m_io->tell(); }
102+
void seekg(Imath::Int64 pos) override
103+
{
104+
if (!m_io->seek(pos))
105+
throw Iex::IoExc("File input failed.");
106+
}
107+
#endif
108+
void clear() override {}
109+
110+
private:
111+
Filesystem::IOProxy* m_io = nullptr;
112+
};
113+
114+
115+
116+
class OpenEXRInput final : public ImageInput {
117+
public:
118+
OpenEXRInput();
119+
~OpenEXRInput() override { close(); }
120+
const char* format_name(void) const override { return "openexr"; }
121+
int supports(string_view feature) const override
122+
{
123+
return (feature == "arbitrary_metadata"
124+
|| feature == "exif" // Because of arbitrary_metadata
125+
|| feature == "iptc" // Because of arbitrary_metadata
126+
|| feature == "ioproxy");
127+
}
128+
bool valid_file(Filesystem::IOProxy* ioproxy) const override;
129+
bool open(const std::string& name, ImageSpec& newspec,
130+
const ImageSpec& config) override;
131+
bool open(const std::string& name, ImageSpec& newspec) override
132+
{
133+
return open(name, newspec, ImageSpec());
134+
}
135+
bool close() override;
136+
int current_subimage(void) const override { return m_subimage; }
137+
int current_miplevel(void) const override { return m_miplevel; }
138+
bool seek_subimage(int subimage, int miplevel) override;
139+
ImageSpec spec(int subimage, int miplevel) override;
140+
ImageSpec spec_dimensions(int subimage, int miplevel) override;
141+
bool read_native_scanline(int subimage, int miplevel, int y, int z,
142+
void* data) override;
143+
bool read_native_scanlines(int subimage, int miplevel, int ybegin, int yend,
144+
int z, void* data) override;
145+
bool read_native_scanlines(int subimage, int miplevel, int ybegin, int yend,
146+
int z, int chbegin, int chend,
147+
void* data) override;
148+
bool read_native_tile(int subimage, int miplevel, int x, int y, int z,
149+
void* data) override;
150+
bool read_native_tiles(int subimage, int miplevel, int xbegin, int xend,
151+
int ybegin, int yend, int zbegin, int zend,
152+
void* data) override;
153+
bool read_native_tiles(int subimage, int miplevel, int xbegin, int xend,
154+
int ybegin, int yend, int zbegin, int zend,
155+
int chbegin, int chend, void* data) override;
156+
bool read_native_deep_scanlines(int subimage, int miplevel, int ybegin,
157+
int yend, int z, int chbegin, int chend,
158+
DeepData& deepdata) override;
159+
bool read_native_deep_tiles(int subimage, int miplevel, int xbegin,
160+
int xend, int ybegin, int yend, int zbegin,
161+
int zend, int chbegin, int chend,
162+
DeepData& deepdata) override;
163+
164+
bool set_ioproxy(Filesystem::IOProxy* ioproxy) override
165+
{
166+
m_io = ioproxy;
167+
return true;
168+
}
169+
170+
private:
171+
struct PartInfo {
172+
std::atomic_bool initialized;
173+
ImageSpec spec;
174+
int topwidth; ///< Width of top mip level
175+
int topheight; ///< Height of top mip level
176+
int levelmode; ///< The level mode
177+
int roundingmode; ///< Rounding mode
178+
bool cubeface; ///< It's a cubeface environment map
179+
int nmiplevels; ///< How many MIP levels are there?
180+
Imath::Box2i top_datawindow;
181+
Imath::Box2i top_displaywindow;
182+
std::vector<Imf::PixelType> pixeltype; ///< Imf pixel type for each chan
183+
std::vector<int> chanbytes; ///< Size (in bytes) of each channel
184+
185+
PartInfo()
186+
: initialized(false)
187+
{
188+
}
189+
PartInfo(const PartInfo& p)
190+
: initialized((bool)p.initialized)
191+
, spec(p.spec)
192+
, topwidth(p.topwidth)
193+
, topheight(p.topheight)
194+
, levelmode(p.levelmode)
195+
, roundingmode(p.roundingmode)
196+
, cubeface(p.cubeface)
197+
, nmiplevels(p.nmiplevels)
198+
, top_datawindow(p.top_datawindow)
199+
, top_displaywindow(p.top_displaywindow)
200+
, pixeltype(p.pixeltype)
201+
, chanbytes(p.chanbytes)
202+
{
203+
}
204+
~PartInfo() {}
205+
bool parse_header(OpenEXRInput* in, const Imf::Header* header);
206+
bool query_channels(OpenEXRInput* in, const Imf::Header* header);
207+
void compute_mipres(int miplevel, ImageSpec& spec) const;
208+
};
209+
friend struct PartInfo;
210+
211+
std::vector<PartInfo> m_parts; ///< Image parts
212+
OpenEXRInputStream* m_input_stream; ///< Stream for input file
213+
Imf::MultiPartInputFile* m_input_multipart; ///< Multipart input
214+
Imf::InputPart* m_scanline_input_part;
215+
Imf::TiledInputPart* m_tiled_input_part;
216+
Imf::DeepScanLineInputPart* m_deep_scanline_input_part;
217+
Imf::DeepTiledInputPart* m_deep_tiled_input_part;
218+
Filesystem::IOProxy* m_io = nullptr;
219+
std::unique_ptr<Filesystem::IOProxy> m_local_io;
220+
int m_subimage; ///< What subimage are we looking at?
221+
int m_nsubimages; ///< How many subimages are there?
222+
int m_miplevel; ///< What MIP level are we looking at?
223+
std::vector<float> m_missingcolor; ///< Color for missing tile/scanline
224+
225+
void init()
226+
{
227+
m_input_stream = NULL;
228+
m_input_multipart = NULL;
229+
m_scanline_input_part = NULL;
230+
m_tiled_input_part = NULL;
231+
m_deep_scanline_input_part = NULL;
232+
m_deep_tiled_input_part = NULL;
233+
m_subimage = -1;
234+
m_miplevel = -1;
235+
m_io = nullptr;
236+
m_local_io.reset();
237+
m_missingcolor.clear();
238+
}
239+
240+
bool read_native_tiles_individually(int subimage, int miplevel, int xbegin,
241+
int xend, int ybegin, int yend,
242+
int zbegin, int zend, int chbegin,
243+
int chend, void* data, stride_t xstride,
244+
stride_t ystride);
245+
246+
// Fill in with 'missing' color/pattern.
247+
void fill_missing(int xbegin, int xend, int ybegin, int yend, int zbegin,
248+
int zend, int chbegin, int chend, void* data,
249+
stride_t xstride, stride_t ystride);
250+
251+
// Prepare friend function for copyPixels
252+
friend class OpenEXROutput;
253+
};
254+
255+
256+
68257
OIIO_PLUGIN_NAMESPACE_END

0 commit comments

Comments
 (0)