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
129
130
|
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', '512x512');
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 {
console.log('loading image');
img.onload = () => {
console.log('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);
};
}
};
// 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;
};
}
|