The code imports modules for interacting with the file system, working with file paths, and making HTTP requests. It defines a function doImage2Image
that takes an image and a prompt, processes the image, makes a POST request to generate an image, and returns the seed and generated image.
npm run import -- "image 2 image"
const fs = require('fs')
const path = require('path')
const {request} = require('gaxios')
const OUTPUT_PATH = path.join(process.env.HOME || process.env.HOMEPATH || process.env.USERPROFILE, 'stable-diffusion-webui/outputs')
async function doImage2Image(image, prompt) {
let width = 1024
if(prompt.includes('View360')) {
width = 2048
}
let base64_image
if(typeof image == 'string') {
if(image.startsWith('data:image/'))
image = image.replace(/^data:image\/.*?;base64,/gi, '')
if(image.includes('://')) {
let result = await request({
url: image,
method: 'GET',
})
base64_image = Buffer.from(await result.data.arrayBuffer()).toString('base64')
} else if (!fs.existsSync(image)) {
base64_image = Buffer.from(image, 'base64').toString('base64')
} else {
base64_image = fs.readFileSync(image).toString('base64')
}
} else {
base64_image = image.toString('base64')
}
try {
let result = await request({
url: 'http://127.0.0.1:7860/sdapi/v1/img2img',
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
data: JSON.stringify({
prompt: prompt,
negative_prompt: 'bad hands, bad feet, bad faces, bad eyes, bad anatomy, extra limbs, missing limbs, tattoo, statue, picture frame, anime, cartoon, signature, abstract',
save_images: true,
"width": width,
"height": 1024,
"steps": 30,
tiling: false,
init_images: [base64_image],
})
})
let seed = JSON.parse(result.data.info).seed
let buff = Buffer.from(result.data.images[0], 'base64');
let now = new Date()
let folderName = now.getFullYear() + '-' + String(now.getMonth() + 1).padStart(2, '0') + '-' + String(now.getDate()).padStart(2, '0')
let stablePath = path.join(OUTPUT_PATH, 'img2img-images', folderName)
let imagePath
if(fs.existsSync(stablePath)) {
let images = fs.readdirSync(stablePath)
for(let i = 0; i < images.length; i++) {
if(images[i].match('-' + seed + '-')) {
imagePath = path.join('img2img-images', folderName, images[i])
break
}
}
}
return {seed, image: buff, imagePath, prompt}
} catch (e) {
console.error(e)
}
}
module.exports = {
doImage2Image,
OUTPUT_PATH
}
const gaxios = require('gaxios');
const fs = require('fs');
const path = require('path');
const OUTPUT_PATH = process.env.HOME
? path.join(process.env.HOME,'stable-diffusion-webui/outputs')
: process.env.HOMEPATH
? path.join(process.env.HOMEPATH,'stable-diffusion-webui/outputs')
: process.env.USERPROFILE
? path.join(process.env.USERPROFILE,'stable-diffusion-webui/outputs')
: './outputs';
async function doImage2Image(image, prompt) {
try {
const width = getPreferredWidth(prompt);
const base64Image = await getImageData(image);
const result = await sendImageData(base64Image, prompt);
const { seed, imagePath } = await processResult(result, width);
return { seed, image: result.data.images[0], imagePath, prompt };
} catch (error) {
console.error(error);
}
}
/**
* Returns the preferred width based on the prompt.
* @param {string} prompt
* @returns {number}
*/
function getPreferredWidth(prompt) {
return prompt.includes('View360')? 2048 : 1024;
}
/**
* Retrieves the image data from the provided image.
* @param {string} image
* @returns {Promise<string>}
*/
async function getImageData(image) {
if (typeof image ==='string' && image.startsWith('data:image/')) {
image = image.replace(/^data:image\/.*?;base64,/gi, '');
}
if (image.includes('://')) {
const response = await gaxios.request({
url: image,
method: 'GET',
});
return Buffer.from(await response.data.arrayBuffer()).toString('base64');
} else if (!fs.existsSync(image)) {
return image;
} else {
return fs.readFileSync(image).toString('base64');
}
}
/**
* Sends the image data to the SD API.
* @param {string} base64Image
* @param {string} prompt
* @returns {Promise<Object>}
*/
async function sendImageData(base64Image, prompt) {
const response = await gaxios.request({
url: 'http://127.0.0.1:7860/sdapi/v1/img2img',
method: 'POST',
headers: { 'Content-Type': 'application/json' },
data: JSON.stringify({
prompt,
negative_prompt: 'bad hands, bad feet, bad faces, bad eyes, bad anatomy, extra limbs, missing limbs, tattoo, statue, picture frame, anime, cartoon, signature, abstract',
save_images: true,
width: getPreferredWidth(prompt),
height: 1024,
steps: 30,
tiling: false,
init_images: [base64Image],
}),
});
return response.data;
}
/**
* Processes the result from the SD API.
* @param {Object} result
* @param {number} width
* @returns {Promise<{ seed: string, imagePath: string }>}
*/
async function processResult(result, width) {
const seed = JSON.parse(result.info).seed;
const buff = Buffer.from(result.images[0], 'base64');
const now = new Date();
const folderName = `${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, '0')}-${String(now.getDate()).padStart(2, '0')}`;
const stablePath = path.join(OUTPUT_PATH, 'img2img-images', folderName);
let imagePath;
if (fs.existsSync(stablePath)) {
const images = fs.readdirSync(stablePath);
for (let i = 0; i < images.length; i++) {
if (images[i].match(`-${seed}-`)) {
imagePath = path.join('img2img-images', folderName, images[i]);
break;
}
}
}
return { seed, imagePath };
}
module.exports = {
doImage2Image,
OUTPUT_PATH,
};
Breakdown of the code
The code starts by importing three modules:
fs
(File System): for interacting with the file systempath
: for working with file pathsgaxios
(Google HTTP client): for making HTTP requestsOUTPUT_PATH
: the path where generated images will be stored, set to stable-diffusion-webui/outputs
in the user's home directorydoImage2Image
FunctionThis is an asynchronous function that takes two arguments:
image
: the input image, which can be a string, a Buffer, or a URLprompt
: the prompt for the image generationThe function processes the input image
as follows:
image
is a string, it checks if it's a base64-encoded image. If not, it attempts to download the image from the URL if it's a valid URL.image
is a Buffer or a string representing a base64-encoded image, it converts it to a base64-encoded stringimage
is a URL, it downloads the image using gaxios
and converts it to a base64-encoded stringThe function makes a POST request to http://127.0.0.1:7860/sdapi/v1/img2img
with the following data:
prompt
: the prompt for the image generationnegative_prompt
: a string of negative promptssave_images
: a boolean indicating whether to save the generated imageswidth
and height
: the dimensions of the generated imagesteps
: the number of steps for the image generationtiling
: a boolean indicating whether to use tilinginit_images
: an array containing the base64-encoded input imageThe response from the server is parsed to extract the seed and the generated image.