import
sys
from
PyQt5.QtWidgets
import
QApplication, QWidget, QLabel, QPushButton, QVBoxLayout, QHBoxLayout, QFileDialog, QMessageBox
from
PyQt5.QtGui
import
QPixmap, QPainter, QPen, QImage, QColor, QBrush
from
PyQt5.QtCore
import
Qt, QPoint, QRect
from
datetime
import
datetime
class
ImageSplitter(QWidget):
def
__init__(
self
):
super
().__init__()
self
.initUI()
self
.image
=
None
self
.image_rect
=
None
self
.drag_start
=
None
self
.scale
=
1.0
def
initUI(
self
):
self
.setWindowTitle(
'微信朋友圈九宫格图片分割工具by林林柒'
)
self
.setGeometry(
100
,
100
,
650
,
700
)
self
.image_frame
=
QLabel(
self
)
self
.image_frame.setFixedSize(
600
,
600
)
self
.image_frame.setAlignment(Qt.AlignCenter)
self
.image_frame.setStyleSheet(
"border: 1px solid black;"
)
self
.info_label
=
QLabel(
self
)
self
.info_label.setAlignment(Qt.AlignCenter)
self
.note_label
=
QLabel(
"备注:可以拖入图片或导入图片,可以拖动和鼠标滚轮缩放进行分割"
,
self
)
self
.note_label.setAlignment(Qt.AlignCenter)
import_button
=
QPushButton(
'导入图片'
,
self
)
import_button.clicked.connect(
self
.importImage)
split_button
=
QPushButton(
'分割图片'
,
self
)
split_button.clicked.connect(
self
.splitImage)
button_layout
=
QHBoxLayout()
button_layout.addWidget(import_button)
button_layout.addWidget(split_button)
layout
=
QVBoxLayout()
layout.addWidget(
self
.image_frame)
layout.addWidget(
self
.info_label)
layout.addWidget(
self
.note_label)
layout.addLayout(button_layout)
self
.setLayout(layout)
self
.setAcceptDrops(
True
)
def
importImage(
self
):
file_name, _
=
QFileDialog.getOpenFileName(
self
,
"选择图片"
, "
", "
图片文件 (
*
.png
*
.jpg
*
.bmp)")
if
file_name:
self
.loadImage(file_name)
def
loadImage(
self
, file_name):
self
.image
=
QImage(file_name)
if
self
.image.width() <
400
or
self
.image.height() <
400
:
self
.info_label.setText(
"图片大小不能小于400*400"
)
return
self
.scale
=
min
(
600
/
self
.image.width(),
600
/
self
.image.height())
self
.image_rect
=
QRect(
0
,
0
,
self
.image.width()
*
self
.scale,
self
.image.height()
*
self
.scale)
self
.updateImage()
self
.info_label.setText(f
"图片尺寸: {self.image.width()} x {self.image.height()}"
)
def
updateImage(
self
):
if
self
.image:
scaled_image
=
self
.image.scaled(
self
.image_rect.width(),
self
.image_rect.height(),
Qt.KeepAspectRatio, Qt.SmoothTransformation)
pixmap
=
QPixmap(
600
,
600
)
pixmap.fill(Qt.white)
painter
=
QPainter(pixmap)
painter.drawImage(
self
.image_rect, scaled_image)
self
.drawGrid(painter)
painter.end()
self
.image_frame.setPixmap(pixmap)
def
drawGrid(
self
, painter):
w, h
=
600
,
600
pen
=
QPen(Qt.blue,
4
, Qt.SolidLine)
painter.setPen(pen)
painter.setBrush(Qt.transparent)
painter.drawEllipse(
0
,
0
, w, h)
pen
=
QPen(Qt.red,
2
, Qt.SolidLine)
painter.setPen(pen)
painter.drawLine(w
/
3
,
0
, w
/
3
, h)
painter.drawLine(
2
*
w
/
3
,
0
,
2
*
w
/
3
, h)
painter.drawLine(
0
, h
/
3
, w, h
/
3
)
painter.drawLine(
0
,
2
*
h
/
3
, w,
2
*
h
/
3
)
mask
=
QImage(w, h, QImage.Format_ARGB32_Premultiplied)
mask.fill(Qt.transparent)
mask_painter
=
QPainter(mask)
mask_painter.setBrush(QColor(
255
,
255
,
255
,
128
))
mask_painter.setPen(Qt.NoPen)
mask_painter.drawRect(
0
,
0
, w, h)
mask_painter.setCompositionMode(QPainter.CompositionMode_DestinationOut)
mask_painter.setBrush(Qt.black)
mask_painter.drawEllipse(
0
,
0
, w, h)
mask_painter.end()
painter.drawImage(
0
,
0
, mask)
def
splitImage(
self
):
if
self
.image:
save_dir
=
QFileDialog.getExistingDirectory(
self
,
"选择保存位置"
, "")
if
save_dir:
frame_rect
=
self
.image_frame.rect()
visible_rect
=
self
.image_rect.intersected(frame_rect)
orig_x
=
max
(
0
,
int
((visible_rect.x()
-
self
.image_rect.x())
/
self
.scale))
orig_y
=
max
(
0
,
int
((visible_rect.y()
-
self
.image_rect.y())
/
self
.scale))
orig_w
=
min
(
self
.image.width()
-
orig_x,
int
(visible_rect.width()
/
self
.scale))
orig_h
=
min
(
self
.image.height()
-
orig_y,
int
(visible_rect.height()
/
self
.scale))
date_prefix
=
datetime.now().strftime(
"%Y%m%d%H%M%S"
)
mask
=
QImage(orig_w, orig_h, QImage.Format_ARGB32_Premultiplied)
mask.fill(Qt.transparent)
mask_painter
=
QPainter(mask)
mask_painter.setBrush(Qt.white)
mask_painter.setPen(Qt.NoPen)
mask_painter.drawEllipse(
0
,
0
, orig_w, orig_h)
mask_painter.end()
result
=
QImage(orig_w, orig_h, QImage.Format_RGB32)
result.fill(Qt.white)
result_painter
=
QPainter(result)
result_painter.setCompositionMode(QPainter.CompositionMode_SourceOver)
result_painter.drawImage(
0
,
0
,
self
.image.copy(orig_x, orig_y, orig_w, orig_h))
result_painter.setCompositionMode(QPainter.CompositionMode_DestinationIn)
result_painter.drawImage(
0
,
0
, mask)
result_painter.setCompositionMode(QPainter.CompositionMode_DestinationOver)
result_painter.fillRect(result.rect(), Qt.white)
result_painter.end()
for
j
in
range
(
3
):
for
i
in
range
(
3
):
x
=
int
(i
*
orig_w
/
3
)
y
=
int
(j
*
orig_h
/
3
)
w
=
int
(orig_w
/
3
)
h
=
int
(orig_h
/
3
)
cropped
=
result.copy(x, y, w, h)
file_path
=
f
'{save_dir}/{date_prefix}_{j*3+i+1:02d}.jpg'
cropped.save(file_path,
'JPEG'
,
100
)
QMessageBox.information(
self
,
"完成"
, f
"圆形图片已分割并保存到 {save_dir}"
)
else
:
print
(
"取消保存"
)
def
dragEnterEvent(
self
, event):
if
event.mimeData().hasUrls():
event.accept()
else
:
event.ignore()
def
dropEvent(
self
, event):
files
=
[u.toLocalFile()
for
u
in
event.mimeData().urls()]
if
files:
self
.loadImage(files[
0
])
def
mousePressEvent(
self
, event):
if
self
.image
and
self
.image_frame.geometry().contains(event.pos()):
self
.drag_start
=
event.pos()
def
mouseMoveEvent(
self
, event):
if
self
.drag_start
and
self
.image:
delta
=
event.pos()
-
self
.drag_start
self
.image_rect.translate(delta)
self
.drag_start
=
event.pos()
self
.updateImage()
def
mouseReleaseEvent(
self
, event):
self
.drag_start
=
None
def
wheelEvent(
self
, event):
if
self
.image:
delta
=
event.angleDelta().y()
if
delta >
0
:
self
.scale
*
=
1.1
else
:
self
.scale
/
=
1.1
self
.image_rect.setWidth(
int
(
self
.image.width()
*
self
.scale))
self
.image_rect.setHeight(
int
(
self
.image.height()
*
self
.scale))
self
.updateImage()
if
__name__
=
=
'__main__'
:
app
=
QApplication(sys.argv)
ex
=
ImageSplitter()
ex.show()
sys.exit(app.exec_())