radames commited on
Commit
809d458
1 Parent(s): 9bf0296

txt2img and inpainting

Browse files
frontend/src/lib/App.svelte CHANGED
@@ -17,7 +17,8 @@
17
  isPrompting,
18
  clickedPosition,
19
  imagesList,
20
- showFrames
 
21
  } from '$lib/store';
22
  import { base64ToBlob, uploadImage } from '$lib/utils';
23
  /**
@@ -26,6 +27,10 @@
26
  */
27
 
28
  export let room: Room;
 
 
 
 
29
  onMount(() => {});
30
 
31
  async function onClose(e: CustomEvent) {
@@ -37,22 +42,91 @@
37
  $isPrompting = false;
38
  console.log('prompt', prompt, imgURLs);
39
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
40
  async function generateImage(_prompt: string) {
 
 
41
  if (!_prompt || $isLoading == true) return;
42
  $loadingState = 'Pending';
43
  $isLoading = true;
44
  const sessionHash = crypto.randomUUID();
45
-
46
  const payload = {
47
  fn_index: 0,
48
  data: [
49
- null,
50
- //{ mask: null, image: null },
51
  _prompt,
52
- true
53
  ],
54
  session_hash: sessionHash
55
  };
 
 
56
  const websocket = new WebSocket(PUBLIC_WS_INPAINTING);
57
  // websocket.onopen = async function (event) {
58
  // websocket.send(JSON.stringify({ hash: sessionHash }));
@@ -127,8 +201,13 @@
127
  {#if $isPrompting}
128
  <PromptModal on:prompt={onPrompt} on:close={onClose} />
129
  {/if}
 
 
 
 
 
130
  <div class="fixed top-0 left-0 z-0 w-screen h-screen">
131
- <Canvas />
132
 
133
  <main class="z-10 relative">
134
  {#if $imagesList && $showFrames}
@@ -174,6 +253,7 @@
174
  {/if}
175
  </main>
176
  </div>
 
177
  <div class="fixed bottom-0 left-0 right-0 z-10 my-2">
178
  <Menu />
179
  </div>
 
17
  isPrompting,
18
  clickedPosition,
19
  imagesList,
20
+ showFrames,
21
+ text2img
22
  } from '$lib/store';
23
  import { base64ToBlob, uploadImage } from '$lib/utils';
24
  /**
 
27
  */
28
 
29
  export let room: Room;
30
+ let CA: HTMLCanvasElement;
31
+ let CB: HTMLCanvasElement;
32
+ let canvasEl: HTMLCanvasElement;
33
+
34
  onMount(() => {});
35
 
36
  async function onClose(e: CustomEvent) {
 
42
  $isPrompting = false;
43
  console.log('prompt', prompt, imgURLs);
44
  }
45
+ function getImageMask(cursor: { x: number; y: number }) {
46
+ const blackImage = document.createElement('canvas');
47
+ const canvasCrop = document.createElement('canvas');
48
+ const mask = document.createElement('canvas');
49
+
50
+ blackImage.width = 512;
51
+ blackImage.height = 512;
52
+ canvasCrop.width = 512;
53
+ canvasCrop.height = 512;
54
+ mask.width = 512;
55
+ mask.height = 512;
56
+
57
+ const blackImageCtx = blackImage.getContext('2d') as CanvasRenderingContext2D;
58
+ const ctxCrop = canvasCrop.getContext('2d') as CanvasRenderingContext2D;
59
+ const ctxMask = mask.getContext('2d') as CanvasRenderingContext2D;
60
+
61
+ // crop image from point canvas
62
+ ctxCrop.save();
63
+ ctxCrop.clearRect(0, 0, 512, 512);
64
+
65
+ const imageData = ctxCrop.getImageData(0, 0, 512, 512);
66
+ const pix = imageData.data;
67
+ for (let i = 0, n = pix.length; i < n; i += 4) {
68
+ pix[i] = Math.round(255 * Math.random());
69
+ pix[i + 1] = Math.round(255 * Math.random());
70
+ pix[i + 2] = Math.round(255 * Math.random());
71
+ pix[i + 3] = 255;
72
+ }
73
+ // ctxCrop.putImageData(imageData, 0, 0);
74
+ ctxCrop.globalCompositeOperation = 'source-over';
75
+ ctxCrop.drawImage(canvasEl, cursor.x, cursor.y, 512, 512, 0, 0, 512, 512);
76
+ ctxCrop.restore();
77
+
78
+ // create black image
79
+ blackImageCtx.fillStyle = 'black';
80
+ blackImageCtx.fillRect(0, 0, 512, 512);
81
+
82
+ // create Mask
83
+ ctxMask.save();
84
+ // ctxMask.clearRect(0, 0, 512, 512);
85
+ ctxMask.drawImage(canvasCrop, 0, 0, 512, 512);
86
+ ctxMask.globalCompositeOperation = 'source-in';
87
+ ctxMask.drawImage(blackImage, 0, 0);
88
+ ctxMask.restore();
89
+
90
+ const contextA = CA.getContext('2d') as CanvasRenderingContext2D;
91
+ const contextB = CB.getContext('2d') as CanvasRenderingContext2D;
92
+
93
+ // draw image to canvas A
94
+ contextA.save();
95
+ contextA.clearRect(0, 0, 512, 512);
96
+ contextA.drawImage(canvasCrop, 0, 0, 512, 512);
97
+ contextA.restore();
98
+
99
+ // draw mask to canvas B
100
+ contextB.save();
101
+ contextB.clearRect(0, 0, 512, 512);
102
+ contextB.drawImage(mask, 0, 0, 512, 512);
103
+ contextB.restore();
104
+
105
+ //convert canvas to base64
106
+ const base64Crop = canvasCrop.toDataURL('image/png');
107
+ const base64Mask = mask.toDataURL('image/png');
108
+ return { image: base64Crop, mask: base64Mask };
109
+ }
110
+
111
  async function generateImage(_prompt: string) {
112
+ // getImageMask($clickedPosition);
113
+ // return;
114
  if (!_prompt || $isLoading == true) return;
115
  $loadingState = 'Pending';
116
  $isLoading = true;
117
  const sessionHash = crypto.randomUUID();
 
118
  const payload = {
119
  fn_index: 0,
120
  data: [
121
+ $text2img ? null : getImageMask($clickedPosition),
122
+ // { mask: null, image: null },
123
  _prompt,
124
+ $text2img
125
  ],
126
  session_hash: sessionHash
127
  };
128
+ console.log('payload', payload);
129
+
130
  const websocket = new WebSocket(PUBLIC_WS_INPAINTING);
131
  // websocket.onopen = async function (event) {
132
  // websocket.send(JSON.stringify({ hash: sessionHash }));
 
201
  {#if $isPrompting}
202
  <PromptModal on:prompt={onPrompt} on:close={onClose} />
203
  {/if}
204
+
205
+ <div class="flex">
206
+ <canvas bind:this={CA} width="512" height="512" />
207
+ <canvas bind:this={CB} width="512" height="512" />
208
+ </div>
209
  <div class="fixed top-0 left-0 z-0 w-screen h-screen">
210
+ <Canvas bind:value={canvasEl} />
211
 
212
  <main class="z-10 relative">
213
  {#if $imagesList && $showFrames}
 
253
  {/if}
254
  </main>
255
  </div>
256
+
257
  <div class="fixed bottom-0 left-0 right-0 z-10 my-2">
258
  <Menu />
259
  </div>
frontend/src/lib/Canvas.svelte CHANGED
@@ -3,6 +3,7 @@
3
  import { select } from 'd3-selection';
4
  import { scaleLinear } from 'd3-scale';
5
  import { onMount } from 'svelte';
 
6
  import {
7
  currZoomTransform,
8
  myPresence,
@@ -15,6 +16,9 @@
15
  const width = 512 * 5;
16
 
17
  let canvasEl: HTMLCanvasElement;
 
 
 
18
  let containerEl: HTMLDivElement;
19
  let canvasCtx: CanvasRenderingContext2D;
20
  let xScale: (x: number) => number;
@@ -47,6 +51,7 @@
47
  .on('dblclick.zoom', () => {
48
  $isPrompting = true;
49
  $clickedPosition = $myPresence.cursor;
 
50
  return null;
51
  })
52
  // .call(zoomHandler.scaleTo as any, 1 / scale)
@@ -61,13 +66,13 @@
61
 
62
  function renderImages(imagesList) {
63
  imagesList.forEach(({ imgURL, position }) => {
64
- // console.log(item);
65
  const img = new Image();
66
  img.onload = () => {
67
- console.log(img);
68
  canvasCtx.drawImage(img, position.x, position.y, img.width, img.height);
69
  };
70
- img.src = imgURL;
 
 
71
  });
72
  }
73
 
 
3
  import { select } from 'd3-selection';
4
  import { scaleLinear } from 'd3-scale';
5
  import { onMount } from 'svelte';
6
+ import { dev } from '$app/environment';
7
  import {
8
  currZoomTransform,
9
  myPresence,
 
16
  const width = 512 * 5;
17
 
18
  let canvasEl: HTMLCanvasElement;
19
+ export { canvasEl as value };
20
+ let value = canvasEl;
21
+
22
  let containerEl: HTMLDivElement;
23
  let canvasCtx: CanvasRenderingContext2D;
24
  let xScale: (x: number) => number;
 
51
  .on('dblclick.zoom', () => {
52
  $isPrompting = true;
53
  $clickedPosition = $myPresence.cursor;
54
+ console.log('clicked', $clickedPosition);
55
  return null;
56
  })
57
  // .call(zoomHandler.scaleTo as any, 1 / scale)
 
66
 
67
  function renderImages(imagesList) {
68
  imagesList.forEach(({ imgURL, position }) => {
 
69
  const img = new Image();
70
  img.onload = () => {
 
71
  canvasCtx.drawImage(img, position.x, position.y, img.width, img.height);
72
  };
73
+ const base = dev ? 'uploads/' : '';
74
+ const url = imgURL.split('/');
75
+ img.src = dev ? `uploads/${url.slice(3).join('/')}` : imgURL;
76
  });
77
  }
78
 
frontend/src/lib/Menu.svelte CHANGED
@@ -1,8 +1,8 @@
1
  <script lang="ts">
2
- import { showFrames } from '$lib/store';
3
  </script>
4
 
5
- <div class="grid grid-cols-3 gap-3 text-sm w-max mx-auto">
6
  <div class="flex items-center">
7
  <input
8
  id="showframes"
@@ -14,6 +14,17 @@
14
  >Show Frames</label
15
  >
16
  </div>
 
 
 
 
 
 
 
 
 
 
 
17
  <button class="button" title="Add Prompt"> Add Prompt </button>
18
  <button class="button-paint bg-violet-100 text-violet-900" title="New Paint Frame">
19
  <span
 
1
  <script lang="ts">
2
+ import { showFrames, text2img } from '$lib/store';
3
  </script>
4
 
5
+ <div class="grid grid-cols-4 gap-3 text-sm w-max mx-auto">
6
  <div class="flex items-center">
7
  <input
8
  id="showframes"
 
14
  >Show Frames</label
15
  >
16
  </div>
17
+ <div class="flex items-center">
18
+ <input
19
+ id="txt2img"
20
+ type="checkbox"
21
+ bind:checked={$text2img}
22
+ class="w-4 h-4 text-blue-600 bg-gray-100 rounded border-gray-300 focus:ring-blue-500 dark:focus:ring-blue-600 dark:ring-offset-gray-800 focus:ring-2 dark:bg-gray-700 dark:border-gray-600 cursor-pointer"
23
+ />
24
+ <label for="txt2img" class="text-black dark:text-white cursor-pointer ml-2"
25
+ >Text2Image</label
26
+ >
27
+ </div>
28
  <button class="button" title="Add Prompt"> Add Prompt </button>
29
  <button class="button-paint bg-violet-100 text-violet-900" title="New Paint Frame">
30
  <span
frontend/src/lib/store.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { writable, get } from 'svelte/store';
2
  import type { Room } from '@liveblocks/client';
3
 
4
  import { type ZoomTransform, zoomIdentity } from 'd3-zoom';
@@ -8,6 +8,7 @@ export const isLoading = writable<boolean>(false);
8
  export const isPrompting = writable<boolean>(false);
9
  export const clickedPosition = writable<{ x: number; y: number }>();
10
  export const showFrames = writable<boolean>(false);
 
11
 
12
  export const currZoomTransform = writable<ZoomTransform>(zoomIdentity);
13
 
 
1
+ import { writable } from 'svelte/store';
2
  import type { Room } from '@liveblocks/client';
3
 
4
  import { type ZoomTransform, zoomIdentity } from 'd3-zoom';
 
8
  export const isPrompting = writable<boolean>(false);
9
  export const clickedPosition = writable<{ x: number; y: number }>();
10
  export const showFrames = writable<boolean>(false);
11
+ export const text2img = writable<boolean>(true);
12
 
13
  export const currZoomTransform = writable<ZoomTransform>(zoomIdentity);
14
 
frontend/vite.config.dev.ts CHANGED
@@ -11,9 +11,14 @@ const config: UserConfig = {
11
  changeOrigin: true,
12
  cookieDomainRewrite: 'localhost',
13
  rewrite: (path) => path.replace(/^\/moon/, '')
 
 
 
 
 
 
14
  }
15
  }
16
  }
17
  };
18
-
19
  export default config;
 
11
  changeOrigin: true,
12
  cookieDomainRewrite: 'localhost',
13
  rewrite: (path) => path.replace(/^\/moon/, '')
14
+ },
15
+ '/uploads': {
16
+ target: 'https://s3.amazonaws.com',
17
+ changeOrigin: true,
18
+ cookieDomainRewrite: 'localhost',
19
+ rewrite: (path) => path.replace(/^\/uploads/, '')
20
  }
21
  }
22
  }
23
  };
 
24
  export default config;