mirror of
				https://github.com/SoftFever/OrcaSlicer.git
				synced 2025-10-31 04:31:15 -06:00 
			
		
		
		
	Add some comments for png read interface
This commit is contained in:
		
							parent
							
								
									ad0df8fd09
								
							
						
					
					
						commit
						79567a1958
					
				
					 2 changed files with 69 additions and 35 deletions
				
			
		|  | @ -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; | ||||
| 
 | ||||
|     ReadBufReader reader {rb}; | ||||
|     png_set_read_fn(dsc.png, static_cast<void *>(&reader), png_read_callback); | ||||
|     png_set_read_fn(dsc.png, static_cast<void *>(&in_buf), 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; | ||||
| } | ||||
|  |  | |||
|  | @ -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; | ||||
| 
 | ||||
| // TODO
 | ||||
| // bool decode_png(Buffer &&pngbuf, ImageRGB &img);
 | ||||
|         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...
 | ||||
| 
 | ||||
| }}     // namespace Slic3r::png
 | ||||
| 
 | ||||
| }} | ||||
| #endif // PNGREAD_HPP
 | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 tamasmeszaros
						tamasmeszaros