feat: build licensed desktop image processor
This commit is contained in:
@@ -0,0 +1,106 @@
|
||||
import { promises as fs } from 'node:fs'
|
||||
import os from 'node:os'
|
||||
import path from 'node:path'
|
||||
import sharp from 'sharp'
|
||||
import { afterEach, beforeEach, describe, expect, it } from 'vitest'
|
||||
import type { ProcessOptions } from '../../src/shared/types'
|
||||
import {
|
||||
ImageProcessor,
|
||||
processSingleImage,
|
||||
readSofHeight,
|
||||
} from './image-processor'
|
||||
|
||||
describe('image processing algorithm', () => {
|
||||
let temporaryDirectory: string
|
||||
let inputPath: string
|
||||
|
||||
beforeEach(async () => {
|
||||
temporaryDirectory = await fs.mkdtemp(path.join(os.tmpdir(), 'genuine-qingquwang-'))
|
||||
inputPath = path.join(temporaryDirectory, 'sample.jpg')
|
||||
await sharp({
|
||||
create: {
|
||||
width: 18,
|
||||
height: 12,
|
||||
channels: 3,
|
||||
background: { r: 23, g: 105, b: 224 },
|
||||
},
|
||||
}).jpeg({ quality: 90 }).toFile(inputPath)
|
||||
})
|
||||
|
||||
afterEach(async () => {
|
||||
await fs.rm(temporaryDirectory, { recursive: true, force: true })
|
||||
})
|
||||
|
||||
it('writes a .file without EOI while restoring original SOF height', async () => {
|
||||
const outputPath = await processSingleImage(inputPath, options('file', 0))
|
||||
const output = await fs.readFile(outputPath)
|
||||
|
||||
expect(outputPath).toBe(path.join(temporaryDirectory, 'sample.file'))
|
||||
expect(readSofHeight(output)).toBe(12)
|
||||
expect(output.subarray(-2).equals(Buffer.from([0xff, 0xd9]))).toBe(false)
|
||||
})
|
||||
|
||||
it('supports .file.jpg and appends the configured random byte count', async () => {
|
||||
const baselinePath = await processSingleImage(inputPath, options('file', 0))
|
||||
const baselineSize = (await fs.stat(baselinePath)).size
|
||||
const outputPath = await processSingleImage(inputPath, options('file-jpg', 0.01))
|
||||
const outputSize = (await fs.stat(outputPath)).size
|
||||
|
||||
expect(outputPath).toBe(path.join(temporaryDirectory, 'sample.file.jpg'))
|
||||
expect(outputSize - baselineSize).toBe(Math.floor(0.01 * 1024 * 1024))
|
||||
})
|
||||
|
||||
it('discovers and converts supported non-JPEG inputs into JPEG delivery files', async () => {
|
||||
const source = sharp({
|
||||
create: {
|
||||
width: 18,
|
||||
height: 12,
|
||||
channels: 4,
|
||||
background: { r: 23, g: 105, b: 224, alpha: 0.5 },
|
||||
},
|
||||
})
|
||||
const inputs = [
|
||||
path.join(temporaryDirectory, 'sample.png'),
|
||||
path.join(temporaryDirectory, 'sample.webp'),
|
||||
path.join(temporaryDirectory, 'sample.gif'),
|
||||
path.join(temporaryDirectory, 'sample.tiff'),
|
||||
path.join(temporaryDirectory, 'sample.avif'),
|
||||
]
|
||||
await Promise.all([
|
||||
source.clone().png().toFile(inputs[0]),
|
||||
source.clone().webp().toFile(inputs[1]),
|
||||
source.clone().gif().toFile(inputs[2]),
|
||||
source.clone().tiff().toFile(inputs[3]),
|
||||
source.clone().avif().toFile(inputs[4]),
|
||||
fs.writeFile(path.join(temporaryDirectory, 'sample.svg'), '<svg xmlns="http://www.w3.org/2000/svg" width="18" height="12"><rect width="18" height="12" fill="#1769e0"/></svg>'),
|
||||
fs.writeFile(path.join(temporaryDirectory, 'ignored.bmp'), 'not-supported'),
|
||||
])
|
||||
|
||||
const processor = new ImageProcessor()
|
||||
const inspected = await processor.inspect([temporaryDirectory])
|
||||
const inspectedNames = inspected.map((item) => item.name)
|
||||
expect(inspectedNames).toEqual([
|
||||
'sample.avif',
|
||||
'sample.gif',
|
||||
'sample.jpg',
|
||||
'sample.png',
|
||||
'sample.svg',
|
||||
'sample.tiff',
|
||||
'sample.webp',
|
||||
])
|
||||
|
||||
for (const input of [...inputs, path.join(temporaryDirectory, 'sample.svg')]) {
|
||||
const outputPath = await processSingleImage(input, options('file', 0))
|
||||
expect(readSofHeight(await fs.readFile(outputPath))).toBe(12)
|
||||
}
|
||||
})
|
||||
|
||||
function options(outputFormat: 'file' | 'file-jpg', junkSizeMb: number): ProcessOptions {
|
||||
return {
|
||||
paths: [inputPath],
|
||||
useSourceDirectory: true,
|
||||
outputFormat,
|
||||
junkSizeMb,
|
||||
}
|
||||
}
|
||||
})
|
||||
Reference in New Issue
Block a user