import os from PyQt5 import QtGui, QtCore from PyQt5 import QtWidgets from PyQt5.QtWidgets import * from PyQt5.QtGui import * import cv2 import numpy as np import qdarkstyle from PIL import Image import glob from ViewerThread import ImageBuffer, ThumbnailThread from QtCanvas import SugarGraphicsView from ThumbnailLoader import ThumbnailLoader import shutil

class ScrollThumbnail(QScrollArea): def init(self, main_win, group_size=1): super(ScrollThumbnail, self).init() self.group_size = group_size self.thumbnail = ThumbnailLoader(self, main_win) self.setWidget(self.thumbnail) self.setFixedHeight(self.thumbnail.image_height + 20) self.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff) self.bar: QScrollBar = self.horizontalScrollBar() self.bar.valueChanged.connect(self.sync_func) self.main_win = main_win self.setFocusPolicy(QtCore.Qt.NoFocus)

def sync_func(self):
    pos = self.mapTo(self.main_win, self.thumbnail.get_item(0).pos())
    self.thumbnail.set_view_x(self.bar.value())

def set_group_size(self, group_size):
    self.group_size = group_size

def set_f_list(self, f_list):
    self.thumbnail.set_f_list(f_list)

from SideViewer import Sidebar class ImageThumbnail(QWidget): save_history = {} def init(self, parent, src_button, group_size=1): super(ImageThumbnail, self).init() self.win = SugarGraphicsView(None, parent) self.win.setFocusPolicy(QtCore.Qt.StrongFocus) self.sider = Sidebar(src_button) self.sider.setFixedWidth(320) self.scroll = ScrollThumbnail(parent, group_size) self.main_win = parent self.layout = QVBoxLayout()

    image_layout = QHBoxLayout()
    image_layout.addWidget(self.win)
    image_layout.addWidget(self.sider)
    self.layout.addLayout(image_layout)
    self.layout.addWidget(self.scroll)
    self.setLayout(self.layout)
    self.keyPressEvent = self.on_key_press_event

def on_key_press_event(self, event):
    key = event.text().upper()
    save_dir = self.sider.get_category_dir(key)
    if save_dir is None:
        print('No such category: ' + key)
    else:
        color = self.sider.get_color(key)
        for src_path in self.main_win.f_list[self.main_win.index:self.main_win.index+self.scroll.group_size]:
            filename = os.path.basename(src_path)
            filepath = os.path.join(save_dir, filename)
            if src_path not in self.save_history:
                print(src_path + 'Save to ' + filepath)
                self.sider.process(src_path, filepath)
                self.scroll.thumbnail.view[src_path].set_color(color)
                self.save_history[src_path] = filepath

            elif os.path.exists(self.save_history[src_path]):
                msg_box = QMessageBox()
                msg_box.setWindowTitle('Move File')
                msg_box.setText(f'该文件已经被放置在[{self.save_history[src_path]}],是否将它移至[{filepath}]?')
                msg_box.setStandardButtons(QMessageBox.Yes | QMessageBox.No | QMessageBox.Cancel)
                msg_box.setDefaultButton(QMessageBox.Cancel)
                result = msg_box.exec_()
                if result == QMessageBox.Yes:
                    print(self.save_history[src_path] + 'move to ' + filepath)
                    self.scroll.thumbnail.view[src_path].set_color(color)
                    shutil.move(self.save_history[src_path], filepath)
                    self.save_history[src_path] = filepath
                elif result == QMessageBox.No:
                    if os.path.exists(src_path):
                        print(src_path + 'Save to ' + filepath)
                        self.scroll.thumbnail.view[src_path].set_color(color)
                        self.sider.process(src_path, filepath)
                        self.save_history[src_path] = filepath
                    else:
                        print(src_path + '文件已经被移动,本次操作视为无效')
                else:
                    print('Operation canceled.')
        

def set_f_list(self, f_list):
    self.scroll.thumbnail.set_f_list(f_list)

def set_data(self, data):
    self.win.set_data(data)
    self.win.reset()

class Window(QMainWindow): def init(self, win_w=2300, win_h=1250): super(Window, self).init() app.setStyleSheet(qdarkstyle.load_stylesheet_pyqt5()) self.label_right = QLabel()

    self.src_folder_button = QPushButton('打开源文件夹')
    self.src_folder_button.clicked.connect(self.openCall)
    self.src_folder_edit = QLineEdit()

    self.image_view = ImageThumbnail(self, (self.src_folder_edit, self.src_folder_button))
    self.setWindowTitle('FilterViewer')
    self.verticalLayout = QtWidgets.QVBoxLayout()
    self.setCentralWidget(self.image_view)
    self.status_bar = self.statusBar()
    self.status_bar.showMessage('ready')
    self.f_list = None
    self.image_buffer_thread = None
    self.setGeometry(0, 0, win_w, win_h)
    self.index = 0
    self.num = -1

    self.setMouseTracking(True)

    openAction = QAction(QIcon('open.png'), '&打开', self)
    openAction.setStatusTip('Open document')
    openAction.triggered.connect(self.openCall)
    saveAction = QAction(QIcon('open.png'), '&Save', self)
    saveAction.setShortcut('Ctrl+O')
    saveAction.setStatusTip('Save document')
    saveAction.triggered.connect(self.saveCall)

    menuBar = self.menuBar()
    MenuFile = menuBar.addMenu('&文件夹')
    MenuFile.addAction(openAction)
    MenuFile.addAction(saveAction)

def keyPressEvent(self, a0: QtGui.QKeyEvent) -> None:
    self.image_view.on_key_press_event(a0)

def put_text(self, t=None):
    num_str = str(self.num) if self.num > 0 else '∞'
    file_num = '[%d / %s]' % (self.index, num_str)
    if t is None:
        if self.f_list is not None:
            t = '当前文件: ' + str(self.f_list[self.index])
        else:
            t = ''
    self.status_bar.showMessage(file_num + t)

def set_index(self, index):
    self.index = index
    self.set_data()

def __add__(self, other):
    self.index += other
    if self.f_list is not None:
        num = len(self.f_list) - 1
    else:
        num = 0
    self.index = min(num, self.index)
    self.index = max(0, self.index)
    self.set_data()
    return self

def set_scale_label(self, scale):
    self.label_right.setText('%d%%  ' % int(scale * 100))

def convertQImageToMat(self, incomingImage):
    incomingImage = incomingImage.convertToFormat(4)
    width = incomingImage.width()
    height = incomingImage.height()
    ptr = incomingImage.bits()
    ptr.setsize(incomingImage.byteCount())
    arr = np.array(ptr).reshape(height, width, 4)
    return cv2.cvtColor(arr, cv2.COLOR_BGR2GRAY)

def convertCv2ToQimage(self, im):
    im = cv2.cvtColor(im, cv2.COLOR_BGR2RGB)
    qim = QImage()
    if im is None:
        return qim
    if im.dtype == np.uint8:
        if len(im.shape) == 2:
            qim = QImage(im.data, im.shape[1], im.shape[0], im.strides[0], QImage.Format_Indexed8)
            qim.setColorTable([qRgb(i, i, i) for i in range(256)])
        elif len(im.shape) == 3:
            if im.shape[2] == 3:
                qim = QImage(im.data, im.shape[1], im.shape[0], im.strides[0], QImage.Format_RGB888)
            elif im.shape[2] == 4:
                qim = QImage(im.data, im.shape[1], im.shape[0], im.strides[0], QImage.Format_ARGB32)
    return qim

def saveCall(self):
    rgb = Image.fromarray(self.cv2Image, mode=None)
    path = QFileDialog.getSaveFileName(self, 'Save File')
    if path:
        print(path)
        rgb.save(path[0])

def openCall(self):
    dlg = QFileDialog()
    dir_path = dlg.getExistingDirectory()
    print('获得文件夹路径:', dir_path)
    if dir_path is None or len(dir_path) == 0:
        return
    f_list = glob.glob(os.path.join(dir_path, '*.*'))
    self.f_list = []
    for file in sorted(f_list):
        if '.' == os.path.basename(file)[0]:
            continue
        if file.lower().endswith(('.jpg', '.jpeg', '.png', '.bmp')):
            file_path = file
            self.f_list.append(file_path)

    self.num = len(self.f_list)
    print('文件夹中存在图片:', self.num)
    self.image_buffer_thread = ImageBuffer(self.f_list)
    print('主窗口图像开始载入')
    self.image_buffer_thread.start()
    print('发送文件列表给缩略图')
    self.image_view.set_f_list(self.f_list)
    self.set_data()

def set_data(self):
    if self.image_buffer_thread is None:
        return
    self.image = self.convertCv2ToQimage(self.image_buffer_thread[self.index])
    self.image_view.set_data(self.image)
    self.put_text()

if name == 'main': import sys app = QApplication(sys.argv) window = Window() window.show() sys.exit(app.exec_())

批量操作图像:自定义显示图像组数

原文地址: https://www.cveoy.top/t/topic/S5z 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录