diff --git a/src/libslic3r/Format/SL1.cpp b/src/libslic3r/Format/SL1.cpp index 6f1e95528..df10ce046 100644 --- a/src/libslic3r/Format/SL1.cpp +++ b/src/libslic3r/Format/SL1.cpp @@ -20,11 +20,14 @@ #include "libslic3r/miniz_extension.hpp" #include "libslic3r/PNGReadWrite.hpp" #include "libslic3r/LocalesUtils.hpp" +#include "libslic3r/GCode/ThumbnailData.hpp" #include #include #include +#include + namespace marchsq { template<> struct _RasterTraits { @@ -482,10 +485,31 @@ sla::RasterEncoder SL1Archive::get_encoder() const return sla::PNGRasterEncoder{}; } -void SL1Archive::export_print(Zipper& zipper, - const SLAPrint &print, - const std::string &prjname) +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(png_data), + png_size); + + mz_free(png_data); + } +} + +void SL1Archive::export_print(const std::string fname, + const SLAPrint &print, + const ThumbnailsList &thumbnails, + const std::string &prjname) +{ + Zipper zipper{fname}; + std::string project = prjname.empty() ? 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()); } + + for (const ThumbnailData& data : thumbnails) + if (data.is_valid()) + write_thumbnail(zipper, data); + + zipper.finalize(); } catch(std::exception& e) { BOOST_LOG_TRIVIAL(error) << e.what(); // Rethrow the exception diff --git a/src/libslic3r/Format/SL1.hpp b/src/libslic3r/Format/SL1.hpp index e6c0ff089..874786eb9 100644 --- a/src/libslic3r/Format/SL1.hpp +++ b/src/libslic3r/Format/SL1.hpp @@ -23,8 +23,11 @@ public: SL1Archive() = default; explicit SL1Archive(const SLAPrinterConfig &cfg): m_cfg(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); diff --git a/src/libslic3r/Format/pwmx.cpp b/src/libslic3r/Format/pwmx.cpp index 3be3c3d57..5b420a49e 100644 --- a/src/libslic3r/Format/pwmx.cpp +++ b/src/libslic3r/Format/pwmx.cpp @@ -1,5 +1,6 @@ #include "pwmx.hpp" #include "GCode/ThumbnailData.hpp" +#include "SLA/RasterBase.hpp" #include #include @@ -27,9 +28,59 @@ #define LAYER_SIZE_ESTIMATE (32 * 1024) - 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 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(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; typedef struct pwmx_format_intro @@ -137,24 +188,28 @@ private: namespace { -const char *get_cfg_value(const DynamicConfig &cfg, - const std::string & key, - const std::string & def = "0") +std::float_t get_cfg_value_f(const DynamicConfig &cfg, + const std::string &key, + const std::float_t &def = 0.f) { - std::string ret; - if (cfg.has(key)) { - auto opt = cfg.option(key); - if (opt) { - ret = opt->serialize(); - } else { - return def.c_str(); - } - } else { - return def.c_str(); + if (auto opt = cfg.option(key)) + return opt->getFloat(); } - 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 void crop_value(T &val, T val_min, T val_max) @@ -167,8 +222,8 @@ template void crop_value(T &val, T val_min, T val_max) } void fill_preview(pwmx_format_preview &p, - pwmx_format_misc &m, - ThumbnailsList &thumbnails) + pwmx_format_misc &/*m*/, + const ThumbnailsList &thumbnails) { p.preview_w = PREV_W; @@ -216,6 +271,8 @@ void fill_header(pwmx_format_header &h, const SLAPrint &print, std::uint32_t layer_count) { + CNumericLocalesSetter locales_setter; + std::float_t bottle_weight_g; std::float_t bottle_volume_ml; std::float_t bottle_cost; @@ -232,21 +289,19 @@ void fill_header(pwmx_format_header &h, mat_cfg.load_from_ini_string(mnotes, ForwardCompatibilitySubstitutionRule::Enable); - h.layer_height_mm = std::atof(get_cfg_value(cfg, "layer_height")); - m.bottom_layer_height_mm = std::atof( - get_cfg_value(cfg, "initial_layer_height")); - h.exposure_time_s = std::atof(get_cfg_value(cfg, "exposure_time")); - h.bottom_exposure_time_s = std::atof( - get_cfg_value(cfg, "initial_exposure_time")); - h.bottom_layer_count = std::atof(get_cfg_value(cfg, "faded_layers")); + h.layer_height_mm = get_cfg_value_f(cfg, "layer_height"); + m.bottom_layer_height_mm = get_cfg_value_f(cfg, "initial_layer_height"); + h.exposure_time_s = get_cfg_value_f(cfg, "exposure_time"); + h.bottom_exposure_time_s = get_cfg_value_f(cfg, "initial_exposure_time"); + h.bottom_layer_count = get_cfg_value_i(cfg, "faded_layers"); if (layer_count < h.bottom_layer_count) { h.bottom_layer_count = layer_count; } - h.res_x = std::atol(get_cfg_value(cfg, "display_pixels_x")); - h.res_y = std::atol(get_cfg_value(cfg, "display_pixels_y")); - bottle_weight_g = std::atof(get_cfg_value(cfg, "bottle_weight")) * 1000.0f; - bottle_volume_ml = std::atof(get_cfg_value(cfg, "bottle_volume")); - bottle_cost = std::atof(get_cfg_value(cfg, "bottle_cost")); + h.res_x = get_cfg_value_i(cfg, "display_pixels_x"); + h.res_y = get_cfg_value_i(cfg, "display_pixels_y"); + bottle_weight_g = get_cfg_value_f(cfg, "bottle_weight") * 1000.0f; + bottle_volume_ml = get_cfg_value_f(cfg, "bottle_volume"); + bottle_cost = get_cfg_value_f(cfg, "bottle_cost"); material_density = bottle_weight_g / bottle_volume_ml; 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; // TODO - expose these variables to the UI rather than using material notes - h.delay_before_exposure_s = std::atof( - get_cfg_value(mat_cfg, CFG_DELAY_BEFORE_EXPOSURE, "0.5")); + h.delay_before_exposure_s = get_cfg_value_f(mat_cfg, CFG_DELAY_BEFORE_EXPOSURE, 0.5f); crop_value(h.delay_before_exposure_s, 0.0f, 1000.0f); - h.lift_distance_mm = std::atof( - get_cfg_value(mat_cfg, CFG_LIFT_DISTANCE, "8.0")); + h.lift_distance_mm = get_cfg_value_f(mat_cfg, CFG_LIFT_DISTANCE, 8.0f); crop_value(h.lift_distance_mm, 0.0f, 100.0f); if (mat_cfg.has(CFG_BOTTOM_LIFT_DISTANCE)) { - m.bottom_lift_distance_mm = std::atof( - get_cfg_value(mat_cfg, CFG_BOTTOM_LIFT_DISTANCE, "8.0")); + m.bottom_lift_distance_mm = get_cfg_value_f(mat_cfg, + CFG_BOTTOM_LIFT_DISTANCE, + 8.0f); crop_value(h.lift_distance_mm, 0.0f, 100.0f); } else { m.bottom_lift_distance_mm = h.lift_distance_mm; } - - h.lift_speed_mms = std::atof( - get_cfg_value(mat_cfg, CFG_LIFT_SPEED, "2.0")); + h.lift_speed_mms = get_cfg_value_f(mat_cfg, CFG_LIFT_SPEED, 2.0f); crop_value(m.bottom_lift_speed_mms, 0.1f, 20.0f); if (mat_cfg.has(CFG_BOTTOM_LIFT_SPEED)) { - m.bottom_lift_speed_mms = std::atof( - get_cfg_value(mat_cfg, CFG_BOTTOM_LIFT_SPEED, "2.0")); + m.bottom_lift_speed_mms = get_cfg_value_f(mat_cfg, CFG_BOTTOM_LIFT_SPEED, 2.0f); crop_value(m.bottom_lift_speed_mms, 0.1f, 20.0f); } else { m.bottom_lift_speed_mms = h.lift_speed_mms; } - h.retract_speed_mms = std::atof( - get_cfg_value(mat_cfg, CFG_RETRACT_SPEED, "3.0")); + h.retract_speed_mms = get_cfg_value_f(mat_cfg, CFG_RETRACT_SPEED, 3.0f); crop_value(h.lift_speed_mms, 0.1f, 20.0f); h.print_time_s = (h.bottom_layer_count * h.bottom_exposure_time_s) + @@ -339,7 +389,7 @@ std::unique_ptr PwmxArchive::create_raster() const sla::RasterEncoder PwmxArchive::get_encoder() const { - return sla::PWXRasterEncoder{}; + return PWXRasterEncoder{}; } // Endian safe write of little endian 32bit ints @@ -430,18 +480,18 @@ static void pwmx_write_layer(std::ofstream &out, pwmx_format_layer &l) pwmx_write_float(out, l.layer48); } -void PwmxArchive::export_print(const std::string fname, - const SLAPrint & print, - ThumbnailsList & thumbnails, - const std::string &prjname) +void PwmxArchive::export_print(const std::string fname, + const SLAPrint &print, + const ThumbnailsList &thumbnails, + const std::string &/*projectname*/) { std::uint32_t layer_count = m_layers.size(); - pwmx_format_intro intro = {0}; - pwmx_format_header header = {0}; - pwmx_format_preview preview = {0}; - pwmx_format_layers_header layers_header = {0}; - pwmx_format_misc misc = {0}; + pwmx_format_intro intro = {}; + pwmx_format_header header = {}; + pwmx_format_preview preview = {}; + pwmx_format_layers_header layers_header = {}; + pwmx_format_misc misc = {}; std::vector layer_images; std::uint32_t image_offset; diff --git a/src/libslic3r/Format/pwmx.hpp b/src/libslic3r/Format/pwmx.hpp index 69cec100c..d1179c014 100644 --- a/src/libslic3r/Format/pwmx.hpp +++ b/src/libslic3r/Format/pwmx.hpp @@ -22,12 +22,11 @@ public: PwmxArchive() = default; explicit PwmxArchive(const SLAPrinterConfig &cfg): m_cfg(cfg) {} explicit PwmxArchive(SLAPrinterConfig &&cfg): m_cfg(std::move(cfg)) {} - - void export_print(const std::string fname, - const SLAPrint &print, - ThumbnailsList &thumbnails, - const std::string &projectname = "") override; - bool uses_zipper_export() override {return false;} + + void export_print(const std::string fname, + const SLAPrint &print, + const ThumbnailsList &thumbnails, + const std::string &projectname = "") override; }; diff --git a/src/libslic3r/SLA/RasterBase.cpp b/src/libslic3r/SLA/RasterBase.cpp index fd3f3e062..0b6c45eff 100644 --- a/src/libslic3r/SLA/RasterBase.cpp +++ b/src/libslic3r/SLA/RasterBase.cpp @@ -16,54 +16,6 @@ const RasterBase::TMirroring RasterBase::MirrorX = {true, false}; const RasterBase::TMirroring RasterBase::MirrorY = {false, 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 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(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, size_t num_components) { diff --git a/src/libslic3r/SLA/RasterBase.hpp b/src/libslic3r/SLA/RasterBase.hpp index 9d22591cc..657fc865c 100644 --- a/src/libslic3r/SLA/RasterBase.hpp +++ b/src/libslic3r/SLA/RasterBase.hpp @@ -97,10 +97,6 @@ public: 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 { EncodedRaster operator()(const void *ptr, size_t w, size_t h, size_t num_components); }; diff --git a/src/libslic3r/SLAPrint.cpp b/src/libslic3r/SLAPrint.cpp index 23502c44e..2622b6a23 100644 --- a/src/libslic3r/SLAPrint.cpp +++ b/src/libslic3r/SLAPrint.cpp @@ -17,8 +17,6 @@ #include #include -#include - // #define 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); } - -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 diff --git a/src/libslic3r/SLAPrint.hpp b/src/libslic3r/SLAPrint.hpp index 8d5b54376..2d49139a4 100644 --- a/src/libslic3r/SLAPrint.hpp +++ b/src/libslic3r/SLAPrint.hpp @@ -422,17 +422,11 @@ public: 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. - virtual void export_print(const std::string fname, - const SLAPrint &print, - ThumbnailsList &thumbnails, - const std::string &projectname = "") {}; - // By default the exporters use zipper export. Return false to use file export. - virtual bool uses_zipper_export() { return true; } + virtual void export_print(const std::string fname, + const SLAPrint &print, + const ThumbnailsList &thumbnails, + const std::string &projectname = "") = 0; }; /** @@ -538,27 +532,18 @@ public: // The aggregated and leveled print records from various objects. // TODO: use this structure for the preview in the future. const std::vector& 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 = "") { - Slic3r::ThumbnailsList thumbnails; //empty thumbnail list + ThumbnailsList thumbnails; //empty thumbnail list 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: