【问题标题】:Blender material from URL来自 URL 的搅拌机材料
【发布时间】:2013-10-05 05:52:04
【问题描述】:

我需要一个 python 脚本,它从给定的 URL 获取 动态创建的图像文件,并使用该图像文件创建一个材质。

然后我将该材质应用到我的搅拌机对象。

下面的python代码适用于本地图像文件

import bpy, os

def run(origin):
    # Load image file from given path.
    realpath = os.path.expanduser('D:/color.png')
    try:
        img = bpy.data.images.load(realpath)
    except:
        raise NameError("Cannot load image %s" % realpath)

    # Create image texture from image
    cTex = bpy.data.textures.new('ColorTex', type = 'IMAGE')
    cTex.image = img

    # Create material
    mat = bpy.data.materials.new('TexMat')

    # Add texture slot for color texture
    mtex = mat.texture_slots.add()
    mtex.texture = cTex

    # Create new cube
    bpy.ops.mesh.primitive_cube_add(location=origin)

    # Add material to created cube
    ob = bpy.context.object
    me = ob.data
    me.materials.append(mat)

    return

run((0,0,0))

我试过了:

import urllib, cStringIO

file = cStringIO.StringIO(urllib.urlopen(URL).read())
img = Image.open(file)

但我没有运气。我得到的第一个错误是

ImportError: 没有名为“StringIO”的模块

Blender 中的 python 脚本 API 使用限制性模块还是什么?

感谢您的帮助。

【问题讨论】:

  • 你能修正一下缩进吗?
  • 你在windows上吗? -> 是的,你是。有 python 可能预装了搅拌机。使用什么 python 版本和二进制文件?
  • 我在 Blender 2.68a 和 Blenders 控制台中使用该 python 脚本,它显示 PYTHON INTERACTIVE CONSOLE 3.3.0(默认,2012 年 11 月 26 日,17:23:29)[MSC v.1500 32 位(Intel)],但我不知道 Blender 的 python 版本。
  • 您能从该脚本中执行“import sys”和“print(sys.version_info)”并像使用普通脚本一样运行它吗?

标签: python blender python-3.3


【解决方案1】:

您似乎使用的是 Python 3.3,它没有 cStringIO。请改用io.BytesIO

import io
data = io.BytesIO(urllib.urlopen(URL).read())

[编辑]

在 osx 上的 Blender 2.68a 中测试:

import io
from urllib import request
data = io.BytesIO(request.urlopen("http://careers.stackoverflow.com/jobs?a=288").read())
data
>>>> <_io.BytesIO object at 0x11050aae0>

[编辑2]

好的,搅拌机似乎只能从文件加载。这是您的脚本的修改,它下载一个 url,将其存储在临时位置,从中创建材料,将材料打包到混合文件中并删除临时图像。

导入 bpy, os, io 从 urllib 导入请求

def run(origin):
    # Load image file from url.    
    try:
        #make a temp filename that is valid on your machine
        tmp_filename = "/tmp/temp.png"
        #fetch the image in this file
        request.urlretrieve("https://www.google.com/images/srpr/logo4w.png", tmp_filename)
        #create a blender datablock of it
        img = bpy.data.images.load(tmp_filename)
        #pack the image in the blender file so...
        img.pack()
        #...we can delete the temp image
        os.remove(tmp_filename)
    except Exception as e:
        raise NameError("Cannot load image: {0}".format(e))
    # Create image texture from image
    cTex = bpy.data.textures.new('ColorTex', type='IMAGE')
    cTex.image = img
    # Create material
    mat = bpy.data.materials.new('TexMat')
    # Add texture slot for color texture
    mtex = mat.texture_slots.add()
    mtex.texture = cTex
    # Create new cube
    bpy.ops.mesh.primitive_cube_add(location=origin)
    # Add material to created cube
    ob = bpy.context.object
    me = ob.data
    me.materials.append(mat)

run((0,0,0))

输出:

【讨论】:

  • 没有名为 'io.BytesIO' 的模块; io 不是一个包
  • 嗯,很奇怪。你能在那个脚本中做一个'print(dir(io))'和'print(dir(io.BytesIO))'并运行它吗?
  • >>> print(dir(urllib)) ['builtins', 'cached', 'doc ', '文件', '初始化', '加载器', '名称', '', '路径']
  • >>> print(dir(io)) Traceback(最近一次调用最后):文件“”,第 1 行,在 NameError: name 'io' is not defined
  • 我在问题末尾添加了 Blender 控制台的屏幕截图。
【解决方案2】:

只需使用urllib.urlretrieve(url, localfilename),然后使用本地文件。

【讨论】:

  • 有没有什么方法可以在不进行检索的情况下执行此操作,因为此任务将是动态且重复的。我不想保留那些临时图像文件。
【解决方案3】:

您可以复制像素数据,但我不确定这样做是否值得。可能它不适用于所有文件格式。

import bpy, io, requests, PIL

def loadImageFromUrl(url,name=None):
    frames = ()
    # load image
    image = PIL.Image.open(io.BytesIO(requests.get(url).content))
    try:
        while True:
            # create new blender image of correct size
            frame = bpy.data.images.new(name or url, image.width, image.height)
            # copy the pixel data. apparently the lines have to be flipped.
            frame.pixels = [
                value / 255
                for pixel in image.transpose(PIL.Image.FLIP_TOP_BOTTOM)
                                  .convert('RGBA')
                                  .getdata()
                for value in pixel
            ]
            frames += frame,
            image.seek(len(frames))
    except EOFError:
        return frames

【讨论】:

    猜你喜欢
    • 2017-12-06
    • 2013-12-25
    • 1970-01-01
    • 2016-01-18
    • 2020-01-06
    • 2019-04-30
    • 2020-12-17
    • 2018-10-01
    • 2016-01-19
    相关资源
    最近更新 更多