kivy: можно ли использовать буфер в качестве источника изображения?

У меня есть следующий код, который создает новое изображение из некоторых существующих изображений.

from PIL import Image as pyImage

def create_compound_image(back_image_path, fore_image_path, fore_x_position):

    back_image_size = get_image_size(back_image_path)
    fore_image_size = get_image_size(fore_image_path)

    new_image_width = (fore_image_size[0] / 2) + back_image_size[0]
    new_image_height = fore_image_size[1] + back_image_size[1]

    new_image = create_new_image_canvas(new_image_width, new_image_height)

    back_image = pyImage.open(back_image_path)
    fore_image = pyImage.open(fore_image_path)

    new_image.paste(back_image, (0, 0), mask = None) 
    new_image.paste(fore_image, (fore_x_position, back_image_size[1]), mask = None)

    return new_image

Позже в коде у меня есть что-то вроде этого:

from kivy.uix.image import Image
img = Image(source = create_compound_image(...))

Если я сделаю это выше, я получу сообщение о том, что Image.source only accepts string/unicode.

Если я создам объект StringIO.StringIO() из нового изображения и попытаюсь использовать его в качестве источника, сообщение об ошибке будет таким же, как и выше. Если я использую вывод метода getvalue() объекта StringIO в качестве источника, сообщение состоит в том, что source must be encoded string without NULL bytes, not str.

Как правильно использовать вывод функции create_compound_image() в качестве источника при создании объекта изображения kivy?


person James_L    schedule 03.01.2014    source источник


Ответы (2)


source является StringProperty и ожидает путь к файлу. Вот почему вы получили ошибки, когда пытались передать объект PIL.Image, объект StringIO или строковое представление изображения. Это не то, чего хочет фреймворк. Что касается получения изображения из StringIO, это уже обсуждалось здесь:

Вы также можете попробовать гораздо более простой, быстрый и грязный метод - просто сохраните свое изображение в виде файла tmp и прочитайте его обычным способом.

person Nykakin    schedule 04.01.2014
comment
Спасибо, Найкакин. Я хотел бы избежать подхода с файлом tmp, чтобы избежать трудоемких операций ввода-вывода. Спасибо за ссылки - они кажутся немного запутанными, хотя и полезными; Я предполагаю, что подход текстуры, предложенный ниже, может быть более подходящим вариантом для этой конкретной проблемы. - person James_L; 06.01.2014

Кажется, вы хотите просто объединить два изображения в одно, на самом деле вы можете просто создать текстуру, используя Texture.create и перенесите данные в определенную позицию, используя Texture.blit_buffer .

from kivy.core.image import Image
from kivy.graphics import Texture

bkimg = Image(bk_img_path)
frimg = Image(fr_img_path)

new_size = ((frimg.texture.size[0]/2) + bkimg.texture.size[0],
            frimg.texture.size[1] + bkimg.texture.size[1])

tex = Texture.create(size=new_size)
tex.blit_buffer(pbuffer=bkimg.texture.pixels, pos=(0, 0), size=bkimg.texture.size)
tex.blit_buffer(pbuffer=frimg.texture.pixels, pos=(fore_x_position, bkimg.texture.size[1]), size=frimg.texture.size)

Теперь вы можете использовать эту текстуру где угодно, например::

from kivy.uix.image import Image
image = Image()
image.texture = tex
person qua-non    schedule 04.01.2014
comment
У меня вопрос по этому методу. При вставке в «tex» кажется, что вместо вставки в пустую поверхность программа пытается заполнить «tex» пикселями из «bkimg» или «frimg»; это, в свою очередь, похоже, масштабирует «текс». Есть ли способ просто заставить его действовать, если вставить его в пустой холст, как и предполагалось? Спасибо! - person James_L; 06.01.2014
comment
Nevermind - позаботился об этом, используя pygame Surfaces. Спасибо еще раз! - person James_L; 07.01.2014
comment
рад видеть, что у вас это работает. Кажется, я пропустил параметр size из blit_buffer, который был бы полезен в этом случае для достижения того, что вам нужно. - person qua-non; 07.01.2014