예제 #1
0
class MainWindow(QMainWindow):

    def __init__(self):
        super(MainWindow, self).__init__()
        self.title = "Image Viewer"
        self.setWindowTitle(self.title)

        self.lastY = 0

        self.image = QImage(2080, 1, QImage.Format.Format_Grayscale8)
        self.label = QLabel(self)
        self.resize (2080, 500)
    
    def updateImage(self, x, y, c):
        if not self.lastY == y:
            self.image = self.image.copy(0, 0, 2080, y+1)
            self.lastY = y
        self.image.setPixelColor(x,y,QColor(c,c,c))
    
    def refreshImage(self):
        pixmap = QPixmap.fromImage(self.image)
        self.label.setPixmap(pixmap)
        self.setCentralWidget(self.label)

    def saveImage(self):
        name = time.strftime("%Y %m %d-%H %M %S")
        self.image.save('NOAA ' + str(name) + '.png')
예제 #2
0
    def rotateImage90(self, direction):
        """Rotate image 90º clockwise or counterclockwise."""
        if self.image.isNull() == False:
            if direction == "cw":
                transform90 = QTransform().rotate(90)
            elif direction == "ccw":
                transform90 = QTransform().rotate(-90)

            pixmap = QPixmap(self.image)

            #TODO: Try flipping the height/width when flipping the image

            rotated = pixmap.transformed(transform90,
                                         mode=Qt.SmoothTransformation)
            self.resize(self.image.height(), self.image.width())
            #rotated = pixmap.trueMatrix(transform90, pixmap.width, pixmap.height)

            #self.image_label.setPixmap(rotated.scaled(self.image_label.size(),
            #    Qt.KeepAspectRatio, Qt.SmoothTransformation))
            self.image = QImage(rotated)
            #self.setPixmap(rotated)
            self.setPixmap(
                rotated.scaled(self.size(), Qt.KeepAspectRatioByExpanding,
                               Qt.SmoothTransformation))
            self.repaint()  # repaint the child widget
        else:
            # No image to rotate
            pass
예제 #3
0
 def convertToRGB(self):
     """Convert image to RGB format."""
     if self.image.isNull() == False:
         converted_img = self.image.convertToFormat(QImage.Format_RGB32)
         #self.image = converted_img
         self.image = QImage(converted_img)
         self.setPixmap(QPixmap().fromImage(converted_img))
         self.repaint()
예제 #4
0
 def convertToGray(self):
     """Convert image to grayscale."""
     if self.image.isNull() == False:
         converted_img = self.image.convertToFormat(
             QImage.Format_Grayscale16)
         #self.image = converted_img
         self.image = QImage(converted_img)
         self.setPixmap(QPixmap().fromImage(converted_img))
         self.repaint()
예제 #5
0
    def cropImage(self):
        """Crop selected portions in the image."""
        if self.image.isNull() == False:
            rect = QRect(10, 20, 400, 200)
            original_image = self.image
            cropped = original_image.copy(rect)

            self.image = QImage(cropped)
            self.setPixmap(QPixmap().fromImage(cropped))
예제 #6
0
    def __init__(self):
        super(MainWindow, self).__init__()
        self.title = "Image Viewer"
        self.setWindowTitle(self.title)

        self.lastY = 0

        self.image = QImage(2080, 1, QImage.Format.Format_Grayscale8)
        self.label = QLabel(self)
        self.resize (2080, 500)
예제 #7
0
파일: Texture.py 프로젝트: BCN3D/Uranium
class Texture:
    """A class describing the interface to be used for texture objects.

    This interface should be implemented by OpenGL implementations to handle texture
    objects.
    """
    def __init__(self,
                 open_gl_binding_object: QAbstractOpenGLFunctions) -> None:
        super().__init__()

        self._qt_texture = QOpenGLTexture(QOpenGLTexture.Target.Target2D)
        self._gl = open_gl_binding_object
        self._file_name = None
        self._image = None

    def getTextureId(self) -> int:
        """Get the OpenGL ID of the texture."""
        return self._qt_texture.textureId()

    def bind(self, texture_unit):
        """Bind the texture to a certain texture unit.

        :param texture_unit: The texture unit to bind to.
        """
        if not self._qt_texture.isCreated():
            if self._file_name != None:
                self._image = QImage(self._file_name).mirrored()
            elif self._image is None:  # No filename or image set.
                self._image = QImage(1, 1, QImage.Format.Format_ARGB32)
                self._image.fill(0)
            self._qt_texture.setData(self._image)
            self._qt_texture.setMinMagFilters(QOpenGLTexture.Filter.Linear,
                                              QOpenGLTexture.Filter.Linear)

        self._qt_texture.bind(texture_unit)

    def release(self, texture_unit):
        """Release the texture from a certain texture unit.

        :param texture_unit: The texture unit to release from.
        """
        self._qt_texture.release(texture_unit)

    def load(self, file_name):
        """Load an image and upload it to the texture.

        :param file_name: The file name of the image to load.
        """
        self._file_name = file_name
        # Actually loading the texture is postponed until the next bind() call.
        # This makes sure we are on the right thread and have a current context when trying to upload.

    def setImage(self, image):
        self._image = image
예제 #8
0
파일: Texture.py 프로젝트: BCN3D/Uranium
    def bind(self, texture_unit):
        """Bind the texture to a certain texture unit.

        :param texture_unit: The texture unit to bind to.
        """
        if not self._qt_texture.isCreated():
            if self._file_name != None:
                self._image = QImage(self._file_name).mirrored()
            elif self._image is None:  # No filename or image set.
                self._image = QImage(1, 1, QImage.Format.Format_ARGB32)
                self._image.fill(0)
            self._qt_texture.setData(self._image)
            self._qt_texture.setMinMagFilters(QOpenGLTexture.Filter.Linear,
                                              QOpenGLTexture.Filter.Linear)

        self._qt_texture.bind(texture_unit)
예제 #9
0
    def __init__(self, comic_info: ComicInfo, tab_widget: QTabWidget, down_v_box_layout: QVBoxLayout):
        super().__init__()
        self.tabWidget = tab_widget
        self.comicInfo = comic_info
        self.down_v_box_layout = down_v_box_layout
        self.setMinimumHeight(200)
        # 图片
        img = QImage.fromData(comic_info.cover)
        self.img_label = QLabel(self)
        self.img_label.setScaledContents(True)
        w, h = image_resize(comic_info.cover, height=200)
        self.img_label.resize(QtCore.QSize(w, h))
        self.img_label.setGeometry(5, 5, w, h)
        self.img_label.setPixmap(QPixmap.fromImage(img))
        # self.img_label.setPixmap(QtGui.QPixmap("/Users/bo/my/tmp/老夫子2/第1卷/1.jpg"))
        # 标题
        self.title = ButtonQLabel(self)
        self.title.onclick(self.add_tab)
        self.title.setText(comic_info.title)
        self.title.setGeometry(180, 10, 550, 35)
        title_font = QtGui.QFont()
        title_font.setPointSize(30)
        title_font.setBold(True)
        title_font.setUnderline(True)
        self.title.setFont(title_font)
        self.title.setCursor(QtGui.QCursor(QtCore.Qt.CursorShape.PointingHandCursor))

        # 作者
        self.author = QLabel(self)
        self.author.setText("作者 : " + comic_info.author)
        self.author.setGeometry(180, 50, 250, 20)
        # 状态
        self.status = QLabel(self)
        self.status.setText("更新状态 : " + comic_info.status)
        self.status.setGeometry(500, 50, 150, 20)
        # 热度
        self.status = QLabel(self)
        self.status.setText("热度 : " + str(comic_info.heat))
        self.status.setGeometry(800, 50, 100, 20)

        # 类型
        self.tip = QLabel(self)
        self.tip.setText("类型 : " + comic_info.tip)
        self.tip.setGeometry(180, 70, 250, 20)

        # web
        self.domain = QLabel(self)
        self.domain.setText(f"查看原网页 : {comic_info.domain}")
        self.domain.setText(f'查看原网页 : <a href="{comic_info.url}">{comic_info.domain}</a>')
        self.domain.setGeometry(500, 70, 250, 20)
        self.domain.setOpenExternalLinks(True)

        # 描述
        self.describe = QLabel(self)
        self.describe.setText("  " + comic_info.describe)
        self.describe.setGeometry(180, 90, 664, 110)
        self.describe.setWordWrap(True)
        # 对齐方式
        self.describe.setAlignment(
            QtCore.Qt.AlignmentFlag.AlignLeading | QtCore.Qt.AlignmentFlag.AlignLeft | QtCore.Qt.AlignmentFlag.AlignTop)
예제 #10
0
    def insertFromMimeData(self, source):

        cursor = self.textCursor()
        document = self.document()

        if source.hasUrls():

            for u in source.urls():
                file_ext = splitext(str(u.toLocalFile()))
                if u.isLocalFile() and file_ext in IMAGE_EXTENSIONS:
                    image = QImage(u.toLocalFile())
                    document.addResource(QTextDocument.ImageResource, u, image)
                    cursor.insertImage(u.toLocalFile())
                else:
                    break

            else:
                return

        elif source.hasImage():
            image = source.imageData()
            uuid = hexuuid()
            document.addResource(QTextDocument.ImageResource, uuid, image)
            cursor.insertImage(uuid)
            return

        super(TextEdit, self).insertFromMimeData(source)
예제 #11
0
    def opencv_to_qt(img) -> QImage:
        """
        Convert OpenCV image to PyQT image
        by changing format to RGB/RGBA from BGR
        """
        qformat = QImage.Format.Format_Indexed8
        if len(img.shape) == 3:
            if img.shape[2] == 4:  # RGBA
                qformat = QImage.Format.Format_RGBA8888
            else:  # RGB
                qformat = QImage.Format.Format_RGB888

        img = numpy.require(img, numpy.uint8, "C")
        out_image = QImage(img, img.shape[1], img.shape[0], img.strides[0],
                           qformat)  # BGR to RGB
        out_image = out_image.rgbSwapped()

        return out_image
예제 #12
0
    def __init__(self, parent, image=None):
        super().__init__(parent)
        self.parent = parent
        self.image = QImage()
        #self.image = "images/parrot.png"

        #self.original_image = self.image.copy
        self.original_image = self.image

        self.rubber_band = QRubberBand(QRubberBand.Shape.Rectangle, self)

        # setBackgroundRole() will create a bg for the image
        #self.setBackgroundRole(QPalette.Base)
        self.setSizePolicy(QSizePolicy.Policy.Ignored,
                           QSizePolicy.Policy.Ignored)
        self.setScaledContents(True)

        # Load image
        self.setPixmap(QPixmap().fromImage(self.image))
        self.setAlignment(Qt.Alignment.AlignCenter)
def test_sanity(tmp_path):
    # Segfault test
    app = QApplication([])
    ex = Example()
    assert app  # Silence warning
    assert ex  # Silence warning

    for mode in ("1", "RGB", "RGBA", "L", "P"):
        # to QPixmap
        im = hopper(mode)
        data = ImageQt.toqpixmap(im)

        assert isinstance(data, QPixmap)
        assert not data.isNull()

        # Test saving the file
        tempfile = str(tmp_path / f"temp_{mode}.png")
        data.save(tempfile)

        # Render the image
        qimage = ImageQt.ImageQt(im)
        data = QPixmap.fromImage(qimage)
        qt_format = QImage.Format if ImageQt.qt_version == "6" else QImage
        qimage = QImage(128, 128, qt_format.Format_ARGB32)
        painter = QPainter(qimage)
        image_label = QLabel()
        image_label.setPixmap(data)
        image_label.render(painter, QPoint(0, 0), QRegion(0, 0, 128, 128))
        painter.end()
        rendered_tempfile = str(tmp_path / f"temp_rendered_{mode}.png")
        qimage.save(rendered_tempfile)
        assert_image_equal_tofile(im.convert("RGBA"), rendered_tempfile)

        # from QPixmap
        roundtrip(hopper(mode))

    app.quit()
    app = None
예제 #14
0
    def openImage(self):
        """Load a new image into the """
        image_file, _ = QFileDialog.getOpenFileName(
            self, "Open Image", "",
            "PNG Files (*.png);;JPG Files (*.jpeg *.jpg );;Bitmap Files (*.bmp);;\
                GIF Files (*.gif)")

        if image_file:
            # Reset values when opening an image
            self.parent.zoom_factor = 1
            #self.parent.scroll_area.setVisible(True)
            self.parent.print_act.setEnabled(True)
            self.parent.updateActions()

            # Reset all sliders
            self.parent.brightness_slider.setValue(0)

            # Get image format
            image_format = self.image.format()
            self.image = QImage(image_file)
            self.original_image = self.image.copy()

            #pixmap = QPixmap(image_file)
            self.setPixmap(QPixmap().fromImage(self.image))
            #image_size = self.image_label.sizeHint()
            self.resize(self.pixmap().size())

            #self.scroll_area.setMinimumSize(image_size)

            #self.image_label.setPixmap(pixmap.scaled(self.image_label.size(),
            #    Qt.KeepAspectRatio, Qt.SmoothTransformation))
        elif image_file == "":
            # User selected Cancel
            pass
        else:
            QMessageBox.information(self, "Error", "Unable to open image.",
                                    QMessageBox.Ok)
예제 #15
0
    def resizeImage(self):
        """Resize image."""
        #TODO: Resize image by specified size
        if self.image.isNull() == False:
            resize = QTransform().scale(0.5, 0.5)

            pixmap = QPixmap(self.image)

            resized_image = pixmap.transformed(resize,
                                               mode=Qt.SmoothTransformation)
            #rotated = pixmap.trueMatrix(transform90, pixmap.width, pixmap.height)

            #self.image_label.setPixmap(rotated)

            #self.image_label.setPixmap(rotated.scaled(self.image_label.size(),
            #    Qt.KeepAspectRatio, Qt.SmoothTransformation))
            self.image = QImage(resized_image)
            self.setPixmap(resized_image)
            #self.image = QPixmap(rotated)
            self.setScaledContents(True)
            self.repaint()  # repaint the child widget
        else:
            # No image to rotate
            pass
예제 #16
0
    def flipImage(self, axis):
        """
        Mirror the image across the horizontal axis.
        """
        if self.image.isNull() == False:
            if axis == "horizontal":
                flip_h = QTransform().scale(-1, 1)
                pixmap = QPixmap(self.image)
                flipped = pixmap.transformed(flip_h)
            elif axis == "vertical":
                flip_v = QTransform().scale(1, -1)
                pixmap = QPixmap(self.image)
                flipped = pixmap.transformed(flip_v)

            #self.image_label.setPixmap(flipped)
            #self.image_label.setPixmap(flipped.scaled(self.image_label.size(),
            #    Qt.KeepAspectRatio, Qt.SmoothTransformation))
            self.image = QImage(flipped)
            self.setPixmap(flipped)
            #self.image = QPixmap(flipped)
            self.repaint()
        else:
            # No image to flip
            pass
예제 #17
0
    def getOutput(self) -> QImage:
        """Get the pixel data produced by this render pass.

        This returns an object that contains the pixel data for this render pass.

        :note The current object type returned is currently dependant on the specific
        implementation of the UM.View.GL.FrameBufferObject class.
        """

        if self._fbo is None:
            Logger.log(
                "w",
                "FrameBufferObject has been released. Can't get frame output.")
            return QImage()
        return self._fbo.getContents()
예제 #18
0
def take_snapshot(camera_position, camera_lookat,
                  is_layer_view) -> typing.Optional[QImage]:
    """
	Take a snapshot of the current scene.
	:param camera_position: The position of the camera to take the snapshot with.
	:param camera_lookat: The position of the focal point of the camera.
	:param is_layer_view: Whether we're looking at layer view or the model itself.
	:return: A screenshot of the current scene.
	"""
    application = cura.CuraApplication.CuraApplication.getInstance()
    plugin_registry = application.getPluginRegistry()

    # Set the camera to the desired position. We'll use the actual camera for the snapshot just because it looks cool while it's busy.
    camera = application.getController().getScene().getActiveCamera()
    camera.setPosition(
        UM.Math.Vector.Vector(camera_position[0], camera_position[2],
                              camera_position[1])
    )  # Note that these are OpenGL coordinates, swapping Y and Z.
    if not camera_lookat:
        bounding_box = UM.Math.AxisAlignedBox.AxisAlignedBox()
        for node in UM.Scene.Iterator.DepthFirstIterator.DepthFirstIterator(
                cura.CuraApplication.CuraApplication.getInstance(
                ).getController().getScene().getRoot()):
            if node.isSelectable():
                bounding_box = bounding_box + node.getBoundingBox()
        camera_lookat = bounding_box.center
    else:
        camera_lookat = UM.Math.Vector.Vector(camera_lookat[0],
                                              camera_lookat[2],
                                              camera_lookat[1])
    camera.lookAt(camera_lookat)
    if abs(camera.getPosition().x - camera_lookat.x) < 0.01 and abs(
            camera.getPosition().z -
            camera_lookat.z) < 0.01:  # Looking straight up or straight down.
        # Make sure the yaw of the camera is consistent regardless of previous position.
        if camera.getPosition().y > camera_lookat.y:
            camera.setOrientation(UM.Math.Quaternion.Quaternion(-2, 0, 0, 2))
        else:
            camera.setOrientation(UM.Math.Quaternion.Quaternion(2, 0, 0, 2))
    time.sleep(
        2
    )  # Some time to update the scene nodes. Don't know if this is necessary but it feels safer.

    # Use a transparent background.
    gl_bindings = UM.View.GL.OpenGL.OpenGL.getInstance().getBindingsObject()
    gl_bindings.glClearColor(0.0, 0.0, 0.0, 0.0)
    gl_bindings.glClear(gl_bindings.GL_COLOR_BUFFER_BIT
                        | gl_bindings.GL_DEPTH_BUFFER_BIT)

    try:  # In Qt6 it's an enum, in Qt5 it's a field of QImage.
        colour_format = QImage.Format.Format_ARGB32  # For Qt6.
    except AttributeError:
        colour_format = QImage.Format_ARGB32  # For Qt5.

    if is_layer_view:
        # Remove any nozzle node. It can get in the way of what we want to see and influence cropping of the image badly.
        simulation_view_plugin = plugin_registry.getPluginObject(
            "SimulationView")
        for node in UM.Scene.Iterator.DepthFirstIterator.DepthFirstIterator(
                application.getController().getScene().getRoot()):
            if hasattr(
                    node, "_createNozzleMesh"
            ):  # This node is a NozzleNode (the actual class is not exposed to us outside the plug-in).
                node.getParent().removeChild(node)

        render_pass = simulation_view_plugin.getSimulationPass()
        render_pass.render()
        time.sleep(1.2)
        screenshot = render_pass.getOutput()
        print("---- screenshot size:", screenshot.width(), "x",
              screenshot.height())
        if screenshot.width() != render_width or screenshot.height(
        ) != render_height:
            print(
                "---- render output not correct size! Resizing window to compensate."
            )
            main_window = application.getMainWindow()
            delta_width = render_width - screenshot.width()
            delta_height = render_height - screenshot.height()
            main_window.setWidth(main_window.width() + delta_width)
            main_window.setHeight(main_window.height() + delta_height)
            return None  # Failed to render. Try again after waiting outside of Qt thread.

        # Remove alpha channel from this picture. We don't want the semi-transparent support since we don't draw the object outline here.
        # Sadly, QImage.convertToFormat has only 2 formats with boolean alpha and they both premultiply. So we'll go the hard way: Through Numpy.
        pixel_bits = screenshot.bits().asarray(screenshot.sizeInBytes())
        pixels = numpy.frombuffer(pixel_bits, dtype=numpy.uint8).reshape(
            [screenshot.height(), screenshot.width(), 4])
        opaque = numpy.nonzero(pixels[:, :, 0])
        pixels[opaque[0], opaque[1], 3] = 255
        return QImage(
            pixels.data, pixels.shape[1], pixels.shape[0], colour_format
        ).copy(
        )  # Make a copy because the pixel data will go out of scope for Numpy, so that would be invalid memory.
    else:  # Render the objects themselves! Going to be quite complex here since the render is highly specialised in what it shows and what it doesn't.
        view = plugin_registry.getPluginObject("SolidView")
        view._checkSetup()
        renderer = view.getRenderer()

        support_angle = application.getGlobalContainerStack().getProperty(
            "support_angle", "value")
        view._enabled_shader.setUniformValue(
            "u_overhangAngle", math.cos(
                math.radians(90 - support_angle)))  # Correct overhang angle.
        view._enabled_shader.setUniformValue(
            "u_lowestPrintableHeight",
            -1.0)  # Don't show initial layer height.
        object_batch = renderer.createRenderBatch(shader=view._enabled_shader)
        renderer.addRenderBatch(object_batch)
        for node in UM.Scene.Iterator.DepthFirstIterator.DepthFirstIterator(
                application.getController().getScene().getRoot()):
            if not node.getMeshData() or not node.isSelectable():
                continue
            uniforms = {}

            # Get the object's colour.
            extruder_index = int(
                node.callDecoration("getActiveExtruderPosition"))
            material_color = application.getExtrudersModel().getItem(
                extruder_index)["color"]
            uniforms["diffuse_color"] = [
                int(material_color[1:3], 16) / 255,
                int(material_color[3:5], 16) / 255,
                int(material_color[5:7], 16) / 255, 1.0
            ]

            # Render with special shaders for special types of meshes, or otherwise in the normal batch.
            if node.callDecoration("isNonPrintingMesh") and (
                    node.callDecoration("isInfillMesh")
                    or node.callDecoration("isCuttingMesh")):
                renderer.queueNode(node,
                                   shader=view._non_printing_shader,
                                   uniforms=uniforms,
                                   transparent=True)
            elif node.callDecoration("isSupportMesh"):
                uniforms["diffuse_color_2"] = [
                    uniforms["diffuse_color"][0] * 0.6,
                    uniforms["diffuse_color"][1] * 0.6,
                    uniforms["diffuse_color"][2] * 0.6, 1.0
                ]
                renderer.queueNode(node,
                                   shader=view._support_mesh_shader,
                                   uniforms=uniforms)
            else:
                object_batch.addItem(
                    node.getWorldTransformation(copy=False),
                    node.getMeshData(),
                    uniforms=uniforms,
                    normal_transformation=node.getCachedNormalMatrix())

        default_pass = renderer.getRenderPass("default")
        default_pass.render()
        time.sleep(1.2)
        normal_shading = default_pass.getOutput()
        xray_pass = renderer.getRenderPass("xray")
        renderer.addRenderPass(xray_pass)
        xray_pass.render()
        time.sleep(1.2)
        xray_shading = xray_pass.getOutput()

        # Manually composite these shadings. Because the composite shader also adds a background colour.
        normal_data = normal_shading.bits().asarray(
            normal_shading.sizeInBytes())
        composite_pixels = numpy.frombuffer(normal_data,
                                            dtype=numpy.uint8).reshape([
                                                normal_shading.height(),
                                                normal_shading.width(), 4
                                            ])  # Start from the normal image.
        colours = numpy.true_divide(composite_pixels[:, :, 0:3],
                                    255)  # Scaled to [0, 1].
        alpha = numpy.true_divide(composite_pixels[:, :, 3], 255)
        xray_data = xray_shading.bits().asarray(xray_shading.sizeInBytes())
        xray_pixels = numpy.frombuffer(xray_data, dtype=numpy.uint8).reshape(
            [xray_shading.height(),
             xray_shading.width(), 4])
        xray_pixels = numpy.mod(
            xray_pixels[:, :, 0:3], 10
        ) // 5  # The X-ray shader creates increments of 5 for some reason. If there are an odd number of increments (not divisible by 10) then it must be highlighted.
        hue_shift = ((alpha - 0.333) * 6.2831853)
        cos_shift = numpy.repeat(numpy.expand_dims(numpy.cos(-hue_shift),
                                                   axis=2),
                                 3,
                                 axis=2)
        sin_shift = numpy.repeat(numpy.expand_dims(numpy.sin(-hue_shift),
                                                   axis=2),
                                 3,
                                 axis=2)
        k = numpy.array(
            [0.57735, 0.57735, 0.57735]
        )  # 1/sqrt(3), resulting in a diagonal unit vector around which we rotate the channels.
        cross_colour = numpy.cross(colours, k) * -1
        dot_colour = numpy.repeat(numpy.expand_dims(numpy.dot(colours, k),
                                                    axis=2),
                                  3,
                                  axis=2)
        rotated_hue = colours * cos_shift + cross_colour * sin_shift + (
            cos_shift * -1 +
            1.0) * dot_colour * k  # Rodrigues' rotation formula!
        rotated_hue = rotated_hue * 255

        composite_pixels[:, :, 0:
                         3] -= composite_pixels[:, :, 0:
                                                3] * xray_pixels  # Don't use the normal colour for x-rayed pixels.
        composite_pixels[:, :, 0:3] += (rotated_hue * xray_pixels).astype(
            "uint8")  # Use the rotated colour instead.
        composite_pixels[:, :, 3][alpha > 0.1] = 255
        return QImage(
            composite_pixels.data, composite_pixels.shape[1],
            composite_pixels.shape[0], colour_format
        ).copy(
        )  # Make a copy because the pixel data will go out of scope for Numpy, so that would be invalid memory.
예제 #19
0
    def __init__(self, comic_info: ComicInfo, down_v_box_layout: QVBoxLayout):
        super().__init__()
        self.comic_info = comic_info
        self.down_v_box_layout = down_v_box_layout
        self.img_label = QLabel(self)
        self.img_label.setScaledContents(True)
        img = QImage.fromData(comic_info.cover)
        w, h = image_resize(comic_info.cover, width=200)
        self.img_label.resize(QtCore.QSize(w, h))
        self.img_label.setGeometry(10, 10, w, h)
        self.img_label.setPixmap(QPixmap.fromImage(img))
        # self.img_label.setPixmap(QtGui.QPixmap("/Users/bo/my/tmp/老夫子2/第1卷/1.jpg"))

        self.title = QLabel(self)
        self.title.setGeometry(220, 10, 100, 40)
        title_font = QtGui.QFont()
        title_font.setPointSize(16)
        title_font.setBold(True)
        title_font.setUnderline(True)
        self.title.setFont(title_font)
        self.title.setText(comic_info.title)
        self.title.setWordWrap(True)

        info_font = QtGui.QFont()
        info_font.setPointSize(14)
        # 作者
        self.author = QLabel(self)
        self.author.setText("作者 : " + comic_info.author)
        self.author.setGeometry(220, 50, 150, 40)
        self.author.setWordWrap(True)
        self.author.setFont(info_font)
        # 状态
        self.status = QLabel(self)
        self.status.setText("更新状态 : " + comic_info.status)
        self.status.setGeometry(220, 90, 150, 40)
        self.status.setFont(info_font)

        # 热度
        self.heat = QLabel(self)
        self.heat.setText("热度 : " + str(comic_info.heat))
        self.heat.setGeometry(220, 130, 150, 40)
        self.heat.setFont(info_font)

        # 类型
        self.tip = QLabel(self)
        self.tip.setText("类型 : " + comic_info.tip)
        self.tip.setGeometry(220, 170, 150, 40)
        self.tip.setWordWrap(True)
        self.tip.setFont(info_font)

        # web
        self.domain = QLabel(self)
        self.domain.setText(f"查看原网页 : {comic_info.domain}")
        self.domain.setText(f'查看原网页 : <a href="{comic_info.url}">{comic_info.domain}</a>')
        self.domain.setGeometry(220, 210, 150, 40)
        self.domain.setOpenExternalLinks(True)
        self.domain.setFont(info_font)

        # 描述
        self.describe = QLabel(self)
        self.describe.setText("  " + comic_info.describe)
        self.describe.setGeometry(10, 320, 350, 330)
        self.describe.setWordWrap(True)
        # 对齐方式
        self.describe.setAlignment(
            QtCore.Qt.AlignmentFlag.AlignLeading | QtCore.Qt.AlignmentFlag.AlignLeft | QtCore.Qt.AlignmentFlag.AlignTop)

        # 章节列表,创建一个区域

        self.searchHBoxLayout = QHBoxLayout()
        # self.searchHBoxLayout.addSpacing()
        self.searchGroupBox = QGroupBox()
        self.searchGroupBox.setLayout(self.searchHBoxLayout)

        self.searchScroll = QScrollArea(self)
        self.searchScroll.setGeometry(370, 10, 574, 590)
        self.searchScroll.setWidget(self.searchGroupBox)
        self.searchScroll.setWidgetResizable(True)

        # 全选
        self.check_all = QCheckBox(self)
        self.check_all.setText("全选")
        self.check_all.setGeometry(700, 610, 100, 20)
        self.check_all.stateChanged.connect(self.check_all_fun)

        # 下载
        self.down_button = QPushButton(self)
        self.down_button.setText("下载")
        self.down_button.setGeometry(780, 605, 50, 30)

        self.down_button.clicked.connect(self.download_button_click)

        self.load_chapter_list_signa.connect(self.load_chapter)
        self.load_download_task_signa.connect(self.download_callback)

        # 调用对应的service的接口,获取章节列表
        constant.SERVICE.chapter(comic_info, self.load_chapter_list_signa.emit)
예제 #20
0
def get_masked_image(path, size=64, overlay_text=""):
    """
    Returns a pixmap from an image file masked with a smooth circle.
    The returned pixmap will have a size of *size* × *size* pixels.

    :param str path: Path to image file.
    :param int size: Target size. Will be the diameter of the masked image.
    :param str overlay_text: Overlay text. This will be shown in white sans-serif on top
        of the image.
    :return: Masked image with overlay text.
    :rtype: QPixmap
    """

    with open(path, "rb") as f:
        imgdata = f.read()

    imgtype = path.split(".")[-1]

    # Load image and convert to 32-bit ARGB (adds an alpha channel):
    image = QImage.fromData(imgdata, imgtype)
    image.convertToFormat(QImage.Format.Format_ARGB32)

    # Crop image to a square:
    imgsize = min(image.width(), image.height())
    width = (image.width() - imgsize) / 2
    height = (image.height() - imgsize) / 2

    rect = QRect(
        round(width),
        round(height),
        imgsize,
        imgsize,
    )
    image = image.copy(rect)

    # Create the output image with the same dimensions and an alpha channel
    # and make it completely transparent:
    out_img = QImage(imgsize, imgsize, QImage.Format.Format_ARGB32)
    out_img.fill(Qt.GlobalColor.transparent)

    # Create a texture brush and paint a circle with the original image onto
    # the output image:
    brush = QBrush(image)  # Create texture brush
    painter = QPainter(out_img)  # Paint the output image
    painter.setBrush(brush)  # Use the image texture brush
    painter.setPen(Qt.PenStyle.NoPen)  # Don't draw an outline
    painter.setRenderHint(QPainter.RenderHint.Antialiasing, True)  # Use AA
    painter.drawEllipse(0, 0, imgsize, imgsize)  # Actually draw the circle

    if overlay_text:
        # draw text
        font = QtGui.QFont("Arial Rounded MT Bold")
        font.setPointSize(imgsize * 0.4)
        painter.setFont(font)
        painter.setPen(Qt.GlobalColor.white)
        painter.drawText(QRect(0, 0, imgsize, imgsize),
                         Qt.AlignmentFlag.AlignCenter, overlay_text)

    painter.end()  # We are done (segfault if you forget this)

    # Convert the image to a pixmap and rescale it.  Take pixel ratio into
    # account to get a sharp image on retina displays:
    pr = QtWidgets.QApplication.instance().devicePixelRatio()
    pm = QPixmap.fromImage(out_img)
    pm.setDevicePixelRatio(pr)
    size = int(pr * size)
    pm = pm.scaled(
        size,
        size,
        Qt.AspectRatioMode.KeepAspectRatio,
        Qt.TransformationMode.SmoothTransformation,
    )

    return pm
예제 #21
0
class imageLabel(QLabel):
    """Subclass of QLabel for displaying image"""
    def __init__(self, parent, image=None):
        super().__init__(parent)
        self.parent = parent
        self.image = QImage()
        #self.image = "images/parrot.png"

        #self.original_image = self.image.copy
        self.original_image = self.image

        self.rubber_band = QRubberBand(QRubberBand.Shape.Rectangle, self)

        # setBackgroundRole() will create a bg for the image
        #self.setBackgroundRole(QPalette.Base)
        self.setSizePolicy(QSizePolicy.Policy.Ignored,
                           QSizePolicy.Policy.Ignored)
        self.setScaledContents(True)

        # Load image
        self.setPixmap(QPixmap().fromImage(self.image))
        self.setAlignment(Qt.Alignment.AlignCenter)

    def openImage(self):
        """Load a new image into the """
        image_file, _ = QFileDialog.getOpenFileName(
            self, "Open Image", "",
            "PNG Files (*.png);;JPG Files (*.jpeg *.jpg );;Bitmap Files (*.bmp);;\
                GIF Files (*.gif)")

        if image_file:
            # Reset values when opening an image
            self.parent.zoom_factor = 1
            #self.parent.scroll_area.setVisible(True)
            self.parent.print_act.setEnabled(True)
            self.parent.updateActions()

            # Reset all sliders
            self.parent.brightness_slider.setValue(0)

            # Get image format
            image_format = self.image.format()
            self.image = QImage(image_file)
            self.original_image = self.image.copy()

            #pixmap = QPixmap(image_file)
            self.setPixmap(QPixmap().fromImage(self.image))
            #image_size = self.image_label.sizeHint()
            self.resize(self.pixmap().size())

            #self.scroll_area.setMinimumSize(image_size)

            #self.image_label.setPixmap(pixmap.scaled(self.image_label.size(),
            #    Qt.KeepAspectRatio, Qt.SmoothTransformation))
        elif image_file == "":
            # User selected Cancel
            pass
        else:
            QMessageBox.information(self, "Error", "Unable to open image.",
                                    QMessageBox.Ok)

    def saveImage(self):
        """Save the image displayed in the label."""
        #TODO: Add different functionality for the way in which the user can save their image.
        if self.image.isNull() == False:
            image_file, _ = QFileDialog.getSaveFileName(
                self, "Save Image", "",
                "PNG Files (*.png);;JPG Files (*.jpeg *.jpg );;Bitmap Files (*.bmp);;\
                    GIF Files (*.gif)")

            if image_file and self.image.isNull() == False:
                self.image.save(image_file)
            else:
                QMessageBox.information(self, "Error", "Unable to save image.",
                                        QMessageBox.Ok)
        else:
            QMessageBox.information(self, "Empty Image",
                                    "There is no image to save.",
                                    QMessageBox.Ok)

    def clearImage(self):
        """ """
        #TODO: If image is not null ask to save image first.
        pass

    def revertToOriginal(self):
        """Revert the image back to original image."""
        #TODO: Display message dialohg to confirm actions
        self.image = self.original_image
        self.setPixmap(QPixmap().fromImage(self.image))
        self.repaint()

        #self.parent.zoom_factor = 1

    def resizeImage(self):
        """Resize image."""
        #TODO: Resize image by specified size
        if self.image.isNull() == False:
            resize = QTransform().scale(0.5, 0.5)

            pixmap = QPixmap(self.image)

            resized_image = pixmap.transformed(resize,
                                               mode=Qt.SmoothTransformation)
            #rotated = pixmap.trueMatrix(transform90, pixmap.width, pixmap.height)

            #self.image_label.setPixmap(rotated)

            #self.image_label.setPixmap(rotated.scaled(self.image_label.size(),
            #    Qt.KeepAspectRatio, Qt.SmoothTransformation))
            self.image = QImage(resized_image)
            self.setPixmap(resized_image)
            #self.image = QPixmap(rotated)
            self.setScaledContents(True)
            self.repaint()  # repaint the child widget
        else:
            # No image to rotate
            pass

    def cropImage(self):
        """Crop selected portions in the image."""
        if self.image.isNull() == False:
            rect = QRect(10, 20, 400, 200)
            original_image = self.image
            cropped = original_image.copy(rect)

            self.image = QImage(cropped)
            self.setPixmap(QPixmap().fromImage(cropped))

    def rotateImage90(self, direction):
        """Rotate image 90º clockwise or counterclockwise."""
        if self.image.isNull() == False:
            if direction == "cw":
                transform90 = QTransform().rotate(90)
            elif direction == "ccw":
                transform90 = QTransform().rotate(-90)

            pixmap = QPixmap(self.image)

            #TODO: Try flipping the height/width when flipping the image

            rotated = pixmap.transformed(transform90,
                                         mode=Qt.SmoothTransformation)
            self.resize(self.image.height(), self.image.width())
            #rotated = pixmap.trueMatrix(transform90, pixmap.width, pixmap.height)

            #self.image_label.setPixmap(rotated.scaled(self.image_label.size(),
            #    Qt.KeepAspectRatio, Qt.SmoothTransformation))
            self.image = QImage(rotated)
            #self.setPixmap(rotated)
            self.setPixmap(
                rotated.scaled(self.size(), Qt.KeepAspectRatioByExpanding,
                               Qt.SmoothTransformation))
            self.repaint()  # repaint the child widget
        else:
            # No image to rotate
            pass

    def flipImage(self, axis):
        """
        Mirror the image across the horizontal axis.
        """
        if self.image.isNull() == False:
            if axis == "horizontal":
                flip_h = QTransform().scale(-1, 1)
                pixmap = QPixmap(self.image)
                flipped = pixmap.transformed(flip_h)
            elif axis == "vertical":
                flip_v = QTransform().scale(1, -1)
                pixmap = QPixmap(self.image)
                flipped = pixmap.transformed(flip_v)

            #self.image_label.setPixmap(flipped)
            #self.image_label.setPixmap(flipped.scaled(self.image_label.size(),
            #    Qt.KeepAspectRatio, Qt.SmoothTransformation))
            self.image = QImage(flipped)
            self.setPixmap(flipped)
            #self.image = QPixmap(flipped)
            self.repaint()
        else:
            # No image to flip
            pass

    def convertToGray(self):
        """Convert image to grayscale."""
        if self.image.isNull() == False:
            converted_img = self.image.convertToFormat(
                QImage.Format_Grayscale16)
            #self.image = converted_img
            self.image = QImage(converted_img)
            self.setPixmap(QPixmap().fromImage(converted_img))
            self.repaint()

    def convertToRGB(self):
        """Convert image to RGB format."""
        if self.image.isNull() == False:
            converted_img = self.image.convertToFormat(QImage.Format_RGB32)
            #self.image = converted_img
            self.image = QImage(converted_img)
            self.setPixmap(QPixmap().fromImage(converted_img))
            self.repaint()

    def convertToSepia(self):
        """Convert image to sepia filter."""
        #TODO: Sepia #704214 rgb(112, 66, 20)
        #TODO: optimize speed that the image converts, or add to thread
        if self.image.isNull() == False:
            for row_pixel in range(self.image.width()):
                for col_pixel in range(self.image.height()):
                    current_val = QColor(self.image.pixel(
                        row_pixel, col_pixel))

                    # Calculate r, g, b values for current pixel
                    red = current_val.red()
                    green = current_val.green()
                    blue = current_val.blue()

                    new_red = int(0.393 * red + 0.769 * green + 0.189 * blue)
                    new_green = int(0.349 * red + 0.686 * green + 0.168 * blue)
                    new_blue = int(0.272 * red + 0.534 * green + 0.131 * blue)

                    # Set the new RGB values for the current pixel
                    if new_red > 255:
                        red = 255
                    else:
                        red = new_red

                    if new_green > 255:
                        green = 255
                    else:
                        green = new_green

                    if new_blue > 255:
                        blue = 255
                    else:
                        blue = new_blue

                    new_value = qRgb(red, green, blue)
                    self.image.setPixel(row_pixel, col_pixel, new_value)

        self.setPixmap(QPixmap().fromImage(self.image))
        self.repaint()

    def changeBrighteness(self, value):
        #TODO: Reset the value of brightness, remember the original values
        # as going back to 0, i.e. keep track of original image's values
        #TODO: modify values based on original image
        if (value < -255 | value > 255):
            return self.image

        for row_pixel in range(self.image.width()):
            for col_pixel in range(self.image.height()):
                current_val = QColor(self.image.pixel(row_pixel, col_pixel))
                red = current_val.red()
                green = current_val.green()
                blue = current_val.blue()

                new_red = red + value
                new_green = green + value
                new_blue = blue + value

                # Set the new RGB values for the current pixel
                if new_red > 255:
                    red = 255
                elif new_red < 0:
                    red = 0
                else:
                    red = new_red

                if new_green > 255:
                    green = 255
                elif new_green < 0:
                    green = 0
                else:
                    green = new_green

                if new_blue > 255:
                    blue = 255
                elif new_blue < 0:
                    blue = 0
                else:
                    blue = new_blue

                new_value = qRgb(red, green, blue)
                self.image.setPixel(row_pixel, col_pixel, new_value)

        self.setPixmap(QPixmap().fromImage(self.image))

    def changeContrast(self, contrast):
        """Change the contrast of the pixels in the image.
           Contrast is the difference between max and min pixel intensity."""
        for row_pixel in range(self.image.width()):
            for col_pixel in range(self.image.height()):
                # Calculate a contrast correction factor
                factor = float(259 * (contrast + 255) / (255 *
                                                         (259 - contrast)))

                current_val = QColor(self.image.pixel(row_pixel, col_pixel))
                red = current_val.red()
                green = current_val.green()
                blue = current_val.blue()

                new_red = factor * (red - 128) + 128
                new_green = factor * (green - 128) + 128
                new_blue = factor * (blue - 128) + 128

                new_value = qRgb(new_red, new_green, new_blue)
                self.image.setPixel(row_pixel, col_pixel, new_value)

        self.setPixmap(QPixmap().fromImage(self.image))

    def changeHue(self):
        for row_pixel in range(self.image.width()):
            for col_pixel in range(self.image.height()):
                current_val = QColor(self.image.pixel(row_pixel, col_pixel))

                hue = current_val.hue()

                current_val.setHsv(hue, current_val.saturation(),
                                   current_val.value(), current_val.alpha())
                self.image.setPixelColor(row_pixel, col_pixel, current_val)

        self.setPixmap(QPixmap().fromImage(self.image))

    def mousePressEvent(self, event):
        """Handle mouse press event."""
        self.origin = event.pos()
        if not (self.rubber_band):
            self.rubber_band = QRubberBand(QRubberBand.Rectangle, self)
        self.rubber_band.setGeometry(QRect(self.origin, QSize()))
        self.rubber_band.show()

        #print(self.rubber_band.height())
        print(self.rubber_band.x())

    def mouseMoveEvent(self, event):
        """Handle mouse move event."""
        self.rubber_band.setGeometry(
            QRect(self.origin, event.pos()).normalized())

    def mouseReleaseEvent(self, event):
        """Handle when the mouse is released."""
        self.rubber_band.hide()
예제 #22
0
    def __init__(self):
        super().__init__()

        self.initializeUI()

        self.image = QImage()