Skip to content

Commit

Permalink
Experimental code which replaces the tags (comments), used by GCodeVi…
Browse files Browse the repository at this point in the history
…ewer to decorate the toolpaths, with MeatPack commands to try to reduce the size of the generated binary gcode file.
  • Loading branch information
enricoturri1966 committed Aug 22, 2023
1 parent ea4d743 commit 5cc26f4
Show file tree
Hide file tree
Showing 7 changed files with 176 additions and 11 deletions.
10 changes: 10 additions & 0 deletions src/LibBGCode/binarize/binarize.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,11 @@ static std::vector<uint8_t> encode(const void* data, size_t data_size)

static uint16_t metadata_encoding_types_count() { return 1 + (uint16_t)EMetadataEncodingType::INI; }
static uint16_t thumbnail_formats_count() { return 1 + (uint16_t)EThumbnailFormat::QOI; }
#if ENABLE_MEATPACK_COMMENTS_EXTENDED
static uint16_t gcode_encoding_types_count() { return 1 + (uint16_t)EGCodeEncodingType::MeatPackCommentsExtended; }
#else
static uint16_t gcode_encoding_types_count() { return 1 + (uint16_t)EGCodeEncodingType::MeatPackComments; }
#endif // ENABLE_MEATPACK_COMMENTS_EXTENDED

static bool encode_metadata(const std::vector<std::pair<std::string, std::string>>& src, std::vector<uint8_t>& dst,
EMetadataEncodingType encoding_type)
Expand Down Expand Up @@ -94,6 +98,9 @@ static bool encode_gcode(const std::string& src, std::vector<uint8_t>& dst, EGCo
}
case EGCodeEncodingType::MeatPack:
case EGCodeEncodingType::MeatPackComments:
#if ENABLE_MEATPACK_COMMENTS_EXTENDED
case EGCodeEncodingType::MeatPackCommentsExtended:
#endif // ENABLE_MEATPACK_COMMENTS_EXTENDED
{
uint8_t binarizer_flags = (encoding_type == EGCodeEncodingType::MeatPack) ? MeatPack::Flag_RemoveComments : 0;
binarizer_flags |= MeatPack::Flag_OmitWhitespaces;
Expand Down Expand Up @@ -127,6 +134,9 @@ static bool decode_gcode(const std::vector<uint8_t>& src, std::string& dst, EGCo
}
case EGCodeEncodingType::MeatPack:
case EGCodeEncodingType::MeatPackComments:
#if ENABLE_MEATPACK_COMMENTS_EXTENDED
case EGCodeEncodingType::MeatPackCommentsExtended:
#endif // ENABLE_MEATPACK_COMMENTS_EXTENDED
{
MeatPack::unbinarize(src, dst);
break;
Expand Down
137 changes: 136 additions & 1 deletion src/LibBGCode/binarize/meatpack.cpp
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
#include "meatpack.hpp"
#include "../core/core.hpp"

#include <unordered_map>
#include <algorithm>
#include <cassert>
#if ENABLE_MEATPACK_COMMENTS_EXTENDED
#include <optional>
#include <cstdio>
#endif // ENABLE_MEATPACK_COMMENTS_EXTENDED

namespace MeatPack {

Expand All @@ -14,6 +19,10 @@ static constexpr const uint8_t Command_ResetAll{ 249 };
static constexpr const uint8_t Command_QueryConfig{ 248 };
static constexpr const uint8_t Command_EnableNoSpaces{ 247 };
static constexpr const uint8_t Command_DisableNoSpaces{ 246 };
#if ENABLE_MEATPACK_COMMENTS_EXTENDED
static constexpr const uint8_t Command_Width{ 239 };
static constexpr const uint8_t Command_Height{ 238 };
#endif // ENABLE_MEATPACK_COMMENTS_EXTENDED
static constexpr const uint8_t Command_SignalByte{ 0xFF };

static constexpr const uint8_t BothUnpackable{ 0b11111111 };
Expand Down Expand Up @@ -43,6 +52,33 @@ static const std::unordered_map<char, uint8_t> ReverseLookupTbl = {
{ '\0', 0b00001111 } // never used, 0b1111 is used to indicate the next 8-bits is a full character
};

#if ENABLE_MEATPACK_COMMENTS_EXTENDED
static std::string_view trim(const std::string_view& str)
{
if (str.empty())
return std::string_view();
size_t start = 0;
while (start < str.size() - 1 && (str[start] == ' ' || str[start] == '\t')) { ++start; }
size_t end = str.size() - 1;
while (end > 0 && (str[end] == ' ' || str[end] == '\t')) { --end; }
if ((start == end && (str[end] == ' ' || str[end] == '\t')) || (start > end))
return std::string_view();
else
return std::string_view(&str[start], end - start + 1);
}

std::string_view trim_right(const std::string_view& str)
{
if (str.back() != ' ')
return str;
auto bit = str.rbegin();
while (bit != str.rend() && *bit == ' ') {
++bit;
}
return str.substr(0, std::distance(str.begin(), bit.base()));
}
#endif // ENABLE_MEATPACK_COMMENTS_EXTENDED

MPBinarizer::LookupTables MPBinarizer::s_lookup_tables = { { 0 }, { 0 }, false, 0 };

MPBinarizer::MPBinarizer(uint8_t flags) : m_flags(flags) {}
Expand Down Expand Up @@ -116,9 +152,49 @@ void MPBinarizer::binarize_line(const std::string& line, std::vector<uint8_t>& d
(s_lookup_tables.value[static_cast<uint8_t>(low)] & 0xF));
};

#if ENABLE_MEATPACK_COMMENTS_EXTENDED
auto extract_value = [](const std::string& line, const std::string& key) {
std::optional<float> ret;
size_t pos = line.find(key);
if (pos != std::string::npos) {
pos = line.find(":", pos);
if (pos != std::string::npos) {
try
{
ret = std::stof(std::string(trim(line.substr(pos + 1, line.length() - pos - 2))));
}
catch(...)
{
// do nothing
}
}
}
return ret;
};

auto append_float = [](float src, std::vector<uint8_t>& dst) {
std::array<uint8_t, sizeof(float)> buf;
*(float*)buf.data() = src;
dst.insert(dst.end(), buf.begin(), buf.end());
};
#endif // ENABLE_MEATPACK_COMMENTS_EXTENDED

if (!line.empty()) {
if ((m_flags & Flag_RemoveComments) == 0) {
if (line[0] == ';') {
#if ENABLE_MEATPACK_COMMENTS_EXTENDED
if (std::optional<float> value = extract_value(line, "WIDTH"); value.has_value()) {
append_command(Command_Width, dst);
append_float(*value, dst);
return;
}
else if (std::optional<float> value = extract_value(line, "HEIGHT"); value.has_value()) {
append_command(Command_Height, dst);
append_float(*value, dst);
return;
}
#endif // ENABLE_MEATPACK_COMMENTS_EXTENDED

if (m_binarizing) {
append_command(Command_DisablePacking, dst);
m_binarizing = false;
Expand All @@ -138,6 +214,7 @@ void MPBinarizer::binarize_line(const std::string& line, std::vector<uint8_t>& d
std::string modifiedLine = line.substr(0, line.find(';'));
if (modifiedLine.empty())
return;
#if !ENABLE_MEATPACK_COMMENTS_EXTENDED
auto trim_right = [](const std::string& str) {
if (str.back() != ' ')
return str;
Expand All @@ -147,6 +224,7 @@ void MPBinarizer::binarize_line(const std::string& line, std::vector<uint8_t>& d
}
return str.substr(0, std::distance(str.begin(), bit.base()));
};
#endif // !ENABLE_MEATPACK_COMMENTS_EXTENDED
modifiedLine = trim_right(modifiedLine);
modifiedLine = unified_method(modifiedLine);
if (modifiedLine.back() != '\n')
Expand Down Expand Up @@ -234,6 +312,50 @@ void unbinarize(const std::vector<uint8_t>& src, std::string& dst)
std::array<uint8_t, 2> char_out_buf; // Output buffer for caching up to 2 characters
size_t char_out_count = 0; // Stores number of characters to be read out

#if ENABLE_MEATPACK_COMMENTS_EXTENDED
auto handle_command = [&](std::vector<uint8_t>::const_iterator& c, std::vector<uint8_t>::iterator& dst_it) {
switch (*c)
{
case Command_EnablePacking: { unbinarizing = true; break; }
case Command_DisablePacking: { unbinarizing = false; break; }
case Command_EnableNoSpaces: { nospace_enabled = true; break; }
case Command_DisableNoSpaces: { nospace_enabled = false; break; }
case Command_ResetAll: { unbinarizing = false; break; }
case Command_Width: {
std::array<uint8_t, sizeof(float)> inbuf;
for (size_t i = 0; i < inbuf.size(); ++i) {
inbuf[i] = *(++c);
}
const float value = *(float*)inbuf.data();

char outbuf[64];
sprintf(outbuf, ";WIDTH:%.6g\n", value);
for (size_t i = 0; i < strlen(outbuf); ++i) {
*dst_it = outbuf[i];
++dst_it;
}
break;
}
case Command_Height: {
std::array<uint8_t, sizeof(float)> buf;
for (size_t i = 0; i < buf.size(); ++i) {
buf[i] = *(++c);
}
float value = *(float*)buf.data();

char outbuf[64];
sprintf(outbuf, ";HEIGHT:%.6g\n", value);
for (size_t i = 0; i < strlen(outbuf); ++i) {
*dst_it = outbuf[i];
++dst_it;
}
break;
}
default:
case Command_QueryConfig: { break; }
}
};
#else
auto handle_command = [&](uint8_t c) {
switch (c)
{
Expand All @@ -246,6 +368,7 @@ void unbinarize(const std::vector<uint8_t>& src, std::string& dst)
case Command_QueryConfig: { break; }
}
};
#endif // ENABLE_MEATPACK_COMMENTS_EXTENDED

auto handle_output_char = [&](uint8_t c) {
char_out_buf[char_out_count++] = c;
Expand Down Expand Up @@ -349,8 +472,12 @@ void unbinarize(const std::vector<uint8_t>& src, std::string& dst)

auto it_bin = begin;
while (it_bin != end) {
#if ENABLE_MEATPACK_COMMENTS_EXTENDED
if (*it_bin == Command_SignalByte) {
#else
uint8_t c_bin = *it_bin;
if (c_bin == Command_SignalByte) {
#endif // ENABLE_MEATPACK_COMMENTS_EXTENDED
if (cmd_count > 0) {
cmd_active = true;
cmd_count = 0;
Expand All @@ -360,7 +487,11 @@ void unbinarize(const std::vector<uint8_t>& src, std::string& dst)
}
else {
if (cmd_active) {
handle_command(c_bin);
#if ENABLE_MEATPACK_COMMENTS_EXTENDED
handle_command(it_bin, it_unbin_end);
#else
handle_command(c_bin);
#endif // ENABLE_MEATPACK_COMMENTS_EXTENDED
cmd_active = false;
}
else {
Expand All @@ -369,7 +500,11 @@ void unbinarize(const std::vector<uint8_t>& src, std::string& dst)
cmd_count = 0;
}

#if ENABLE_MEATPACK_COMMENTS_EXTENDED
handle_rx_char(*it_bin);
#else
handle_rx_char(c_bin);
#endif // ENABLE_MEATPACK_COMMENTS_EXTENDED
}
}

Expand Down
4 changes: 4 additions & 0 deletions src/LibBGCode/cmd/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,11 @@ static const std::vector<Parameter> parameters = {
{ "printer_metadata_compression"sv, { "None"sv, "Deflate"sv, "Heatshrink_11_4"sv, "Heatshrink_12_4"sv }, (int)BinarizerConfig().compression.printer_metadata },
{ "slicer_metadata_compression"sv, { "None"sv, "Deflate"sv, "Heatshrink_11_4"sv, "Heatshrink_12_4"sv }, (int)BinarizerConfig().compression.slicer_metadata },
{ "gcode_compression"sv, { "None"sv, "Deflate"sv, "Heatshrink_11_4"sv, "Heatshrink_12_4"sv }, (int)BinarizerConfig().compression.gcode },
#if ENABLE_MEATPACK_COMMENTS_EXTENDED
{ "gcode_encoding"sv, { "None"sv, "MeatPack"sv, "MeatPackComments"sv, "MeatPackExtended"sv }, (int)BinarizerConfig().gcode_encoding },
#else
{ "gcode_encoding"sv, { "None"sv, "MeatPack"sv, "MeatPackComments"sv }, (int)BinarizerConfig().gcode_encoding },
#endif // ENABLE_MEATPACK_COMMENTS_EXTENDED
{ "metadata_encoding"sv, { "INI"sv }, (int)BinarizerConfig().metadata_encoding }
};

Expand Down
14 changes: 7 additions & 7 deletions src/LibBGCode/convert/convert.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -377,36 +377,36 @@ BGCODE_CONVERT_EXPORT EResult from_ascii_to_binary(FILE& src_file, FILE& dst_fil

// update thumbnails
if (!reading_thumbnail.has_value()) {
std::string_view sv_thumbnail_str;
std::string_view thumbnail_sv;
if (sv_line.find(ThumbnailPNGBegin) == 0) {
reading_thumbnail = EThumbnailFormat::PNG;
sv_thumbnail_str = trim(sv_line.substr(ThumbnailPNGBegin.size()));
thumbnail_sv = trim(sv_line.substr(ThumbnailPNGBegin.size()));
}
else if (sv_line.find(ThumbnailJPGBegin) == 0) {
reading_thumbnail = EThumbnailFormat::JPG;
sv_thumbnail_str = trim(sv_line.substr(ThumbnailJPGBegin.size()));
thumbnail_sv = trim(sv_line.substr(ThumbnailJPGBegin.size()));
}
else if (sv_line.find(ThumbnailQOIBegin) == 0) {
reading_thumbnail = EThumbnailFormat::QOI;
sv_thumbnail_str = trim(sv_line.substr(ThumbnailQOIBegin.size()));
thumbnail_sv = trim(sv_line.substr(ThumbnailQOIBegin.size()));
}
if (reading_thumbnail.has_value()) {
ThumbnailBlock& thumbnail = binary_data.thumbnails.emplace_back(ThumbnailBlock());
thumbnail.params.format = (uint16_t)*reading_thumbnail;
pos = sv_thumbnail_str.find(" ");
pos = thumbnail_sv.find(" ");
if (pos == std::string_view::npos) {
parse_res = EResult::InvalidAsciiGCodeFile;
return;
}
const std::string_view sv_rect_str = trim(sv_thumbnail_str.substr(0, pos));
const std::string_view sv_rect_str = trim(thumbnail_sv.substr(0, pos));
std::pair<uint16_t, uint16_t> rect = extract_thumbnail_rect(sv_rect_str);
if (rect.first == 0 || rect.second == 0) {
parse_res = EResult::InvalidAsciiGCodeFile;
return;
}
thumbnail.params.width = rect.first;
thumbnail.params.height = rect.second;
const std::string_view sv_data_size_str = trim(sv_thumbnail_str.substr(pos + 1));
const std::string_view sv_data_size_str = trim(thumbnail_sv.substr(pos + 1));
size_t data_size;
to_int(sv_data_size_str, data_size);
if (data_size == 0) {
Expand Down
9 changes: 9 additions & 0 deletions src/LibBGCode/core/core.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@
#include <string>
#include <string_view>

// Experimental code which replaces the tags (comments), used by GCodeViewer to decorate the toolpaths,
// with MeatPack commands to try to reduce the size of the generated binary gcode file.
#define ENABLE_MEATPACK_COMMENTS_EXTENDED 1

namespace bgcode { namespace core {

static constexpr const std::array<uint8_t, 4> MAGIC{ 'G', 'C', 'D', 'E' };
Expand Down Expand Up @@ -83,7 +87,12 @@ enum class EGCodeEncodingType : uint16_t
{
None,
MeatPack,
#if ENABLE_MEATPACK_COMMENTS_EXTENDED
MeatPackComments,
MeatPackCommentsExtended
#else
MeatPackComments
#endif // ENABLE_MEATPACK_COMMENTS_EXTENDED
};

enum class EThumbnailFormat : uint16_t
Expand Down
4 changes: 4 additions & 0 deletions tests/convert/convert_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,11 @@ TEST_CASE("Convert from ascii to binary", "[Convert]")
config.compression.printer_metadata = ECompressionType::None;
config.compression.slicer_metadata = ECompressionType::Deflate;
config.compression.gcode = ECompressionType::Heatshrink_12_4;
#if ENABLE_MEATPACK_COMMENTS_EXTENDED
config.gcode_encoding = EGCodeEncodingType::MeatPackCommentsExtended;
#else
config.gcode_encoding = EGCodeEncodingType::MeatPackComments;
#endif // ENABLE_MEATPACK_COMMENTS_EXTENDED
config.metadata_encoding = EMetadataEncodingType::INI;
ascii_to_binary(ab_src_filename, ab_dst_filename, config);

Expand Down
9 changes: 6 additions & 3 deletions tests/core/core_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -64,9 +64,12 @@ static std::string gcode_encoding_as_string(EGCodeEncodingType type)
{
switch (type)
{
case EGCodeEncodingType::None: { return "None"; }
case EGCodeEncodingType::MeatPack: { return "MeatPack"; }
case EGCodeEncodingType::MeatPackComments: { return "MeatPackComments"; }
case EGCodeEncodingType::None: { return "None"; }
case EGCodeEncodingType::MeatPack: { return "MeatPack"; }
case EGCodeEncodingType::MeatPackComments: { return "MeatPackComments"; }
#if ENABLE_MEATPACK_COMMENTS_EXTENDED
case EGCodeEncodingType::MeatPackCommentsExtended: { return "MeatPackCommentsExtended"; }
#endif // ENABLE_MEATPACK_COMMENTS_EXTENDED
}
return "";
};
Expand Down

0 comments on commit 5cc26f4

Please sign in to comment.