import type { Image } from '../Image.js'; import { Mask } from '../Mask.js'; import { getNodeApiOrThrow } from '../utils/cross_platform.js'; import type { EncodeOptionsBmp, EncodeOptionsJpeg, EncodeOptionsPng, } from './encode.js'; import { encode } from './encode.js'; export interface WriteOptions { /** * If true, attempts to create all the missing directories recursively. */ recursive?: boolean; } export type WriteOptionsPng = WriteOptions & EncodeOptionsPng; export type WriteOptionsJpeg = WriteOptions & EncodeOptionsJpeg; export type WriteOptionsBmp = WriteOptions & EncodeOptionsBmp; /** * Write an image to the disk. * The file format is determined automatically from the file's extension. * If the extension is not supported, an error will be thrown. * This method is only implemented for Node.js. * @param path - Path or file URL where the image should be written. * @param image - Image to save. * @param options - Write options. * @returns A promise that resolves when the image is written. */ export async function write( path: string | URL, image: Image | Mask, options?: WriteOptions, ): Promise; /** * Write an image to the disk as PNG. * When the `png` format is specified, the file's extension doesn't matter. * This method is only implemented for Node.js. * @param path - Path or file URL where the image should be written. * @param image - Image to save. * @param options - Encode options for png images. * @returns A promise that resolves when the image is written. */ export async function write( path: string | URL, image: Image | Mask, options: WriteOptionsPng, ): Promise; /** * Write an image to the disk as JPEG. * When the `jpeg` format is specified, the file's extension doesn't matter. * This method is only implemented for Node.js. * @param path - Path or file URL where the image should be written. * @param image - Image to save. * @param options - Encode options for jpeg images. * @returns A promise that resolves when the image is written. */ export async function write( path: string | URL, image: Image | Mask, options: WriteOptionsJpeg, ): Promise; /** * Write an image to the disk as BMP. * When the `bmp` format is specified, the file's extension doesn't matter. * This method is only implemented for Node.js. * @param path - Path or file URL where the image should be written. * @param image - Image to save. * @param options - Encode options for bmp images. * @returns A promise that resolves when the image is written. */ export async function write( path: string | URL, image: Mask, options?: WriteOptionsBmp, ): Promise; /** * Asynchronously write an image to the disk. * This method is only implemented for Node.js. * @param path - Path where the image should be written. * @param image - Image to save. * @param options - Encode options. */ export async function write( path: string | URL, image: Image | Mask, options?: WriteOptionsBmp | WriteOptionsPng | WriteOptionsJpeg | WriteOptions, ): Promise { const nodeApi = getNodeApiOrThrow('write'); if (typeof path !== 'string') { path = nodeApi.url.fileURLToPath(path); } if (image instanceof Mask) { image = image.convertColor('GREY'); } const toWrite = getDataToWrite(path, image, options, nodeApi); if (options?.recursive) { const dir = nodeApi.path.dirname(path); await nodeApi.fs.promises.mkdir(dir, { recursive: true }); } await nodeApi.fs.promises.writeFile(path, toWrite); } /** * Synchronous version of {@link write}. * This method is only implemented for Node.js. * @param path - Path where the image should be written. * @param image - Image to save. * @param options - Encode options. */ export function writeSync( path: string | URL, image: Image | Mask, options?: WriteOptionsBmp | WriteOptionsPng | WriteOptionsJpeg | WriteOptions, ): void { const nodeApi = getNodeApiOrThrow('writeSync'); if (typeof path !== 'string') { path = nodeApi.url.fileURLToPath(path); } const toWrite = getDataToWrite(path, image, options, nodeApi); if (options?.recursive) { const dir = nodeApi.path.dirname(path); nodeApi.fs.mkdirSync(dir, { recursive: true }); } nodeApi.fs.writeFileSync(path, toWrite); } /** * Encode the image to the format specified by the file's extension. * @param destinationPath - Image destination. * @param image - Image to save. * @param options - Encode options. * @param nodeApi - Object with Node.js APIs. * @returns Buffer containing the encoded image. */ function getDataToWrite( destinationPath: string, image: Image | Mask, options: | WriteOptionsBmp | WriteOptionsPng | WriteOptionsJpeg | WriteOptions | undefined, nodeApi: ReturnType, ): Uint8Array { if (!options || !('format' in options)) { const extension = nodeApi.path .extname(destinationPath) .slice(1) .toLowerCase(); if ( extension === 'png' || extension === 'jpg' || extension === 'jpeg' || extension === 'bmp' ) { return encode(image, { ...options, format: extension }); } else { throw new RangeError( 'image format could not be determined from file extension. Use a supported extension or specify the format option', ); } } else { return encode(image, options); } }