Skip to content

Commit

Permalink
Merge branch 'main' into fix-wipe-tower-moves
Browse files Browse the repository at this point in the history
  • Loading branch information
SoftFever authored Oct 17, 2023
2 parents 4e29aea + d0ccc5e commit 4a13eb0
Show file tree
Hide file tree
Showing 16 changed files with 1,630 additions and 549 deletions.
1,005 changes: 506 additions & 499 deletions localization/i18n/zh_TW/OrcaSlicer_zh_TW.po

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ add_subdirectory(semver)
add_subdirectory(libigl)
add_subdirectory(hints)
add_subdirectory(mcut)
add_subdirectory(qoi)

# Adding libnest2d project for bin packing...
add_subdirectory(libnest2d)
Expand Down
6 changes: 6 additions & 0 deletions src/libslic3r/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -411,6 +411,8 @@ set(lisbslic3r_sources
Shape/TextShape.cpp
calib.hpp
calib.cpp
GCode/Thumbnails.cpp
GCode/Thumbnails.hpp
)

if (APPLE)
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -525,6 +529,8 @@ target_link_libraries(libslic3r
${OCCT_LIBS}
Clipper2
mcut
JPEG::JPEG
qoi
)

if(NOT WIN32)
Expand Down
64 changes: 16 additions & 48 deletions src/libslic3r/GCode.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -1665,50 +1666,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,
Expand Down Expand Up @@ -1920,6 +1877,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.
Expand Down Expand Up @@ -1979,10 +1945,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(); });
}
}

Expand Down
5 changes: 4 additions & 1 deletion src/libslic3r/GCode/GCodeProcessor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
196 changes: 196 additions & 0 deletions src/libslic3r/GCode/Thumbnails.cpp
Original file line number Diff line number Diff line change
@@ -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
Loading

0 comments on commit 4a13eb0

Please sign in to comment.