Add an overload of `Image::ReadPPM` method

Make it able to load image data from a `hwy::Span`.
This commit is contained in:
RangerUFO 2024-10-16 17:34:11 +08:00
parent a784b8459d
commit de2f7d7e2c
2 changed files with 73 additions and 0 deletions

View File

@ -64,6 +64,69 @@ void SkipWhitespaceAndComments(std::istream& in) {
} }
in.unget(); // Rewind last byte. in.unget(); // Rewind last byte.
} }
template <class CharT, class Traits = std::char_traits<CharT>>
class basic_spanbuf : public std::basic_streambuf<CharT, Traits> {
public:
using base_type = std::basic_streambuf<CharT, Traits>;
using char_type = typename base_type::char_type;
using traits_type = typename base_type::traits_type;
using int_type = typename traits_type::int_type;
using pos_type = typename traits_type::pos_type;
using off_type = typename traits_type::off_type;
basic_spanbuf(const hwy::Span<char_type>& buf) {
this->setg(buf.data(), buf.data(), buf.data() + buf.size());
}
std::streamsize showmanyc() override {
return this->egptr() - this->gptr();
}
std::streamsize xsgetn(char_type* s, std::streamsize n) override {
if (n == 0) {
return 0;
}
if (this->gptr() + n > this->egptr()) {
n = this->egptr() - this->gptr();
if (n == 0) {
if (this->uflow() == traits_type::eof()) {
return -1;
}
return 0;
}
}
std::memmove(s, this->gptr(), n);
this->gbump(n);
return n;
}
int_type pbackfail(int_type c) override {
*(this->gptr() - 1) = traits_type::to_char_type(c);
this->pbump(-1);
return 1;
}
};
template <class CharT, class Traits = std::char_traits<CharT>>
class basic_ispanstream : public std::basic_istream<CharT, Traits> {
public:
using base_type = std::basic_istream<CharT, Traits>;
using char_type = typename base_type::char_type;
using traits_type = typename base_type::traits_type;
using int_type = typename traits_type::int_type;
using pos_type = typename traits_type::pos_type;
using off_type = typename traits_type::off_type;
basic_ispanstream(const hwy::Span<char_type>& buf)
: base_type(nullptr)
, sb_(buf) {
this->init(&sb_);
}
private:
basic_spanbuf<CharT, Traits> sb_;
};
} // namespace } // namespace
bool Image::ReadPPM(const std::string& filename) { bool Image::ReadPPM(const std::string& filename) {
@ -123,6 +186,11 @@ bool Image::ReadPPM(std::istream& in) {
return true; return true;
} }
bool Image::ReadPPM(const hwy::Span<char>& buf) {
basic_ispanstream<char> in(buf);
return ReadPPM(in);
}
void Image::Resize() { void Image::Resize() {
int new_width = 224; int new_width = 224;
int new_height = kImageSize; int new_height = kImageSize;

View File

@ -21,6 +21,8 @@
#include <istream> #include <istream>
#include <vector> #include <vector>
#include "hwy/aligned_allocator.h" // Span
namespace gcpp { namespace gcpp {
// Very basic image loading and processing for PaliGemma-224. Does not try to be // Very basic image loading and processing for PaliGemma-224. Does not try to be
@ -34,6 +36,9 @@ class Image {
// Reads PPM format (P6, binary) data from a stream, normalizes to [-1, 1]. // Reads PPM format (P6, binary) data from a stream, normalizes to [-1, 1].
// Returns true on success. // Returns true on success.
bool ReadPPM(std::istream& in); bool ReadPPM(std::istream& in);
// Reads PPM format (P6, binary) data from a hwy::Span, normalizes to [-1, 1].
// Returns true on success.
bool ReadPPM(const hwy::Span<char>& buf);
// Resizes to 224x224 (nearest-neighbor for now, bilinear or antialias would // Resizes to 224x224 (nearest-neighbor for now, bilinear or antialias would
// be better). // be better).
void Resize(); void Resize();