Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/prusa3d/PrusaSlicer.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'src/libslic3r/Rasterizer/Rasterizer.cpp')
-rw-r--r--src/libslic3r/Rasterizer/Rasterizer.cpp214
1 files changed, 214 insertions, 0 deletions
diff --git a/src/libslic3r/Rasterizer/Rasterizer.cpp b/src/libslic3r/Rasterizer/Rasterizer.cpp
new file mode 100644
index 000000000..b0bf04343
--- /dev/null
+++ b/src/libslic3r/Rasterizer/Rasterizer.cpp
@@ -0,0 +1,214 @@
+#include "Rasterizer.hpp"
+#include <ExPolygon.hpp>
+
+#include <cstdint>
+
+// For rasterizing
+#include <agg/agg_basics.h>
+#include <agg/agg_rendering_buffer.h>
+#include <agg/agg_pixfmt_gray.h>
+#include <agg/agg_pixfmt_rgb.h>
+#include <agg/agg_renderer_base.h>
+#include <agg/agg_renderer_scanline.h>
+
+#include <agg/agg_scanline_p.h>
+#include <agg/agg_rasterizer_scanline_aa.h>
+#include <agg/agg_path_storage.h>
+
+// For png compression
+#include <png/writer.hpp>
+
+namespace Slic3r {
+
+class Raster::Impl {
+public:
+ using TPixelRenderer = agg::pixfmt_gray8; // agg::pixfmt_rgb24;
+ using TRawRenderer = agg::renderer_base<TPixelRenderer>;
+ using TPixel = TPixelRenderer::color_type;
+ using TRawBuffer = agg::rendering_buffer;
+
+ using TBuffer = std::vector<TPixelRenderer::pixel_type>;
+
+ using TRendererAA = agg::renderer_scanline_aa_solid<TRawRenderer>;
+
+ static const TPixel ColorWhite;
+ static const TPixel ColorBlack;
+
+ using Origin = Raster::Origin;
+
+private:
+ Raster::Resolution resolution_;
+ Raster::PixelDim pxdim_;
+ TBuffer buf_;
+ TRawBuffer rbuf_;
+ TPixelRenderer pixfmt_;
+ TRawRenderer raw_renderer_;
+ TRendererAA renderer_;
+ Origin o_;
+ std::function<void(agg::path_storage&)> flipy_ = [](agg::path_storage&) {};
+public:
+ inline Impl(const Raster::Resolution& res, const Raster::PixelDim &pd,
+ Origin o):
+ resolution_(res), pxdim_(pd),
+ buf_(res.pixels()),
+ rbuf_(reinterpret_cast<TPixelRenderer::value_type*>(buf_.data()),
+ res.width_px, res.height_px,
+ res.width_px*TPixelRenderer::num_components),
+ pixfmt_(rbuf_),
+ raw_renderer_(pixfmt_),
+ renderer_(raw_renderer_),
+ o_(o)
+ {
+ renderer_.color(ColorWhite);
+
+ // If we would like to play around with gamma
+ // ras.gamma(agg::gamma_power(1.0));
+
+ clear();
+
+ if(o_ == Origin::TOP_LEFT) flipy_ = [this](agg::path_storage& path) {
+ path.flip_y(0, resolution_.height_px);
+ };
+ }
+
+ void draw(const ExPolygon &poly) {
+ agg::rasterizer_scanline_aa<> ras;
+ agg::scanline_p8 scanlines;
+
+ auto&& path = to_path(poly.contour);
+ flipy_(path);
+ ras.add_path(path);
+
+ for(auto h : poly.holes) {
+ auto&& holepath = to_path(h);
+ flipy_(holepath);
+ ras.add_path(holepath);
+ }
+
+ agg::render_scanlines(ras, scanlines, renderer_);
+ }
+
+ inline void clear() {
+ raw_renderer_.clear(ColorBlack);
+ }
+
+ inline TBuffer& buffer() { return buf_; }
+
+ inline const Raster::Resolution resolution() { return resolution_; }
+
+ inline Origin origin() const /*noexcept*/ { return o_; }
+
+private:
+ double getPx(const Point& p) {
+ return p(0) * SCALING_FACTOR/pxdim_.w_mm;
+ }
+
+ double getPy(const Point& p) {
+ return p(1) * SCALING_FACTOR/pxdim_.h_mm;
+ }
+
+ agg::path_storage to_path(const Polygon& poly) {
+ agg::path_storage path;
+ auto it = poly.points.begin();
+ path.move_to(getPx(*it), getPy(*it));
+ while(++it != poly.points.end())
+ path.line_to(getPx(*it), getPy(*it));
+
+ path.line_to(getPx(poly.points.front()), getPy(poly.points.front()));
+ return path;
+ }
+
+};
+
+const Raster::Impl::TPixel Raster::Impl::ColorWhite = Raster::Impl::TPixel(255);
+const Raster::Impl::TPixel Raster::Impl::ColorBlack = Raster::Impl::TPixel(0);
+
+Raster::Raster(const Resolution &r, const PixelDim &pd, Origin o):
+ impl_(new Impl(r, pd, o)) {}
+
+Raster::Raster() {}
+
+Raster::~Raster() {}
+
+Raster::Raster(Raster &&m):
+ impl_(std::move(m.impl_)) {}
+
+void Raster::reset(const Raster::Resolution &r, const Raster::PixelDim &pd)
+{
+ // Free up the unnecessary memory and make sure it stays clear after
+ // an exception
+ auto o = impl_? impl_->origin() : Origin::TOP_LEFT;
+ reset(r, pd, o);
+}
+
+void Raster::reset(const Raster::Resolution &r, const Raster::PixelDim &pd,
+ Raster::Origin o)
+{
+ impl_.reset();
+ impl_.reset(new Impl(r, pd, o));
+}
+
+void Raster::reset()
+{
+ impl_.reset();
+}
+
+Raster::Resolution Raster::resolution() const
+{
+ if(impl_) return impl_->resolution();
+
+ return Resolution(0, 0);
+}
+
+void Raster::clear()
+{
+ assert(impl_);
+ impl_->clear();
+}
+
+void Raster::draw(const ExPolygon &poly)
+{
+ assert(impl_);
+ impl_->draw(poly);
+}
+
+void Raster::save(std::ostream& stream, Compression comp)
+{
+ assert(impl_);
+ switch(comp) {
+ case Compression::PNG: {
+
+ png::writer<std::ostream> wr(stream);
+
+ wr.set_bit_depth(8);
+ wr.set_color_type(png::color_type_gray);
+ wr.set_width(resolution().width_px);
+ wr.set_height(resolution().height_px);
+ wr.set_compression_type(png::compression_type_default);
+
+ wr.write_info();
+
+ auto& b = impl_->buffer();
+ auto ptr = reinterpret_cast<png::byte*>( b.data() );
+ unsigned stride =
+ sizeof(Impl::TBuffer::value_type) * resolution().width_px;
+
+ for(unsigned r = 0; r < resolution().height_px; r++, ptr+=stride) {
+ wr.write_row(ptr);
+ }
+
+ break;
+ }
+ case Compression::RAW: {
+ stream << "P5 "
+ << impl_->resolution().width_px << " "
+ << impl_->resolution().height_px << " "
+ << "255 ";
+
+ stream.write(reinterpret_cast<const char*>(impl_->buffer().data()),
+ impl_->buffer().size()*sizeof(Impl::TBuffer::value_type));
+ }
+ }
+}
+
+}