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