OBJ importer cannot deal with texture names with spaces #49357

Closed
opened 2016-09-14 19:43:51 +02:00 by Tiago Cardoso · 16 comments

System Information

Not relevant

Blender Version
Latest (2.78)

Short description of error
The OBJ importer, when processing the MTL cannot deal with material images cannot parse filenames with spaces.

Exact steps for others to reproduce the error
Load any OBJ with textures with spaces on the filename.

On the code: https://developer.blender.org/diffusion/BA/browse/master/io_scene_obj/import_obj.py

  • on "def load_material_image(blender_material, context_material_name, img_data, type):" method
    • on "imagepath = os.fsdecode(img_data[-1])" line

This line of code only uses the last separated-by-space part of the MTL line content. If the filename is (without quotes) "blue 3.jpg" the imagepath will be "3.jpg" instead of "blue 3.jpg". Just a bad parse.
This will result in Blender trying to load an image that does not exist.

Thank you for any effort to resolve this.

**System Information** Not relevant **Blender Version** Latest (2.78) **Short description of error** The OBJ importer, when processing the MTL cannot deal with material images cannot parse filenames with spaces. **Exact steps for others to reproduce the error** Load any OBJ with textures with spaces on the filename. On the code: https://developer.blender.org/diffusion/BA/browse/master/io_scene_obj/import_obj.py - on "def load_material_image(blender_material, context_material_name, img_data, type):" method - on "imagepath = os.fsdecode(img_data[-1])" line This line of code only uses the last separated-by-space part of the MTL line content. If the filename is (without quotes) "blue 3.jpg" the imagepath will be "3.jpg" instead of "blue 3.jpg". Just a bad parse. This will result in Blender trying to load an image that does not exist. Thank you for any effort to resolve this.
Author

Changed status to: 'Open'

Changed status to: 'Open'
Author

Added subscriber: @tiago.cardoso

Added subscriber: @tiago.cardoso

Added subscriber: @mont29

Added subscriber: @mont29

Changed status from 'Open' to: 'Archived'

Changed status from 'Open' to: 'Archived'
Bastien Montagne self-assigned this 2016-09-14 20:03:42 +02:00

Thanks for the report, but no bug here, MTL does not support filenames with spaces, which is quite obvious since it uses spaces to separate options… Some programs are not smart enough to cope with this limitation when exporting, but we cannot do anything about it.

Thanks for the report, but no bug here, MTL does not support filenames with spaces, which is quite obvious since it uses spaces to separate options… Some programs are not smart enough to cope with this limitation when exporting, but we cannot do anything about it.
Author

I haven't seen any indication on MTL specifications that prohibits spaces in the filename.

All the args options and parameters are well defined on the specs and could be taken in account, eg. after that code line, the last token is getting too much parameters (the begining of the filename) with no need. All options have a set number of parameters.

Just need to do a regular expression to eliminate options as it's parameters and you can get the complete filename.

It's not simple, but I think, very feasable and would be a great improvement :D

Thank you

I haven't seen any indication on MTL specifications that prohibits spaces in the filename. All the args options and parameters are well defined on the specs and could be taken in account, eg. after that code line, the last token is getting too much parameters (the begining of the filename) with no need. All options have a set number of parameters. Just need to do a regular expression to eliminate options as it's parameters and you can get the complete filename. It's not simple, but I think, very feasable and would be a great improvement :D Thank you
Author

Changed status from 'Archived' to: 'Open'

Changed status from 'Archived' to: 'Open'
Author

^\S+(\s-(((blenu|blenv|bm|boost|cc|clamp|imfchan|texres)\s[^-]\S+)|(mm(\s[^-]\S+){2})|(s(\s[^-]\S+){3})))*\s

If I've not made a mistake somewhere, this regex should work. Just remove what it grab and you have the filename, with or without spaces.

Could you test and commit it (if correct) ? :) It would be great.

Thank you!

^\S+(\s-(((blenu|blenv|bm|boost|cc|clamp|imfchan|texres)\s[^-]\S+)|(mm(\s[^-]\S+){2})|(s(\s[^-]\S+){3})))*\s If I've not made a mistake somewhere, this regex should work. Just remove what it grab and you have the filename, with or without spaces. Could you test and commit it (if correct) ? :) It would be great. Thank you!

That won't work in all cases, see e.g. the -o/-s/-t options, which can have optional v/w values (ref MTL doc). So how to you handle e.g. map_Ka -o 1 2 3 foo.png ? Is it file "2 3 foo.png"?

Short answer/fix: do not use spaces in your filenames in OBJ context, this is not designed to support it, and will always make things harder, whatever solution is hacked around.

Will try some workaround though (like going backward adding items to 'potential' filename until we find an existing match), but this won't probably cover all cases anyway.

That won't work in all cases, see e.g. the `-o`/`-s`/`-t` options, which can have optional `v`/`w` values ([ref MTL doc](http://paulbourke.net/dataformats/mtl/)). So how to you handle e.g. `map_Ka -o 1 2 3 foo.png` ? Is it file `"2 3 foo.png"`? Short answer/fix: do not use spaces in your filenames in OBJ context, this is not designed to support it, and will always make things harder, whatever solution is hacked around. Will try some workaround though (like going backward adding items to 'potential' filename until we find an existing match), but this won't probably cover all cases anyway.
Author

My regex is missing some options:

^\S+(\s-(((blenu|blenv|bm|boost|cc|clamp|imfchan|texres)\s[^-]\S+)|(mm(\s[^-]\S+){2})|((s|o|t)(\s[^-]\S+){3})))*\s

This should be it. Options like -o, -s or -t always have 3 parameters, so the regex accounts for that and the name should be just foo.png.

As the number of parameters is static for each option. A regex should be able to parse it, no ?

Can you see another case that wouldn't work ?

Thank you

My regex is missing some options: ^\S+(\s-(((blenu|blenv|bm|boost|cc|clamp|imfchan|texres)\s[^-]\S+)|(mm(\s[^-]\S+){2})|((s|o|t)(\s[^-]\S+){3})))*\s This should be it. Options like -o, -s or -t always have 3 parameters, so the regex accounts for that and the name should be just foo.png. As the number of parameters is static for each option. A regex should be able to parse it, no ? Can you see another case that wouldn't work ? Thank you

Read the specs, v and w are optional, so there is no guarantee you'll have three params here…

Read the specs, v and w are optional, so there is no guarantee you'll have three params here…
Author

You're right.

But we could use :

!!^\S+(\s-(((blenu|blenv|bm|boost|cc|clamp|imfchan|texres)\s[^-]\S+)|(mm(\s[^-]\S+){2})|((s|o|t)(\s\d(.\d+)?){1,3})))*\s!!

This would take in account those optional parameters. It will check only for number as parameters (specs) and never "eat" the texture filename.

The only (I think) time this could be wrong is in similar cases to the one that you provides, but it would return !!foo.png!! that is what you are already returning. So we do not had any more wrong cases and resolve a lot a cases that now don't work.

For example, for !!map_Ka -o 1.0 2 bar foo.png!! it would leave !!bar foo.png!! that might not be the correct filename but is way better guess than just !!foo.png!! that is what is happening right now.

I think this would improve much the situation we have right now. It's a perfect build on what there is now as it reduces the number of times it gets the wrong filename and doesn't add any more wrong filename that it already gets.

For my use case, this is very importing, as we are using Blender to render files and a lot of files (in OBJ) appear with spaces (and we cannot change it as we do not control the files that we get.

Do you agree that this would just reduce the amount of wrong file_paths without getting any other side effects ?

Once again, thank you!

You're right. But we could use : !!^\S+(\s-(((blenu|blenv|bm|boost|cc|clamp|imfchan|texres)\s[^-]\S+)|(mm(\s[^-]\S+){2})|((s|o|t)(\s\d(.\d+)?){1,3})))*\s!! This would take in account those optional parameters. It will check only for number as parameters (specs) and never "eat" the texture filename. The only (I think) time this could be wrong is in similar cases to the one that you provides, but it would return !!foo.png!! that is what you are already returning. So we do not had any more wrong cases and resolve a lot a cases that now don't work. For example, for !!map_Ka -o 1.0 2 bar foo.png!! it would leave !!bar foo.png!! that might not be the correct filename but is way better guess than just !!foo.png!! that is what is happening right now. I think this would improve much the situation we have right now. It's a perfect build on what there is now as it reduces the number of times it gets the wrong filename and doesn't add any more wrong filename that it already gets. For my use case, this is very importing, as we are using Blender to render files and a lot of files (in OBJ) appear with spaces (and we cannot change it as we do not control the files that we get. Do you agree that this would just reduce the amount of wrong file_paths without getting any other side effects ? Once again, thank you!

This issue was referenced by d98fc12f8d

This issue was referenced by d98fc12f8d0535ee6ca80b16a20da478913f922e

This issue was referenced by 959f9d28d2

This issue was referenced by 959f9d28d26cd2de4c0db2fb4f65607e9ec7e2bf

Changed status from 'Open' to: 'Resolved'

Changed status from 'Open' to: 'Resolved'
Author

+1 Thanks!

+1 Thanks!
Sign in to join this conversation.
No Milestone
No project
No Assignees
3 Participants
Notifications
Due Date
The due date is invalid or out of range. Please use the format 'yyyy-mm-dd'.

No due date set.

Dependencies

No dependencies set.

Reference: blender/blender-addons#49357
No description provided.