diff --git a/io_scene_gltf2/__init__.py b/io_scene_gltf2/__init__.py index 3c0833407df27e97da4b460c83d22b12ab49f95e..c00da55f414b435cd0061be794623720e63edf1b 100755 --- a/io_scene_gltf2/__init__.py +++ b/io_scene_gltf2/__init__.py @@ -15,7 +15,7 @@ bl_info = { 'name': 'glTF 2.0 format', 'author': 'Julien Duroure, Norbert Nopper, Urs Hanselmann, Moritz Becher, Benjamin SchmithĂĽsen, Jim Eckerlein, and many external contributors', - "version": (1, 2, 2), + "version": (1, 2, 3), 'blender': (2, 81, 6), 'location': 'File > Import-Export', 'description': 'Import-Export as glTF 2.0', @@ -113,18 +113,18 @@ class ExportGLTF2_Base: export_image_format: EnumProperty( name='Images', - items=(('NAME', 'Automatic', - 'Determine the image format from the blender image name'), + items=(('AUTO', 'Automatic', + 'Save PNGs as PNGs and JPEGs as JPEGs.\n' + 'If neither one, use PNG'), ('JPEG', 'JPEG Format (.jpg)', - 'Encode and save textures as .jpg files. Be aware of a possible loss in quality'), - ('PNG', 'PNG Format (.png)', - 'Encode and save textures as .png files') + 'Save images as JPEGs. (Images that need alpha are saved as PNGs though.)\n' + 'Be aware of a possible loss in quality'), ), description=( 'Output format for images. PNG is lossless and generally preferred, but JPEG might be preferable for web ' 'applications due to the smaller file size' ), - default='NAME' + default='AUTO' ) export_texture_dir: StringProperty( diff --git a/io_scene_gltf2/blender/exp/gltf2_blender_gather_image.py b/io_scene_gltf2/blender/exp/gltf2_blender_gather_image.py index 81da3780c6437d0557457c613417cee78491195d..ee184cdc8c525da600a0aeb7e4e866966a8a0417 100755 --- a/io_scene_gltf2/blender/exp/gltf2_blender_gather_image.py +++ b/io_scene_gltf2/blender/exp/gltf2_blender_gather_image.py @@ -42,7 +42,7 @@ def gather_image( # The export image has no data return None - mime_type = __gather_mime_type(blender_shader_sockets_or_texture_slots, export_settings) + mime_type = __gather_mime_type(blender_shader_sockets_or_texture_slots, image_data, export_settings) name = __gather_name(blender_shader_sockets_or_texture_slots, export_settings) uri = __gather_uri(image_data, mime_type, name, export_settings) @@ -95,27 +95,20 @@ def __gather_extras(sockets_or_slots, export_settings): return None -def __gather_mime_type(sockets_or_slots, export_settings): +def __gather_mime_type(sockets_or_slots, export_image, export_settings): # force png if Alpha contained so we can export alpha for socket in sockets_or_slots: if socket.name == "Alpha": return "image/png" - if export_settings["gltf_image_format"] == "NAME": - extension = __get_extension_from_slot(sockets_or_slots, export_settings) - extension = extension.lower() - if extension in [".jpeg", ".jpg", ".png"]: - return { - ".jpeg": "image/jpeg", - ".jpg": "image/jpeg", - ".png": "image/png", - }[extension] + if export_settings["gltf_image_format"] == "AUTO": + image = export_image.blender_image() + if image is not None and image.file_format == 'JPEG': + return "image/jpeg" return "image/png" elif export_settings["gltf_image_format"] == "JPEG": return "image/jpeg" - else: - return "image/png" def __gather_name(sockets_or_slots, export_settings): @@ -246,23 +239,3 @@ def __get_texname_from_slot(sockets_or_slots, export_settings): elif isinstance(sockets_or_slots[0], bpy.types.MaterialTextureSlot): return sockets_or_slots[0].texture.image.name - -@cached -def __get_extension_from_slot(sockets_or_slots, export_settings): - if __is_socket(sockets_or_slots): - for socket in sockets_or_slots: - node = __get_tex_from_socket(socket, export_settings) - if node is not None: - image_name = node.shader_node.image.name - filepath = bpy.data.images[image_name].filepath - name, extension = os.path.splitext(filepath) - if extension: - return extension - return '.png' - - elif isinstance(sockets_or_slots[0], bpy.types.MaterialTextureSlot): - image_name = sockets_or_slots[0].texture.image.name - filepath = bpy.data.images[image_name].filepath - name, extension = os.path.splitext(filepath) - return extension - diff --git a/io_scene_gltf2/blender/exp/gltf2_blender_image.py b/io_scene_gltf2/blender/exp/gltf2_blender_image.py index 4a7818fe3efd7858da6ee2e9e5beca636bfefd27..a21dcba52d595b57e21bc2581e1abd30e97274fb 100644 --- a/io_scene_gltf2/blender/exp/gltf2_blender_image.py +++ b/io_scene_gltf2/blender/exp/gltf2_blender_image.py @@ -86,15 +86,18 @@ class ExportImage: def empty(self) -> bool: return not self.fills + def blender_image(self) -> Optional[bpy.types.Image]: + """If there's an existing Blender image we can use, + returns it. Otherwise (if channels need packing), + returns None. + """ + if self.__on_happy_path(): + for fill in self.fills.values(): + return fill.image + return None + def __on_happy_path(self) -> bool: - # Whether there is an existing Blender image we can use for this - # ExportImage because all the channels come from the matching - # channel of that image, eg. - # - # self.fills = { - # Channel.R: FillImage(image=im, src_chan=Channel.R), - # Channel.G: FillImage(image=im, src_chan=Channel.G), - # } + # All src_chans match their dst_chan and come from the same image return ( all(isinstance(fill, FillImage) for fill in self.fills.values()) and all(dst_chan == fill.src_chan for dst_chan, fill in self.fills.items()) and @@ -115,8 +118,7 @@ class ExportImage: return self.__encode_unhappy() def __encode_happy(self) -> bytes: - for fill in self.fills.values(): - return self.__encode_from_image(fill.image) + return self.__encode_from_image(self.blender_image()) def __encode_unhappy(self) -> bytes: result = self.__encode_unhappy_with_compositor()