mirror of
https://github.com/SoftFever/OrcaSlicer.git
synced 2025-07-19 12:47:50 -06:00
Thumbnails feature revamp. (#5555)
* Thumbnails feature revamp. Support generating different size/format combinations * misc fix Co-authored-by: Lukas Matena <lukasmatena@seznam.cz>
This commit is contained in:
parent
50d00a1d54
commit
c083541e0a
26 changed files with 1145 additions and 854 deletions
|
@ -528,5 +528,81 @@ int ColPic_EncodeStr(unsigned short* fromcolor16, int picw, int pich, unsigned c
|
|||
outputdata[qty] = 0;
|
||||
return qty;
|
||||
}
|
||||
std::pair<GCodeThumbnailDefinitionsList, ThumbnailErrors> make_and_check_thumbnail_list(const std::string& thumbnails_string, const std::string_view def_ext /*= "PNG"sv*/)
|
||||
{
|
||||
if (thumbnails_string.empty())
|
||||
return {};
|
||||
|
||||
std::istringstream is(thumbnails_string);
|
||||
std::string point_str;
|
||||
|
||||
ThumbnailErrors errors;
|
||||
|
||||
// generate thumbnails data to process it
|
||||
|
||||
GCodeThumbnailDefinitionsList thumbnails_list;
|
||||
while (std::getline(is, point_str, ',')) {
|
||||
Vec2d point(Vec2d::Zero());
|
||||
GCodeThumbnailsFormat format;
|
||||
std::istringstream iss(point_str);
|
||||
std::string coord_str;
|
||||
if (std::getline(iss, coord_str, 'x') && !coord_str.empty()) {
|
||||
std::istringstream(coord_str) >> point(0);
|
||||
if (std::getline(iss, coord_str, '/') && !coord_str.empty()) {
|
||||
std::istringstream(coord_str) >> point(1);
|
||||
|
||||
if (0 < point(0) && point(0) < 1000 && 0 < point(1) && point(1) < 1000) {
|
||||
std::string ext_str;
|
||||
std::getline(iss, ext_str, '/');
|
||||
|
||||
if (ext_str.empty())
|
||||
ext_str = def_ext.empty() ? "PNG"sv : def_ext;
|
||||
|
||||
// check validity of extention
|
||||
boost::to_upper(ext_str);
|
||||
if (!ConfigOptionEnum<GCodeThumbnailsFormat>::from_string(ext_str, format)) {
|
||||
format = GCodeThumbnailsFormat::PNG;
|
||||
errors = enum_bitmask(errors | ThumbnailError::InvalidExt);
|
||||
}
|
||||
|
||||
thumbnails_list.emplace_back(std::make_pair(format, point));
|
||||
}
|
||||
else
|
||||
errors = enum_bitmask(errors | ThumbnailError::OutOfRange);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
errors = enum_bitmask(errors | ThumbnailError::InvalidVal);
|
||||
}
|
||||
|
||||
return std::make_pair(std::move(thumbnails_list), errors);
|
||||
}
|
||||
|
||||
std::pair<GCodeThumbnailDefinitionsList, ThumbnailErrors> make_and_check_thumbnail_list(const ConfigBase& config)
|
||||
{
|
||||
// ??? Unit tests or command line slicing may not define "thumbnails" or "thumbnails_format".
|
||||
// ??? If "thumbnails_format" is not defined, export to PNG.
|
||||
|
||||
// generate thumbnails data to process it
|
||||
|
||||
if (const auto thumbnails_value = config.option<ConfigOptionString>("thumbnails"))
|
||||
return make_and_check_thumbnail_list(thumbnails_value->value);
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
std::string get_error_string(const ThumbnailErrors& errors)
|
||||
{
|
||||
std::string error_str;
|
||||
|
||||
if (errors.has(ThumbnailError::InvalidVal))
|
||||
error_str += "\n - " + format("Invalid input format. Expected vector of dimensions in the following format: \"%1%\"", "XxY/EXT, XxY/EXT, ...");
|
||||
if (errors.has(ThumbnailError::OutOfRange))
|
||||
error_str += "\n - Input value is out of range";
|
||||
if (errors.has(ThumbnailError::InvalidExt))
|
||||
error_str += "\n - Some extension in the input is invalid";
|
||||
|
||||
return error_str;
|
||||
}
|
||||
|
||||
} // namespace Slic3r::GCodeThumbnails
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
|
||||
#include "../Point.hpp"
|
||||
#include "../PrintConfig.hpp"
|
||||
#include "PrintConfig.hpp"
|
||||
#include "ThumbnailData.hpp"
|
||||
|
||||
#include <vector>
|
||||
|
@ -16,6 +15,12 @@
|
|||
|
||||
#include <boost/beast/core/detail/base64.hpp>
|
||||
|
||||
namespace Slic3r {
|
||||
enum class ThumbnailError : int { InvalidVal, OutOfRange, InvalidExt };
|
||||
using ThumbnailErrors = enum_bitmask<ThumbnailError>;
|
||||
ENABLE_ENUM_BITMASK_OPERATORS(ThumbnailError);
|
||||
}
|
||||
|
||||
namespace Slic3r::GCodeThumbnails {
|
||||
|
||||
struct CompressedImageBuffer
|
||||
|
@ -29,20 +34,30 @@ struct CompressedImageBuffer
|
|||
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);
|
||||
std::string get_error_string(const ThumbnailErrors& errors);
|
||||
|
||||
|
||||
typedef std::vector<std::pair<GCodeThumbnailsFormat, Vec2d>> GCodeThumbnailDefinitionsList;
|
||||
using namespace std::literals;
|
||||
std::pair<GCodeThumbnailDefinitionsList, ThumbnailErrors> make_and_check_thumbnail_list(const std::string& thumbnails_string, const std::string_view def_ext = "PNG"sv);
|
||||
std::pair<GCodeThumbnailDefinitionsList, ThumbnailErrors> make_and_check_thumbnail_list(const ConfigBase &config);
|
||||
|
||||
|
||||
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)
|
||||
inline void export_thumbnails_to_file(ThumbnailsGeneratorCallback& thumbnail_cb,
|
||||
int plate_id,
|
||||
const std::vector<std::pair<GCodeThumbnailsFormat, Vec2d>>& thumbnails_list,
|
||||
WriteToOutput output,
|
||||
ThrowIfCanceledCallback throw_if_canceled)
|
||||
{
|
||||
// Write thumbnails using base64 encoding
|
||||
if (thumbnail_cb != nullptr) {
|
||||
if (thumbnail_cb == nullptr)
|
||||
return;
|
||||
short i = 0;
|
||||
bool first_ColPic = true;
|
||||
for (const auto& [format, size] : thumbnails_list) {
|
||||
static constexpr const size_t max_row_length = 78;
|
||||
ThumbnailsList thumbnails = thumbnail_cb(ThumbnailsParams{sizes, true, true, true, true, plate_id});
|
||||
short i = 0;
|
||||
ThumbnailsList thumbnails = thumbnail_cb(ThumbnailsParams{{size}, true, true, true, true, plate_id});
|
||||
for (const ThumbnailData &data : thumbnails) {
|
||||
if (data.is_valid()) {
|
||||
auto compressed = compress_thumbnail(data, format);
|
||||
|
@ -51,15 +66,16 @@ inline void export_thumbnails_to_file(ThumbnailsGeneratorCallback &thumbnail_cb,
|
|||
// 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))
|
||||
if (i == (thumbnails_list.size() - 1))
|
||||
output("; bigtree thumbnail end\r\n\r\n");
|
||||
}
|
||||
else if (format == GCodeThumbnailsFormat::ColPic) {
|
||||
if (i == 0) {
|
||||
if (first_ColPic) {
|
||||
output((boost::format("\n\n;gimage:%s\n\n") % reinterpret_cast<char*>(compressed->data)).str().c_str());
|
||||
} else {
|
||||
output((boost::format("\n\n;simage:%s\n\n") % reinterpret_cast<char*>(compressed->data)).str().c_str());
|
||||
}
|
||||
first_ColPic = false;
|
||||
}
|
||||
else {
|
||||
output("; THUMBNAIL_BLOCK_START\n");
|
||||
|
@ -84,10 +100,9 @@ inline void export_thumbnails_to_file(ThumbnailsGeneratorCallback &thumbnail_cb,
|
|||
}
|
||||
throw_if_canceled();
|
||||
}
|
||||
|
||||
i++;
|
||||
}
|
||||
}
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue