diff options
author | tamasmeszaros <meszaros.q@gmail.com> | 2020-08-04 11:13:01 +0300 |
---|---|---|
committer | tamasmeszaros <meszaros.q@gmail.com> | 2020-08-28 00:14:42 +0300 |
commit | 79567a1958f334e9c43208aa336e668e7da1a311 (patch) | |
tree | db5ec4461b2a448b449b0de4f6fce1cdac7fe86c /src | |
parent | ad0df8fd098cfead66f9ede7456cd783a88ba049 (diff) |
Add some comments for png read interface
Diffstat (limited to 'src')
-rw-r--r-- | src/libslic3r/PNGRead.cpp | 46 | ||||
-rw-r--r-- | src/libslic3r/PNGRead.hpp | 58 |
2 files changed, 69 insertions, 35 deletions
diff --git a/src/libslic3r/PNGRead.cpp b/src/libslic3r/PNGRead.cpp index 5b5b9ffec..e66143b84 100644 --- a/src/libslic3r/PNGRead.cpp +++ b/src/libslic3r/PNGRead.cpp @@ -41,13 +41,6 @@ bool is_png(const ReadBuf &rb) return rb.sz >= PNG_SIG_BYTES && !png_sig_cmp(buf, 0, PNG_SIG_BYTES); } -// A wrapper around ReadBuf to be read repeatedly like a stream. libpng needs -// this form for its buffer read callback. -struct ReadBufReader { - const ReadBuf &rdbuf; size_t pos; - ReadBufReader(const ReadBuf &rd): rdbuf{rd}, pos{0} {} -}; - // Buffer read callback for libpng. It provides an allocated output buffer and // the amount of data it desires to read from the input. void png_read_callback(png_struct *png_ptr, @@ -55,20 +48,21 @@ void png_read_callback(png_struct *png_ptr, png_size_t byteCountToRead) { // Retrieve our input buffer through the png_ptr - auto reader = static_cast<ReadBufReader *>(png_get_io_ptr(png_ptr)); + auto reader = static_cast<IStream *>(png_get_io_ptr(png_ptr)); - if (!reader || byteCountToRead > reader->rdbuf.sz - reader->pos) return; + if (!reader || !reader->is_ok()) return; - auto buf = static_cast<const png_byte *>(reader->rdbuf.buf); - size_t pos = reader->pos; - - std::copy(buf + pos, buf + (pos + byteCountToRead), outBytes); - reader->pos += byteCountToRead; + reader->read(static_cast<std::uint8_t *>(outBytes), byteCountToRead); } -bool decode_png(const ReadBuf &rb, ImageGreyscale &img) +bool decode_png(IStream &in_buf, ImageGreyscale &out_img) { - if (!is_png(rb)) return false; + static const constexpr int PNG_SIG_BYTES = 8; + + std::vector<png_byte> sig(PNG_SIG_BYTES, 0); + in_buf.read(sig.data(), PNG_SIG_BYTES); + if (!png_check_sig(sig.data(), PNG_SIG_BYTES)) + return false; PNGDescr dsc; dsc.png = png_create_read_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, @@ -77,26 +71,28 @@ bool decode_png(const ReadBuf &rb, ImageGreyscale &img) if(!dsc.png) return false; dsc.info = png_create_info_struct(dsc.png); - if(!dsc.info) return {}; + if(!dsc.info) return false; + + png_set_read_fn(dsc.png, static_cast<void *>(&in_buf), png_read_callback); - ReadBufReader reader {rb}; - png_set_read_fn(dsc.png, static_cast<void *>(&reader), png_read_callback); + // Tell that we have already read the first bytes to check the signature + png_set_sig_bytes(dsc.png, PNG_SIG_BYTES); png_read_info(dsc.png, dsc.info); - img.cols = png_get_image_width(dsc.png, dsc.info); - img.rows = png_get_image_height(dsc.png, dsc.info); + out_img.cols = png_get_image_width(dsc.png, dsc.info); + out_img.rows = png_get_image_height(dsc.png, dsc.info); size_t color_type = png_get_color_type(dsc.png, dsc.info); size_t bit_depth = png_get_bit_depth(dsc.png, dsc.info); if (color_type != PNG_COLOR_TYPE_GRAY || bit_depth != 8) return false; - img.buf.resize(img.rows * img.cols); + out_img.buf.resize(out_img.rows * out_img.cols); - auto readbuf = static_cast<png_bytep>(img.buf.data()); - for (size_t r = 0; r < img.rows; ++r) - png_read_row(dsc.png, readbuf + r * img.cols, nullptr); + auto readbuf = static_cast<png_bytep>(out_img.buf.data()); + for (size_t r = 0; r < out_img.rows; ++r) + png_read_row(dsc.png, readbuf + r * out_img.cols, nullptr); return true; } diff --git a/src/libslic3r/PNGRead.hpp b/src/libslic3r/PNGRead.hpp index 0e7311f2e..082edd569 100644 --- a/src/libslic3r/PNGRead.hpp +++ b/src/libslic3r/PNGRead.hpp @@ -3,30 +3,68 @@ #include <vector> #include <string> +#include <istream> namespace Slic3r { namespace png { -struct ReadBuf { const void *buf = nullptr; const size_t sz = 0; }; +// Interface for an input stream of encoded png image data. +struct IStream { + virtual ~IStream() = default; + virtual size_t read(std::uint8_t *outp, size_t amount) = 0; + virtual bool is_ok() const = 0; +}; +// The output format of decode_png: a 2D pixel matrix stored continuously row +// after row (row major layout). template<class PxT> struct Image { std::vector<PxT> buf; size_t rows, cols; PxT get(size_t row, size_t col) const { return buf[row * cols + col]; } }; -struct RGB { uint8_t r, g, b; }; - -using ImageRGB = Image<RGB>; using ImageGreyscale = Image<uint8_t>; +// Only decodes true 8 bit grayscale png images. Returns false for other formats +// TODO (if needed): implement transformation of rgb images into grayscale... +bool decode_png(IStream &stream, ImageGreyscale &out_img); + +// TODO (if needed) +// struct RGB { uint8_t r, g, b; }; +// using ImageRGB = Image<RGB>; +// bool decode_png(IStream &stream, ImageRGB &img); + + +// Encoded png data buffer: a simple read-only buffer and its size. +struct ReadBuf { const void *buf = nullptr; const size_t sz = 0; }; + bool is_png(const ReadBuf &pngbuf); -// Only decodes true 8 bit grayscale png images. Returns false for other formats -// TODO: implement transformation of rgb images into grayscale... -bool decode_png(const ReadBuf &pngbuf, ImageGreyscale &img); +template<class Img> bool decode_png(const ReadBuf &in_buf, Img &out_img) +{ + struct ReadBufStream: public IStream { + const ReadBuf &rbuf_ref; size_t pos = 0; + + explicit ReadBufStream(const ReadBuf &buf): rbuf_ref{buf} {} + + size_t read(std::uint8_t *outp, size_t amount) override + { + if (amount > rbuf_ref.sz - pos) return 0; + + auto buf = static_cast<const std::uint8_t *>(rbuf_ref.buf); + std::copy(buf + pos, buf + (pos + amount), outp); + pos += amount; + + return amount; + } + + bool is_ok() const override { return pos < rbuf_ref.sz; } + } stream{in_buf}; + + return decode_png(stream, out_img); +} + +// TODO: std::istream of FILE* could be similarly adapted in case its needed... -// TODO -// bool decode_png(Buffer &&pngbuf, ImageRGB &img); +}} // namespace Slic3r::png -}} #endif // PNGREAD_HPP |