//Api key Credit : https://platform.openai.com/api-keys
const API_KEYS = "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";
const submitIcon = document.querySelector("#submit-icon");
const inputElement = document.querySelector("input");
const imageSection = document.querySelector(".images-section");
//svg background generator credit: https://app.haikei.app/
document.write(`
<svg
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
id="visual"
viewBox="0 0 960 540"
width="100vw"
version="1.1"
>
<path
d="M0 93L14.5 84.8C29 76.7 58 60.3 87.2 54.8C116.3 49.3 145.7 54.7 174.8 61.8C204 69 233 78 262 83.5C291 89 320 91 349 82C378 73 407 53 436.2 53C465.3 53 494.7 73 523.8 80.3C553 87.7 582 82.3 611 73.3C640 64.3 669 51.7 698 54.3C727 57 756 75 785.2 76.8C814.3 78.7 843.7 64.3 872.8 55.3C902 46.3 931 42.7 945.5 40.8L960 39L960 0L945.5 0C931 0 902 0 872.8 0C843.7 0 814.3 0 785.2 0C756 0 727 0 698 0C669 0 640 0 611 0C582 0 553 0 523.8 0C494.7 0 465.3 0 436.2 0C407 0 378 0 349 0C320 0 291 0 262 0C233 0 204 0 174.8 0C145.7 0 116.3 0 87.2 0C58 0 29 0 14.5 0L0 0Z"
fill="#6198ff"
/>
<path
d="M0 174L14.5 164C29 154 58 134 87.2 134C116.3 134 145.7 154 174.8 173.8C204 193.7 233 213.3 262 213.3C291 213.3 320 193.7 349 179.3C378 165 407 156 436.2 179.3C465.3 202.7 494.7 258.3 523.8 274.5C553 290.7 582 267.3 611 239.5C640 211.7 669 179.3 698 188.3C727 197.3 756 247.7 785.2 250.3C814.3 253 843.7 208 872.8 186.3C902 164.7 931 166.3 945.5 167.2L960 168L960 37L945.5 38.8C931 40.7 902 44.3 872.8 53.3C843.7 62.3 814.3 76.7 785.2 74.8C756 73 727 55 698 52.3C669 49.7 640 62.3 611 71.3C582 80.3 553 85.7 523.8 78.3C494.7 71 465.3 51 436.2 51C407 51 378 71 349 80C320 89 291 87 262 81.5C233 76 204 67 174.8 59.8C145.7 52.7 116.3 47.3 87.2 52.8C58 58.3 29 74.7 14.5 82.8L0 91Z"
fill="#3c80ff"
/>
<path
d="M0 228L14.5 233.3C29 238.7 58 249.3 87.2 248.3C116.3 247.3 145.7 234.7 174.8 251.8C204 269 233 316 262 326.8C291 337.7 320 312.3 349 286.2C378 260 407 233 436.2 251C465.3 269 494.7 332 523.8 362.7C553 393.3 582 391.7 611 373.7C640 355.7 669 321.3 698 317.7C727 314 756 341 785.2 333C814.3 325 843.7 282 872.8 266.7C902 251.3 931 263.7 945.5 269.8L960 276L960 166L945.5 165.2C931 164.3 902 162.7 872.8 184.3C843.7 206 814.3 251 785.2 248.3C756 245.7 727 195.3 698 186.3C669 177.3 640 209.7 611 237.5C582 265.3 553 288.7 523.8 272.5C494.7 256.3 465.3 200.7 436.2 177.3C407 154 378 163 349 177.3C320 191.7 291 211.3 262 211.3C233 211.3 204 191.7 174.8 171.8C145.7 152 116.3 132 87.2 132C58 132 29 152 14.5 162L0 172Z"
fill="#0066ff"
/>
<path
d="M0 309L14.5 314.3C29 319.7 58 330.3 87.2 331.2C116.3 332 145.7 323 174.8 333C204 343 233 372 262 379.2C291 386.3 320 371.7 349 349.2C378 326.7 407 296.3 436.2 310.8C465.3 325.3 494.7 384.7 523.8 415.2C553 445.7 582 447.3 611 436.5C640 425.7 669 402.3 698 400.5C727 398.7 756 418.3 785.2 408.5C814.3 398.7 843.7 359.3 872.8 346.8C902 334.3 931 348.7 945.5 355.8L960 363L960 274L945.5 267.8C931 261.7 902 249.3 872.8 264.7C843.7 280 814.3 323 785.2 331C756 339 727 312 698 315.7C669 319.3 640 353.7 611 371.7C582 389.7 553 391.3 523.8 360.7C494.7 330 465.3 267 436.2 249C407 231 378 258 349 284.2C320 310.3 291 335.7 262 324.8C233 314 204 267 174.8 249.8C145.7 232.7 116.3 245.3 87.2 246.3C58 247.3 29 236.7 14.5 231.3L0 226Z"
fill="#0059dd"
/>
<path
d="M0 541L14.5 541C29 541 58 541 87.2 541C116.3 541 145.7 541 174.8 541C204 541 233 541 262 541C291 541 320 541 349 541C378 541 407 541 436.2 541C465.3 541 494.7 541 523.8 541C553 541 582 541 611 541C640 541 669 541 698 541C727 541 756 541 785.2 541C814.3 541 843.7 541 872.8 541C902 541 931 541 945.5 541L960 541L960 361L945.5 353.8C931 346.7 902 332.3 872.8 344.8C843.7 357.3 814.3 396.7 785.2 406.5C756 416.3 727 396.7 698 398.5C669 400.3 640 423.7 611 434.5C582 445.3 553 443.7 523.8 413.2C494.7 382.7 465.3 323.3 436.2 308.8C407 294.3 378 324.7 349 347.2C320 369.7 291 384.3 262 377.2C233 370 204 341 174.8 331C145.7 321 116.3 330 87.2 329.2C58 328.3 29 317.7 14.5 312.3L0 307Z"
fill="#004cbb"
/>
</svg>
<!-- Image gererator Section -->
<header>
<h1>AI Image Generator</h1>
</header>
<section class="images-section">
<div id="scene-container"></div></section>
<br>
<br>
<h2 class="explain">What kind of image do you want to generate?</h2>
<h4 class="explain">Specific demand will get satisfaction,</h4>
<h4 class="explain">just like ordering pizza with extra cheese and getting a delivery guy </h4>
<h4 class="explain">who moonwalks to your doorstep while singing 'Cheesy Love'!</h4>
<!-- Customizable size & number of images Section -->
<section class="bottom-section">
<select id="image-size-dropdown">
<option value="" disabled hidden>Size</option>
<option value="256x256" selected>256 * 256</option>
<option value="512x512">512 * 512</option>
<option value="1024x1024">1024 * 1024</option>
</select>
</select>
<select id="number-count-dropdown">
<option value="1" selected>1</option>
<option value="2">2</option>
<option value="3">3</option>
<option value="4" >4</option>
</select>
<!-- User Input Section -->
<div class="input-container">
<input />
<div id="submit-icon">Click</div>
</div>
<br>
</div>
<br>
</section>
<h4 id="count"></h4>
<br>
<!-- Ascii Art gererator Section -->
<h2 id="ascii">Save your image and upload here!</h2>
<div>
<input type="file" id="image-upload" accept="image/*" />
</div>
<pre id="ascii-art-container" style="height: 512px;"></pre>
</section>
`);
//Ascii art converter credit : https://marmelab.com/blog/2018/02/20/convert-image-to-ascii-art-masterpiece.html
// Resizes the image and maintains the aspect ratio
function resizeImage(img, maxWidth, maxHeight) {
let ratio = Math.min(maxWidth / img.width, maxHeight / img.height);
return { width: img.width * ratio, height: img.height * ratio };
}
// Generates the ASCII art
function convertToAscii(ctx, width, height, maxLineLength) {
const asciiCharacters = "@%#*+=-:. ";
let asciiArt = "";
const pixelW = width / maxLineLength;
const pixelH = 2 * pixelW;
for (let y = 0; y < height; y += pixelH) {
for (let x = 0; x < width; x += pixelW) {
const imageData = ctx.getImageData(x, y, pixelW, pixelH);
const avgBrightness = getAverageBrightness(imageData);
const character =
asciiCharacters[
Math.round((asciiCharacters.length - 1) * avgBrightness)
];
asciiArt += character;
}
asciiArt += "\n";
}
return asciiArt;
}
//Calculates the average brightness of a region of pixels
function getAverageBrightness(imageData) {
let totalBrightness = 0;
const data = imageData.data;
for (let i = 0; i < data.length; i += 4) {
const brightness =
(0.3 * data[i] + 0.59 * data[i + 1] + 0.11 * data[i + 2]) / 255;
totalBrightness += brightness;
}
return totalBrightness / (imageData.data.length / 4);
}
document.addEventListener("DOMContentLoaded", function () {
const fileInputElement = document.querySelector("#image-upload");
fileInputElement.addEventListener("change", function (event) {
if (event.target.files && event.target.files[0]) {
const reader = new FileReader();
reader.onload = function (e) {
const img = new Image();
img.onload = function () {
const canvas = document.createElement("canvas");
const ctx = canvas.getContext("2d", { willReadFrequently: true }); // Setting the optimization here
const resizedDimensions = resizeImage(img, 512, 512);
canvas.width = resizedDimensions.width;
canvas.height = resizedDimensions.height;
ctx.drawImage(
img,
0,
0,
resizedDimensions.width,
resizedDimensions.height
);
const asciiArt = convertToAscii(ctx, canvas.width, canvas.height, 80); // Adjust maxLineLength to fit your container
document.getElementById("ascii-art-container").textContent = asciiArt;
};
img.src = e.target.result;
};
reader.readAsDataURL(event.target.files[0]);
}
});
});
// Image generator credit :https://platform.openai.com/docs/guides/images/usage?context=node
// I implemented Dall-e model. This is Customizable fields like size & number of images
// Get Image from AI image generator
function getImages() {
const prompt = $("input").val(); // User Prompt input
const selectedSize = $("#image-size-dropdown").val(); // Image size choices
const imageCount = parseInt($("#number-count-dropdown").val(), 10); // Number of images choices -> Convert to the integer value.
const options = {
method: "POST",
headers: {
Authorization: `Bearer ${API_KEYS}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
prompt: prompt,
n: imageCount,
size: selectedSize,
}),
};
// Start time
const startTime = new Date().getTime();
$.ajax({
type: "POST",
url: "https://api.openai.com/v1/images/generations",
headers: options.headers,
data: options.body,
success: function (data) {
// End time
const endTime = new Date().getTime();
const timeTaken = endTime - startTime;
// Dispaly the count element on the page with the time taken
$('#count').text("Time taken to generate image(s): " + timeTaken + "ms");
displayImage(data);
},
error: function (xhr, status, error) {
console.error("Error: " + error);
console.error("Status: " + status);
console.error("Response: " + xhr.responseText);
},
});
}
//User can generate the image 1 to 4. It will be display in 2*2 grid.
function displayImage(data) {
$(".images-section").empty();
if (data && data.data && data.data.length > 0) {
const imagesGrid = $('<div class="images-grid"></div>');
imagesGrid.css({
display: "grid",
"grid-template-columns": "repeat(2, 1fr)",
gap: "10px",
});
data.data.forEach((imageObject) => {
const imageContainer = $('<div class="image-container"></div>');
const imageElement = $("<img>").attr("src", imageObject.url);
imageContainer.append(imageElement);
imagesGrid.append(imageContainer);
});
$(".images-section").append(imagesGrid);
}
}
$(document).ready(function () {
$("body").css({
margin: "0",
padding: "0",
"background-color": "#004cbb",
display: "flex",
"flex-direction": "column",
width: "100vw",
height: "100vw",
"justify-content": "space-between",
"align-items": "center",
"font-family": "Verdana, Geneva, Tahoma, sans-serif",
});
$("svg").css({
position: "absolute",
top: "0",
left: "0",
"z-index": "-10",
});
$("header").css({
color: "white",
height: "150px",
display: "flex",
"align-items": "center",
width: "100%",
"justify-content": "center",
});
$(".explain").css({
color: "white",
display: "flex",
"align-items": "center",
width: "100%",
"justify-content": "center",
margin: "10px",
});
$(".bottom-section").css({
width: "100%",
display: "flex",
"justify-content": "center",
height: "150px",
});
$(".input-container").css({
width: "100%",
"max-width": "600px",
position: "relative",
});
$("input").css({
width: "100%",
border: "none",
"font-size": "20px",
padding: "10px",
"border-radius": "5px",
"box-shadow": "rgb(38, 57, 77) 0 20px 30px -10px",
"box-sizing": "border-box",
});
$("#submit-icon").css({
position: "absolute",
top: "10px",
right: "30px",
"justify-content": "center",
cursor: "pointer",
});
$("#ascii").css({
color: "white",
});
$("#count").css({
color: "white",
});
$("#image-upload").css({
color: "black",
background: "white",
});
$("#ascii-art-container").css({
color: "black",
"font-family": "monospace",
"font-size": "10px",
"white-space": "pre",
"text-align": "left",
background: "white",
height: "512px",
});
$(".image-section").css({
width: "40%",
padding: "10",
});
$(".image-container").css({
width: "10vw",
margin: "20",
"border-radius": "15px",
overflow: "hidden",
"box-shadow": "rgb(38, 57, 77) 0 20px 30px -10px",
});
$("#image-size-dropdown").css({
width: "10vw",
height: "45px",
"border-radius": "7px",
overflow: "hidden",
"box-shadow": "rgb(38, 57, 77) 0 20px 30px -10px",
});
$("#number-count-dropdown").css({
width: "5vw",
height: "45px",
"border-radius": "7px",
overflow: "hidden",
"box-shadow": "rgb(38, 57, 77) 0 20px 30px -10px",
});
$(".image-container img").css({
width: "100%",
height: "auto",
});
$("#submit-icon").click(function () {
getImages();
});
});