# core/converters/image.converter.ts

> 26 lines of code and 7 definitions.

Tree: Bane's Lab Social Share
Language: typescript
Layer: processing
Canonical: https://banes-lab.com/anatomy/social-share#file-social-share-core-converters-image-converter-ts
Source text: https://banes-lab.com/source/social-share/core/converters/image.converter.ts.txt

Listed in [core/converters](https://banes-lab.com/api/source/social-share/core/converters.md), after [core/converters/filename.converter.ts](https://banes-lab.com/source/social-share/core/converters/filename.converter.ts.md) and before [core/converters/style.converter.ts](https://banes-lab.com/source/social-share/core/converters/style.converter.ts.md).

## Definitions

- `resized` (lexical_declaration, line 10)
- `motionOf` (lexical_declaration, line 18, exported)
- `stillOf` (lexical_declaration, line 14, exported)
- `ENDLESS` (lexical_declaration, line 6)
- `ONCE` (lexical_declaration, line 7)
- `KERNEL` (lexical_declaration, line 8)
- `scaled` (lexical_declaration, line 26, exported)

## Contained in

- [core/converters](https://banes-lab.com/anatomy/social-share/folder-social-share-core-converters.md)

## Used by

- [core/coordinators/card.coordinator.ts](https://banes-lab.com/source/social-share/core/coordinators/card.coordinator.ts.md)

## Linked from

- [core/converters](https://banes-lab.com/anatomy/social-share/folder-social-share-core-converters.md)
- [core/coordinators](https://banes-lab.com/anatomy/social-share/folder-social-share-core-coordinators.md)

## Source

```typescript
import { OUTPUT_FRAME_MS, WEBP_QUALITY } from "#configuration/configs/card.config";
import type { ImageSize } from "#types/image.types";
import type { Timeline } from "#types/card.types";
import sharp from "sharp";

const ENDLESS = 0;
const ONCE = 1;
const KERNEL = "lanczos3";

const resized = async function resized(frame: Buffer, size: ImageSize): Promise<Buffer> {
    return sharp(frame).resize(size.width, size.height, { fit: "fill", kernel: KERNEL }).png().toBuffer();
};

export const stillOf = async function stillOf(frame: Buffer, size: ImageSize): Promise<Buffer> {
    return resized(frame, size);
};

export const motionOf = async function motionOf(
    frames: readonly Buffer[],
    timeline: Timeline,
    size: ImageSize,
): Promise<Buffer | null> {
    if (frames.length < 2) {
        return null;
    }
    const scaled = await Promise.all(frames.map(async (frame) => resized(frame, size)));
    return sharp(scaled, { join: { animated: true } })
        .webp({ delay: scaled.map(() => OUTPUT_FRAME_MS), loop: timeline.loop ? ENDLESS : ONCE, quality: WEBP_QUALITY })
        .toBuffer();
};
```
