Commit 492e8d9a authored by dmMaze's avatar dmMaze
Browse files

optimize canvas layers rendering

parent a441bfb7
Loading
Loading
Loading
Loading
+77 −55
Original line number Diff line number Diff line
@@ -4,7 +4,7 @@ import os

from qtpy.QtWidgets import QSlider, QMenu, QGraphicsScene, QGraphicsView, QGraphicsSceneDragDropEvent, QGraphicsRectItem, QGraphicsItem, QScrollBar, QGraphicsPixmapItem, QGraphicsSceneMouseEvent, QGraphicsSceneContextMenuEvent, QRubberBand
from qtpy.QtCore import Qt, QDateTime, QRectF, QPointF, QPoint, Signal, QSizeF, QEvent
from qtpy.QtGui import QKeySequence, QPixmap, QHideEvent, QKeyEvent, QWheelEvent, QResizeEvent, QPainter, QPen, QPainterPath, QCursor, QNativeGestureEvent
from qtpy.QtGui import QKeySequence, QPixmap, QImage, QHideEvent, QKeyEvent, QWheelEvent, QResizeEvent, QPainter, QPen, QPainterPath, QCursor, QNativeGestureEvent

try:
    from qtpy.QtWidgets import QUndoStack, QUndoCommand
@@ -19,6 +19,7 @@ from .stylewidgets import FadeLabel
from .image_edit import ImageEditMode, DrawingLayer, StrokeImgItem
from .page_search_widget import PageSearchWidget
from utils import shared as C
from utils.config import pcfg

CANVAS_SCALE_MAX = 3.0
CANVAS_SCALE_MIN = 0.1
@@ -252,26 +253,21 @@ class Canvas(QGraphicsScene):
        pen.setColor(Qt.GlobalColor.transparent)
        self.baseLayer.setPen(pen)

        self.imgLayer = QGraphicsPixmapItem()
        self.imgLayer.setTransformationMode(Qt.TransformationMode.SmoothTransformation)
        self.inpaintLayer = QGraphicsPixmapItem()
        self.inpaintLayer.setTransformationMode(Qt.TransformationMode.SmoothTransformation)
        self.maskLayer = QGraphicsPixmapItem()
        self.drawingLayer = DrawingLayer()
        self.drawingLayer.setTransformationMode(Qt.TransformationMode.FastTransformation)
        self.textLayer = QGraphicsPixmapItem()

        self.imgLayer.setAcceptDrops(True)
        self.inpaintLayer.setAcceptDrops(True)
        self.maskLayer.setAcceptDrops(True)
        self.drawingLayer.setAcceptDrops(True)
        self.textLayer.setAcceptDrops(True)
        self.baseLayer.setAcceptDrops(True)
        
        self.base_pixmap: QPixmap = None

        self.addItem(self.baseLayer)
        self.inpaintLayer.setParentItem(self.baseLayer)
        self.imgLayer.setParentItem(self.baseLayer)
        self.maskLayer.setParentItem(self.baseLayer)
        self.drawingLayer.setParentItem(self.baseLayer)
        self.textLayer.setParentItem(self.baseLayer)
        self.txtblkShapeControl.setParentItem(self.baseLayer)
@@ -301,6 +297,11 @@ class Canvas(QGraphicsScene):
        self.originallayer_trans_slider: QSlider = None
        self.masklayer_trans_slider: QSlider = None

    def img_window_size(self):
        if self.imgtrans_proj.inpainted_valid:
            return self.inpaintLayer.pixmap().size()
        return self.baseLayer.rect().size().toSize()

    def dragEnterEvent(self, e: QGraphicsSceneDragDropEvent):
        
        self.drop_folder = None
@@ -337,41 +338,62 @@ class Canvas(QGraphicsScene):
    def scaleBy(self, value: float):
        self.scaleImage(value)

    def setImageLayer(self):
    def render_result_img(self):

        self.clearSelection()
        if self.textEditMode() and self.txtblkShapeControl.blk_item is not None:
            if self.txtblkShapeControl.blk_item.is_editting():
                self.txtblkShapeControl.blk_item.endEdit()
        
        ipainted_layer_pixmap = ndarray2pixmap(self.imgtrans_proj.inpainted_array)
        old_ilayer_pixmap = self.inpaintLayer.pixmap()
        self.inpaintLayer.setPixmap(ipainted_layer_pixmap)

        result = QImage(self.img_window_size(), QImage.Format.Format_ARGB32)
        painter = QPainter(result)
        painter.setRenderHint(QPainter.RenderHint.Antialiasing)
        self.render(painter)
        painter.end()
        
        self.inpaintLayer.setPixmap(old_ilayer_pixmap)
        
        return result

    def updateLayers(self):
        
        if not self.imgtrans_proj.img_valid:
            return
        pixmap = ndarray2pixmap(self.imgtrans_proj.img_array)
        self.imgLayer.setPixmap(pixmap)
        
        im_rect = self.imgLayer.pixmap().rect()
        self.baseLayer.setRect(QRectF(im_rect))
        if im_rect != self.sceneRect():
            self.setSceneRect(0, 0, im_rect.width(), im_rect.height())
        self.scaleImage(1)
        self.imgLayer.setOpacity(self.original_transparency)
        inpainted_as_base = self.imgtrans_proj.inpainted_valid
        
    def setMaskLayer(self):
        if not self.imgtrans_proj.mask_valid:
            return
        pixmap = ndarray2pixmap(self.imgtrans_proj.mask_array)
        self.maskLayer.setPixmap(pixmap)
        self.maskLayer.setOpacity(self.mask_transparency)
        if inpainted_as_base:
            self.base_pixmap = ndarray2pixmap(self.imgtrans_proj.inpainted_array)

        pixmap = self.base_pixmap.copy()
        painter = QPainter(pixmap)
        origin = QPoint(0, 0)

        if self.imgtrans_proj.img_valid and self.original_transparency > 0:
            painter.setOpacity(self.original_transparency)
            if inpainted_as_base:
                painter.drawPixmap(origin, ndarray2pixmap(self.imgtrans_proj.img_array))
            else:
                painter.drawPixmap(origin, pixmap)

        if self.imgtrans_proj.mask_valid and self.mask_transparency > 0 and not self.textEditMode():
            painter.setOpacity(self.mask_transparency)
            painter.drawPixmap(origin, ndarray2pixmap(self.imgtrans_proj.mask_array))

        painter.end()
        self.inpaintLayer.setPixmap(pixmap)

    def setMaskTransparency(self, transparency: float):
        self.maskLayer.setOpacity(transparency)
        self.mask_transparency = transparency
        if transparency == 0:
            self.maskLayer.setVisible(False)
        else:
            self.maskLayer.setVisible(True)
        self.updateLayers()

    def setOriginalTransparency(self, transparency: float):
        self.imgLayer.setOpacity(transparency)
        self.original_transparency = transparency
        if transparency == 0:
            self.imgLayer.hide()
        else:
            self.imgLayer.show()
        self.updateLayers()

    def setTextLayerTransparency(self, transparency: float):
        self.textLayer.setOpacity(transparency)
@@ -386,7 +408,7 @@ class Canvas(QGraphicsScene):
        s_f = self.scale_factor * factor
        s_f = np.clip(s_f, CANVAS_SCALE_MIN, CANVAS_SCALE_MAX)

        sbr = self.imgLayer.sceneBoundingRect()
        sbr = self.baseLayer.sceneBoundingRect()
        self.old_size = sbr.size()
        scale_changed = self.scale_factor != s_f
        self.scale_factor = s_f
@@ -397,7 +419,7 @@ class Canvas(QGraphicsScene):
            self.adjustScrollBar(self.gv.horizontalScrollBar(), factor)
            self.adjustScrollBar(self.gv.verticalScrollBar(), factor)
            self.scalefactor_changed.emit()
        self.setSceneRect(0, 0, self.imgLayer.sceneBoundingRect().width(), self.imgLayer.sceneBoundingRect().height())
        self.setSceneRect(0, 0, self.baseLayer.sceneBoundingRect().width(), self.baseLayer.sceneBoundingRect().height())

    def onViewResized(self):
        gv_w, gv_h = self.gv.geometry().width(), self.gv.geometry().height()
@@ -462,7 +484,7 @@ class Canvas(QGraphicsScene):
        if self.stroke_img_item is not None:
            self.stroke_img_item.startNewPoint(pos)
        else:
            self.stroke_img_item = StrokeImgItem(pen, pos, self.imgLayer.pixmap().size(), shape=self.painting_shape)
            self.stroke_img_item = StrokeImgItem(pen, pos, self.img_window_size(), shape=self.painting_shape)
            if not erasing:
                self.stroke_img_item.setParentItem(self.baseLayer)
            else:
@@ -506,7 +528,7 @@ class Canvas(QGraphicsScene):
        
        elif self.stroke_img_item is not None:
            if self.stroke_img_item.is_painting:
                pos = self.imgLayer.mapFromScene(event.scenePos())
                pos = self.inpaintLayer.mapFromScene(event.scenePos())
                if self.erase_img_key is None:
                    # painting
                    self.stroke_img_item.lineTo(pos)
@@ -580,13 +602,13 @@ class Canvas(QGraphicsScene):
                    self.scale_tool_mode = True
                    self.begin_scale_tool.emit(event.scenePos())
                elif self.painting:
                    self.addStrokeImageItem(self.imgLayer.mapFromScene(event.scenePos()), self.painting_pen)
                    self.addStrokeImageItem(self.inpaintLayer.mapFromScene(event.scenePos()), self.painting_pen)

            elif btn == Qt.MouseButton.RightButton:
                # user is drawing using eraser
                if self.painting:
                    erasing = self.image_edit_mode == ImageEditMode.PenTool
                    self.addStrokeImageItem(self.imgLayer.mapFromScene(event.scenePos()), self.erasing_pen, erasing)
                    self.addStrokeImageItem(self.inpaintLayer.mapFromScene(event.scenePos()), self.erasing_pen, erasing)
                else:   # rubber band selection
                    self.rubber_band_origin = event.scenePos()
                    self.rubber_band.setGeometry(QRectF(self.rubber_band_origin, self.rubber_band_origin).normalized())
@@ -633,20 +655,22 @@ class Canvas(QGraphicsScene):

        self.clearSelection()
        self.setProjSaveState(False)
        self.setImageLayer()
        self.setInpaintLayer()
        self.setMaskLayer()
        self.setDrawingLayer()

    def setInpaintLayer(self):
        if not self.imgtrans_proj.inpainted_valid:
            return
        pixmap = ndarray2pixmap(self.imgtrans_proj.inpainted_array)
        self.inpaintLayer.setPixmap(pixmap)
        self.updateLayers()

        if self.base_pixmap is not None:
            pixmap = self.base_pixmap.copy()
            pixmap.fill(Qt.GlobalColor.transparent)
            self.textLayer.setPixmap(pixmap)

            im_rect = pixmap.rect()
            self.baseLayer.setRect(QRectF(im_rect))
            if im_rect != self.sceneRect():
                self.setSceneRect(0, 0, im_rect.width(), im_rect.height())
            self.scaleImage(1)

        self.setDrawingLayer()


    def setDrawingLayer(self, img: Union[QPixmap, np.ndarray] = None):
        
        self.drawingLayer.clearAllDrawings()
@@ -654,7 +678,7 @@ class Canvas(QGraphicsScene):
        if not self.imgtrans_proj.img_valid:
            return
        if img is None:
            drawing_map = self.imgLayer.pixmap().copy()
            drawing_map = self.inpaintLayer.pixmap().copy()
            drawing_map.fill(Qt.GlobalColor.transparent)
        elif not isinstance(img, QPixmap):
            drawing_map = ndarray2pixmap(img)
@@ -666,9 +690,7 @@ class Canvas(QGraphicsScene):
        if painting:
            self.editing_textblkitem = None
            self.textblock_mode = False
            self.maskLayer.setVisible(True)
        else:
            self.maskLayer.setVisible(False)
            # self.gv.setCursor(self.default_cursor)
            self.gv.setDragMode(QGraphicsView.DragMode.ScrollHandDrag)
            self.image_edit_mode = ImageEditMode.NONE
+4 −8
Original line number Diff line number Diff line
@@ -60,8 +60,7 @@ class InpaintUndoCommand(QUndoCommand):
        mask_view = mask_array[inpaint_rect[1]: inpaint_rect[3], inpaint_rect[0]: inpaint_rect[2]]
        img_view[:] = self.redo_img
        mask_view[:] = self.redo_mask
        self.canvas.setInpaintLayer()
        self.canvas.setMaskLayer()
        self.canvas.updateLayers()

    def undo(self) -> None:
        inpaint_rect = self.inpaint_rect
@@ -71,8 +70,7 @@ class InpaintUndoCommand(QUndoCommand):
        mask_view = mask_array[inpaint_rect[1]: inpaint_rect[3], inpaint_rect[0]: inpaint_rect[2]]
        img_view[:] = self.undo_img
        mask_view[:] = self.undo_mask
        self.canvas.setInpaintLayer()
        self.canvas.setMaskLayer()
        self.canvas.updateLayers()



@@ -135,8 +133,7 @@ class RunBlkTransCommand(QUndoCommand):
                mask_view = mask_array[inpaint_rect[1]: inpaint_rect[3], inpaint_rect[0]: inpaint_rect[2]]
                img_view[:] = redo_img
                mask_view[:] = redo_mask
            self.canvas.setInpaintLayer()
            self.canvas.setMaskLayer()
            self.canvas.updateLayers()

        if self.op_counter < 0:
            self.op_counter += 1
@@ -160,8 +157,7 @@ class RunBlkTransCommand(QUndoCommand):
                mask_view = mask_array[inpaint_rect[1]: inpaint_rect[3], inpaint_rect[0]: inpaint_rect[2]]
                img_view[:] = undo_img
                mask_view[:] = undo_mask
            self.canvas.setInpaintLayer()
            self.canvas.setMaskLayer()
            self.canvas.updateLayers()

        for blkitem, transpairw in zip(self.blkitems, self.transpairw_list):
            if self.mode != 0:
+2 −7
Original line number Diff line number Diff line
@@ -696,7 +696,6 @@ class MainWindow(FramelessWindow):
        if self.leftBar.imgTransChecker.isChecked()\
            and self.imgtrans_proj.directory is not None:
            
            # self.saveCurrentPage(update_scene_text=True, restore_interface=True)
            self.conditional_manual_save()

    def saveCurrentPage(self, update_scene_text=True, save_proj=True, restore_interface=False, save_rst_only=False):
@@ -714,6 +713,7 @@ class MainWindow(FramelessWindow):
        if trans_idx != 1:
            self.bottomBar.texteditChecker.click()

        
        restore_original_transparency = None
        if self.bottomBar.originalSlider.value() != 0:
            restore_original_transparency = self.bottomBar.originalSlider.value()
@@ -753,12 +753,7 @@ class MainWindow(FramelessWindow):
                    inpainted = self.imgtrans_proj.inpainted_array
                self.imsave_thread.saveImg(inpainted_path, inpainted)

        img = QImage(self.canvas.imgLayer.pixmap().size(), QImage.Format.Format_ARGB32)
        painter = QPainter(img)
        painter.setRenderHint(QPainter.RenderHint.Antialiasing)
        self.canvas.clearSelection()
        self.canvas.render(painter)
        painter.end()
        img = self.canvas.render_result_img()
        imsave_path = self.imgtrans_proj.get_result_path(self.imgtrans_proj.current_img)
        self.imsave_thread.saveImg(imsave_path, img, self.imgtrans_proj.current_img, save_params={'ext': pcfg.imgsave_ext, 'quality': pcfg.imgsave_quality})
            
+13 −17
Original line number Diff line number Diff line
@@ -154,8 +154,7 @@ class DeleteBlkItemsCommand(QUndoCommand):
                x1, y1, x2, y2 = inpaint_rect
                img_array[y1: y2, x1: x2][mskpnt] = redo_img[mskpnt]
                mask_array[y1: y2, x1: x2][mskpnt] = 0
            self.canvas.setInpaintLayer()
            self.canvas.setMaskLayer()
            self.canvas.updateLayers()

        if self.op_counter == 0:
            self.op_counter += 1
@@ -191,8 +190,7 @@ class DeleteBlkItemsCommand(QUndoCommand):
                x1, y1, x2, y2 = inpaint_rect
                img_array[y1: y2, x1: x2][mskpnt] = undo_img[mskpnt]
                mask_array[y1: y2, x1: x2][mskpnt] = 255
            self.canvas.setInpaintLayer()
            self.canvas.setMaskLayer()
            self.canvas.updateLayers()

        self.ctrl.recoverTextblkItemList(self.blk_list, self.pwidget_list)
        if self.sw_changed:
@@ -383,7 +381,9 @@ class SceneTextManager(QObject):
            blk_item = TextBlkItem(blk, len(self.textblk_item_list), show_rect=self.canvas.textblock_mode)
            if translation:
                blk.translation = translation
                self.layout_textblk(blk_item, text=translation)
                rst = self.layout_textblk(blk_item, text=translation)
                if rst is None:
                    blk_item.setPlainText(translation)
        self.addTextBlkItem(blk_item)

        pair_widget = TransPairWidget(blk, len(self.pairwidget_list), pcfg.fold_textarea)
@@ -644,8 +644,7 @@ class SceneTextManager(QObject):
        tgt_is_cjk = is_cjk(pcfg.module.translate_target)

        # disable for vertical writing
        if (src_is_cjk and tgt_is_cjk and blkitem.blk.src_is_vertical) or \
            (pcfg.let_writing_mode_flag == 1 and self.formatpanel.global_format.vertical):
        if blkitem.blk.vertical:
            return

        blk_font = blkitem.font()
@@ -688,7 +687,7 @@ class SceneTextManager(QObject):
 
        adaptive_fntsize = False
        if self.auto_textlayout_flag and pcfg.let_fntsize_flag == 0 and pcfg.let_autolayout_flag and pcfg.let_autolayout_adaptive_fntsz:
            if not tgt_is_cjk:
            if blkitem.blk.src_is_vertical and blkitem.blk.vertical != blkitem.blk.src_is_vertical:
                adaptive_fntsize = True
            
        resize_ratio = 1
@@ -702,12 +701,8 @@ class SceneTextManager(QObject):
            # resize_ratio = np.clip(min(area_ratio / ballon_area_thresh, region_rect [2] / max(wl_list), blkitem.blk.font_size / line_height), downscale_constraint, 1.0) 
            resize_ratio = np.clip(min(area_ratio / ballon_area_thresh, region_rect [2] / max(wl_list)), downscale_constraint, 1.0)

        if text.startswith('SAKUY'):
            cv2.imwrite('sakuy.png', mask)
            pass

        max_central_width = np.inf
        if tgt_is_cjk:
        if tgt_is_cjk and not src_is_cjk:
            if ballon_area / text_area > 2:
                if blkitem.blk.text:
                    _, _, brw, brh = blkitem.blk.bounding_rect()
@@ -737,7 +732,7 @@ class SceneTextManager(QObject):
        if max_central_width != np.inf:
            max_central_width = max(int(max_central_width * text_w), 0.75 * region_rect[2])

        padding = pt2px(blk_font.pointSizeF()) + 10   # dummpy padding variable
        padding = pt2px(blk_font.pointSizeF()) + 20   # dummpy padding variable
        if fmt.alignment == 1:
            if len(blkitem.blk) > 0:
                centroid = blkitem.blk.center().astype(np.int64).tolist()
@@ -765,9 +760,9 @@ class SceneTextManager(QObject):
            post_resize_ratio = np.clip(max(region_rect[2] / w, downscale_constraint), 0, 1)
            resize_ratio *= post_resize_ratio

        if tgt_is_cjk:
            resize_ratio = 1
            post_resize_ratio = 1 / resize_ratio
        # if tgt_is_cjk:
        #     resize_ratio = 1
        #     post_resize_ratio = 1 / resize_ratio

        if post_resize_ratio != 1:
            cx, cy = xywh[0] + xywh[2] / 2, xywh[1] + xywh[3] / 2
@@ -803,6 +798,7 @@ class SceneTextManager(QObject):
        if restore_charfmts:
            self.restore_charfmts(blkitem, text, new_text, char_fmts)
        blkitem.shrinkSize()
        return True
    
    def restore_charfmts(self, blkitem: TextBlkItem, text: str, new_text: str, char_fmts: List[QTextCharFormat]):
        cursor = blkitem.textCursor()
+0 −1
Original line number Diff line number Diff line
@@ -723,7 +723,6 @@ class TextBlkItem(QGraphicsTextItem):
        self.blk.vertical = fmt.vertical
        self.blk.set_font_colors(fmt.frgb, fmt.srgb, accumulate=False)


    def set_cursor_cfmt(self, cursor: QTextCursor, cfmt, merge_char: bool = False):
        if merge_char:
            cursor.mergeCharFormat(cfmt)
Loading