Fixes for pwmx format PR

This commit is contained in:
tamasmeszaros 2022-02-14 13:27:06 +01:00
parent 5fcb618f96
commit b6fe41d5ab
8 changed files with 154 additions and 153 deletions

View File

@ -20,11 +20,14 @@
#include "libslic3r/miniz_extension.hpp" #include "libslic3r/miniz_extension.hpp"
#include "libslic3r/PNGReadWrite.hpp" #include "libslic3r/PNGReadWrite.hpp"
#include "libslic3r/LocalesUtils.hpp" #include "libslic3r/LocalesUtils.hpp"
#include "libslic3r/GCode/ThumbnailData.hpp"
#include <boost/property_tree/ini_parser.hpp> #include <boost/property_tree/ini_parser.hpp>
#include <boost/filesystem/path.hpp> #include <boost/filesystem/path.hpp>
#include <boost/algorithm/string.hpp> #include <boost/algorithm/string.hpp>
#include <miniz.h>
namespace marchsq { namespace marchsq {
template<> struct _RasterTraits<Slic3r::png::ImageGreyscale> { template<> struct _RasterTraits<Slic3r::png::ImageGreyscale> {
@ -482,10 +485,31 @@ sla::RasterEncoder SL1Archive::get_encoder() const
return sla::PNGRasterEncoder{}; return sla::PNGRasterEncoder{};
} }
void SL1Archive::export_print(Zipper& zipper, static void write_thumbnail(Zipper &zipper, const ThumbnailData &data)
{
size_t png_size = 0;
void *png_data = tdefl_write_image_to_png_file_in_memory_ex(
(const void *) data.pixels.data(), data.width, data.height, 4,
&png_size, MZ_DEFAULT_LEVEL, 1);
if (png_data != nullptr) {
zipper.add_entry("thumbnail/thumbnail" + std::to_string(data.width) +
"x" + std::to_string(data.height) + ".png",
static_cast<const std::uint8_t *>(png_data),
png_size);
mz_free(png_data);
}
}
void SL1Archive::export_print(const std::string fname,
const SLAPrint &print, const SLAPrint &print,
const ThumbnailsList &thumbnails,
const std::string &prjname) const std::string &prjname)
{ {
Zipper zipper{fname};
std::string project = std::string project =
prjname.empty() ? prjname.empty() ?
boost::filesystem::path(zipper.get_filename()).stem().string() : boost::filesystem::path(zipper.get_filename()).stem().string() :
@ -512,6 +536,12 @@ void SL1Archive::export_print(Zipper& zipper,
zipper.add_entry(imgname.c_str(), rst.data(), rst.size()); zipper.add_entry(imgname.c_str(), rst.data(), rst.size());
} }
for (const ThumbnailData& data : thumbnails)
if (data.is_valid())
write_thumbnail(zipper, data);
zipper.finalize();
} catch(std::exception& e) { } catch(std::exception& e) {
BOOST_LOG_TRIVIAL(error) << e.what(); BOOST_LOG_TRIVIAL(error) << e.what();
// Rethrow the exception // Rethrow the exception

View File

@ -24,7 +24,10 @@ public:
explicit SL1Archive(const SLAPrinterConfig &cfg): m_cfg(cfg) {} explicit SL1Archive(const SLAPrinterConfig &cfg): m_cfg(cfg) {}
explicit SL1Archive(SLAPrinterConfig &&cfg): m_cfg(std::move(cfg)) {} explicit SL1Archive(SLAPrinterConfig &&cfg): m_cfg(std::move(cfg)) {}
void export_print(Zipper &zipper, const SLAPrint &print, const std::string &projectname = "") override; void export_print(const std::string fname,
const SLAPrint &print,
const ThumbnailsList &thumbnails,
const std::string &projectname = "") override;
}; };
ConfigSubstitutions import_sla_archive(const std::string &zipfname, DynamicPrintConfig &out); ConfigSubstitutions import_sla_archive(const std::string &zipfname, DynamicPrintConfig &out);

View File

@ -1,5 +1,6 @@
#include "pwmx.hpp" #include "pwmx.hpp"
#include "GCode/ThumbnailData.hpp" #include "GCode/ThumbnailData.hpp"
#include "SLA/RasterBase.hpp"
#include <sstream> #include <sstream>
#include <iostream> #include <iostream>
@ -27,9 +28,59 @@
#define LAYER_SIZE_ESTIMATE (32 * 1024) #define LAYER_SIZE_ESTIMATE (32 * 1024)
namespace Slic3r { namespace Slic3r {
static void pwx_get_pixel_span(const std::uint8_t* ptr, const std::uint8_t* end,
std::uint8_t& pixel, size_t& span_len)
{
size_t max_len;
span_len = 0;
pixel = (*ptr) & 0xF0;
// the maximum length of the span depends on the pixel color
max_len = (pixel == 0 || pixel == 0xF0) ? 0xFFF : 0xF;
while (ptr < end && span_len < max_len && ((*ptr) & 0xF0) == pixel) {
span_len++;
ptr++;
}
}
struct PWXRasterEncoder
{
sla::EncodedRaster operator()(const void *ptr,
size_t w,
size_t h,
size_t num_components)
{
std::vector<uint8_t> dst;
size_t span_len;
std::uint8_t pixel;
auto size = w * h * num_components;
dst.reserve(size);
const std::uint8_t *src = reinterpret_cast<const std::uint8_t *>(ptr);
const std::uint8_t *src_end = src + size;
while (src < src_end) {
pwx_get_pixel_span(src, src_end, pixel, span_len);
src += span_len;
// fully transparent of fully opaque pixel
if (pixel == 0 || pixel == 0xF0) {
pixel = pixel | (span_len >> 8);
std::copy(&pixel, (&pixel) + 1, std::back_inserter(dst));
pixel = span_len & 0xFF;
std::copy(&pixel, (&pixel) + 1, std::back_inserter(dst));
}
// antialiased pixel
else {
pixel = pixel | span_len;
std::copy(&pixel, (&pixel) + 1, std::back_inserter(dst));
}
}
return sla::EncodedRaster(std::move(dst), "pwx");
}
};
using ConfMap = std::map<std::string, std::string>; using ConfMap = std::map<std::string, std::string>;
typedef struct pwmx_format_intro typedef struct pwmx_format_intro
@ -137,24 +188,28 @@ private:
namespace { namespace {
const char *get_cfg_value(const DynamicConfig &cfg, std::float_t get_cfg_value_f(const DynamicConfig &cfg,
const std::string &key, const std::string &key,
const std::string & def = "0") const std::float_t &def = 0.f)
{ {
std::string ret;
if (cfg.has(key)) { if (cfg.has(key)) {
auto opt = cfg.option(key); if (auto opt = cfg.option(key))
if (opt) { return opt->getFloat();
ret = opt->serialize();
} else {
return def.c_str();
}
} else {
return def.c_str();
} }
return ret.c_str(); return def;
}
int get_cfg_value_i(const DynamicConfig &cfg,
const std::string &key,
const int &def = 0)
{
if (cfg.has(key)) {
if (auto opt = cfg.option(key))
return opt->getInt();
}
return def;
} }
template<class T> void crop_value(T &val, T val_min, T val_max) template<class T> void crop_value(T &val, T val_min, T val_max)
@ -167,8 +222,8 @@ template<class T> void crop_value(T &val, T val_min, T val_max)
} }
void fill_preview(pwmx_format_preview &p, void fill_preview(pwmx_format_preview &p,
pwmx_format_misc &m, pwmx_format_misc &/*m*/,
ThumbnailsList &thumbnails) const ThumbnailsList &thumbnails)
{ {
p.preview_w = PREV_W; p.preview_w = PREV_W;
@ -216,6 +271,8 @@ void fill_header(pwmx_format_header &h,
const SLAPrint &print, const SLAPrint &print,
std::uint32_t layer_count) std::uint32_t layer_count)
{ {
CNumericLocalesSetter locales_setter;
std::float_t bottle_weight_g; std::float_t bottle_weight_g;
std::float_t bottle_volume_ml; std::float_t bottle_volume_ml;
std::float_t bottle_cost; std::float_t bottle_cost;
@ -232,21 +289,19 @@ void fill_header(pwmx_format_header &h,
mat_cfg.load_from_ini_string(mnotes, mat_cfg.load_from_ini_string(mnotes,
ForwardCompatibilitySubstitutionRule::Enable); ForwardCompatibilitySubstitutionRule::Enable);
h.layer_height_mm = std::atof(get_cfg_value(cfg, "layer_height")); h.layer_height_mm = get_cfg_value_f(cfg, "layer_height");
m.bottom_layer_height_mm = std::atof( m.bottom_layer_height_mm = get_cfg_value_f(cfg, "initial_layer_height");
get_cfg_value(cfg, "initial_layer_height")); h.exposure_time_s = get_cfg_value_f(cfg, "exposure_time");
h.exposure_time_s = std::atof(get_cfg_value(cfg, "exposure_time")); h.bottom_exposure_time_s = get_cfg_value_f(cfg, "initial_exposure_time");
h.bottom_exposure_time_s = std::atof( h.bottom_layer_count = get_cfg_value_i(cfg, "faded_layers");
get_cfg_value(cfg, "initial_exposure_time"));
h.bottom_layer_count = std::atof(get_cfg_value(cfg, "faded_layers"));
if (layer_count < h.bottom_layer_count) { if (layer_count < h.bottom_layer_count) {
h.bottom_layer_count = layer_count; h.bottom_layer_count = layer_count;
} }
h.res_x = std::atol(get_cfg_value(cfg, "display_pixels_x")); h.res_x = get_cfg_value_i(cfg, "display_pixels_x");
h.res_y = std::atol(get_cfg_value(cfg, "display_pixels_y")); h.res_y = get_cfg_value_i(cfg, "display_pixels_y");
bottle_weight_g = std::atof(get_cfg_value(cfg, "bottle_weight")) * 1000.0f; bottle_weight_g = get_cfg_value_f(cfg, "bottle_weight") * 1000.0f;
bottle_volume_ml = std::atof(get_cfg_value(cfg, "bottle_volume")); bottle_volume_ml = get_cfg_value_f(cfg, "bottle_volume");
bottle_cost = std::atof(get_cfg_value(cfg, "bottle_cost")); bottle_cost = get_cfg_value_f(cfg, "bottle_cost");
material_density = bottle_weight_g / bottle_volume_ml; material_density = bottle_weight_g / bottle_volume_ml;
h.volume_ml = (stats.objects_used_material + stats.support_used_material) / 1000; h.volume_ml = (stats.objects_used_material + stats.support_used_material) / 1000;
@ -257,37 +312,32 @@ void fill_header(pwmx_format_header &h,
h.per_layer_override = 0; h.per_layer_override = 0;
// TODO - expose these variables to the UI rather than using material notes // TODO - expose these variables to the UI rather than using material notes
h.delay_before_exposure_s = std::atof( h.delay_before_exposure_s = get_cfg_value_f(mat_cfg, CFG_DELAY_BEFORE_EXPOSURE, 0.5f);
get_cfg_value(mat_cfg, CFG_DELAY_BEFORE_EXPOSURE, "0.5"));
crop_value(h.delay_before_exposure_s, 0.0f, 1000.0f); crop_value(h.delay_before_exposure_s, 0.0f, 1000.0f);
h.lift_distance_mm = std::atof( h.lift_distance_mm = get_cfg_value_f(mat_cfg, CFG_LIFT_DISTANCE, 8.0f);
get_cfg_value(mat_cfg, CFG_LIFT_DISTANCE, "8.0"));
crop_value(h.lift_distance_mm, 0.0f, 100.0f); crop_value(h.lift_distance_mm, 0.0f, 100.0f);
if (mat_cfg.has(CFG_BOTTOM_LIFT_DISTANCE)) { if (mat_cfg.has(CFG_BOTTOM_LIFT_DISTANCE)) {
m.bottom_lift_distance_mm = std::atof( m.bottom_lift_distance_mm = get_cfg_value_f(mat_cfg,
get_cfg_value(mat_cfg, CFG_BOTTOM_LIFT_DISTANCE, "8.0")); CFG_BOTTOM_LIFT_DISTANCE,
8.0f);
crop_value(h.lift_distance_mm, 0.0f, 100.0f); crop_value(h.lift_distance_mm, 0.0f, 100.0f);
} else { } else {
m.bottom_lift_distance_mm = h.lift_distance_mm; m.bottom_lift_distance_mm = h.lift_distance_mm;
} }
h.lift_speed_mms = get_cfg_value_f(mat_cfg, CFG_LIFT_SPEED, 2.0f);
h.lift_speed_mms = std::atof(
get_cfg_value(mat_cfg, CFG_LIFT_SPEED, "2.0"));
crop_value(m.bottom_lift_speed_mms, 0.1f, 20.0f); crop_value(m.bottom_lift_speed_mms, 0.1f, 20.0f);
if (mat_cfg.has(CFG_BOTTOM_LIFT_SPEED)) { if (mat_cfg.has(CFG_BOTTOM_LIFT_SPEED)) {
m.bottom_lift_speed_mms = std::atof( m.bottom_lift_speed_mms = get_cfg_value_f(mat_cfg, CFG_BOTTOM_LIFT_SPEED, 2.0f);
get_cfg_value(mat_cfg, CFG_BOTTOM_LIFT_SPEED, "2.0"));
crop_value(m.bottom_lift_speed_mms, 0.1f, 20.0f); crop_value(m.bottom_lift_speed_mms, 0.1f, 20.0f);
} else { } else {
m.bottom_lift_speed_mms = h.lift_speed_mms; m.bottom_lift_speed_mms = h.lift_speed_mms;
} }
h.retract_speed_mms = std::atof( h.retract_speed_mms = get_cfg_value_f(mat_cfg, CFG_RETRACT_SPEED, 3.0f);
get_cfg_value(mat_cfg, CFG_RETRACT_SPEED, "3.0"));
crop_value(h.lift_speed_mms, 0.1f, 20.0f); crop_value(h.lift_speed_mms, 0.1f, 20.0f);
h.print_time_s = (h.bottom_layer_count * h.bottom_exposure_time_s) + h.print_time_s = (h.bottom_layer_count * h.bottom_exposure_time_s) +
@ -339,7 +389,7 @@ std::unique_ptr<sla::RasterBase> PwmxArchive::create_raster() const
sla::RasterEncoder PwmxArchive::get_encoder() const sla::RasterEncoder PwmxArchive::get_encoder() const
{ {
return sla::PWXRasterEncoder{}; return PWXRasterEncoder{};
} }
// Endian safe write of little endian 32bit ints // Endian safe write of little endian 32bit ints
@ -432,16 +482,16 @@ static void pwmx_write_layer(std::ofstream &out, pwmx_format_layer &l)
void PwmxArchive::export_print(const std::string fname, void PwmxArchive::export_print(const std::string fname,
const SLAPrint &print, const SLAPrint &print,
ThumbnailsList & thumbnails, const ThumbnailsList &thumbnails,
const std::string &prjname) const std::string &/*projectname*/)
{ {
std::uint32_t layer_count = m_layers.size(); std::uint32_t layer_count = m_layers.size();
pwmx_format_intro intro = {0}; pwmx_format_intro intro = {};
pwmx_format_header header = {0}; pwmx_format_header header = {};
pwmx_format_preview preview = {0}; pwmx_format_preview preview = {};
pwmx_format_layers_header layers_header = {0}; pwmx_format_layers_header layers_header = {};
pwmx_format_misc misc = {0}; pwmx_format_misc misc = {};
std::vector<uint8_t> layer_images; std::vector<uint8_t> layer_images;
std::uint32_t image_offset; std::uint32_t image_offset;

View File

@ -25,9 +25,8 @@ public:
void export_print(const std::string fname, void export_print(const std::string fname,
const SLAPrint &print, const SLAPrint &print,
ThumbnailsList &thumbnails, const ThumbnailsList &thumbnails,
const std::string &projectname = "") override; const std::string &projectname = "") override;
bool uses_zipper_export() override {return false;}
}; };

View File

@ -16,54 +16,6 @@ const RasterBase::TMirroring RasterBase::MirrorX = {true, false};
const RasterBase::TMirroring RasterBase::MirrorY = {false, true}; const RasterBase::TMirroring RasterBase::MirrorY = {false, true};
const RasterBase::TMirroring RasterBase::MirrorXY = {true, true}; const RasterBase::TMirroring RasterBase::MirrorXY = {true, true};
static void pwx_get_pixel_span(const std::uint8_t* ptr, const std::uint8_t* end,
std::uint8_t& pixel, size_t& span_len)
{
size_t max_len;
span_len = 0;
pixel = (*ptr) & 0xF0;
// the maximum length of the span depends on the pixel color
max_len = (pixel == 0 || pixel == 0xF0) ? 0xFFF : 0xF;
while (((*ptr) & 0xF0) == pixel && ptr < end && span_len < max_len) {
span_len++;
ptr++;
}
}
EncodedRaster PWXRasterEncoder::operator()(const void *ptr, size_t w, size_t h,
size_t num_components)
{
std::vector<uint8_t> dst;
size_t span_len;
std::uint8_t pixel;
auto size = w * h * num_components;
dst.reserve(size);
const std::uint8_t* src = reinterpret_cast<const std::uint8_t*>(ptr);
const std::uint8_t* src_end = src + size;
while (src < src_end) {
pwx_get_pixel_span(src, src_end, pixel, span_len);
src += span_len;
// fully transparent of fully opaque pixel
if (pixel == 0 || pixel == 0xF0) {
pixel = pixel | (span_len >> 8);
std::copy(&pixel, (&pixel) + 1, std::back_inserter(dst));
pixel = span_len & 0xFF;
std::copy(&pixel, (&pixel) + 1, std::back_inserter(dst));
}
// antialiased pixel
else {
pixel = pixel | span_len;
std::copy(&pixel, (&pixel) + 1, std::back_inserter(dst));
}
}
return EncodedRaster(std::move(dst), "pwx");
}
EncodedRaster PNGRasterEncoder::operator()(const void *ptr, size_t w, size_t h, EncodedRaster PNGRasterEncoder::operator()(const void *ptr, size_t w, size_t h,
size_t num_components) size_t num_components)
{ {

View File

@ -97,10 +97,6 @@ public:
virtual EncodedRaster encode(RasterEncoder encoder) const = 0; virtual EncodedRaster encode(RasterEncoder encoder) const = 0;
}; };
struct PWXRasterEncoder {
EncodedRaster operator()(const void *ptr, size_t w, size_t h, size_t num_components);
};
struct PNGRasterEncoder { struct PNGRasterEncoder {
EncodedRaster operator()(const void *ptr, size_t w, size_t h, size_t num_components); EncodedRaster operator()(const void *ptr, size_t w, size_t h, size_t num_components);
}; };

View File

@ -17,8 +17,6 @@
#include <boost/filesystem/path.hpp> #include <boost/filesystem/path.hpp>
#include <boost/log/trivial.hpp> #include <boost/log/trivial.hpp>
#include <miniz.h>
// #define SLAPRINT_DO_BENCHMARK // #define SLAPRINT_DO_BENCHMARK
#ifdef SLAPRINT_DO_BENCHMARK #ifdef SLAPRINT_DO_BENCHMARK
@ -1271,16 +1269,4 @@ void SLAPrint::StatusReporter::operator()(SLAPrint & p,
p.set_status(int(std::round(st)), msg, flags); p.set_status(int(std::round(st)), msg, flags);
} }
void SLAPrint::write_thumbnail(Zipper& zipper, const ThumbnailData& data)
{
size_t png_size = 0;
void* png_data = tdefl_write_image_to_png_file_in_memory_ex((const void*)data.pixels.data(), data.width, data.height, 4, &png_size, MZ_DEFAULT_LEVEL, 1);
if (png_data != nullptr)
{
zipper.add_entry("thumbnail/thumbnail" + std::to_string(data.width) + "x" + std::to_string(data.height) + ".png", (const std::uint8_t*)png_data, png_size);
mz_free(png_data);
}
}
} // namespace Slic3r } // namespace Slic3r

View File

@ -422,17 +422,11 @@ public:
execution::max_concurrency(ep)); execution::max_concurrency(ep));
} }
// Export the print into an archive using the provided zipper.
virtual void export_print(Zipper &zipper,
const SLAPrint &print,
const std::string &projectname = "") {};
// Export the print into an archive using the provided filename. // Export the print into an archive using the provided filename.
virtual void export_print(const std::string fname, virtual void export_print(const std::string fname,
const SLAPrint &print, const SLAPrint &print,
ThumbnailsList &thumbnails, const ThumbnailsList &thumbnails,
const std::string &projectname = "") {}; const std::string &projectname = "") = 0;
// By default the exporters use zipper export. Return false to use file export.
virtual bool uses_zipper_export() { return true; }
}; };
/** /**
@ -539,27 +533,18 @@ public:
// TODO: use this structure for the preview in the future. // TODO: use this structure for the preview in the future.
const std::vector<PrintLayer>& print_layers() const { return m_printer_input; } const std::vector<PrintLayer>& print_layers() const { return m_printer_input; }
void write_thumbnail(Zipper& zipper, const ThumbnailData& data);
void export_print(const std::string &fname, const std::string &projectname = "") void export_print(const std::string &fname, const std::string &projectname = "")
{ {
Slic3r::ThumbnailsList thumbnails; //empty thumbnail list ThumbnailsList thumbnails; //empty thumbnail list
export_print(fname, thumbnails, projectname); export_print(fname, thumbnails, projectname);
} }
void export_print(const std::string &fname, Slic3r::ThumbnailsList &thumbnails, const std::string &projectname = "") void export_print(const std::string &fname,
const ThumbnailsList &thumbnails,
const std::string &projectname = "")
{ {
if (m_archiver->uses_zipper_export()) {
Zipper zipper(fname);
m_archiver->export_print(zipper, *this, projectname);
for (const ThumbnailData& data : thumbnails)
if (data.is_valid())
write_thumbnail(zipper, data);
zipper.finalize();
} else {
m_archiver->export_print(fname, *this, thumbnails, projectname); m_archiver->export_print(fname, *this, thumbnails, projectname);
} }
}
private: private: