SPE-1784: New compressed (binary) gcode format integration

Added conversion of gcodes from binary to ascii format
This commit is contained in:
enricoturri1966 2023-07-26 11:14:21 +02:00
parent 004a64a651
commit fba2406ace
6 changed files with 431 additions and 25 deletions

View File

@ -0,0 +1,93 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Generator: Adobe Illustrator 23.0.3, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg
version="1.0"
id="Layer_1"
x="0px"
y="0px"
viewBox="0 0 128 128"
enable-background="new 0 0 128 128"
xml:space="preserve"
sodipodi:docname="convert_file.svg"
inkscape:version="1.1 (c68e22c387, 2021-05-23)"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"><defs
id="defs1064">
</defs><sodipodi:namedview
id="namedview1062"
pagecolor="#505050"
bordercolor="#eeeeee"
borderopacity="1"
inkscape:pageshadow="0"
inkscape:pageopacity="0"
inkscape:pagecheckerboard="0"
showgrid="false"
inkscape:zoom="4.8782082"
inkscape:cx="62.830447"
inkscape:cy="67.750287"
inkscape:window-width="1920"
inkscape:window-height="1001"
inkscape:window-x="3191"
inkscape:window-y="-9"
inkscape:window-maximized="1"
inkscape:current-layer="Layer_1" />
<g
id="g1046"
style="stroke:none;stroke-opacity:1;fill:#808080;fill-opacity:1">
<path
fill="#ed6b21"
d="M 115.76,51.2 107.7,43.14 C 105.23,40.67 100.73,38.8 97.23,38.8 h -50.8 c -4.2,0 -7.62,3.42 -7.62,7.62 v 66.04 c 0,4.2 3.42,7.62 7.62,7.62 h 66.04 c 4.2,0 7.62,-3.42 7.62,-7.62 v -50.8 c 0,-3.49 -1.86,-7.99 -4.33,-10.46 z m -4.34,2.84 h -6.57 v -6.57 z m 3.59,58.43 c 0,1.4 -1.14,2.54 -2.54,2.54 H 46.43 c -1.4,0 -2.54,-1.14 -2.54,-2.54 V 46.42 c 0,-1.4 1.14,-2.54 2.54,-2.54 h 50.8 c 0.74,0 1.63,0.18 2.54,0.46 v 12.24 c 0,1.4 1.14,2.54 2.54,2.54 h 12.24 c 0.28,0.91 0.46,1.8 0.46,2.54 z"
id="path1036"
style="stroke:none;stroke-opacity:1;fill:#808080;fill-opacity:1" />
<path
fill="#ed6b21"
d="m 53.97,59.13 h 35.72 c 1.4,0 2.54,-1.14 2.54,-2.54 0,-1.4 -1.14,-2.54 -2.54,-2.54 H 53.97 c -1.4,0 -2.54,1.14 -2.54,2.54 0,1.4 1.13,2.54 2.54,2.54 z"
id="path1038"
style="stroke:none;stroke-opacity:1;fill:#808080;fill-opacity:1" />
<path
fill="#ed6b21"
d="M 104.93,69.29 H 53.97 c -1.4,0 -2.54,1.14 -2.54,2.54 0,1.4 1.14,2.54 2.54,2.54 h 50.96 c 1.4,0 2.54,-1.14 2.54,-2.54 0,-1.4 -1.14,-2.54 -2.54,-2.54 z"
id="path1040"
style="stroke:none;stroke-opacity:1;fill:#808080;fill-opacity:1" />
<path
fill="#ed6b21"
d="M 104.93,84.53 H 53.97 c -1.4,0 -2.54,1.14 -2.54,2.54 0,1.4 1.14,2.54 2.54,2.54 h 50.96 c 1.4,0 2.54,-1.14 2.54,-2.54 0,-1.4 -1.14,-2.54 -2.54,-2.54 z"
id="path1042"
style="stroke:none;stroke-opacity:1;fill:#808080;fill-opacity:1" />
<path
fill="#ed6b21"
d="M 104.93,99.77 H 53.97 c -1.4,0 -2.54,1.14 -2.54,2.54 0,1.4 1.14,2.54 2.54,2.54 h 50.96 c 1.4,0 2.54,-1.14 2.54,-2.54 0,-1.4 -1.14,-2.54 -2.54,-2.54 z"
id="path1044"
style="stroke:none;stroke-opacity:1;fill:#808080;fill-opacity:1" />
</g><g
id="g1058">
<path
fill="#808080"
d="M 85.27,20.71 77.21,12.65 C 74.74,10.18 70.24,8.31 66.74,8.31 h -50.8 c -4.2,0 -7.62,3.42 -7.62,7.62 v 66.04 c 0,4.2 3.42,7.62 7.62,7.62 h 17.78 c 1.4,0 2.54,-1.14 2.54,-2.54 0,-1.4 -1.14,-2.54 -2.54,-2.54 H 15.94 c -1.4,0 -2.54,-1.14 -2.54,-2.54 V 15.94 c 0,-1.4 1.14,-2.54 2.54,-2.54 h 50.8 c 0.74,0 1.63,0.18 2.54,0.46 V 26.1 c 0,1.4 1.14,2.54 2.54,2.54 h 12.45 c 0.16,0.49 0.25,0.93 0.25,1.27 v 3.81 c 0,1.4 1.14,2.54 2.54,2.54 1.4,0 2.54,-1.14 2.54,-2.54 v -3.81 c 0.01,-2.77 -1.85,-6.72 -4.33,-9.2 z m -10.9,-3.72 6.57,6.57 h -6.57 z"
id="path1048" />
<path
fill="#808080"
d="M 59.21,23.56 H 23.48 c -1.4,0 -2.54,1.14 -2.54,2.54 0,1.4 1.14,2.54 2.54,2.54 H 59.2 c 1.4,0 2.54,-1.14 2.54,-2.54 0,-1.4 -1.13,-2.54 -2.53,-2.54 z"
id="path1050" />
<path
fill="#808080"
d="m 28.73,38.8 h -5.24 c -1.4,0 -2.54,1.14 -2.54,2.54 0,1.4 1.14,2.54 2.54,2.54 h 5.24 c 1.4,0 2.54,-1.14 2.54,-2.54 0,-1.4 -1.14,-2.54 -2.54,-2.54 z"
id="path1052" />
<path
fill="#808080"
d="m 28.73,54.04 h -5.24 c -1.4,0 -2.54,1.14 -2.54,2.54 0,1.4 1.14,2.54 2.54,2.54 h 5.24 c 1.4,0 2.54,-1.14 2.54,-2.54 0,-1.4 -1.14,-2.54 -2.54,-2.54 z"
id="path1054" />
<path
fill="#808080"
d="m 28.73,69.29 h -5.24 c -1.4,0 -2.54,1.14 -2.54,2.54 0,1.4 1.14,2.54 2.54,2.54 h 5.24 c 1.4,0 2.54,-1.14 2.54,-2.54 0,-1.4 -1.14,-2.54 -2.54,-2.54 z"
id="path1056" />
</g>
<path
d="M 104.85,54.04 82.71545,76.15908 60.58864,54.03226 66.08342,48.53747 78.78283,61.23685 V 43.51678 C 78.76993,34.93742 71.81821,27.98568 63.23888,27.97284 H 47.69494 v -7.77197 h 15.54394 c 12.87167,0.0129 23.30304,10.44422 23.31591,23.31591 V 61.33793 L 99.34746,48.54524 Z"
id="path1427"
style="stroke-width:0.233159;fill:#ed6b21;fill-opacity:1" /></svg>

After

Width:  |  Height:  |  Size: 4.6 KiB

View File

@ -6,6 +6,10 @@
#include <debugapi.h>
#endif // ENABLE_BINARIZED_GCODE_DEBUG
#if ENABLE_FILE_CONVERSION_INTERFACE
#include <boost/beast/core/detail/base64.hpp>
#endif // ENABLE_FILE_CONVERSION_INTERFACE
extern "C" {
#include <heatshrink/heatshrink_encoder.h>
#include <heatshrink/heatshrink_decoder.h>
@ -441,32 +445,34 @@ static void unbinarize(const std::vector<uint8_t>& src, std::string& dst) {
}
} // namespace MeatPack
std::string translate_result(BinaryGCode::EResult result)
std::string translate_result(EResult result)
{
switch (result)
{
case BinaryGCode::EResult::Success: { return "Success"; }
case BinaryGCode::EResult::ReadError: { return "Read error"; }
case BinaryGCode::EResult::WriteError: { return "Write error"; }
case BinaryGCode::EResult::InvalidMagicNumber: { return "Invalid magic number"; }
case BinaryGCode::EResult::InvalidVersionNumber: { return "Invalid version number"; }
case BinaryGCode::EResult::InvalidChecksumType: { return "Invalid checksum type"; }
case BinaryGCode::EResult::InvalidBlockType: { return "Invalid block type"; }
case BinaryGCode::EResult::InvalidCompressionType: { return "Invalid compression type"; }
case BinaryGCode::EResult::InvalidMetadataEncodingType: { return "Invalid metadata encoding type"; }
case BinaryGCode::EResult::InvalidGCodeEncodingType: { return "Invalid gcode encoding type"; }
case BinaryGCode::EResult::DataCompressionError: { return "Data compression error"; }
case BinaryGCode::EResult::DataUncompressionError: { return "Data uncompression error"; }
case BinaryGCode::EResult::MetadataEncodingError: { return "Data encoding error"; }
case BinaryGCode::EResult::MetadataDecodingError: { return "Data decoding error"; }
case BinaryGCode::EResult::GCodeEncodingError: { return "GCode encoding error"; }
case BinaryGCode::EResult::GCodeDecodingError: { return "GCode decoding error"; }
case BinaryGCode::EResult::BlockNotFound: { return "Block not found"; }
case BinaryGCode::EResult::InvalidChecksum: { return "Invalid checksum"; }
case BinaryGCode::EResult::InvalidThumbnailFormat: { return "Invalid thumbnail format"; }
case BinaryGCode::EResult::InvalidThumbnailWidth: { return "Invalid thumbnail width"; }
case BinaryGCode::EResult::InvalidThumbnailHeight: { return "Invalid thumbnail height"; }
case BinaryGCode::EResult::InvalidThumbnailDataSize: { return "Invalid thumbnail data size"; }
case EResult::Success: { return "Success"; }
case EResult::ReadError: { return "Read error"; }
case EResult::WriteError: { return "Write error"; }
case EResult::InvalidMagicNumber: { return "Invalid magic number"; }
case EResult::InvalidVersionNumber: { return "Invalid version number"; }
case EResult::InvalidChecksumType: { return "Invalid checksum type"; }
case EResult::InvalidBlockType: { return "Invalid block type"; }
case EResult::InvalidCompressionType: { return "Invalid compression type"; }
case EResult::InvalidMetadataEncodingType: { return "Invalid metadata encoding type"; }
case EResult::InvalidGCodeEncodingType: { return "Invalid gcode encoding type"; }
case EResult::DataCompressionError: { return "Data compression error"; }
case EResult::DataUncompressionError: { return "Data uncompression error"; }
case EResult::MetadataEncodingError: { return "Data encoding error"; }
case EResult::MetadataDecodingError: { return "Data decoding error"; }
case EResult::GCodeEncodingError: { return "GCode encoding error"; }
case EResult::GCodeDecodingError: { return "GCode decoding error"; }
case EResult::BlockNotFound: { return "Block not found"; }
case EResult::InvalidChecksum: { return "Invalid checksum"; }
case EResult::InvalidThumbnailFormat: { return "Invalid thumbnail format"; }
case EResult::InvalidThumbnailWidth: { return "Invalid thumbnail width"; }
case EResult::InvalidThumbnailHeight: { return "Invalid thumbnail height"; }
case EResult::InvalidThumbnailDataSize: { return "Invalid thumbnail data size"; }
case EResult::InvalidBinaryGCodeFile: { return "Invalid binary GCode file"; }
case EResult::InvalidSequenceOfBlocks: { return "Invalid sequence of blocks"; }
}
return std::string();
}
@ -1658,5 +1664,200 @@ extern size_t block_content_size(const FileHeader& file_header, const BlockHeade
#endif // ENABLE_CHECKSUM_BLOCK
}
#if ENABLE_FILE_CONVERSION_INTERFACE
EResult from_ascii_to_binary(FILE& src_file, FILE& dst_file)
{
return EResult::WriteError;
}
EResult from_binary_to_ascii(FILE& src_file, FILE& dst_file, bool verify_checksum)
{
auto write_line = [&](const std::string& line) {
fwrite(line.data(), 1, line.length(), &dst_file);
return !ferror(&dst_file);
};
auto write_metadata = [&](const std::vector<std::pair<std::string, std::string>>& data) {
for (const auto& [key, value] : data) {
if (!write_line("; " + key + " = " + value + "\n"))
return false;
}
return !ferror(&dst_file);
};
if (!is_valid_binary_gcode(src_file))
return EResult::InvalidBinaryGCodeFile;
fseek(&src_file, 0, SEEK_END);
const long file_size = ftell(&src_file);
rewind(&src_file);
//
// read file header
//
FileHeader file_header;
EResult res = read_header(src_file, file_header, nullptr);
if (res != EResult::Success)
// propagate error
return res;
//
// convert file metadata block
//
BlockHeader block_header;
res = read_next_block_header(src_file, file_header, block_header, verify_checksum);
if (res != EResult::Success)
// propagate error
return res;
if ((EBlockType)block_header.type != EBlockType::FileMetadata)
return EResult::InvalidSequenceOfBlocks;
FileMetadataBlock file_metadata_block;
res = file_metadata_block.read_data(src_file, file_header, block_header);
if (res != EResult::Success)
// propagate error
return res;
auto producer_it = std::find_if(file_metadata_block.raw_data.begin(), file_metadata_block.raw_data.end(),
[](const std::pair<std::string, std::string>& item) { return item.first == "Producer"; });
const std::string producer_str = (producer_it != file_metadata_block.raw_data.end()) ? producer_it->second : "Unknown";
if (!write_line("; generated by " + producer_str + "\n\n\n"))
return EResult::WriteError;
//
// convert printer metadata block
//
res = read_next_block_header(src_file, file_header, block_header, verify_checksum);
if (res != EResult::Success)
// propagate error
return res;
if ((EBlockType)block_header.type != EBlockType::PrinterMetadata)
return EResult::InvalidSequenceOfBlocks;
PrinterMetadataBlock printer_metadata_block;
res = printer_metadata_block.read_data(src_file, file_header, block_header);
if (res != EResult::Success)
// propagate error
return res;
if (!write_metadata(printer_metadata_block.raw_data))
return EResult::WriteError;
//
// convert thumbnail blocks
//
long restore_position = ftell(&src_file);
res = read_next_block_header(src_file, file_header, block_header, verify_checksum);
if (res != EResult::Success)
// propagate error
return res;
while ((EBlockType)block_header.type == EBlockType::Thumbnail) {
ThumbnailBlock thumbnail_block;
res = thumbnail_block.read_data(src_file, file_header, block_header);
if (res != EResult::Success)
// propagate error
return res;
static constexpr const size_t max_row_length = 78;
std::string encoded;
encoded.resize(boost::beast::detail::base64::encoded_size(thumbnail_block.data.size()));
encoded.resize(boost::beast::detail::base64::encode((void*)encoded.data(), (const void*)thumbnail_block.data.data(), thumbnail_block.data.size()));
std::string format;
switch ((EThumbnailFormat)thumbnail_block.format)
{
default:
case EThumbnailFormat::PNG: { format = "thumbnail"; break; }
case EThumbnailFormat::JPG: { format = "thumbnail_JPG"; break; }
case EThumbnailFormat::QOI: { format = "thumbnail_QOI"; break; }
}
if (!write_line(";\n; " + format + " begin " + std::to_string(thumbnail_block.width) + "x" + std::to_string(thumbnail_block.height) +
" " + std::to_string(encoded.length()) + "\n"))
return EResult::WriteError;
while (encoded.size() > max_row_length) {
if (!write_line("; " + encoded.substr(0, max_row_length) + "\n"))
return EResult::WriteError;
encoded = encoded.substr(max_row_length);
}
if (encoded.size() > 0) {
if (!write_line("; " + encoded + "\n"))
return EResult::WriteError;
}
if (!write_line("; " + format + " end\n;\n\n"))
return EResult::WriteError;
restore_position = ftell(&src_file);
res = read_next_block_header(src_file, file_header, block_header, verify_checksum);
if (res != EResult::Success)
// propagate error
return res;
}
//
// convert gcode blocks
//
res = skip_block_content(src_file, file_header, block_header);
if (res != EResult::Success)
// propagate error
return res;
res = read_next_block_header(src_file, file_header, block_header, EBlockType::GCode, verify_checksum);
if (res != EResult::Success)
// propagate error
return res;
while ((EBlockType)block_header.type == EBlockType::GCode) {
GCodeBlock block;
res = block.read_data(src_file, file_header, block_header);
if (res != EResult::Success)
// propagate error
return res;
if (!write_line(block.raw_data))
return EResult::WriteError;
if (ftell(&src_file) == file_size)
break;
res = read_next_block_header(src_file, file_header, block_header, verify_checksum);
if (res != EResult::Success)
// propagate error
return res;
}
//
// convert print metadata block
//
fseek(&src_file, restore_position, SEEK_SET);
res = read_next_block_header(src_file, file_header, block_header, verify_checksum);
if (res != EResult::Success)
// propagate error
return res;
if ((EBlockType)block_header.type != EBlockType::PrintMetadata)
return EResult::InvalidSequenceOfBlocks;
PrintMetadataBlock print_metadata_block;
res = print_metadata_block.read_data(src_file, file_header, block_header);
if (res != EResult::Success)
// propagate error
return res;
if (!write_line("\n"))
return EResult::WriteError;
if (!write_metadata(print_metadata_block.raw_data))
return EResult::WriteError;
//
// convert slicer metadata block
//
res = read_next_block_header(src_file, file_header, block_header, verify_checksum);
if (res != EResult::Success)
// propagate error
return res;
if ((EBlockType)block_header.type != EBlockType::SlicerMetadata)
return EResult::InvalidSequenceOfBlocks;
SlicerMetadataBlock slicer_metadata_block;
res = slicer_metadata_block.read_data(src_file, file_header, block_header);
if (res != EResult::Success)
// propagate error
return res;
if (!write_line("\n; prusaslicer_config = begin\n"))
return EResult::WriteError;
if (!write_metadata(slicer_metadata_block.raw_data))
return EResult::WriteError;
if (!write_line("; prusaslicer_config = end\n\n"))
return EResult::WriteError;
return EResult::Success;
}
#endif // ENABLE_FILE_CONVERSION_INTERFACE
} // namespace BinaryGCode

View File

@ -6,6 +6,7 @@
#endif // _WIN32
#define ENABLE_CHECKSUM_BLOCK 0
#define ENABLE_FILE_CONVERSION_INTERFACE 1
#include <array>
#include <vector>
@ -41,7 +42,9 @@ enum class EResult : uint16_t
InvalidThumbnailFormat,
InvalidThumbnailWidth,
InvalidThumbnailHeight,
InvalidThumbnailDataSize
InvalidThumbnailDataSize,
InvalidBinaryGCodeFile,
InvalidSequenceOfBlocks
};
// Returns a string description of the given result
@ -359,6 +362,20 @@ extern size_t checksum_size(EChecksumType type);
// Returns the size of the content (parameters + data + checksum) of the block with the given header, in bytes.
extern size_t block_content_size(const FileHeader& file_header, const BlockHeader& block_header);
#if ENABLE_FILE_CONVERSION_INTERFACE
//=====================================================================================================================================
//
// FILE CONVERSION INTERFACE
//
//=====================================================================================================================================
// Converts the gcode file contained into src_file from ascii to binary format and save the results into dst_file
extern EResult from_ascii_to_binary(FILE& src_file, FILE& dst_file);
// Converts the gcode file contained into src_file from binary to ascii format and save the results into dst_file
extern EResult from_binary_to_ascii(FILE& src_file, FILE& dst_file, bool verify_checksum);
#endif // ENABLE_FILE_CONVERSION_INTERFACE
} // namespace BinaryGCode
#endif // slic3r_GCode_GCodeBinarizer_hpp_

View File

@ -1349,6 +1349,17 @@ void MainFrame::init_menubar_as_editor()
[]() {return true; }, this);
append_submenu(fileMenu, export_menu, wxID_ANY, _L("&Export"), "");
#if ENABLE_BINARIZED_GCODE
wxMenu* convert_menu = new wxMenu();
append_menu_item(convert_menu, wxID_ANY, _L("Convert ascii G-code to &binary") + dots, _L("Convert a G-code file from ascii to binary format"),
[this](wxCommandEvent&) { if (m_plater != nullptr) m_plater->convert_gcode_to_binary(); }, "convert_file", nullptr,
[this]() { return true; }, this);
append_menu_item(convert_menu, wxID_ANY, _L("Convert binary G-code to &ascii") + dots, _L("Convert a G-code file from binary to ascii format"),
[this](wxCommandEvent&) { if (m_plater != nullptr) m_plater->convert_gcode_to_ascii(); }, "convert_file", nullptr,
[this]() { return true; }, this);
append_submenu(fileMenu, convert_menu, wxID_ANY, _L("&Convert"), "");
#endif // ENABLE_BINARIZED_GCODE
append_menu_item(fileMenu, wxID_ANY, _L("Ejec&t SD Card / Flash Drive") + dots + "\tCtrl+T", _L("Eject SD card / Flash drive after the G-code was exported to it."),
[this](wxCommandEvent&) { if (m_plater) m_plater->eject_drive(); }, "eject_sd", nullptr,
[this]() {return can_eject(); }, this);
@ -1621,13 +1632,22 @@ void MainFrame::init_menubar_as_gcodeviewer()
_L("Reload the plater from disk"), [this](wxCommandEvent&) { m_plater->reload_gcode_from_disk(); },
"", nullptr, [this]() { return !m_plater->get_last_loaded_gcode().empty(); }, this);
#endif // __APPLE__
#if ENABLE_BINARIZED_GCODE
fileMenu->AppendSeparator();
append_menu_item(fileMenu, wxID_ANY, _L("Convert ascii G-code to &binary") + dots, _L("Convert a G-code file from ascii to binary format"),
[this](wxCommandEvent&) { if (m_plater != nullptr) m_plater->convert_gcode_to_binary(); }, "convert_file", nullptr,
[this]() { return true; }, this);
append_menu_item(fileMenu, wxID_ANY, _L("Convert binary G-code to &ascii") + dots, _L("Convert a G-code file from binary to ascii format"),
[this](wxCommandEvent&) { if (m_plater != nullptr) m_plater->convert_gcode_to_ascii(); }, "convert_file", nullptr,
[this]() { return true; }, this);
#endif // ENABLE_BINARIZED_GCODE
fileMenu->AppendSeparator();
append_menu_item(fileMenu, wxID_ANY, _L("Export &Toolpaths as OBJ") + dots, _L("Export toolpaths as OBJ"),
[this](wxCommandEvent&) { if (m_plater != nullptr) m_plater->export_toolpaths_to_obj(); }, "export_plater", nullptr,
[this]() {return can_export_toolpaths(); }, this);
append_menu_item(fileMenu, wxID_ANY, _L("Open &PrusaSlicer") + dots, _L("Open PrusaSlicer"),
[](wxCommandEvent&) { start_new_slicer(); }, "", nullptr,
[]() {return true; }, this);
[]() { return true; }, this);
fileMenu->AppendSeparator();
append_menu_item(fileMenu, wxID_EXIT, _L("&Quit"), wxString::Format(_L("Quit %s"), SLIC3R_APP_NAME),
[this](wxCommandEvent&) { Close(false); });

View File

@ -5430,6 +5430,77 @@ void Plater::reload_gcode_from_disk()
load_gcode(filename);
}
#if ENABLE_BINARIZED_GCODE
static bool is_valid_binary_gcode(const wxString& filename)
{
FILE* file = boost::nowide::fopen(into_u8(filename).c_str(), "rb");
if (file == nullptr)
return false;
const bool ret = BinaryGCode::is_valid_binary_gcode(*file);
fclose(file);
return ret;
}
void Plater::convert_gcode_to_ascii()
{
// Ask user for a gcode file name.
wxString input_file;
wxGetApp().load_gcode(this, input_file);
class ScopedFile
{
public:
explicit ScopedFile(FILE* file) : m_file(file) {}
~ScopedFile() { if (m_file != nullptr) fclose(m_file); }
private:
FILE* m_file{ nullptr };
};
// Open source file
FILE* in_file = boost::nowide::fopen(into_u8(input_file).c_str(), "rb");
if (in_file == nullptr) {
MessageDialog msg_dlg(this, _L("Unable to open the selected file."), _L("Error"), wxICON_ERROR | wxOK);
msg_dlg.ShowModal();
return;
}
ScopedFile scoped_in_file(in_file);
// Set out filename
boost::filesystem::path path(into_u8(input_file));
const std::string output_file = path.parent_path().string() + "/" + path.stem().string() + "_ascii" + path.extension().string();
// Open destination file
FILE* out_file = boost::nowide::fopen(output_file.c_str(), "wb");
if (out_file == nullptr) {
MessageDialog msg_dlg(this, _L("Unable to open output file."), _L("Error"), wxICON_ERROR | wxOK);
msg_dlg.ShowModal();
return;
}
ScopedFile scoped_out_file(out_file);
// Perform conversion
{
wxBusyCursor busy;
BinaryGCode::EResult res = BinaryGCode::from_binary_to_ascii(*in_file, *out_file, true);
if (res != BinaryGCode::EResult::Success) {
MessageDialog msg_dlg(this, _L(BinaryGCode::translate_result(res)), _L("Error converting gcode file"), wxICON_INFORMATION | wxOK);
msg_dlg.ShowModal();
return;
}
}
MessageDialog msg_dlg(this, _L("Succesfully created gcode ascii file:\n") + output_file, _L("Convert gcode file to ascii format"), wxICON_ERROR | wxOK);
msg_dlg.ShowModal();
}
void Plater::convert_gcode_to_binary()
{
MessageDialog msg_dlg(this, _L("Not implemented yet."), _L("Error"), wxICON_ERROR | wxOK);
msg_dlg.ShowModal();
}
#endif // ENABLE_BINARIZED_GCODE
void Plater::refresh_print()
{
p->preview->refresh_print();

View File

@ -172,6 +172,10 @@ public:
void load_gcode();
void load_gcode(const wxString& filename);
void reload_gcode_from_disk();
#if ENABLE_BINARIZED_GCODE
void convert_gcode_to_ascii();
void convert_gcode_to_binary();
#endif // ENABLE_BINARIZED_GCODE
void refresh_print();
std::vector<size_t> load_files(const std::vector<boost::filesystem::path>& input_files, bool load_model = true, bool load_config = true, bool imperial_units = false);