Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
E
electron-printer
Overview
Overview
Details
Activity
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
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
zhuzhequan
electron-printer
Commits
c55b2d32
Commit
c55b2d32
authored
Jul 19, 2025
by
linjinhong
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
修改裁剪方法
parent
867cb6f6
Show whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
238 additions
and
29 deletions
+238
-29
src/background.js
+0
-19
src/server/utils/setImage.js
+238
-10
No files found.
src/background.js
View file @
c55b2d32
...
@@ -187,8 +187,6 @@ app.on("activate", async () => {
...
@@ -187,8 +187,6 @@ app.on("activate", async () => {
app
.
on
(
"ready"
,
async
()
=>
{
app
.
on
(
"ready"
,
async
()
=>
{
await
createWindow
();
await
createWindow
();
checkMemorySetting
();
// 获取当前窗口的尺寸
// 获取当前窗口的尺寸
const
{
width
,
height
}
=
win
.
getBounds
();
const
{
width
,
height
}
=
win
.
getBounds
();
win
.
webContents
.
send
(
"window-size"
,
{
width
,
height
});
win
.
webContents
.
send
(
"window-size"
,
{
width
,
height
});
...
@@ -205,23 +203,6 @@ app.on("will-quit", () => {
...
@@ -205,23 +203,6 @@ app.on("will-quit", () => {
globalShortcut
.
unregister
(
"CommandOrControl+R"
);
globalShortcut
.
unregister
(
"CommandOrControl+R"
);
});
});
function
checkMemorySetting
()
{
try
{
const
v8
=
require
(
"v8"
);
const
heapStats
=
v8
.
getHeapStatistics
();
const
currentLimitMB
=
Math
.
floor
(
heapStats
.
heap_size_limit
/
(
1024
*
1024
)
);
console
.
log
(
`当前堆内存限制:
${
currentLimitMB
}
MB`
);
if
(
currentLimitMB
<
4096
)
{
console
.
warn
(
"内存设置不足,建议重启应用"
);
}
}
catch
(
error
)
{
console
.
error
(
"无法检查内存设置"
,
error
);
}
}
if
(
isDevelopment
)
{
if
(
isDevelopment
)
{
if
(
process
.
platform
===
"win32"
)
{
if
(
process
.
platform
===
"win32"
)
{
process
.
on
(
"message"
,
(
data
)
=>
{
process
.
on
(
"message"
,
(
data
)
=>
{
...
...
src/server/utils/setImage.js
View file @
c55b2d32
...
@@ -124,11 +124,7 @@ async function cropTransparentEdges(inputDir, outputDir, options = {}) {
...
@@ -124,11 +124,7 @@ async function cropTransparentEdges(inputDir, outputDir, options = {}) {
const
inputPath
=
path
.
join
(
inputDir
,
file
);
const
inputPath
=
path
.
join
(
inputDir
,
file
);
const
outputPath
=
path
.
join
(
outputDir
,
file
);
const
outputPath
=
path
.
join
(
outputDir
,
file
);
const
result
=
await
cropImageTransparentEdges
(
const
result
=
await
cropImage
(
inputPath
,
outputPath
,
options
);
inputPath
,
outputPath
,
options
);
results
.
push
({
file
,
...
result
});
results
.
push
({
file
,
...
result
});
}
}
...
@@ -162,11 +158,7 @@ async function processImages(inputPath, outputPath, options = {}) {
...
@@ -162,11 +158,7 @@ async function processImages(inputPath, outputPath, options = {}) {
results
=
await
cropTransparentEdges
(
inputPath
,
outputPath
,
options
);
results
=
await
cropTransparentEdges
(
inputPath
,
outputPath
,
options
);
}
else
{
}
else
{
// 处理单个图片
// 处理单个图片
const
result
=
await
cropImageTransparentEdges
(
const
result
=
await
cropImage
(
inputPath
,
outputPath
,
options
);
inputPath
,
outputPath
,
options
);
results
=
[{
file
:
path
.
basename
(
inputPath
),
...
result
}];
results
=
[{
file
:
path
.
basename
(
inputPath
),
...
result
}];
}
}
...
@@ -190,10 +182,246 @@ async function processImages(inputPath, outputPath, options = {}) {
...
@@ -190,10 +182,246 @@ async function processImages(inputPath, outputPath, options = {}) {
}
}
}
}
/**
* 裁切方法优化
*/
async
function
cropImage
(
inputPath
,
outputPath
,
options
=
{})
{
const
{
threshold
=
10
,
// 透明度阈值
stripHeight
=
64
,
// 流式模式条带高度
maxDimension
=
2500
,
// 小图/大图分界点
padding
=
0
,
// 裁剪后留白
debug
=
false
,
// 调试模式
forceStreamMode
=
false
,
// 强制使用流式模式
}
=
options
;
// 确保输出目录存在
const
outputDir
=
path
.
dirname
(
outputPath
);
if
(
!
fs
.
existsSync
(
outputDir
))
{
fs
.
mkdirSync
(
outputDir
,
{
recursive
:
true
});
}
try
{
// 获取图像元数据
const
metadata
=
await
sharp
(
inputPath
).
metadata
();
const
{
width
,
height
}
=
metadata
;
const
channels
=
metadata
.
channels
||
4
;
const
alphaIndex
=
channels
-
1
;
// 根据尺寸选择处理模式
const
useStreamMode
=
forceStreamMode
||
width
>
maxDimension
||
height
>
maxDimension
;
let
bounds
=
{
top
:
height
,
bottom
:
0
,
left
:
width
,
right
:
0
,
foundPixels
:
false
,
};
if
(
debug
)
{
console
.
log
(
`处理图像:
${
width
}
x
${
height
}
`
);
console
.
log
(
`模式:
${
useStreamMode
?
"流式处理"
:
"快速处理"
}
`
);
}
if
(
useStreamMode
)
{
// 流式安全模式(处理大图)
await
processInStreamMode
(
inputPath
,
bounds
,
{
width
,
height
,
channels
,
alphaIndex
,
threshold
,
stripHeight
,
debug
,
});
}
else
{
// 快速模式(处理小图)
await
processInFastMode
(
inputPath
,
bounds
,
{
width
,
height
,
channels
,
alphaIndex
,
threshold
,
});
}
// 检查是否找到有效像素
if
(
!
bounds
.
foundPixels
)
{
// 全透明图像直接复制
await
fs
.
promises
.
copyFile
(
inputPath
,
outputPath
);
return
{
status
:
"unchanged"
,
reason
:
"全透明图片"
,
originalSize
:
{
width
,
height
},
};
}
// 应用边界留白
applyPadding
(
bounds
,
padding
,
width
,
height
);
// 计算裁剪区域
const
cropWidth
=
Math
.
min
(
width
-
bounds
.
left
,
bounds
.
right
-
bounds
.
left
+
1
);
const
cropHeight
=
Math
.
min
(
height
-
bounds
.
top
,
bounds
.
bottom
-
bounds
.
top
+
1
);
if
(
cropWidth
<=
0
||
cropHeight
<=
0
)
{
throw
new
Error
(
`无效的裁剪尺寸:
${
cropWidth
}
x
${
cropHeight
}
`
);
}
// 如果裁剪区域和原图一样则跳过
if
(
cropWidth
===
width
&&
cropHeight
===
height
)
{
await
fs
.
promises
.
copyFile
(
inputPath
,
outputPath
);
return
{
status
:
"unchanged"
,
reason
:
"裁剪尺寸与原图相同"
,
originalSize
:
{
width
,
height
},
};
}
// 执行裁剪
await
sharp
(
inputPath
)
.
extract
({
left
:
bounds
.
left
,
top
:
bounds
.
top
,
width
:
cropWidth
,
height
:
cropHeight
,
})
.
toFile
(
outputPath
);
return
{
status
:
"cropped"
,
outputPath
,
originalSize
:
{
width
,
height
},
newSize
:
{
width
:
cropWidth
,
height
:
cropHeight
},
cropArea
:
{
x
:
bounds
.
left
,
y
:
bounds
.
top
,
width
:
cropWidth
,
height
:
cropHeight
,
},
};
}
catch
(
error
)
{
return
{
status
:
"error"
,
error
:
error
.
message
,
stack
:
error
.
stack
,
};
}
}
async
function
processInStreamMode
(
inputPath
,
bounds
,
options
)
{
const
{
width
,
height
,
channels
,
alphaIndex
,
threshold
,
stripHeight
,
debug
,
}
=
options
;
// 垂直分条带处理(从0到height)
for
(
let
y
=
0
;
y
<
height
;
y
+=
stripHeight
)
{
const
currentStripHeight
=
Math
.
min
(
stripHeight
,
height
-
y
);
// 读取当前条带
const
stripData
=
await
sharp
(
inputPath
)
.
extract
({
left
:
0
,
top
:
y
,
width
,
height
:
currentStripHeight
,
})
.
raw
()
.
toBuffer
();
// 处理当前条带内的像素
for
(
let
row
=
0
;
row
<
currentStripHeight
;
row
++
)
{
const
rowStartIdx
=
row
*
width
*
channels
;
let
rowHasPixel
=
false
;
// 扫描当前行寻找像素
for
(
let
x
=
0
;
x
<
width
;
x
++
)
{
const
idx
=
rowStartIdx
+
x
*
channels
+
alphaIndex
;
if
(
stripData
[
idx
]
>
threshold
)
{
rowHasPixel
=
true
;
const
absY
=
y
+
row
;
// 更新垂直边界
if
(
absY
<
bounds
.
top
)
bounds
.
top
=
absY
;
if
(
absY
>
bounds
.
bottom
)
bounds
.
bottom
=
absY
;
// 更新水平边界
if
(
x
<
bounds
.
left
)
bounds
.
left
=
x
;
if
(
x
>
bounds
.
right
)
bounds
.
right
=
x
;
}
}
// 标记找到像素
if
(
rowHasPixel
)
bounds
.
foundPixels
=
true
;
}
// 调试信息
if
(
debug
&&
y
%
(
stripHeight
*
10
)
===
0
)
{
console
.
log
(
`流式处理进度:
${
y
}
/
${
height
}
(
${
Math
.
round
((
y
/
height
)
*
100
)}
%)`
);
}
}
}
// 快速模式(高效处理小图)
async
function
processInFastMode
(
inputPath
,
bounds
,
options
)
{
const
{
width
,
height
,
channels
,
alphaIndex
,
threshold
}
=
options
;
// 一次性读取整个图像
const
imageBuffer
=
await
sharp
(
inputPath
)
.
raw
()
.
toBuffer
();
// 遍历整张图像
for
(
let
y
=
0
;
y
<
height
;
y
++
)
{
for
(
let
x
=
0
;
x
<
width
;
x
++
)
{
const
idx
=
(
y
*
width
+
x
)
*
channels
+
alphaIndex
;
if
(
imageBuffer
[
idx
]
>
threshold
)
{
bounds
.
foundPixels
=
true
;
// 更新所有边界
if
(
y
<
bounds
.
top
)
bounds
.
top
=
y
;
if
(
y
>
bounds
.
bottom
)
bounds
.
bottom
=
y
;
if
(
x
<
bounds
.
left
)
bounds
.
left
=
x
;
if
(
x
>
bounds
.
right
)
bounds
.
right
=
x
;
}
}
}
}
// ================= 辅助函数 =================
// 应用边界留白
function
applyPadding
(
bounds
,
padding
,
imgWidth
,
imgHeight
)
{
if
(
padding
>
0
)
{
bounds
.
top
=
Math
.
max
(
0
,
bounds
.
top
-
padding
);
bounds
.
bottom
=
Math
.
min
(
imgHeight
-
1
,
bounds
.
bottom
+
padding
);
bounds
.
left
=
Math
.
max
(
0
,
bounds
.
left
-
padding
);
bounds
.
right
=
Math
.
min
(
imgWidth
-
1
,
bounds
.
right
+
padding
);
}
}
// 分区边界检测实现
// 分区边界检测实现
module
.
exports
=
{
module
.
exports
=
{
cropTransparentEdges
,
cropTransparentEdges
,
cropImageTransparentEdges
,
cropImageTransparentEdges
,
processImages
,
processImages
,
cropImage
,
};
};
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