diff --git a/src/libslic3r/GCode/Thumbnails.cpp b/src/libslic3r/GCode/Thumbnails.cpp index 02b5e4f02d4..78a032acf33 100644 --- a/src/libslic3r/GCode/Thumbnails.cpp +++ b/src/libslic3r/GCode/Thumbnails.cpp @@ -33,6 +33,12 @@ struct CompressedBIQU : CompressedImageBuffer std::string_view tag() const override { return "thumbnail_BIQU"sv; } }; +struct CompressedTFT : CompressedImageBuffer +{ + ~CompressedTFT() override { free(data); } + std::string_view tag() const override { return "thumbnail_TFT"sv; } +}; + std::unique_ptr compress_thumbnail_png(const ThumbnailData& data) { auto out = std::make_unique(); @@ -76,6 +82,43 @@ std::unique_ptr compress_thumbnail_biqu(const ThumbnailDa return out; } +std::unique_ptr compress_thumbnail_tft(const ThumbnailData& data) +{ + auto out = std::make_unique(); + //size: height is number of lines. Add 9 byte to each line for the 'M10086 ;' and '\n'. Each pixel is 4 byte, +1 for the 0 of the c_str + out->size = data.height * (9 + data.width * 4) + 1; + out->data = malloc(out->size); + + // Take vector of RGBA pixels and flip the image vertically + std::vector rgba_pixels(data.pixels.size()); + const 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); + + int idx = 0; + std::stringstream tohex; + tohex << std::setfill('0') << std::hex; + for (size_t y = 0; y < data.height; ++y) { + tohex << "M10086 ;"; + for (size_t x = 0; x < data.width; ++x) { + uint16_t pixel = 0; + //r + pixel |= uint16_t(((rgba_pixels[y * row_size + x * 4 + 0 ] & 0x000000FF) >> 3) << 11); + //g + pixel |= uint16_t(((rgba_pixels[y * row_size + x * 4 + 1 ] & 0x000000FF) >> 2) <<5); + //b + pixel |= uint16_t((rgba_pixels[y * row_size + x * 4 + 2 ] & 0x000000FF) >> 3); + tohex << std::setw(4) << pixel; + } + tohex << "\n"; + } + std::string str = tohex.str(); + + assert(str.size() + 1 == out->size); + ::memcpy(out->data, (const void*)str.c_str(), out->size); + return out; +} + std::unique_ptr compress_thumbnail_jpg(const ThumbnailData& data) { // Take vector of RGBA pixels and flip the image vertically @@ -157,6 +200,8 @@ std::unique_ptr compress_thumbnail(const ThumbnailData &d return compress_thumbnail_qoi(data); case GCodeThumbnailsFormat::BIQU: return compress_thumbnail_biqu(data); + case GCodeThumbnailsFormat::TFT: + return compress_thumbnail_tft(data); } } diff --git a/src/libslic3r/GCode/Thumbnails.hpp b/src/libslic3r/GCode/Thumbnails.hpp index 45565d0647c..a05fa2ffeb9 100644 --- a/src/libslic3r/GCode/Thumbnails.hpp +++ b/src/libslic3r/GCode/Thumbnails.hpp @@ -38,6 +38,7 @@ inline void export_thumbnails_to_file(ThumbnailsGeneratorCallback &thumbnail_cb, //Create the thumbnails static constexpr const size_t max_row_length = 78; ThumbnailsList thumbnails = thumbnail_cb(ThumbnailsParams{ good_sizes, true, true, with_bed, true }); + image_count = 0 for (const ThumbnailData& data : thumbnails) if (data.is_valid()) { auto compressed = compress_thumbnail(data, format); @@ -55,6 +56,27 @@ inline void export_thumbnails_to_file(ThumbnailsGeneratorCallback &thumbnail_cb, else assert(false); output("; bigtree thumbnail end\n"); + } + else if (format == GCodeThumbnailsFormat::TFT) { + // for TFT, small and big thumbnails are necessary + + image_tag = ";simage:" + + // if second image (big) + if (image_count == 1){ + image_tag = ";;gimage:" + } + + output((boost::format("\n;\n; %s begin %dx%d\n") % compressed->tag() % data.width % data.height); + + if (((char*)compressed->data)[compressed->size -1] == '\0') + output((char*)(compressed->data)); + else + assert(false); + + output("M10086 ;\n"); + + image_count++; } else { std::string encoded; encoded.resize(boost::beast::detail::base64::encoded_size(compressed->size)); diff --git a/src/libslic3r/PrintConfig.cpp b/src/libslic3r/PrintConfig.cpp index 865fd12e5ee..7fe3e6ffc1d 100644 --- a/src/libslic3r/PrintConfig.cpp +++ b/src/libslic3r/PrintConfig.cpp @@ -293,7 +293,8 @@ static const t_config_enum_values s_keys_map_GCodeThumbnailsFormat = { { "PNG", int(GCodeThumbnailsFormat::PNG) }, { "JPG", int(GCodeThumbnailsFormat::JPG) }, { "QOI", int(GCodeThumbnailsFormat::QOI) }, - { "BIQU", int(GCodeThumbnailsFormat::BIQU) } + { "BIQU", int(GCodeThumbnailsFormat::BIQU) }, + { "TFT", int(GCodeThumbnailsFormat::TFT) } }; CONFIG_OPTION_ENUM_DEFINE_STATIC_MAPS(GCodeThumbnailsFormat) @@ -417,10 +418,12 @@ void PrintConfigDef::init_common_params() def->enum_values.push_back("JPG"); def->enum_values.push_back("QOI"); def->enum_values.push_back("BIQU"); + def->enum_values.push_back("TFT"); def->enum_labels.push_back("PNG"); def->enum_labels.push_back("JPG"); def->enum_labels.push_back("QOI"); def->enum_labels.push_back("Biqu"); + def->enum_labels.push_back("TFT"); def->set_default_value(new ConfigOptionEnum(GCodeThumbnailsFormat::PNG)); def = this->add("thumbnails_with_support", coBool); diff --git a/src/libslic3r/PrintConfig.hpp b/src/libslic3r/PrintConfig.hpp index f2428957a00..7fabbd740ca 100644 --- a/src/libslic3r/PrintConfig.hpp +++ b/src/libslic3r/PrintConfig.hpp @@ -256,7 +256,7 @@ enum class PerimeterGeneratorType }; enum class GCodeThumbnailsFormat { - PNG, JPG, QOI, BIQU + PNG, JPG, QOI, BIQU, TFT }; enum ZLiftTop {