Spaces:
Running
Running
<html><head><base href="https://websim.ai" /> | |
<title>Advanced Crusty JPEG Pixelator</title> | |
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.9.4/p5.min.js"></script> | |
<style> | |
body { | |
font-family: Arial, sans-serif; | |
display: flex; | |
justify-content: center; | |
align-items: center; | |
height: 100vh; | |
margin: 0; | |
background-color: #f0f0f0; | |
background-image: url('https://i.redd.it/9vbk2x63s1c91.jpg'); | |
background-size: cover; | |
background-position: center; | |
background-repeat: no-repeat; | |
background-attachment: fixed; | |
} | |
body::before { | |
content: ""; | |
position: fixed; | |
top: 0; | |
left: 0; | |
right: 0; | |
bottom: 0; | |
background-color: rgba(240, 240, 240, 0.5); | |
z-index: -1; | |
} | |
.container { | |
text-align: center; | |
background-color: rgba(255, 255, 255, 0.8); | |
padding: 20px; | |
border-radius: 8px; | |
box-shadow: 0 0 10px rgba(0,0,0,0.1); | |
max-width: 90vw; | |
width: 100%; | |
} | |
#uploadBtn, #downloadBtn { | |
margin: 10px; | |
padding: 10px 20px; | |
font-size: 16px; | |
cursor: pointer; | |
} | |
#canvas { | |
margin-top: 20px; | |
max-width: 100%; | |
max-height: 70vh; | |
overflow: auto; | |
} | |
.slider-container { | |
display: flex; | |
flex-direction: column; | |
align-items: center; | |
margin: 10px 0; | |
} | |
.slider-label { | |
margin-bottom: 5px; | |
} | |
.slider { | |
width: 80%; | |
margin: 5px auto; | |
} | |
</style> | |
</head> | |
<body> | |
<div class="container"> | |
<h1>Advanced Crusty JPEG Pixelator</h1> | |
<input type="file" id="fileInput" accept="image/*" style="display: none;"> | |
<button id="uploadBtn">Upload Image</button> | |
<button id="downloadBtn" disabled>Download Processed Image</button> | |
<div class="slider-container"> | |
<label class="slider-label" for="crustySlider">Crustiness Level: </label> | |
<input type="range" id="crustySlider" class="slider" min="0" max="10" value="0" step="0.1"> | |
</div> | |
<div class="slider-container"> | |
<label class="slider-label" for="pixelSlider">Pixelation Level: </label> | |
<input type="range" id="pixelSlider" class="slider" min="0" max="10" value="0" step="0.1"> | |
</div> | |
<div id="canvas"></div> | |
</div> | |
<script> | |
let img; | |
let processedImg; | |
let crustySlider; | |
let pixelSlider; | |
let canvas; | |
const MAX_WIDTH = Math.min(800, window.innerWidth * 0.9); | |
const MAX_HEIGHT = window.innerHeight * 0.7; | |
function setup() { | |
console.log('Setup function called'); | |
canvas = createCanvas(1, 1); | |
canvas.parent('canvas'); | |
select('#uploadBtn').mousePressed(() => { | |
console.log('Upload button clicked'); | |
select('#fileInput').elt.click(); | |
}); | |
select('#fileInput').changed(handleFile); | |
select('#downloadBtn').mousePressed(downloadProcessedImage); | |
crustySlider = select('#crustySlider'); | |
pixelSlider = select('#pixelSlider'); | |
crustySlider.input(updateImage); | |
pixelSlider.input(updateImage); | |
crustySlider.attribute('disabled', ''); | |
pixelSlider.attribute('disabled', ''); | |
console.log('Setup complete'); | |
} | |
function handleFile(event) { | |
console.log('File selected:', event); | |
const file = event.target.files[0]; | |
if (file && file.type.startsWith('image')) { | |
console.log('File type:', file.type); | |
loadImage(URL.createObjectURL(file), (loadedImg) => { | |
console.log('Image loaded'); | |
img = loadedImg; | |
let scaleFactor = Math.min(MAX_WIDTH / img.width, MAX_HEIGHT / img.height); | |
let newWidth = img.width * scaleFactor; | |
let newHeight = img.height * scaleFactor; | |
resizeCanvas(newWidth, newHeight); | |
image(img, 0, 0, newWidth, newHeight); | |
select('#downloadBtn').removeAttribute('disabled'); | |
crustySlider.removeAttribute('disabled'); | |
pixelSlider.removeAttribute('disabled'); | |
updateImage(); | |
}, (error) => { | |
console.error('Error loading image:', error); | |
}); | |
} else { | |
console.log('No valid image file selected'); | |
} | |
} | |
function updateImage() { | |
console.log('Updating image'); | |
if (!img) { | |
console.log('No image loaded yet'); | |
return; | |
} | |
let crustiness = crustySlider.value(); | |
let pixelation = pixelSlider.value(); | |
console.log('Crustiness level:', crustiness, 'Pixelation level:', pixelation); | |
// Apply JPEG-like artifacts (crustiness) | |
processedImg = createImage(img.width, img.height); | |
processedImg.copy(img, 0, 0, img.width, img.height, 0, 0, img.width, img.height); | |
processedImg.loadPixels(); | |
for (let i = 0; i < processedImg.pixels.length; i += 4) { | |
let quantizationFactor = Math.floor(crustiness * 25) + 1; | |
processedImg.pixels[i] = Math.floor(processedImg.pixels[i] / quantizationFactor) * quantizationFactor; | |
processedImg.pixels[i+1] = Math.floor(processedImg.pixels[i+1] / quantizationFactor) * quantizationFactor; | |
processedImg.pixels[i+2] = Math.floor(processedImg.pixels[i+2] / quantizationFactor) * quantizationFactor; | |
} | |
processedImg.updatePixels(); | |
// Apply pixelation | |
let scaleFactor = Math.pow(0.5, pixelation / 2); | |
let newWidth = Math.max(1, Math.floor(img.width * scaleFactor)); | |
let newHeight = Math.max(1, Math.floor(img.height * scaleFactor)); | |
// Create a temporary canvas for pixelation | |
let tempCanvas = createGraphics(newWidth, newHeight); | |
tempCanvas.image(processedImg, 0, 0, newWidth, newHeight); | |
// Resize back to original size with nearest-neighbor interpolation | |
processedImg = createImage(img.width, img.height); | |
processedImg.copy(tempCanvas, 0, 0, newWidth, newHeight, 0, 0, img.width, img.height); | |
// Display the processed image | |
image(processedImg, 0, 0, width, height); | |
console.log('Image updated and displayed'); | |
} | |
function downloadProcessedImage() { | |
console.log('Downloading processed image'); | |
if (processedImg) { | |
save(processedImg, 'crusty_pixelated_image.jpg'); | |
} else { | |
console.log('No processed image to download'); | |
} | |
} | |
function windowResized() { | |
if (img) { | |
let scaleFactor = Math.min(MAX_WIDTH / img.width, MAX_HEIGHT / img.height); | |
let newWidth = img.width * scaleFactor; | |
let newHeight = img.height * scaleFactor; | |
resizeCanvas(newWidth, newHeight); | |
updateImage(); | |
} | |
} | |
// Initialize p5.js | |
new p5(); | |
// Error handling and logging | |
window.onerror = function(message, source, lineno, colno, error) { | |
console.error('Global error:', message, 'at', source, 'line', lineno, 'column', colno); | |
console.error('Error object:', error); | |
}; | |
// Ensure all DOM elements are loaded before initializing | |
document.addEventListener('DOMContentLoaded', function() { | |
console.log('DOM fully loaded and parsed'); | |
}); | |
</script> | |
</body> | |
</html> |