File size: 7,827 Bytes
5fe33ce
 
 
 
 
 
 
 
 
 
 
 
d6e25c0
 
 
 
 
 
5fe33ce
 
 
d6e25c0
5fe33ce
d6e25c0
5fe33ce
 
 
 
 
 
 
 
 
 
 
 
 
d6e25c0
 
 
 
 
 
 
5fe33ce
 
 
d6e25c0
5fe33ce
 
 
 
d6e25c0
5fe33ce
 
 
 
 
 
 
 
 
 
 
 
 
 
d6e25c0
5fe33ce
 
 
 
 
 
 
 
 
2b51741
 
5fe33ce
 
 
 
 
 
 
d6e25c0
 
 
 
 
 
5fe33ce
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
d6e25c0
 
 
 
 
 
5fe33ce
 
cbd4321
5fe33ce
 
 
 
 
2b51741
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
class ImageGenerator {
    constructor() {
        this.baseURL = 'https://soiz-flux-1-dev-serverless.hf.space/generate';
        this.prompt = '';
        this.negativePrompt = '';
        this.width = 512;
        this.height = 512;
        this.steps = 25;
        this.cfgs = 7;
        this.sampler = 'DPM++ 2M';
        this.strength = 0.7;
        this.seed = -1;
        this.guidanceScale = 7.5;
        this.numReturnSequences = 1;
        this.temperature = 1.0;
        this.topK = 50;
        this.topP = 0.9;
        this.eta = 0.1;
        this.returnType = 'dataURL'; // dataURL or blobURL
    }

    // Generate URL for fetching
    generateFetchURL() {
        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}&guidance_scale=${this.guidanceScale}&num_return_sequences=${this.numReturnSequences}&temperature=${this.temperature}&top_k=${this.topK}&top_p=${this.topP}&eta=${this.eta}`;
    }

    // Return parameters as JSON for debugging
    getParametersAsJSON() {
        return JSON.stringify({
            prompt: this.prompt,
            negativePrompt: this.negativePrompt,
            width: this.width,
            height: this.height,
            steps: this.steps,
            cfgs: this.cfgs,
            sampler: this.sampler,
            strength: this.strength,
            seed: this.seed,
            guidanceScale: this.guidanceScale,
            numReturnSequences: this.numReturnSequences,
            temperature: this.temperature,
            topK: this.topK,
            topP: this.topP,
            eta: this.eta
        });
    }

    // Fetch function to generate the image
    async fetchImage() {
        const url = this.generateFetchURL();
        try {
            const response = await fetch(url);
            if (!response.ok) throw new Error('Failed to generate image');

            const blob = await response.blob();
            if (this.returnType === 'blobURL') {
                return URL.createObjectURL(blob);
            } else {
                // Convert Blob to Data URL
                return await new Promise((resolve, reject) => {
                    const reader = new FileReader();
                    reader.onloadend = () => resolve(reader.result);
                    reader.onerror = reject;
                    reader.readAsDataURL(blob);
                });
            }
        } catch (error) {
            console.error(error);
            throw new Error('Error generating image: ' + error.message);
        }
    }

    getInfo() {
        return {
            id: 'imageGenerator',
            name: 'Image Generator',
            blocks: [
                { opcode: 'setPrompt', blockType: Scratch.BlockType.COMMAND, text: 'set prompt to [TEXT]', arguments: { TEXT: { type: Scratch.ArgumentType.STRING, defaultValue: '1girl, halo, white wings, white sundress, angel, blue sky, blonde hair, blue eyes, long hair, dynamic angle' } } },
                { opcode: 'setNegativePrompt', blockType: Scratch.BlockType.COMMAND, text: 'set negative prompt to [TEXT]', arguments: { TEXT: { type: Scratch.ArgumentType.STRING, defaultValue: 'anatomically bad, low quality, old, 1900s, 1800s, bad anatomically, many fingers, deformed feet, deformed fingers, deformed face , deformed eyes, blurry eyes, blurry, old quality' } } },
                { opcode: 'setWidth', blockType: Scratch.BlockType.COMMAND, text: 'set width to [NUM]', arguments: { NUM: { type: Scratch.ArgumentType.NUMBER, defaultValue: 512 } } },
                { opcode: 'setHeight', blockType: Scratch.BlockType.COMMAND, text: 'set height to [NUM]', arguments: { NUM: { type: Scratch.ArgumentType.NUMBER, defaultValue: 512 } } },
                { opcode: 'setSteps', blockType: Scratch.BlockType.COMMAND, text: 'set steps to [NUM]', arguments: { NUM: { type: Scratch.ArgumentType.NUMBER, defaultValue: 25 } } },
                { opcode: 'setCfgScale', blockType: Scratch.BlockType.COMMAND, text: 'set CFG Scale to [NUM]', arguments: { NUM: { type: Scratch.ArgumentType.NUMBER, defaultValue: 7 } } },
                { opcode: 'setSampler', blockType: Scratch.BlockType.COMMAND, text: 'set sampler to [TEXT]', arguments: { TEXT: { type: Scratch.ArgumentType.STRING, defaultValue: 'DPM++ 2M' } } },
                { opcode: 'setStrength', blockType: Scratch.BlockType.COMMAND, text: 'set strength to [NUM]', arguments: { NUM: { type: Scratch.ArgumentType.NUMBER, defaultValue: 0.7 } } },
                { opcode: 'setSeed', blockType: Scratch.BlockType.COMMAND, text: 'set seed to [NUM]', arguments: { NUM: { type: Scratch.ArgumentType.NUMBER, defaultValue: -1 } } },
                { opcode: 'setGuidanceScale', blockType: Scratch.BlockType.COMMAND, text: 'set guidance scale to [NUM]', arguments: { NUM: { type: Scratch.ArgumentType.NUMBER, defaultValue: 7.5 } } },
                { opcode: 'setNumReturnSequences', blockType: Scratch.BlockType.COMMAND, text: 'set number of return sequences to [NUM]', arguments: { NUM: { type: Scratch.ArgumentType.NUMBER, defaultValue: 1 } } },
                { opcode: 'setTemperature', blockType: Scratch.BlockType.COMMAND, text: 'set temperature to [NUM]', arguments: { NUM: { type: Scratch.ArgumentType.NUMBER, defaultValue: 1.0 } } },
                { opcode: 'setTopK', blockType: Scratch.BlockType.COMMAND, text: 'set top K to [NUM]', arguments: { NUM: { type: Scratch.ArgumentType.NUMBER, defaultValue: 50 } } },
                { opcode: 'setTopP', blockType: Scratch.BlockType.COMMAND, text: 'set top P to [NUM]', arguments: { NUM: { type: Scratch.ArgumentType.NUMBER, defaultValue: 0.9 } } },
                { opcode: 'setEta', blockType: Scratch.BlockType.COMMAND, text: 'set eta to [NUM]', arguments: { NUM: { type: Scratch.ArgumentType.NUMBER, defaultValue: 0.1 } } },
                { opcode: 'setReturnType', blockType: Scratch.BlockType.COMMAND, text: 'set return type to [TYPE]', arguments: { TYPE: { type: Scratch.ArgumentType.STRING, menu: 'returnTypes', defaultValue: 'dataURL' } } },
                { opcode: 'generateImage', blockType: Scratch.BlockType.REPORTER, text: 'generate image' },
                { opcode: 'getFetchURL', blockType: Scratch.BlockType.REPORTER, text: 'get fetch URL' },
                { opcode: 'getParametersJSON', blockType: Scratch.BlockType.REPORTER, text: 'get parameters as JSON' }
            ],
            menus: {
                returnTypes: { acceptReporters: true, items: ['dataURL', 'blobURL'] }
            }
        };
    }

    // Block functions
    setPrompt(args) { this.prompt = args.TEXT; }
    setNegativePrompt(args) { this.negativePrompt = args.TEXT; }
    setWidth(args) { this.width = args.NUM; }
    setHeight(args) { this.height = args.NUM; }
    setSteps(args) { this.steps = args.NUM; }
    setCfgScale(args) { this.cfgs = args.NUM; }
    setSampler(args) { this.sampler = args.TEXT; }
    setStrength(args) { this.strength = args.NUM; }
    setSeed(args) { this.seed = args.NUM; }
    setGuidanceScale(args) { this.guidanceScale = args.NUM; }
    setNumReturnSequences(args) { this.numReturnSequences = args.NUM; }
    setTemperature(args) { this.temperature = args.NUM; }
    setTopK(args) { this.topK = args.NUM; }
    setTopP(args) { this.topP = args.NUM; }
    setEta(args) { this.eta = args.NUM; }
    setReturnType(args) { this.returnType = args.TYPE; }

    async generateImage() { return this.fetchImage(); }
    getFetchURL() { return this.generateFetchURL(); }
    getParametersJSON() { return this.getParametersAsJSON(); }
}

// Register the extension
Scratch.extensions.register(new ImageGenerator());