import base64 from UM.Logger import Logger from cura.Snapshot import Snapshot from PyQt6.QtCore import QByteArray, QIODevice, QBuffer from ..Script import Script class CreateThumbnail(Script): def __init__(self): super().__init__() def _createSnapshot(self, width, height): Logger.log("d", "Creating thumbnail image...") try: return Snapshot.snapshot(width, height) except Exception: Logger.logException("w", "Failed to create snapshot image") def _encodeSnapshot(self, snapshot): Logger.log("d", "Encoding thumbnail image...") try: thumbnail_buffer = QBuffer() thumbnail_buffer.open(QBuffer.OpenModeFlag.ReadWrite) thumbnail_image = snapshot thumbnail_image.save(thumbnail_buffer, "PNG") base64_bytes = base64.b64encode(thumbnail_buffer.data()) base64_message = base64_bytes.decode('ascii') thumbnail_buffer.close() return base64_message except Exception: Logger.logException("w", "Failed to encode snapshot image") def _convertSnapshotToGcode(self, encoded_snapshot, width, height, chunk_size=78): gcode = [] use_thumbnail = self.getSettingValueByKey("use_thumbnail") use_star = self.getSettingValueByKey("use_star") encoded_snapshot_length = len(encoded_snapshot) image_type = "thumbnail" if use_thumbnail else "png" resolution_symbol = '*' if use_star else 'x' gcode.append(";") gcode.append("; {} begin {}{}{} {}".format( image_type, width, resolution_symbol, height, encoded_snapshot_length)) chunks = ["; {}".format(encoded_snapshot[i:i+chunk_size]) for i in range(0, len(encoded_snapshot), chunk_size)] gcode.extend(chunks) gcode.append("; {} end".format(image_type)) gcode.append(";") gcode.append("") return gcode def getSettingDataString(self): return """{ "name": "Create Thumbnail", "key": "CreateThumbnail", "metadata": {}, "version": 2, "settings": { "width": { "label": "Width", "description": "Width of the generated thumbnail", "unit": "px", "type": "int", "default_value": 32, "minimum_value": "0", "minimum_value_warning": "12", "maximum_value_warning": "800" }, "height": { "label": "Height", "description": "Height of the generated thumbnail", "unit": "px", "type": "int", "default_value": 32, "minimum_value": "0", "minimum_value_warning": "12", "maximum_value_warning": "600" }, "use_thumbnail": { "label": "Thumbnail Begin/End", "description": "Use Thumbnail Begin/End rather than PNG", "type": "bool", "default_value": true }, "use_star": { "label": "xxx*yyy", "description": "Use '*' instead of 'x' for size of image", "type": "bool", "default_value": false } } }""" def execute(self, data): width = self.getSettingValueByKey("width") height = self.getSettingValueByKey("height") snapshot = self._createSnapshot(width, height) if snapshot: encoded_snapshot = self._encodeSnapshot(snapshot) snapshot_gcode = self._convertSnapshotToGcode( encoded_snapshot, width, height) for layer in data: layer_index = data.index(layer) lines = data[layer_index].split("\n") for line in lines: if line.startswith(";Generated with Cura"): line_index = lines.index(line) insert_index = line_index + 1 lines[insert_index:insert_index] = snapshot_gcode break final_lines = "\n".join(lines) data[layer_index] = final_lines return data