99 lines
2.8 KiB
JavaScript
99 lines
2.8 KiB
JavaScript
|
|
import assert from "node:assert/strict";
|
||
|
|
import test from "node:test";
|
||
|
|
import sharp from "sharp";
|
||
|
|
import { normalizeWorkbookImage } from "../lib/workbook-image.ts";
|
||
|
|
|
||
|
|
test("bakes EXIF orientation into exported workbook image pixels", async () => {
|
||
|
|
const source = await sharp({
|
||
|
|
create: {
|
||
|
|
width: 8,
|
||
|
|
height: 4,
|
||
|
|
channels: 3,
|
||
|
|
background: "#e95420",
|
||
|
|
},
|
||
|
|
})
|
||
|
|
.jpeg()
|
||
|
|
.withMetadata({ orientation: 6 })
|
||
|
|
.toBuffer();
|
||
|
|
|
||
|
|
const normalized = await normalizeWorkbookImage({
|
||
|
|
bytes: new Uint8Array(source),
|
||
|
|
contentType: "image/jpeg",
|
||
|
|
width: 8,
|
||
|
|
height: 4,
|
||
|
|
description: "手机照片",
|
||
|
|
});
|
||
|
|
const metadata = await sharp(normalized.bytes).metadata();
|
||
|
|
|
||
|
|
assert.equal(normalized.contentType, "image/png");
|
||
|
|
assert.equal(normalized.width, 4);
|
||
|
|
assert.equal(normalized.height, 8);
|
||
|
|
assert.equal(metadata.width, 4);
|
||
|
|
assert.equal(metadata.height, 8);
|
||
|
|
assert.equal(metadata.orientation, undefined);
|
||
|
|
});
|
||
|
|
|
||
|
|
test("keeps unsupported image bytes unchanged", async () => {
|
||
|
|
const bytes = Uint8Array.from([1, 2, 3]);
|
||
|
|
const normalized = await normalizeWorkbookImage({
|
||
|
|
bytes,
|
||
|
|
contentType: "application/octet-stream",
|
||
|
|
description: "未知文件",
|
||
|
|
});
|
||
|
|
assert.equal(normalized.bytes, bytes);
|
||
|
|
assert.equal(normalized.contentType, "application/octet-stream");
|
||
|
|
});
|
||
|
|
|
||
|
|
test("normalizes recognizable images even when storage metadata has no image MIME type", async () => {
|
||
|
|
const source = await sharp({
|
||
|
|
create: {
|
||
|
|
width: 8,
|
||
|
|
height: 4,
|
||
|
|
channels: 3,
|
||
|
|
background: "#22c55e",
|
||
|
|
},
|
||
|
|
})
|
||
|
|
.jpeg()
|
||
|
|
.withMetadata({ orientation: 6 })
|
||
|
|
.toBuffer();
|
||
|
|
const normalized = await normalizeWorkbookImage({
|
||
|
|
bytes: new Uint8Array(source),
|
||
|
|
contentType: "application/octet-stream",
|
||
|
|
description: "方向元数据缺失测试",
|
||
|
|
});
|
||
|
|
|
||
|
|
assert.equal(normalized.contentType, "image/png");
|
||
|
|
assert.equal(normalized.width, 4);
|
||
|
|
assert.equal(normalized.height, 8);
|
||
|
|
});
|
||
|
|
|
||
|
|
test("can downsize full-resolution source images for compact workbook exports", async () => {
|
||
|
|
const source = await sharp({
|
||
|
|
create: {
|
||
|
|
width: 4000,
|
||
|
|
height: 3000,
|
||
|
|
channels: 3,
|
||
|
|
background: "#d4a72c",
|
||
|
|
},
|
||
|
|
})
|
||
|
|
.png({ compressionLevel: 0 })
|
||
|
|
.toBuffer();
|
||
|
|
const normalized = await normalizeWorkbookImage(
|
||
|
|
{
|
||
|
|
bytes: new Uint8Array(source),
|
||
|
|
contentType: "image/png",
|
||
|
|
width: 4000,
|
||
|
|
height: 3000,
|
||
|
|
description: "批量回填原图",
|
||
|
|
},
|
||
|
|
{ maxDimension: 1600, outputFormat: "jpeg", jpegQuality: 82 },
|
||
|
|
);
|
||
|
|
const metadata = await sharp(normalized.bytes).metadata();
|
||
|
|
|
||
|
|
assert.equal(normalized.contentType, "image/jpeg");
|
||
|
|
assert.equal(normalized.width, 1600);
|
||
|
|
assert.equal(normalized.height, 1200);
|
||
|
|
assert.equal(metadata.format, "jpeg");
|
||
|
|
assert.ok(normalized.bytes.byteLength < source.byteLength / 20);
|
||
|
|
});
|