Spaces:
Running
Running
Create imgen.js
Browse files
imgen.js
ADDED
@@ -0,0 +1,104 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
class ImageGenerator {
|
2 |
+
constructor() {
|
3 |
+
this.baseURL = 'https://soiz-flux-1-dev-serverless.hf.space/generate';
|
4 |
+
this.prompt = '';
|
5 |
+
this.negativePrompt = '';
|
6 |
+
this.width = 512;
|
7 |
+
this.height = 512;
|
8 |
+
this.steps = 25;
|
9 |
+
this.cfgs = 7;
|
10 |
+
this.sampler = 'DPM++ 2M';
|
11 |
+
this.strength = 0.7;
|
12 |
+
this.seed = -1;
|
13 |
+
this.returnType = 'dataURL'; // dataURL or blobURL
|
14 |
+
}
|
15 |
+
|
16 |
+
// Generate URL for fetching
|
17 |
+
generateFetchURL() {
|
18 |
+
return `${this.baseURL}?prompt=${encodeURIComponent(this.prompt)}&negative_prompt=${encodeURIComponent(this.negativePrompt)}&width=${this.width}&height=${this.height}&steps=${this.steps}&cfgs=${this.cfgs}&sampler=${encodeURIComponent(this.sampler)}&strength=${this.strength}&seed=${this.seed}`;
|
19 |
+
}
|
20 |
+
|
21 |
+
// Return parameters as JSON for debugging
|
22 |
+
getParametersAsJSON() {
|
23 |
+
return JSON.stringify({
|
24 |
+
prompt: this.prompt,
|
25 |
+
negativePrompt: this.negativePrompt,
|
26 |
+
width: this.width,
|
27 |
+
height: this.height,
|
28 |
+
steps: this.steps,
|
29 |
+
cfgs: this.cfgs,
|
30 |
+
sampler: this.sampler,
|
31 |
+
strength: this.strength,
|
32 |
+
seed: this.seed
|
33 |
+
});
|
34 |
+
}
|
35 |
+
|
36 |
+
// Fetch function to generate the image
|
37 |
+
async fetchImage() {
|
38 |
+
const url = this.generateFetchURL();
|
39 |
+
try {
|
40 |
+
const response = await fetch(url);
|
41 |
+
if (!response.ok) throw new Error('Failed to generate image');
|
42 |
+
|
43 |
+
const blob = await response.blob();
|
44 |
+
if (this.returnType === 'blobURL') {
|
45 |
+
return URL.createObjectURL(blob);
|
46 |
+
} else {
|
47 |
+
// Convert Blob to Data URL
|
48 |
+
return await new Promise((resolve, reject) => {
|
49 |
+
const reader = new FileReader();
|
50 |
+
reader.onloadend = () => resolve(reader.result);
|
51 |
+
reader.onerror = reject;
|
52 |
+
reader.readAsDataURL(blob);
|
53 |
+
});
|
54 |
+
}
|
55 |
+
} catch (error) {
|
56 |
+
console.error(error);
|
57 |
+
throw new Error('Error generating image: ' + error.message);
|
58 |
+
}
|
59 |
+
}
|
60 |
+
|
61 |
+
getInfo() {
|
62 |
+
return {
|
63 |
+
id: 'imageGenerator',
|
64 |
+
name: 'Image Generator',
|
65 |
+
blocks: [
|
66 |
+
{ opcode: 'setPrompt', blockType: Scratch.BlockType.COMMAND, text: 'set prompt to [TEXT]', arguments: { TEXT: { type: Scratch.ArgumentType.STRING, defaultValue: '1girl, halo, white wings, blue sky' } } },
|
67 |
+
{ opcode: 'setNegativePrompt', blockType: Scratch.BlockType.COMMAND, text: 'set negative prompt to [TEXT]', arguments: { TEXT: { type: Scratch.ArgumentType.STRING, defaultValue: 'blurry, low quality' } } },
|
68 |
+
{ opcode: 'setWidth', blockType: Scratch.BlockType.COMMAND, text: 'set width to [NUM]', arguments: { NUM: { type: Scratch.ArgumentType.NUMBER, defaultValue: 512 } } },
|
69 |
+
{ opcode: 'setHeight', blockType: Scratch.BlockType.COMMAND, text: 'set height to [NUM]', arguments: { NUM: { type: Scratch.ArgumentType.NUMBER, defaultValue: 512 } } },
|
70 |
+
{ opcode: 'setSteps', blockType: Scratch.BlockType.COMMAND, text: 'set steps to [NUM]', arguments: { NUM: { type: Scratch.ArgumentType.NUMBER, defaultValue: 25 } } },
|
71 |
+
{ opcode: 'setCfgScale', blockType: Scratch.BlockType.COMMAND, text: 'set CFG Scale to [NUM]', arguments: { NUM: { type: Scratch.ArgumentType.NUMBER, defaultValue: 7 } } },
|
72 |
+
{ opcode: 'setSampler', blockType: Scratch.BlockType.COMMAND, text: 'set sampler to [TEXT]', arguments: { TEXT: { type: Scratch.ArgumentType.STRING, defaultValue: 'DPM++ 2M' } } },
|
73 |
+
{ opcode: 'setStrength', blockType: Scratch.BlockType.COMMAND, text: 'set strength to [NUM]', arguments: { NUM: { type: Scratch.ArgumentType.NUMBER, defaultValue: 0.7 } } },
|
74 |
+
{ opcode: 'setSeed', blockType: Scratch.BlockType.COMMAND, text: 'set seed to [NUM]', arguments: { NUM: { type: Scratch.ArgumentType.NUMBER, defaultValue: -1 } } },
|
75 |
+
{ opcode: 'setReturnType', blockType: Scratch.BlockType.COMMAND, text: 'set return type to [TYPE]', arguments: { TYPE: { type: Scratch.ArgumentType.STRING, menu: 'returnTypes', defaultValue: 'dataURL' } } },
|
76 |
+
{ opcode: 'generateImage', blockType: Scratch.BlockType.REPORTER, text: 'generate image' },
|
77 |
+
{ opcode: 'getFetchURL', blockType: Scratch.BlockType.REPORTER, text: 'get fetch URL' },
|
78 |
+
{ opcode: 'getParametersJSON', blockType: Scratch.BlockType.REPORTER, text: 'get parameters as JSON' }
|
79 |
+
],
|
80 |
+
menus: {
|
81 |
+
returnTypes: { acceptReporters: true, items: ['dataURL', 'blobURL'] }
|
82 |
+
}
|
83 |
+
};
|
84 |
+
}
|
85 |
+
|
86 |
+
// Block functions
|
87 |
+
setPrompt(args) { this.prompt = args.TEXT; }
|
88 |
+
setNegativePrompt(args) { this.negativePrompt = args.TEXT; }
|
89 |
+
setWidth(args) { this.width = args.NUM; }
|
90 |
+
setHeight(args) { this.height = args.NUM; }
|
91 |
+
setSteps(args) { this.steps = args.NUM; }
|
92 |
+
setCfgScale(args) { this.cfgs = args.NUM; }
|
93 |
+
setSampler(args) { this.sampler = args.TEXT; }
|
94 |
+
setStrength(args) { this.strength = args.NUM; }
|
95 |
+
setSeed(args) { this.seed = args.NUM; }
|
96 |
+
setReturnType(args) { this.returnType = args.TYPE; }
|
97 |
+
|
98 |
+
generateImage() { return this.fetchImage(); }
|
99 |
+
getFetchURL() { return this.generateFetchURL(); }
|
100 |
+
getParametersJSON() { return this.getParametersAsJSON(); }
|
101 |
+
}
|
102 |
+
|
103 |
+
// Register the extension
|
104 |
+
Scratch.extensions.register(new ImageGenerator());
|