aboutsummaryrefslogtreecommitdiff
path: root/src/client/views/nodes/generativeFill/generativeFillUtils/ImageHandler.ts
blob: 48055903c3a5ee8a80ff9e40431e0d73088d0bec (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
import { RefObject } from 'react';
import { canvasSize } from './generativeFillConstants';

export interface APISuccess {
    status: 'success';
    urls: string[];
}

export interface APIError {
    status: 'error';
    message: string;
}

export class ImageUtility {
    static canvasToBlob = (canvas: HTMLCanvasElement): Promise<Blob> => {
        return new Promise(resolve => {
            canvas.toBlob(blob => {
                if (blob) {
                    resolve(blob);
                }
            }, 'image/png');
        });
    };

    static getEdit = async (imgBlob: Blob, maskBlob: Blob, prompt: string, n?: number): Promise<APISuccess | APIError> => {
        const apiUrl = 'https://api.openai.com/v1/images/edits';
        const fd = new FormData();
        fd.append('image', imgBlob, 'image.png');
        fd.append('mask', maskBlob, 'mask.png');
        fd.append('prompt', prompt);
        fd.append('size', '1024x1024');
        fd.append('n', n ? JSON.stringify(n) : '1');
        fd.append('response_format', 'b64_json');

        try {
            const res = await fetch(apiUrl, {
                method: 'POST',
                headers: {
                    Authorization: `Bearer ${process.env.OPENAI_KEY}`,
                },
                body: fd,
            });
            const data = await res.json();
            console.log(data.data);
            return {
                status: 'success',
                urls: (data.data as { b64_json: string }[]).map(data => `data:image/png;base64,${data.b64_json}`),
            };
        } catch (err) {
            console.log(err);
            return { status: 'error', message: 'API error.' };
        }
    };

    static mockGetEdit = async (mockSrc: string): Promise<APISuccess | APIError> => {
        return {
            status: 'success',
            urls: [mockSrc, mockSrc, mockSrc],
        };
    };

    static getCanvasContext = (canvasRef: RefObject<HTMLCanvasElement>): CanvasRenderingContext2D | null => {
        if (!canvasRef.current) return null;
        const ctx = canvasRef.current.getContext('2d');
        if (!ctx) return null;
        return ctx;
    };

    static downloadCanvas = (canvas: HTMLCanvasElement) => {
        const url = canvas.toDataURL();
        const downloadLink = document.createElement('a');
        downloadLink.href = url;
        downloadLink.download = 'canvas';

        downloadLink.click();
        downloadLink.remove();
    };

    static downloadImageCanvas = (imgUrl: string) => {
        const img = new Image();
        img.src = imgUrl;
        img.onload = () => {
            const canvas = document.createElement('canvas');
            canvas.width = canvasSize;
            canvas.height = canvasSize;
            const ctx = canvas.getContext('2d');
            ctx?.drawImage(img, 0, 0, canvasSize, canvasSize);

            this.downloadCanvas(canvas);
        };
    };

    static drawImgToCanvas = (img: HTMLImageElement, canvasRef: React.RefObject<HTMLCanvasElement>, loaded?: boolean) => {
        if (loaded) {
            const ctx = this.getCanvasContext(canvasRef);
            if (!ctx) return;
            ctx.globalCompositeOperation = 'source-over';
            const scale = Math.max(canvasSize / img.width, canvasSize / img.height);
            const width = img.width * scale;
            const height = img.height * scale;
            ctx.clearRect(0, 0, canvasSize, canvasSize);
            ctx.drawImage(img, 0, 0, width, height);
        } else {
            img.onload = () => {
                const ctx = this.getCanvasContext(canvasRef);
                if (!ctx) return;
                ctx.globalCompositeOperation = 'source-over';
                const scale = Math.max(canvasSize / img.width, canvasSize / img.height);
                const width = img.width * scale;
                const height = img.height * scale;
                ctx.clearRect(0, 0, canvasSize, canvasSize);
                ctx.drawImage(img, 0, 0, width, height);
            };
        }
    };

    // The image must be loaded!
    static getCanvasImg = (img: HTMLImageElement): HTMLCanvasElement => {
        const canvas = document.createElement('canvas');
        canvas.width = canvasSize;
        canvas.height = canvasSize;
        const ctx = canvas.getContext('2d');
        ctx?.clearRect(0, 0, canvasSize, canvasSize);
        ctx?.drawImage(img, 0, 0, canvasSize, canvasSize);

        return canvas;
    };
}