| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332 |
- import json
- import os.path
- from import_qt_mode import *
- from UI.manual_image_matching.image_items import Ui_Form as Ui_Image_Items
- from PIL import Image
- import rawpy, io
- class ImageLabel(QLabel, Ui_Image_Items):
- drop_sign = Signal(dict) # 粘贴的位置
- drop_from_sign = Signal(dict) # 粘贴来源的位置
- select_clearn_all_sign = Signal()
- selected_sign = Signal() # 有选中
- delete_image_sign = Signal(list) # 删除通知
- def __init__(self, text, image_index, image_path, image_name, root_path, is_goods_list, parent=None, windows=None,
- top_windows=None):
- super().__init__(parent)
- self.setupUi(self)
- # self.setFixedSize(150, 160)
- # self.ui_image.setFixedSize(150, 150)
- self.windows = windows
- self.top_windows = top_windows
- self.parent = parent
- self.text = image_name
- self.image_index = image_index
- self.image_path = image_path
- self.image_name = image_name
- self.root_path = root_path
- self.ui_text.setText(self.text)
- # 是图片列表还是普通列表
- self.is_goods_list = is_goods_list
- self.icon = None
- self.set_label_image()
- self.setMouseTracking(True)
- self.drag_start_position = None
- self.selected = False
- self.setAcceptDrops(True)
- def set_image_label_windows(self,windows):
- self.windows = windows
- def show_text(self):
- self.ui_text.setText(self.text)
- def crop_to_square(self, img):
- # 打开图片
- width, height = img.size # 获取原始图片的宽度和高度
- if width == height:
- return img
- if width > height:
- _x = int((width - height) / 2)
- img = img.crop((_x, 0, width - _x, height))
- else:
- _y = int((height - width) / 2)
- img = img.crop((0, _y, width, height - _y))
- return img
- def set_new_parent(self, parent):
- self.parent = parent
- self.setParent(parent)
- def show_big_image(self):
- if self.top_windows is not None:
- if self.icon:
- self.top_windows.show_big_image(self.icon)
- def set_label_image2(self):
- try:
- w, h = self.ui_image.width() * 2, self.ui_image.height() * 2
- if "CR2" == self.image_path[-3:]:
- _img_raw = Image.open(self.image_path)
- else:
- if "jpg" == self.image_path[-3:] or "png" == self.image_path[-3:]:
- _img_raw = Image.open(self.image_path)
- else:
- with rawpy.imread(self.image_path) as raw:
- raw_image = raw.postprocess()
- _img_raw = Image.fromarray(raw_image)
- size = (w, int(_img_raw.height * w / _img_raw.width))
- _img_raw = _img_raw.resize(size)
- _img_raw = _img_raw.convert("RGB")
- bytes_io = io.BytesIO()
- _img_raw.save(bytes_io, "JPEG")
- icon = QPixmap()
- icon.loadFromData(bytes_io.getvalue())
- self.icon = icon
- icon = icon.scaled(
- self.ui_image.size(), Qt.KeepAspectRatio, Qt.SmoothTransformation
- )
- self.ui_image.setPixmap(icon)
- except:
- pass
- def set_label_image(self):
- try:
- w, h = self.ui_image.width() * 2, self.ui_image.height() * 2
- if "CR2" == self.image_path[-3:]:
- _img_raw = Image.open(self.image_path)
- else:
- if "jpg" == self.image_path[-3:] or "png" == self.image_path[-3:]:
- _img_raw = Image.open(self.image_path)
- else:
- with rawpy.imread(self.image_path) as raw:
- raw_image = raw.postprocess()
- _img_raw = Image.fromarray(raw_image)
- # 取缩略图
- _img_raw.thumbnail((w, int(_img_raw.height * w / _img_raw.width)))
- size = (w, int(_img_raw.height * w / _img_raw.width))
- _img_raw = _img_raw.resize(size)
- _img_raw = _img_raw.convert("RGB")
- bytes_io = io.BytesIO()
- _img_raw.save(bytes_io, "JPEG")
- icon = QPixmap()
- icon.loadFromData(bytes_io.getvalue())
- self.icon = icon
- icon = icon.scaled(
- self.ui_image.size(), Qt.KeepAspectRatio, Qt.SmoothTransformation
- )
- self.ui_image.setPixmap(icon)
- except:
- pass
- def get_image_orientation(self, img):
- # 获取EXIF数据
- exif = img._getexif()
- if exif is not None:
- # EXIF标签274对应的是Orientation
- orientation = exif.get(0x0112)
- if orientation == 2:
- # 水平翻转
- img = img.transpose(Image.FLIP_LEFT_RIGHT)
- elif orientation == 3:
- # 旋转180度
- img = img.rotate(180, expand=True)
- elif orientation == 4:
- # 垂直翻转
- img = img.transpose(Image.FLIP_TOP_BOTTOM)
- elif orientation == 5:
- # 水平翻转后顺时针旋转90度
- img = img.transpose(Image.FLIP_LEFT_RIGHT).transpose(Image.ROTATE_270)
- elif orientation == 6:
- # 顺时针旋转90度
- img = img.transpose(Image.ROTATE_270)
- elif orientation == 7:
- # 水平翻转后逆时针旋转90度
- img = img.transpose(Image.FLIP_LEFT_RIGHT).transpose(Image.ROTATE_90)
- elif orientation == 8:
- # 逆时针旋转90度
- img = img.transpose(Image.ROTATE_90)
- else:
- pass
- return img
- def set_selected(self, selected):
- self.selected = selected
- self.setStyleSheet("background-color: yellow;" if selected else "background-color: white;")
- def mouseMoveEvent(self, event):
- if not (event.buttons() & Qt.LeftButton) or self.drag_start_position is None:
- return
- if (event.pos() - self.drag_start_position).manhattanLength() < QApplication.startDragDistance():
- return
- print("Starting drag...{}".format(self.image_name)) # 调试信息
- # 创建拖拽任务
- drag = QDrag(self)
- mime_data = QMimeData()
- # 收集所有选中的控件的数据
- data = QByteArray()
- stream = QDataStream(data, QIODevice.WriteOnly)
- # 写入图片索引
- for widget in self.parent.findChildren(ImageLabel):
- if widget.selected:
- if widget != self:
- stream.writeInt32(widget.image_index)
- # 设置当前为选中
- self.set_selected(True)
- stream.writeInt32(self.image_index)
- mime_data.setData('application/x-draggable-labels', data)
- drag.setMimeData(mime_data)
- # 可选:设置一个图标或快照来表示正在拖拽的对象
- pixmap = QPixmap(self.size())
- self.render(pixmap)
- drag.setPixmap(pixmap)
- # 设置热点为鼠标点击位置相对窗口的位置
- hot_spot = event.position().toPoint()
- drag.setHotSpot(hot_spot)
- # 开始拖拽操作
- result = drag.exec(Qt.MoveAction)
- if result == Qt.MoveAction:
- self.setParent(None) # 如果成功移动,则从原位置移除
- self.hide()
- self.drag_start_position = None
- print("end drag...{}".format(self.image_name)) # 调试信息
- def mouseReleaseEvent(self, event):
- super().mouseReleaseEvent(event)
- # print("Mouse released.") # 调试信息
- self.drag_start_position = None
- # 清除所有已选
- def clear_all(self):
- self.select_clearn_all_sign.emit()
- def mousePressEvent(self, event):
- if event.button() == Qt.LeftButton:
- self.show_big_image()
- self.drag_start_position = event.pos()
- self.selected_sign.emit() # 发送单击事件给父窗口
- if event.modifiers() & Qt.ControlModifier:
- # 如果按下了 Ctrl 键,则进行复选
- self.set_selected(not self.selected)
- else:
- self.clear_all()
- self.set_selected(not self.selected)
- def dragEnterEvent(self, event):
- event.acceptProposedAction()
- def dragMoveEvent(self, event):
- event.acceptProposedAction()
- # 粘贴来源的位置,发送信号
- def drop_from_event(self, return_data):
- self.drop_from_sign.emit(return_data)
- def dropEvent(self, event):
- mime = event.mimeData()
- if mime.hasFormat('application/x-draggable-labels'):
- return_data = {"is_same_folder": True,
- "from_image_index_list": [],
- "from_source": "",
- "to_image_index": 0,
- "to_source": "",
- }
- byte_array = mime.data('application/x-draggable-labels')
- stream = QDataStream(byte_array, QIODevice.ReadOnly)
- while not stream.atEnd():
- image_index = stream.readInt32()
- return_data["from_image_index_list"].append(image_index)
- from_source = event.source()
- return_data["from_source"] = from_source.windows
- return_data["to_source"] = self.windows
- return_data["to_image_index"] = self.image_index
- if from_source.windows == self.windows:
- return_data["is_same_folder"] = True
- print("同文件夹")
- else:
- return_data["is_same_folder"] = False
- print("不同文件夹")
- if return_data["is_same_folder"] is False:
- # 不同文件夹处理,处理发送到来源文件夹的操作
- from_source.drop_from_event(return_data)
- else:
- # 同文件夹处理,发送粘贴的信号
- self.drop_sign.emit(return_data)
- def contextMenuEvent(self, event):
- # 创建一个QMenu对象
- menu = QMenu(self)
- # 添加菜单项
- delete_action = menu.addAction("删除图片")
- # 连接菜单项到槽函数
- action = menu.exec(self.mapToGlobal(event.pos()))
- if action == delete_action:
- self.delete_selected_item()
- def delete_selected_item(self):
- # 获取当前选中的项并删除它
- print("delete_selected_item")
- image_index_list = [self.image_index]
- # 写入图片索引
- for widget in self.parent.findChildren(ImageLabel):
- if widget.selected:
- if widget != self:
- image_index_list.append(widget.image_index)
- if image_index_list:
- self.delete_image_sign.emit(image_index_list)
- def del_image(self):
- """
- 删除图片
- """
- parentPath, _ = os.path.split(self.root_path)
- cutImagePath = "{}/原始图_已抠图/{}.png".format(parentPath, self.image_name)
- f = False
- try:
- if os.path.exists(self.image_path):
- os.remove(self.image_path)
- f = True
- if os.path.exists(cutImagePath):
- os.remove(cutImagePath)
- f = True
- except FileNotFoundError:
- print(f"删除文件失败.")
- except Exception as e:
- print(f"发生错误: {e}")
- if f:
- self.hide()
- del self
|