Skip to content

Instantly share code, notes, and snippets.

@boomsya
Last active March 3, 2024 08:02
Show Gist options
  • Save boomsya/2df000b2b3f64b88a9c2ecbda85d4fa1 to your computer and use it in GitHub Desktop.
Save boomsya/2df000b2b3f64b88a9c2ecbda85d4fa1 to your computer and use it in GitHub Desktop.
Enabling Ender 3 V3 KE Model Preview (Thumbnail) With Cura 5+
# Cura V3KE Thumbnail creator
# Kolio (boomsya@gmail.com)
#
# This only works with Cura 5.0+
import base64
from UM.Logger import Logger
from cura.Snapshot import Snapshot
from PyQt6.QtCore import QByteArray, QIODevice, QBuffer
from ..Script import Script
class CreateV3KEThumbnail(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")
thumbnail_data = thumbnail_buffer.data()
thumbnail_length = thumbnail_data.length()
base64_bytes = base64.b64encode(thumbnail_data)
base64_message = base64_bytes.decode('ascii')
thumbnail_buffer.close()
Logger.log("d", "Snapshot thumbnail_length={}".format(thumbnail_length))
return (base64_message, thumbnail_length)
except Exception:
Logger.logException("w", "Failed to encode snapshot image")
def _convertSnapshotToGcode(self, thumbnail_length, encoded_snapshot, width, height, chunk_size=76):
Logger.log("d", "Converting snapshot into gcode...")
gcode = []
# these numbers appear to be related to image size, guessing here
x1 = (int)(width/80) + 1
x2 = width - x1
header = "; png begin {}*{} {} {} {} {}".format(width, height, thumbnail_length, x1, x2, 192)
Logger.log("d", "Gcode header={}".format(header))
gcode.append(header)
chunks = ["; {}".format(encoded_snapshot[i:i+chunk_size])
for i in range(0, len(encoded_snapshot), chunk_size)]
gcode.extend(chunks)
gcode.append("; png end")
return gcode
def _convertSnapshotToThumbnailGcode(self, thumbnail_length, encoded_snapshot, width, height, chunk_size=76):
Logger.log("d", "Converting snapshot into thumbnail gcode...")
gcode = []
# these numbers appear to be related to image size, guessing here
header = "; thumbnail begin {} {} {}".format(width, height, thumbnail_length)
Logger.log("d", "Gcode header={}".format(header))
gcode.append(header)
chunks = ["; {}".format(encoded_snapshot[i:i+chunk_size])
for i in range(0, len(encoded_snapshot), chunk_size)]
gcode.extend(chunks)
gcode.append("; thumbnail end")
gcode.append(";")
gcode.append("")
return gcode
def getSettingDataString(self):
return """{
"name": "Create Thumbnail (Ender 3 V3 KE)",
"key": "CreateV3KEThumbnail",
"metadata": {},
"version": 2,
"settings":
{}
}"""
def execute(self, data):
width1 = 96
height1 = 96
width2 = 300
height2 = 300
Logger.log("d", "CreateV3KEThumbnail Plugin start")
snapshot1 = self._createSnapshot(width1, height1)
snapshot2 = self._createSnapshot(width2, height2)
if snapshot1 and snapshot2:
Logger.log("d", "Snapshots created")
(encoded_snapshot, thumbnail_length) = self._encodeSnapshot(snapshot1)
snapshot_gcode1 = self._convertSnapshotToGcode(thumbnail_length, encoded_snapshot, width1, height1)
(encoded_snapshot, thumbnail_length) = self._encodeSnapshot(snapshot2)
snapshot_gcode2 = self._convertSnapshotToGcode(thumbnail_length, encoded_snapshot, width2, height2)
snapshot_gcode3 = self._convertSnapshotToThumbnailGcode(thumbnail_length, encoded_snapshot, width2, height2)
Logger.log("d", "Layer count={}".format(len(data)))
if len(data) > 0:
# The Ender-3 V3 KE Neo really wants this at the top of the file
layer_index = 0
lines = data[layer_index].split("\n")
Logger.log("d", "Adding snapshot1 gcode lines (len={})".format(len(snapshot_gcode1)))
Logger.log("d", "Adding snapshot2 gcode lines (len={})".format(len(snapshot_gcode2)))
Logger.log("d", "Adding snapshot3 gcode lines (len={})".format(len(snapshot_gcode3)))
lines[0:0] = snapshot_gcode1 + snapshot_gcode2 + snapshot_gcode3
final_lines = "\n".join(lines)
data[layer_index] = final_lines
Logger.log("d", "CreateV3KEThumbnail Plugin end")
return data
The Creality Ender 3 V3 KE include a convenient feature that allows you to preview the model you are printing before starting the print. This feature works great if you use the Creality Slicer that is included with the printer, but if you are using Cura, the model preview will not work by default.
If you are using Cura 5.0 or later, you can use a post processing script to add the image in the format that the Ender 3 V3 KE expects.
Installation Steps
1. Download the following script CreateV3KEThumbnail.py and save it to the Cura directory
C:\Program Files\Ultimaker Cura 5.X.X\share\cura\plugins\PostProcessingPlugin\scripts
2. To enable the script in Cura:
1. If Cura is open, close and relaunch it to ensure the new script is available
2. Navigate to Extensions » Post Processing » Modify G-Code
3. Click Add a script, then choose "Create Thumbnail (Ender 3 V3 KE)"
4. Click Close
5. After you add a model, you’ll know the script is enabled if you see a small </> icon near the slice button
3. You can now slice your model and save it to the USB-stick or local drive as normal, and you will see the print preview when you select the model on your Ender 3 V3 KE.
@boomsya
Copy link
Author

boomsya commented Jan 18, 2024

20240118_140032
20240118_141255

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment