Найти - Пользователи
Полная версия: Картинка PIL.Image в QPixmap
Начало » GUI » Картинка PIL.Image в QPixmap
1
degid
Всем привет.
Можно ли как-нить организовать помещение картинки из PIL.Image в QLabel (вернее в QPixmap) без предварительной записи на диск? Уже долго роюсь в интернетах, нашел 2 варианта (понятных), но что-то они не пашут
# 2.7
# -*- coding: utf-8 -*-
import sys
from PyQt4 import QtGui, QtCore
import win32gui, win32con
from PIL import Image, ImageGrab
class MainWindow(QtGui.QWidget):
    def __init__(self):
        QtGui.QWidget.__init__(self)
        self.setFixedSize(760, 170)
        label = QtGui.QLabel(u'(¬_¬)', self)
        bbox_section = (875, 636, 1656, 774)
        screen = ImageGrab.grab(bbox_section)
        screen = screen.convert("P")
        #screen.save('test3.gif','GIF')
        variant = 1
        if variant == 1:
            data = screen.tostring('raw')
            image = QtGui.QImage(data, screen.size[0], screen.size[1], QtGui.QImage.Format_Indexed8)#Format_ARGB32
            pixIM = QtGui.QPixmap.fromImage(image)
            label.setPixmap(pixIM)
        else:
            bytesIM = QtCore.QByteArray()
            bufferIM = QtCore.QBuffer(bytesIM)
            bufferIM.open(QtCore.QIODevice.WriteOnly)
            screen.save(bufferIM, 'PNG')               # err :(
            pixIM = QtGui.QPixmap(bufferIM)
            label.setPixmap(pixIM)
if __name__=="__main__":
    app = QtGui.QApplication(sys.argv)
    win_project = MainWindow()
    win_project.show()
    sys.exit(app.exec_())

Суть программы такая - необходимо сделать скрин области и поместить его в QLabel.
В первом варианте картинка помещается, но какой-бы формат не выставлял, картинка отображается с искажениями

Второй вариант переделывал С++, но застрял на screen.save(bufferIM, ‘PNG’), ошибка
File "D:\Python27\lib\site-packages\PIL\Image.py", line 1423, in save
    raise KeyError(ext) # unknown extension
KeyError: ''
хелп!
degid
С первым вариантом почти разобрался, несоответствие картинки screen.mode с форматом. У меня обработка картинок проходит в режиме screen.convert(“P”), а для него могу подобрать формат. Если конвертировать screen.convert(“RGBA”) и формат выставить QtGui.QImage.Format_ARGB32 то всё работает. Мнеб второй вариант, так как хочу картинки сохранять в базе. Тут вот человек писал про свою проблему, и он юзал как раз этот способ, только он не показал как картинку засовывал в QIODevice.
degid
Shaman
http://pillow.readthedocs.org/en/3.0.x/reference/ImageQt.html
Спасибо за вариант, но он тоже не работает с режимом “P” (это Format_Indexed8 вроде). Белый фон показывает и всё.
Я тут ещё обратил внимание, в документации написано, что в таком режиме нельзя рисовать на картинках, так что, мне всё равно походу придется иметь 2 варианта изображения. Первый для нужных обработок, и второй для отображения и рисования на нём.
Для второго варианта нашел как писать в буфер (исправленный код + 3й вариант)
import sys
from PyQt4 import QtGui, QtCore
import win32gui, win32con
from PIL import Image, ImageGrab
import ImageQt
import cStringIO
class MainWindow(QtGui.QWidget):
    def __init__(self):
        QtGui.QWidget.__init__(self)
        self.setFixedSize(760, 170)
        label = QtGui.QLabel(u'(¬_¬)', self)
        bbox_section = (875, 636, 1656, 774)
        screen = ImageGrab.grab(bbox_section)
        screen = screen.convert("P")
        #screen.save('test3.gif','GIF')
        variant = 2
        if variant == 1:
            print screen.mode
            data = screen.tostring('raw')
            image = QtGui.QImage(data, screen.size[0], screen.size[1], QtGui.QImage.Format_Indexed8) #Format_ARGB32
            pixIM = QtGui.QPixmap.fromImage(image)
            label.setPixmap(pixIM)
        elif variant == 2:
            bufferIM = QtCore.QBuffer()
            bufferIM.open(QtCore.QIODevice.ReadWrite)
            screen.save(bufferIM, 'PNG')
            strio = cStringIO.StringIO()
            strio.write(bufferIM.data())
            bufferIM.close()
            strio.seek(0)
            pixIM = QtGui.QPixmap.fromImage(strio) #err на QByteArray или cStringIO.StringO
            label.setPixmap(pixIM)
        else:
            # работает если screen = screen.convert("RGBA")
            image = ImageQt.ImageQt(screen)
            pixIM = QtGui.QPixmap.fromImage(image)
            label.setPixmap(pixIM)
if __name__=="__main__":
    app = QtGui.QApplication(sys.argv)
    win_project = MainWindow()
    win_project.show()
    sys.exit(app.exec_())

Но теперь застрял на строчке с помещением данных из буфера в QPixmap. Если ей кормить bufferIM.data()
TypeError: QPixmap.fromImage(QImage, Qt.ImageConversionFlags flags=Qt.AutoColor): argument 1 has unexpected type 'QByteArray'
Если cStringIO.StringO, то
TypeError: QPixmap.fromImage(QImage, Qt.ImageConversionFlags flags=Qt.AutoColor): argument 1 has unexpected type 'cStringIO.StringO'
Поигрался с ImageConversionFlags, тоже не помогло.
Shaman
degid
Спасибо за вариант, но он тоже не работает с режимом “P” (это Format_Indexed8 вроде). Белый фон показывает и всё.
А преобразовать формат перед отображением в кьюте никак?
degid
Я пробовал играть переконвертированием в первом варианте, так там появлялись какие-то цверные пиксели-артефакты.
Сейчас вот попробовал с вашем вариантом, так тут что-то вообще странно творится. Хоть видео пиши… Глюки какие-то. То работает, то вылетает с ошибкой, то черная картинка загружена. И это всё зависит от того где расположено screen.convert(“RGBA”) - или перед условием или в самом условии, если перед image = ImageQt.ImageQt(screen) какие-нибудь др команды = вылетает или черная/белая картинка. В общем бред какой-то.
Shaman
У меня всё нормально работало.
from PIL import Image
from PIL.ImageQt import ImageQt
 
 
    def show_(self):
 
        def extract(tar, info, args, types):
 
            def text(xr, param):
                n = xr.find(param)
                return n.text if n is not None else ''
 
            f = tar.extractfile(info)
            xr = ET.fromstringlist(f)
            data = [t(text(xr, p)) for p, t in zip(args, types)]
            f.close()
            return data
 
        if self.current is None:
            return
        name, (dscr, (img, ext)) = self.index[self.current]
        width, height = extract(self.archive, dscr,
                                ('./targetinfo/nImageWidth', './targetinfo/nImageHeight'),
                                (int, int))
        f = self.archive.extractfile(img)
        if ext == 'raw':
            im = Image.frombuffer('L', (width, f.size / width), f.read(), 'raw', 'L', 0, 1)
            prop = IMG_ASP_RAW
        else:
            im = Image.open(f)
            prop = IMG_ASP
        image = ImageQt(im.resize((width, int(width * prop)), Image.BICUBIC))
        im.close()
        f.close()
        self.imageLabel.setPixmap(QtGui.QPixmap.fromImage(image))
        self.setWindowTitle('%s [%s]' % (TITLE, name))
degid
Хм, я использовал import ImageQt (по ссылке вроде про это говорится), а у вас в скрипте from PIL.ImageQt import ImageQt
В любом случае, это вариант тоже работает только c “RGBA”, но он корректно переконвертируется из “P”.
Баги и ошибки что у меня были, вероятно из-за того что параллельно выполнялся другой скрипт. По крайней мере, сейчас такого уже не наблюдается.

***продолжаю ковырять вариант с буфером…
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Powered by DjangoBB