On 19/08/2019 14:16, Cameron Simpson wrote:
On 19Aug2019 08:52, Paul St George <em...@paulstgeorge.com> wrote:
On 19/08/2019 01:31, Cameron Simpson wrote:
On 18Aug2019 17:29, Paul St George <em...@paulstgeorge.com> wrote:
On 18/08/2019 02:03, Cameron Simpson wrote:
1: Is image01.tif a real existing file when you ran this code?
Yes. image01.tif is real, existing and apparent.
But in what directory? What is its _actual_ full path as you expect it to be?

Aha. The Blender file that I am using to test this on has two images used as textures. They reside at:
/Users/Lion/Desktop/test8/image01.tif
/Users/Lion/Desktop/images/image02.tif

The Blender file is at /Users/Lion/Desktop/test8/tifftest8.blend

There's a remark on that web page I mentioned that suggests that the leading '//' indicates the filename is relative to the Blender model, so the context directory for the '//' is likely /Users/Lion/Desktop/test8.

Yes. That makes sense. The reason I was testing with two images, one at /Users/Lion/Desktop/test8/image01.tif and the other at /Users/Lion/Desktop/images/image02.tif is that I cannot rely on images being in the same folder as the Blender file.

So, let's assume the context directory is /Users/Lion/Desktop/test8
and see how we get on below.


(Chris and Peter lead me to believe that Blender has a special kind of relative path. The double slashes replace the path to the blend file’s directory.) realpath has done something but I know not what.

realpath needs a UNIX path. Your //image01.tif isn't a UNIX path, it is a special Blender path. First you need to convert it. By replacing '//' with the blend file's directory. Then you can call realpath. If you still need to.

Understood. Now. Thanks!

[...snip...]

Did you just [...snip...] yourself?

So you might want to write an unBlenderiser (untested example):

 from os.path import isabs, join as joinpath

 def unblenderise(filename, context_dir=None):
   # transmute Blender "relative" path
   if filename.startswith('//'):
     filename = filename[2:]
   if not isabs(filename) and context_dir is not None:
     # attach the filename to `context_dir` if supplied
     filename = joinpath(context_dir, filename)
   return filename

The idea here is to get back a meaningful UNIX path from a Blender path. It first strips a leading '//'. Next, _if_ the filename is relative _and_ you supplied the optional context_dir (eg the directory used for a file brwoser dialogue box), then it prepends that context directory.

This _does not_ call abspath or realpath or anything, it just returns a filename which can be used with them.

The idea is that if you know where image01.tif lives, you could supply that as the context directory.

Yes! Until Peter Otten's timely intervention, I was trying to do this and had managed to join the path_to_the_folder_that_contains_the_Blender_file to the_name_of_the_image (stripped of its preceding slashes).

Your unblenderise looks much better than my nascent saneblender so thank you. I will explore more!

Looks like you want wd=os.path.dirname(path_of_blend_file).

Thank you!

Does it depend on knowing where image01.tif lives and manually supplying that?

Sort of.

What you've got is '//image01.tif', which is Blender's special notation indicating a filename relative to the blend file's directory. All the Python library stuff expects an OS path (OS==UNIX on a Mac). So you want to convert that into a UNIX path.  For example:

    from os.path import dirname

    # Get this from somewhere just hardwiring it for the example.
    # Maybe from your 'n' object below?
    blend_file = '/Users/Lion/Desktop/test8/tifftest8.blend'
Is this setting a relative path?

    blender_image_file = n.image.filename

    unix_image_file = unblenderise(blender_image_file, dirname(blend_file))

Now you have a UNIX path. If blend_file is an absolute path, unix_image_path will also be an absolute path. But if blend_file is a relative path (eg you opened up "tifftest8.blend") unix_image_path will be a relative path.


Does unix_image_path = unix_image_file?

Two possibilities here.
blend_file (and so unix_image_file) is an absolute path OR blend_file (and so unix_image_file) is a relative path.

I just want to check my understanding. If I supply the path to blend_file then it is absolute, and if I ask Python to generate the path to blend_file from within Blender it is relative. Have I got it?


You don't need to use realpath or abspath on that _unless_ you need to reference the file from any directory (i.e. _not_ relative to where you currently are).

If I decided not to supply the path and so ended up with a relative UNIX path, I could now use realpath or abspath to find the absolute path. Have I still got it?

#
I combined your unblenderise and your use of it (see below). Is my attempt error free?

It works very well. So thank you! I tested it with a Blend file that had two images, one in the same folder as the Blend file and the other was in a folder on the Desktop called 'images'.

The initial results were:
Plane uses image01.tif saved at //image01.tif which is at /Users/Lion/Desktop/test8/image01.tif

Plane uses image02.tif saved at //../images/image02.tif which is at /Users/Lion/Desktop/test8/../images/image02.tif

BUT as you say, this was easily sorted by using os.path.realpath or os.path.abspath. Both worked equally well.

Plane uses image01.tif saved at //image01.tif which is at /Users/Lion/Desktop/test8/image01.tif Plane uses image02.tif saved at //../images/image02.tif which is at /Users/Lion/Desktop/images/image02.tif

So, everything now works. Thank you again. I am just a little unclear on the absolute and relative, hence my questions.

Cheers,
Cameron Simpson <c...@cskk.id.au>

#some of this can be tidied later
import bpy
import os

from os.path import realpath
from os.path import isabs, join as joinpath
from os.path import dirname



def unblenderise(filename, context_dir=None):

 if filename.startswith('//'):
  filename = filename[2:]
 if not isabs(filename) and context_dir is not None:
# attach the filename to `context_dir` if supplied
  filename = joinpath(context_dir, filename)
 return filename


blend_file = '/Users/Lion/Desktop/test8/tifftest8.blend'


texture_list = []

for obj in bpy.context.scene.objects:
    for s in obj.material_slots:
        if s.material and s.material.use_nodes:
            for n in s.material.node_tree.nodes:
                if n.type == 'TEX_IMAGE':
                    texture_list += [n.image]
print(obj.name,'uses',n.image.name,'saved at',n.image.filepath, 'which is at', unblenderise(n.image.filepath, dirname(blend_file)))





print('Texture list:',texture_list)


--
https://mail.python.org/mailman/listinfo/python-list

Reply via email to