From 4d14ee15cebb6f96342ed0c181d1dd33a70df6a2 Mon Sep 17 00:00:00 2001 From: Ocraftyone Date: Tue, 17 Oct 2023 08:00:38 -0400 Subject: [PATCH 1/2] Thumbnail Formats Option Ported from PrusaSlicer and add BIQU/BTT format (#2405) * Add needed src files and update CMake files * Implementation of GCodeThumbnailsFormat for PNG, JPG, and QOI complete * Implement BIQU (Big Tree Tech) Thumbnail Format * have GCodeProcessor.post_process pass through original line end characters * fix biqu thumbnail output use \r\n for new lines in the biqu thumbnail portion. the firmware requires these end characters to function properly. update names of variables and add comments to be more descriptive replace modified Qt pixel algorithm with much simpler algorithm from BTT TFT firmware * rename BiQU to BTT_TFT for better clarity * remove underscore from GUI option --------- Co-authored-by: SoftFever <103989404+SoftFever@users.noreply.github.com> --- src/CMakeLists.txt | 1 + src/libslic3r/CMakeLists.txt | 6 + src/libslic3r/GCode.cpp | 64 +-- src/libslic3r/GCode/GCodeProcessor.cpp | 5 +- src/libslic3r/GCode/Thumbnails.cpp | 196 ++++++++ src/libslic3r/GCode/Thumbnails.hpp | 80 +++ src/libslic3r/Preset.cpp | 2 +- src/libslic3r/Print.cpp | 1 + src/libslic3r/PrintConfig.cpp | 19 + src/libslic3r/PrintConfig.hpp | 5 + src/qoi/CMakeLists.txt | 9 + src/qoi/README.md | 108 ++++ src/qoi/qoi.h | 671 +++++++++++++++++++++++++ src/qoi/qoilib.c | 6 + src/slic3r/GUI/Tab.cpp | 1 + 15 files changed, 1124 insertions(+), 50 deletions(-) create mode 100644 src/libslic3r/GCode/Thumbnails.cpp create mode 100644 src/libslic3r/GCode/Thumbnails.hpp create mode 100644 src/qoi/CMakeLists.txt create mode 100644 src/qoi/README.md create mode 100644 src/qoi/qoi.h create mode 100644 src/qoi/qoilib.c diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index ab9a9707931..71f6fe1f5f6 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -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) diff --git a/src/libslic3r/CMakeLists.txt b/src/libslic3r/CMakeLists.txt index 3365a3e6bea..9aae0a8f0a2 100644 --- a/src/libslic3r/CMakeLists.txt +++ b/src/libslic3r/CMakeLists.txt @@ -411,6 +411,8 @@ set(lisbslic3r_sources Shape/TextShape.cpp calib.hpp calib.cpp + GCode/Thumbnails.cpp + GCode/Thumbnails.hpp ) if (APPLE) @@ -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 @@ -525,6 +529,8 @@ target_link_libraries(libslic3r ${OCCT_LIBS} Clipper2 mcut + JPEG::JPEG + qoi ) if(NOT WIN32) diff --git a/src/libslic3r/GCode.cpp b/src/libslic3r/GCode.cpp index 10663452ea9..9217519ea79 100644 --- a/src/libslic3r/GCode.cpp +++ b/src/libslic3r/GCode.cpp @@ -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" @@ -1663,50 +1664,6 @@ namespace DoExport { } } - //BBS: add plate id for thumbnail generate param - template - static void export_thumbnails_to_file(ThumbnailsGeneratorCallback &thumbnail_cb, int plate_id, const std::vector &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("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("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. @@ -1977,10 +1943,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("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("thumbnails")->values, + m_gcode_thumbnail_format, + [&file](const char *sz) { file.write(sz); }, + [&print]() { print.throw_if_canceled(); }); } } diff --git a/src/libslic3r/GCode/GCodeProcessor.cpp b/src/libslic3r/GCode/GCodeProcessor.cpp index e776a5fbb1c..a6f8b7d8ecb 100644 --- a/src/libslic3r/GCode/GCodeProcessor.cpp +++ b/src/libslic3r/GCode/GCodeProcessor.cpp @@ -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) diff --git a/src/libslic3r/GCode/Thumbnails.cpp b/src/libslic3r/GCode/Thumbnails.cpp new file mode 100644 index 00000000000..22788967ec1 --- /dev/null +++ b/src/libslic3r/GCode/Thumbnails.cpp @@ -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 +#include +#include + +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 compress_thumbnail_png(const ThumbnailData &data) +{ + auto out = std::make_unique(); + 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 compress_thumbnail_jpg(const ThumbnailData& data) +{ + // Take vector of RGBA pixels and flip the image vertically + std::vector 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 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 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(); + 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 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 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(); + int size; + out->data = qoi_encode((const void*)rgba_pixels.data(), &desc, &size); + out->size = size; + return out; +} + +std::unique_ptr compress_thumbnail_btt_tft(const ThumbnailData &data) { + + // Take vector of RGBA pixels and flip the image vertically + std::vector 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(); + + // 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 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 \ No newline at end of file diff --git a/src/libslic3r/GCode/Thumbnails.hpp b/src/libslic3r/GCode/Thumbnails.hpp new file mode 100644 index 00000000000..b2ea4ea5fd8 --- /dev/null +++ b/src/libslic3r/GCode/Thumbnails.hpp @@ -0,0 +1,80 @@ +///|/ Copyright (c) Prusa Research 2022 Lukáš Hejl @hejllukas, Vojtěch Bubník @bubnikv +///|/ +///|/ PrusaSlicer is released under the terms of the AGPLv3 or higher +///|/ +#ifndef slic3r_GCodeThumbnails_hpp_ +#define slic3r_GCodeThumbnails_hpp_ + +#include "../Point.hpp" +#include "../PrintConfig.hpp" +#include "ThumbnailData.hpp" + +#include +#include +#include + +#include + +namespace Slic3r::GCodeThumbnails { + +struct CompressedImageBuffer +{ + void *data { nullptr }; + size_t size { 0 }; + virtual ~CompressedImageBuffer() {} + virtual std::string_view tag() const = 0; +}; + +std::string get_hex(const unsigned int input); +std::string rjust(std::string input, unsigned int width, char fill_char); +std::unique_ptr compress_thumbnail(const ThumbnailData &data, GCodeThumbnailsFormat format); + +template +inline void export_thumbnails_to_file(ThumbnailsGeneratorCallback &thumbnail_cb, int plate_id, const std::vector &sizes, GCodeThumbnailsFormat format, WriteToOutput output, ThrowIfCanceledCallback throw_if_canceled) +{ + // Write thumbnails using base64 encoding + if (thumbnail_cb != nullptr) { + static constexpr const size_t max_row_length = 78; + ThumbnailsList thumbnails = thumbnail_cb(ThumbnailsParams{ sizes, true, true, true, true, plate_id }); + short i = 0; + for (const ThumbnailData& data : thumbnails) { + if (data.is_valid()) { + auto compressed = compress_thumbnail(data, format); + if (compressed->data && compressed->size) { + if (format == GCodeThumbnailsFormat::BTT_TFT) { + // write BTT_TFT header + output((";" + rjust(get_hex(data.width), 4, '0') + rjust(get_hex(data.height), 4, '0') + "\r\n").c_str()); + output((char *) compressed->data); + if (i == (thumbnails.size() - 1)) + output("; bigtree thumbnail end\r\n\r\n"); + } else { + std::string encoded; + encoded.resize(boost::beast::detail::base64::encoded_size(compressed->size)); + encoded.resize(boost::beast::detail::base64::encode((void *) encoded.data(), (const void *) compressed->data, + compressed->size)); + + output((boost::format("\n;\n; %s begin %dx%d %d\n") % compressed->tag() % data.width % data.height % encoded.size()) + .str() + .c_str()); + + while (encoded.size() > max_row_length) { + output((boost::format("; %s\n") % encoded.substr(0, max_row_length)).str().c_str()); + encoded = encoded.substr(max_row_length); + } + + if (encoded.size() > 0) + output((boost::format("; %s\n") % encoded).str().c_str()); + + output((boost::format("; %s end\n;\n") % compressed->tag()).str().c_str()); + } + throw_if_canceled(); + } + i++; + } + } + } +} + +} // namespace Slic3r::GCodeThumbnails + +#endif // slic3r_GCodeThumbnails_hpp_ \ No newline at end of file diff --git a/src/libslic3r/Preset.cpp b/src/libslic3r/Preset.cpp index aee4117fd1e..0e845743072 100644 --- a/src/libslic3r/Preset.cpp +++ b/src/libslic3r/Preset.cpp @@ -823,7 +823,7 @@ static std::vector s_Preset_printer_options { "host_type", "print_host", "printhost_apikey", "print_host_webui", "printhost_cafile","printhost_port","printhost_authorization_type", - "printhost_user", "printhost_password", "printhost_ssl_ignore_revoke", "thumbnails", + "printhost_user", "printhost_password", "printhost_ssl_ignore_revoke", "thumbnails", "thumbnails_format", "use_firmware_retraction", "use_relative_e_distances", "printer_notes", "cooling_tube_retraction", "cooling_tube_length", "high_current_on_filament_swap", "parking_pos_retraction", "extra_loading_move", "purge_in_prime_tower", "enable_filament_ramming"}; diff --git a/src/libslic3r/Print.cpp b/src/libslic3r/Print.cpp index 798d5bc6853..26bd7f3ed5d 100644 --- a/src/libslic3r/Print.cpp +++ b/src/libslic3r/Print.cpp @@ -184,6 +184,7 @@ bool Print::invalidate_state_by_config_options(const ConfigOptionResolver & /* n // SoftFever "chamber_temperature", "thumbnails", + "thumbnails_format", "seam_gap", "role_based_wipe_speed", "wipe_speed", diff --git a/src/libslic3r/PrintConfig.cpp b/src/libslic3r/PrintConfig.cpp index 0b6c8715b8a..cc7f6052b08 100644 --- a/src/libslic3r/PrintConfig.cpp +++ b/src/libslic3r/PrintConfig.cpp @@ -327,6 +327,14 @@ static const t_config_enum_values s_keys_map_RetractLiftEnforceType = { }; CONFIG_OPTION_ENUM_DEFINE_STATIC_MAPS(RetractLiftEnforceType) +static const t_config_enum_values s_keys_map_GCodeThumbnailsFormat = { + { "PNG", int(GCodeThumbnailsFormat::PNG) }, + { "JPG", int(GCodeThumbnailsFormat::JPG) }, + { "QOI", int(GCodeThumbnailsFormat::QOI) }, + { "BTT_TFT", int(GCodeThumbnailsFormat::BTT_TFT) } +}; +CONFIG_OPTION_ENUM_DEFINE_STATIC_MAPS(GCodeThumbnailsFormat) + static void assign_printer_technology_to_unknown(t_optiondef_map &options, PrinterTechnology printer_technology) { for (std::pair &kvp : options) @@ -4188,6 +4196,17 @@ def = this->add("filament_loading_speed", coFloats); def->gui_type = ConfigOptionDef::GUIType::one_string; def->set_default_value(new ConfigOptionPoints{Vec2d(300, 300)}); + def = this->add("thumbnails_format", coEnum); + def->label = L("Format of G-code thumbnails"); + def->tooltip = L("Format of G-code thumbnails: PNG for best quality, JPG for smallest size, QOI for low memory firmware"); + def->mode = comAdvanced; + def->enum_keys_map = &ConfigOptionEnum::get_enum_values(); + def->enum_values.push_back("PNG"); + def->enum_values.push_back("JPG"); + def->enum_values.push_back("QOI"); + def->enum_values.push_back("BTT TFT"); + def->set_default_value(new ConfigOptionEnum(GCodeThumbnailsFormat::PNG)); + def = this->add("use_relative_e_distances", coBool); def->label = L("Use relative E distances"); def->tooltip = L("Relative extrusion is recommended when using \"label_objects\" option." diff --git a/src/libslic3r/PrintConfig.hpp b/src/libslic3r/PrintConfig.hpp index 367e594e032..dfc43335068 100644 --- a/src/libslic3r/PrintConfig.hpp +++ b/src/libslic3r/PrintConfig.hpp @@ -233,6 +233,10 @@ enum RetractLiftEnforceType { rletTopAndBottom }; +enum class GCodeThumbnailsFormat { + PNG, JPG, QOI, BTT_TFT +}; + static std::string bed_type_to_gcode_string(const BedType type) { std::string type_str; @@ -315,6 +319,7 @@ CONFIG_OPTION_ENUM_DECLARE_STATIC_MAPS(TimelapseType) CONFIG_OPTION_ENUM_DECLARE_STATIC_MAPS(BedType) CONFIG_OPTION_ENUM_DECLARE_STATIC_MAPS(DraftShield) CONFIG_OPTION_ENUM_DECLARE_STATIC_MAPS(ForwardCompatibilitySubstitutionRule) +CONFIG_OPTION_ENUM_DECLARE_STATIC_MAPS(GCodeThumbnailsFormat) CONFIG_OPTION_ENUM_DECLARE_STATIC_MAPS(PrintHostType) CONFIG_OPTION_ENUM_DECLARE_STATIC_MAPS(AuthorizationType) diff --git a/src/qoi/CMakeLists.txt b/src/qoi/CMakeLists.txt new file mode 100644 index 00000000000..af8bf2e051a --- /dev/null +++ b/src/qoi/CMakeLists.txt @@ -0,0 +1,9 @@ +# PrusaSlicer specific CMake + +cmake_minimum_required(VERSION 2.8.12) +project(qoi) + +add_library(qoi STATIC + qoi.h + qoilib.c +) diff --git a/src/qoi/README.md b/src/qoi/README.md new file mode 100644 index 00000000000..4006c385078 --- /dev/null +++ b/src/qoi/README.md @@ -0,0 +1,108 @@ +Bundled with PrusaSlicer: commit 6c0831f91ffde5dfe2ceef32cbaff91d62b0e0ee +Original README follows: + + +![QOI Logo](https://qoiformat.org/qoi-logo.svg) + +# QOI - The “Quite OK Image Format” for fast, lossless image compression + +Single-file MIT licensed library for C/C++ + +See [qoi.h](https://github.com/phoboslab/qoi/blob/master/qoi.h) for +the documentation and format specification. + +More info at https://qoiformat.org + + +## Why? + +Compared to stb_image and stb_image_write QOI offers 20x-50x faster encoding, +3x-4x faster decoding and 20% better compression. It's also stupidly simple and +fits in about 300 lines of C. + + +## Example Usage + +- [qoiconv.c](https://github.com/phoboslab/qoi/blob/master/qoiconv.c) +converts between png <> qoi + - [qoibench.c](https://github.com/phoboslab/qoi/blob/master/qoibench.c) +a simple wrapper to benchmark stbi, libpng and qoi + + +## Limitations + +The QOI file format allows for huge images with up to 18 exa-pixels. A streaming +en-/decoder can handle these with minimal RAM requirements, assuming there is +enough storage space. + +This particular implementation of QOI however is limited to images with a +maximum size of 400 million pixels. It will safely refuse to en-/decode anything +larger than that. This is not a streaming en-/decoder. It loads the whole image +file into RAM before doing any work and is not extensively optimized for +performance (but it's still very fast). + +If this is a limitation for your use case, please look into any of the other +implementations listed below. + + +## Tools + +- https://github.com/floooh/qoiview - native QOI viewer +- https://github.com/pfusik/qoi-ci/releases/tag/qoi-ci-1.1.0 - QOI Plugin installer for GIMP, Imagine, Paint.NET and XnView MP +- https://github.com/iOrange/QoiFileTypeNet/releases/tag/v0.2 - QOI Plugin for Paint.NET +- https://github.com/iOrange/QOIThumbnailProvider - Add thumbnails for QOI images in Windows Explorer +- https://github.com/Tom94/tev - another native QOI viewer (allows pixel peeping and comparison with other image formats) +- https://apps.apple.com/br/app/qoiconverterx/id1602159820 QOI <=> PNG converter available on the Mac App Store +- https://github.com/kaetemi/qoi-max - QOI Bitmap I/O Plugin for 3ds Max +- https://raylibtech.itch.io/rtexviewer - texture viewer, supports QOI + + +## Implementations & Bindings of QOI + +- https://github.com/pfusik/qoi-ci (Ć, transpiled to C, C++, C#, Java, JavaScript, Python and Swift) +- https://github.com/kodonnell/qoi (Python) +- https://github.com/Cr4xy/lua-qoi (Lua) +- https://github.com/superzazu/SDL_QOI (C, SDL2 bindings) +- https://github.com/saharNooby/qoi-java (Java) +- https://github.com/MasterQ32/zig-qoi (Zig) +- https://github.com/rbino/qoix (Elixir) +- https://github.com/NUlliiON/QoiSharp (C#) +- https://github.com/aldanor/qoi-rust (Rust) +- https://github.com/zakarumych/rapid-qoi (Rust) +- https://github.com/takeyourhatoff/qoi (Go) +- https://github.com/DosWorld/pasqoi (Pascal) +- https://github.com/elihwyma/Swift-QOI (Swift) +- https://github.com/xfmoulet/qoi (Go) +- https://erratique.ch/software/qoic (OCaml) +- https://github.com/arian/go-qoi (Go) +- https://github.com/kchapelier/qoijs (JavaScript) +- https://github.com/KristofferC/QOI.jl (Julia) +- https://github.com/shadowMitia/libqoi/ (C++) +- https://github.com/MKCG/php-qoi (PHP) +- https://github.com/LightHouseSoftware/qoiformats (D) +- https://github.com/mhoward540/qoi-nim (Nim) + + +## QOI Support in Other Software + +- [SerenityOS](https://github.com/SerenityOS/serenity) supports decoding QOI system wide through a custom [cpp implementation in LibGfx](https://github.com/SerenityOS/serenity/blob/master/Userland/Libraries/LibGfx/QOILoader.h) +- [Raylib](https://github.com/raysan5/raylib) supports decoding and encoding QOI textures through its [rtextures module](https://github.com/raysan5/raylib/blob/master/src/rtextures.c) +- [Rebol3](https://github.com/Oldes/Rebol3/issues/39) supports decoding and encoding QOI using a native codec +- [c-ray](https://github.com/vkoskiv/c-ray) supports QOI natively +- [SAIL](https://github.com/HappySeaFox/sail) image decoding library, supports decoding and encoding QOI images +- [Orx](https://github.com/orx/orx) 2D game engine, supports QOI natively + + +## Packages + +[AUR](https://aur.archlinux.org/pkgbase/qoi-git/) - system-wide qoi.h, qoiconv and qoibench install as split packages. + + +## Implementations not yet conforming to the final specification + +These implementations are based on the pre-release version of QOI. Resulting files are not compatible with the current version. + +- https://github.com/ChevyRay/qoi_rs (Rust) +- https://github.com/panzi/jsqoi (TypeScript) +- https://github.com/0xd34df00d/hsqoi (Haskell) + diff --git a/src/qoi/qoi.h b/src/qoi/qoi.h new file mode 100644 index 00000000000..988f9edcb4f --- /dev/null +++ b/src/qoi/qoi.h @@ -0,0 +1,671 @@ +/* + +QOI - The "Quite OK Image" format for fast, lossless image compression + +Dominic Szablewski - https://phoboslab.org + + +-- LICENSE: The MIT License(MIT) + +Copyright(c) 2021 Dominic Szablewski + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files(the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and / or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions : +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + +-- About + +QOI encodes and decodes images in a lossless format. Compared to stb_image and +stb_image_write QOI offers 20x-50x faster encoding, 3x-4x faster decoding and +20% better compression. + + +-- Synopsis + +// Define `QOI_IMPLEMENTATION` in *one* C/C++ file before including this +// library to create the implementation. + +#define QOI_IMPLEMENTATION +#include "qoi.h" + +// Encode and store an RGBA buffer to the file system. The qoi_desc describes +// the input pixel data. +qoi_write("image_new.qoi", rgba_pixels, &(qoi_desc){ + .width = 1920, + .height = 1080, + .channels = 4, + .colorspace = QOI_SRGB +}); + +// Load and decode a QOI image from the file system into a 32bbp RGBA buffer. +// The qoi_desc struct will be filled with the width, height, number of channels +// and colorspace read from the file header. +qoi_desc desc; +void *rgba_pixels = qoi_read("image.qoi", &desc, 4); + + + +-- Documentation + +This library provides the following functions; +- qoi_read -- read and decode a QOI file +- qoi_decode -- decode the raw bytes of a QOI image from memory +- qoi_write -- encode and write a QOI file +- qoi_encode -- encode an rgba buffer into a QOI image in memory + +See the function declaration below for the signature and more information. + +If you don't want/need the qoi_read and qoi_write functions, you can define +QOI_NO_STDIO before including this library. + +This library uses malloc() and free(). To supply your own malloc implementation +you can define QOI_MALLOC and QOI_FREE before including this library. + +This library uses memset() to zero-initialize the index. To supply your own +implementation you can define QOI_ZEROARR before including this library. + + +-- Data Format + +A QOI file has a 14 byte header, followed by any number of data "chunks" and an +8-byte end marker. + +struct qoi_header_t { + char magic[4]; // magic bytes "qoif" + uint32_t width; // image width in pixels (BE) + uint32_t height; // image height in pixels (BE) + uint8_t channels; // 3 = RGB, 4 = RGBA + uint8_t colorspace; // 0 = sRGB with linear alpha, 1 = all channels linear +}; + +Images are encoded row by row, left to right, top to bottom. The decoder and +encoder start with {r: 0, g: 0, b: 0, a: 255} as the previous pixel value. An +image is complete when all pixels specified by width * height have been covered. + +Pixels are encoded as + - a run of the previous pixel + - an index into an array of previously seen pixels + - a difference to the previous pixel value in r,g,b + - full r,g,b or r,g,b,a values + +The color channels are assumed to not be premultiplied with the alpha channel +("un-premultiplied alpha"). + +A running array[64] (zero-initialized) of previously seen pixel values is +maintained by the encoder and decoder. Each pixel that is seen by the encoder +and decoder is put into this array at the position formed by a hash function of +the color value. In the encoder, if the pixel value at the index matches the +current pixel, this index position is written to the stream as QOI_OP_INDEX. +The hash function for the index is: + + index_position = (r * 3 + g * 5 + b * 7 + a * 11) % 64 + +Each chunk starts with a 2- or 8-bit tag, followed by a number of data bits. The +bit length of chunks is divisible by 8 - i.e. all chunks are byte aligned. All +values encoded in these data bits have the most significant bit on the left. + +The 8-bit tags have precedence over the 2-bit tags. A decoder must check for the +presence of an 8-bit tag first. + +The byte stream's end is marked with 7 0x00 bytes followed a single 0x01 byte. + + +The possible chunks are: + + +.- QOI_OP_INDEX ----------. +| Byte[0] | +| 7 6 5 4 3 2 1 0 | +|-------+-----------------| +| 0 0 | index | +`-------------------------` +2-bit tag b00 +6-bit index into the color index array: 0..63 + +A valid encoder must not issue 2 or more consecutive QOI_OP_INDEX chunks to the +same index. QOI_OP_RUN should be used instead. + + +.- QOI_OP_DIFF -----------. +| Byte[0] | +| 7 6 5 4 3 2 1 0 | +|-------+-----+-----+-----| +| 0 1 | dr | dg | db | +`-------------------------` +2-bit tag b01 +2-bit red channel difference from the previous pixel between -2..1 +2-bit green channel difference from the previous pixel between -2..1 +2-bit blue channel difference from the previous pixel between -2..1 + +The difference to the current channel values are using a wraparound operation, +so "1 - 2" will result in 255, while "255 + 1" will result in 0. + +Values are stored as unsigned integers with a bias of 2. E.g. -2 is stored as +0 (b00). 1 is stored as 3 (b11). + +The alpha value remains unchanged from the previous pixel. + + +.- QOI_OP_LUMA -------------------------------------. +| Byte[0] | Byte[1] | +| 7 6 5 4 3 2 1 0 | 7 6 5 4 3 2 1 0 | +|-------+-----------------+-------------+-----------| +| 1 0 | green diff | dr - dg | db - dg | +`---------------------------------------------------` +2-bit tag b10 +6-bit green channel difference from the previous pixel -32..31 +4-bit red channel difference minus green channel difference -8..7 +4-bit blue channel difference minus green channel difference -8..7 + +The green channel is used to indicate the general direction of change and is +encoded in 6 bits. The red and blue channels (dr and db) base their diffs off +of the green channel difference and are encoded in 4 bits. I.e.: + dr_dg = (cur_px.r - prev_px.r) - (cur_px.g - prev_px.g) + db_dg = (cur_px.b - prev_px.b) - (cur_px.g - prev_px.g) + +The difference to the current channel values are using a wraparound operation, +so "10 - 13" will result in 253, while "250 + 7" will result in 1. + +Values are stored as unsigned integers with a bias of 32 for the green channel +and a bias of 8 for the red and blue channel. + +The alpha value remains unchanged from the previous pixel. + + +.- QOI_OP_RUN ------------. +| Byte[0] | +| 7 6 5 4 3 2 1 0 | +|-------+-----------------| +| 1 1 | run | +`-------------------------` +2-bit tag b11 +6-bit run-length repeating the previous pixel: 1..62 + +The run-length is stored with a bias of -1. Note that the run-lengths 63 and 64 +(b111110 and b111111) are illegal as they are occupied by the QOI_OP_RGB and +QOI_OP_RGBA tags. + + +.- QOI_OP_RGB ------------------------------------------. +| Byte[0] | Byte[1] | Byte[2] | Byte[3] | +| 7 6 5 4 3 2 1 0 | 7 .. 0 | 7 .. 0 | 7 .. 0 | +|-------------------------+---------+---------+---------| +| 1 1 1 1 1 1 1 0 | red | green | blue | +`-------------------------------------------------------` +8-bit tag b11111110 +8-bit red channel value +8-bit green channel value +8-bit blue channel value + +The alpha value remains unchanged from the previous pixel. + + +.- QOI_OP_RGBA ---------------------------------------------------. +| Byte[0] | Byte[1] | Byte[2] | Byte[3] | Byte[4] | +| 7 6 5 4 3 2 1 0 | 7 .. 0 | 7 .. 0 | 7 .. 0 | 7 .. 0 | +|-------------------------+---------+---------+---------+---------| +| 1 1 1 1 1 1 1 1 | red | green | blue | alpha | +`-----------------------------------------------------------------` +8-bit tag b11111111 +8-bit red channel value +8-bit green channel value +8-bit blue channel value +8-bit alpha channel value + +*/ + + +/* ----------------------------------------------------------------------------- +Header - Public functions */ + +#ifndef QOI_H +#define QOI_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* A pointer to a qoi_desc struct has to be supplied to all of qoi's functions. +It describes either the input format (for qoi_write and qoi_encode), or is +filled with the description read from the file header (for qoi_read and +qoi_decode). + +The colorspace in this qoi_desc is an enum where + 0 = sRGB, i.e. gamma scaled RGB channels and a linear alpha channel + 1 = all channels are linear +You may use the constants QOI_SRGB or QOI_LINEAR. The colorspace is purely +informative. It will be saved to the file header, but does not affect +how chunks are en-/decoded. */ + +#define QOI_SRGB 0 +#define QOI_LINEAR 1 + +typedef struct { + unsigned int width; + unsigned int height; + unsigned char channels; + unsigned char colorspace; +} qoi_desc; + +#ifndef QOI_NO_STDIO + +/* Encode raw RGB or RGBA pixels into a QOI image and write it to the file +system. The qoi_desc struct must be filled with the image width, height, +number of channels (3 = RGB, 4 = RGBA) and the colorspace. + +The function returns 0 on failure (invalid parameters, or fopen or malloc +failed) or the number of bytes written on success. */ + +int qoi_write(const char *filename, const void *data, const qoi_desc *desc); + + +/* Read and decode a QOI image from the file system. If channels is 0, the +number of channels from the file header is used. If channels is 3 or 4 the +output format will be forced into this number of channels. + +The function either returns NULL on failure (invalid data, or malloc or fopen +failed) or a pointer to the decoded pixels. On success, the qoi_desc struct +will be filled with the description from the file header. + +The returned pixel data should be free()d after use. */ + +void *qoi_read(const char *filename, qoi_desc *desc, int channels); + +#endif /* QOI_NO_STDIO */ + + +/* Encode raw RGB or RGBA pixels into a QOI image in memory. + +The function either returns NULL on failure (invalid parameters or malloc +failed) or a pointer to the encoded data on success. On success the out_len +is set to the size in bytes of the encoded data. + +The returned qoi data should be free()d after use. */ + +void *qoi_encode(const void *data, const qoi_desc *desc, int *out_len); + + +/* Decode a QOI image from memory. + +The function either returns NULL on failure (invalid parameters or malloc +failed) or a pointer to the decoded pixels. On success, the qoi_desc struct +is filled with the description from the file header. + +The returned pixel data should be free()d after use. */ + +void *qoi_decode(const void *data, int size, qoi_desc *desc, int channels); + + +#ifdef __cplusplus +} +#endif +#endif /* QOI_H */ + + +/* ----------------------------------------------------------------------------- +Implementation */ + +#ifdef QOI_IMPLEMENTATION +#include +#include + +#ifndef QOI_MALLOC + #define QOI_MALLOC(sz) malloc(sz) + #define QOI_FREE(p) free(p) +#endif +#ifndef QOI_ZEROARR + #define QOI_ZEROARR(a) memset((a),0,sizeof(a)) +#endif + +#define QOI_OP_INDEX 0x00 /* 00xxxxxx */ +#define QOI_OP_DIFF 0x40 /* 01xxxxxx */ +#define QOI_OP_LUMA 0x80 /* 10xxxxxx */ +#define QOI_OP_RUN 0xc0 /* 11xxxxxx */ +#define QOI_OP_RGB 0xfe /* 11111110 */ +#define QOI_OP_RGBA 0xff /* 11111111 */ + +#define QOI_MASK_2 0xc0 /* 11000000 */ + +#define QOI_COLOR_HASH(C) (C.rgba.r*3 + C.rgba.g*5 + C.rgba.b*7 + C.rgba.a*11) +#define QOI_MAGIC \ + (((unsigned int)'q') << 24 | ((unsigned int)'o') << 16 | \ + ((unsigned int)'i') << 8 | ((unsigned int)'f')) +#define QOI_HEADER_SIZE 14 + +/* 2GB is the max file size that this implementation can safely handle. We guard +against anything larger than that, assuming the worst case with 5 bytes per +pixel, rounded down to a nice clean value. 400 million pixels ought to be +enough for anybody. */ +#define QOI_PIXELS_MAX ((unsigned int)400000000) + +typedef union { + struct { unsigned char r, g, b, a; } rgba; + unsigned int v; +} qoi_rgba_t; + +static const unsigned char qoi_padding[8] = {0,0,0,0,0,0,0,1}; + +static void qoi_write_32(unsigned char *bytes, int *p, unsigned int v) { + bytes[(*p)++] = (0xff000000 & v) >> 24; + bytes[(*p)++] = (0x00ff0000 & v) >> 16; + bytes[(*p)++] = (0x0000ff00 & v) >> 8; + bytes[(*p)++] = (0x000000ff & v); +} + +static unsigned int qoi_read_32(const unsigned char *bytes, int *p) { + unsigned int a = bytes[(*p)++]; + unsigned int b = bytes[(*p)++]; + unsigned int c = bytes[(*p)++]; + unsigned int d = bytes[(*p)++]; + return a << 24 | b << 16 | c << 8 | d; +} + +void *qoi_encode(const void *data, const qoi_desc *desc, int *out_len) { + int i, max_size, p, run; + int px_len, px_end, px_pos, channels; + unsigned char *bytes; + const unsigned char *pixels; + qoi_rgba_t index[64]; + qoi_rgba_t px, px_prev; + + if ( + data == NULL || out_len == NULL || desc == NULL || + desc->width == 0 || desc->height == 0 || + desc->channels < 3 || desc->channels > 4 || + desc->colorspace > 1 || + desc->height >= QOI_PIXELS_MAX / desc->width + ) { + return NULL; + } + + max_size = + desc->width * desc->height * (desc->channels + 1) + + QOI_HEADER_SIZE + sizeof(qoi_padding); + + p = 0; + bytes = (unsigned char *) QOI_MALLOC(max_size); + if (!bytes) { + return NULL; + } + + qoi_write_32(bytes, &p, QOI_MAGIC); + qoi_write_32(bytes, &p, desc->width); + qoi_write_32(bytes, &p, desc->height); + bytes[p++] = desc->channels; + bytes[p++] = desc->colorspace; + + + pixels = (const unsigned char *)data; + + QOI_ZEROARR(index); + + run = 0; + px_prev.rgba.r = 0; + px_prev.rgba.g = 0; + px_prev.rgba.b = 0; + px_prev.rgba.a = 255; + px = px_prev; + + px_len = desc->width * desc->height * desc->channels; + px_end = px_len - desc->channels; + channels = desc->channels; + + for (px_pos = 0; px_pos < px_len; px_pos += channels) { + if (channels == 4) { + px = *(qoi_rgba_t *)(pixels + px_pos); + } + else { + px.rgba.r = pixels[px_pos + 0]; + px.rgba.g = pixels[px_pos + 1]; + px.rgba.b = pixels[px_pos + 2]; + } + + if (px.v == px_prev.v) { + run++; + if (run == 62 || px_pos == px_end) { + bytes[p++] = QOI_OP_RUN | (run - 1); + run = 0; + } + } + else { + int index_pos; + + if (run > 0) { + bytes[p++] = QOI_OP_RUN | (run - 1); + run = 0; + } + + index_pos = QOI_COLOR_HASH(px) % 64; + + if (index[index_pos].v == px.v) { + bytes[p++] = QOI_OP_INDEX | index_pos; + } + else { + index[index_pos] = px; + + if (px.rgba.a == px_prev.rgba.a) { + signed char vr = px.rgba.r - px_prev.rgba.r; + signed char vg = px.rgba.g - px_prev.rgba.g; + signed char vb = px.rgba.b - px_prev.rgba.b; + + signed char vg_r = vr - vg; + signed char vg_b = vb - vg; + + if ( + vr > -3 && vr < 2 && + vg > -3 && vg < 2 && + vb > -3 && vb < 2 + ) { + bytes[p++] = QOI_OP_DIFF | (vr + 2) << 4 | (vg + 2) << 2 | (vb + 2); + } + else if ( + vg_r > -9 && vg_r < 8 && + vg > -33 && vg < 32 && + vg_b > -9 && vg_b < 8 + ) { + bytes[p++] = QOI_OP_LUMA | (vg + 32); + bytes[p++] = (vg_r + 8) << 4 | (vg_b + 8); + } + else { + bytes[p++] = QOI_OP_RGB; + bytes[p++] = px.rgba.r; + bytes[p++] = px.rgba.g; + bytes[p++] = px.rgba.b; + } + } + else { + bytes[p++] = QOI_OP_RGBA; + bytes[p++] = px.rgba.r; + bytes[p++] = px.rgba.g; + bytes[p++] = px.rgba.b; + bytes[p++] = px.rgba.a; + } + } + } + px_prev = px; + } + + for (i = 0; i < (int)sizeof(qoi_padding); i++) { + bytes[p++] = qoi_padding[i]; + } + + *out_len = p; + return bytes; +} + +void *qoi_decode(const void *data, int size, qoi_desc *desc, int channels) { + const unsigned char *bytes; + unsigned int header_magic; + unsigned char *pixels; + qoi_rgba_t index[64]; + qoi_rgba_t px; + int px_len, chunks_len, px_pos; + int p = 0, run = 0; + + if ( + data == NULL || desc == NULL || + (channels != 0 && channels != 3 && channels != 4) || + size < QOI_HEADER_SIZE + (int)sizeof(qoi_padding) + ) { + return NULL; + } + + bytes = (const unsigned char *)data; + + header_magic = qoi_read_32(bytes, &p); + desc->width = qoi_read_32(bytes, &p); + desc->height = qoi_read_32(bytes, &p); + desc->channels = bytes[p++]; + desc->colorspace = bytes[p++]; + + if ( + desc->width == 0 || desc->height == 0 || + desc->channels < 3 || desc->channels > 4 || + desc->colorspace > 1 || + header_magic != QOI_MAGIC || + desc->height >= QOI_PIXELS_MAX / desc->width + ) { + return NULL; + } + + if (channels == 0) { + channels = desc->channels; + } + + px_len = desc->width * desc->height * channels; + pixels = (unsigned char *) QOI_MALLOC(px_len); + if (!pixels) { + return NULL; + } + + QOI_ZEROARR(index); + px.rgba.r = 0; + px.rgba.g = 0; + px.rgba.b = 0; + px.rgba.a = 255; + + chunks_len = size - (int)sizeof(qoi_padding); + for (px_pos = 0; px_pos < px_len; px_pos += channels) { + if (run > 0) { + run--; + } + else if (p < chunks_len) { + int b1 = bytes[p++]; + + if (b1 == QOI_OP_RGB) { + px.rgba.r = bytes[p++]; + px.rgba.g = bytes[p++]; + px.rgba.b = bytes[p++]; + } + else if (b1 == QOI_OP_RGBA) { + px.rgba.r = bytes[p++]; + px.rgba.g = bytes[p++]; + px.rgba.b = bytes[p++]; + px.rgba.a = bytes[p++]; + } + else if ((b1 & QOI_MASK_2) == QOI_OP_INDEX) { + px = index[b1]; + } + else if ((b1 & QOI_MASK_2) == QOI_OP_DIFF) { + px.rgba.r += ((b1 >> 4) & 0x03) - 2; + px.rgba.g += ((b1 >> 2) & 0x03) - 2; + px.rgba.b += ( b1 & 0x03) - 2; + } + else if ((b1 & QOI_MASK_2) == QOI_OP_LUMA) { + int b2 = bytes[p++]; + int vg = (b1 & 0x3f) - 32; + px.rgba.r += vg - 8 + ((b2 >> 4) & 0x0f); + px.rgba.g += vg; + px.rgba.b += vg - 8 + (b2 & 0x0f); + } + else if ((b1 & QOI_MASK_2) == QOI_OP_RUN) { + run = (b1 & 0x3f); + } + + index[QOI_COLOR_HASH(px) % 64] = px; + } + + if (channels == 4) { + *(qoi_rgba_t*)(pixels + px_pos) = px; + } + else { + pixels[px_pos + 0] = px.rgba.r; + pixels[px_pos + 1] = px.rgba.g; + pixels[px_pos + 2] = px.rgba.b; + } + } + + return pixels; +} + +#ifndef QOI_NO_STDIO +#include + +int qoi_write(const char *filename, const void *data, const qoi_desc *desc) { + FILE *f = fopen(filename, "wb"); + int size; + void *encoded; + + if (!f) { + return 0; + } + + encoded = qoi_encode(data, desc, &size); + if (!encoded) { + fclose(f); + return 0; + } + + fwrite(encoded, 1, size, f); + fclose(f); + + QOI_FREE(encoded); + return size; +} + +void *qoi_read(const char *filename, qoi_desc *desc, int channels) { + FILE *f = fopen(filename, "rb"); + int size, bytes_read; + void *pixels, *data; + + if (!f) { + return NULL; + } + + fseek(f, 0, SEEK_END); + size = ftell(f); + if (size <= 0) { + fclose(f); + return NULL; + } + fseek(f, 0, SEEK_SET); + + data = QOI_MALLOC(size); + if (!data) { + fclose(f); + return NULL; + } + + bytes_read = fread(data, 1, size, f); + fclose(f); + + pixels = qoi_decode(data, bytes_read, desc, channels); + QOI_FREE(data); + return pixels; +} + +#endif /* QOI_NO_STDIO */ +#endif /* QOI_IMPLEMENTATION */ diff --git a/src/qoi/qoilib.c b/src/qoi/qoilib.c new file mode 100644 index 00000000000..e3aa809c74c --- /dev/null +++ b/src/qoi/qoilib.c @@ -0,0 +1,6 @@ +// PrusaSlicer specific: +// Include and compile QOI library. + +#define QOI_IMPLEMENTATION +#define QOI_NO_STDIO +#include "qoi.h" diff --git a/src/slic3r/GUI/Tab.cpp b/src/slic3r/GUI/Tab.cpp index dbadbe40a7c..d3ddb0db9f2 100644 --- a/src/slic3r/GUI/Tab.cpp +++ b/src/slic3r/GUI/Tab.cpp @@ -3142,6 +3142,7 @@ void TabPrinter::build_fff() option = optgroup->get_option("thumbnails"); option.opt.full_width = true; optgroup->append_single_option_line(option); + optgroup->append_single_option_line("thumbnails_format"); optgroup->append_single_option_line("use_relative_e_distances"); optgroup->append_single_option_line("use_firmware_retraction"); optgroup->append_single_option_line("scan_first_layer"); From d0ccc5ee96f905dd1f59297199d8de5b1d06e574 Mon Sep 17 00:00:00 2001 From: ablegods <85563455+ablegods@users.noreply.github.com> Date: Tue, 17 Oct 2023 20:03:11 +0800 Subject: [PATCH 2/2] Updated TW translation (#2433) Changed some localization strings to be more appropriate --- localization/i18n/zh_TW/OrcaSlicer_zh_TW.po | 1005 ++++++++++--------- 1 file changed, 506 insertions(+), 499 deletions(-) diff --git a/localization/i18n/zh_TW/OrcaSlicer_zh_TW.po b/localization/i18n/zh_TW/OrcaSlicer_zh_TW.po index 2c9d1f7ac79..bf6eb49fc5f 100644 --- a/localization/i18n/zh_TW/OrcaSlicer_zh_TW.po +++ b/localization/i18n/zh_TW/OrcaSlicer_zh_TW.po @@ -162,10 +162,10 @@ msgid "Height Range" msgstr "高度範圍" msgid "Vertical" -msgstr "" +msgstr "垂直" msgid "Horizontal" -msgstr "" +msgstr "水平" msgid "Remove painted color" msgstr "移除已繪製的顏色" @@ -416,7 +416,7 @@ msgstr "簡化率" msgid "" "Processing model '%1%' with more than 1M triangles could be slow. It is " "highly recommended to simplify the model." -msgstr "處理超出1M個三角形面片的模型“%1%”可能會很慢。強烈建議簡化模型。" +msgstr "處理超出 1M 個三角形面片的模型“%1%”可能會很慢。強烈建議簡化模型。" msgid "Simplify model" msgstr "簡化模型" @@ -425,7 +425,7 @@ msgid "Simplify" msgstr "簡化" msgid "Simplification is currently only allowed when a single part is selected" -msgstr "僅支援對單個零件做簡化" +msgstr "僅支援對單一零件做簡化" msgid "Error" msgstr "錯誤" @@ -481,7 +481,7 @@ msgid "Block seam" msgstr "遮蔽Z縫" msgid "Seam painting" -msgstr "Z縫繪製" +msgstr "繪製Z縫" msgid "Remove selection" msgstr "移除繪製" @@ -519,7 +519,7 @@ msgid "" msgstr "內嵌深度" msgid "Surface" -msgstr "附著曲面" +msgstr "附著於曲面" msgid "Horizontal text" msgstr "水平文字" @@ -535,7 +535,7 @@ msgstr "未定義" #, boost-format msgid "%1% was replaced with %2%" -msgstr "%1%已被%2%替換" +msgstr "%1% 已被 %2% 替換" msgid "The configuration may be generated by a newer version of OrcaSlicer." msgstr "此配置可能由新版本的 Orcaslicer 產生" @@ -544,7 +544,7 @@ msgid "Some values have been replaced. Please check them:" msgstr "部分數值已被替換,請檢查:" msgid "Process" -msgstr "工藝" +msgstr "列印參數" msgid "Filament" msgstr "線材" @@ -577,7 +577,7 @@ msgid "" "OrcaSlicer will terminate because of a localization error. It will be " "appreciated if you report the specific scenario this issue happened." msgstr "" -"遇到本地化錯誤,OrcaSlicer 即將停止並且結束。希望您可以報告發生此問題的具體狀" +"遇到語系本地化錯誤,OrcaSlicer 即將停止並且結束。希望您可以報告發生此問題的具體狀" "況,我們將非常感激。" msgid "Critical error" @@ -591,7 +591,7 @@ msgid "Downloading Bambu Network Plug-in" msgstr "正在下載Bambu網路套件" msgid "Login information expired. Please login again." -msgstr "登錄資訊過期。請重新登入。" +msgstr "登入資訊已過期。請重新登入。" msgid "Incorrect password" msgstr "密碼不正確" @@ -615,7 +615,7 @@ msgid "" "OrcaSlicer configuration file may be corrupted and is not abled to be parsed." "Please delete the file and try again." msgstr "" -"OrcaSlicer 組態檔可能已損壞而無法解析。請刪除此文件並重新啟動 OrcaSlicer。" +"OrcaSlicer 組態檔可能已損壞而無法解析。請刪除此檔案並重新啟動 OrcaSlicer。" #, c-format, boost-format msgid "" @@ -652,16 +652,16 @@ msgid "Loading a mode view" msgstr "載入模式視圖" msgid "Choose one file (3mf):" -msgstr "選擇一個文件(3mf):" +msgstr "選擇一個檔案(3mf):" msgid "Choose one or more files (3mf/step/stl/svg/obj/amf/usd*/abc/ply):" -msgstr "" +msgstr "選擇一個或多個檔案 (3mf/step/stl/svg/obj/amf/usd*/abc/ply):" msgid "Choose one or more files (3mf/step/stl/svg/obj/amf):" -msgstr "選擇一個或多個文件(3mf/step/stl/svg/obj/amf):" +msgstr "選擇一個或多個檔案(3mf/step/stl/svg/obj/amf):" msgid "Choose one file (gcode/3mf):" -msgstr "選擇一個文件(gcode/3mf)" +msgstr "選擇一個檔案(gcode/3mf)" msgid "Some presets are modified." msgstr "部分預設已被修改。" @@ -675,10 +675,10 @@ msgid "User logged out" msgstr "使用者登出" msgid "new or open project file is not allowed during the slicing process!" -msgstr "在切片過程不允許新建或打開項目文件!" +msgstr "在執行切片過程中不允許新增或打開專案項目!" msgid "Open Project" -msgstr "打開項目" +msgstr "打開專案項目" msgid "" "The version of Orca Slicer is too low and needs to be updated to the latest " @@ -716,19 +716,19 @@ msgid "Ongoing uploads" msgstr "正在進行的上傳" msgid "Select a G-code file:" -msgstr "選擇一個G-code文件:" +msgstr "選擇一個 G-code 檔案:" msgid "Import File" -msgstr "匯入文件" +msgstr "匯入檔案" msgid "Delete" msgstr "刪除" msgid "Choose files" -msgstr "選擇文件" +msgstr "選擇檔案" msgid "New Folder" -msgstr "新增文件夾" +msgstr "新增資料夾" msgid "Open" msgstr "打開" @@ -756,7 +756,7 @@ msgid "Support" msgstr "支撐" msgid "Flush options" -msgstr "換料沖刷選項" +msgstr "多色列印換料選項" msgid "Speed" msgstr "速度" @@ -825,7 +825,7 @@ msgid "Del" msgstr "刪除" msgid "Delete the selected object" -msgstr "刪除所選對象" +msgstr "刪除所選物件" msgid "Edit Text" msgstr "編輯文字" @@ -873,7 +873,7 @@ msgid "Fill bed with copies" msgstr "鋪滿列印板" msgid "Fill the remaining area of bed with copies of the selected object" -msgstr "用選定對象的副本填充床的剩餘區域" +msgstr "用選定對象的副本鋪滿列印板的剩餘區域" msgid "Printable" msgstr "可列印的" @@ -907,28 +907,28 @@ msgstr "預設" #, c-format, boost-format msgid "Filament %d" -msgstr "線材%d" +msgstr "線材 %d" msgid "active" msgstr "活動的" msgid "Scale to build volume" -msgstr "縮放到構建空間大小" +msgstr "縮放到列印空間範圍大小" msgid "Scale an object to fit the build volume" -msgstr "縮放對象以適應構建空間大小" +msgstr "縮放物件以適應列印空間範圍大小" msgid "Flush Options" -msgstr "換料沖刷選項" +msgstr "多色打印換料選項" msgid "Flush into objects' infill" -msgstr "沖刷到對象的填充" +msgstr "將換色的廢料使用在物件的填充" msgid "Flush into this object" -msgstr "沖刷到這個對象" +msgstr "將換色的廢料使用在這個物件" msgid "Flush into objects' support" -msgstr "沖刷到對象的支撐" +msgstr "將換色的廢料使用在物件的支撐" msgid "Edit in Parameter Table" msgstr "在參數表格中編輯" @@ -949,10 +949,10 @@ msgid "Assemble" msgstr "組合" msgid "Assemble the selected objects to an object with multiple parts" -msgstr "組合所選對象為一個多零件對象" +msgstr "組合所選物件為一個多零件物件" msgid "Assemble the selected objects to an object with single part" -msgstr "組合所選對象為一個單零件對象" +msgstr "組合所選物件為一個單零件物件" msgid "Mesh boolean" msgstr "網格布林值操作" @@ -982,7 +982,7 @@ msgid "Mirror" msgstr "鏡像" msgid "Mirror object" -msgstr "鏡像對象" +msgstr "鏡像物件" msgid "Invalidate cut info" msgstr "解除切割關係" @@ -994,46 +994,46 @@ msgid "Show Labels" msgstr "顯示標籤" msgid "To objects" -msgstr "拆分到對象" +msgstr "拆分到物件" msgid "Split the selected object into multiple objects" -msgstr "拆分所選對象為多個對象" +msgstr "拆分所選物件為多個物件" msgid "To parts" msgstr "到零件" msgid "Split the selected object into multiple parts" -msgstr "拆分所選對象為多個零件" +msgstr "拆分所選物件為多個零件" msgid "Split" msgstr "拆分" msgid "Split the selected object" -msgstr "拆分所選對象" +msgstr "拆分所選物件" msgid "Auto orientation" msgstr "自動定向" msgid "Auto orient the object to improve print quality." -msgstr "自動調整對象朝向以提高列印質量。" +msgstr "自動調整物件方向以提高列印質量。" msgid "Split the selected object into mutiple objects" -msgstr "拆分所選對象為多個對象" +msgstr "拆分所選物件為多個物件" msgid "Split the selected object into mutiple parts" -msgstr "拆分所選對象為多個零件" +msgstr "拆分所選物件為多個零件" msgid "Select All" msgstr "全選" msgid "select all objects on current plate" -msgstr "全選當前盤對象" +msgstr "全選當前盤物件" msgid "Delete All" msgstr "刪除所有" msgid "delete all objects on current plate" -msgstr "刪除當前盤所有對象" +msgstr "刪除當前盤所有物件" msgid "Arrange" msgstr "自動擺放" @@ -1042,10 +1042,10 @@ msgid "arrange current plate" msgstr "在當前盤執行自動擺放" msgid "Auto Rotate" -msgstr "自動朝向" +msgstr "自動旋轉方向" msgid "auto rotate current plate" -msgstr "在當前盤執行自動朝向" +msgstr "在當前盤執行自動旋轉方向" msgid "Delete Plate" msgstr "刪除盤" @@ -1063,16 +1063,16 @@ msgid "Center" msgstr "居中" msgid "Edit Process Settings" -msgstr "編輯工藝參數" +msgstr "編輯列印參數" msgid "Edit print parameters for a single object" -msgstr "編輯單個對象的列印參數" +msgstr "編輯單個物件的列印參數" msgid "Change Filament" msgstr "更換線材" msgid "Set Filament for selected items" -msgstr "設定線材為所選項目" +msgstr "為所選項目設定使用的線材" msgid "current" msgstr "當前" @@ -1111,37 +1111,37 @@ msgid_plural "%1$d non-manifold edges" msgstr[0] "%1$d 非流形邊" msgid "Right click the icon to fix model object" -msgstr "右鍵點擊此圖示可修復模型對象" +msgstr "滑鼠右鍵點擊此圖示可修復模型對象" msgid "Right button click the icon to drop the object settings" -msgstr "右鍵點擊此圖示以放棄對象的設定參數" +msgstr "滑鼠右鍵點擊此圖示以放棄對象的設定參數" msgid "Click the icon to reset all settings of the object" -msgstr "點擊此圖示可重設對象的所有設定參數" +msgstr "滑鼠左鍵點擊此圖示可重設對象的所有設定參數" msgid "Right button click the icon to drop the object printable property" -msgstr "右鍵點擊此圖示以捨棄對象的可列印屬性" +msgstr "滑鼠右鍵點擊此圖示以捨棄對象的可列印屬性" msgid "Click the icon to toggle printable property of the object" -msgstr "點擊此圖示可切換這個對象的可列印屬性" +msgstr "滑鼠左點擊此圖示可切換這個對象的可列印屬性" msgid "Click the icon to edit support painting of the object" -msgstr "點擊此圖示可編輯這個對象的支撐繪製" +msgstr "滑鼠左鍵點擊此圖示可編輯這個對象的支撐繪製" msgid "Click the icon to edit color painting of the object" -msgstr "點擊此圖示可編輯這個對象的顏色繪製" +msgstr "滑鼠左鍵點擊此圖示可編輯這個對象的顏色繪製" msgid "Click the icon to shift this object to the bed" -msgstr "點擊這個圖示可將對象移動到熱床上" +msgstr "滑鼠左鍵點擊這個圖示可將對象移動到熱床上" msgid "Loading file" -msgstr "載入文件中" +msgstr "載入檔案中" msgid "Error!" msgstr "錯誤!" msgid "Failed to get the model data in the current file." -msgstr "無法獲取當前文件中的模型數據。" +msgstr "取得目前檔案中的模型資料失敗。" msgid "Generic" msgstr "通用" @@ -1150,26 +1150,26 @@ msgid "Add Modifier" msgstr "新增修改器" msgid "Switch to per-object setting mode to edit modifier settings." -msgstr "切換到對象模式以編輯修改器的設定參數。" +msgstr "切換到每個物件設定模式以編輯修改器的設定參數。" msgid "" "Switch to per-object setting mode to edit process settings of selected " "objects." -msgstr "切換到對象設置模式,以編輯所選對象的工藝參數" +msgstr "切換到每個物件設定模式,以編輯所選物件的列印參數" msgid "Delete connector from object which is a part of cut" -msgstr "刪除的連接件屬於切割對象的一部分" +msgstr "刪除的連接件屬於切割物件的一部分" msgid "Delete solid part from object which is a part of cut" -msgstr "刪除的實體屬於切割對象的一部分" +msgstr "刪除的實體屬於切割物件的一部分" msgid "Delete negative volume from object which is a part of cut" -msgstr "刪除的負體積屬於切割對象的一部分" +msgstr "刪除的負體積屬於切割物件的一部分" msgid "" "To save cut correspondence you can delete all connectors from all related " "objects." -msgstr "為保證切割關係,您可以將所有關聯對象的連接件一起刪除。" +msgstr "為保證切割關係,您可以將所有關聯物件的連接件一起刪除。" msgid "" "This action will break a cut correspondence.\n" @@ -1186,10 +1186,10 @@ msgid "Delete all connectors" msgstr "刪除所有連接件" msgid "Deleting the last solid part is not allowed." -msgstr "不允許刪除對象的最後一個實體零件。" +msgstr "不允許刪除物件的最後一個實體零件。" msgid "The target object contains only one part and can not be splited." -msgstr "目標對象僅包含一個零件,無法被拆分。" +msgstr "目標物件僅包含一個零件,無法被拆分。" msgid "Assembly" msgstr "組合體" @@ -1198,13 +1198,13 @@ msgid "Cut Connectors information" msgstr "切割連接件資訊" msgid "Object manipulation" -msgstr "操作對象" +msgstr "操作物件" msgid "Group manipulation" msgstr "操作組" msgid "Object Settings to modify" -msgstr "要修改的對象設定" +msgstr "要修改的物件設定" msgid "Part Settings to modify" msgstr "要修改的零件設定" @@ -1225,7 +1225,7 @@ msgid "Settings for height range" msgstr "高度範圍設定" msgid "Object" -msgstr "對象" +msgstr "物件" msgid "Part" msgstr "零件" @@ -1238,7 +1238,7 @@ msgstr "選擇衝突" msgid "" "If first selected item is an object, the second one should also be object." -msgstr "如果第一個選擇的是對象,那麼第二個選擇的也必須是對象。" +msgstr "如果第一個選擇的是物件,那麼第二個選擇的也必須是物件。" msgid "" "If first selected item is a part, the second one should be part in the same " @@ -1246,7 +1246,7 @@ msgid "" msgstr "如果第一個選擇的是零件,那麼第二個選擇的也必須是同一個對象中的零件。" msgid "The type of the last solid object part is not to be changed." -msgstr "不允許修改對象中最後一個實體零件的類型。" +msgstr "不允許修改物件中最後一個實體零件的類型。" msgid "Negative Part" msgstr "負零件" @@ -1273,21 +1273,21 @@ msgid "Renaming" msgstr "重新命名" msgid "Repairing model object" -msgstr "修復模型對象" +msgstr "修復模型物件" msgid "Following model object has been repaired" msgid_plural "Following model objects have been repaired" -msgstr[0] "以下模型對象已被修復" +msgstr[0] "以下模型物件已被修復" msgid "Failed to repair folowing model object" msgid_plural "Failed to repair folowing model objects" -msgstr[0] "以下模型對象修復失敗" +msgstr[0] "以下模型物件修復失敗" msgid "Repairing was canceled" msgstr "修復被取消" msgid "Additional process preset" -msgstr "附加工藝預設" +msgstr "附加參數預設" msgid "Remove parameter" msgstr "刪除參數" @@ -1356,7 +1356,7 @@ msgid "Brim" msgstr "Brim" msgid "Object/Part Setting" -msgstr "對象/零件 設定值" +msgstr "物件/零件 設定值" msgid "Reset parameter" msgstr "重設參數" @@ -1371,13 +1371,13 @@ msgid "More" msgstr "詳情" msgid "Open Preferences." -msgstr "打開首選項" +msgstr "偏好設定" msgid "Open next tip." msgstr "打開下一條提示" msgid "Open Documentation in web browser." -msgstr "在web瀏覽器中打開文件。" +msgstr "在網頁瀏覽器中打開檔案。" msgid "Pause:" msgstr "暫停" @@ -1386,22 +1386,22 @@ msgid "Custom Template:" msgstr "自訂模板:" msgid "Custom G-code:" -msgstr "自訂G-code:" +msgstr "自訂 G-code:" msgid "Custom G-code" msgstr "自訂 G-code" msgid "Enter Custom G-code used on current layer:" -msgstr "輸入當前層上使用的自訂G-code:" +msgstr "輸入當前層上使用的自訂 G-code:" msgid "OK" msgstr "確認" msgid "Jump to Layer" -msgstr "跳轉到層" +msgstr "轉換到層" msgid "Jump to layer" -msgstr "跳轉到層" +msgstr "轉換到層" msgid "Please enter the layer number" msgstr "請輸入層數" @@ -1413,16 +1413,16 @@ msgid "Insert a pause command at the beginning of this layer." msgstr "在該層的起始位置插入暫停。" msgid "Add Custom G-code" -msgstr "新增自訂G-code" +msgstr "新增自訂 G-code" msgid "Insert custom G-code at the beginning of this layer." -msgstr "在該層的起始位置插入自訂G-code。" +msgstr "在該層的起始位置插入自訂 G-code。" msgid "Add Custom Template" msgstr "新增自訂模板" msgid "Insert template custom G-code at the beginning of this layer." -msgstr "在該層的起始位置插入模板自訂G-code。" +msgstr "在該層的起始位置插入模板自訂 G-code。" msgid "Filament " msgstr "線材" @@ -1437,10 +1437,10 @@ msgid "Delete Custom Template" msgstr "刪除自訂模板" msgid "Edit Custom G-code" -msgstr "編輯自訂G-code" +msgstr "編輯自訂 G-code" msgid "Delete Custom G-code" -msgstr "刪除自訂G-code" +msgstr "刪除自訂 G-code" msgid "Delete Filament Change" msgstr "刪除線材更換" @@ -1455,16 +1455,16 @@ msgid "Failed to connect to the server" msgstr "無法連接伺服器" msgid "Check cloud service status" -msgstr "檢查雲服務狀態" +msgstr "檢查雲端服務狀態" msgid "code" msgstr "code" msgid "Failed to connect to cloud service" -msgstr "無法連接到雲服務" +msgstr "無法連接到雲端服務" msgid "Please click on the hyperlink above to view the cloud service status" -msgstr "請點擊上方的超連結以查看雲服務狀態" +msgstr "請點擊上方的超連結以查看雲端服務狀態" msgid "Failed to connect to the printer" msgstr "無法連接3D列印機" @@ -1473,7 +1473,7 @@ msgid "Connection to printer failed" msgstr "連接3D列印機失敗" msgid "Please check the network connection of the printer and Studio." -msgstr "請檢查3D列印機和工作室的網路連接" +msgstr "請檢查3D列印機和 Bambu Studio 的網路連接" msgid "Connecting..." msgstr "連線中..." @@ -1491,10 +1491,10 @@ msgid "AMS" msgstr "AMS" msgid "Auto Refill" -msgstr "自動補給" +msgstr "自動補充" msgid "AMS not connected" -msgstr "AMS 未連接" +msgstr "AMS 尚未連接" msgid "Load Filament" msgstr "進料" @@ -1542,7 +1542,7 @@ msgid "Push new filament into extruder" msgstr "送出新的線材到擠出機" msgid "Purge old filament" -msgstr "沖刷舊線材" +msgstr "清除舊線材" msgid "Feed Filament" msgstr "" @@ -1551,7 +1551,7 @@ msgid "Confirm extruded" msgstr "" msgid "Check filament location" -msgstr "" +msgstr "檢查線材位置" msgid "Grab new filament" msgstr "咬入線材" @@ -1559,7 +1559,7 @@ msgstr "咬入線材" msgid "" "Choose an AMS slot then press \"Load\" or \"Unload\" button to automatically " "load or unload filiament." -msgstr "選擇1個 AMS 槽位,然後點擊進料/退料按鈕以自動進料/退料。" +msgstr "選擇 1 個 AMS 槽位,然後點擊進料/退料按鈕以自動進料/退料。" msgid "Edit" msgstr "編輯" @@ -1568,11 +1568,11 @@ msgid "" "All the selected objects are on the locked plate,\n" "We can not do auto-arrange on these objects." msgstr "" -"所有選中的對象都處於被鎖定的盤上,\n" -"無法對這些對象做自動擺盤。" +"所有選中的物件都處於被鎖定的盤上,\n" +"無法對這些物件做自動擺盤。" msgid "No arrangable objects are selected." -msgstr "沒有可擺盤的對象被選中。" +msgstr "未選擇可排列的物件象。" msgid "" "This plate is locked,\n" @@ -1584,7 +1584,7 @@ msgstr "自動擺放中..." msgid "" "Arrange failed. Found some exceptions when processing object geometries." -msgstr "自動擺放失敗,處理對象幾何物件時遇到異常。" +msgstr "自動擺放失敗,處理物件位置時遇到異常。" msgid "Arranging" msgstr "自動擺放" @@ -1623,10 +1623,10 @@ msgstr "" "無法對其進行自動朝向。" msgid "Orienting..." -msgstr "自動朝向中..." +msgstr "自動旋轉方向..." msgid "Orienting" -msgstr "自動朝向中..." +msgstr "自動旋轉方向..." msgid "Filling bed " msgstr "填充熱床" @@ -1653,7 +1653,7 @@ msgid "Please check the printer network connection." msgstr "請檢查3D列印機的網路連接。" msgid "Abnormal print file data. Please slice again." -msgstr "列印文件資料異常,請重新切片" +msgstr "列印檔案資料異常,請重新切片" msgid "Task canceled." msgstr "任務已取消。" @@ -1665,18 +1665,18 @@ msgid "Cloud service connection failed. Please try again." msgstr "雲端服務連接失敗,請重試" msgid "Print file not found. please slice again." -msgstr "未找到列印文件,請重新切片。" +msgstr "未找到列印檔案,請重新切片。" msgid "" "The print file exceeds the maximum allowable size (1GB). Please simplify the " "model and slice again." -msgstr "列印文件超過最大允許大小(1GB),請簡化模型後重新切片。" +msgstr "列印檔案超過最大允許大小(1GB),請簡化模型後重新切片。" msgid "Failed to send the print job. Please try again." msgstr "無法傳送列印作業,請重試。" msgid "Failed to upload file to ftp. Please try again." -msgstr "上傳文件至 FTP 失敗,請重試。" +msgstr "上傳檔案至 FTP 失敗,請重試。" msgid "" "Check the current status of the bambu server by clicking on the link above." @@ -1685,15 +1685,15 @@ msgstr "點擊上方的連結檢查 Bambu 伺服器的當前狀態。" msgid "" "The size of the print file is too large. Please adjust the file size and try " "again." -msgstr "列印文件的大小過大,請調整檔案大小後重試。" +msgstr "列印檔案過大,請調整檔案大小後重試。" msgid "Print file not found, Please slice it again and send it for printing." -msgstr "未找到列印文件,請重新切片後再傳送列印。" +msgstr "未找到列印檔案,請重新切片後再傳送列印。" msgid "" "Failed to upload print file to FTP. Please check the network status and try " "again." -msgstr "無法將列印文件上傳至 FTP。請檢查網路狀態並重試。" +msgstr "無法將列印檔案上傳至 FTP。請檢查網路狀態並重試。" msgid "Sending print job over LAN" msgstr "正在通過區域網路傳送列印作業" @@ -1712,20 +1712,20 @@ msgstr "正在傳送列印組態" #, c-format, boost-format msgid "Successfully sent. Will automatically jump to the device page in %ss" -msgstr "已傳送完成,即將自動跳轉到設備頁面(%s秒)" +msgstr "已傳送完成,即將自動轉換到設備頁面(%s秒)" #, c-format, boost-format msgid "Successfully sent. Will automatically jump to the next page in %ss" -msgstr "已成功傳送。將自動跳轉到%ss中的下一頁。" +msgstr "已成功傳送。將自動轉換到%ss中的下一頁。" msgid "An SD card needs to be inserted before printing via LAN." msgstr "透過區域網路列印之前需要插入SD記憶卡。" msgid "Sending gcode file over LAN" -msgstr "透過區域網路傳送gcode文件" +msgstr "透過區域網路傳送 gcode 檔案" msgid "Sending gcode file to sdcard" -msgstr "傳送gcode文件到SD記憶卡" +msgstr "傳送 gcode 檔案到SD記憶卡" #, c-format, boost-format msgid "Successfully sent. Close current page in %s s" @@ -1738,7 +1738,7 @@ msgid "Choose SLA archive:" msgstr "選擇 SLA 存檔:" msgid "Import file" -msgstr "匯入文件" +msgstr "匯入檔案" msgid "Import model and profile" msgstr "匯入模型和設定檔" @@ -1779,7 +1779,7 @@ msgid "" msgstr "匯入的 SLA 存檔不包含任何預設。當前的 SLA 預設被用作備用選項。" msgid "You cannot load SLA project with a multi-part object on the bed" -msgstr "您不能載入一個在床上有多個部件的 SLA 項目" +msgstr "您無法在床上載入包含多部分物件的 SLA 項目" msgid "Please check your object list before preset changing." msgstr "請在更改預設之前檢查您的物件清單。" @@ -1899,7 +1899,7 @@ msgid "Factors of Flow Dynamics Calibration" msgstr "動態流量係數校準" msgid "PA Profile" -msgstr "PA 配置文件" +msgstr "PA 配置檔" msgid "Factor K" msgstr "係數K" @@ -1978,7 +1978,7 @@ msgstr "" "數值填入係數K輸入框。" msgid "Save" -msgstr "保存" +msgstr "儲存" msgid "Last Step" msgstr "上一步" @@ -2023,7 +2023,7 @@ msgid "Print with the filament mounted on the back of chassis" msgstr "使用機箱背後掛載的線材列印" msgid "Cabin humidity" -msgstr "艙內濕度" +msgstr "AMS 內部濕度" msgid "" "Green means that AMS humidity is normal, orange represent humidity is high, " @@ -2045,24 +2045,24 @@ msgid "" "process. During this time, the indicator may not represent the chamber " "accurately." msgstr "" -"注意:當蓋子打開或更換乾燥劑包裝時,可能需要數小時或一晚才能吸收水分,低溫也" -"會減慢這一過程。在此期間,指示器的數值可能並不準確。" +"注意:當 AMS 蓋子打開或更換乾燥劑包裝時,可能需要數小時或一晚才能吸收水分,低溫也" +"會減慢這一過程。在此期間,濕度指示的數值可能並不準確。" msgid "" "Config which AMS slot should be used for a filament used in the print job" -msgstr "配置當前列印作業應使用哪個 AMS 槽位" +msgstr "配置列印作業中使用的線材應使用哪個 AMS 槽位" msgid "Filament used in this print job" -msgstr "當前列印使用的線材" +msgstr "目前列印作業中使用的線材" msgid "AMS slot used for this filament" -msgstr "當前線材對應的 AMS 槽位" +msgstr "目前線材對應的 AMS 槽位" msgid "Click to select AMS slot manually" -msgstr "點擊以手動選擇 AMS 槽位" +msgstr "滑鼠左鍵點擊以手動選擇 AMS 槽位" msgid "Do not Enable AMS" -msgstr "不啟用 AMS" +msgstr "不使用 AMS" msgid "Print using materials mounted on the back of the case" msgstr "使用安裝在機箱背面的線材進行列印" @@ -2076,7 +2076,7 @@ msgstr "採用掛載在機箱背部的線材列印" msgid "" "When the current material run out, the printer will continue to print in the " "following order." -msgstr "當前線材耗盡時,3D列印機將按照以下順序繼續列印。" +msgstr "當目前線材耗盡時,3D列印機將按照以下順序繼續列印。" msgid "Group" msgstr "組" @@ -2087,7 +2087,7 @@ msgid "" "(Currently supporting automatic supply of consumables with the same brand, " "material type, and color)" msgstr "" -"目前無相同的備用線材,暫時無法自動補給。\n" +"目前無相同的備用線材,暫時無法自動補充線材。\n" "(目前支援品牌、線材種類、顏色相同的線材的自動補給)" msgid "AMS Settings" @@ -2107,7 +2107,7 @@ msgid "" "Note: if new filament is inserted during printing, the AMS will not " "automatically read any information until printing is completed." msgstr "" -"注意:如果是在列印過程中插入新的線材,AMS 會在列印結束後自動讀取此線材信息。" +"注意:如果是在列印過程中插入新的線材,AMS 會在列印作業結束後自動讀取此線材信息。" msgid "" "When inserting a new filament, the AMS will not automatically read its " @@ -2145,7 +2145,7 @@ msgstr "" "量會自動更新。" msgid "AMS filament backup" -msgstr "AMS 線材備份" +msgstr "AMS 線材備用" msgid "" "AMS will continue to another spool with the same properties of filament " @@ -2153,7 +2153,7 @@ msgid "" msgstr "AMS 線材耗盡後將自動切換到屬性完全相同的線材" msgid "File" -msgstr "文件" +msgstr "檔案" msgid "Calibration" msgstr "校準" @@ -2161,12 +2161,12 @@ msgstr "校準" msgid "" "Failed to download the plug-in. Please check your firewall settings and vpn " "software, check and retry." -msgstr "外掛套件下載失敗。請檢查您的防火牆設置和 VPN 軟體,檢查後重試。" +msgstr "插件下載失敗。請檢查您的防火牆設置和 VPN 軟體,檢查後重試。" msgid "" "Failed to install the plug-in. Please check whether it is blocked or deleted " "by anti-virus software." -msgstr "安裝外掛套件失敗。請檢查是否被防毒軟體阻擋或刪除。" +msgstr "安裝插件失敗。請檢查是否被防毒軟體阻擋或刪除。" msgid "click here to see more info" msgstr "點擊這裡查看更多資訊" @@ -2185,13 +2185,13 @@ msgstr "回原點" msgid "" "A error occurred. Maybe memory of system is not enough or it's a bug of the " "program" -msgstr "發生錯誤。可能系統記憶體不足或者程式存在 bug。" +msgstr "發生錯誤。可能系統記憶體不足或者程式存在錯誤。" msgid "Please save project and restart the program. " -msgstr "請保存項目並重啟程式。" +msgstr "請儲存專案項目並重啟程式。" msgid "Processing G-Code from Previous file..." -msgstr "從之前的文件載入 G代碼..." +msgstr "從之前的檔案載入 G-Code..." msgid "Slicing complete" msgstr "切片完成" @@ -2218,7 +2218,7 @@ msgid "Stack overflow" msgstr "堆疊溢位" msgid "Unknown error when export G-code." -msgstr "匯出 G-code 文件發生未知錯誤。" +msgstr "匯出 G-code 檔案發生未知錯誤。" #, boost-format msgid "" @@ -2226,9 +2226,9 @@ msgid "" "Error message: %1%.\n" "Source file %2%." msgstr "" -"無法保存 Gcode 文件。\n" +"無法儲存 G-code 檔案。\n" "錯誤資訊:%1%。\n" -"源文件 %2%." +"原始檔 %2%." #, boost-format msgid "Succeed to export G-code to %1%" @@ -2238,7 +2238,7 @@ msgid "Running post-processing scripts" msgstr "執行後處理腳本" msgid "Copying of the temporary G-code to the output G-code failed" -msgstr "將臨時 G 代碼複製到輸出 G 代碼失敗" +msgstr "將臨時 G-Code 複製到輸出 G-Code 碼失敗" #, boost-format msgid "Scheduling upload to `%1%`. See Window -> Print Host Upload Queue" @@ -2273,7 +2273,7 @@ msgid "Custom" msgstr "自訂" msgid "Load shape from STL..." -msgstr "從 STL 文件載入形狀..." +msgstr "從 STL 檔案載入形狀..." msgid "Settings" msgstr "設定" @@ -2291,26 +2291,26 @@ msgid "Model" msgstr "模型" msgid "Choose an STL file to import bed shape from:" -msgstr "選擇熱床形狀的 STL 文件:" +msgstr "選擇熱床形狀的 STL 檔案:" msgid "Invalid file format." -msgstr "無效的文件格式。" +msgstr "無效的檔案格式。" msgid "Error! Invalid model" msgstr "錯誤!無效模型" msgid "The selected file contains no geometry." -msgstr "所選文件不包含任何幾何數據。" +msgstr "所選檔案不包含任何幾何圖形。" msgid "" "The selected file contains several disjoint areas. This is not supported." -msgstr "所選文件包含多個未連接的區域。不支援這種類型。" +msgstr "所選檔案包含多個未連接的區域。不支援這種類型。" msgid "Choose a file to import bed texture from (PNG/SVG):" -msgstr "選擇 (PNG/SVG) 文件作為熱床紋理:" +msgstr "選擇 (PNG/SVG) 檔案作為熱床紋理:" msgid "Choose an STL file to import bed model from:" -msgstr "選擇 STL 文件來匯入床模型:" +msgstr "選擇 STL 檔案來匯入床模型:" msgid "Bed Shape" msgstr "熱床形狀" @@ -2359,7 +2359,7 @@ msgid "" "\n" "The first layer height will be reset to 0.2." msgstr "" -"首層層高為無效的0值。\n" +"首層層高為無效的 0值。\n" "將被重設為0.2。" msgid "" @@ -2393,7 +2393,7 @@ msgid "" "Spiral mode only works when wall loops is 1, support is disabled, top shell " "layers is 0, sparse infill density is 0 and timelapse type is traditional." msgstr "" -"旋轉模式只能在外牆層數為1,關閉支撐,頂層層數為0,稀疏填充密度為0,傳統縮時攝" +"花瓶模式只能在外牆層數為1,關閉支撐,頂層層數為0,稀疏填充密度為0,傳統縮時攝" "影時有效。" msgid " But machines with I3 structure will not generate timelapse videos." @@ -2404,8 +2404,8 @@ msgid "" "Yes - Change these settings and enable spiral mode automatically\n" "No - Give up using spiral mode this time" msgstr "" -"自動調整這些設置?\n" -"是 - 自動調整這些設置並開啟旋轉模式\n" +"自動調整這些設定?\n" +"是 - 自動調整這些設定並開啟花瓶模式\n" "否 - 暫不使用旋轉模式" msgid "" @@ -2453,7 +2453,7 @@ msgid "" msgstr "" "切換到直線圖案?\n" "是 - 自動切換到直線圖案\n" -"否 - 自動將密度重設為預設的非100%值" +"否 - 自動將密度重設為預設的非 100% 值" msgid "" "While printing by Object, the extruder may collide skirt.\n" @@ -2476,7 +2476,7 @@ msgid "M400 pause" msgstr "M400 暫停" msgid "Paused due to filament runout" -msgstr "斷料暫停" +msgstr "線材斷料暫停" msgid "Heating hotend" msgstr "加熱熱端" @@ -2512,7 +2512,7 @@ msgid "Pause of front cover falling" msgstr "工具頭前蓋掉落暫停列印" msgid "Calibrating the micro lida" -msgstr "校準微型雷射" +msgstr "校準微型雷達" msgid "Calibrating extrusion flow" msgstr "校準擠出流量" @@ -2524,16 +2524,16 @@ msgid "Paused due to heat bed temperature malfunction" msgstr "熱床溫度異常暫停" msgid "Filament unloading" -msgstr "" +msgstr "退料" msgid "Skip step pause" msgstr "" msgid "Filament loading" -msgstr "" +msgstr "進料" msgid "Motor noise calibration" -msgstr "" +msgstr "馬達噪音校準" msgid "Paused due to AMS lost" msgstr "" @@ -2730,7 +2730,7 @@ msgid "Display" msgstr "顯示" msgid "Flushed" -msgstr "沖刷" +msgstr "排出列印板" msgid "Total" msgstr "總計" @@ -2742,7 +2742,7 @@ msgid "Total time" msgstr "總時間" msgid "Total cost" -msgstr "" +msgstr "總成本" msgid "up to" msgstr "達到" @@ -2904,13 +2904,13 @@ msgid "Mirror Object" msgstr "鏡像物體" msgid "Tool Move" -msgstr "工具 移動" +msgstr "工具移動" msgid "Tool Rotate" -msgstr "工具 旋轉" +msgstr "工具旋轉" msgid "Move Object" -msgstr "移動對象" +msgstr "移動物件" msgid "Auto Orientation options" msgstr "自動朝向選項" @@ -2953,13 +2953,13 @@ msgid "Auto orient" msgstr "自動朝向" msgid "Arrange all objects" -msgstr "全局整理" +msgstr "全域整理" msgid "Arrange objects on selected plates" msgstr "單盤整理" msgid "Split to objects" -msgstr "拆分為對象" +msgstr "拆分為物件" msgid "Split to parts" msgstr "拆分為零件" @@ -3018,15 +3018,15 @@ msgid "A G-code path goes beyond the boundary of plate." msgstr "檢測超出熱床邊界的 G-code 路徑。" msgid "Only the object being edit is visible." -msgstr "只有正在編輯的對象是可見的。" +msgstr "只有正在編輯的物件是可見的。" msgid "" "An object is laid over the boundary of plate or exceeds the height limit.\n" "Please solve the problem by moving it totally on or off the plate, and " "confirming that the height is within the build volume." msgstr "" -"對象被放置在構建板的邊界上或超過高度限制。\n" -"請透過將其完全移動到構建板內或構建板外,並確認高度在構建空間以內來解決問題。" +"物件被放置在列印板的邊界上或超過高度限制。\n" +"請透過將其完全移動到列印板內或列印板外,並確認高度在列印空間範圍以內來解決問題。" msgid "Calibration step selection" msgstr "校準步驟選擇" @@ -3038,10 +3038,10 @@ msgid "Bed leveling" msgstr "熱床調平" msgid "Vibration compensation" -msgstr "" +msgstr "共振補償" msgid "Motor noise cancellation" -msgstr "" +msgstr "馬達噪音消除" msgid "Calibration program" msgstr "校準程序" @@ -3061,7 +3061,7 @@ msgid "Start Calibration" msgstr "開始校準" msgid "No step selected" -msgstr "" +msgstr "未選擇任何步驟" msgid "Completed" msgstr "已完成" @@ -3104,10 +3104,10 @@ msgid "Invalid input." msgstr "輸入無效" msgid "New Window" -msgstr "新窗口" +msgstr "新視窗" msgid "Open a new window" -msgstr "打開新窗口" +msgstr "打開新視窗" msgid "Application is closing" msgstr "正在關閉應用程式" @@ -3128,7 +3128,7 @@ msgid "Device" msgstr "設備" msgid "Project" -msgstr "項目" +msgstr "專案項目" msgid "Yes" msgstr "是" @@ -3149,16 +3149,16 @@ msgid "Slice all" msgstr "切片所有盤" msgid "Export G-code file" -msgstr "匯出 G-code 文件" +msgstr "匯出 G-code 檔案" msgid "Send" msgstr "傳送" msgid "Export plate sliced file" -msgstr "匯出單盤切片文件" +msgstr "匯出單盤切片檔案" msgid "Export all sliced file" -msgstr "匯出所有切片文件" +msgstr "匯出所有切片檔案" msgid "Print all" msgstr "列印所有盤" @@ -3176,7 +3176,7 @@ msgid "Setup Wizard" msgstr "設定精靈" msgid "Show Configuration Folder" -msgstr "打開組態檔文件夾" +msgstr "打開組態檔的檔案夾" msgid "Show Tip of the Day" msgstr "顯示每日小提示" @@ -3239,34 +3239,34 @@ msgid "Right View" msgstr "右視圖" msgid "Start a new window" -msgstr "打開新窗口" +msgstr "打開新視窗" msgid "New Project" -msgstr "新建項目" +msgstr "新建專案項目" msgid "Start a new project" -msgstr "新建一個項目" +msgstr "新建一個專案項目" msgid "Open a project file" -msgstr "打開項目文件" +msgstr "打開專案項目" msgid "Recent projects" -msgstr "最近的項目" +msgstr "最近的專案項目" msgid "Save Project" -msgstr "保存項目" +msgstr "儲存專案項目" msgid "Save current project to file" -msgstr "保存當前項目到文件" +msgstr "儲存當前專案項目到檔案" msgid "Save Project as" -msgstr "項目另存為" +msgstr "另存專案項目為" msgid "Shift+" msgstr "" msgid "Save current project as" -msgstr "項目另存為" +msgstr "將目前專案項目另存為" msgid "Import 3MF/STL/STEP/SVG/OBJ/AMF" msgstr "匯入 3MF/STL/STEP/SVG/OBJ/AMF" @@ -3290,13 +3290,13 @@ msgid "Export Generic 3MF" msgstr "匯出通用 3MF" msgid "Export 3mf file without using some 3mf-extensions" -msgstr "匯出不含 3mf 擴展的 3mf 文件" +msgstr "匯出不含 3mf 擴展的 3mf 檔案" msgid "Export current sliced file" -msgstr "匯出當前已切片的文件" +msgstr "匯出當前已切片的檔案" msgid "Export all plate sliced file" -msgstr "匯出所有盤已切片的文件" +msgstr "匯出所有盤已切片的檔案" msgid "Export G-code" msgstr "匯出 G-code" @@ -3314,7 +3314,7 @@ msgid "Export" msgstr "匯出" msgid "Quit" -msgstr "退出程序" +msgstr "結束" msgid "Undo" msgstr "復原" @@ -3323,19 +3323,19 @@ msgid "Redo" msgstr "重做" msgid "Cut selection to clipboard" -msgstr "剪下所選項到剪貼板" +msgstr "剪下所選項到剪貼簿" msgid "Copy" msgstr "複製" msgid "Copy selection to clipboard" -msgstr "複製所選項到剪貼板" +msgstr "複製所選項到剪貼簿" msgid "Paste" msgstr "貼上" msgid "Paste clipboard" -msgstr "從剪貼板貼上" +msgstr "從剪貼簿貼上" msgid "Delete selected" msgstr "刪除所選項" @@ -3359,13 +3359,13 @@ msgid "Select all" msgstr "選中所有" msgid "Selects all objects" -msgstr "選中所有對象" +msgstr "選中所有物件" msgid "Deselect all" msgstr "取消所有選中" msgid "Deselects all objects" -msgstr "取消所有選中" +msgstr "取消所有選中物件" msgid "Use Perspective View" msgstr "使用透視視角" @@ -3377,7 +3377,7 @@ msgid "Show &Labels" msgstr "顯示名稱" msgid "Show object labels in 3D scene" -msgstr "在 3D 場景中顯示對象名稱" +msgstr "在 3D 場景中顯示物件名稱" msgid "Show &Overhang" msgstr "顯示懸空高亮" @@ -3444,7 +3444,7 @@ msgid "&Open G-code" msgstr "打開 G-code" msgid "Open a G-code file" -msgstr "打開 G-code 文件" +msgstr "打開 G-code 檔案" msgid "Re&load from Disk" msgstr "從磁碟重新載入" @@ -3462,7 +3462,7 @@ msgid "Open &Studio" msgstr "" msgid "Open Studio" -msgstr "打開 Studio" +msgstr "開啟 Studio" msgid "&Quit" msgstr "" @@ -3482,14 +3482,14 @@ msgstr "" #, c-format, boost-format msgid "A file exists with the same name: %s, do you want to override it." -msgstr "有一個同名的文件 %s。你想覆蓋它嗎?" +msgstr "有一個同名的檔案 %s。你想覆蓋它嗎?" #, c-format, boost-format msgid "A config exists with the same name: %s, do you want to override it." msgstr "有一個同名的設定檔 %s。你想覆蓋它嗎?" msgid "Overwrite file" -msgstr "覆蓋文件" +msgstr "覆蓋檔案" msgid "Yes to All" msgstr "全是" @@ -3521,7 +3521,7 @@ msgid "Import result" msgstr "匯入結果" msgid "File is missing" -msgstr "文件遺失" +msgstr "檔案遺失" msgid "The project is no longer available." msgstr "此項目不可用。" @@ -3538,7 +3538,7 @@ msgid "" msgstr "" "想從 Bambu 雲端同步你的個人數據嗎?\n" "包含如下資訊:\n" -"1. 工藝預設\n" +"1. 列印參數預設\n" "2. 線材預設\n" "3. 3D列印機預設" @@ -3627,7 +3627,7 @@ msgid "Month" msgstr "月" msgid "All Files" -msgstr "所有文件" +msgstr "所有檔案" msgid "Group files by year, recent first." msgstr "按年份分組,從最近的開始展示" @@ -3636,13 +3636,13 @@ msgid "Group files by month, recent first." msgstr "按月份分組,從最近的開始展示" msgid "Show all files, recent first." -msgstr "顯示所有文件,從最近的開始展示" +msgstr "顯示所有檔案,從最近的開始展示" msgid "Timelapse" msgstr "縮時攝影" msgid "Switch to timelapse files." -msgstr "切換到縮時攝影文件列表" +msgstr "切換到縮時攝影檔案列表" msgid "Video" msgstr "錄影" @@ -3651,22 +3651,22 @@ msgid "Switch to video files." msgstr "切換到影片檔案列表" msgid "Switch to 3mf model files." -msgstr "切換到 3MF 模型文件。" +msgstr "切換到 3MF 模型檔案。" msgid "Delete selected files from printer." -msgstr "從3D列印機中刪除選中的文件" +msgstr "從3D列印機中刪除選中的檔案" msgid "Download" msgstr "下載" msgid "Download selected files from printer." -msgstr "從3D列印機中下載選擇的文件" +msgstr "從3D列印機中下載選擇的檔案" msgid "Select" msgstr "選擇" msgid "Batch manage files." -msgstr "批次管理文件" +msgstr "批次管理檔案" msgid "No printers." msgstr "未選擇3D列印機" @@ -3676,11 +3676,11 @@ msgid "Connect failed [%d]!" msgstr "連接失敗 [%d]!" msgid "Loading file list..." -msgstr "載入文件列表..." +msgstr "載入檔案列表..." #, c-format, boost-format msgid "No files [%d]" -msgstr "文件列表為空[%d]" +msgstr "檔案列表為空[%d]" #, c-format, boost-format msgid "Load failed [%d]" @@ -3690,17 +3690,17 @@ msgstr "載入失敗 [%d]" msgid "You are going to delete %u file from printer. Are you sure to continue?" msgid_plural "" "You are going to delete %u files from printer. Are you sure to continue?" -msgstr[0] "您將從3D列印機中刪除%u個文件。確定要繼續嗎?" +msgstr[0] "您將從3D列印機中刪除%u個檔案。確定要繼續嗎?" msgid "Delete files" -msgstr "刪除文件" +msgstr "刪除檔案" #, c-format, boost-format msgid "Do you want to delete the file '%s' from printer?" -msgstr "你確定要從3D列印機中刪除文件'%s'嗎?" +msgstr "你確定要從3D列印機中刪除檔案'%s'嗎?" msgid "Delete file" -msgstr "刪除文件" +msgstr "刪除檔案" msgid "Fetching model infomations ..." msgstr "正在獲取模型資訊..." @@ -3715,12 +3715,12 @@ msgid "" "The .gcode.3mf file contains no G-code data.Please slice it whthBambu Studio " "and export a new .gcode.3mf file." msgstr "" -".gcode.3mf 文件中不包含 G-code 數據。請使用 Bambu Studio 進行切片並匯出新的." -"gcode.3mf 文件。" +".gcode.3mf 檔案中不包含 G-code 數據。請使用 Bambu Studio 進行切片並匯出新的." +"gcode.3mf 檔案。" #, c-format, boost-format msgid "File '%s' was lost! Please download it again." -msgstr "文件%s遺失,請重新下載。" +msgstr "檔案 %s 遺失,請重新下載。" msgid "Download waiting..." msgstr "等待下載中..." @@ -3729,7 +3729,7 @@ msgid "Play" msgstr "播放" msgid "Open Folder" -msgstr "打開目錄" +msgstr "打開資料夾" msgid "Download finished" msgstr "下載完成" @@ -3763,7 +3763,7 @@ msgid "3Dconnexion settings" msgstr "3Dconnexion設置" msgid "Swap Y/Z axes" -msgstr "交換Y/Z軸" +msgstr "交換 Y/Z 軸" msgid "Invert X axis" msgstr "反轉 X 軸" @@ -3802,7 +3802,7 @@ msgid "Clear" msgstr "清除" msgid "How do you like this printing file?" -msgstr "" +msgstr "您覺得這個列印檔案怎麼樣?" msgid "" "(The model has already been rated. Your rating will overwrite the previous " @@ -3902,16 +3902,16 @@ msgid "This only takes effect during printing" msgstr "僅在列印過程中生效" msgid "Silent" -msgstr "靜音模式" +msgstr "靜音模式(50%)" msgid "Standard" -msgstr "標準模式" +msgstr "標準模式(100%)" msgid "Sport" -msgstr "運動模式" +msgstr "運動模式(125%)" msgid "Ludicrous" -msgstr "狂暴模式" +msgstr "狂暴模式(150%)" msgid "Can't start this without SD card." msgstr "沒有SD記憶卡無法開始任務" @@ -3920,37 +3920,37 @@ msgid "Rate the Print Profile" msgstr "" msgid "Comment" -msgstr "" +msgstr "評論" msgid "Rate this print" msgstr "" msgid "Add Photo" -msgstr "" +msgstr "新增照片" msgid "Delete Photo" -msgstr "" +msgstr "刪除照片" msgid "Submit" -msgstr "" +msgstr "送出" msgid "Please click on the star first." msgstr "" msgid "InFo" -msgstr "" +msgstr "資訊" msgid "Get oss config failed." msgstr "" msgid "Upload Pictrues" -msgstr "" +msgstr "上傳圖片" msgid "Number of images successfully uploaded" -msgstr "" +msgstr "成功上傳的圖片數量" msgid " upload failed" -msgstr "" +msgstr "上傳失敗" msgid " upload config prase failed\n" msgstr "" @@ -3966,15 +3966,17 @@ msgid "" "want to ignore them?\n" "\n" msgstr "" +msgstr "在上傳圖片的過程中出現了以下問題。" +msgstr "要忽略此問題嗎?" msgid "info" msgstr "資訊" msgid "Synchronizing the printing results. Please retry a few seconds later." -msgstr "" +msgstr "正在同步列印結果。請稍後重試。" msgid "Upload failed\n" -msgstr "" +msgstr "上傳失敗" msgid "obtaining instance_id failed\n" msgstr "" @@ -3986,7 +3988,7 @@ msgid "" msgstr "" msgid "error message: " -msgstr "" +msgstr "錯誤訊息:" msgid "" "\n" @@ -4000,7 +4002,7 @@ msgid "" msgstr "" msgid "You can select up to 16 images." -msgstr "" +msgstr "您最多可以選擇 16 張圖片。" msgid "" "At least one successful print record of this print profile is required \n" @@ -4056,22 +4058,22 @@ msgid "Detail." msgstr "詳情。" msgid "Integration was successful." -msgstr "集成成功。" +msgstr "整合成功。" msgid "Integration failed." -msgstr "集成失敗。" +msgstr "整合失敗。" msgid "Undo integration was successful." -msgstr "集成取消成功。" +msgstr "整合取消成功。" msgid "New network plug-in available." msgstr "新的網路插件可用。" msgid "Details" -msgstr "詳情" +msgstr "細節" msgid "Undo integration failed." -msgstr "集成取消失敗。" +msgstr "整合取消失敗。" msgid "Exporting." msgstr "正在匯出。" @@ -4083,7 +4085,7 @@ msgid "Goto download page." msgstr "前往下載網站。" msgid "Open Folder." -msgstr "打開目錄。" +msgstr "打開資料夾。" msgid "Safely remove hardware." msgstr "安全移除硬體。" @@ -4096,12 +4098,12 @@ msgstr[0] "%1$d 模型有自訂支撐。" #, c-format, boost-format msgid "%1$d Object has color painting." msgid_plural "%1$d Objects have color painting." -msgstr[0] "%1$d對象有塗色。" +msgstr[0] "%1$d 物件有塗色。" #, c-format, boost-format msgid "%1$d object was loaded as a part of cut object." msgid_plural "%1$d objects were loaded as parts of cut object" -msgstr[0] "%1$d對象載入為一個切割對象的子部件" +msgstr[0] "%1$d 物件載入為一個切割對象的子部件" msgid "ERROR" msgstr "錯誤" @@ -4119,7 +4121,7 @@ msgid "Slice ok." msgstr "切片完成." msgid "Jump to" -msgstr "跳轉到" +msgstr "轉換到" msgid "Error:" msgstr "錯誤:" @@ -4131,7 +4133,7 @@ msgid "Export successfully." msgstr "匯出成功." msgid "Model file downloaded." -msgstr "" +msgstr "模型檔案已下載。" msgid "Serious warning:" msgstr "嚴重警告:" @@ -4201,12 +4203,12 @@ msgid "Sensitivity of pausing is" msgstr "暫停的靈敏度為" msgid "Enable detection of build plate position" -msgstr "啟用構建板位置檢測" +msgstr "啟用列印板位置檢測" msgid "" "The localization tag of build plate is detected, and printing is paused if " "the tag is not in predefined range." -msgstr "檢測構建板的定位標記,如果標記不在預定義範圍內時暫停列印。" +msgstr "檢測列印板的定位標記,如果標記不在預定義範圍內時暫停列印。" msgid "First Layer Inspection" msgstr "首層掃描" @@ -4215,13 +4217,13 @@ msgid "Auto-recovery from step loss" msgstr "自動從丟步中恢復" msgid "Allow Prompt Sound" -msgstr "" +msgstr "允許提示音效" msgid "Global" msgstr "全局" msgid "Objects" -msgstr "對象" +msgstr "物件" msgid "Advance" msgstr "高級" @@ -4230,7 +4232,7 @@ msgid "Compare presets" msgstr "比較預設" msgid "View all object's settings" -msgstr "查看所有對象的配置" +msgstr "查看所有物件的配置" msgid "Filament settings" msgstr "線材設置" @@ -4267,7 +4269,7 @@ msgid "Invalid name, the following characters are not allowed:" msgstr "無效名稱,不允許使用以下字元:" msgid "Sliced Info" -msgstr "切片你資訊" +msgstr "切片資訊" msgid "Used Filament (m)" msgstr "線材消耗長度 (m)" @@ -4288,7 +4290,7 @@ msgid "Filament changes" msgstr "線材切換" msgid "Click to edit preset" -msgstr "點擊編輯配置" +msgstr "滑鼠左鍵點擊編輯配置" msgid "Connection" msgstr "連接" @@ -4297,7 +4299,7 @@ msgid "Bed type" msgstr "熱床類型" msgid "Flushing volumes" -msgstr "沖刷體積" +msgstr "換色廢料體積" msgid "Add one filament" msgstr "增加一個線材" @@ -4321,7 +4323,7 @@ msgstr "同步到 AMS 的線材列表" msgid "" "Sync filaments with AMS will drop all current selected filament presets and " "colors. Do you want to continue?" -msgstr "同步到 AMS 的線材列表將丟棄所有當前配置的線材預設、顏色。是否繼續?" +msgstr "同步到 AMS 的線材列表將丟棄所有目前配置的線材預設、顏色。是否繼續?" msgid "" "Already did a synchronization, do you want to sync only changes or resync " @@ -4347,7 +4349,7 @@ msgstr "" #, boost-format msgid "Do you want to save changes to \"%1%\"?" -msgstr "是否保存修改到“%1%”?" +msgstr "是否儲存修改到“%1%”?" #, c-format, boost-format msgid "" @@ -4360,7 +4362,7 @@ msgid "Ejecting of device %s(%s) has failed." msgstr "彈出設備%s(%s)失敗。" msgid "Previous unsaved project detected, do you want to restore it?" -msgstr "檢測到有未保存的項目,是否恢復此項目?" +msgstr "檢測到有未儲存的專案項目,是否恢復此項目?" msgid "Restore" msgstr "恢復" @@ -4385,10 +4387,10 @@ msgstr "" #, c-format, boost-format msgid "Loading file: %s" -msgstr "載入文件:%s" +msgstr "載入檔案:%s" msgid "The 3mf is not supported by OrcaSlicer, load geometry data only." -msgstr "該 3mf 文件不是來自 Orca Slicer,將只載入幾何數據。" +msgstr "該 3mf 檔案不是來自 Orca Slicer,將只載入幾何數據。" msgid "Load 3mf" msgstr "載入 3mf" @@ -4397,7 +4399,7 @@ msgid "The Config can not be loaded." msgstr "配置無法載入。" msgid "The 3mf is generated by old Orca Slicer, load geometry data only." -msgstr "該 3mf 文件來自舊版本的 Orca Slicer" +msgstr "該 3mf 檔案來自舊版本的 Orca Slicer" #, c-format, boost-format msgid "" @@ -4418,87 +4420,87 @@ msgid "" msgstr "該 3mf 的版本%s比%s的版本%s要新,建議升級你的軟體。" msgid "Invalid values found in the 3mf:" -msgstr "在 3mf 文件中發現無效值:" +msgstr "在 3mf 檔案中發現無效值:" msgid "Please correct them in the param tabs" msgstr "請在參數頁更正它們" msgid "The 3mf is not compatible, load geometry data only!" -msgstr "該 3mf 文件與軟體不相容,將只載入幾何數據。" +msgstr "該 3mf 檔案與軟體不相容,將只載入幾何數據。" msgid "Incompatible 3mf" msgstr "不相容的 3mf" msgid "Name of components inside step file is not UTF8 format!" -msgstr "step 文件中的部件名稱包含非UTF8格式的字元!" +msgstr "step 檔案中的部件名稱包含非UTF8格式的字元!" msgid "The name may show garbage characters!" msgstr "此名稱可能顯示亂碼字元!" #, boost-format msgid "Failed loading file \"%1%\". An invalid configuration was found." -msgstr "載入文件“%1%”失敗。發現無效配置。" +msgstr "載入檔案“%1%”失敗。發現無效配置。" msgid "Objects with zero volume removed" msgstr "體積為零的對象已被移除" msgid "The volume of the object is zero" -msgstr "對象的體積為零" +msgstr "物件的體積為零" #, c-format, boost-format msgid "" "The object from file %s is too small, and maybe in meters or inches.\n" " Do you want to scale to millimeters?" msgstr "" -"文件 %s 中對象的尺寸似乎是以公尺或者英寸為單位定義的。\n" +"檔案 %s 中物件的尺寸似乎是以公尺或者英寸為單位定義的。\n" " Orcaslicer 的內部單位為毫米。是否要轉換成毫米?" msgid "Object too small" -msgstr "對象尺寸過小" +msgstr "物件尺寸過小" msgid "" "This file contains several objects positioned at multiple heights.\n" "Instead of considering them as multiple objects, should \n" "the file be loaded as a single object having multiple parts?" msgstr "" -"該文件包含多個位於不同高度的對象。\n" -"是否將文件載入為一個由多個零件組合而成的對象,而非多個單零件的對象?" +"該檔案包含多個位於不同高度的物件。\n" +"是否將檔案載入為一個由多個零件組合而成的物件,而非多個單零件的物件?" msgid "Multi-part object detected" -msgstr "檢測到多部分對象" +msgstr "檢測到多部分物件" msgid "Load these files as a single object with multiple parts?\n" -msgstr "將這些文件載入為一個多零件對象?\n" +msgstr "將這些檔案載入為一個多零件物件?\n" msgid "Object with multiple parts was detected" -msgstr "檢測到多零件對象" +msgstr "檢測到多零件物件" msgid "The file does not contain any geometry data." -msgstr "此文件不包含任何幾何數據。" +msgstr "此檔案不包含任何幾何數據。" msgid "" "Your object appears to be too large, Do you want to scale it down to fit the " "heat bed automatically?" -msgstr "對象看起來太大,希望將對象自動縮小以適應熱床嗎?" +msgstr "物件看起來太大,希望將物件自動縮小以適應熱床嗎?" msgid "Object too large" -msgstr "對象太大" +msgstr "物件太大" msgid "Export STL file:" -msgstr "匯出 STL 文件:" +msgstr "匯出 STL 檔案:" msgid "Save file as:" -msgstr "文件另存為:" +msgstr "檔案另存為:" msgid "Delete object which is a part of cut object" -msgstr "刪除切割對象的一部分" +msgstr "刪除切割物件的一部分" msgid "" "You try to delete an object which is a part of a cut object.\n" "This action will break a cut correspondence.\n" "After that model consistency can't be guaranteed." msgstr "" -"您正嘗試刪除切割對象的一部分,這將破壞切割對應關係,刪除之後,將無法再保證模" +"您正嘗試刪除切割物件的一部分,這將破壞切割對應關係,刪除之後,將無法再保證模" "型的一致性。" msgid "The selected object couldn't be split." @@ -4508,16 +4510,16 @@ msgid "Another export job is running." msgstr "有其他匯出任務正在進行中。" msgid "Select a new file" -msgstr "選擇新文件" +msgstr "選擇新檔案" msgid "File for the replace wasn't selected" -msgstr "未選擇替換文件" +msgstr "未選擇替換檔案" msgid "Error during replace" msgstr "替換時發生錯誤" msgid "Please select a file" -msgstr "請選擇一個文件" +msgstr "請選擇一個檔案" msgid "Slicing" msgstr "正在切片" @@ -4536,7 +4538,7 @@ msgstr "切片已取消" #, c-format, boost-format msgid "Slicing Plate %d" -msgstr "正在切片盤%d" +msgstr "正在切片盤 %d" msgid "Please resolve the slicing errors and publish again." msgstr "請解決切片錯誤後再重新發布。" @@ -4550,73 +4552,73 @@ msgid "" "The loaded file contains gcode only, Can not enter the Prepare page" msgstr "" "僅預覽模式:\n" -"被載入的文件僅包含G-Code,不支援進入準備頁面" +"被載入的檔案僅包含 G-Code,不支援進入準備頁面" msgid "You can keep the modified presets to the new project or discard them" -msgstr "您可以保留修改的預設到新項目中或者忽略這些修改" +msgstr "您可以保留修改的預設到新專案項目中或者忽略這些修改" msgid "Creating a new project" -msgstr "創建新項目" +msgstr "創建新專案項目" msgid "Load project" -msgstr "載入項目" +msgstr "載入專案項目" msgid "" "Failed to save the project.\n" "Please check whether the folder exists online or if other programs open the " "project file." -msgstr "保存文件失敗。請檢查目錄是否存在,以及是否有其他程序打開了該項目文件。" +msgstr "儲存檔案失敗。請檢查資料夾是否存在,以及是否有其他程式打開了該專案項目檔案。" msgid "Save project" -msgstr "保存項目" +msgstr "儲存專案項目" msgid "Importing Model" msgstr "正在匯入模型" msgid "prepare 3mf file..." -msgstr "正在準備 3mf 文件..." +msgstr "正在準備 3mf 檔案..." msgid "downloading project ..." -msgstr "項目下載中..." +msgstr "專案項目下載中..." #, c-format, boost-format msgid "Project downloaded %d%%" -msgstr "項目已下載%d%%" +msgstr "專案項目已下載%d%%" msgid "" "Importing to Bambu Studio failed. Please download the file and manually " "import it." -msgstr "" +msgstr "匯入 Bambu Studio 失敗。 請下載該檔案並手動匯入。" msgid "The selected file" -msgstr "已選擇的文件" +msgstr "已選擇的檔案" msgid "does not contain valid gcode." -msgstr "不包含有效的 G-code 文件。" +msgstr "不包含有效的 G-code 檔案。" msgid "Error occurs while loading G-code file" -msgstr "載入 G-code 文件時遇到錯誤" +msgstr "載入 G-code 檔案時遇到錯誤" msgid "Drop project file" -msgstr "項目文件操作" +msgstr "專案項目檔案操作" msgid "Please select an action" msgstr "請選擇處理方式" msgid "Open as project" -msgstr "按項目打開" +msgstr "作為專案項目打開" msgid "Import geometry only" msgstr "僅匯入模型數據" msgid "Only one G-code file can be opened at the same time." -msgstr "只能同時打開一個 G-code 文件。" +msgstr "只能同時打開一個 G-code 檔案。" msgid "G-code loading" -msgstr "正在載入 G-code 文件" +msgstr "正在載入 G-code 檔案" msgid "G-code files can not be loaded with models together!" -msgstr "G-code 文件不能和模型一起載入" +msgstr "G-code 檔案不能和模型一起載入" msgid "Can not add models when in preview mode!" msgstr "在預覽模式不允許增加模型" @@ -4625,10 +4627,10 @@ msgid "Add Models" msgstr "新增模型" msgid "All objects will be removed, continue?" -msgstr "即將刪除所有對象,是否繼續?" +msgstr "即將刪除所有物件,是否繼續?" msgid "The current project has unsaved changes, save it before continue?" -msgstr "當前項目包含未保存的修改,是否先保存?" +msgstr "當前項目包含未儲存的修改,是否先儲存?" msgid "Remember my choice." msgstr "記住我的選擇。" @@ -4640,16 +4642,16 @@ msgid "Copies of the selected object" msgstr "所選對象的複製數量" msgid "Save G-code file as:" -msgstr "G-code 文件另存為:" +msgstr "G-code 檔案另存為:" msgid "Save Sliced file as:" -msgstr "切片文件另存為:" +msgstr "切片檔案另存為:" #, c-format, boost-format msgid "" "The file %s has been sent to the printer's storage space and can be viewed " "on the printer." -msgstr "文件%s已經傳送到3D列印機的儲存空間,可以在3D列印機上瀏覽。" +msgstr "檔案%s已經傳送到3D列印機的儲存空間,可以在3D列印機上瀏覽。" msgid "" "Unable to perform boolean operation on model meshes. Only positive parts " @@ -4670,7 +4672,7 @@ msgstr "" "建議使用自動擺盤避免列印時發生碰撞。" msgid "Send G-code" -msgstr "傳送 G 代碼" +msgstr "傳送 G-Code" msgid "Send to printer" msgstr "傳送到3D列印機" @@ -4690,7 +4692,7 @@ msgstr "當前選擇的零件數量: %1%\n" #, boost-format msgid "Number of currently selected objects: %1%\n" -msgstr "當前選擇的對象數量: %1%\n" +msgstr "當前選擇的物件數量: %1%\n" #, boost-format msgid "Part name: %1%\n" @@ -4698,7 +4700,7 @@ msgstr "零件名字:%1%\n" #, boost-format msgid "Object name: %1%\n" -msgstr "對象名字:%1%\n" +msgstr "物件名字:%1%\n" #, boost-format msgid "Size: %1% x %2% x %3% in\n" @@ -4736,7 +4738,7 @@ msgid "" "still want to do this printing, please set this filament's bed temperature " "to non zero." msgstr "" -"熱床% d:%s不建議被用於列印%s(%s)線材。如果你依然想列印,請設置耗材對應的熱" +"熱床% d:%s不建議被用於列印%s(%s)線材。如果你依然想列印,請設置線材對應的熱" "床溫度為非零值。" msgid "Switching the language requires application restart.\n" @@ -4767,7 +4769,7 @@ msgid "Browse" msgstr "瀏覽" msgid "Choose Download Directory" -msgstr "選擇下載文件夾" +msgstr "選擇下載資料夾" msgid "General Settings" msgstr "通用設置" @@ -4788,7 +4790,7 @@ msgid "Others" msgstr "其他" msgid "Login Region" -msgstr "登錄區域" +msgstr "登入區域" msgid "Stealth Mode" msgstr "區域網路模式" @@ -4823,10 +4825,10 @@ msgid "If enabled, useful hints are displayed at startup." msgstr "如果啟用,將在啟動時顯示有用的提示。" msgid "Show g-code window" -msgstr "顯示 g-code 窗口" +msgstr "顯示 g-code 視窗" msgid "If enabled, g-code window will be displayed." -msgstr "如果啟用,將顯示 g-code 窗口。" +msgstr "如果啟用,將顯示 g-code 視窗。" msgid "Presets" msgstr "預設" @@ -4844,50 +4846,50 @@ msgid "System Sync" msgstr "系統同步" msgid "Clear my choice on the unsaved presets." -msgstr "清除我對未保存的預置的選擇。" +msgstr "清除我對未儲存預設的選擇。" msgid "Associate files to OrcaSlicer" -msgstr " Orcaslicer 文件關聯" +msgstr " Orcaslicer 檔案關聯" msgid "Associate .3mf files to OrcaSlicer" -msgstr "使用 Orcaslicer 打開 .3mf 文件" +msgstr "使用 Orcaslicer 打開 .3mf 檔案" msgid "If enabled, sets OrcaSlicer as default application to open .3mf files" -msgstr "開啟後,將預設使用 Orcaslicer 打開 .3mf 文件" +msgstr "開啟後,將預設使用 Orcaslicer 打開 .3mf 檔案" msgid "Associate .stl files to OrcaSlicer" -msgstr "使用 Orcaslicer 打開 .stl 文件" +msgstr "使用 Orcaslicer 打開 .stl 檔案" msgid "If enabled, sets OrcaSlicer as default application to open .stl files" -msgstr "開啟後,將預設使用 Orcaslicer 打開 .stl 文件" +msgstr "開啟後,將預設使用 Orcaslicer 打開 .stl 檔案" msgid "Associate .step/.stp files to OrcaSlicer" -msgstr "使用 Orcaslicer 打開 .step/.stp 文件" +msgstr "使用 Orcaslicer 打開 .step/.stp 檔案" msgid "If enabled, sets OrcaSlicer as default application to open .step files" -msgstr "開啟後,將預設使用 Orcaslicer 打開 .step 文件" +msgstr "開啟後,將預設使用 Orcaslicer 打開 .step 檔案" msgid "Online Models" -msgstr "在線模型" +msgstr "線上模型" msgid "Show online staff-picked models on the home page" -msgstr "在首頁上顯示工作人員挑選的在線模型" +msgstr "在首頁上顯示工作人員挑選的線上模型" msgid "Maximum recent projects" -msgstr "近期項目的最大數量" +msgstr "最近專案項目的最大數量" msgid "Maximum count of recent projects" -msgstr "近期項目的最大計數" +msgstr "近期專案項目的最大統計" msgid "Clear my choice on the unsaved projects." -msgstr "清除我對未保存的項目的選擇。" +msgstr "清除我對未儲存的專案項目的選擇。" msgid "Auto-Backup" msgstr "自動備份" msgid "" "Backup your project periodically for restoring from the occasional crash." -msgstr "定期備份你的項目,以便從偶爾的崩潰中恢復過來。" +msgstr "定期備份專案項目,以便從偶發崩潰中恢復。" msgid "every" msgstr "" @@ -4908,7 +4910,7 @@ msgid "Develop mode" msgstr "開發者模式" msgid "Skip AMS blacklist check" -msgstr "跳過AMS黑名單檢查" +msgstr "跳過 AMS 黑名單檢查" msgid "Home page and daily tips" msgstr "首頁和每日小建議" @@ -4926,7 +4928,7 @@ msgid "Preset sync" msgstr "配置同步" msgid "Preferences sync" -msgstr "首選項同步" +msgstr "偏好設定同步" msgid "View control settings" msgstr "視圖控制設置" @@ -4989,16 +4991,16 @@ msgid "Product host" msgstr "正式環境" msgid "debug save button" -msgstr "保存" +msgstr "儲存" msgid "save debug settings" -msgstr "保存除錯設置" +msgstr "儲存除錯設定" msgid "DEBUG settings have saved successfully!" -msgstr "DEBUG模式生效!" +msgstr "除錯模式生效!" msgid "Switch cloud environment, Please login again!" -msgstr "切換雲環境,請重新登入!" +msgstr "切換雲端環境,請重新登入!" msgid "System presets" msgstr "系統配置" @@ -5031,7 +5033,7 @@ msgid "Add/Remove filaments" msgstr "新增/刪除線材" msgid "Add/Remove materials" -msgstr "新增/刪除線材" +msgstr "新增/刪除材料" msgid "Add/Remove printers" msgstr "新增/刪除3D列印機" @@ -5079,13 +5081,13 @@ msgid "Slice all plate to obtain time and filament estimation" msgstr "正在切片以獲取切片資訊和預估列印時間" msgid "Packing project data into 3mf file" -msgstr "正在打包數據到 3mf 文件" +msgstr "正在打包數據到 3mf 檔案" msgid "Uploading 3mf" msgstr "正在上傳 3mf " msgid "Jump to model publish web page" -msgstr "跳轉到發布頁面" +msgstr "發布頁面" msgid "Note: The preparation may takes several minutes. Please be patiant." msgstr "提示:發布前需要一些準備時間,請耐心等待。" @@ -5103,7 +5105,7 @@ msgid "Packing data to 3mf" msgstr "打包數據到3mf" msgid "Jump to webpage" -msgstr "跳轉到網頁" +msgstr "轉換到網頁" #, c-format, boost-format msgid "Save %s as" @@ -5139,7 +5141,7 @@ msgid "Preset \"%1%\" already exists and is incompatible with current printer." msgstr "預設“%1%”已存在,並且和當前3D列印機不相容。" msgid "Please note that saving action will replace this preset" -msgstr "請注意這個預設會在保存過程中被替換" +msgstr "請注意這個預設會在儲存過程中被替換" msgid "The name is not allowed to be empty." msgstr "名稱不允許為空。" @@ -5154,11 +5156,11 @@ msgid "The name cannot be the same as a preset alias name." msgstr "名稱不能和一個預設的別名相同。" msgid "Save preset" -msgstr "保存預設" +msgstr "儲存預設" msgctxt "PresetName" msgid "Copy" -msgstr "拷貝" +msgstr "複製" #, boost-format msgid "Printer \"%1%\" is selected with preset \"%2%\"" @@ -5166,7 +5168,7 @@ msgstr "選中3D列印機“%1%”和預設“%2%”" #, boost-format msgid "Please choose an action with \"%1%\" preset after saving." -msgstr "請選擇保存後對%1%預設的操作。" +msgstr "請選擇儲存後對%1%預設的操作。" #, boost-format msgid "For \"%1%\", change \"%2%\" to \"%3%\" " @@ -5217,7 +5219,7 @@ msgid "PLA Plate" msgstr "PLA 列印板" msgid "Bambu Engineering Plate" -msgstr "" +msgstr "高溫工程板" msgid "Bambu Smooth PEI Plate" msgstr "" @@ -5241,7 +5243,7 @@ msgid "Flow Dynamics Calibration" msgstr "動態流量校準" msgid "Click here if you can't connect to the printer" -msgstr "" +msgstr "如果無法連接到印表機,請按一下此處" msgid "send completed" msgstr "傳送完成" @@ -5292,13 +5294,13 @@ msgid "" "Filaments to AMS slots mappings have been established. You can click a " "filament above to change its mapping AMS slot" msgstr "" -"已自動建立 \"線材列表=>AMS槽位\" 的映射關係。 可點擊上方具體的線材手動設置其" -"所對應的AMS槽位" +"已自動建立 \"線材列表=>AMS 槽位\" 的映射關係。 可點擊上方具體的線材手動設置其" +"所對應的 AMS 槽位" msgid "" "Please click each filament above to specify its mapping AMS slot before " "sending the print job" -msgstr "請在傳送列印前點擊上方各個線材,指定其所對應的AMS槽位" +msgstr "請在傳送列印前點擊上方各個線材,指定其所對應的 AMS 槽位" #, c-format, boost-format msgid "" @@ -5319,8 +5321,8 @@ msgid "" "The printer firmware only supports sequential mapping of filament => AMS " "slot." msgstr "" -"已自動建立 \"線材列表=>AMS槽位\" 的映射關係。 可點擊上方具體的線材手動設置其" -"所對應的AMS槽位" +"已自動建立 \"線材列表=>AMS 槽位\" 的映射關係。 可點擊上方具體的線材手動設置其" +"所對應的 AMS 槽位" msgid "An SD card needs to be inserted before printing." msgstr "請在進行列印前插入SD記憶卡" @@ -5346,11 +5348,16 @@ msgid "" "When enable spiral vase mode, machines with I3 structure will not generate " "timelapse videos." msgstr "" +msgstr "當啟用花瓶模式時,龍門結構的機器不會產生" +msgstr "縮時攝影影片" msgid "" "When print by object, machines with I3 structure will not generate timelapse " "videos." msgstr "" +msgstr "按物件列印時,龍門結構的機器不會產生" +msgstr "縮時攝影影片" + msgid "Errors" msgstr "錯誤" @@ -5363,12 +5370,12 @@ msgid "" "currently selected printer. It is recommended that you use the same printer " "type for slicing." msgstr "" -"產生 G代碼 時選擇的3D列印機類型與當前選擇的3D列印機不一致。建議您使用相同" +"產生 G-Code 時選擇的3D列印機類型與當前選擇的3D列印機不一致。建議您使用相同" "的3D列印機類型進行切片。" #, c-format, boost-format msgid "%s is not supported by AMS." -msgstr "%s 不受 AMS 支援。" +msgstr "AMS 不支援 %s 。" msgid "" "There are some unknown filaments in the AMS mappings. Please check whether " @@ -5380,7 +5387,7 @@ msgstr "" msgid "" "Please click the confirm button if you still want to proceed with printing." -msgstr "如果您仍然想繼續列印,請單擊“確定”按鈕。" +msgstr "如果您仍然想繼續列印,請滑鼠左鍵單擊“確定”按鈕。" msgid "" "Connecting to the printer. Unable to cancel during the connection process." @@ -5390,7 +5397,7 @@ msgid "Preparing print job" msgstr "正在準備列印作業" msgid "Abnormal print file data. Please slice again" -msgstr "列印文件數據異常,請重新切片" +msgstr "列印檔案數據異常,請重新切片" msgid "The name length exceeds the limit." msgstr "名稱長度超過限制。" @@ -5398,7 +5405,7 @@ msgstr "名稱長度超過限制。" msgid "" "Caution to use! Flow calibration on Textured PEI Plate may fail due to the " "scattered surface." -msgstr "小心使用!紋理PEI板 上的流量校準可能會因表面散射而失敗。" +msgstr "小心使用!金屬紋理PEI板 上的流量校準可能會因表面散射而失敗。" msgid "Automatic flow calibration using Micro Lidar" msgstr "使用微型雷達進行自動流量校準" @@ -5416,7 +5423,7 @@ msgid "An SD card needs to be inserted before send to printer SD card." msgstr "傳送到3D列印機需要插入SD記憶卡" msgid "The printer is required to be in the same LAN as Bambu Studio." -msgstr "3D列印機需要與Bambu Studio在同一個區域網路內。" +msgstr "3D列印機需要與 Bambu Studio 在同一個區域網路內。" msgid "The printer does not support sending to printer SD card." msgstr "該3D列印機不支援傳送到3D列印機SD記憶卡。" @@ -5446,7 +5453,7 @@ msgid "Receive login report timeout" msgstr "" msgid "Unknown Failure" -msgstr "發生錯誤" +msgstr "未知錯誤" msgid "Log in printer" msgstr "登入3D列印機" @@ -5470,9 +5477,9 @@ msgid "" "Use(collectively, the \"Terms\"). If you do not comply with or agree to the " "Bambu Lab Privacy Policy, please do not use Bambu Lab equipment and services." msgstr "" -"感謝您購買Bambu Lab設備,使用Bambu Lab設備前,請閱讀一下條款,單擊同意使用您" -"的Bambu Lab設備即表示您同意遵守隱私政策以及使用條款(統稱為“條款”)。如果您不" -"符合或不同意Bambu Lab隱私政策,請不要使用Bambu Lab設備和服務。" +"感謝您購買 Bambu Lab 設備,使用 Bambu Lab 設備前,請閱讀一下條款,單擊同意使用您" +"的 Bambu Lab 設備即表示您同意遵守隱私政策以及使用條款(統稱為“條款”)。如果您不" +"遵守或不同意 Bambu Lab 隱私政策,請不要使用 Bambu Lab 設備和服務。" msgid "and" msgstr "和" @@ -5531,7 +5538,7 @@ msgstr "登出失敗。" #. TRN "Save current Settings" #, c-format, boost-format msgid "Save current %s" -msgstr "保存當前 %s" +msgstr "儲存當前 %s" msgid "Delete this preset" msgstr "刪除此預設" @@ -5540,7 +5547,7 @@ msgid "Search in preset" msgstr "在預設中搜索" msgid "Click to reset all settings to the last saved preset." -msgstr "點擊以將所有設置還原到最後一次保存的版本。" +msgstr "點擊以將所有設置還原到最後一次儲存的版本。" msgid "" "Prime tower is required for smooth timeplase. There may be flaws on the " @@ -5787,7 +5794,7 @@ msgid "Exhaust fan" msgstr "" msgid "During print" -msgstr "" +msgstr "列印期間" msgid "Complete print" msgstr "" @@ -5917,22 +5924,22 @@ msgid "All" msgstr "所有" msgid "Set" -msgstr "設置" +msgstr "設定" msgid "Click to reset current value and attach to the global value." -msgstr "點擊該圖示,恢復到全局的配置數值,並與全局配置同步變化。" +msgstr "點擊該圖示,恢復到全域的配置數值,並與全域配置同步變化。" msgid "Click to drop current modify and reset to saved value." -msgstr "點擊該圖示,丟棄當前的修改,恢復到上次保存的數值。" +msgstr "點擊該圖示,丟棄當前的修改,恢復到上次儲存的數值。" msgid "Process Settings" -msgstr "工藝設置" +msgstr "列印參數設置" msgid "Undef" msgstr "未定義" msgid "Unsaved Changes" -msgstr "未保存的更改" +msgstr "未儲存的更改" msgid "Discard or Keep changes" msgstr "放棄或保留更改" @@ -5947,7 +5954,7 @@ msgid "Transfer" msgstr "遷移" msgid "Don't save" -msgstr "不保存" +msgstr "不儲存" msgid "Discard" msgstr "放棄" @@ -5956,13 +5963,13 @@ msgid "Click the right mouse button to display the full text." msgstr "單擊滑鼠右鍵顯示全文。" msgid "All changes will not be saved" -msgstr "所有的修改都不會被保存" +msgstr "所有的修改都不會被儲存" msgid "All changes will be discarded." msgstr "所有的修改都將被丟棄。" msgid "Save the selected options." -msgstr "保存所選項。" +msgstr "儲存所選項。" msgid "Keep the selected options." msgstr "保持所選項。" @@ -5975,7 +5982,7 @@ msgid "" "Save the selected options to preset \n" "\"%1%\"." msgstr "" -"保存所選選項到預設 \n" +"儲存所選選項到預設 \n" "\"%1%\"." #, boost-format @@ -5988,19 +5995,19 @@ msgstr "" #, boost-format msgid "Preset \"%1%\" contains the following unsaved changes:" -msgstr "預設 \"%1%\" 包含以下未保存的修改:" +msgstr "預設 \"%1%\" 包含以下未儲存的修改:" #, boost-format msgid "" "Preset \"%1%\" is not compatible with the new printer profile and it " "contains the following unsaved changes:" -msgstr "預設 \"%1%\" 與新的3D列印機預設不相容,並且包含以下未保存的修改:" +msgstr "預設 \"%1%\" 與新的3D列印機預設不相容,並且包含以下未儲存的修改:" #, boost-format msgid "" "Preset \"%1%\" is not compatible with the new process profile and it " "contains the following unsaved changes:" -msgstr "預設“%1%”和新的工藝預設不相容,並且它包含以下未保存的修改:" +msgstr "預設“%1%”和新的工藝預設不相容,並且它包含以下未儲存的修改:" #, boost-format msgid "" @@ -6031,7 +6038,7 @@ msgid "Show all presets (including incompatible)" msgstr "顯示所有預設(包括不相容的)" msgid "Add File" -msgstr "新增文件" +msgstr "新增檔案" msgid "Set as cover" msgstr "設置為封面" @@ -6141,27 +6148,27 @@ msgid "Auto-Calc" msgstr "自動計算" msgid "Flushing volumes for filament change" -msgstr "線材更換時的沖刷體積" +msgstr "線材更換時產生的廢料體積" msgid "Multiplier" msgstr "乘數" msgid "Flushing volume (mm³) for each filament pair." -msgstr "在兩個線材間切換所需的沖刷量(mm³)" +msgstr "在兩個線材間切換所需的廢料體積(mm³)" #, c-format, boost-format msgid "Suggestion: Flushing Volume in range [%d, %d]" -msgstr "建議:沖刷量設置在[%d, %d]範圍內" +msgstr "建議:廢料體積量設置在[%d, %d]範圍內" #, c-format, boost-format msgid "The multiplier should be in range [%.2f, %.2f]." msgstr "乘數的取值範圍是[%.2f, %.2f]" msgid "unloaded" -msgstr "卸載" +msgstr "退料" msgid "loaded" -msgstr "裝載" +msgstr "進料" msgid "Filament #" msgstr "線材#" @@ -6173,7 +6180,7 @@ msgid "To" msgstr "到" msgid "Login" -msgstr "登錄" +msgstr "登入" msgid "The configuration package is changed in previous Config Guide" msgstr "參數配置包在之前的配置嚮導中發生了變更" @@ -6185,10 +6192,10 @@ msgid "Toolbar" msgstr "工具欄" msgid "Objects list" -msgstr "對象列表" +msgstr "物件列表" msgid "Import geometry data from STL/STEP/3MF/OBJ/AMF files" -msgstr "從STL/STEP/3MF/OBJ/AMF文件中匯入幾何數據" +msgstr "從STL/STEP/3MF/OBJ/AMF檔案中匯入幾何數據" msgid "⌘+Shift+G" msgstr "" @@ -6209,7 +6216,7 @@ msgid "Show keyboard shortcuts list" msgstr "顯示鍵盤快捷鍵列表" msgid "Global shortcuts" -msgstr "全局快捷鍵" +msgstr "全域快捷鍵" msgid "Rotate View" msgstr "旋轉視角" @@ -6310,7 +6317,7 @@ msgid "Esc" msgstr "" msgid "keyboard 1-9: set filament for object/part" -msgstr "按鍵1-9:設置對象/零件的線材" +msgstr "按鍵1-9:設置物件/零件的線材" msgid "Camera view - Default" msgstr "攝影機視角 - 默認" @@ -6334,7 +6341,7 @@ msgid "Camera Angle - Right side" msgstr "攝影機視角 - 右面" msgid "Select all objects" -msgstr "選擇所有對象" +msgstr "選擇所有物件" msgid "Gizmo move" msgstr "線框移動" @@ -6388,16 +6395,16 @@ msgid "Gizmo" msgstr "" msgid "Set extruder number for the objects and parts" -msgstr "設置對象、零件使用的擠出機編號" +msgstr "設置物件、零件使用的擠出機編號" msgid "Delete objects, parts, modifiers " -msgstr "刪除對象、零件、修改器" +msgstr "刪除物件、零件、修改器" msgid "Space" msgstr "空格鍵" msgid "Select the object/part and press space to change the name" -msgstr "選中對象、零件,按空格可修改名稱" +msgstr "選中物件、零件,按空格可修改名稱" msgid "Mouse click" msgstr "滑鼠點擊" @@ -6424,7 +6431,7 @@ msgid "On/Off one layer mode of the vertical slider" msgstr "開啟/關閉垂直滑動條的單層模式" msgid "On/Off g-code window" -msgstr "" +msgstr "開啟/關閉 g-code 視窗" msgid "Move slider 5x faster" msgstr "5倍速移動滑動條" @@ -6440,18 +6447,18 @@ msgid "version %s update information :" msgstr "版本 %s 更新資訊" msgid "Network plug-in update" -msgstr "網路外掛套件升級" +msgstr "網路插件升級" msgid "" "Click OK to update the Network plug-in when Bambu Studio launches next time." -msgstr "按一下「確定」以在下次啟動 Bambu Studio 時更新網路外掛套件" +msgstr "按一下「確定」以在下次啟動 Bambu Studio 時更新網路插件" #, c-format, boost-format msgid "A new Network plug-in(%s) available, Do you want to install it?" -msgstr "新的網路外掛套件(%s) 可用,您是否需要安裝它?" +msgstr "新的網路插件(%s) 可用,您是否需要安裝它?" msgid "New version of Bambu Studio" -msgstr "新版本的Bambu Studio" +msgstr "新版本的 Bambu Studio" msgid "Don't remind me of this version again" msgstr "此版本不再提示" @@ -6461,13 +6468,13 @@ msgstr "區域網路連接失敗 (傳送列印作業)" msgid "" "Step 1, please confirm Bambu Studio and your printer are in the same LAN." -msgstr "第1步,請確認Bambu Studio和您的3D列印機在同一個區域網路上。" +msgstr "第1步,請確認 Bambu Studio 和您的3D列印機在同一個區域網路上。" msgid "" "Step 2, if the IP and Access Code below are different from the actual values " "on your printer, please correct them." msgstr "" -"步驟2, 如果下面的IP和訪問碼與3D列印機上的實際值不同,請輸入正確的值。" +"步驟2, 如果下面的 IP 和訪問碼與3D列印機上的實際值不同,請輸入正確的值。" msgid "IP" msgstr "" @@ -6476,10 +6483,10 @@ msgid "Access Code" msgstr "訪問碼" msgid "Where to find your printer's IP and Access Code?" -msgstr "在哪裡可以找到3D列印機的IP和訪問碼?" +msgstr "在哪裡可以找到3D列印機的 IP 和訪問碼?" msgid "Error: IP or Access Code are not correct" -msgstr "錯誤:IP或訪問碼不正確" +msgstr "錯誤:IP 或訪問碼不正確" msgid "Model:" msgstr "型號:" @@ -6514,7 +6521,7 @@ msgstr "更新成功" msgid "" "Are you sure you want to update? This will take about 10 minutes. Do not " "turn off the power while the printer is updating." -msgstr "確定要更新嗎?更新需要大約10分鐘,在此期間請勿關閉電源。" +msgstr "確定要更新嗎?更新需要大約10分鐘,更新期間請勿關閉電源。" msgid "" "An important update was detected and needs to be run before printing can " @@ -6529,8 +6536,8 @@ msgid "" "printing. Do you want to update now? You can also update later on printer or " "update next time starting the studio." msgstr "" -"當前韌體版本異常,需要進行修復升級,否則無法繼續列印。你想現在就開始升級嗎?" -"你也可以稍後在3D列印機上升級,或者下一次啟動studio再升級。" +"目前韌體版本異常,需要進行修復升級,否則無法繼續列印。你想現在就開始升級嗎?" +"你也可以稍後在3D列印機上升級,或者下一次啟動 studio 再升級。" msgid "Extension Board" msgstr "擴展板" @@ -6560,22 +6567,22 @@ msgid "Loading repaired objects" msgstr "正在載入修復的物件。" msgid "Exporting 3mf file failed" -msgstr "匯出 3mf 文件失敗" +msgstr "匯出 3mf 檔案失敗" msgid "Import 3mf file failed" -msgstr "匯入 3mf 文件失敗" +msgstr "匯入 3mf 檔案失敗" msgid "Repaired 3mf file does not contain any object" -msgstr "已修復的 3mf 文件不包含任何物件" +msgstr "已修復的 3mf 檔案不包含任何物件" msgid "Repaired 3mf file contains more than one object" -msgstr "已修復的 3mf 文件包含了不止一個物件" +msgstr "已修復的 3mf 檔案包含了不止一個物件" msgid "Repaired 3mf file does not contain any volume" -msgstr "修復的 3mf 文件不包含任何零件" +msgstr "修復的 3mf 檔案不包含任何零件" msgid "Repaired 3mf file contains more than one volume" -msgstr "已修復的 3mf 文件包含多個零件" +msgstr "已修復的 3mf 檔案包含多個零件" msgid "Repair finished" msgstr "修復已完成" @@ -6585,7 +6592,7 @@ msgstr "修復被取消" #, boost-format msgid "Copying of file %1% to %2% failed: %3%" -msgstr "從%1%拷貝文件到%2%失敗:%3%" +msgstr "從 %1% 拷貝檔案到 %2% 失敗:%3%" msgid "Need to check the unsaved changes before configuration updates." msgstr "在組態檔更新之前需要檢查未儲存的參數變更。" @@ -6594,7 +6601,7 @@ msgid "Configuration package updated to " msgstr "組態檔已更新到" msgid "Open G-code file:" -msgstr "打開 G-code 文件:" +msgstr "打開 G-code 檔案:" msgid "" "One object has empty initial layer and can't be printed. Please Cut the " @@ -6603,7 +6610,7 @@ msgstr "模型出現空層無法列印。請切掉底部或打開支撐。" #, boost-format msgid "Object can't be printed for empty layer between %1% and %2%." -msgstr "模型在%1%和%2%之間出現空層,無法列印。" +msgstr "模型在 %1% 和 %2% 之間出現空層,無法列印。" #, boost-format msgid "Object: %1%" @@ -6672,7 +6679,7 @@ msgstr "多個" #, boost-format msgid "Failed to calculate line width of %1%. Can not get value of \"%2%\" " -msgstr "計算 %1%的線寬失敗。無法獲得 \"%2%\" 的值" +msgstr "計算 %1% 的線寬失敗。無法獲得 \"%2%\" 的值" msgid "" "Invalid spacing supplied to Flow::with_spacing(), check your layer height " @@ -6683,10 +6690,10 @@ msgid "undefined error" msgstr "未定義的錯誤" msgid "too many files" -msgstr "文件過多" +msgstr "檔案過多" msgid "file too large" -msgstr "文件太大" +msgstr "檔案太大" msgid "unsupported method" msgstr "不支援的壓縮方法" @@ -6698,13 +6705,13 @@ msgid "unsupported feature" msgstr "不支援的功能" msgid "failed finding central directory" -msgstr "查找中心目錄失敗" +msgstr 找不到核心目錄" msgid "not a ZIP archive" msgstr "不是一個 zip 壓縮檔" msgid "invalid header or corrupted" -msgstr "無效文件頭或文件已損壞" +msgstr "無效檔案頭或檔案已損壞" msgid "unsupported multidisk" msgstr "不支援多磁碟存檔" @@ -6719,40 +6726,40 @@ msgid "unexpected decompressed size" msgstr "意外的解壓縮大小" msgid "CRC check failed" -msgstr "CRC檢查失敗" +msgstr "CRC 檢查失敗" msgid "unsupported central directory size" -msgstr "不支援的中央目錄大小" +msgstr "不支援的核心目錄大小" msgid "allocation failed" msgstr "分配記憶體失敗" msgid "file open failed" -msgstr "文件開啟失敗" +msgstr "檔案開啟失敗" msgid "file create failed" -msgstr "文件建立失敗" +msgstr "檔案建立失敗" msgid "file write failed" -msgstr "文件寫入失敗" +msgstr "檔案寫入失敗" msgid "file read failed" -msgstr "文件讀取失敗" +msgstr "檔案讀取失敗" msgid "file close failed" -msgstr "文件關閉失敗" +msgstr "檔案關閉失敗" msgid "file seek failed" -msgstr "文件隨機訪問失敗" +msgstr "檔案隨機訪問失敗" msgid "file stat failed" -msgstr "文件統計資訊失敗" +msgstr "檔案統計資訊失敗" msgid "invalid parameter" msgstr "無效參數" msgid "invalid filename" -msgstr "無效的文件名" +msgstr "無效的檔案名" msgid "buffer too small" msgstr "緩衝區太小" @@ -6761,10 +6768,10 @@ msgid "internal error" msgstr "內部錯誤" msgid "file not found" -msgstr "文件未找到" +msgstr "檔案未找到" msgid "archive too large" -msgstr "存檔文件太大" +msgstr "存檔檔案太大" msgid "validation failed" msgstr "驗證失敗" @@ -6775,18 +6782,18 @@ msgstr "寫入回調失敗" #, boost-format msgid "" "%1% is too close to exclusion area, there may be collisions when printing." -msgstr "%1%離屏蔽區域太近,可能會發生碰撞。" +msgstr "%1% 離屏蔽區域太近,可能會發生碰撞。" #, boost-format msgid "%1% is too close to others, and collisions may be caused." -msgstr "%1%離其它對象太近,可能會發生碰撞。" +msgstr "%1% 離其它對象太近,可能會發生碰撞。" #, boost-format msgid "%1% is too tall, and collisions will be caused." -msgstr "%1%太高,會發生碰撞。" +msgstr "%1% 太高,會發生碰撞。" msgid " is too close to others, there may be collisions when printing." -msgstr "離其它對象太近,列印時可能會發生碰撞。" +msgstr "離其它物件太近,列印時可能會發生碰撞。" msgid " is too close to exclusion area, there may be collisions when printing." msgstr "離不可列印區域太近,列印時可能會發生碰撞。" @@ -6795,7 +6802,7 @@ msgid "Prime Tower" msgstr "擦拭塔" msgid " is too close to others, and collisions may be caused.\n" -msgstr "離其它對象太近,可能會發生碰撞。\n" +msgstr "離其它物件太近,可能會發生碰撞。\n" msgid " is too close to exclusion area, and collisions will be caused.\n" msgstr "離不可列印區域太近,會發生碰撞。\n" @@ -6808,7 +6815,7 @@ msgstr "" "不能將溫度差異過大的線材一起列印。否則擠出機和噴嘴在列印中可能被堵塞或損壞" msgid "No extrusions under current settings." -msgstr "根據當前設定,不會產生任何列印。" +msgstr "根據目前設定,不會產生任何列印。" msgid "" "Smooth mode of timelapse is not supported when \"by object\" sequence is " @@ -6818,12 +6825,12 @@ msgstr "平滑模式的縮時錄影不支援在逐件列印模式下使用。" msgid "" "Please select \"By object\" print sequence to print multiple objects in " "spiral vase mode." -msgstr "請選擇逐件列印以支援在旋轉花瓶模式下列印多個物件。" +msgstr "請選擇逐件列印以支援在花瓶模式下列印多個物件。" msgid "" "The spiral vase mode does not work when an object contains more than one " "materials." -msgstr "不支援在包含多個線材的列印中使用旋轉花瓶模式。" +msgstr "不支援在包含多個線材的列印中使用花瓶模式。" #, boost-format msgid "The object %1% exceeds the maximum build volume height." @@ -6992,7 +6999,7 @@ msgid "Printer preset names" msgstr "3D列印機預設名" msgid "Hostname, IP or URL" -msgstr "主機名,IP或者URL" +msgstr "主機名,IP 或者 URL" msgid "" "Slic3r can upload G-code files to a printer host. This field should contain " @@ -7001,8 +7008,8 @@ msgid "" "name and password into the URL in the following format: https://username:" "password@your-octopi-address/" msgstr "" -"Slic3r 可以將 G-code 文件上傳到3D列印機主機。此欄位應包含3D列印機主機實例" -"的主機名、IP位址或URL。啟用基本身份驗證的Print host可以透過將使用者名稱和密碼" +"Slic3r 可以將 G-code 檔案上傳到3D列印機主機。此欄位應包含3D列印機主機實例" +"的主機名、IP 位址或 URL。啟用基本身份驗證的3D列印主機可以透過將使用者名稱和密碼" "放入以下格式的URL中來訪問:https://username:password@your-octopi-address/" msgid "Device UI" @@ -7010,7 +7017,7 @@ msgstr "設備使用者界面" msgid "" "Specify the URL of your device user interface if it's not same as print_host" -msgstr "如果3D列印機的設備使用者界面的URL不同,請在此指定。" +msgstr "如果3D列印機的設備使用者界面的 URL 不同,請在此指定。" msgid "API Key / Password" msgstr "" @@ -7019,7 +7026,7 @@ msgid "" "Slic3r can upload G-code files to a printer host. This field should contain " "the API Key or the password required for authentication." msgstr "" -"Slic3r 可以將 G-code 文件上傳到3D列印機主機。此欄位應包含用於身份驗證的API" +"Slic3r 可以將 G-code 檔案上傳到3D列印機主機。此欄位應包含用於身份驗證的API" "金鑰或密碼。" msgid "Name of the printer" @@ -7033,8 +7040,8 @@ msgid "" "in crt/pem format. If left blank, the default OS CA certificate repository " "is used." msgstr "" -"可以為HTTPS OctoPrint連接指定自訂CA憑證文件,格式為crt/pem。如果留空,則使用" -"預設的操作系統CA憑證儲存庫。" +"可以為 HTTPS OctoPrint 連接指定自訂 CA憑證檔案,格式為 crt/pem。如果留空,則使用" +"預設的操作系統 CA憑證儲存庫。" msgid "User" msgstr "使用者名稱" @@ -7043,14 +7050,14 @@ msgid "Password" msgstr "密碼" msgid "Ignore HTTPS certificate revocation checks" -msgstr "忽略HTTPS憑證吊銷檢查" +msgstr "忽略 HTTPS憑證吊銷檢查" msgid "" "Ignore HTTPS certificate revocation checks in case of missing or offline " "distribution points. One may want to enable this option for self signed " "certificates if connection fails." msgstr "" -"在缺少或離線分發點的情況下忽略HTTPS憑證吊銷檢查。如果連接失敗,可以啟用此選項" +"在缺少或離線分發點的情況下忽略 HTTPS憑證吊銷檢查。如果連接失敗,可以啟用此選項" "來處理自簽名憑證。" msgid "Names of presets related to the physical printer" @@ -7659,7 +7666,7 @@ msgid "" "has slight overflow or underflow" msgstr "" "線材經過融化後凝固可能會產生體積差異。這個設置會等比例改變所有擠出走線的擠出" -"量。推薦的範圍為0.95到1.05。發現大平層模型的頂面有輕微的缺料或多料時,或許可" +"量。推薦的範圍為 0.95 到 1.05。發現大平層模型的頂面有輕微的缺料或多料時,或許可" "以嘗試微調這個參數。" msgid "Enable pressure advance" @@ -7748,7 +7755,7 @@ msgstr "切換線材時,卸載舊的線材所需時間。只用於統計資訊 msgid "" "Filament diameter is used to calculate extrusion in gcode, so it's important " "and should be accurate" -msgstr "線材直徑被用於計算G-code文件中的擠出量。因此很重要,應盡可能精確。" +msgstr "線材直徑被用於計算 G-code 檔案中的擠出量。因此很重要,應盡可能精確。" msgid "Shrinkage" msgstr "耗材收縮率" @@ -8067,7 +8074,7 @@ msgstr "" msgid "" "Acceleration of initial layer. Using a lower value can improve build plate " "adhensive" -msgstr "首層加速度。使用較低值可以改善和構建板的黏接。" +msgstr "首層加速度。使用較低值可以改善和列印板的黏接。" msgid "Enable accel_to_decel" msgstr "啟用煞車速度" @@ -8225,7 +8232,7 @@ msgid "" "Enable this to get a G-code file which has G2 and G3 moves. And the fitting " "tolerance is same with resolution" msgstr "" -"打開這個設置,匯出的G-code將包含G2 G3指令。圓弧擬合的容許值和精度相同。" +"打開這個設置,匯出的 G-code 將包含G2 G3指令。圓弧擬合的容許值和精度相同。" msgid "Add line number" msgstr "標註行號" @@ -8273,7 +8280,7 @@ msgid "HRC" msgstr "洛氏硬度" msgid "Printer structure" -msgstr "" +msgstr "3D列印機結構" msgid "The physical arrangement and components of a printing device" msgstr "" @@ -8333,10 +8340,10 @@ msgstr "" "設為0禁用此選項" msgid "Time cost" -msgstr "" +msgstr "時間成本" msgid "The printer cost per hour" -msgstr "" +msgstr "3D列印機每小時成本" msgid "money/h" msgstr "" @@ -8355,16 +8362,16 @@ msgid "Enable this if printer support air filtration" msgstr "" msgid "G-code flavor" -msgstr "G-code風格" +msgstr "G-code 風格" msgid "What kind of gcode the printer is compatible with" -msgstr "3D列印機相容的G-code風格'" +msgstr "3D列印機相容的 G-code 風格'" msgid "Klipper" msgstr "" msgid "Label objects" -msgstr "標註模型" +msgstr "標註物件" msgid "" "Enable this to add comments into the G-Code labeling print moves with what " @@ -8374,13 +8381,13 @@ msgid "" msgstr "" msgid "Exclude objects" -msgstr "對象排除" +msgstr "物件排除" msgid "Enable this option to add EXCLUDE OBJECT command in g-code" -msgstr "開啟此選項以支援對象排除" +msgstr "開啟此選項以支援物件排除" msgid "Verbose G-code" -msgstr "注釋G-code" +msgstr "詳細 G-code" msgid "" "Enable this to get a commented G-code file, with each line explained by a " @@ -8476,7 +8483,7 @@ msgid "Print speed of ironing lines" msgstr "熨燙的列印速度" msgid "Ironing angle" -msgstr "" +msgstr "熨燙角度" msgid "" "The angle ironing is done at. A negative number disables this function and " @@ -8484,7 +8491,7 @@ msgid "" msgstr "" msgid "This gcode part is inserted at every layer change after lift z" -msgstr "在每次換層抬升Z高度之後插入這段G-code。" +msgstr "在每次換層抬升Z高度之後插入這段 G-code。" msgid "Supports silent mode" msgstr "支援靜音模式" @@ -8497,10 +8504,10 @@ msgstr "機器是否支援使用低加速度列印的靜音模式。" msgid "" "This G-code will be used as a code for the pause print. User can insert " "pause G-code in gcode viewer" -msgstr "該G-code用於暫停列印。您可以在gcode預覽中插入暫停G-code" +msgstr "該 G-code 用於暫停列印。您可以在 gcode 預覽中插入暫停 G-code" msgid "This G-code will be used as a custom code" -msgstr "該G-code是訂製化指令" +msgstr "該 G-code 是訂製化指令" msgid "Maximum speed X" msgstr "X最大速度" @@ -8715,7 +8722,7 @@ msgstr "主機類型" msgid "" "Slic3r can upload G-code files to a printer host. This field must contain " "the kind of the host." -msgstr "Slic3r可以將G-code文件上傳到3D列印機主機。此欄位必須包含主機類型。" +msgstr "Slic3r 可以將 G-code 檔案上傳到3D列印機主機。此欄位必須包含主機類型。" msgid "Nozzle volume" msgstr "噴嘴內腔體積" @@ -8777,16 +8784,16 @@ msgid "" "model and save printing time, but make slicing and G-code generating slower" msgstr "" "當空駛完全在填充區域內時不觸發回抽。這意味著即使漏料也是不可見的。對於複雜模" -"型,該設置能夠減少回抽次數以及列印時長,但是會造成G-code產生變慢" +"型,該設置能夠減少回抽次數以及列印時長,但是會造成 G-code 產生變慢" msgid "Enable" msgstr "開啟" msgid "Filename format" -msgstr "檔案名格式" +msgstr "檔案名稱格式" msgid "User can self-define the project file name when export" -msgstr "使用者可以自訂匯出項目文件的名稱。" +msgstr "使用者可以自訂匯出項目檔案的名稱。" msgid "Make overhang printable" msgstr "懸垂可列印化" @@ -8884,14 +8891,14 @@ msgid "" "Object will be raised by this number of support layers. Use this function to " "avoid wrapping when print ABS" msgstr "" -"模型會在相應層數的支撐上抬高進行列印。使用該功能通常用於列印ABS時翹曲。" +"模型會在相應層數的支撐上抬高進行列印。使用該功能通常用於列印 ABS 時翹曲。" msgid "" "G-code path is genereated after simplifing the contour of model to avoid too " "much points and gcode lines in gcode file. Smaller value means higher " "resolution and more time to slice" msgstr "" -"為了避免G-code文件中過密集的點和走線,G-code走線通常是在簡化模型的外輪廓之後" +"為了避免 G-code 檔案中過密集的點和走線,G-code走線通常是在簡化模型的外輪廓之後" "產生。越小的數值代表更高的解析度,同時需要更長的切片時間。" msgid "Travel distance threshold" @@ -9150,7 +9157,7 @@ msgid "Speed of internal solid infill, not the top and bottom surface" msgstr "內部實心填充的速度,不是頂面和底面。" msgid "Spiral vase" -msgstr "旋轉花瓶" +msgstr "花瓶模式" msgid "" "Spiralize smooths out the z moves of the outer contour. And turns a solid " @@ -9291,7 +9298,7 @@ msgid "Use this setting to rotate the support pattern on the horizontal plane." msgstr "設置支撐圖案在水平面的旋轉角度。" msgid "On build plate only" -msgstr "僅在構建板產生" +msgstr "僅在列印板產生" msgid "Don't create support on model surface, only on build plate" msgstr "不在模型表面上產生支撐,只在熱床上產生。" @@ -9944,7 +9951,7 @@ msgid " doesn't work at 100%% density " msgstr " 填充圖案不支援 100%% 密度" msgid "Invalid value when spiral vase mode is enabled: " -msgstr "旋轉花瓶模式下非法的值" +msgstr "花瓶模式下非法的值" msgid "too large line width " msgstr "線寬過大" @@ -9971,10 +9978,10 @@ msgid "Load cached slicing data from directory" msgstr "從目錄匯入快取的切片數據" msgid "Export STL" -msgstr "匯出STL文件" +msgstr "匯出STL檔案" msgid "Export the objects as multiple STL." -msgstr "將對象匯出為多個STL文件" +msgstr "將對象匯出為多個STL檔案" msgid "Slice" msgstr "切片" @@ -10037,7 +10044,7 @@ msgid "Export Settings" msgstr "匯出配置" msgid "Export settings to a file." -msgstr "匯出配置到文件。" +msgstr "匯出配置到檔案。" msgid "Send progress to pipe" msgstr "將進度傳送到管道" @@ -10098,13 +10105,13 @@ msgid "Load General Settings" msgstr "載入通用設置" msgid "Load process/machine settings from the specified file" -msgstr "從指定文件載入工藝/3D列印機設置" +msgstr "從指定檔案載入工藝/3D列印機設置" msgid "Load Filament Settings" msgstr "載入線材設置" msgid "Load filament settings from the specified file list" -msgstr "從指定文件載入線材設置" +msgstr "從指定檔案載入線材設置" msgid "Skip Objects" msgstr "零件跳過" @@ -10118,7 +10125,7 @@ msgstr "在使用最新設置時載入最新的進程/機器設置" msgid "" "load uptodate process/machine settings from the specified file when using " "uptodate" -msgstr "在使用最新設置時,從指定的文件中載入最新的進程/機器設置。" +msgstr "在使用最新設置時,從指定的檔案中載入最新的進程/機器設置。" msgid "Data directory" msgstr "" @@ -10133,7 +10140,7 @@ msgid "Output directory" msgstr "輸出路徑" msgid "Output directory for the exported files." -msgstr "匯出文件的輸出路徑。" +msgstr "匯出檔案的輸出路徑。" msgid "Debug level" msgstr "除錯等級" @@ -10152,7 +10159,7 @@ msgid "Load custom gcode from json" msgstr "" msgid "Error in zip archive" -msgstr "zip文件中存在錯誤" +msgstr "zip檔案中存在錯誤" msgid "Generating walls" msgstr "產生內外牆" @@ -10197,7 +10204,7 @@ msgid "" "No layers were detected. You might want to repair your STL file(s) or check " "their size or thickness and retry.\n" msgstr "" -"沒有檢測到層。您可能需要修復STL文件,或檢查模型尺寸、厚度等,之後再重試。\n" +"沒有檢測到層。您可能需要修復STL檔案,或檢查模型尺寸、厚度等,之後再重試。\n" msgid "" "An object's XY size compensation will not be used because it is also color-" @@ -10240,16 +10247,16 @@ msgstr "支撐:正在生長層%d的樹枝" msgid "" "Unknown file format. Input file must have .stl, .obj, .amf(.xml) extension." -msgstr "未知的檔案格式。輸入文件的副檔名必須為.stl、.obj 或 .amf(.xml)。" +msgstr "未知的檔案格式。輸入檔案的副檔名必須為.stl、.obj 或 .amf(.xml)。" msgid "Loading of a model file failed." -msgstr "載入模型文件失敗。" +msgstr "載入模型檔案失敗。" msgid "The supplied file couldn't be read because it's empty" -msgstr "無法讀取提供的文件,因為該文件為空。" +msgstr "無法讀取提供的檔案,因為該檔案為空。" msgid "Unknown file format. Input file must have .3mf or .zip.amf extension." -msgstr "未知的檔案格式。輸入文件的副檔名必須為.3mf或.zip .amf。" +msgstr "未知的檔案格式。輸入檔案的副檔名必須為.3mf或.zip .amf。" msgid "Canceled" msgstr "已取消" @@ -10258,16 +10265,16 @@ msgid "load_obj: failed to parse" msgstr "載入對象:無法分析" msgid "The file contains polygons with more than 4 vertices." -msgstr "該文件包含頂點超過4個的多邊形。" +msgstr "該檔案包含頂點超過4個的多邊形。" msgid "The file contains polygons with less than 2 vertices." -msgstr "該文件包含頂點少於2個的多邊形。" +msgstr "該檔案包含頂點少於2個的多邊形。" msgid "The file contains invalid vertex index." -msgstr "文件包含無效的頂點索引。" +msgstr "檔案包含無效的頂點索引。" msgid "This OBJ file couldn't be read because it's empty." -msgstr "無法讀取此OBJ文件,因為它是空的。" +msgstr "無法讀取此OBJ檔案,因為它是空的。" msgid "Flow Rate Calibration" msgstr "流量比例校準" @@ -10332,7 +10339,7 @@ msgid "Max Volumetric Speed" msgstr "最大容積速度" msgid "Please enter the name you want to save to printer." -msgstr "請輸入要保存到3D列印機的名稱。" +msgstr "請輸入要儲存到3D列印機的名稱。" msgid "The name cannot exceed 40 characters." msgstr "名稱不能超過40個字元。" @@ -10385,7 +10392,7 @@ msgid "The failed test result has been dropped." msgstr "測試失敗的結果已被刪除。" msgid "Flow Dynamics Calibration result has been saved to the printer" -msgstr "動態流量校準的結果已保存至3D列印機。" +msgstr "動態流量校準的結果已儲存至3D列印機。" msgid "Internal Error" msgstr "內部錯誤" @@ -10394,10 +10401,10 @@ msgid "Please select at least one filament for calibration" msgstr "請至少選擇一種線材進行校準。" msgid "Flow rate calibration result has been saved to preset" -msgstr "流量比例校準結果已保存到預設" +msgstr "流量比例校準結果已儲存到預設" msgid "Max volumetric speed calibration result has been saved to preset" -msgstr "最大體積速度校準結果已保存到預設值" +msgstr "最大體積速度校準結果已儲存到預設值" msgid "When do you need Flow Dynamics Calibration" msgstr "在什麼情況下需要進行動態流量校準" @@ -10413,7 +10420,7 @@ msgid "" "filament setting." msgstr "" "我們現在已經為不同的列印線材新增了自動校準功能,該功能是完全自動化的,並且結" -"果將保存在3D列印機中以供將來使用。您只需要在以下有限情況下進行校準:\n" +"果將儲存在3D列印機中以供將來使用。您只需要在以下有限情況下進行校準:\n" "1. 如果您引入了不同品牌/型號的新列印線材,或者列印線材受潮;\n" "2. 如果噴嘴磨損或更換了新的噴嘴;\n" "3. 如果您在列印線材設置中更改了最大體積速度或列印溫度。" @@ -10559,7 +10566,7 @@ msgstr "失敗" msgid "" "Only one of the results with the same name will be saved. Are you sure you " "want to overrides the other results?" -msgstr "相同名稱的結果只會保存一個。您確定要覆蓋其他結果嗎?" +msgstr "相同名稱的結果只會儲存一個。您確定要覆蓋其他結果嗎?" #, c-format, boost-format msgid "" @@ -10567,7 +10574,7 @@ msgid "" "Only one of the results with the same name is saved. Are you sure you want " "to overrides the historical result?" msgstr "" -"已經存在一個具有相同名稱的歷史校準結果:%s。相同名稱的結果只會保存一個。您確" +"已經存在一個具有相同名稱的歷史校準結果:%s。相同名稱的結果只會儲存一個。您確" "定要覆蓋歷史結果嗎?" msgid "Please find the best line on your plate" @@ -10580,7 +10587,7 @@ msgid "Input Value" msgstr "輸入值" msgid "Save to Filament Preset" -msgstr "保存到材料預設" +msgstr "儲存到材料預設" msgid "Preset" msgstr "預設" @@ -10598,7 +10605,7 @@ msgid "Please input a valid value (0.0 < flow ratio < 2.0)" msgstr "請輸入一個有效值(0.0<流量比<2.0)" msgid "Please enter the name of the preset you want to save." -msgstr "請輸入要保存的預設的名稱。" +msgstr "請輸入要儲存的預設的名稱。" msgid "Calibration1" msgstr "校準1" @@ -11166,9 +11173,9 @@ msgid "" "Orca Slicer supports slicing STEP files, providing smoother results than a " "lower resolution STL. Give it a try!" msgstr "" -"STEP文件\n" -"您知道嗎,通過切片STEP文件而不是STL文件可以提高列印質量。\n" -" Orcaslicer 支援切片STEP文件,提供比低解析度STL更平滑的結果。試試看!" +"STEP檔案\n" +"您知道嗎,通過切片STEP檔案而不是STL檔案可以提高列印質量。\n" +" Orcaslicer 支援切片STEP檔案,提供比低解析度STL更平滑的結果。試試看!" #: resources/data/hints.ini: [hint:Z seam location] msgid ""