Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
C
cut_pic
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
dovahkiin
cut_pic
Commits
2cf75cd4
Commit
2cf75cd4
authored
Oct 27, 2023
by
dovahkiin
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
添加指定区域切割功能
parent
e0eaaf86
Changes
5
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
497 additions
and
77 deletions
+497
-77
EvenSpinBox.py
EvenSpinBox.py
+51
-0
comm_class.py
comm_class.py
+23
-6
cti_pic_ui.ui
cti_pic_ui.ui
+245
-60
cut_pic.py
cut_pic.py
+103
-8
ui_main.py
ui_main.py
+75
-3
No files found.
EvenSpinBox.py
0 → 100644
View file @
2cf75cd4
from
PyQt5.QtWidgets
import
QApplication
,
QWidget
,
QVBoxLayout
,
QSpinBox
from
PyQt5.QtGui
import
QValidator
from
PyQt5.QtCore
import
Qt
class
EvenSpinBox
(
QSpinBox
):
def
__init__
(
self
,
parent
=
None
):
super
()
.
__init__
(
parent
)
self
.
setMaximum
(
65534
)
self
.
setMinimum
(
2
)
self
.
setSingleStep
(
2
)
# 设置步长为2
def
validate
(
self
,
text
,
pos
):
try
:
if
len
(
self
.
suffix
()):
value
=
int
(
text
[
len
(
self
.
prefix
()):
-
len
(
self
.
suffix
())])
else
:
value
=
int
(
text
[
len
(
self
.
prefix
()):])
if
value
%
2
==
0
:
return
QValidator
.
Acceptable
,
text
,
pos
else
:
return
QValidator
.
Intermediate
,
text
,
pos
except
ValueError
:
return
QValidator
.
Invalid
,
text
,
pos
def
fixup
(
self
,
text
):
try
:
if
len
(
self
.
suffix
()):
value
=
int
(
text
[
len
(
self
.
prefix
()):
-
len
(
self
.
suffix
())])
else
:
value
=
int
(
text
[
len
(
self
.
prefix
()):])
# 如果值是奇数,增加1使其成为偶数
if
value
%
2
!=
0
:
self
.
setValue
(
value
+
1
)
except
ValueError
:
pass
class
_Demo
(
QWidget
):
def
__init__
(
self
):
super
()
.
__init__
()
self
.
spinBox
=
EvenSpinBox
()
layout
=
QVBoxLayout
()
layout
.
addWidget
(
self
.
spinBox
)
self
.
setLayout
(
layout
)
if
__name__
==
'__main__'
:
app
=
QApplication
([])
demo
=
_Demo
()
demo
.
show
()
app
.
exec_
()
comm_class.py
View file @
2cf75cd4
...
...
@@ -3,14 +3,31 @@ from typing import Dict, List, Tuple
from
psd_tools.api.layers
import
PixelLayer
,
TypeLayer
class
rect
:
def
__init__
(
self
)
->
None
:
self
.
x
=
0
self
.
y
=
0
self
.
w
=
1
self
.
h
=
1
def
set_value
(
self
,
x_
,
y_
,
w_
,
h_
)
->
None
:
self
.
x
=
x_
self
.
y
=
y_
self
.
w
=
w_
self
.
h
=
h_
def
__str__
(
self
)
->
str
:
return
"rect(({self.x},{self.y}),({self.w},{self.h}))"
# 标志位类
class
flag_data
:
psd_name
=
''
english
=
False
cobit
=
False
show
=
False
equal_size
=
True
Auto_cut_1
=
False
psd_name
=
''
# psd名字
english
=
False
# 是否需要英文
cobit
=
False
# 是否需要共位
show
=
False
# 是否显示
equal_size
=
True
# 是否等大
Auto_cut_1
=
False
# 智能切图
self_set_cut
=
False
# 自定义切图
range_group
:
List
[
rect
]
=
[]
# 自定义切图数组
def
__str__
(
self
)
->
str
:
return
"psd名:{}, english:{}, cobit:{}, show:{}, equal_size:{}"
.
format
(
self
.
psd_name
,
self
.
english
,
self
.
cobit
,
self
.
show
,
self
.
equal_size
)
...
...
cti_pic_ui.ui
View file @
2cf75cd4
This diff is collapsed.
Click to expand it.
cut_pic.py
View file @
2cf75cd4
...
...
@@ -6,17 +6,17 @@ import urllib.request
from
random
import
uniform
from
time
import
sleep
import
numpy
as
np
import
openpyxl
import
psd_tools
from
PIL
import
ImageChops
,
Image
from
psd_tools
import
PSDImage
from
PyQt5.QtWidgets
import
QMessageBox
,
QListWidgetItem
from
PyQt5.QtGui
import
QColor
,
QBrush
from
PyQt5.QtGui
import
QBrush
,
QColor
from
PyQt5.QtWidgets
import
QListWidgetItem
,
QMessageBox
from
skimage.metrics
import
structural_similarity
as
ssim
from
comm_class
import
flag_data
,
lay_item
auto_cut_info
=
{}
class
exc
(
object
):
...
...
@@ -304,6 +304,69 @@ def extractLayerImge(lay_info:lay_item, psd_name:str, lwdtI:QListWidgetItem):
return
x1
,
y1
,
layer_name
,
temp_layer_name
,
lay_info
.
layer
.
name
def
find_common_area
(
rect1
,
rect2
):
x1
,
y1
,
w1
,
h1
=
rect1
x2
,
y2
,
w2
,
h2
=
rect2
# 计算矩形的右上角坐标
r1
=
x1
+
w1
t1
=
y1
+
h1
r2
=
x2
+
w2
t2
=
y2
+
h2
# 判断矩形是否重叠
if
x1
<
r2
and
r1
>
x2
and
y1
<
t2
and
t1
>
y2
:
# 计算公共矩形的坐标和大小
x
=
max
(
x1
,
x2
)
y
=
max
(
y1
,
y2
)
w
=
min
(
r1
,
r2
)
-
x
h
=
min
(
t1
,
t2
)
-
y
return
(
x
,
y
,
w
,
h
)
else
:
# 没有重叠的公共面积
return
None
# for x_ in range(x, w+1):
# for y_ in range(y, h+1):
# # pixel = psd_layer.as_PIL().getpixel((x_, y_))
# pixel = psd_layer.getpixel((x_, y_))
# if pixel[3] != 0:
# return True
# return False
def
have_pixel
(
psd_layer
,
x
,
y
,
w
,
h
,
l_x
,
l_y
,
l_w
,
l_h
):
# 指定你关心的范围 (left, top, right, bottom)
bounds
=
find_common_area
((
x
,
y
,
w
,
h
),
(
l_x
,
l_y
,
l_w
,
l_h
))
# 返回xywh坐标格式
if
bounds
==
None
:
return
False
# xywh转成ltrb坐标格式
bounds
=
(
bounds
[
0
]
-
l_x
,
bounds
[
1
]
-
l_y
,
bounds
[
0
]
+
bounds
[
2
]
-
l_x
,
bounds
[
1
]
+
bounds
[
3
]
-
l_y
)
# 从图层中提取像素数据并转换为RGBA模式
image
=
psd_layer
.
topil
()
.
convert
(
"RGBA"
)
# image.show()
cropped_image
=
image
.
crop
(
bounds
)
a_
=
0
# cropped_image.show()
# 遍历所有像素
for
x_
in
range
(
bounds
[
2
]
-
bounds
[
0
]):
for
y_
in
range
(
bounds
[
3
]
-
bounds
[
1
]):
r
,
g
,
b
,
a
=
cropped_image
.
getpixel
((
x_
,
y_
))
# 检查每个像素的alpha值,如果alpha值大于0, 则至少有一个不透明像素
if
a
>
0
:
# return True
a_
+=
a
return
a_
# # 创建一个与裁剪区域相同大小的完全透明的图片
# empty_image = Image.new('RGBA', (w, h), (0, 0, 0, 0))
# # 使用ImageChops的difference方法比较两张图片
# diff = ImageChops.difference(cropped_image, empty_image)
# # 获取像素值的和,如果和为0,说明两张图片完全相同,裁剪区域完全透明
# pixel_sum = sum(diff.getdata(), (0, 0, 0, 0))
# # 如果四个通道的像素和都为0,说明该区域完全透明,否则有像素点
# return any(value != 0 for value in pixel_sum)
def
get_lay_info
(
psd_info
:
flag_data
):
psd
=
PSDImage
.
open
(
psd_info
.
psd_name
)
max_w
=
max_h
=
0
...
...
@@ -360,6 +423,7 @@ def get_lay_info(psd_info:flag_data):
layer_info_list
:
list
[
lay_item
]
=
[]
for
layer
in
layer_list
:
is_join_flag
=
True
layer_info_item
=
lay_item
()
if
psd_info
.
Auto_cut_1
:
max_w
=
max_h
=
0
...
...
@@ -376,6 +440,22 @@ def get_lay_info(psd_info:flag_data):
break
if
break_flag
:
break
elif
psd_info
.
self_set_cut
:
max_w
=
max_h
=
0
max_x
=
max_y
=
-
1
print
(
psd_info
.
range_group
)
is_join_flag
=
False
for
rect_item
in
psd_info
.
range_group
:
if
have_pixel
(
layer
,
rect_item
.
x
,
rect_item
.
y
,
rect_item
.
w
,
rect_item
.
h
,
layer
.
left
,
layer
.
top
,
layer
.
width
,
layer
.
height
):
# 判断图像中是否存在像素点
layer_info_item
.
x
=
rect_item
.
x
layer_info_item
.
y
=
rect_item
.
y
layer_info_item
.
w
=
rect_item
.
w
layer_info_item
.
h
=
rect_item
.
h
is_join_flag
=
True
break
# 坐标内没有
else
:
if
psd_info
.
cobit
:
layer_info_item
.
x
=
max_x
...
...
@@ -393,10 +473,25 @@ def get_lay_info(psd_info:flag_data):
layer_info_item
.
x
=
layer
.
left
layer_info_item
.
y
=
layer
.
top
layer_info_item
.
layer_name
=
layer
.
name
layer_info_item
.
layer
=
layer
print
(
layer_info_item
)
layer_info_list
.
append
(
layer_info_item
)
if
is_join_flag
:
layer_info_item
.
layer_name
=
layer
.
name
layer_info_item
.
layer
=
layer
print
(
layer_info_item
)
layer_info_list
.
append
(
layer_info_item
)
return
layer_info_list
if
__name__
==
'__main__'
:
psd_data
:
flag_data
=
flag_data
()
psd_data
.
psd_name
=
"NB35_W_0.psd"
psd_data
.
equal_size
=
False
from
comm_class
import
rect
psd_data
.
range_group
=
[
rect
()]
psd_data
.
range_group
[
0
]
.
y
=
10
psd_data
.
range_group
[
0
]
.
w
=
12
psd_data
.
range_group
[
0
]
.
h
=
10
psd_data
.
self_set_cut
=
1
get_lay_info
(
psd_data
)
ui_main.py
View file @
2cf75cd4
...
...
@@ -17,9 +17,11 @@ from PyQt5.QtWidgets import (QApplication, QListWidgetItem, QMessageBox,
QStatusBar
,
QStyleFactory
,
QFileDialog
,
QApplication
)
from
comm_class
import
flag_data
,
lay_item
from
comm_class
import
flag_data
,
lay_item
,
rect
from
cut_pic
import
extractLayerImge
,
get_lay_info
from
outputUI
import
Ui_MainWindow
as
Ui_Form
import
EvenSpinBox
EvenSpinBox
=
EvenSpinBox
.
EvenSpinBox
fozu
=
r"""
##################################################################
...
...
@@ -69,6 +71,7 @@ class Pyqt5_Cut_psd(QtWidgets.QMainWindow, Ui_Form):
# self.MainWindow.setWindowIcon(icon)
# self.statusbar.showMessage("初始化中")
self
.
lay_lwdtI
=
{}
self
.
cut_range_group_list
:
list
[
rect
]
=
[
rect
()]
self
.
cut_pic_t
=
Thread
(
target
=
self
.
cut_pic_thread
)
# ui初始化状态
self
.
__init
()
...
...
@@ -78,6 +81,16 @@ class Pyqt5_Cut_psd(QtWidgets.QMainWindow, Ui_Form):
def
__init
(
self
):
self
.
stackedWidget
.
setCurrentIndex
(
0
)
self
.
let_psd_name
.
clear
()
# 设置选择框界面的界面值
self
.
stk_set_cut_type
.
setCurrentIndex
(
0
)
# # 设置输入框w,h仅能输入偶数
# esb_w = EvenSpinBox(self)
# # 获取布局
# layout = self.win_range_cut_w.layout()
# self.sbx_w.deleteLater()
# layout.replaceWidget(self.sbx_w,esb_w)
# self.sbx_w = esb_w
def
__add_item
(
self
,
layer_data
:
lay_item
):
temp_item
=
QListWidgetItem
()
...
...
@@ -85,6 +98,44 @@ class Pyqt5_Cut_psd(QtWidgets.QMainWindow, Ui_Form):
temp_item
.
setText
(
str
(
layer_data
))
self
.
lwg_confirmed
.
addItem
(
temp_item
)
def
__set_range_cut_xywh
(
self
,
x
,
y
,
w
,
h
):
self
.
sbx_x
.
setValue
(
x
)
self
.
sbx_x
.
setValue
(
y
)
self
.
sbx_w
.
setValue
(
w
)
self
.
sbx_h
.
setValue
(
h
)
# 点击按钮后添加一个选择框的范围
def
__add_range_cut_item
(
self
):
self
.
cbb_range_group
.
addItem
(
"范围
%
d"
%
((
self
.
cbb_range_group
.
count
()
+
1
)))
self
.
cut_range_group_list
.
append
(
rect
())
def
__del_range_cut_item
(
self
):
if
(
self
.
cbb_range_group
.
count
()
>
1
):
del
self
.
cut_range_group_list
[
self
.
cbb_range_group
.
currentIndex
()]
self
.
cbb_range_group
.
removeItem
(
self
.
cbb_range_group
.
count
()
-
1
)
self
.
__switchOut_range_cut_item
(
self
.
cbb_range_group
.
currentIndex
())
def
__switchOut_range_cut_item
(
self
,
index
):
self
.
sbx_x
.
setValue
(
self
.
cut_range_group_list
[
self
.
cbb_range_group
.
currentIndex
()]
.
x
)
self
.
sbx_y
.
setValue
(
self
.
cut_range_group_list
[
self
.
cbb_range_group
.
currentIndex
()]
.
y
)
self
.
sbx_w
.
setValue
(
self
.
cut_range_group_list
[
self
.
cbb_range_group
.
currentIndex
()]
.
w
)
self
.
sbx_h
.
setValue
(
self
.
cut_range_group_list
[
self
.
cbb_range_group
.
currentIndex
()]
.
h
)
def
__set_range_group_x
(
self
,
value
):
self
.
cut_range_group_list
[
self
.
cbb_range_group
.
currentIndex
()]
.
x
=
value
def
__set_range_group_y
(
self
,
value
):
self
.
cut_range_group_list
[
self
.
cbb_range_group
.
currentIndex
()]
.
y
=
value
def
__set_range_group_w
(
self
,
value
):
self
.
cut_range_group_list
[
self
.
cbb_range_group
.
currentIndex
()]
.
w
=
value
def
__set_range_group_h
(
self
,
value
):
self
.
cut_range_group_list
[
self
.
cbb_range_group
.
currentIndex
()]
.
h
=
value
# 读取文件地址
def
__read_file_path
(
self
):
file_path
,
_
=
QFileDialog
.
getOpenFileNames
(
self
,
"选择PSD文件"
,
os
.
getcwd
(),
'PSD文件(*.psd)'
)
...
...
@@ -109,10 +160,13 @@ class Pyqt5_Cut_psd(QtWidgets.QMainWindow, Ui_Form):
psd_data
.
show
=
self
.
cbx_show
.
isChecked
()
psd_data
.
equal_size
=
self
.
cbx_equal_size
.
isChecked
()
psd_data
.
Auto_cut_1
=
self
.
cbx_auto_1
.
isChecked
()
psd_data
.
self_set_cut
=
self
.
stk_set_cut_type
.
currentIndex
==
1
self
.
lib_info_data
.
clear
()
info_prompt
=
"<"
+
psd_name
+
"|"
if
psd_data
.
Auto_cut_1
:
if
psd_data
.
self_set_cut
:
info_prompt
=
"< | 自 定 义 切 割 | >"
elif
psd_data
.
Auto_cut_1
:
info_prompt
=
"< | 智 能 切 割 | >"
else
:
if
psd_data
.
equal_size
:
...
...
@@ -133,7 +187,8 @@ class Pyqt5_Cut_psd(QtWidgets.QMainWindow, Ui_Form):
info_prompt
+=
"无需显示>"
self
.
lib_info_data
.
setText
(
info_prompt
)
psd_data
.
range_group
=
self
.
cut_range_group_list
psd_data
.
self_set_cut
=
self
.
stk_set_cut_type
.
currentIndex
()
self
.
lay_info_s
[
psd_name
]
=
get_lay_info
(
psd_data
)
self
.
lwg_confirmed
.
addItem
(
str
(
psd_name
))
# a = b = None
...
...
@@ -190,12 +245,29 @@ class Pyqt5_Cut_psd(QtWidgets.QMainWindow, Ui_Form):
extractLayerImge
(
lay_info
,
psd_name
,
self
.
lay_lwdtI
[
lay_info
])
self
.
cut_info_ok
.
emit
()
def
to_selfset_page
(
self
):
self
.
stk_set_cut_type
.
setCurrentIndex
(
1
)
def
return_selfset_page
(
self
):
self
.
stk_set_cut_type
.
setCurrentIndex
(
0
)
def
connects
(
self
):
self
.
btn_analysis
.
clicked
.
connect
(
self
.
__analysis_psd
)
self
.
btnb_confirmed
.
clicked
.
connect
(
self
.
__btnb_confirmed
)
self
.
cut_info_ok
.
connect
(
self
.
cut_pic_ok
)
self
.
cut_info_error
.
connect
(
self
.
cut_pic_error
)
self
.
btn_select_file
.
clicked
.
connect
(
self
.
__read_file_path
)
self
.
btn_selfset
.
clicked
.
connect
(
self
.
to_selfset_page
)
self
.
btn_selfset_return
.
clicked
.
connect
(
self
.
return_selfset_page
)
self
.
sbx_x
.
valueChanged
.
connect
(
self
.
__set_range_group_x
)
self
.
sbx_y
.
valueChanged
.
connect
(
self
.
__set_range_group_y
)
self
.
sbx_w
.
valueChanged
.
connect
(
self
.
__set_range_group_w
)
self
.
sbx_h
.
valueChanged
.
connect
(
self
.
__set_range_group_h
)
self
.
btn_new_range_group
.
clicked
.
connect
(
self
.
__add_range_cut_item
)
self
.
btn_del_range_group
.
clicked
.
connect
(
self
.
__del_range_cut_item
)
self
.
cbb_range_group
.
activated
[
int
]
.
connect
(
self
.
__switchOut_range_cut_item
)
if
__name__
==
'__main__'
:
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment