perf(read-image-resizer): decode only first 32KB of base64 for dimension parsing
Previously decoded entire image buffer to read headers. Now slices base64 to 32KB prefix before decoding — sufficient for PNG/GIF/WebP/JPEG headers. Dramatically reduces memory allocation for large images.
This commit is contained in:
parent
1a9e7eb305
commit
0dd9ac43ea
@ -28,6 +28,13 @@ function createGifDataUrl(width: number, height: number): string {
|
|||||||
return `data:image/gif;base64,${buf.toString("base64")}`
|
return `data:image/gif;base64,${buf.toString("base64")}`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function createLargePngDataUrl(width: number, height: number, extraBase64Chars: number): string {
|
||||||
|
const baseDataUrl = createPngDataUrl(width, height)
|
||||||
|
const base64Data = baseDataUrl.slice(baseDataUrl.indexOf(",") + 1)
|
||||||
|
const paddedBase64 = `${base64Data}${"A".repeat(extraBase64Chars)}`
|
||||||
|
return `data:image/png;base64,${paddedBase64}`
|
||||||
|
}
|
||||||
|
|
||||||
describe("parseImageDimensions", () => {
|
describe("parseImageDimensions", () => {
|
||||||
it("parses PNG 1x1 dimensions", () => {
|
it("parses PNG 1x1 dimensions", () => {
|
||||||
//#given
|
//#given
|
||||||
@ -51,6 +58,17 @@ describe("parseImageDimensions", () => {
|
|||||||
expect(result).toEqual({ width: 3000, height: 2000 })
|
expect(result).toEqual({ width: 3000, height: 2000 })
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it("parses PNG dimensions from a very large base64 payload", () => {
|
||||||
|
//#given
|
||||||
|
const dataUrl = createLargePngDataUrl(4096, 2160, 10 * 1024 * 1024)
|
||||||
|
|
||||||
|
//#when
|
||||||
|
const result = parseImageDimensions(dataUrl, "image/png")
|
||||||
|
|
||||||
|
//#then
|
||||||
|
expect(result).toEqual({ width: 4096, height: 2160 })
|
||||||
|
})
|
||||||
|
|
||||||
it("parses GIF 1x1 dimensions", () => {
|
it("parses GIF 1x1 dimensions", () => {
|
||||||
//#given
|
//#given
|
||||||
const dataUrl = GIF_1X1_DATA_URL
|
const dataUrl = GIF_1X1_DATA_URL
|
||||||
|
|||||||
@ -2,6 +2,9 @@ import type { ImageDimensions } from "./types"
|
|||||||
|
|
||||||
import { extractBase64Data } from "../../tools/look-at/mime-type-inference"
|
import { extractBase64Data } from "../../tools/look-at/mime-type-inference"
|
||||||
|
|
||||||
|
const HEADER_BYTES = 32_768
|
||||||
|
const HEADER_BASE64_CHARS = Math.ceil(HEADER_BYTES / 3) * 4
|
||||||
|
|
||||||
function toImageDimensions(width: number, height: number): ImageDimensions | null {
|
function toImageDimensions(width: number, height: number): ImageDimensions | null {
|
||||||
if (!Number.isFinite(width) || !Number.isFinite(height)) {
|
if (!Number.isFinite(width) || !Number.isFinite(height)) {
|
||||||
return null
|
return null
|
||||||
@ -157,7 +160,8 @@ export function parseImageDimensions(base64DataUrl: string, mimeType: string): I
|
|||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
const buffer = Buffer.from(rawBase64, "base64")
|
const headerBase64 = rawBase64.length > HEADER_BASE64_CHARS ? rawBase64.slice(0, HEADER_BASE64_CHARS) : rawBase64
|
||||||
|
const buffer = Buffer.from(headerBase64, "base64")
|
||||||
if (buffer.length === 0) {
|
if (buffer.length === 0) {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user