Skip to content

Commit 99ef5ed

Browse files
committed
feat: add pixel limit
1 parent d82c247 commit 99ef5ed

File tree

4 files changed

+27
-17
lines changed

4 files changed

+27
-17
lines changed

demo/index.ts

+5-3
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ const defaultConfig: CompressOptions = {
88
quality: 0.9,
99
fileSizeLimit: 30,
1010
lenSizeLimit: 8192,
11+
pixelSizeLimit: 1 << 26,
1112
};
1213

1314
// 添加一个图片上传按钮
@@ -19,7 +20,8 @@ input.multiple = true;
1920
pane.addBinding(defaultConfig, "useWebp", { label: "useWebp" });
2021
pane.addBinding(defaultConfig, "quality", { label: "quality", min: 0, max: 1 });
2122
pane.addBinding(defaultConfig, "fileSizeLimit", { label: "fileSizeLimit", min: 1, max: 100 });
22-
pane.addBinding(defaultConfig, "lenSizeLimit", { label: "lenSizeLimit", min: 1000, max: 16383 });
23+
pane.addBinding(defaultConfig, "lenSizeLimit", { label: "lenSizeLimit", min: 1000, max: (1 << 14) - 1 });
24+
pane.addBinding(defaultConfig, "pixelSizeLimit", { label: "pixelSizeLimit", min: 1 << 20, max: 1 << 28 });
2325
pane.addButton({ title: "upload for compress" }).on("click", () => {
2426
input.click();
2527
});
@@ -40,7 +42,7 @@ input.onchange = async (): Promise<void> => {
4042

4143
files.forEach(async (file, i) => {
4244
const { size: beforeSize, name } = file;
43-
45+
4446
const blob = await CEngine.runCompress(file, defaultConfig);
4547

4648
const afterSize = blob.size;
@@ -77,7 +79,7 @@ function preDownloadForBlobs(blob: Blob, i = 0): void {
7779
const a = document.createElement("a");
7880
a.href = url;
7981
a.download = `compressed-${i + 1}.${blob.type.split("/")[1]}`;
80-
a.textContent = `d-${i + 1}`;
82+
a.textContent = `d-${i + 1}-${blob.size >> 10}kb`;
8183

8284
const div = document.createElement("div");
8385
const img = document.createElement("img");

package.json

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "zhiwen-img-compress",
33
"private": false,
4-
"version": "0.1.0",
4+
"version": "0.2.0",
55
"main": "dist/index.js",
66
"module": "dist/index.js",
77
"types": "dist/index.d.ts",
@@ -17,8 +17,8 @@
1717
"@tweakpane/core": "^2.0.5",
1818
"gh-pages": "^6.2.0",
1919
"tweakpane": "^4.0.5",
20-
"typescript": "^5.7.0",
21-
"vite": "^6.0.0",
20+
"typescript": "^5.7.2",
21+
"vite": "^6.0.3",
2222
"vite-plugin-dts": "^4.3.0"
2323
},
2424
"files": [

src/compress.ts

+17-5
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,17 @@ export interface CompressOptions {
1717
fileSizeLimit?: number;
1818

1919
/**
20-
* 图片尺寸限制,单位 px,不应超过浏览器上限 16383
21-
* @default 8192
20+
* 图片尺寸限制,单位 px,不应超过浏览器上限 32767
21+
* @default 8196
2222
*/
2323
lenSizeLimit?: number;
2424

25+
/**
26+
* 像素限制
27+
* @default 268,435,456
28+
*/
29+
pixelSizeLimit?: number;
30+
2531
/**
2632
* 压缩质量
2733
* @default 0.9
@@ -38,10 +44,14 @@ export interface CompressOptions {
3844
const canvas = new OffscreenCanvas(1, 1);
3945
export async function compressImg(originBlob: Blob, options?: CompressOptions): Promise<Blob> {
4046
const { type: originType, size: originSize } = originBlob;
47+
const { quality = 0.9, lenSizeLimit = 1 << 13, pixelSizeLimit = 1 << 26, fileSizeLimit = 30, useWebp = true } = options || {};
48+
4149
const bitmap = await createImageBitmap(originBlob);
4250
// originBlob = null as any;
4351
const { width, height } = bitmap;
44-
const { quality = 0.9, lenSizeLimit = 8192, fileSizeLimit = 30, useWebp = true } = options || {};
52+
53+
const needCompress = originSize > fileSizeLimit << 20 || width * height > pixelSizeLimit || width > lenSizeLimit || height > lenSizeLimit;
54+
if (!needCompress) return originBlob;
4555

4656
const type = useWebp ? "image/webp" : "image/jpeg";
4757
/**max size 最大文件体积 */
@@ -50,10 +60,12 @@ export async function compressImg(originBlob: Blob, options?: CompressOptions):
5060

5161
/**max len 最大尺寸 */
5262
const mLen = Math.min(lenSizeLimit, MaxLen);
63+
64+
const mArea = Math.min(pixelSizeLimit, MaxArea);
5365
// jpg 直接缩放尺寸
5466
let scale = originType === "image/jpeg" ? Math.sqrt(mSize / originSize) : 1;
55-
if (area * scale * scale > MaxArea || width * scale > mLen || height * scale > mLen) {
56-
scale = Math.min(Math.sqrt(MaxArea / area), mLen / width, mLen / height);
67+
if (area * scale * scale > mArea || width * scale > mLen || height * scale > mLen) {
68+
scale = Math.min(Math.sqrt(mArea / area), mLen / width, mLen / height);
5769
}
5870

5971
let blob: Blob | null = null;

src/index.ts

+2-6
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ class WorkerPool {
77
queue: { file: Blob; options?: CompressOptions; resolve: (value: Blob | PromiseLike<Blob>) => void }[];
88
timer?: number;
99

10-
constructor(size: number) {
10+
constructor (size: number) {
1111
this.size = size;
1212
this.queue = [];
1313
}
@@ -45,11 +45,7 @@ class WorkerPool {
4545
if (!file.type.startsWith("image/")) {
4646
throw new Error("only image support");
4747
}
48-
const { fileSizeLimit: FileSizeLimit = 30 } = options || {};
49-
// 小于 30Mb 的图片不压缩
50-
if (file.size <= FileSizeLimit << 20) {
51-
return file;
52-
}
48+
5349
const promise = new Promise<Blob>((resolve, reject) => {
5450
// 线程不够用,将任务放入队列
5551
if (workers.length <= 0) {

0 commit comments

Comments
 (0)