converting textures to another format

Hi,

I’m working on a small project in WebGL, and thus I’m limited to png’s and jpg’s. Unfortunately, a lot of test scenes that I have are using tga textures. So I thought it would be nice to have an option in my exporter to convert unsupported file formats to png.

I tried this:


tex.image.pack(as_png = True)
tex.image.unpack('USE_LOCAL')

It kinda works: let’s say the input texture was “floor.tga” then after the export, the texture is still “floor.tga” but the content is a png. I thought I could then just change the filepath after the pack to avoid overwritting “floor.tga”, so it became:


tex.image.pack(as_png = True)
tex.image.filepath = "//converted_texture/" + os.path.basename(tex.image.filepath.replace(".tga", ".png"))
tex.image.unpack('USE_LOCAL')

but then I have the following error:


Error: Unable to pack file, source path '/Users/aaaaa/Documents/Blender/Models/test/converted_texture/floor.png' not found
ERROR: Image not available. Keeping packed image

This is weird, it feels like the pack() function is somehow differed and is trying to actually pack the file after I change the filepath property …

Anyway, is there a way to convert all the tga’s into png’s ? And is there a way to more generally convert any image format supported by Blender into another Blender supported image format ? (it feels like it should: blender is able to load and save from/into a lot of format, it should be doable to give access to those functions to python, but I can’t seem to find how)

Thanks in advance :slight_smile:

Edit: this is getting frustrating, I just noticed the bpy_extras.image_utils module which contains a “load_image” method … but nothing else ! That would be sooo nice to have a “save_image” method in this module :stuck_out_tongue:

Hmm, now I’m completely puzzled. Here is the test I just did:


image.file_format = 'PNG'
image.save()

and it overwrites my file with the content of a png file ! If I use ‘JPEG’ instead, it overwrites with the content of a jpg format. Well, it seems to work as intended. The problem is that it write without changing the extension of the file, and as soon as I try to change the filepath I get various errors. For instance, the following:


image.file_format = 'PNG'
image.filepath = image.filepath.replace(".tga", ".png")
image.save()

generate this error: “Error: Image ‘test.tga.001’ does not have any image data”

In my exporter, I used ‘save_render’, that way I could just change the format by changing render.image_settings.file_format.

Ok, I think I found a bug. Attached is a small example to reproduce: bug_save_image.zip (91.8 KB)
Basically, I need to save() my image twice to actually saving it into the correct format. If you open the attached .blend and run the script, you’ll see the following output:


size of 'test.tga': 49196
size of 'test.jpg' after the 1st save: 49290
size of 'test.jpg' after the 2d save:  7696

So now, here is how I convert my images:


# first, I copy my source image into a custom folder, and I rename it (Blender doesn't care about the extensions)
tex_name = os.path.basename(tex.image.filepath).replace(".tga", ".jpg")
source = os.path.dirname(bpy.data.filepath) + "/converted_texture/" + tex_name
shutil.copyfile(tex.image.filepath, source)

# then I create a new image from this one, and change its format to JPEG + save it... twice.
image = bpy_extras.image_utils.load_image(source)
image.file_format = "JPEG"
image.save()
image.file_format = "JPEG"
image.save()

It works for any format.

Sorry to bump this post, but I wanted to say “thank you” cmomoney ! I didn’t see your post last time, and recently my method didn’t work anymore (since I updated to 2.67 I think) so I dug this thread up to get the test scene I posted, and just saw your method. Which works perfectly :slight_smile:

Here is the small function I’m using, in case anyone has the same problem and is too lazy to read the documentation :stuck_out_tongue:



def convert_image(image, dest):

    # backup image settings
    backup_file_format = bpy.context.scene.render.image_settings.file_format
    backup_color_mode = bpy.context.scene.render.image_settings.color_mode
    
    # update file format and color format to what we want
    bpy.context.scene.render.image_settings.file_format = 'PNG'
    bpy.context.scene.render.image_settings.color_mode = 'RGBA'

    # convert and save the texture: the name of the method is a bit misleading: it doesn't
    # render anything. It just saves the image using the settings in bpy.context.scene.render.image_settings
    image.save_render(dest)

    # restore image settings
    bpy.context.scene.render.image_settings.file_format = backup_file_format
    bpy.context.scene.render.image_settings.color_mode = backup_color_mode

1 Like