Skip to content

Commit

Permalink
feat: add bmp input support
Browse files Browse the repository at this point in the history
  • Loading branch information
magicdawn committed Dec 20, 2023
1 parent 8d9f32a commit d01db2c
Show file tree
Hide file tree
Showing 3 changed files with 61 additions and 3 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
"dependencies": {
"@magicdawn/finder-sort": "^0.3.4",
"@magicdawn/x-args": "^1.0.0",
"@vingle/bmp-js": "^0.2.5",
"bytes": "^3.1.2",
"chalk": "5",
"clipanion": "3.2.1",
Expand Down
13 changes: 13 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

50 changes: 47 additions & 3 deletions src/compress.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
import * as bmp from '@vingle/bmp-js'
import { readFile } from 'fs/promises'
import NodeMozjpeg, { type EncodeOptions as MozjpegEncodeOptions } from 'node-mozjpeg'
import sharp from 'sharp'
import path from 'path'
import sharp, { Sharp } from 'sharp'
import { decode, SharpInput } from './codec/decode.js'

const { encode: mozjpegEncode } = NodeMozjpeg
Expand All @@ -18,12 +21,53 @@ export async function mozjpegCompress(file: SharpInput, options?: Partial<Mozjpe
return bufEncoded
}

/**
* bmp support
* @see /~https://github.com/lovell/sharp/issues/806#issuecomment-419661745
*/

const BUF_BMP = Buffer.from([0x42, 0x4d]) // "BM" file signature

function isBitmap(buf: Buffer): boolean {
return Buffer.compare(BUF_BMP, buf.slice(0, 2)) === 0
}

const handleBmp = (buf: Buffer) => {
const bitmap = bmp.decode(buf, true)
return sharp(bitmap.data, {
raw: {
width: bitmap.width,
height: bitmap.height,
channels: 4,
},
})
}

async function getSharpInstance(input: SharpInput): Promise<Sharp> {
// bmp
if (typeof input === 'string') {
if (path.extname(input).toLowerCase() === '.bmp') {
const buf = await readFile(input)
if (isBitmap(buf)) {
return handleBmp(buf)
}
}
}
if (Buffer.isBuffer(input)) {
if (isBitmap(input)) {
return handleBmp(input)
}
}

return sharp(input)
}

export async function sharpMozjpegCompress(
file: SharpInput,
keepMetadata = true,
options?: sharp.JpegOptions,
) {
let img = sharp(file).jpeg({
let img = (await getSharpInstance(file)).jpeg({
mozjpeg: true,
...options,
})
Expand All @@ -50,7 +94,7 @@ function sharpTargetFormatFactory<T extends 'webp' | 'avif' | 'jxl'>(
keepMetadata = true,
options?: IOptions,
) {
let img = sharp(file)[targetFormat](options)
let img = (await getSharpInstance(file))[targetFormat](options)

if (keepMetadata) {
img = img.withMetadata()
Expand Down

0 comments on commit d01db2c

Please sign in to comment.