From a1145a193558737230bde3f9b5c9642e87beb7e0 Mon Sep 17 00:00:00 2001 From: collidingScopes <166117863+collidingScopes@users.noreply.github.com> Date: Thu, 8 Aug 2024 08:06:33 -0400 Subject: [PATCH] Delete imageMage.js --- imageMage.js | 2046 -------------------------------------------------- 1 file changed, 2046 deletions(-) delete mode 100644 imageMage.js diff --git a/imageMage.js b/imageMage.js deleted file mode 100644 index f9cb653..0000000 --- a/imageMage.js +++ /dev/null @@ -1,2046 +0,0 @@ -var imageInput = document.getElementById('imageInput'); -var imageContainer = document.getElementById('imageContainer'); -var pixelColors = document.getElementById('pixelColors'); -var newImageContainer = document.getElementById('newImageContainer'); -var originalImage; -var clickXPosition; -var clickYPosition; -var visualizationChoiceMenu = document.getElementById('visualizationChoice'); -var visualizationChoice = visualizationChoiceMenu.value; -var previousVisualizationChoice = visualizationChoice; -var loadingScreen = document.getElementById("coverScreen"); - -var redInput = document.getElementById('red'); -var greenInput = document.getElementById('green'); -var blueInput = document.getElementById('blue'); -var alphaInput = document.getElementById('alpha'); - -var smearWidthInput = document.getElementById('smearWidth'); -var smearWidth = smearWidthInput.value; -var chosenPixelInput = document.getElementById('chosenPixel'); -var chosenPixel = chosenPixelInput.value; - -var noiseProbabilityInput = document.getElementById('noiseProbability'); -var noiseProbability = noiseProbabilityInput.value; - -var noiseColorRangeInput = document.getElementById('noiseColorRange'); -var noiseColorRange = noiseColorRangeInput.value; -var rgbColorRange = noiseColorRange/100 * 255; - -var dotSizeFactorInput = document.getElementById('dotSizeFactor'); -var dotSizeFactor = dotSizeFactorInput.value; - -var lightnessLevelInput = document.getElementById('lightnessLevel'); -var lightnessLevel = lightnessLevelInput.value; - -var saturationLevelInput = document.getElementById('saturationLevel'); -var saturationLevel = saturationLevelInput.value; - -var isImageLoaded = false; - -var redrawButton = document.getElementById('generate-button'); -redrawButton.addEventListener('click', refresh); - -var actualWidth; -var actualHeight; -var scaledWidth; -var scaledHeight; -var widthScalingRatio; - -var newCanvas = document.createElement('canvas'); -var newCtx = newCanvas.getContext('2d'); - -var pixelData; -var pixels; - -var redShift = redInput.value; -var greenShift = greenInput.value; -var blueShift = blueInput.value; -var alphaShift = alphaInput.value; - -var screenWidth = window.innerWidth; // get the width of the browser screen -var maxImageWidth = (screenWidth*0.96) / 2; // max width for each of the two images -var maxImageHeight = window.innerHeight * 0.78; -console.log("max image dimensions: "+maxImageWidth+", "+maxImageHeight); - -//color pickers -var paletteChoiceInput = document.getElementById('paletteChoice'); -var colorPicker = document.getElementById('color-picker'); -var colorPicker2 = document.getElementById('color-picker2'); -var colorPicker3 = document.getElementById('color-picker3'); -var colorPicker4 = document.getElementById('color-picker4'); -var colorPicker5 = document.getElementById('color-picker5'); -var colorPicker6 = document.getElementById('color-picker6'); -var pickers = [colorPicker, colorPicker2, colorPicker3, colorPicker4, colorPicker5, colorPicker6]; - -var backgroundColorInput = document.getElementById('backgroundColorInput'); -var backgroundColor = backgroundColorInput.value; - -var palettePresets = [ - {name: "mage", displayName: "Mage", palette: ["#0066A4","#640000","#006400","#FFC300","#FFFFFF","#000000"]}, - {name: "viridis", displayName: "Viridis", palette: ["#fde725","#7ad151","#22a884","#2a788e","#414487","#440154"]}, - {name: "analog", displayName: "Analog", palette: ["#d27575","#675a55","#529b9c","#9cba8f","#eac392","#FFFFFF"]}, - {name: "inferno", displayName: "Inferno", palette: ["#fcffa4","#fca50a","#dd513a","#932667","#420a68","#000004"]}, - {name: "vaporwave", displayName: "Vaporwave", palette: ["#D336BE","#E1A5EE","#05C3DD","#1E22AA","#D1EFED","#FFFFFF"]}, - {name: "bohemian", displayName: "Bohemian", palette: ["#3F2021","#B04A5A","#BA5B3F","#CB9576","#7FA0AC","#EEE5D3"]}, - {name: "earth", displayName: "Earth", palette: ["#8e412e","#ba6f4d","#e6cebc","#a2a182","#687259","#123524"]}, - {name: "primary", displayName: "Primary", palette: ["#c90000","#fff400","#0004ff","#ffffff","#ffffff","#000000"]}, - {name: "custom", displayName: "Custom >>", palette: ["#FFFFFF","#DDDDDD","#BBBBBB","#000000","#000000","#000000"]} -]; - -var chosenPalette = palettePresets[0].palette; - -//set as equal to mage palette upon first load, in RGB space -var chosenPaletteRGBValues = [ - [0, 102, 164], - [100, 0, 0], - [0, 100, 0], - [255, 195, 0], - [255, 255, 255], - [0, 0, 0] -]; - -//fill the paletteChoice HTML element dynamically -palettePresets.forEach((preset) => { - const option = document.createElement('option'); - option.value = preset.name; - option.text = preset.displayName; - paletteChoiceInput.appendChild(option); -}); - -var paletteChoice = paletteChoiceInput.value; - -//dual color picker -var dualColorPicker1 = document.getElementById('dualColorInput1'); -var dualColorPicker2 = document.getElementById('dualColorInput2'); - -var dualColor1 = dualColorPicker1.value; -var dualColor2 = dualColorPicker2.value; - -//Pop-up for grid visual style -var popup = document.querySelector('.popup'); - -// hide the popup when the user clicks on the image -popup.addEventListener('click', () => { - popup.style.display = 'none'; -}); - -var drawImageCounter = 0; -var gridLoadCounter = 0; -var ringsLoadCounter = 0; -var frontierLoadCounter = 0; -var eclipseLoadCounter = 0; - -//Save and export the new image in png format -var saveButton = document.getElementById('save-image-button'); - -saveButton.addEventListener('click', () => { - saveImage(); -}); - - -// Add event listeners to the input boxes -imageInput.addEventListener('change', readSourceImage); - -visualizationChoiceMenu.addEventListener('change',refresh); -redInput.addEventListener('change', refresh); -greenInput.addEventListener('change', refresh); -blueInput.addEventListener('change', refresh); -alphaInput.addEventListener('change', refresh); -smearWidthInput.addEventListener('change', refresh); -chosenPixelInput.addEventListener('change', refresh); -noiseProbabilityInput.addEventListener('change', refresh); -noiseColorRangeInput.addEventListener('change', refresh); -dotSizeFactorInput.addEventListener('change', refresh); - -paletteChoiceInput.addEventListener('change', changePalette); -dualColorPicker1.addEventListener('change', refresh); -dualColorPicker2.addEventListener('change', refresh); -lightnessLevelInput.addEventListener('change', refresh); -saturationLevelInput.addEventListener('change', refresh); - - -//main method -initPhotoCarousel(); -getUserInputs(); -initColorPickers(); -showDefaultImage(); - -// Grab new user inputs from control menu -function getUserInputs() { - - visualizationChoice = String(visualizationChoiceMenu.value); - - redShift = parseInt(redInput.value); - greenShift = parseInt(greenInput.value); - blueShift = parseInt(blueInput.value); - alphaShift = parseFloat(alphaInput.value); - - smearWidth = Math.min(100,Math.max(0,Number(smearWidthInput.value))); - chosenPixel = Math.min(100,Math.max(0,Number(chosenPixelInput.value))); - noiseProbability = Math.min(100,Math.max(0,Number(noiseProbabilityInput.value))); - noiseColorRange = Math.min(100,Math.max(0,Number(noiseColorRangeInput.value))); - dotSizeFactor = Math.min(100,Math.max(0,Number(dotSizeFactorInput.value))); - - rgbColorRange = noiseColorRange/100 * 255; - - dualColor1 = dualColorPicker1.value; - dualColor2 = dualColorPicker2.value; - - lightnessLevel = Math.min(100,Math.max(0,Number(lightnessLevelInput.value))); - saturationLevel = Math.min(100,Math.max(0,Number(saturationLevelInput.value))); - - //set background color - if(visualizationChoice == previousVisualizationChoice){ - backgroundColor = backgroundColorInput.value; - } else if(visualizationChoice == "eclipse"){ - backgroundColorInput.value = "#000000"; - backgroundColor = "#000000"; - } else { - backgroundColorInput.value = "#FFF9EB"; - backgroundColor = "#FFF9EB"; - } - - toggleInputMenu(); -} - -function toggleInputMenu(){ - - var numColumns = 12; - - //columns: Style, RGBA shift, Smear, Sensitivity, Color Range, Max Dot Size, Palette, Color pickers, Background, dual color picker - //Value of 1 if the columnn should be shown for that style, 0 if hidden - var menuControlFlags = [ - {menuOptions: [1,0,0,0,1,1,0,0,0,0,0,0], name: "pointillist"}, - {menuOptions: [1,0,0,1,0,0,0,0,0,0,0,0], name: "sketch"}, - {menuOptions: [1,0,0,1,0,0,0,0,0,0,0,0], name: "roller"}, - {menuOptions: [1,0,0,1,0,0,1,1,0,0,0,0], name: "palletize"}, - {menuOptions: [1,0,0,1,0,0,0,0,0,0,0,0], name: "pixel"}, - {menuOptions: [1,0,0,1,0,0,0,0,1,0,0,0], name: "clippings"}, - {menuOptions: [1,0,0,1,0,0,0,0,0,0,0,0], name: "grid"}, - {menuOptions: [1,0,0,1,0,0,1,1,0,0,0,0], name: "mondrian"}, - {menuOptions: [1,0,0,1,0,1,0,0,1,0,0,0], name: "rings"}, - {menuOptions: [1,0,0,1,0,0,0,0,1,0,0,0], name: "gumball"}, - {menuOptions: [1,0,0,1,0,0,0,0,0,0,0,0], name: "noisySort"}, - {menuOptions: [1,0,0,1,0,0,0,0,0,0,0,0], name: "void"}, - {menuOptions: [1,0,0,1,0,0,0,0,1,0,0,0], name: "braille"}, - {menuOptions: [1,0,0,1,0,0,1,1,0,0,0,0], name: "dust"}, - {menuOptions: [1,0,0,1,0,0,0,0,0,1,0,0], name: "outlines"}, - {menuOptions: [1,0,0,1,0,0,0,0,1,0,0,0], name: "frontier"}, - {menuOptions: [1,0,0,1,0,0,0,0,1,0,0,0], name: "eclipse"}, - {menuOptions: [1,0,0,0,0,0,0,0,1,0,1,1], name: "satLight"}, - {menuOptions: [1,0,0,1,0,0,0,0,1,1,0,0], name: "edgy"}, - {menuOptions: [1,0,0,1,0,0,0,0,0,0,0,0], name: "shadow"}, - ]; - - var styleIndex = menuControlFlags.findIndex(obj => obj.name == visualizationChoice); - - for(var idx=0; idx { - if(menuControlFlags[styleIndex].menuOptions[idx] == 1){ - element.classList.remove('hidden'); - } else { - element.classList.add('hidden'); - } - }); - } - -} - -function showDefaultImage() { - - var defaultImage = new Image(); - defaultImage.src = 'images/HK2024.jpg'; - - defaultImage.onload = () => { - - actualWidth = defaultImage.width; - actualHeight = defaultImage.height; - - //adjust for max width - if(actualWidth >= maxImageWidth){ - scaledWidth = maxImageWidth; - } else{ - scaledWidth = Math.min(maxImageWidth,actualWidth*1.0); - } - - widthScalingRatio = scaledWidth / actualWidth; - scaledHeight = actualHeight * widthScalingRatio; - - //adjust for max height - if(scaledHeight > maxImageHeight){ - scaledWidth = (maxImageHeight / scaledHeight) * scaledWidth; - widthScalingRatio = scaledWidth / actualWidth; - scaledHeight = actualHeight * widthScalingRatio; - } - - newCanvas = document.createElement('canvas'); - newCtx = newCanvas.getContext('2d'); - - newCanvas.width = actualWidth; - newCanvas.height = actualHeight; - - newCtx.drawImage(defaultImage, 0, 0); - - const newImageData = newCanvas.toDataURL(); - const newImage = new Image(); - newImage.src = newImageData; - newImage.style.width = `${scaledWidth}px`; - imageContainer.appendChild(newImage); - - var img = imageContainer.querySelector('img'); - - img.onload = () => { - const canvas = document.createElement('canvas'); - canvas.width = actualWidth; - canvas.height = actualHeight; - const ctx = canvas.getContext('2d'); - ctx.drawImage(img, 0, 0); - pixelData = ctx.getImageData(0, 0, actualWidth, actualHeight); - pixels = pixelData.data; - isImageLoaded = true; - drawNewImage(); - - img.addEventListener('click', (e) => { - clickXPosition = e.offsetX / widthScalingRatio; - clickYPosition = e.offsetY / widthScalingRatio; - console.log(`Clicked at (${clickXPosition}, ${clickYPosition})`); - if(visualizationChoice=="grid" || visualizationChoice=="rings" || visualizationChoice=="frontier"){ - drawNewImage(); - } - }); - - window.scrollTo(0, 0); - } - - } -} - -function readSourceImage(){ - -//remove any existing images -while (imageContainer.firstChild) { - imageContainer.removeChild(imageContainer.firstChild); -} - -while (newImageContainer.firstChild) { - newImageContainer.removeChild(newImageContainer.firstChild); -} - -//read image file - var file = imageInput.files[0]; - var reader = new FileReader(); - reader.onload = (event) => { - var imageData = event.target.result; - var image = new Image(); - image.src = imageData; - image.onload = () => { - - actualWidth = image.width; - actualHeight = image.height; - - //adjust for max width - if(actualWidth >= maxImageWidth){ - scaledWidth = maxImageWidth; - } else{ - scaledWidth = Math.min(maxImageWidth,actualWidth*2); - } - - widthScalingRatio = scaledWidth / actualWidth; - scaledHeight = actualHeight * widthScalingRatio; - - //adjust for max height - if(scaledHeight > maxImageHeight){ - scaledWidth = (maxImageHeight / scaledHeight) * scaledWidth; - widthScalingRatio = scaledWidth / actualWidth; - scaledHeight = actualHeight * widthScalingRatio; - } - - var originalImg = document.createElement('img'); - originalImg.src = imageData; - originalImg.width = scaledWidth; - originalImg.height = scaledHeight; - imageContainer.appendChild(originalImg); - - // Get the pixel colors - const canvas = document.createElement('canvas'); - const ctx = canvas.getContext('2d'); - canvas.width = actualWidth; - canvas.height = actualHeight; - ctx.drawImage(image, 0, 0); - pixelData = ctx.getImageData(0, 0, actualWidth, actualHeight); - pixels = pixelData.data; - - //add click position event listener - originalImg.addEventListener('click', (e) => { - clickXPosition = e.offsetX / widthScalingRatio; - clickYPosition = e.offsetY / widthScalingRatio; - console.log(`Clicked at (${clickXPosition}, ${clickYPosition})`); - if(visualizationChoice=="grid" || visualizationChoice=="rings" || visualizationChoice=="frontier"){ - drawNewImage(); - } - }); - - refresh(); - - }; - }; - reader.readAsDataURL(file); - - isImageLoaded = true; - -} - -function refresh(){ - - console.log("refresh"); - - //show the loading screen - loadingScreen.classList.remove("hidden"); - loadingScreen.classList.add("lockOn"); - - getUserInputs(); - setTimeout(drawNewImage,5); - -} - -function drawNewImage(){ - - if (!isImageLoaded) { - //hide the loading screen - loadingScreen.classList.remove("lockOn"); - loadingScreen.classList.add("hidden"); - return; // exit the function if isImageLoaded is false - } - - //remove any existing new images - while (newImageContainer.firstChild) { - newImageContainer.removeChild(newImageContainer.firstChild); - } - - originalImage = imageContainer.querySelector('img'); - - // Create a new image - newCanvas = document.createElement('canvas'); - newCtx = newCanvas.getContext('2d'); - - newCanvas.width = actualWidth; - newCanvas.height = actualHeight; - - //set background color of new canvas - newCtx.fillStyle = backgroundColor; - newCtx.fillRect(0, 0, actualWidth, actualHeight); - - console.log("actual width: "+actualWidth); - console.log("actual height: "+actualHeight); - - drawImageCounter++; - - if(visualizationChoice == "rgba"){ - console.log("running rgba visual"); - for (let j = 0; j < pixels.length; j += 4) { - const newRed = pixels[j] * (redShift/100); - const newGreen = pixels[j + 1] * (greenShift/100); - const newBlue = pixels[j + 2] * (blueShift/100); - const newAlpha = pixels[j + 3] * (alphaShift/100); - newCtx.fillStyle = `rgba(${newRed}, ${newGreen}, ${newBlue}, ${newAlpha})`; - newCtx.fillRect(j / 4 % actualWidth, Math.floor(j / 4 / actualWidth), 1, 1); - } - } else if(visualizationChoice == "smear"){ - console.log("running smear visual"); - for (let j = 0; j < pixels.length; j += 4) { - var currentColNum = j / 4 % actualWidth; - var currentRowNum = Math.floor(j / 4 / actualWidth); - var currentRightPixel = (Math.floor(actualWidth * chosenPixel/100) + (actualWidth*currentRowNum))-1; - - var newRed = pixels[currentRightPixel*4]; - var newGreen = pixels[currentRightPixel*4+1]; - var newBlue = pixels[currentRightPixel*4+2]; - var newAlpha = 1; - if(currentColNum < (actualWidth * smearWidth/100)){ - newAlpha = pixels[currentRightPixel*4+3]; - } else { - newAlpha = 0; - } - newCtx.fillStyle = `rgba(${newRed}, ${newGreen}, ${newBlue}, ${newAlpha})`; - newCtx.fillRect(j / 4 % actualWidth, Math.floor(j / 4 / actualWidth), 1, 1); - } - } else if(visualizationChoice == "roller"){ - console.log("running roller visual"); - - //faithful reproduction - newCtx.drawImage(originalImage, 0, 0); - - //smear effect - var numSmears = 4; - - for(var smearCounter=0; smearCounter noiseProbability/100){ - //newCtx.fillStyle = `rgba(${red}, ${green}, ${blue}, ${alpha})`; - } else { - newCtx.fillStyle = `rgba(${newRed}, ${newGreen}, ${newBlue}, ${newAlpha})`; - } - newCtx.fillRect(j / 4 % actualWidth, Math.floor(j / 4 / actualWidth), 1, 1); - } - - } else if(visualizationChoice == "perlin2"){ - console.log("running perlin2 visual"); - generatePerlinNoise(); - - for (let j = 0; j < pixels.length; j += 4) { - - var pixelX = j / 4 % actualWidth; - var pixelY = Math.floor(j / 4 / actualWidth); - - var perlinXGridSize = actualWidth / dataWidth; - var perlinYGridSize = actualHeight / dataHeight; - - var perlinX = Math.floor(pixelX / perlinXGridSize); - var perlinY = Math.floor(pixelY / perlinYGridSize); - - var perlinDataValue = perlinDataArray[perlinY][perlinX]; - - var red = pixels[j]; - var green = pixels[j + 1]; - var blue = pixels[j + 2]; - var alpha = pixels[j + 3]; - - var randomRed = chosenColorR - rgbColorRange/2 + (Math.random() * rgbColorRange); - var randomGreen = chosenColorG - rgbColorRange/2 + (Math.random() * rgbColorRange); - var randomBlue = chosenColorB - rgbColorRange/2 + (Math.random() * rgbColorRange); - var randomAlpha = 1; - - if((Math.pow(perlinDataValue,2.5) * Math.random()) < ((noiseProbability/100) * 0.025) || ((((100 - noiseProbability)/100) * Math.random() * Math.pow(perlinDataValue,2)) < 0.005)){ - newCtx.fillStyle = `rgba(${randomRed}, ${randomGreen}, ${randomBlue}, ${randomAlpha})`; - - } else { - newCtx.fillStyle = `rgba(${red}, ${green}, ${blue}, ${alpha})`; - } - newCtx.fillRect(j / 4 % actualWidth, Math.floor(j / 4 / actualWidth), 1, 1); - } - - } else if(visualizationChoice == "perlin3"){ - console.log("running perlin3 visual"); - - var maxPixelSize = 15; - - generatePerlinNoise(); - - for (let j = pixels.length-4; j >= 0; j -= 4) { - - var pixelSize = Math.max(1, Math.round(Math.random() * maxPixelSize * (noiseProbability/100))); - - var pixelX = j / 4 % actualWidth; - var pixelY = Math.floor(j / 4 / actualWidth); - - var perlinXGridSize = actualWidth / dataWidth; - var perlinYGridSize = actualHeight / dataHeight; - - var perlinX = Math.floor(pixelX / perlinXGridSize); - var perlinY = Math.floor(pixelY / perlinYGridSize); - - var perlinDataValue = perlinDataArray[perlinY][perlinX]; - - var red = pixels[j]; - var green = pixels[j + 1]; - var blue = pixels[j + 2]; - var alpha = pixels[j + 3]; - - var randomRed = chosenColorR - rgbColorRange/2 + (Math.random() * rgbColorRange); - var randomGreen = chosenColorG - rgbColorRange/2 + (Math.random() * rgbColorRange); - var randomBlue = chosenColorB - rgbColorRange/2 + (Math.random() * rgbColorRange); - var randomAlpha = 1; - - if((Math.pow(perlinDataValue,1.6) * Math.random()) < ((noiseProbability/100) * 0.010) || ((((100 - noiseProbability)/100) * Math.random() * Math.pow(perlinDataValue,2)) < 0.0001)){ - newCtx.fillStyle = `rgba(${randomRed}, ${randomGreen}, ${randomBlue}, ${randomAlpha})`; - - } else { - //pixelSize = 1; - newCtx.fillStyle = `rgba(${red}, ${green}, ${blue}, ${alpha})`; - } - newCtx.fillRect(j / 4 % actualWidth, Math.floor(j / 4 / actualWidth), pixelSize, pixelSize); - } - - } else if(visualizationChoice == "pixelPop"){ - console.log("running pixelPop visual"); - - var numChangePixels = 300; - var maxWidth = 500; - var maxHeight = 500; - var backgroundAlphaValue = 0.8; - var foregroundAlphaValue = 0.5; - - - for(i=0; i 0; j -= 4) { - - var currentRed = pixels[j]; - var currentGreen = pixels[j + 1]; - var currentBlue = pixels[j + 2]; - var currentLum = Math.pow((0.299 * currentRed + 0.587 * currentGreen + 0.114 * currentBlue), 1/2.2); - - var previousRed = pixels[j-4]; - var previousGreen = pixels[j-4+1]; - var previousBlue = pixels[j-4+2]; - var previousLum = Math.pow((0.299 * currentRed + 0.587 * currentGreen + 0.114 * currentBlue), 1/2.2); - - var redDelta = Math.abs(currentRed - previousRed); - var greenDelta = Math.abs(currentGreen - previousGreen); - var blueDelta = Math.abs(currentBlue - previousBlue); - var lumDelta = Math.abs(currentLum - previousLum); - - var alpha = Math.pow(Math.min(1,Math.max(0,(redDelta + greenDelta + blueDelta)/100)), 4); - - var primaryThreshold = 14 * (Math.pow((noiseProbability/100 + 0.5),5)); - - var pixelWidth = Math.round(Math.random()*actualWidth*0.01); - var pixelHeight = Math.round(Math.random()*7); - - if(redDelta > primaryThreshold || greenDelta > primaryThreshold || blueDelta > primaryThreshold || lumDelta > 1){ - newCtx.fillStyle = `rgba(${currentRed}, ${currentGreen}, ${currentBlue}, ${alpha})`; //colour sketch - newCtx.fillRect(j / 4 % actualWidth, Math.floor(j / 4 / actualWidth), pixelWidth, pixelHeight); - - } else { - if(Math.random() < 0.04){ - var alpha = 0.2; - newCtx.fillStyle = `rgba(${currentRed}, ${currentGreen}, ${currentBlue}, ${alpha})`; //colour sketch - newCtx.fillRect(j / 4 % actualWidth, Math.floor(j / 4 / actualWidth), pixelWidth*0.75, pixelHeight*0.75); - } - } - - } - - } else if(visualizationChoice == "palletize"){ - console.log("running palletize visual"); - console.log("Color Palette: "+paletteChoice); - - //faithful reproduction - newCtx.drawImage(originalImage, 0, 0); - - for (let j = 0; j < pixels.length; j += 4) { - - var red = pixels[j]; - var green = pixels[j + 1]; - var blue = pixels[j + 2]; - - var lowestDistance = 0; - var targetR; - var targetG; - var targetB; - var alpha = Math.min(1,Math.max(0,noiseProbability/100)); - - for(i=0; i a.score - b.score); - - for (let i = 0; i < sortedPixelData.length; i++) { - var red = sortedPixelData[i].red; - var green = sortedPixelData[i].green; - var blue = sortedPixelData[i].blue; - var alpha = 1; - newCtx.fillStyle = `rgba(${red}, ${green}, ${blue}, ${alpha})`; - newCtx.fillRect(i % actualWidth, Math.floor(i / actualWidth), 1, 1); - } - - } else if(visualizationChoice == "void"){ - console.log("running void visual"); - - var numPixels = actualWidth * actualHeight; - - for(var i=numPixels-1; i>=0; i--){ - - var red = pixels[i*4]; - var green = pixels[i*4+1]; - var blue = pixels[i*4+2]; - var lum = Math.pow((0.299 * red + 0.587 * green + 0.114 * blue), 1/2.2) - var threshold = noiseProbability / 9; - var alpha = 1; - var pixelWidth = 1; - var pixelHeight = 1; - - if(lum > threshold){ - newCtx.fillStyle = `rgba(${red}, ${green}, ${blue}, ${alpha})`; - pixelWidth = 1; - pixelHeight = 1; - } else { - if(Math.random()<0.7){ - newCtx.fillStyle = `black`; - } else { - var randomRed = Math.random() * 255; - var randomGreen = Math.random() * 255; - var randomBlue = Math.random() * 255; - newCtx.fillStyle = `rgba(${randomRed}, ${randomGreen}, ${randomBlue}, ${alpha})`; - } - pixelWidth = Math.ceil(Math.random()* actualWidth*0.006); - pixelHeight = Math.ceil(Math.random()* actualHeight*0.006); - - } - newCtx.fillRect(i % actualWidth, Math.floor(i / actualWidth), pixelWidth, pixelHeight); - - } - - } else if(visualizationChoice == "braille"){ - console.log("running braille visual"); - - var numPixels = actualWidth * actualHeight; - var colSpacing = Math.floor(actualWidth/50 * Math.pow((noiseProbability/100 + 0.5),2) ); - var rowSpacing = colSpacing; - - var alpha = 1; - var pixelWidth = 1; - var pixelHeight = 1; - var skipRow = true; - var skipCol = true; - - for(var row=0; row 0; j -= 4*skipStep) { - - var currentRed = pixels[j]; - var currentGreen = pixels[j + 1]; - var currentBlue = pixels[j + 2]; - var currentLum = Math.pow((0.299 * currentRed + 0.587 * currentGreen + 0.114 * currentBlue), 1/2.2); - - var previousRed = pixels[j-4]; - var previousGreen = pixels[j-4+1]; - var previousBlue = pixels[j-4+2]; - var previousLum = Math.pow((0.299 * previousRed + 0.587 * previousGreen + 0.114 * previousBlue), 1/2.2); - - var redDelta = Math.abs(currentRed - previousRed); - var greenDelta = Math.abs(currentGreen - previousGreen); - var blueDelta = Math.abs(currentBlue - previousBlue); - var lumDelta = Math.abs(currentLum - previousLum); - - var alpha = Math.pow(Math.min(1,Math.max(0,(redDelta + greenDelta + blueDelta)/100)), 4); - - var primaryThreshold = 7 * (Math.pow((noiseProbability/100 + 0.5),1.1)); - - var pixelWidth = Math.random()*3; - var pixelHeight = Math.random()*3; - - var pixelColor = chosenPalette[ Math.floor(Math.random() * chosenPalette.length) ]; - - if(currentLum < primaryThreshold){ - newCtx.fillStyle = pixelColor; - newCtx.fillRect(j / 4 % actualWidth, Math.floor(j / 4 / actualWidth), pixelWidth, pixelHeight); - } - } - } else if(visualizationChoice == "outlines"){ - console.log("running outlines visual"); - var skipStep = 1; - - for (let j = pixels.length-4; j > 0; j -= 4*skipStep) { - - var currentRed = pixels[j]; - var currentGreen = pixels[j + 1]; - var currentBlue = pixels[j + 2]; - //var currentLum = Math.pow((0.299 * currentRed + 0.587 * currentGreen + 0.114 * currentBlue), 1/2.2); - var currentLight = rgbToLightness(currentRed,currentGreen,currentBlue); - - var previousRed = pixels[j-4]; - var previousGreen = pixels[j-4+1]; - var previousBlue = pixels[j-4+2]; - //var previousLum = Math.pow((0.299 * previousRed + 0.587 * previousGreen + 0.114 * previousBlue), 1/2.2); - var previousLight = rgbToLightness(previousRed,previousGreen,previousBlue); - - - var nextRed = pixels[j+4]; - var nextGreen = pixels[j+4 + 1]; - var nextBlue = pixels[j+4 + 2]; - //var nextLum = Math.pow((0.299 * nextRed + 0.587 * nextGreen + 0.114 * nextBlue), 1/2.2); - var nextLight = rgbToLightness(nextRed,nextGreen,nextBlue); - - var lightDelta = Math.abs(currentLight - previousLight) + Math.abs(currentLight - nextLight); - newCtx.globalAlpha = Math.max(0.2,lightDelta*3); - - //var primaryThreshold = 7 * (Math.pow((noiseProbability/100 + 0.5),1.1)); - //var secondaryThreshold = 7 * (Math.pow(((100-noiseProbability)/100 + 0.5),1.1)); - - var primaryThreshold = (3+0.94*noiseProbability)/100; - var secondaryThreshold = (100 - (3+0.94*noiseProbability)) / 100; - - var pixelWidth = Math.random()*actualWidth*0.004; - var pixelHeight = Math.random()*actualHeight*0.004; - - if( (currentLight < primaryThreshold && previousLight > primaryThreshold && nextLight < primaryThreshold) || (currentLight < primaryThreshold && previousLight < primaryThreshold && nextLight > primaryThreshold) ){ - newCtx.fillStyle = dualColor1; - newCtx.fillRect(j / 4 % actualWidth, Math.floor(j / 4 / actualWidth), pixelWidth, pixelHeight); - } else if( (currentLight < secondaryThreshold && previousLight > secondaryThreshold && nextLight < secondaryThreshold) || (currentLight < secondaryThreshold && previousLight < secondaryThreshold && nextLight > secondaryThreshold) ){ - newCtx.fillStyle = dualColor2; - newCtx.fillRect(j / 4 % actualWidth, Math.floor(j / 4 / actualWidth), pixelWidth, pixelHeight); - } - - } - } else if(visualizationChoice == "frontier"){ - console.log("running frontier visual"); - - if(frontierLoadCounter == 0){ - // show the popup - popup.style.display = 'block'; - - clickXPosition = actualWidth/2; - clickYPosition = actualHeight/2; - } - frontierLoadCounter++; - - var heightWidthRatio = actualHeight / actualWidth; - var alpha = 1; - var pixelWidth = 1; - var pixelHeight = 1; - - for(var y=0; y threshold ){ - newCtx.fillStyle = `rgba(${actualRed}, ${actualGreen}, ${actualBlue}, ${alpha})`; - newCtx.fillRect(x, y, 1, 1); - } - } - } - } else if(visualizationChoice == "satLight"){ - console.log("running satLight visual"); - - var alpha = 1; - var lightnessThreshold = (3+0.7*lightnessLevel)/100; - var saturationThreshold = (100 - (3+0.8*saturationLevel))/100; - console.log(lightnessLevel + ", "+saturationLevel); - - - for(var y=0; y < actualHeight; y++ ){ - for(var x=0; x < actualWidth; x++ ){ - - var actualPixel = (y * actualWidth + x) * 4; - var actualRed = pixels[actualPixel]; - var actualGreen = pixels[actualPixel + 1]; - var actualBlue = pixels[actualPixel + 2]; - var actualSaturation = rgbToSaturation(actualRed, actualGreen, actualBlue); - var actualLightness = rgbToLightness(actualRed, actualGreen, actualBlue); - var actualAlpha = 1; - - if(actualLightness < lightnessThreshold || actualSaturation > saturationThreshold){ - newCtx.fillStyle = `rgba(${actualRed}, ${actualGreen}, ${actualBlue}, ${actualAlpha})`; - newCtx.fillRect(x, y, 1, 1); - - } - } - } - } else if(visualizationChoice == "edgy"){ - console.log("running edgy visual"); - - var lightDataArray = []; - - //generate data array for all pixel lightness values - for(var y=0; y < actualHeight; y++ ){ - - lightDataArray[y] = []; - - for(var x=0; x < actualWidth; x++ ){ - - var actualPixel = (y * actualWidth + x) * 4; - var actualRed = pixels[actualPixel]; - var actualGreen = pixels[actualPixel + 1]; - var actualBlue = pixels[actualPixel + 2]; - //var actualLightness = rgbToLightness(actualRed, actualGreen, actualBlue); - var actualLum = (0.2989 * actualRed + 0.5870 * actualGreen + 0.1140 * actualBlue)/255; - - lightDataArray[y][x] = actualLum; - - } - } - - console.log("lightness data array filled"); - - //gaussian smoothing function - var smoothedLightDataArray = [] - var kernelWidth = 5; - var kernelHeight = kernelWidth; - var middlePixel = Math.floor(kernelWidth/2); - var kernelWeights = [0.003663004, 0.014652015, 0.025641026, 0.014652015, 0.003663004, 0.014652015, 0.058608059, 0.095238095, 0.058608059, 0.014652015, 0.025641026, 0.095238095, 0.15018315, 0.095238095, 0.025641026, 0.014652015, 0.058608059, 0.095238095, 0.058608059, 0.014652015, 0.003663004, 0.014652015, 0.025641026, 0.014652015, 0.003663004]; - - for(var y=0; y < actualHeight; y++ ){ - smoothedLightDataArray[y] = []; - - for(var x=0; x < actualWidth; x++ ){ - - var kernelData = []; - - for(var kernelY=0; kernelY= 0 && pixelXPosition < actualWidth && pixelYPosition >= 0 && pixelYPosition < actualHeight){ - kernelData.push(lightDataArray[pixelYPosition][pixelXPosition]); - }else{ - kernelData.push(0); - } - } - } - - var weightedAverageLight = calcWeightedAverage(kernelData,kernelWeights); - smoothedLightDataArray[y][x] = weightedAverageLight; - - } - } - - //draw vertical edges - var alpha = 1; - //var threshold = 0.02 + ((0.8*noiseProbability)/100); - var threshold = 0.165 - (noiseProbability/100 * 0.15); - var pixelWidth = 2; - var pixelHeight = 2; - - for(var y=0; y < actualHeight; y++ ){ - for(var x=0; x < actualWidth; x++ ){ - - if(x==0 || y==0 || x==actualWidth-1 || y==actualHeight-1){ - continue; - } - var lightValue = smoothedLightDataArray[y][x]; - var leftLight = smoothedLightDataArray[y][x-1]; - var rightLight = smoothedLightDataArray[y][x+1]; - - var delta1 = Math.abs(lightValue - leftLight); - var delta2 = Math.abs(lightValue - rightLight); - - var red = lightValue * 255; - var green = lightValue * 255; - var blue = lightValue * 255; - - //if(lightValue < threshold && (leftLight > threshold || rightLight > threshold)){ - if(delta1 > threshold){ - //newCtx.fillStyle = `rgba(${red}, ${green}, ${blue}, ${alpha})`; - newCtx.fillStyle = dualColor1; - newCtx.globalAlpha = 0.5; - newCtx.fillRect(x, y, pixelWidth, pixelHeight); - } - - } - } - - //draw horizontal edges - for(var y=0; y < actualHeight; y++ ){ - for(var x=0; x < actualWidth; x++ ){ - - if(x==0 || y==0 || x==actualWidth-1 || y==actualHeight-1){ - continue; - } - var lightValue = smoothedLightDataArray[y][x]; - var topLight = smoothedLightDataArray[y-1][x]; - var bottomLight = smoothedLightDataArray[y+1][x]; - - var delta1 = Math.abs(lightValue - topLight); - var delta2 = Math.abs(lightValue - bottomLight); - - var red = lightValue * 255; - var green = lightValue * 255; - var blue = lightValue * 255; - - //if(lightValue < threshold && (topLight > threshold || bottomLight > threshold)){ - if(delta1 > threshold){ - //newCtx.fillStyle = `rgba(${red}, ${green}, ${blue}, ${alpha})`; - newCtx.fillStyle = dualColor2; - newCtx.globalAlpha = 0.5; - newCtx.fillRect(x, y, pixelWidth, pixelHeight); - } - - } - } - - } else if(visualizationChoice == "shadow"){ - - //faithful reproduction - newCtx.drawImage(originalImage, 0, 0); - - var numLayers = 4; - var alpha = 0.3; - var maxXOffset = 0.03 * actualWidth; - var maxYOffset = 0.03 * actualHeight - - for(var layerCounter=0; layerCounter= actualWidth || newY<0 || newY>= actualHeight){ - continue; - } - - var actualPixel = (y * actualWidth + x) * 4; - var actualRed = pixels[actualPixel]; - var actualGreen = pixels[actualPixel + 1]; - var actualBlue = pixels[actualPixel + 2]; - var actualLum = (0.2989 * actualRed + 0.5870 * actualGreen + 0.1140 * actualBlue)/255; - - /* - if(actualLum < 0.3){ - continue; - } - */ - - newCtx.fillStyle = `rgba(${actualRed}, ${actualGreen}, ${actualBlue}, ${alpha})`; - newCtx.fillRect(x+xOffset, y+yOffset, 1, 1); - - } - } - - } - - - - } - - const newImageData = newCanvas.toDataURL(); - const newImage = new Image(); - newImage.src = newImageData; - newImage.style.width = `${scaledWidth}px`; - newImageContainer.appendChild(newImage); - - resizeTable(); - - //hide the loading screen - loadingScreen.classList.remove("lockOn"); - loadingScreen.classList.add("hidden"); - - previousVisualizationChoice = visualizationChoice; - -} - -//Helper Functions - -//shortcut key presses -document.addEventListener('keydown', function(event) { - if (event.key === 'r') { - refresh(); - - } else if (event.key === 's') { - saveImage(); - } else if (event.key === 'e') { - saveBothImages(); - } -}); - -function saveImage(){ - const image = newImageContainer.querySelector('img'); - const imageUrl = image.src; - const link = document.createElement('a'); - const date = new Date(); - const filename = `image_${date.toLocaleDateString()}_${date.toLocaleTimeString()}.png`; - - // Create a blob from the image - fetch(imageUrl) - .then(response => response.blob()) - .then(blob => { - const url = URL.createObjectURL(blob); - const link = document.createElement('a'); - link.href = url; - link.download = filename; - link.click(); - }); - -} - -function saveBothImages(){ - - // Get the two images - const originalImage = imageContainer.querySelector('img'); - const newImage = newImageContainer.querySelector('img'); - - // Create a canvas element - const canvas = document.createElement('canvas'); - const ctx = canvas.getContext('2d'); - - // Set the canvas dimensions to match the combined width of the two images - canvas.width = actualWidth*2; - canvas.height = actualHeight; - console.log("Save both images -- canvas width / height: "+canvas.width+", "+canvas.height); - - // Draw the original image on the left side of the canvas - ctx.drawImage(originalImage, 0, 0, actualWidth, actualHeight); - - // Draw the new image on the right side of the canvas - ctx.drawImage(newImage, actualWidth, 0, actualWidth, actualHeight); - - // Use the canvas.toDataURL() method to generate a data URL for the combined image - const combinedImageURL = canvas.toDataURL(); - - const link = document.createElement('a'); - const date = new Date(); - const filename = `image_${date.toLocaleDateString()}_${date.toLocaleTimeString()}.png`; - - // Create a blob from the image - fetch(combinedImageURL) - .then(response => response.blob()) - .then(blob => { - const url = URL.createObjectURL(blob); - const link = document.createElement('a'); - link.href = url; - link.download = filename; - link.click(); - }); - -} - -function rgbToHue(r, g, b) { - const rNorm = r / 255; - const gNorm = g / 255; - const bNorm = b / 255; - const hue = Math.atan2(Math.sqrt(3) * (gNorm - bNorm), 2 * rNorm - gNorm - bNorm); - return hue * 180 / Math.PI; -} - -function rgbToSaturation(r, g, b) { - const max = Math.max(r, g, b); - const min = Math.min(r, g, b); - return (max - min) / max; -} - -function rgbToLightness(r, g, b) { - const max = Math.max(r, g, b); - const min = Math.min(r, g, b); - return (max + min) / 2 / 255; -} - -//returns random number between 0-1 based on normal distribution -function randomBM() { - let u = 0, v = 0; - while(u === 0) u = Math.random(); //Converting [0,1) to (0,1) - while(v === 0) v = Math.random(); - let num = Math.sqrt( -2.0 * Math.log( u ) ) * Math.cos( 2.0 * Math.PI * v ); - num = num / 10.0 + 0.5; // Translate to 0 -> 1 - if (num > 1 || num < 0) return randn_bm() // resample between 0 and 1 - return num -} - -function extractRGB(rgbString) { - const rgbRegex = /rgb\((\d+),\s*(\d+),\s*(\d+)\)/; - const match = rgbString.match(rgbRegex); - if (match) { - return { - r: parseInt(match[1]), - g: parseInt(match[2]), - b: parseInt(match[3]), - }; - } else { - return null; - } -} - -function calcWeightedAverage(data,weights){ - var weightedAverage = 0; - for(var i=0; i { - updateColorPickers(); - }); - - colorPicker2.addEventListener('change', (e) => { - updateColorPickers(); - }); - - colorPicker3.addEventListener('change', (e) => { - updateColorPickers(); - }); - - colorPicker4.addEventListener('change', (e) => { - updateColorPickers(); - }); - - colorPicker5.addEventListener('change', (e) => { - updateColorPickers(); - }); - - colorPicker6.addEventListener('change', (e) => { - updateColorPickers(); - }); - - backgroundColorInput.addEventListener('change', (e) => { - refresh(); - }); -} - -function changePalette(){ - - paletteChoice = paletteChoiceInput.value; - - for (let idx = 0; idx < palettePresets.length; idx++){ - if (palettePresets[idx].name == paletteChoice){ - chosenPalette = palettePresets[idx].palette; - break; - } - } - - for (let idx = 0; idx < pickers.length; idx++){ - pickers[idx].value = chosenPalette[idx]; - } - - updateColorPickers(); -} - -function updateColorPickers(){ - - for (let idx = 0; idx < pickers.length; idx++){ - var currentColor = pickers[idx].value; - chosenPalette[idx] = currentColor; - var currentColorRGB = hexToRgb(currentColor); - chosenPaletteRGBValues[idx] = [currentColorRGB.r, currentColorRGB.g, currentColorRGB.b]; - } - - //Modify and save changes to custom palette - var customIndex = palettePresets.findIndex(obj => obj.name === "custom"); - console.log("Palette choice: "+paletteChoice); - if(paletteChoice == "custom"){ - palettePresets[customIndex].palette = chosenPalette; - } - - refresh(); -} - -var carouselClickCounter = 0; - -function initPhotoCarousel(){ - - const carousel = document.querySelector('.carousel'); - const carouselInner = carousel.querySelector('.carousel-inner'); - const carouselItems = carouselInner.querySelectorAll('.carousel-item'); - const carouselDots = carousel.querySelectorAll('.carousel-dot'); - - let currentSlide = 0; - - carouselDots.forEach((dot, index) => { - dot.addEventListener('click', () => { - carouselClickCounter++; - currentSlide = index; - updateCarousel(); - }); - }); - - function updateCarousel() { - - if (currentSlide < 0) { - currentSlide = carouselItems.length - 1; - } else if (currentSlide >= carouselItems.length) { - currentSlide = 0; - } - - carouselItems.forEach((item, index) => { - item.classList.remove('active'); - if (index === currentSlide) { - item.classList.add('active'); - } - }); - - carouselDots.forEach((dot, index) => { - dot.classList.remove('active'); - if (index === currentSlide) { - dot.classList.add('active'); - } - }); - } - - //Autoplay three times only - let iterationCount = 0; - let autoplayIntervalId = setInterval(() => { - if(carouselClickCounter>0){ - return; - } - currentSlide++; - updateCarousel(); - iterationCount++; - if (iterationCount >= 3) { - clearInterval(autoplayIntervalId); - } - }, 4800); //milliseconds before slide change - -} - -// Mondrian object and functions - -function randInt (min, max) { - return Math.floor(Math.random() * (max - min) + min) -} - -class Point { - constructor (x, y) { - this.x = x - this.y = y - } -} - -class Rectangle { - constructor (min, max) { - this.min = min - this.max = max - } - - get width () { - return this.max.x - this.min.x - } - - get height () { - return this.max.y - this.min.y - } - - draw (ctx) { - // Draw clockwise - ctx.moveTo(this.min.x, this.min.y) - ctx.lineTo(this.max.x, this.min.y) - ctx.lineTo(this.max.x, this.max.y) - ctx.lineTo(this.min.x, this.max.y) - ctx.lineTo(this.min.x, this.min.y) - } - - split (xPad, yPad, depth, limit, ctx) { - ctx.fillStyle = chosenPalette[randInt(0, chosenPalette.length)] - ctx.fillRect(this.min.x, this.min.y, this.max.x, this.max.y) - this.draw(ctx) - - // Check the level of recursion - if (depth === limit) { - return - } - - // Check the rectangle is enough large and tall - if (this.width < 2 * xPad || this.height < 2 * yPad) { - return - } - - // If the rectangle is wider than it's height do a left/right split - var r1 = new Rectangle() - var r2 = new Rectangle() - if (this.width > this.height) { - var x = randInt(this.min.x + xPad, this.max.x - xPad) - r1 = new Rectangle(this.min, new Point(x, this.max.y)) - r2 = new Rectangle(new Point(x, this.min.y), this.max) - // Else do a top/bottom split - } else { - var y = randInt(this.min.y + yPad, this.max.y - yPad) - r1 = new Rectangle(this.min, new Point(this.max.x, y)) - r2 = new Rectangle(new Point(this.min.x, y), this.max) - } - - // Split the sub-rectangles - r1.split(xPad, yPad, depth + 1, limit, ctx) - r2.split(xPad, yPad, depth + 1, limit, ctx) - } -} \ No newline at end of file