CLI thumbnails - use thumbnail from 3MF

This commit is contained in:
Lukas Matena 2024-11-13 12:21:17 +01:00
parent 4dabb5ade5
commit cd81c686d1
3 changed files with 91 additions and 2 deletions

View File

@ -58,6 +58,8 @@
#include "libslic3r/Format/STL.hpp"
#include "libslic3r/Format/OBJ.hpp"
#include "libslic3r/Format/SL1.hpp"
#include "libslic3r/miniz_extension.hpp"
#include "libslic3r/PNGReadWrite.hpp"
#include "libslic3r/Utils.hpp"
#include "libslic3r/Thread.hpp"
#include "libslic3r/BlacklistedLibraryCheck.hpp"
@ -671,8 +673,67 @@ int CLI::run(int argc, char **argv)
std::string outfile_final;
print->process();
if (printer_technology == ptFFF) {
std::function<ThumbnailsList(const ThumbnailsParams&)> thumbnail_generator_cli;
if (!fff_print.model().objects.empty() && boost::iends_with(fff_print.model().objects.front()->input_file, ".3mf")) {
std::string filename = fff_print.model().objects.front()->input_file;
thumbnail_generator_cli = [filename](const ThumbnailsParams&) {
ThumbnailsList list_out;
mz_zip_archive archive;
mz_zip_zero_struct(&archive);
if (!open_zip_reader(&archive, filename))
return list_out;
mz_uint num_entries = mz_zip_reader_get_num_files(&archive);
mz_zip_archive_file_stat stat;
int index = mz_zip_reader_locate_file(&archive, "Metadata/thumbnail.png", nullptr, 0);
if (index < 0 || !mz_zip_reader_file_stat(&archive, index, &stat))
return list_out;
std::string buffer;
buffer.resize(int(stat.m_uncomp_size));
mz_bool res = mz_zip_reader_extract_file_to_mem(&archive, stat.m_filename, buffer.data(), (size_t)stat.m_uncomp_size, 0);
if (res == 0)
return list_out;
close_zip_reader(&archive);
std::vector<unsigned char> data;
unsigned width = 0;
unsigned height = 0;
png::decode_png(buffer, data, width, height);
{
// Flip the image vertically so it matches the convention in Thumbnails generator.
const int row_size = width * 4; // Each pixel is 4 bytes (RGBA)
std::vector<unsigned char> temp_row(row_size);
for (int i = 0; i < height / 2; ++i) {
unsigned char* top_row = &data[i * row_size];
unsigned char* bottom_row = &data[(height - i - 1) * row_size];
std::copy(bottom_row, bottom_row + row_size, temp_row.begin());
std::copy(top_row, top_row + row_size, bottom_row);
std::copy(temp_row.begin(), temp_row.end(), top_row);
}
}
ThumbnailData th;
th.set(width, height);
th.pixels = data;
list_out.push_back(th);
return list_out;
};
}
// The outfile is processed by a PlaceholderParser.
outfile = fff_print.export_gcode(outfile, nullptr, nullptr);
outfile = fff_print.export_gcode(outfile, nullptr, thumbnail_generator_cli);
outfile_final = fff_print.print_statistics().finalize_output_path(outfile);
} else {
outfile = sla_print.output_filepath(outfile);

View File

@ -190,6 +190,34 @@ fopen_failed:
return result;
}
bool decode_png(const std::string& png_data, std::vector<unsigned char>& image_data, unsigned& width, unsigned& height)
{
png_image image;
memset(&image, 0, sizeof(image));
image.version = PNG_IMAGE_VERSION;
if (!png_image_begin_read_from_memory(&image, png_data.data(), png_data.size()))
return false;
image.format = PNG_FORMAT_RGBA;
// Allocate memory for the image data
image_data.resize(PNG_IMAGE_SIZE(image));
if (!png_image_finish_read(&image, nullptr, image_data.data(), 0, nullptr)) {
png_image_free(&image);
return false;
}
width = image.width;
height = image.height;
png_image_free(&image);
return true;
}
bool write_rgb_to_file(const char *file_name_utf8, size_t width, size_t height, const uint8_t *data_rgb)
{
return write_rgb_or_gray_to_file(file_name_utf8, width, height, PNG_COLOR_TYPE_RGB, data_rgb);

View File

@ -74,7 +74,7 @@ template<class Img> bool decode_png(const ReadBuf &in_buf, Img &out_img)
// TODO: std::istream of FILE* could be similarly adapted in case its needed...
bool decode_png(const std::string& png_data, std::vector<unsigned char>& image_data, unsigned& width, unsigned& height);
// Down to earth function to store a packed RGB image to file. Mostly useful for debugging purposes.
bool write_rgb_to_file(const char *file_name_utf8, size_t width, size_t height, const uint8_t *data_rgb);