Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for image decoder options #1336

Merged
merged 1 commit into from
Sep 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading