blender/release/scripts/bpymodules/BPyImage.py
Campbell Barton 30fb777971 py api
bpy.*libBlickSeq*.new() - name is now an optiona arg.
moved some more scripts to bpy.* api.
2007-03-27 14:49:37 +00:00

302 lines
10 KiB
Python

# --------------------------------------------------------------------------
# BPyImage.py version 0.15
# --------------------------------------------------------------------------
# helper functions to be used by other scripts
# --------------------------------------------------------------------------
# ***** BEGIN GPL LICENSE BLOCK *****
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
# ***** END GPL LICENCE BLOCK *****
# --------------------------------------------------------------------------
#===========================================================================#
# Comprehensive image loader, will search and find the image #
# Will return a blender image or a new image if the image is missing #
#===========================================================================#
import bpy
from Blender import sys
try:
import os
except:
os=None
#==============================================#
# Return directory, where the file is #
#==============================================#
def stripFile(path):
lastSlash = max(path.rfind('\\'), path.rfind('/'))
if lastSlash != -1:
path = path[:lastSlash]
newpath= '%s%s' % (path, sys.sep)
else:
newpath= path
return newpath
#==============================================#
# Strips the slashes from the back of a string #
#==============================================#
def stripPath(path):
return path.split('/')[-1].split('\\')[-1]
#====================================================#
# Strips the prefix off the name before writing #
#====================================================#
def stripExt(name): # name is a string
index = name.rfind('.')
if index != -1:
return name[ : index ]
else:
return name
def getExt(name):
index = name.rfind('.')
if index != -1:
return name[index+1:]
return name
#====================================================#
# Adds a slash to the end of a path if its not there #
#====================================================#
def addSlash(path):
if not path:
return ''
elif path.endswith('\\') or path.endswith('/'):
return path
return path + sys.sep
def comprehensiveImageLoad(imagePath, filePath, PLACE_HOLDER= True, RECURSIVE=True, VERBOSE=False):
'''
imagePath: The image filename
If a path precedes it, this will be searched as well.
filePath: is the directory where the image may be located - any file at teh end will be ignored.
PLACE_HOLDER: if True a new place holder image will be created.
this is usefull so later you can relink the image to its original data.
VERBOSE: If True debug info will be printed.
RECURSIVE: If True, directories will be recursivly searched.
Be carefull with this if you have files in your root directory because it may take a long time.
'''
if VERBOSE: print 'img:', imagePath, 'file:', filePath
# When we have the file load it with this. try/except niceness.
def imageLoad(path):
#if path.endswith('\\') or path.endswith('/'):
# raise 'INVALID PATH'
try:
img = bpy.images.new(filename=path)
if VERBOSE: print '\t\tImage loaded "%s"' % path
return img
except:
if VERBOSE:
if sys.exists(path): print '\t\tImage failed loading "%s", mabe its not a format blender can read.' % (path)
else: print '\t\tImage not found, making a place holder "%s"' % (path)
if PLACE_HOLDER:
img= bpy.images.new(stripPath(path),4,4)
img.filename= path
return img #blank image
else:
return None
# Image formats blender can read
IMAGE_EXT = ['jpg', 'jpeg', 'png', 'tga', 'bmp', 'rgb', 'sgi', 'bw', 'iff', 'lbm', # Blender Internal
'gif', 'psd', 'tif', 'tiff', 'pct', 'pict', 'pntg', 'qtif'] # Quacktime, worth a try.
imageFileName = stripPath(imagePath) # image path only
imageFileName_lower = imageFileName.lower() # image path only
if VERBOSE: print '\tSearchingExisting Images for "%s"' % imagePath
for i in bpy.images:
if stripPath(i.filename.lower()) == imageFileName_lower:
if VERBOSE: print '\t\tUsing existing image.'
return i
if VERBOSE: print '\tAttempting to load "%s"' % imagePath
if sys.exists(imagePath):
if VERBOSE: print '\t\tFile found where expected "%s".' % imagePath
return imageLoad(imagePath)
imageFileName_noext = stripExt(imageFileName) # With no extension.
imageFileName_noext_lower = stripExt(imageFileName_lower) # With no extension.
imageFilePath = stripFile(imagePath)
# Remove relative path from image path
if imageFilePath.startswith('./') or imageFilePath.startswith('.\\'):
imageFilePath = imageFilePath[2:]
# Attempt to load from obj path.
tmpPath = stripFile(filePath) + stripPath(imageFileName)
if sys.exists(tmpPath):
if VERBOSE: print '\t\tFile found in path (1)"%s".' % tmpPath
return imageLoad(tmpPath)
# os needed if we go any further.
if not os:
if VERBOSE: print '\t\tCreating a placeholder with a face path: "%s".' % imagePath
return imageLoad(imagePath) # Will jus treturn a placeholder.
# We have os.
# GATHER PATHS.
paths = {} # Store possible paths we may use, dict for no doubles.
tmpPath = addSlash(sys.expandpath('//')) # Blenders path
if sys.exists(tmpPath):
if VERBOSE: print '\t\tSearching in %s' % tmpPath
paths[tmpPath] = [os.listdir(tmpPath)] # Orig name for loading
paths[tmpPath].append([f.lower() for f in paths[tmpPath][0]]) # Lower case list.
paths[tmpPath].append([stripExt(f) for f in paths[tmpPath][1]]) # Lower case no ext
else:
if VERBOSE: print '\tNo Path: "%s"' % tmpPath
tmpPath = imageFilePath
if sys.exists(tmpPath):
if VERBOSE: print '\t\tSearching in %s' % tmpPath
paths[tmpPath] = [os.listdir(tmpPath)] # Orig name for loading
paths[tmpPath].append([f.lower() for f in paths[tmpPath][0]]) # Lower case list.
paths[tmpPath].append([stripExt(f) for f in paths[tmpPath][1]]) # Lower case no ext
else:
if VERBOSE: print '\tNo Path: "%s"' % tmpPath
tmpPath = stripFile(filePath)
if sys.exists(tmpPath):
if VERBOSE: print '\t\tSearching in %s' % tmpPath
paths[tmpPath] = [os.listdir(tmpPath)] # Orig name for loading
paths[tmpPath].append([f.lower() for f in paths[tmpPath][0]]) # Lower case list.
paths[tmpPath].append([stripExt(f) for f in paths[tmpPath][1]]) # Lower case no ext
else:
if VERBOSE: print '\tNo Path: "%s"' % tmpPath
tmpPath = addSlash(bpy.config.textureDir)
if tmpPath and sys.exists(tmpPath):
if VERBOSE: print '\t\tSearching in %s' % tmpPath
paths[tmpPath] = [os.listdir(tmpPath)] # Orig name for loading
paths[tmpPath].append([f.lower() for f in paths[tmpPath][0]]) # Lower case list.
paths[tmpPath].append([stripExt(f) for f in paths[tmpPath][1]]) # Lower case no ext
else:
if VERBOSE: print '\tNo Path: "%s"' % tmpPath
# Add path if relative image patrh was given.
tmp_paths= paths.keys()
for k in tmp_paths:
tmpPath = k + imageFilePath
if sys.exists(tmpPath):
paths[tmpPath] = [os.listdir(tmpPath)] # Orig name for loading
paths[tmpPath].append([f.lower() for f in paths[tmpPath][0]]) # Lower case list.
paths[tmpPath].append([stripExt(f) for f in paths[tmpPath][1]]) # Lower case no ext
else:
if VERBOSE: print '\tNo Path: "%s"' % tmpPath
# DONE
#
for path, files in paths.iteritems():
if sys.exists(path + imageFileName):
if VERBOSE: print '\tFound image at path: "%s" file" "%s"' % (path, imageFileName)
return imageLoad(path + imageFileName)
# If the files not there then well do a case insensitive seek.
filesOrigCase = files[0]
filesLower = files[1]
filesLowerNoExt = files[2]
# We are going to try in index the file directly, if its not there just keep on
index = None
try:
# Is it just a case mismatch?
index = filesLower.index(imageFileName_lower)
except:
try:
# Have the extensions changed?
index = filesLowerNoExt.index(imageFileName_noext_lower)
ext = getExt( filesLower[index] ) # Get the extension of the file that matches all but ext.
# Check that the ext is useable eg- not a 3ds file :)
if ext.lower() not in IMAGE_EXT:
index = None
except:
index = None
if index != None:
tmpPath = path + filesOrigCase[index]
img = imageLoad( tmpPath )
if img != None:
if VERBOSE: print '\t\tImage Found "%s"' % tmpPath
return img
if RECURSIVE:
# IMAGE NOT FOUND IN ANY OF THE DIRS!, DO A RECURSIVE SEARCH.
if VERBOSE: print '\t\tImage Not Found in any of the dirs, doing a recusrive search'
for path in paths.iterkeys():
# Were not going to use files
if path == '/' or len(path) == 3 and path[1:] == ':\\':
continue
# print path , 'ASS'
#------------------
# finds the file starting at the root.
# def findImage(findRoot, imagePath):
#W---------------
# ROOT, DIRS, FILES
pathWalk = os.walk(path)
pathList = [True]
matchList = [] # Store a list of (match, size), choose the biggest.
while True:
try:
pathList = pathWalk.next()
except:
break
for file in pathList[2]:
file_lower = file.lower()
# FOUND A MATCH
if (file_lower == imageFileName_lower) or\
(stripExt(file_lower) == imageFileName_noext_lower and getExt(file_lower) in IMAGE_EXT):
name = pathList[0] + sys.sep + file
size = os.path.getsize(name)
if VERBOSE: print '\t\t\tfound:', name
matchList.append( (name, size) )
if matchList:
# Sort by file size
matchList.sort(lambda A, B: cmp(B[1], A[1]) )
if VERBOSE: print '\t\tFound "%s"' % matchList[0][0]
# Loop through all we have found
img = None
for match in matchList:
img = imageLoad(match[0]) # 0 - first, 0 - pathname
if img != None:
break
return img
# No go.
if VERBOSE: print '\t\tImage Not Found after looking everywhere! "%s"' % imagePath
return imageLoad(imagePath) # Will jus treturn a placeholder.