This commit is contained in:
iperov 2021-08-26 19:12:05 +04:00
parent babe7e3215
commit 035029bdd6
4 changed files with 116 additions and 15 deletions

View file

@ -1 +1,2 @@
from .ImageProcessor import ImageProcessor from .ImageProcessor import ImageProcessor
from .misc import get_NHWC_shape

View file

@ -4,7 +4,8 @@ from .core.widget import (BlockSignals, disable, enable, hide,
hide_and_disable, show, show_and_enable) hide_and_disable, show, show_and_enable)
from .gui.from_file import (QIcon_from_file, QPixmap_from_file, from .gui.from_file import (QIcon_from_file, QPixmap_from_file,
QXImage_from_file, QXPixmap_from_file) QXImage_from_file, QXPixmap_from_file)
from .gui.from_np import QPixmap_from_np from .gui.from_np import (QImage_ARGB32_from_buffer, QImage_BGR888_from_buffer,
QPixmap_from_np)
from .gui.QXImageSequence import QXImageSequence from .gui.QXImageSequence import QXImageSequence
from .gui.QXPixmap import QXPixmap from .gui.QXPixmap import QXPixmap
from .widgets.QXCheckBox import QXCheckBox from .widgets.QXCheckBox import QXCheckBox
@ -22,6 +23,7 @@ from .widgets.QXLabel import QXLabel
from .widgets.QXLineEdit import QXLineEdit from .widgets.QXLineEdit import QXLineEdit
from .widgets.QXMainApplication import QXMainApplication from .widgets.QXMainApplication import QXMainApplication
from .widgets.QXMenuBar import QXMenuBar from .widgets.QXMenuBar import QXMenuBar
from .widgets.QXOpenGLWidget import QXOpenGLWidget
from .widgets.QXProgressBar import QXProgressBar from .widgets.QXProgressBar import QXProgressBar
from .widgets.QXPushButton import QXPushButton from .widgets.QXPushButton import QXPushButton
from .widgets.QXRadioButton import QXRadioButton from .widgets.QXRadioButton import QXRadioButton

View file

@ -1,25 +1,72 @@
from typing import Union
import numpy as np import numpy as np
from PyQt6.QtGui import * from PyQt6.QtGui import *
from ...image import ImageProcessor
from ...image import ImageProcessor, get_NHWC_shape
_C_to_Format = {
1: QImage.Format.Format_Grayscale8,
3: QImage.Format.Format_BGR888,
4: QImage.Format.Format_ARGB32
}
def QPixmap_from_np(image : np.ndarray): def QPixmap_from_np(image : np.ndarray):
ip = ImageProcessor(image).to_uint8() """
N,H,W,C = ip.get_dims() constructs QPixmap from image np.ndarray
"""
if image.dtype != np.uint8:
raise ValueError('image.dtype must be np.uint8')
if N > 1: N,H,W,C = get_NHWC_shape(image)
raise ValueError(f'N dim must be == 1') if N != 1:
raise ValueError('image N must == 1')
if C == 1:
format = QImage.Format.Format_Grayscale8 format = _C_to_Format.get(C, None)
elif C == 3: if format is None:
format = QImage.Format.Format_BGR888
elif C == 4:
format = QImage.Format.Format_ARGB32
else:
raise ValueError(f'Unsupported channels {C}') raise ValueError(f'Unsupported channels {C}')
image = ip.get_image('HWC')
q_image = QImage(image.data, W, H, W*C, format) q_image = QImage(image.data, W, H, W*C, format)
q_pixmap = QPixmap.fromImage(q_image) q_pixmap = QPixmap.fromImage(q_image)
return q_pixmap return q_pixmap
def QImage_from_np(image : np.ndarray):
"""
constructs QImage from image np.ndarray
given image must live the whole life cycle of QImage.
"""
if image.dtype != np.uint8:
raise ValueError('image.dtype must be np.uint8')
N,H,W,C = get_NHWC_shape(image)
if N != 1:
raise ValueError('image N must == 1')
format = _C_to_Format.get(C, None)
if format is None:
raise ValueError(f'Unsupported channels {C}')
return QImage(image.data, W, H, W*C, format)
def QImage_BGR888_from_buffer(buffer : Union[bytes, bytearray], width : int, height : int ):
"""
constructs QImage of BGR888 format from byte buffer with given width,height
given buffer must live the whole life cycle of QImage.
"""
if len(buffer) != width*height*3:
raise ValueError(f'Size of buffer must be width*height*3 == {width*height*3}')
return QImage(buffer, width, height, width*3, QImage.Format.Format_BGR888)
def QImage_ARGB32_from_buffer(buffer : Union[bytes, bytearray], width : int, height : int ):
"""
constructs QImage of ARGB32 format from byte buffer with given width,height
given buffer must live the whole life cycle of QImage.
"""
if len(buffer) != width*height*4:
raise ValueError(f'Size of buffer must be width*height*4 == {width*height*4}')
return QImage(buffer, width, height, width*3, QImage.Format.Format_ARGB32)

View file

@ -0,0 +1,51 @@
from PyQt6.QtGui import *
from PyQt6.QtOpenGL import *
from PyQt6.QtOpenGLWidgets import *
from PyQt6.QtWidgets import *
from ._part_QXWidget import _part_QXWidget
_size_policy_from_str = {
'fixed' : QSizePolicy.Policy.Fixed,
'minimum' : QSizePolicy.Policy.Minimum,
'maximum' : QSizePolicy.Policy.Maximum,
'preferred' : QSizePolicy.Policy.Preferred,
'minimumexpanding' : QSizePolicy.Policy.MinimumExpanding,
'expanding' : QSizePolicy.Policy.Expanding,
'ignored' : QSizePolicy.Policy.Ignored,
}
class QXOpenGLWidget(QOpenGLWidget, _part_QXWidget):
def __init__(self,
font=None, tooltip_text=None,
size_policy=None,
minimum_size=None, minimum_width=None, minimum_height=None,
maximum_size=None, maximum_width=None, maximum_height=None,
fixed_size=None, fixed_width=None, fixed_height=None,
hided=False, enabled=True
):
super().__init__()
self._default_pal = QPalette( self.palette() )
if size_policy is not None:
x1, x2 = size_policy
if isinstance(x1, str):
x1 = _size_policy_from_str[x1.lower()]
if isinstance(x2, str):
x2 = _size_policy_from_str[x2.lower()]
size_policy = (x1, x2)
_part_QXWidget.__init__(self, font=font, tooltip_text=tooltip_text,
size_policy=size_policy,
minimum_size=minimum_size, minimum_width=minimum_width, minimum_height=minimum_height,
maximum_size=maximum_size, maximum_width=maximum_width, maximum_height=maximum_height,
fixed_size=fixed_size, fixed_width=fixed_width, fixed_height=fixed_height,
hided=hided, enabled=enabled )
def focusInEvent(self, ev : QFocusEvent):
super().focusInEvent(ev)
_part_QXWidget.focusInEvent(self, ev)
def resizeEvent(self, ev : QResizeEvent):
super().resizeEvent(ev)
_part_QXWidget.resizeEvent(self, ev)