mirror of
https://git.mirrors.martin98.com/https://github.com/prusa3d/PrusaSlicer.git
synced 2025-07-30 23:51:57 +08:00
SPE-1784: New compressed (binary) gcode format integration
Added conversion of gcodes from binary to ascii format
This commit is contained in:
parent
004a64a651
commit
fba2406ace
93
resources/icons/convert_file.svg
Normal file
93
resources/icons/convert_file.svg
Normal 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 |
@ -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
|
||||
|
||||
|
@ -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_
|
||||
|
@ -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); });
|
||||
|
@ -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();
|
||||
|
@ -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);
|
||||
|
Loading…
x
Reference in New Issue
Block a user