Уведомления

Группа в Telegram: @pythonsu

#1 Янв. 13, 2016 09:56:01

degid
От: Ясиноватая
Зарегистрирован: 2012-12-04
Сообщения: 49
Репутация: +  1  -
Профиль   Отправить e-mail  

Картинка PIL.Image в QPixmap

Всем привет.
Можно ли как-нить организовать помещение картинки из 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 (Янв. 13, 2016 22:05:12)

Офлайн

#2 Янв. 13, 2016 10:20:48

degid
От: Ясиноватая
Зарегистрирован: 2012-12-04
Сообщения: 49
Репутация: +  1  -
Профиль   Отправить e-mail  

Картинка PIL.Image в QPixmap

С первым вариантом почти разобрался, несоответствие картинки screen.mode с форматом. У меня обработка картинок проходит в режиме screen.convert(“P”), а для него могу подобрать формат. Если конвертировать screen.convert(“RGBA”) и формат выставить QtGui.QImage.Format_ARGB32 то всё работает. Мнеб второй вариант, так как хочу картинки сохранять в базе. Тут вот человек писал про свою проблему, и он юзал как раз этот способ, только он не показал как картинку засовывал в QIODevice.



Офлайн

#3 Янв. 13, 2016 17:32:06

Shaman
Зарегистрирован: 2013-03-15
Сообщения: 1369
Репутация: +  88  -
Профиль   Отправить e-mail  

Офлайн

#4 Янв. 13, 2016 23:02:41

degid
От: Ясиноватая
Зарегистрирован: 2012-12-04
Сообщения: 49
Репутация: +  1  -
Профиль   Отправить e-mail  

Картинка PIL.Image в QPixmap

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, тоже не помогло.



Офлайн

#5 Янв. 13, 2016 23:30:35

Shaman
Зарегистрирован: 2013-03-15
Сообщения: 1369
Репутация: +  88  -
Профиль   Отправить e-mail  

Картинка PIL.Image в QPixmap

degid
Спасибо за вариант, но он тоже не работает с режимом “P” (это Format_Indexed8 вроде). Белый фон показывает и всё.
А преобразовать формат перед отображением в кьюте никак?

Офлайн

#6 Янв. 13, 2016 23:48:31

degid
От: Ясиноватая
Зарегистрирован: 2012-12-04
Сообщения: 49
Репутация: +  1  -
Профиль   Отправить e-mail  

Картинка PIL.Image в QPixmap

Я пробовал играть переконвертированием в первом варианте, так там появлялись какие-то цверные пиксели-артефакты.
Сейчас вот попробовал с вашем вариантом, так тут что-то вообще странно творится. Хоть видео пиши… Глюки какие-то. То работает, то вылетает с ошибкой, то черная картинка загружена. И это всё зависит от того где расположено screen.convert(“RGBA”) - или перед условием или в самом условии, если перед image = ImageQt.ImageQt(screen) какие-нибудь др команды = вылетает или черная/белая картинка. В общем бред какой-то.



Отредактировано degid (Янв. 13, 2016 23:49:26)

Офлайн

#7 Янв. 14, 2016 00:00:54

Shaman
Зарегистрирован: 2013-03-15
Сообщения: 1369
Репутация: +  88  -
Профиль   Отправить e-mail  

Картинка PIL.Image в QPixmap

У меня всё нормально работало.

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))

Отредактировано Shaman (Янв. 14, 2016 00:01:40)

Офлайн

#8 Янв. 14, 2016 01:14:26

degid
От: Ясиноватая
Зарегистрирован: 2012-12-04
Сообщения: 49
Репутация: +  1  -
Профиль   Отправить e-mail  

Картинка PIL.Image в QPixmap

Хм, я использовал import ImageQt (по ссылке вроде про это говорится), а у вас в скрипте from PIL.ImageQt import ImageQt
В любом случае, это вариант тоже работает только c “RGBA”, но он корректно переконвертируется из “P”.
Баги и ошибки что у меня были, вероятно из-за того что параллельно выполнялся другой скрипт. По крайней мере, сейчас такого уже не наблюдается.

***продолжаю ковырять вариант с буфером…



Отредактировано degid (Янв. 14, 2016 01:15:49)

Офлайн

Board footer

Модераторировать

Powered by DjangoBB

Lo-Fi Version