Skip to content

Commit

Permalink
use subprocess
Browse files Browse the repository at this point in the history
  • Loading branch information
Timer committed Feb 17, 2021
1 parent 495af07 commit ff86315
Show file tree
Hide file tree
Showing 2 changed files with 93 additions and 43 deletions.
70 changes: 70 additions & 0 deletions packages/next/next-server/server/lib/squoosh/impl.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import { codecs as supportedFormats, preprocessors } from './codecs'
import ImageData from './image_data'

export async function decodeBuffer(buffer: Buffer): Promise<ImageData> {
const firstChunk = buffer.slice(0, 16)
const firstChunkString = Array.from(firstChunk)
.map((v) => String.fromCodePoint(v))
.join('')
const key = Object.entries(supportedFormats).find(([, { detectors }]) =>
detectors.some((detector) => detector.exec(firstChunkString))
)?.[0] as keyof typeof supportedFormats
if (!key) {
throw Error(`Buffer has an unsupported format`)
}
const d = await supportedFormats[key].dec()
const rgba = d.decode(new Uint8Array(buffer))
return rgba
}

export async function rotate(
image: ImageData,
numRotations: number
): Promise<ImageData> {
const m = await preprocessors['rotate'].instantiate()
return await m(image.data, image.width, image.height, { numRotations })
}

export async function resize(image: ImageData, { width }: { width: number }) {
const p = preprocessors['resize']
const m = await p.instantiate()
return await m(image.data, image.width, image.height, {
...p.defaultOptions,
width,
})
}

export async function encodeJpeg(
image: ImageData,
{ quality }: { quality: number }
): Promise<Buffer> {
const e = supportedFormats['mozjpeg']
const m = await e.enc()
const r = await m.encode!(image.data, image.width, image.height, {
...e.defaultEncoderOptions,
quality,
})
return Buffer.from(r)
}

export async function encodeWebp(
image: ImageData,
{ quality }: { quality: number }
): Promise<Buffer> {
const e = supportedFormats['webp']
const m = await e.enc()
const r = await m.encode!(image.data, image.width, image.height, {
...e.defaultEncoderOptions,
quality,
})
return Buffer.from(r)
}

export async function encodePng(image: ImageData): Promise<Buffer> {
const e = supportedFormats['oxipng']
const m = await e.enc()
const r = await m.encode(image.data, image.width, image.height, {
...e.defaultEncoderOptions,
})
return Buffer.from(r)
}
66 changes: 23 additions & 43 deletions packages/next/next-server/server/lib/squoosh/main.ts
Original file line number Diff line number Diff line change
@@ -1,67 +1,47 @@
import { codecs as supportedFormats, preprocessors } from './codecs'
import JestWorker from 'jest-worker'
import * as path from 'path'
import { execOnce } from '../../../lib/utils'
import ImageData from './image_data'

const getWorker = execOnce(
() => new JestWorker(path.resolve(__dirname, 'impl'))
)

export async function decodeBuffer(buffer: Buffer): Promise<ImageData> {
const firstChunk = buffer.slice(0, 16)
const firstChunkString = Array.from(firstChunk)
.map((v) => String.fromCodePoint(v))
.join('')
const key = Object.entries(supportedFormats).find(([, { detectors }]) =>
detectors.some((detector) => detector.exec(firstChunkString))
)?.[0] as keyof typeof supportedFormats
if (!key) {
throw Error(`Buffer has an unsupported format`)
}
const d = await supportedFormats[key].dec()
const rgba = d.decode(new Uint8Array(buffer))
return rgba
const worker: typeof import('./impl') = getWorker() as any
return await worker.decodeBuffer(buffer)
}

export async function rotate(image: ImageData, numRotations: number) {
const m = await preprocessors['rotate'].instantiate()
return await m(image.data, image.width, image.height, { numRotations })
export async function rotate(
image: ImageData,
numRotations: number
): Promise<ImageData> {
const worker: typeof import('./impl') = getWorker() as any
return await worker.rotate(image, numRotations)
}

export async function resize(image: ImageData, { width }: { width: number }) {
const p = preprocessors['resize']
const m = await p.instantiate()
return await m(image.data, image.width, image.height, {
...p.defaultOptions,
width,
})
const worker: typeof import('./impl') = getWorker() as any
return await worker.resize(image, { width })
}

export async function encodeJpeg(
image: ImageData,
{ quality }: { quality: number }
): Promise<Buffer> {
const e = supportedFormats['mozjpeg']
const m = await e.enc()
const r = await m.encode!(image.data, image.width, image.height, {
...e.defaultEncoderOptions,
quality,
})
return Buffer.from(r)
const worker: typeof import('./impl') = getWorker() as any
return await worker.encodeJpeg(image, { quality })
}

export async function encodeWebp(
image: ImageData,
{ quality }: { quality: number }
): Promise<Buffer> {
const e = supportedFormats['webp']
const m = await e.enc()
const r = await m.encode!(image.data, image.width, image.height, {
...e.defaultEncoderOptions,
quality,
})
return Buffer.from(r)
const worker: typeof import('./impl') = getWorker() as any
return await worker.encodeWebp(image, { quality })
}

export async function encodePng(image: ImageData): Promise<Buffer> {
const e = supportedFormats['oxipng']
const m = await e.enc()
const r = await m.encode(image.data, image.width, image.height, {
...e.defaultEncoderOptions,
})
return Buffer.from(r)
const worker: typeof import('./impl') = getWorker() as any
return await worker.encodePng(image)
}

0 comments on commit ff86315

Please sign in to comment.