mirror of
https://github.com/SoftFever/OrcaSlicer.git
synced 2025-07-12 01:07:57 -06:00
Reducing copies when writing png data.
This commit is contained in:
parent
24145cc14f
commit
04e03c840d
6 changed files with 88 additions and 12 deletions
|
@ -93,6 +93,10 @@ public:
|
||||||
|
|
||||||
void next_entry(const std::string& /*fname*/) {}
|
void next_entry(const std::string& /*fname*/) {}
|
||||||
|
|
||||||
|
// binary entry
|
||||||
|
void binary_entry(const std::string& /*fname*/,
|
||||||
|
const std::uint8_t* buf, size_t len);
|
||||||
|
|
||||||
std::string get_name() { return ""; }
|
std::string get_name() { return ""; }
|
||||||
|
|
||||||
bool is_ok() { return false; }
|
bool is_ok() { return false; }
|
||||||
|
@ -111,7 +115,7 @@ template<> class FilePrinter<FilePrinterFormat::SLA_PNGZIP>
|
||||||
{
|
{
|
||||||
struct Layer {
|
struct Layer {
|
||||||
Raster first;
|
Raster first;
|
||||||
std::stringstream second;
|
RawBytes second;
|
||||||
|
|
||||||
Layer() {}
|
Layer() {}
|
||||||
|
|
||||||
|
@ -226,15 +230,15 @@ public:
|
||||||
|
|
||||||
inline void finish_layer(unsigned lyr_id) {
|
inline void finish_layer(unsigned lyr_id) {
|
||||||
assert(lyr_id < m_layers_rst.size());
|
assert(lyr_id < m_layers_rst.size());
|
||||||
m_layers_rst[lyr_id].first.save(m_layers_rst[lyr_id].second,
|
m_layers_rst[lyr_id].second =
|
||||||
Raster::Compression::PNG);
|
m_layers_rst[lyr_id].first.save(Raster::Compression::PNG);
|
||||||
m_layers_rst[lyr_id].first.reset();
|
m_layers_rst[lyr_id].first.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void finish_layer() {
|
inline void finish_layer() {
|
||||||
if(!m_layers_rst.empty()) {
|
if(!m_layers_rst.empty()) {
|
||||||
m_layers_rst.back().first.save(m_layers_rst.back().second,
|
m_layers_rst.back().second =
|
||||||
Raster::Compression::PNG);
|
m_layers_rst.back().first.save(Raster::Compression::PNG);
|
||||||
m_layers_rst.back().first.reset();
|
m_layers_rst.back().first.reset();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -254,18 +258,15 @@ public:
|
||||||
|
|
||||||
for(unsigned i = 0; i < m_layers_rst.size() && writer.is_ok(); i++)
|
for(unsigned i = 0; i < m_layers_rst.size() && writer.is_ok(); i++)
|
||||||
{
|
{
|
||||||
if(m_layers_rst[i].second.rdbuf()->in_avail() > 0) {
|
if(m_layers_rst[i].second.size > 0) {
|
||||||
char lyrnum[6];
|
char lyrnum[6];
|
||||||
std::sprintf(lyrnum, "%.5d", i);
|
std::sprintf(lyrnum, "%.5d", i);
|
||||||
auto zfilename = project + lyrnum + ".png";
|
auto zfilename = project + lyrnum + ".png";
|
||||||
writer.next_entry(zfilename);
|
|
||||||
|
|
||||||
if(!writer.is_ok()) break;
|
if(!writer.is_ok()) break;
|
||||||
|
|
||||||
writer << m_layers_rst[i].second.str();
|
writer.binary_entry(zfilename,
|
||||||
// writer << m_layers_rst[i].second.rdbuf();
|
m_layers_rst[i].second.buffer.get(),
|
||||||
// we can keep the date for later calls of this method
|
m_layers_rst[i].second.size);
|
||||||
//m_layers_rst[i].second.str("");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch(std::exception& e) {
|
} catch(std::exception& e) {
|
||||||
|
|
|
@ -18,6 +18,8 @@
|
||||||
// Experimental minz image write:
|
// Experimental minz image write:
|
||||||
#include <miniz/miniz_tdef.h>
|
#include <miniz/miniz_tdef.h>
|
||||||
|
|
||||||
|
#include <miniz/miniz_tdef.h>
|
||||||
|
|
||||||
namespace Slic3r {
|
namespace Slic3r {
|
||||||
|
|
||||||
class Raster::Impl {
|
class Raster::Impl {
|
||||||
|
@ -211,4 +213,41 @@ void Raster::save(std::ostream& stream, Compression comp)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RawBytes Raster::save(Raster::Compression comp)
|
||||||
|
{
|
||||||
|
assert(m_impl);
|
||||||
|
|
||||||
|
RawBytes ret;
|
||||||
|
|
||||||
|
switch(comp) {
|
||||||
|
case Compression::PNG: {
|
||||||
|
|
||||||
|
void *rawdata = tdefl_write_image_to_png_file_in_memory(
|
||||||
|
m_impl->buffer().data(),
|
||||||
|
int(resolution().width_px),
|
||||||
|
int(resolution().height_px), 1, &ret.size);
|
||||||
|
|
||||||
|
if(rawdata == nullptr) break;
|
||||||
|
|
||||||
|
ret.buffer.reset(static_cast<std::uint8_t*>(rawdata));
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case Compression::RAW: {
|
||||||
|
auto header = std::string("P5 ") +
|
||||||
|
std::to_string(m_impl->resolution().width_px) + " " +
|
||||||
|
std::to_string(m_impl->resolution().height_px) + " " + "255 ";
|
||||||
|
|
||||||
|
auto sz = m_impl->buffer().size()*sizeof(Impl::TBuffer::value_type);
|
||||||
|
|
||||||
|
ret.buffer.reset(new std::uint8_t[sz + header.size()]);
|
||||||
|
|
||||||
|
auto buff = reinterpret_cast<std::uint8_t*>(m_impl->buffer().data());
|
||||||
|
std::copy(buff, buff+sz, ret.buffer.get() + header.size());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,11 +3,18 @@
|
||||||
|
|
||||||
#include <ostream>
|
#include <ostream>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
namespace Slic3r {
|
namespace Slic3r {
|
||||||
|
|
||||||
class ExPolygon;
|
class ExPolygon;
|
||||||
|
|
||||||
|
// Raw byte buffer paired with its size. Suitable for compressed PNG data.
|
||||||
|
struct RawBytes {
|
||||||
|
std::unique_ptr<std::uint8_t> buffer = nullptr;
|
||||||
|
size_t size = 0;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Raster captures an anti-aliased monochrome canvas where vectorial
|
* @brief Raster captures an anti-aliased monochrome canvas where vectorial
|
||||||
* polygons can be rasterized. Fill color is always white and the background is
|
* polygons can be rasterized. Fill color is always white and the background is
|
||||||
|
@ -87,6 +94,8 @@ public:
|
||||||
|
|
||||||
/// Save the raster on the specified stream.
|
/// Save the raster on the specified stream.
|
||||||
void save(std::ostream& stream, Compression comp = Compression::RAW);
|
void save(std::ostream& stream, Compression comp = Compression::RAW);
|
||||||
|
|
||||||
|
RawBytes save(Compression comp = Compression::RAW);
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -212,6 +212,13 @@ public:
|
||||||
|
|
||||||
inline void next_entry(const std::string& fname) { m_zip.add_entry(fname); }
|
inline void next_entry(const std::string& fname) { m_zip.add_entry(fname); }
|
||||||
|
|
||||||
|
inline void binary_entry(const std::string& fname,
|
||||||
|
const std::uint8_t* buf,
|
||||||
|
size_t l)
|
||||||
|
{
|
||||||
|
m_zip.add_entry(fname, buf, l);
|
||||||
|
}
|
||||||
|
|
||||||
inline std::string get_name() const {
|
inline std::string get_name() const {
|
||||||
return m_zip.get_name();
|
return m_zip.get_name();
|
||||||
}
|
}
|
||||||
|
|
|
@ -149,6 +149,23 @@ void Zipper::add_entry(const std::string &name)
|
||||||
m_entry = name;
|
m_entry = name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Zipper::add_entry(const std::string &name, const uint8_t *data, size_t l)
|
||||||
|
{
|
||||||
|
finish_entry();
|
||||||
|
mz_uint cmpr = MZ_NO_COMPRESSION;
|
||||||
|
switch (m_compression) {
|
||||||
|
case NO_COMPRESSION: cmpr = MZ_NO_COMPRESSION; break;
|
||||||
|
case FAST_COMPRESSION: cmpr = MZ_BEST_SPEED; break;
|
||||||
|
case TIGHT_COMPRESSION: cmpr = MZ_BEST_COMPRESSION; break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!mz_zip_writer_add_mem(&m_impl->arch, name.c_str(), data, l, cmpr))
|
||||||
|
m_impl->blow_up();
|
||||||
|
|
||||||
|
m_entry.clear();
|
||||||
|
m_data.clear();
|
||||||
|
}
|
||||||
|
|
||||||
void Zipper::finish_entry()
|
void Zipper::finish_entry()
|
||||||
{
|
{
|
||||||
if(!m_data.empty() > 0 && !m_entry.empty()) {
|
if(!m_data.empty() > 0 && !m_entry.empty()) {
|
||||||
|
|
|
@ -46,6 +46,9 @@ public:
|
||||||
/// The previous entry is finished (see finish_entry)
|
/// The previous entry is finished (see finish_entry)
|
||||||
void add_entry(const std::string& name);
|
void add_entry(const std::string& name);
|
||||||
|
|
||||||
|
/// Add a new binary file entry with an instantly given byte buffer.
|
||||||
|
void add_entry(const std::string& name, const std::uint8_t* data, size_t l);
|
||||||
|
|
||||||
// Writing data to the archive works like with standard streams. The target
|
// Writing data to the archive works like with standard streams. The target
|
||||||
// within the zip file is the entry created with the add_entry method.
|
// within the zip file is the entry created with the add_entry method.
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue