Add constructor that takes generic std::istream objects (#11)

This commit is contained in:
Juha Reunanen
2021-04-02 20:31:04 +03:00
committed by GitHub
parent a41f1c89f7
commit d75f772ffa
4 changed files with 42 additions and 32 deletions

View File

@@ -18,16 +18,11 @@ int main(int argc, const char** argv) {
return -1; return -1;
} }
// read entire image file // open a stream to read just the necessary parts of the image file
std::ifstream file(argv[1], std::ifstream::in|std::ifstream::binary); std::ifstream istream(argv[1], std::ifstream::binary);
file.seekg(0,std::ios::end);
std::streampos length = file.tellg();
file.seekg(0,std::ios::beg);
std::vector<uint8_t> data(length);
file.read((char*)data.data(), length);
// parse image EXIF and XMP metadata // parse image EXIF and XMP metadata
TinyEXIF::EXIFInfo imageEXIF(data.data(), length); TinyEXIF::EXIFInfo imageEXIF(istream);
if (imageEXIF.Fields) if (imageEXIF.Fields)
std::cout std::cout
<< "Image Description " << imageEXIF.ImageDescription << "\n" << "Image Description " << imageEXIF.ImageDescription << "\n"

View File

@@ -43,6 +43,7 @@
#include <cfloat> #include <cfloat>
#include <vector> #include <vector>
#include <algorithm> #include <algorithm>
#include <iostream>
#ifdef _MSC_VER #ifdef _MSC_VER
namespace { namespace {
@@ -338,6 +339,9 @@ EXIFInfo::EXIFInfo() : Fields(FIELD_NA) {
EXIFInfo::EXIFInfo(EXIFStream& stream) { EXIFInfo::EXIFInfo(EXIFStream& stream) {
parseFrom(stream); parseFrom(stream);
} }
EXIFInfo::EXIFInfo(std::istream& stream) {
parseFrom(stream);
}
EXIFInfo::EXIFInfo(const uint8_t* data, unsigned length) { EXIFInfo::EXIFInfo(const uint8_t* data, unsigned length) {
parseFrom(data, length); parseFrom(data, length);
} }
@@ -848,6 +852,36 @@ int EXIFInfo::parseFrom(EXIFStream& stream) {
return app1s(); return app1s();
} }
int EXIFInfo::parseFrom(std::istream& stream) {
class EXIFStdStream : public EXIFStream {
public:
EXIFStdStream(std::istream& stream)
: stream(stream) {
// Would be nice to assert here that the stream was opened in binary mode, but
// apparently that's not possible: https://stackoverflow.com/a/224259/19254
}
bool IsValid() const override {
return !!stream;
}
const uint8_t* GetBuffer(unsigned desiredLength) override {
buffer.resize(desiredLength);
if (!stream.read(reinterpret_cast<char*>(buffer.data()), desiredLength))
return NULL;
return buffer.data();
}
bool SkipBuffer(unsigned desiredLength) override {
return (bool)stream.seekg(desiredLength, std::ios::cur);
}
private:
std::istream& stream;
std::vector<uint8_t> buffer;
};
EXIFStdStream streamWrapper(stream);
return parseFrom(streamWrapper);
}
int EXIFInfo::parseFrom(const uint8_t* buf, unsigned len) { int EXIFInfo::parseFrom(const uint8_t* buf, unsigned len) {
class EXIFStreamBuffer : public EXIFStream { class EXIFStreamBuffer : public EXIFStream {
public: public:

View File

@@ -100,6 +100,7 @@ class TINYEXIF_LIB EXIFInfo {
public: public:
EXIFInfo(); EXIFInfo();
EXIFInfo(EXIFStream& stream); EXIFInfo(EXIFStream& stream);
EXIFInfo(std::istream& stream); // NB: the stream must have been opened in binary mode
EXIFInfo(const uint8_t* data, unsigned length); EXIFInfo(const uint8_t* data, unsigned length);
// Parsing function for an entire JPEG image stream. // Parsing function for an entire JPEG image stream.
@@ -110,6 +111,7 @@ public:
// RETURN: PARSE_SUCCESS (0) on success with 'result' filled out // RETURN: PARSE_SUCCESS (0) on success with 'result' filled out
// error code otherwise, as defined by the PARSE_* macros // error code otherwise, as defined by the PARSE_* macros
int parseFrom(EXIFStream& stream); int parseFrom(EXIFStream& stream);
int parseFrom(std::istream& stream); // NB: the stream must have been opened in binary mode
int parseFrom(const uint8_t* data, unsigned length); int parseFrom(const uint8_t* data, unsigned length);
// Parsing function for an EXIF segment. This is used internally by parseFrom() // Parsing function for an EXIF segment. This is used internally by parseFrom()

View File

@@ -9,27 +9,6 @@
#include <vector> // std::vector #include <vector> // std::vector
#include <iomanip> // std::setprecision #include <iomanip> // std::setprecision
class EXIFStreamFile : public TinyEXIF::EXIFStream {
public:
explicit EXIFStreamFile(const char* fileName)
: file(fileName, std::ifstream::in|std::ifstream::binary) {}
bool IsValid() const override {
return file.is_open();
}
const uint8_t* GetBuffer(unsigned desiredLength) override {
buffer.resize(desiredLength);
if (!file.read((char*)buffer.data(), desiredLength))
return NULL;
return buffer.data();
}
bool SkipBuffer(unsigned desiredLength) override {
return (bool)file.seekg(desiredLength,std::ios::cur);
}
private:
std::ifstream file;
std::vector<uint8_t> buffer;
};
int main(int argc, const char** argv) int main(int argc, const char** argv)
{ {
if (argc != 2) { if (argc != 2) {
@@ -37,9 +16,9 @@ int main(int argc, const char** argv)
return -1; return -1;
} }
// read entire image file // open a stream to read just the necessary parts of the image file
EXIFStreamFile stream(argv[1]); std::ifstream stream(argv[1], std::ios::binary);
if (!stream.IsValid()) { if (!stream) {
std::cout << "error: can not open '" << argv[1] << "'\n"; std::cout << "error: can not open '" << argv[1] << "'\n";
return -2; return -2;
} }