Skip to content

Commit

Permalink
Add support for image decoder options (#1336)
Browse files Browse the repository at this point in the history
  • Loading branch information
hipstersmoothie authored Sep 7, 2024
1 parent c1b91e9 commit a1fac89
Show file tree
Hide file tree
Showing 5 changed files with 52 additions and 16 deletions.
30 changes: 23 additions & 7 deletions packages/core/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -98,13 +98,20 @@ type UnionToIntersection<U> = (U extends any ? (k: U) => void : never) extends (
type Constructor<T> = new (...args: any[]) => T;

type JimpFormat<
M extends string = string,
O extends Record<string, any> | undefined = undefined,
T extends Format<M, O> = Format<M, O>,
MimeType extends string = string,
EncodeOptions extends Record<string, any> | undefined = undefined,
DecodeOptions extends Record<string, any> | undefined = undefined,
T extends Format<MimeType, EncodeOptions, DecodeOptions> = Format<
MimeType,
EncodeOptions,
DecodeOptions
>,
> = () => T;

type CreateMimeTypeToExportOptions<T extends Format<string, any>> =
T extends Format<infer M, infer O> ? Record<M, O> : never;
type CreateMimeTypeToDecodeOptions<T extends Format<string, any>> =
T extends Format<infer M, any, infer O> ? Record<M, O> : never;
type GetOptionsForMimeType<Mime extends string, MimeTypeMap> =
MimeTypeMap extends Record<Mime, infer O> ? O : never;

Expand Down Expand Up @@ -138,6 +145,9 @@ export function createJimp<
type MimeTypeToExportOptions = CreateMimeTypeToExportOptions<
ReturnType<Formats[number]>
>;
type MimeTypeToDecodeOptions = CreateMimeTypeToDecodeOptions<
ReturnType<Formats[number]>
>;
type ExtensionToMimeType = CreateExtensionToMimeType<SupportedMimeTypes>;

const plugins = pluginsArg || [];
Expand Down Expand Up @@ -213,7 +223,10 @@ export function createJimp<
* const image = await Jimp.read("https://upload.wikimedia.org/wikipedia/commons/0/01/Bot-Test.jpg");
* ```
*/
static async read(url: string | Buffer | ArrayBuffer) {
static async read(
url: string | Buffer | ArrayBuffer,
options?: MimeTypeToDecodeOptions
) {
if (Buffer.isBuffer(url) || url instanceof ArrayBuffer) {
return this.fromBuffer(url);
}
Expand All @@ -239,7 +252,7 @@ export function createJimp<
}

const buffer = bufferFromArrayBuffer(data);
return this.fromBuffer(buffer);
return this.fromBuffer(buffer, options);
}

/**
Expand Down Expand Up @@ -314,7 +327,10 @@ export function createJimp<
* const image = await Jimp.fromBuffer(buffer);
* ```
*/
static async fromBuffer(buffer: Buffer | ArrayBuffer) {
static async fromBuffer(
buffer: Buffer | ArrayBuffer,
options?: MimeTypeToDecodeOptions
) {
const actualBuffer =
buffer instanceof ArrayBuffer ? bufferFromArrayBuffer(buffer) : buffer;

Expand All @@ -331,7 +347,7 @@ export function createJimp<
}

const image = new CustomJimp(
await format.decode(actualBuffer)
await format.decode(actualBuffer, options?.[format.mime])
) as InstanceType<typeof CustomJimp> & ExtraMethodMap;

image.mime = mime.mime;
Expand Down
4 changes: 3 additions & 1 deletion packages/types/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,13 @@ export interface Format<
Mime extends string = string,
// eslint-disable-next-line @typescript-eslint/no-explicit-any
ExportOptions extends Record<string, any> | undefined = undefined,
// eslint-disable-next-line @typescript-eslint/no-explicit-any
DecodeOptions extends Record<string, any> | undefined = undefined,
> {
mime: Mime;
hasAlpha?: boolean;
encode: (image: Bitmap, options?: ExportOptions) => Promise<Buffer> | Buffer;
decode: (data: Buffer) => Promise<Bitmap> | Bitmap;
decode: (data: Buffer, options?: DecodeOptions) => Promise<Bitmap> | Bitmap;
}

export interface RGBColor {
Expand Down
12 changes: 8 additions & 4 deletions plugins/js-bmp/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@ export type EncodeOptions = Pretty<
>
>;

export interface DecodeBmpOptions {
toRGBA?: boolean;
}

function encode(image: Bitmap, options: EncodeOptions = {}) {
scan(
{ bitmap: image },
Expand All @@ -47,14 +51,14 @@ function encode(image: Bitmap, options: EncodeOptions = {}) {
image.data[index + 1] = blue;
image.data[index + 2] = green;
image.data[index + 3] = red;
},
}
);

return BMP.encode({ ...image, ...options }).data;
}

function decode(data: Buffer) {
const result = BMP.decode(data);
function decode(data: Buffer, options?: DecodeBmpOptions) {
const result = BMP.decode(data, options);

scan(
{ bitmap: result },
Expand All @@ -72,7 +76,7 @@ function decode(data: Buffer) {
result.data[index + 1] = green;
result.data[index + 2] = blue;
result.data[index + 3] = 0xff;
},
}
);

return result as Bitmap;
Expand Down
11 changes: 10 additions & 1 deletion plugins/js-jpeg/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,20 @@ export interface JPEGOptions {
quality?: number;
}

export interface DecodeJpegOptions {
useTArray?: false;
colorTransform?: boolean;
formatAsRGBA?: boolean;
tolerantDecoding?: boolean;
maxResolutionInMP?: number;
maxMemoryUsageInMB?: number;
}

export default function jpeg() {
return {
mime: "image/jpeg",
encode: (bitmap, { quality = 100 }: JPEGOptions = {}) =>
JPEG.encode(bitmap, quality).data,
decode: (data) => JPEG.decode(data),
decode: (data, options?: DecodeJpegOptions) => JPEG.decode(data, options),
} satisfies Format<"image/jpeg">;
}
11 changes: 8 additions & 3 deletions plugins/js-png/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,11 @@ export type PNGOptions = Omit<
inputColorType?: PNGColorType;
};

export interface DecodePngOptions {
checkCRC?: boolean | undefined;
skipRescale?: boolean | undefined;
}

export * from "./constants.js";

export default function png() {
Expand All @@ -27,7 +32,7 @@ export default function png() {
colorType,
inputHasAlpha = true,
...options
}: PNGOptions = {},
}: PNGOptions = {}
) => {
const png = new PNG({
width: bitmap.width,
Expand All @@ -50,8 +55,8 @@ export default function png() {
inputHasAlpha,
});
},
decode: (data) => {
const result = PNG.sync.read(data);
decode: (data, options?: DecodePngOptions) => {
const result = PNG.sync.read(data, options);

return {
data: result.data,
Expand Down

0 comments on commit a1fac89

Please sign in to comment.