mirror of
https://github.com/SoftFever/OrcaSlicer.git
synced 2025-07-25 07:34:03 -06:00
Thumbnail Formats Option Ported from PrusaSlicer and add BIQU/BTT format (#2405)
* Add needed src files and update CMake files * Implementation of GCodeThumbnailsFormat for PNG, JPG, and QOI complete * Implement BIQU (Big Tree Tech) Thumbnail Format * have GCodeProcessor.post_process pass through original line end characters * fix biqu thumbnail output use \r\n for new lines in the biqu thumbnail portion. the firmware requires these end characters to function properly. update names of variables and add comments to be more descriptive replace modified Qt pixel algorithm with much simpler algorithm from BTT TFT firmware * rename BiQU to BTT_TFT for better clarity * remove underscore from GUI option --------- Co-authored-by: SoftFever <103989404+SoftFever@users.noreply.github.com>
This commit is contained in:
parent
25c9b43d62
commit
4d14ee15ce
15 changed files with 1124 additions and 50 deletions
|
@ -411,6 +411,8 @@ set(lisbslic3r_sources
|
|||
Shape/TextShape.cpp
|
||||
calib.hpp
|
||||
calib.cpp
|
||||
GCode/Thumbnails.cpp
|
||||
GCode/Thumbnails.hpp
|
||||
)
|
||||
|
||||
if (APPLE)
|
||||
|
@ -473,6 +475,8 @@ set(OpenCASCADE_DIR "${CMAKE_PREFIX_PATH}/lib/cmake/occt")
|
|||
find_package(OpenCASCADE REQUIRED)
|
||||
target_include_directories(libslic3r PUBLIC ${OpenCASCADE_INCLUDE_DIR})
|
||||
|
||||
find_package(JPEG REQUIRED)
|
||||
|
||||
set(OCCT_LIBS
|
||||
TKXDESTEP
|
||||
TKSTEP
|
||||
|
@ -525,6 +529,8 @@ target_link_libraries(libslic3r
|
|||
${OCCT_LIBS}
|
||||
Clipper2
|
||||
mcut
|
||||
JPEG::JPEG
|
||||
qoi
|
||||
)
|
||||
|
||||
if(NOT WIN32)
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#include "EdgeGrid.hpp"
|
||||
#include "Geometry/ConvexHull.hpp"
|
||||
#include "GCode/PrintExtents.hpp"
|
||||
#include "GCode/Thumbnails.hpp"
|
||||
#include "GCode/WipeTower.hpp"
|
||||
#include "ShortestPath.hpp"
|
||||
#include "Print.hpp"
|
||||
|
@ -1663,50 +1664,6 @@ namespace DoExport {
|
|||
}
|
||||
}
|
||||
|
||||
//BBS: add plate id for thumbnail generate param
|
||||
template<typename WriteToOutput, typename ThrowIfCanceledCallback>
|
||||
static void export_thumbnails_to_file(ThumbnailsGeneratorCallback &thumbnail_cb, int plate_id, const std::vector<Vec2d> &sizes, WriteToOutput output, ThrowIfCanceledCallback throw_if_canceled)
|
||||
{
|
||||
// Write thumbnails using base64 encoding
|
||||
if (thumbnail_cb != nullptr)
|
||||
{
|
||||
const size_t max_row_length = 78;
|
||||
//BBS: add plate id for thumbnail generate param
|
||||
ThumbnailsList thumbnails = thumbnail_cb(ThumbnailsParams{ sizes, true, true, true, true, plate_id });
|
||||
for (const ThumbnailData& data : thumbnails)
|
||||
{
|
||||
if (data.is_valid())
|
||||
{
|
||||
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)
|
||||
{
|
||||
std::string encoded;
|
||||
encoded.resize(boost::beast::detail::base64::encoded_size(png_size));
|
||||
encoded.resize(boost::beast::detail::base64::encode((void*)&encoded[0], (const void*)png_data, png_size));
|
||||
|
||||
output("; THUMBNAIL_BLOCK_START\n");
|
||||
output((boost::format("; thumbnail begin %dx%d %d\n") % data.width % data.height % encoded.size()).str().c_str());
|
||||
|
||||
unsigned int row_count = 0;
|
||||
//BBS: optimize performance ,reduce too much memeory operation
|
||||
size_t current_index = 0;
|
||||
while(current_index<encoded.size()){
|
||||
output((boost::format("; %s\n") % encoded.substr(current_index, max_row_length)).str().c_str());
|
||||
current_index+=std::min(max_row_length,encoded.size()-current_index);
|
||||
++row_count;
|
||||
}
|
||||
output("; thumbnail end\n");
|
||||
output("; THUMBNAIL_BLOCK_END\n\n");
|
||||
|
||||
mz_free(png_data);
|
||||
}
|
||||
}
|
||||
throw_if_canceled();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Fill in print_statistics and return formatted string containing filament statistics to be inserted into G-code comment section.
|
||||
static std::string update_print_stats_and_format_filament_stats(
|
||||
const bool has_wipe_tower,
|
||||
|
@ -1918,6 +1875,15 @@ void GCode::_do_export(Print& print, GCodeOutputStream &file, ThumbnailsGenerato
|
|||
} else
|
||||
m_enable_extrusion_role_markers = false;
|
||||
|
||||
// if thumbnail type of BTT_TFT, insert above header
|
||||
// if not, it is inserted under the header in its normal spot
|
||||
const GCodeThumbnailsFormat m_gcode_thumbnail_format = print.full_print_config().opt_enum<GCodeThumbnailsFormat>("thumbnails_format");
|
||||
if (m_gcode_thumbnail_format == GCodeThumbnailsFormat::BTT_TFT)
|
||||
GCodeThumbnails::export_thumbnails_to_file(
|
||||
thumbnail_cb, print.get_plate_index(), print.full_print_config().option<ConfigOptionPoints>("thumbnails")->values,
|
||||
m_gcode_thumbnail_format,
|
||||
[&file](const char *sz) { file.write(sz); },
|
||||
[&print]() { print.throw_if_canceled(); });
|
||||
|
||||
file.write_format("; HEADER_BLOCK_START\n");
|
||||
// Write information on the generator.
|
||||
|
@ -1977,10 +1943,12 @@ void GCode::_do_export(Print& print, GCodeOutputStream &file, ThumbnailsGenerato
|
|||
print.config().nozzle_temperature_initial_layer.get_at(0));
|
||||
file.write("; CONFIG_BLOCK_END\n\n");
|
||||
} else {
|
||||
DoExport::export_thumbnails_to_file(
|
||||
thumbnail_cb, print.get_plate_index(), print.full_print_config().option<ConfigOptionPoints>("thumbnails")->values,
|
||||
[&file](const char *sz) { file.write(sz); },
|
||||
[&print]() { print.throw_if_canceled(); });
|
||||
if (m_gcode_thumbnail_format != GCodeThumbnailsFormat::BTT_TFT)
|
||||
GCodeThumbnails::export_thumbnails_to_file(
|
||||
thumbnail_cb, print.get_plate_index(), print.full_print_config().option<ConfigOptionPoints>("thumbnails")->values,
|
||||
m_gcode_thumbnail_format,
|
||||
[&file](const char *sz) { file.write(sz); },
|
||||
[&print]() { print.throw_if_canceled(); });
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -668,7 +668,10 @@ void GCodeProcessor::TimeProcessor::post_process(const std::string& filename, st
|
|||
if (eol) {
|
||||
++line_id;
|
||||
|
||||
gcode_line += "\n";
|
||||
// determine the end of line character and pass to output
|
||||
gcode_line += *it_end;
|
||||
if(*it_end == '\r' && *(++ it_end) == '\n')
|
||||
gcode_line += '\n';
|
||||
// replace placeholder lines
|
||||
auto [processed, lines_added_count] = process_placeholders(gcode_line);
|
||||
if (processed && lines_added_count > 0)
|
||||
|
|
196
src/libslic3r/GCode/Thumbnails.cpp
Normal file
196
src/libslic3r/GCode/Thumbnails.cpp
Normal file
|
@ -0,0 +1,196 @@
|
|||
///|/ Copyright (c) Prusa Research 2022 Enrico Turri @enricoturri1966, Vojtěch Bubník @bubnikv
|
||||
///|/
|
||||
///|/ PrusaSlicer is released under the terms of the AGPLv3 or higher
|
||||
///|/
|
||||
#include "Thumbnails.hpp"
|
||||
#include "../miniz_extension.hpp"
|
||||
|
||||
#include <qoi/qoi.h>
|
||||
#include <jpeglib.h>
|
||||
#include <jerror.h>
|
||||
|
||||
namespace Slic3r::GCodeThumbnails {
|
||||
|
||||
using namespace std::literals;
|
||||
|
||||
struct CompressedPNG : CompressedImageBuffer
|
||||
{
|
||||
~CompressedPNG() override { if (data) mz_free(data); }
|
||||
std::string_view tag() const override { return "thumbnail"sv; }
|
||||
};
|
||||
|
||||
struct CompressedJPG : CompressedImageBuffer
|
||||
{
|
||||
~CompressedJPG() override { free(data); }
|
||||
std::string_view tag() const override { return "thumbnail_JPG"sv; }
|
||||
};
|
||||
|
||||
struct CompressedQOI : CompressedImageBuffer
|
||||
{
|
||||
~CompressedQOI() override { free(data); }
|
||||
std::string_view tag() const override { return "thumbnail_QOI"sv; }
|
||||
};
|
||||
|
||||
struct CompressedBIQU : CompressedImageBuffer
|
||||
{
|
||||
~CompressedBIQU() override { free(data); }
|
||||
std::string_view tag() const override { return "thumbnail_BIQU"sv; }
|
||||
};
|
||||
|
||||
std::unique_ptr<CompressedImageBuffer> compress_thumbnail_png(const ThumbnailData &data)
|
||||
{
|
||||
auto out = std::make_unique<CompressedPNG>();
|
||||
out->data = tdefl_write_image_to_png_file_in_memory_ex((const void*)data.pixels.data(), data.width, data.height, 4, &out->size, MZ_DEFAULT_LEVEL, 1);
|
||||
return out;
|
||||
}
|
||||
|
||||
std::unique_ptr<CompressedImageBuffer> compress_thumbnail_jpg(const ThumbnailData& data)
|
||||
{
|
||||
// Take vector of RGBA pixels and flip the image vertically
|
||||
std::vector<unsigned char> rgba_pixels(data.pixels.size());
|
||||
const unsigned int row_size = data.width * 4;
|
||||
for (unsigned int y = 0; y < data.height; ++y) {
|
||||
::memcpy(rgba_pixels.data() + (data.height - y - 1) * row_size, data.pixels.data() + y * row_size, row_size);
|
||||
}
|
||||
|
||||
// Store pointers to scanlines start for later use
|
||||
std::vector<unsigned char*> rows_ptrs;
|
||||
rows_ptrs.reserve(data.height);
|
||||
for (unsigned int y = 0; y < data.height; ++y) {
|
||||
rows_ptrs.emplace_back(&rgba_pixels[y * row_size]);
|
||||
}
|
||||
|
||||
std::vector<unsigned char> compressed_data(data.pixels.size());
|
||||
unsigned char* compressed_data_ptr = compressed_data.data();
|
||||
unsigned long compressed_data_size = data.pixels.size();
|
||||
|
||||
jpeg_error_mgr err;
|
||||
jpeg_compress_struct info;
|
||||
info.err = jpeg_std_error(&err);
|
||||
jpeg_create_compress(&info);
|
||||
jpeg_mem_dest(&info, &compressed_data_ptr, &compressed_data_size);
|
||||
|
||||
info.image_width = data.width;
|
||||
info.image_height = data.height;
|
||||
info.input_components = 4;
|
||||
info.in_color_space = JCS_EXT_RGBA;
|
||||
|
||||
jpeg_set_defaults(&info);
|
||||
jpeg_set_quality(&info, 85, TRUE);
|
||||
jpeg_start_compress(&info, TRUE);
|
||||
|
||||
jpeg_write_scanlines(&info, rows_ptrs.data(), data.height);
|
||||
jpeg_finish_compress(&info);
|
||||
jpeg_destroy_compress(&info);
|
||||
|
||||
// FIXME -> Add error checking
|
||||
|
||||
auto out = std::make_unique<CompressedJPG>();
|
||||
out->data = malloc(compressed_data_size);
|
||||
out->size = size_t(compressed_data_size);
|
||||
::memcpy(out->data, (const void*)compressed_data.data(), out->size);
|
||||
return out;
|
||||
}
|
||||
|
||||
std::unique_ptr<CompressedImageBuffer> compress_thumbnail_qoi(const ThumbnailData &data)
|
||||
{
|
||||
qoi_desc desc;
|
||||
desc.width = data.width;
|
||||
desc.height = data.height;
|
||||
desc.channels = 4;
|
||||
desc.colorspace = QOI_SRGB;
|
||||
|
||||
// Take vector of RGBA pixels and flip the image vertically
|
||||
std::vector<uint8_t> rgba_pixels(data.pixels.size() * 4);
|
||||
size_t row_size = data.width * 4;
|
||||
for (size_t y = 0; y < data.height; ++ y)
|
||||
memcpy(rgba_pixels.data() + (data.height - y - 1) * row_size, data.pixels.data() + y * row_size, row_size);
|
||||
|
||||
auto out = std::make_unique<CompressedQOI>();
|
||||
int size;
|
||||
out->data = qoi_encode((const void*)rgba_pixels.data(), &desc, &size);
|
||||
out->size = size;
|
||||
return out;
|
||||
}
|
||||
|
||||
std::unique_ptr<CompressedImageBuffer> compress_thumbnail_btt_tft(const ThumbnailData &data) {
|
||||
|
||||
// Take vector of RGBA pixels and flip the image vertically
|
||||
std::vector<unsigned char> rgba_pixels(data.pixels.size());
|
||||
const unsigned int row_size = data.width * 4;
|
||||
for (unsigned int y = 0; y < data.height; ++y) {
|
||||
::memcpy(rgba_pixels.data() + (data.height - y - 1) * row_size, data.pixels.data() + y * row_size, row_size);
|
||||
}
|
||||
|
||||
auto out = std::make_unique<CompressedBIQU>();
|
||||
|
||||
// get the output size of the data
|
||||
// add 4 bytes to the row_size to account for end of line (\r\n)
|
||||
// add 1 byte for the 0 of the c_str
|
||||
out->size = data.height * (row_size + 4) + 1;
|
||||
out->data = malloc(out->size);
|
||||
|
||||
std::stringstream out_data;
|
||||
typedef struct {unsigned char r, g, b, a;} pixel;
|
||||
pixel px;
|
||||
for (int ypos = 0; ypos < data.height; ypos++) {
|
||||
std::stringstream line;
|
||||
line << ";";
|
||||
for (int xpos = 0; xpos < row_size; xpos+=4) {
|
||||
px.r = rgba_pixels[ypos * row_size + xpos];
|
||||
px.g = rgba_pixels[ypos * row_size + xpos + 1];
|
||||
px.b = rgba_pixels[ypos * row_size + xpos + 2];
|
||||
px.a = rgba_pixels[ypos * row_size + xpos + 3];
|
||||
|
||||
// calculate values for RGB with alpha
|
||||
const uint8_t rv = ((px.a * px.r) / 255);
|
||||
const uint8_t gv = ((px.a * px.g) / 255);
|
||||
const uint8_t bv = ((px.a * px.b) / 255);
|
||||
|
||||
// convert the RGB values to RGB565 hex that is right justified (same algorithm BTT firmware uses)
|
||||
auto color_565 = rjust(get_hex(((rv >> 3) << 11) | ((gv >> 2) << 5) | (bv >> 3)), 4, '0');
|
||||
|
||||
//BTT original converter specifies these values should be '0000'
|
||||
if (color_565 == "0020" || color_565 == "0841" || color_565 == "0861")
|
||||
color_565 = "0000";
|
||||
//add the color to the line
|
||||
line << color_565;
|
||||
}
|
||||
// output line and end line (\r\n is important. BTT firmware requires it)
|
||||
out_data << line.str() << "\r\n";
|
||||
line.clear();
|
||||
}
|
||||
::memcpy(out->data, (const void*) out_data.str().c_str(), out->size);
|
||||
return out;
|
||||
}
|
||||
|
||||
std::string get_hex(const unsigned int input) {
|
||||
std::stringstream stream;
|
||||
stream << std::hex << input;
|
||||
return stream.str();
|
||||
}
|
||||
|
||||
std::string rjust(std::string input, unsigned int width, char fill_char) {
|
||||
std::stringstream stream;
|
||||
stream.fill(fill_char);
|
||||
stream.width(width);
|
||||
stream << input;
|
||||
return stream.str();
|
||||
}
|
||||
|
||||
std::unique_ptr<CompressedImageBuffer> compress_thumbnail(const ThumbnailData &data, GCodeThumbnailsFormat format)
|
||||
{
|
||||
switch (format) {
|
||||
case GCodeThumbnailsFormat::PNG:
|
||||
default:
|
||||
return compress_thumbnail_png(data);
|
||||
case GCodeThumbnailsFormat::JPG:
|
||||
return compress_thumbnail_jpg(data);
|
||||
case GCodeThumbnailsFormat::QOI:
|
||||
return compress_thumbnail_qoi(data);
|
||||
case GCodeThumbnailsFormat::BTT_TFT:
|
||||
return compress_thumbnail_btt_tft(data);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Slic3r::GCodeThumbnails
|
80
src/libslic3r/GCode/Thumbnails.hpp
Normal file
80
src/libslic3r/GCode/Thumbnails.hpp
Normal file
|
@ -0,0 +1,80 @@
|
|||
///|/ Copyright (c) Prusa Research 2022 Lukáš Hejl @hejllukas, Vojtěch Bubník @bubnikv
|
||||
///|/
|
||||
///|/ PrusaSlicer is released under the terms of the AGPLv3 or higher
|
||||
///|/
|
||||
#ifndef slic3r_GCodeThumbnails_hpp_
|
||||
#define slic3r_GCodeThumbnails_hpp_
|
||||
|
||||
#include "../Point.hpp"
|
||||
#include "../PrintConfig.hpp"
|
||||
#include "ThumbnailData.hpp"
|
||||
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
#include <string_view>
|
||||
|
||||
#include <boost/beast/core/detail/base64.hpp>
|
||||
|
||||
namespace Slic3r::GCodeThumbnails {
|
||||
|
||||
struct CompressedImageBuffer
|
||||
{
|
||||
void *data { nullptr };
|
||||
size_t size { 0 };
|
||||
virtual ~CompressedImageBuffer() {}
|
||||
virtual std::string_view tag() const = 0;
|
||||
};
|
||||
|
||||
std::string get_hex(const unsigned int input);
|
||||
std::string rjust(std::string input, unsigned int width, char fill_char);
|
||||
std::unique_ptr<CompressedImageBuffer> compress_thumbnail(const ThumbnailData &data, GCodeThumbnailsFormat format);
|
||||
|
||||
template<typename WriteToOutput, typename ThrowIfCanceledCallback>
|
||||
inline void export_thumbnails_to_file(ThumbnailsGeneratorCallback &thumbnail_cb, int plate_id, const std::vector<Vec2d> &sizes, GCodeThumbnailsFormat format, WriteToOutput output, ThrowIfCanceledCallback throw_if_canceled)
|
||||
{
|
||||
// Write thumbnails using base64 encoding
|
||||
if (thumbnail_cb != nullptr) {
|
||||
static constexpr const size_t max_row_length = 78;
|
||||
ThumbnailsList thumbnails = thumbnail_cb(ThumbnailsParams{ sizes, true, true, true, true, plate_id });
|
||||
short i = 0;
|
||||
for (const ThumbnailData& data : thumbnails) {
|
||||
if (data.is_valid()) {
|
||||
auto compressed = compress_thumbnail(data, format);
|
||||
if (compressed->data && compressed->size) {
|
||||
if (format == GCodeThumbnailsFormat::BTT_TFT) {
|
||||
// write BTT_TFT header
|
||||
output((";" + rjust(get_hex(data.width), 4, '0') + rjust(get_hex(data.height), 4, '0') + "\r\n").c_str());
|
||||
output((char *) compressed->data);
|
||||
if (i == (thumbnails.size() - 1))
|
||||
output("; bigtree thumbnail end\r\n\r\n");
|
||||
} else {
|
||||
std::string encoded;
|
||||
encoded.resize(boost::beast::detail::base64::encoded_size(compressed->size));
|
||||
encoded.resize(boost::beast::detail::base64::encode((void *) encoded.data(), (const void *) compressed->data,
|
||||
compressed->size));
|
||||
|
||||
output((boost::format("\n;\n; %s begin %dx%d %d\n") % compressed->tag() % data.width % data.height % encoded.size())
|
||||
.str()
|
||||
.c_str());
|
||||
|
||||
while (encoded.size() > max_row_length) {
|
||||
output((boost::format("; %s\n") % encoded.substr(0, max_row_length)).str().c_str());
|
||||
encoded = encoded.substr(max_row_length);
|
||||
}
|
||||
|
||||
if (encoded.size() > 0)
|
||||
output((boost::format("; %s\n") % encoded).str().c_str());
|
||||
|
||||
output((boost::format("; %s end\n;\n") % compressed->tag()).str().c_str());
|
||||
}
|
||||
throw_if_canceled();
|
||||
}
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Slic3r::GCodeThumbnails
|
||||
|
||||
#endif // slic3r_GCodeThumbnails_hpp_
|
|
@ -823,7 +823,7 @@ static std::vector<std::string> s_Preset_printer_options {
|
|||
"host_type", "print_host", "printhost_apikey",
|
||||
"print_host_webui",
|
||||
"printhost_cafile","printhost_port","printhost_authorization_type",
|
||||
"printhost_user", "printhost_password", "printhost_ssl_ignore_revoke", "thumbnails",
|
||||
"printhost_user", "printhost_password", "printhost_ssl_ignore_revoke", "thumbnails", "thumbnails_format",
|
||||
"use_firmware_retraction", "use_relative_e_distances", "printer_notes",
|
||||
"cooling_tube_retraction",
|
||||
"cooling_tube_length", "high_current_on_filament_swap", "parking_pos_retraction", "extra_loading_move", "purge_in_prime_tower", "enable_filament_ramming"};
|
||||
|
|
|
@ -184,6 +184,7 @@ bool Print::invalidate_state_by_config_options(const ConfigOptionResolver & /* n
|
|||
// SoftFever
|
||||
"chamber_temperature",
|
||||
"thumbnails",
|
||||
"thumbnails_format",
|
||||
"seam_gap",
|
||||
"role_based_wipe_speed",
|
||||
"wipe_speed",
|
||||
|
|
|
@ -327,6 +327,14 @@ static const t_config_enum_values s_keys_map_RetractLiftEnforceType = {
|
|||
};
|
||||
CONFIG_OPTION_ENUM_DEFINE_STATIC_MAPS(RetractLiftEnforceType)
|
||||
|
||||
static const t_config_enum_values s_keys_map_GCodeThumbnailsFormat = {
|
||||
{ "PNG", int(GCodeThumbnailsFormat::PNG) },
|
||||
{ "JPG", int(GCodeThumbnailsFormat::JPG) },
|
||||
{ "QOI", int(GCodeThumbnailsFormat::QOI) },
|
||||
{ "BTT_TFT", int(GCodeThumbnailsFormat::BTT_TFT) }
|
||||
};
|
||||
CONFIG_OPTION_ENUM_DEFINE_STATIC_MAPS(GCodeThumbnailsFormat)
|
||||
|
||||
static void assign_printer_technology_to_unknown(t_optiondef_map &options, PrinterTechnology printer_technology)
|
||||
{
|
||||
for (std::pair<const t_config_option_key, ConfigOptionDef> &kvp : options)
|
||||
|
@ -4188,6 +4196,17 @@ def = this->add("filament_loading_speed", coFloats);
|
|||
def->gui_type = ConfigOptionDef::GUIType::one_string;
|
||||
def->set_default_value(new ConfigOptionPoints{Vec2d(300, 300)});
|
||||
|
||||
def = this->add("thumbnails_format", coEnum);
|
||||
def->label = L("Format of G-code thumbnails");
|
||||
def->tooltip = L("Format of G-code thumbnails: PNG for best quality, JPG for smallest size, QOI for low memory firmware");
|
||||
def->mode = comAdvanced;
|
||||
def->enum_keys_map = &ConfigOptionEnum<GCodeThumbnailsFormat>::get_enum_values();
|
||||
def->enum_values.push_back("PNG");
|
||||
def->enum_values.push_back("JPG");
|
||||
def->enum_values.push_back("QOI");
|
||||
def->enum_values.push_back("BTT TFT");
|
||||
def->set_default_value(new ConfigOptionEnum<GCodeThumbnailsFormat>(GCodeThumbnailsFormat::PNG));
|
||||
|
||||
def = this->add("use_relative_e_distances", coBool);
|
||||
def->label = L("Use relative E distances");
|
||||
def->tooltip = L("Relative extrusion is recommended when using \"label_objects\" option."
|
||||
|
|
|
@ -233,6 +233,10 @@ enum RetractLiftEnforceType {
|
|||
rletTopAndBottom
|
||||
};
|
||||
|
||||
enum class GCodeThumbnailsFormat {
|
||||
PNG, JPG, QOI, BTT_TFT
|
||||
};
|
||||
|
||||
static std::string bed_type_to_gcode_string(const BedType type)
|
||||
{
|
||||
std::string type_str;
|
||||
|
@ -315,6 +319,7 @@ CONFIG_OPTION_ENUM_DECLARE_STATIC_MAPS(TimelapseType)
|
|||
CONFIG_OPTION_ENUM_DECLARE_STATIC_MAPS(BedType)
|
||||
CONFIG_OPTION_ENUM_DECLARE_STATIC_MAPS(DraftShield)
|
||||
CONFIG_OPTION_ENUM_DECLARE_STATIC_MAPS(ForwardCompatibilitySubstitutionRule)
|
||||
CONFIG_OPTION_ENUM_DECLARE_STATIC_MAPS(GCodeThumbnailsFormat)
|
||||
|
||||
CONFIG_OPTION_ENUM_DECLARE_STATIC_MAPS(PrintHostType)
|
||||
CONFIG_OPTION_ENUM_DECLARE_STATIC_MAPS(AuthorizationType)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue