AImage Creator

Settings

name

AImage Creator

description

Pick between images relevant to your note's content

icon

add_photo_alternate

setting

API Key

setting

Image size (default is 512, can be 256 or 1024)

setting

Images generated per prompt (default 3, more images = longer response time)

instructions

Notice: This plugin is deprecated by its author. Its functionality now exists within the generic AmpleAI plugin.

Setting up AImage Creator

0. Install the plugin
1. Open the plugin settings and paste the OpenAI key you have generated
2. If you want higher res pics, enter "1024" into the "Image size" field, otherwise you'll get images that look like the defaults shown below.

Using this plugin
Installing this plugin allows a user to quickly generate and insert images into their notes. Since OpenAI has yet to claim any copyright on generated AI images, this plugin can greatly expedite content creation for those who have previously used stock image libraries. It can probably also be useful to help documenters, wiki creators, and writers in general.

There are currently three ways to invoke it:
1. Expression operator {AImage Creator: from preceding} will, by default, give you three options of 512x512 images that pertain to the previous paragraph (either earlier on the same line, or on a previous line)
2. Expression operator {AImage Creator: via prompt} will pop up an input for you to enter a prompt to generate some images
3. Note option Summary image will send the content of the note to OpenAI's image generator and see what happens 🎭

Example
Adopt a lab puppy {AImage Creator: from preceding}


It does that sort of thing, and also this sort of thing




"I don't always create images, but when I do, I prefer AImage Creator"

{
// --------------------------------------------------------------------------------------
constants: {
corsProxy: "https://wispy-darkness-7716.amplenote.workers.dev", // Only proxies whitelisted image generation domain & folder
generatedImageCount: app => (app.settings["Images generated per prompt (default 3, more images = longer response time)"]?.trim() || 3),
imageSize: app => (app.settings["Image size (default is 512, can be 256 or 1024)"]?.trim() || 512),
pluginName: "AImage Creator",
},
 
// --------------------------------------------------------------------------------------
insertText: {
"from preceding": async function (app) {
if (this._stopForApiKey(app)) return;
const note = await app.notes.find(app.context.noteUUID);
const noteContent = await note.content();
const promptIndex = noteContent.indexOf(`{${ this.constants.pluginName }: from preceding}`);
const precedingContent = noteContent.substring(0, promptIndex).trim();
const prompt = precedingContent.split("\n").pop();
console.log("Deduced prompt", prompt);
if (prompt?.trim()) {
const markdown = await this._imageMarkdownFromPrompt(app, prompt.trim(), { note });
if (markdown) {
app.context.replaceSelection(markdown);
}
} else {
app.alert("Could not determine preceding text to use as a prompt");
}
},
"via prompt": async function (app) {
if (this._stopForApiKey(app)) return;
const instruction = await app.prompt("What would you like to generate images of?");
if (!instruction) return;
const markdown = await this._imageMarkdownFromPrompt(app, instruction);
if (markdown) {
app.context.replaceSelection(markdown);
}
}
},
 
// --------------------------------------------------------------------------------------
// https://www.amplenote.com/help/developing_amplenote_plugins#noteOption
noteOption: {
"summary image": async function (app, noteUUID) {
if (this._stopForApiKey(app)) return;
const note = await app.notes.find(noteUUID);
const noteContent = await note.content();
const markdown = await this._imageMarkdownFromPrompt(app, noteContent, { note });
if (markdown) {
note.insertContent(markdown);
}
},
},
 
// --------------------------------------------------------------------------------------
_stopForApiKey(app) {
if (app.settings["API Key"].trim()) {
return false;
} else {
app.alert("Please set your OpenAI API Key in the plugin settings");
return true;
}
},
 
// --------------------------------------------------------------------------------------
async _imageMarkdownFromPrompt(app, prompt, { note = null } = {}) {
// Aka "It's not *us* making this slow, fine developer friend"
console.log("C'mon OpenAI you can do it... request sent at", new Date())
// https://platform.openai.com/docs/guides/images/usage
const response = await fetch("https://api.openai.com/v1/images/generations", {
method: "POST",
headers: {
"Authorization": `Bearer ${ app.settings["API Key"].trim() }`,
"Content-Type": "application/json"
},
body: JSON.stringify({
prompt,
n: this.constants.generatedImageCount(app),
size: `${ this.constants.imageSize(app) }x${ this.constants.imageSize(app) }`,
})
});
const result = await response.json();
const { data } = result;
if (data?.length) {
const urls = data.map(d => d.url);
console.log("Received options", urls, "at", new Date());
const radioOptions = urls.map(url => ({ image: url, value: url }));
radioOptions.push({ label: "More options", value: "more" });
const chosenImageURL = await app.prompt(`Received ${ urls.length } options`, {
inputs: [{
label: "Choose an image",
options: radioOptions,
type: "radio"
}]
});
if (chosenImageURL === "more") {
return this._imageMarkdownFromPrompt(app, prompt, { note });
} else if (chosenImageURL) {
console.log("Fetching and uploading chosen URL", chosenImageURL)
const imageData = await this._fetchImageAsDataURL(chosenImageURL);
if (!note) note = await app.notes.find(app.context.noteUUID);
const ampleImageUrl = await note.attachMedia(imageData);
return `![image](${ ampleImageUrl })`;
}
return null;
} else {
return null;
}
},
 
// --------------------------------------------------------------------------------------
async _fetchImageAsDataURL(url) {
const response = await fetch(`${ this.constants.corsProxy }/${ url }`);
const blob = await response.blob();
 
return new Promise((resolve, reject) => {
const reader = new FileReader();
 
reader.onload = event => {
resolve(event.target.result);
};
 
reader.onerror = function (event) {
reader.abort();
reject(event.target.error);
};
 
reader.readAsDataURL(blob);
});
}
}



beep boop



linkChangelog

April 24. v1.1 adds the "More options" option

April 23. v1.0 allows image selection from preceding text or prompt