Skip to content

Add an ImageInput::valid_file(IOProxy) overload #3826

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 6 additions & 4 deletions src/bmp.imageio/bmpinput.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ class BmpInput final : public ImageInput {
{
return feature == "ioproxy";
}
bool valid_file(const std::string& filename) const override;
bool valid_file(Filesystem::IOProxy* ioproxy) const override;
bool open(const std::string& name, ImageSpec& newspec) override;
bool open(const std::string& name, ImageSpec& newspec,
const ImageSpec& config) override;
Expand Down Expand Up @@ -94,11 +94,13 @@ OIIO_PLUGIN_EXPORTS_END


bool
BmpInput::valid_file(const std::string& filename) const
BmpInput::valid_file(Filesystem::IOProxy* ioproxy) const
{
if (!ioproxy || ioproxy->mode() != Filesystem::IOProxy::Mode::Read)
return false;

bmp_pvt::BmpFileHeader header;
Filesystem::IOFile file(filename, Filesystem::IOProxy::Read);
return file.opened() && header.read_header(&file) && header.isBmp();
return header.read_header(ioproxy) && header.isBmp();
}


Expand Down
13 changes: 5 additions & 8 deletions src/dpx.imageio/dpxinput.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ class DPXInput final : public ImageInput {
{
return (feature == "ioproxy");
}
bool valid_file(const std::string& filename) const override;
bool valid_file(Filesystem::IOProxy* ioproxy) const override;
bool open(const std::string& name, ImageSpec& newspec) override;
bool open(const std::string& name, ImageSpec& newspec,
const ImageSpec& config) override;
Expand Down Expand Up @@ -107,21 +107,18 @@ OIIO_PLUGIN_EXPORTS_END


bool
DPXInput::valid_file(const std::string& filename) const
DPXInput::valid_file(Filesystem::IOProxy* ioproxy) const
{
Filesystem::IOProxy* io
= new Filesystem::IOFile(filename, Filesystem::IOProxy::Mode::Read);
std::unique_ptr<Filesystem::IOProxy> io_uptr(io);
if (!io || io->mode() != Filesystem::IOProxy::Mode::Read)
if (!ioproxy || ioproxy->mode() != Filesystem::IOProxy::Mode::Read)
return false;

std::unique_ptr<InStream> stream_uptr(new InStream(io));
std::unique_ptr<InStream> stream_uptr(new InStream(ioproxy));
if (!stream_uptr)
return false;

dpx::Reader dpx;
dpx.SetInStream(stream_uptr.get());
return dpx.ReadHeader(); // IOFile is automatically closed when destructed
return dpx.ReadHeader();
}


Expand Down
15 changes: 14 additions & 1 deletion src/include/OpenImageIO/imageio.h
Original file line number Diff line number Diff line change
Expand Up @@ -1025,11 +1025,24 @@ class OIIO_API ImageInput {
/// `true` upon success, or `false` upon failure.
virtual bool valid_file (const std::string& filename) const;

/// Check valid vile using a UTF-16 encoded wstring filename.
/// Check valid file using a UTF-16 encoded wstring filename.
bool valid_file (const std::wstring& filename) const {
return valid_file(Strutil::utf16_to_utf8(filename));
}

/// Return true if the `ioproxy` represents a file of the type for this
/// ImageInput. The implementation will try to determine this as
/// efficiently as possible, in most cases much less expensively than
/// doing a full `open()`. Note that there can be false positives: a
/// file can appear to be of the right type (i.e., `valid_file()`
/// returning `true`) but still fail a subsequent call to `open()`, such
/// as if the contents of the file are truncated, nonsensical, or
/// otherwise corrupted.
///
/// @returns
/// `true` upon success, or `false` upon failure.
virtual bool valid_file (Filesystem::IOProxy* ioproxy) const;

/// Opens the file with given name and seek to the first subimage in the
/// file. Various file attributes are put in `newspec` and a copy
/// is also saved internally to the `ImageInput` (retrievable via
Expand Down
8 changes: 2 additions & 6 deletions src/jpeg.imageio/jpeg_pvt.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,10 +62,8 @@ class JpgInput final : public ImageInput {
{
return (feature == "exif" || feature == "iptc" || feature == "ioproxy");
}
bool valid_file(const std::string& filename) const override
{
return valid_file(filename, nullptr);
}
bool valid_file(Filesystem::IOProxy* ioproxy) const override;

bool open(const std::string& name, ImageSpec& spec) override;
bool open(const std::string& name, ImageSpec& spec,
const ImageSpec& config) override;
Expand Down Expand Up @@ -119,8 +117,6 @@ class JpgInput final : public ImageInput {

bool read_icc_profile(j_decompress_ptr cinfo, ImageSpec& spec);

bool valid_file(const std::string& filename, Filesystem::IOProxy* io) const;

void close_file() { init(); }

friend class JpgOutput;
Expand Down
24 changes: 7 additions & 17 deletions src/jpeg.imageio/jpeginput.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -138,26 +138,16 @@ JpgInput::jpegerror(my_error_ptr /*myerr*/, bool fatal)


bool
JpgInput::valid_file(const std::string& filename, Filesystem::IOProxy* io) const
JpgInput::valid_file(Filesystem::IOProxy* ioproxy) const
{
// Check magic number to assure this is a JPEG file
uint8_t magic[2] = { 0, 0 };
bool ok = true;

if (io) {
ok = (io->pread(magic, sizeof(magic), 0) == sizeof(magic));
} else {
FILE* fd = Filesystem::fopen(filename, "rb");
if (!fd)
return false;
ok = (::fread(magic, sizeof(magic), 1, fd) == 1);
fclose(fd);
}
if (!ioproxy || ioproxy->mode() != Filesystem::IOProxy::Read)
return false;

if (magic[0] != JPEG_MAGIC1 || magic[1] != JPEG_MAGIC2) {
ok = false;
}
return ok;
uint8_t magic[2] {};
const size_t numRead = ioproxy->pread(magic, sizeof(magic), 0);
return numRead == sizeof(magic) && magic[0] == JPEG_MAGIC1
&& magic[1] == JPEG_MAGIC2;
}


Expand Down
37 changes: 33 additions & 4 deletions src/libOpenImageIO/imageinput.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -93,10 +93,39 @@ ImageInput::~ImageInput() {}
bool
ImageInput::valid_file(const std::string& filename) const
{
ImageSpec tmpspec;
bool ok = const_cast<ImageInput*>(this)->open(filename, tmpspec);
if (ok)
const_cast<ImageInput*>(this)->close();
ImageInput* self = const_cast<ImageInput*>(this);

if (self->supports("ioproxy")) {
Filesystem::IOFile io(filename, Filesystem::IOProxy::Read);
return valid_file(&io);
} else {
ImageSpec tmpspec;
bool ok = self->open(filename, tmpspec);
if (ok)
self->close();
(void)geterror(); // Clear any errors
return ok;
}
}



bool
ImageInput::valid_file(Filesystem::IOProxy* ioproxy) const
{
ImageInput* self = const_cast<ImageInput*>(this);

/* Open using the ioproxy if possible. */
if (!self->set_ioproxy(ioproxy))
return false;

ImageSpec config, tmpspec;
bool ok = self->open("", tmpspec, config);
if (ok) {
self->close();
}
self->ioproxy_clear();

(void)geterror(); // Clear any errors
return ok;
}
Expand Down
42 changes: 16 additions & 26 deletions src/openexr.imageio/exrinput.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ class OpenEXRInput final : public ImageInput {
|| feature == "iptc" // Because of arbitrary_metadata
|| feature == "ioproxy");
}
bool valid_file(const std::string& filename) const override;
bool valid_file(Filesystem::IOProxy* ioproxy) const override;
bool open(const std::string& name, ImageSpec& newspec,
const ImageSpec& config) override;
bool open(const std::string& name, ImageSpec& newspec) override
Expand Down Expand Up @@ -245,8 +245,6 @@ class OpenEXRInput final : public ImageInput {
m_missingcolor.clear();
}

bool valid_file(const std::string& filename, Filesystem::IOProxy* io) const;

bool read_native_tiles_individually(int subimage, int miplevel, int xbegin,
int xend, int ybegin, int yend,
int zbegin, int zend, int chbegin,
Expand Down Expand Up @@ -338,24 +336,13 @@ OpenEXRInput::OpenEXRInput() { init(); }


bool
OpenEXRInput::valid_file(const std::string& filename) const
OpenEXRInput::valid_file(Filesystem::IOProxy* ioproxy) const
{
return valid_file(filename, nullptr);
}


if (!ioproxy || ioproxy->mode() != Filesystem::IOProxy::Mode::Read)
return false;

bool
OpenEXRInput::valid_file(const std::string& filename,
Filesystem::IOProxy* io) const
{
try {
std::unique_ptr<Filesystem::IOProxy> local_io;
if (!io) {
io = new Filesystem::IOFile(filename, Filesystem::IOProxy::Read);
local_io.reset(io);
}
OpenEXRInputStream IStream(filename.c_str(), io);
OpenEXRInputStream IStream("", ioproxy);
return Imf::isOpenExrFile(IStream);
} catch (const std::exception& e) {
return false;
Expand All @@ -381,7 +368,16 @@ OpenEXRInput::open(const std::string& name, ImageSpec& newspec,
errorf("Could not open file \"%s\"", name);
return false;
}
if (!valid_file(name, m_io)) {

// If we weren't given an IOProxy, create one now that just reads from
// the file.
if (!m_io) {
m_io = new Filesystem::IOFile(name, Filesystem::IOProxy::Read);
m_local_io.reset(m_io);
}
OIIO_ASSERT(m_io);

if (!valid_file(m_io)) {
errorf("\"%s\" is not an OpenEXR file", name);
return false;
}
Expand Down Expand Up @@ -416,14 +412,8 @@ OpenEXRInput::open(const std::string& name, ImageSpec& newspec,
// Clear the spec with default constructor
m_spec = ImageSpec();

// Establish an input stream. If we weren't given an IOProxy, create one
// now that just reads from the file.
// Establish an input stream.
try {
if (!m_io) {
m_io = new Filesystem::IOFile(name, Filesystem::IOProxy::Read);
m_local_io.reset(m_io);
}
OIIO_ASSERT(m_io);
if (m_io->mode() != Filesystem::IOProxy::Read) {
// If the proxy couldn't be opened in write mode, try to
// return an error.
Expand Down
18 changes: 8 additions & 10 deletions src/png.imageio/pnginput.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ class PNGInput final : public ImageInput {
{
return (feature == "ioproxy" || feature == "exif");
}
bool valid_file(const std::string& filename) const override;
bool valid_file(Filesystem::IOProxy* ioproxy) const override;
bool open(const std::string& name, ImageSpec& newspec) override;
bool open(const std::string& name, ImageSpec& newspec,
const ImageSpec& config) override;
Expand Down Expand Up @@ -110,16 +110,14 @@ OIIO_PLUGIN_EXPORTS_END


bool
PNGInput::valid_file(const std::string& filename) const
PNGInput::valid_file(Filesystem::IOProxy* ioproxy) const
{
FILE* fd = Filesystem::fopen(filename, "rb");
if (!fd)
if (!ioproxy || ioproxy->mode() != Filesystem::IOProxy::Mode::Read)
return false;
unsigned char sig[8];
bool ok = (fread(sig, 1, sizeof(sig), fd) == sizeof(sig)
&& png_sig_cmp(sig, 0, 7) == 0);
fclose(fd);
return ok;

unsigned char sig[8] {};
const size_t numRead = ioproxy->pread(sig, sizeof(sig), 0);
return numRead == sizeof(sig) && png_sig_cmp(sig, 0, 8) == 0;
}


Expand All @@ -136,7 +134,7 @@ PNGInput::open(const std::string& name, ImageSpec& newspec)

unsigned char sig[8];
if (ioproxy()->pread(sig, sizeof(sig), 0) != sizeof(sig)
|| png_sig_cmp(sig, 0, 7)) {
|| png_sig_cmp(sig, 0, 8)) {
if (!has_error())
errorf("Not a PNG file");
return false; // Read failed
Expand Down
16 changes: 7 additions & 9 deletions src/sgi.imageio/sgiinput.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ class SgiInput final : public ImageInput {
{
return feature == "ioproxy";
}
bool valid_file(const std::string& filename) const override;
bool valid_file(Filesystem::IOProxy* ioproxy) const override;
bool open(const std::string& name, ImageSpec& spec) override;
bool open(const std::string& name, ImageSpec& newspec,
const ImageSpec& config) override;
Expand Down Expand Up @@ -82,16 +82,14 @@ OIIO_PLUGIN_EXPORTS_END


bool
SgiInput::valid_file(const std::string& filename) const
SgiInput::valid_file(Filesystem::IOProxy* ioproxy) const
{
FILE* fd = Filesystem::fopen(filename, "rb");
if (!fd)
if (!ioproxy || ioproxy->mode() != Filesystem::IOProxy::Read)
return false;
int16_t magic;
bool ok = (::fread(&magic, sizeof(magic), 1, fd) == 1)
&& (magic == sgi_pvt::SGI_MAGIC);
fclose(fd);
return ok;

int16_t magic {};
const size_t numRead = ioproxy->pread(&magic, sizeof(magic), 0);
return numRead == sizeof(magic) && magic == sgi_pvt::SGI_MAGIC;
}


Expand Down
Loading