Load and save texture data mapping in 3MF

CURA-12566
This commit is contained in:
Erwan MATHIEU 2025-06-19 15:57:07 +02:00
parent 7248624315
commit 3c04680c71
2 changed files with 28 additions and 7 deletions

View file

@ -1,13 +1,14 @@
# Copyright (c) 2021-2022 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
import json
import os.path
import zipfile
from typing import List, Optional, Union, TYPE_CHECKING, cast
import pySavitar as Savitar
import numpy
from PyQt6.QtGui import QImage
from PyQt6.QtCore import QBuffer
from PyQt6.QtGui import QImage, QImageReader
from UM.Logger import Logger
from UM.Math.Matrix import Matrix
@ -232,11 +233,27 @@ class ThreeMFReader(MeshReader):
if texture_path != "" and archive is not None:
texture_data = archive.open(texture_path).read()
texture_image = QImage.fromData(texture_data, "PNG")
texture_buffer = QBuffer()
texture_buffer.open(QBuffer.OpenModeFlag.ReadWrite)
texture_buffer.write(texture_data)
image_reader = QImageReader(texture_buffer, b"png")
texture_buffer.seek(0)
texture_image = image_reader.read()
texture = Texture(OpenGL.getInstance())
texture.setImage(texture_image)
sliceable_decorator.setPaintTexture(texture)
texture_buffer.seek(0)
data_mapping_desc = image_reader.text("Description")
if data_mapping_desc != "":
data_mapping = json.loads(data_mapping_desc)
for key, value in data_mapping.items():
# Tuples are stored as lists in json, restore them back to tuples
data_mapping[key] = tuple(value)
sliceable_decorator.setTextureDataMapping(data_mapping)
return um_node
def _read(self, file_name: str) -> Union[SceneNode, List[SceneNode]]:

View file

@ -29,7 +29,7 @@ from cura.Scene.CuraSceneNode import CuraSceneNode
from cura.Snapshot import Snapshot
from PyQt6.QtCore import Qt, QBuffer
from PyQt6.QtGui import QImage, QPainter
from PyQt6.QtGui import QImage, QPainter, QImageWriter
import pySavitar as Savitar
from .UCPDialog import UCPDialog
@ -163,12 +163,16 @@ class ThreeMFWriter(MeshWriter):
if texture is not None and archive is not None and uv_coordinates_array is not None and len(uv_coordinates_array) > 0:
texture_image = texture.getImage()
if texture_image is not None:
texture_path = f"{TEXTURES_PATH}/{id(um_node)}.png"
texture_buffer = QBuffer()
texture_buffer.open(QBuffer.OpenModeFlag.ReadWrite)
texture_image.save(texture_buffer, "PNG")
image_writer = QImageWriter(texture_buffer, b"png")
texture_data_mapping = um_node.callDecoration("getTextureDataMapping")
if texture_data_mapping is not None:
image_writer.setText("Description", json.dumps(texture_data_mapping))
image_writer.write(texture_image)
texture_path = f"{TEXTURES_PATH}/{id(um_node)}.png"
texture_file = zipfile.ZipInfo(texture_path)
# Don't try to compress texture file, because the PNG is pretty much as compact as it will get
archive.writestr(texture_file, texture_buffer.data())