diff --git a/src/libslic3r/PrintExport.hpp b/src/libslic3r/PrintExport.hpp index 0a9a54187..3f96cfaea 100644 --- a/src/libslic3r/PrintExport.hpp +++ b/src/libslic3r/PrintExport.hpp @@ -31,8 +31,6 @@ template class FilePrinter { public: - void print_config(const Print&); - // Draw an ExPolygon which is a polygon inside a slice on the specified layer. void draw_polygon(const ExPolygon& p, unsigned lyr); @@ -147,8 +145,8 @@ template<> class FilePrinter +layerh_str+"+printer=DWARF3\n"; } - // Change this to TOP_LEFT if you want correct PNG orientation - static const Raster::Origin ORIGIN = Raster::Origin::BOTTOM_LEFT; + // The PNG format has its origin in the top left corner. + static const Raster::Origin ORIGIN = Raster::Origin::TOP_LEFT; public: inline FilePrinter(double width_mm, double height_mm, diff --git a/src/libslic3r/Rasterizer/Rasterizer.cpp b/src/libslic3r/Rasterizer/Rasterizer.cpp index 3ff3e0949..621b76b08 100644 --- a/src/libslic3r/Rasterizer/Rasterizer.cpp +++ b/src/libslic3r/Rasterizer/Rasterizer.cpp @@ -45,15 +45,20 @@ private: TRawRenderer m_raw_renderer; TRendererAA m_renderer; Origin m_o; - std::function m_flipy = [](agg::path_storage&) {}; + + inline void flipy(agg::path_storage& path) const { + path.flip_y(0, m_resolution.height_px); + } + public: + inline Impl(const Raster::Resolution& res, const Raster::PixelDim &pd, Origin o): m_resolution(res), m_pxdim(pd), m_buf(res.pixels()), m_rbuf(reinterpret_cast(m_buf.data()), res.width_px, res.height_px, - res.width_px*TPixelRenderer::num_components), + int(res.width_px*TPixelRenderer::num_components)), m_pixfmt(m_rbuf), m_raw_renderer(m_pixfmt), m_renderer(m_raw_renderer), @@ -65,10 +70,6 @@ public: // ras.gamma(agg::gamma_power(1.0)); clear(); - - if(m_o == Origin::TOP_LEFT) m_flipy = [this](agg::path_storage& path) { - path.flip_y(0, m_resolution.height_px); - }; } void draw(const ExPolygon &poly) { @@ -76,12 +77,14 @@ public: agg::scanline_p8 scanlines; auto&& path = to_path(poly.contour); - m_flipy(path); + + if(m_o == Origin::TOP_LEFT) flipy(path); + ras.add_path(path); for(auto h : poly.holes) { auto&& holepath = to_path(h); - m_flipy(holepath); + if(m_o == Origin::TOP_LEFT) flipy(holepath); ras.add_path(holepath); } @@ -205,8 +208,9 @@ void Raster::save(std::ostream& stream, Compression comp) << m_impl->resolution().height_px << " " << "255 "; + auto sz = m_impl->buffer().size()*sizeof(Impl::TBuffer::value_type); stream.write(reinterpret_cast(m_impl->buffer().data()), - m_impl->buffer().size()*sizeof(Impl::TBuffer::value_type)); + std::streamsize(sz)); } } } diff --git a/src/libslic3r/Rasterizer/Rasterizer.hpp b/src/libslic3r/Rasterizer/Rasterizer.hpp index b6406b770..06d5b88c6 100644 --- a/src/libslic3r/Rasterizer/Rasterizer.hpp +++ b/src/libslic3r/Rasterizer/Rasterizer.hpp @@ -27,6 +27,13 @@ public: PNG //!> PNG compression }; + /// The Rasterizer expects the input polygons to have their coordinate + /// system origin in the bottom left corner. If the raster is then + /// configured with the TOP_LEFT origin parameter (in the constructor) than + /// it will flip the Y axis in output to maintain the correct orientation. + /// This is the default case with PNG images. They have the origin in the + /// top left corner. Without the flipping, the image would be upside down + /// with the scaled (clipper) coordinate system of the input polygons. enum class Origin { TOP_LEFT, BOTTOM_LEFT diff --git a/src/libslic3r/SLAPrint.cpp b/src/libslic3r/SLAPrint.cpp index 3cd1d0a24..2aed15273 100644 --- a/src/libslic3r/SLAPrint.cpp +++ b/src/libslic3r/SLAPrint.cpp @@ -715,6 +715,8 @@ void SLAPrint::process() std::vector keys; keys.reserve(levels.size()); for(auto& e : levels) keys.emplace_back(e.first); + bool flpXY = m_printer_config.display_flip_xy.getBool(); + { // create a raster printer for the current print parameters // I don't know any better auto& ocfg = m_objects.front()->m_config; @@ -729,6 +731,8 @@ void SLAPrint::process() double exp_t = matcfg.exposure_time.getFloat(); double iexp_t = matcfg.initial_exposure_time.getFloat(); + if(flpXY) { std::swap(w, h); std::swap(pw, ph); } + m_printer.reset(new SLAPrinter(w, h, pw, ph, lh, exp_t, iexp_t)); } @@ -744,7 +748,7 @@ void SLAPrint::process() // procedure to process one height level. This will run in parallel auto lvlfn = - [this, &slck, &keys, &levels, &printer, slot, sd, ist, &pst] + [this, &slck, &keys, &levels, &printer, slot, sd, ist, &pst, flpXY] (unsigned level_id) { if(canceled()) return; @@ -764,8 +768,12 @@ void SLAPrint::process() for(ExPolygon slice : sl) { // The order is important here: // apply rotation before translation... - slice.rotate(cp.rotation); + slice.rotate(double(cp.rotation)); slice.translate(cp.shift(X), cp.shift(Y)); + if(flpXY) { + for(auto& p : slice.contour.points) std::swap(p(X), p(Y)); + for(auto& h : slice.holes) for(auto& p : h.points) std::swap(p(X), p(Y)); + } printer.draw_polygon(slice, level_id); } }