KhronosGroup / glTF-Blender-IO

Blender glTF 2.0 importer and exporter
https://docs.blender.org/manual/en/latest/addons/import_export/scene_gltf2.html
Apache License 2.0
1.48k stars 316 forks source link

Webp conversion fails for B&W images #2081

Open globglob3D opened 8 months ago

globglob3D commented 8 months ago

Describe the bug When exporting using the Webp format conversion it fails. This has to do with textures being of different sizes (accross different materials, which is weird). When textures are all the same size it's working fine.

Webp conversion fails when trying to export a B&W (8 bit depth) texture.

duplicate https://github.com/KhronosGroup/glTF-Blender-IO/issues/2077

The workaround for now is to convert the image to 24 bit depth with an image editing tool like Photoshop before trying to export your model in Blender.

To Reproduce Try to export to .glb with Webp image format.

.blend file/ .gltf webp_conversion_diff_sizes_error.zip

Version

Additional context 17:22:58 | INFO: Starting glTF 2.0 export 17:22:58 | INFO: Extracting primitive: Plane.004 WebP: Unsupported bytes per pixel: 1 for file: 'C:\Users\arthu\AppData\Local\Temp\tmp7xtctwa2\img' C:\Users\arthu\AppData\Local\Temp\tmp7xtctwa2\img: No error Traceback (most recent call last): File "C:\Program Files\Blender Foundation\Blender 4.0\4.0\scripts\addons\io_scene_gltf2__init.py", line 915, in execute return gltf2_blender_export.save(context, export_settings) File "C:\Program Files\Blender Foundation\Blender 4.0\4.0\scripts\addons\io_scene_gltf2\blender\exp\gltf2_blender_export.py", line 36, in save json, buffer = __export(export_settings) File "C:\Program Files\Blender Foundation\Blender 4.0\4.0\scripts\addons\io_scene_gltf2\blender\exp\gltf2_blender_export.py", line 53, in export gather_gltf(exporter, export_settings) File "C:\Program Files\Blender Foundation\Blender 4.0\4.0\scripts\addons\io_scene_gltf2\blender\exp\gltf2_blender_export.py", line 67, in gather_gltf active_scene_idx, scenes, animations = gltf2_blender_gather.gather_gltf2(export_settings) File "C:\Program Files\Blender Foundation\Blender 4.0\4.0\scripts\addons\io_scene_gltf2\blender\exp\gltf2_blender_gather.py", line 29, in gather_gltf2 scenes.append(gather_scene(blender_scene, export_settings)) File "C:\Program Files\Blender Foundation\Blender 4.0\4.0\scripts\addons\io_scene_gltf2\blender\exp\gltf2_blender_gather_cache.py", line 36, in wrapper_cached result = func(*args, **kwargs) File "C:\Program Files\Blender Foundation\Blender 4.0\4.0\scripts\addons\io_scene_gltf2\blender\exp\gltf2_blender_gather.py", line 70, in __gather_scene node = gltf2_blender_gather_nodes.gather_node( File "C:\Program Files\Blender Foundation\Blender 4.0\4.0\scripts\addons\io_scene_gltf2\blender\exp\gltf2_blender_gather_nodes.py", line 36, in gather_node mesh=gather_mesh(vnode, blender_object, export_settings), File "C:\Program Files\Blender Foundation\Blender 4.0\4.0\scripts\addons\io_scene_gltf2\blender\exp\gltf2_blender_gather_nodes.py", line 246, in gather_mesh result = gltf2_blender_gather_mesh.gather_mesh(blender_mesh, File "C:\Program Files\Blender Foundation\Blender 4.0\4.0\scripts\addons\io_scene_gltf2\blender\exp\gltf2_blender_gather_cache.py", line 36, in wrapper_cached result = func(*args, **kwargs) File "C:\Program Files\Blender Foundation\Blender 4.0\4.0\scripts\addons\io_scene_gltf2\blender\exp\gltf2_blender_gather_mesh.py", line 58, in gather_mesh primitives=gather_primitives(blender_mesh, uuid_for_skined_data, vertex_groups, modifiers, materials, export_settings), File "C:\Program Files\Blender Foundation\Blender 4.0\4.0\scripts\addons\io_scene_gltf2\blender\exp\gltf2_blender_gather_mesh.py", line 135, in gather_primitives return gltf2_blender_gather_primitives.gather_primitives(blender_mesh, File "C:\Program Files\Blender Foundation\Blender 4.0\4.0\scripts\addons\io_scene_gltf2\blender\exp\gltf2_blender_gather_cache.py", line 36, in wrapper_cached result = func(*args, *kwargs) File "C:\Program Files\Blender Foundation\Blender 4.0\4.0\scripts\addons\io_scene_gltf2\blender\exp\gltf2_blender_gather_primitives.py", line 57, in gather_primitives blender_primitives = __gather_cache_primitives(materials, blender_mesh, uuid_for_skined_data, File "C:\Program Files\Blender Foundation\Blender 4.0\4.0\scripts\addons\io_scene_gltf2\blender\exp\gltf2_blender_gather_cache.py", line 36, in wrapper_cached result = func(args, **kwargs) File "C:\Program Files\Blender Foundation\Blender 4.0\4.0\scripts\addons\io_scene_gltf2\blender\exp\gltf2_blender_gather_primitives.py", line 120, in gather_cache_primitives blender_primitives = gltf2_blender_gather_primitives_extract.extract_primitives( File "C:\Program Files\Blender Foundation\Blender 4.0\4.0\scripts\addons\io_scene_gltf2\blender\exp\gltf2_blender_gather_primitives_extract.py", line 27, in extract_primitives primitive_creator.material_uvmap_attribute_add() File "C:\Program Files\Blender Foundation\Blender 4.0\4.0\scripts\addons\io_scene_gltf2\blender\exp\gltf2_blender_gather_primitives_extract.py", line 398, in material_uvmap_attributeadd , material_info = get_base_material(material_idx, self.materials, self.export_settings) File "C:\Program Files\Blender Foundation\Blender 4.0\4.0\scripts\addons\io_scene_gltf2\blender\exp\material\gltf2_blender_gather_materials.py", line 456, in get_base_material material, material_info = gather_material( File "C:\Program Files\Blender Foundation\Blender 4.0\4.0\scripts\addons\io_scene_gltf2\blender\exp\gltf2_blender_gather_cache.py", line 36, in wrapper_cached result = func(*args, kwargs) File "C:\Program Files\Blender Foundation\Blender 4.0\4.0\scripts\addons\io_scene_gltf2\blender\exp\material\gltf2_blender_gather_materials.py", line 60, in gather_material pbr_metallic_roughness, uvmap_info_pbr_metallic_roughness, vc_info = gather_pbr_metallic_roughness(blender_material, orm_texture, export_settings) File "C:\Program Files\Blender Foundation\Blender 4.0\4.0\scripts\addons\io_scene_gltf2\blender\exp\material\gltf2_blender_gather_materials.py", line 294, in gather_pbr_metallic_roughness return gltf2_blender_gather_materials_pbr_metallic_roughness.gather_material_pbr_metallic_roughness( File "C:\Program Files\Blender Foundation\Blender 4.0\4.0\scripts\addons\io_scene_gltf2\blender\exp\gltf2_blender_gather_cache.py", line 36, in wrapper_cached result = func(*args, **kwargs) File "C:\Program Files\Blender Foundation\Blender 4.0\4.0\scripts\addons\io_scene_gltf2\blender\exp\material\gltf2_blender_gather_materials_pbr_metallic_roughness.py", line 22, in gather_material_pbr_metallic_roughness base_color_texture, uvmap_info, vcinfo, = gather_base_color_texture(blender_material, export_settings) File "C:\Program Files\Blender Foundation\Blender 4.0\4.0\scripts\addons\io_scene_gltf2\blender\exp\material\gltf2_blender_gather_materials_pbr_metallic_roughness.py", line 99, in gather_base_color_texture tex, uvmap_info, factor = gather_texture_info(inputs[0], inputs, (), export_settings) File "C:\Program Files\Blender Foundation\Blender 4.0\4.0\scripts\addons\io_scene_gltf2\blender\exp\material\gltf2_blender_gather_texture_info.py", line 27, in gather_texture_info return __gather_texture_info_helper(primary_socket, blender_shader_sockets, default_sockets, 'DEFAULT', filter_type, export_settings) File "C:\Program Files\Blender Foundation\Blender 4.0\4.0\scripts\addons\io_scene_gltf2\blender\exp\gltf2_blender_gather_cache.py", line 36, in wrapper_cached result = func(*args, kwargs) File "C:\Program Files\Blender Foundation\Blender 4.0\4.0\scripts\addons\io_scene_gltf2\blender\exp\material\gltf2_blender_gather_texture_info.py", line 49, in gather_texture_info_helper index, factor = __gather_index(blender_shader_sockets, default_sockets, export_settings) File "C:\Program Files\Blender Foundation\Blender 4.0\4.0\scripts\addons\io_scene_gltf2\blender\exp\material\gltf2_blender_gather_texture_info.py", line 146, in gather_index return gltf2_blender_gather_texture.gather_texture(blender_shader_sockets, default_sockets, export_settings) File "C:\Program Files\Blender Foundation\Blender 4.0\4.0\scripts\addons\io_scene_gltf2\blender\exp\gltf2_blender_gather_cache.py", line 36, in wrapper_cached result = func(*args, kwargs) File "C:\Program Files\Blender Foundation\Blender 4.0\4.0\scripts\addons\io_scene_gltf2\blender\exp\material\gltf2_blender_gather_texture.py", line 34, in gather_texture source, webp_image, image_data, factor = gather_source(blender_shader_sockets, default_sockets, export_settings) File "C:\Program Files\Blender Foundation\Blender 4.0\4.0\scripts\addons\io_scene_gltf2\blender\exp\material\gltf2_blender_gather_texture.py", line 179, in gather_source source, image_data, factor = gltf2_blender_gather_image.gather_image(blender_shader_sockets, default_sockets, export_settings) File "C:\Program Files\Blender Foundation\Blender 4.0\4.0\scripts\addons\io_scene_gltf2\blender\exp\gltf2_blender_gather_cache.py", line 36, in wrapper_cached result = func(*args, *kwargs) File "C:\Program Files\Blender Foundation\Blender 4.0\4.0\scripts\addons\io_scene_gltf2\blender\exp\material\gltf2_blender_gather_image.py", line 46, in gather_image buffer_view, factor_buffer_view = __gather_buffer_view(image_data, mime_type, name, export_settings) File "C:\Program Files\Blender Foundation\Blender 4.0\4.0\scripts\addons\io_scene_gltf2\blender\exp\gltf2_blender_gather_cache.py", line 36, in wrapper_cached result = func(args, kwargs) File "C:\Program Files\Blender Foundation\Blender 4.0\4.0\scripts\addons\io_scene_gltf2\blender\exp\material\gltf2_blender_gather_image.py", line 101, in gather_buffer_view data, factor = image_data.encode(mime_type, export_settings) File "C:\Program Files\Blender Foundation\Blender 4.0\4.0\scripts\addons\io_scene_gltf2\blender\exp\material\extensions\gltf2_blender_image.py", line 146, in encode return self.encode_happy(export_settings), None File "C:\Program Files\Blender Foundation\Blender 4.0\4.0\scripts\addons\io_scene_gltf2\blender\exp\material\extensions\gltf2_blender_image.py", line 156, in encode_happy return self.encode_from_image(self.blender_image(), export_settings) File "C:\Program Files\Blender Foundation\Blender 4.0\4.0\scripts\addons\io_scene_gltf2\blender\exp\material\extensions\gltf2_blender_image.py", line 245, in __encode_from_image return _encode_temp_image(tmp_image, self.file_format, export_settings) File "C:\Program Files\Blender Foundation\Blender 4.0\4.0\scripts\addons\io_scene_gltf2\blender\exp\material\extensions\gltf2_blender_image.py", line 257, in _encode_temp_image tmp_image.save(quality=export_settings['gltf_image_quality']) RuntimeError: Error: Could not write image: No error Error: Image 'Valchromat_Light Grey.jpg.001' could not be saved to 'C:\Users\arthu\AppData\Local\Temp\tmp7xtctwa2/img'

julienduroure commented 8 months ago

Thanks for the test case. I am able to reproduce. I am also able to create my own test case. The problem comes from B&W images. We are using Blender itself to convert any images to WebP, and it seems that Blender can't convert an B&W image to WebP.

We need to find a workaround to save a B&W image in WebP by using RGB with 3 identical channels

globglob3D commented 8 months ago

Thanks for the test case. I am able to reproduce. I am also able to create my own test case. The problem comes from B&W images. We are using Blender itself to convert any images to WebP, and it seems that Blender can't convert an B&W image to WebP.

We need to find a workaround to save a B&W image in WebP by using RGB with 3 identical channels

Ha you are correct, sorry for leading you on the wrong path. I batch converted them all to 512x512 with another software for testing if the different resolutions were the issue, and the export worked so I assumed that was the problem. But it also implicitely converted them all to 24 bit depth which I did not see. So that's must be why it worked.

So just to confirm, image resolution is not part of the problem at all? I tested it and this has nothing to do with image resolution. 8 bits depth images are the problem as stated.

Blender doesn't show anywhere that an image is B&W, right? You have to go into the properties of the file itself on your OS to know that?

scurest commented 8 months ago

Blender doesn't show anywhere that an image is B&W, right? You have to go into the properties of the file itself on your OS to know that?

I believe it is shown in the Image Editor, in the sidebar, under the "Image" tab. See "R16F"? That would normally be "SRGB8_A8".

Sidebar of Image Editor, Image tab

ShortVanco commented 8 months ago

Blender不会在任何地方显示图像是黑白的,对吧?你必须进入网络上文件本身的属性才能知道这一点?

我相信它显示在图像编辑器的侧边看到“图像”下方标签。“R16F”了吗?通常是“SRGB8_A8”。

图片编辑器的侧边栏,图片选项卡

How do you use bpy to get this information?

scurest commented 8 months ago

AFAIK there is no direct way to get the "SRG8_A8" datum from bpy. Similar to this question about how to detect the presence of an alpha channel. I would try is_grayscale = img.depth == (32 if img.is_float else 8).

ShortVanco commented 8 months ago

AFAIK there is no direct way to get the "SRG8_A8" datum from bpy. Similar to this question about how to detect the presence of an alpha channel. I would try is_grayscale = img.depth == (32 if img.is_float else 8).

ok thanks!