Last active
April 25, 2022 03:47
-
-
Save volfegan/62d6f58cb8d057044360e7ab4e3b132e to your computer and use it in GitHub Desktop.
A burn/dissolving image effect that flows using either a 2D noise map or some image pixel brightness
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//Reference: | |
//https://www.youtube.com/watch?v=cLkORfzQPEU | |
//https://github.com/leonardo-ono/Java2DIntegrationDisintegrationEffectTest/blob/main/src/Test.java | |
float flowValue=350;//354~255 (display full image), -54~Zero (no image) | |
float flowDirection=-1;//1 (re-creating) or -1 (burning/dissolving) | |
float[][] flowMap; //2D map of brightness on how to proceed the dissolving effect | |
PImage source; | |
String filename; | |
//there is no file validation, so any non-source selected file will crash the program | |
void fileSelected(File selection) { | |
if (selection == null) { | |
println("No image file selected."); | |
exit(); | |
} else { | |
String filepath = selection.getAbsolutePath(); | |
filename = selection.getName(); | |
int pos = filename.lastIndexOf("."); | |
if (pos != -1) filename = filename.substring(0, pos); //remove extension | |
println("File selected " + filepath); | |
// load file here | |
source = loadImage(filepath); | |
} | |
} | |
void interrupt() { | |
while (source==null) delay(200); | |
} | |
void settings() { | |
selectInput("Select an image file to process:", "fileSelected"); | |
interrupt(); //interrupt process until source is selected | |
//for testing | |
//source = loadImage("cat.jpg"); | |
width = source.width; | |
height = source.height; | |
//the canvas window size will be according to the source size | |
//if the source is bigger, it will be resized to 80% of display | |
if (width > displayWidth) { | |
float resizer = width / (displayWidth * 0.8); | |
width = (int)((float)displayWidth * 0.8); | |
height = (int)((float)height / resizer); | |
source.resize(width, height); | |
} | |
if (height > displayHeight) { | |
float resizer = height / (displayHeight * 0.8); | |
height = (int)((float)displayHeight * 0.8); | |
width = (int)((float)width / resizer); | |
source.resize(width, height); | |
} | |
size(width, height); | |
} | |
void setup() { | |
boolean saveImage = true; | |
flowMap = buildFlowMapFrom2DNoise(source, saveImage); | |
//flowMap = buildFlowMapFromImage(source, saveImage); | |
//image(source, 0, 0); | |
} | |
void draw() { | |
clear(); | |
//dissolve/burn/regrow image (we are actually redrawing the image where values are below the parameter) | |
loadPixels(); | |
for (int x = 0; x < width; x++) { | |
for (int y = 0; y < height; y++) { | |
int level = (int)flowMap[x][y] & 255;//ensure only numbers cap at 255 | |
if (abs(level - flowValue) < 8) { | |
color white = color(255); | |
pixels[x+y*width] = color(white); | |
} else if (abs(level - flowValue) < 16) { | |
if (flowDirection < 0) { | |
color yellow = color(255, 255, 0); | |
pixels[x+y*width] = color(yellow); | |
} else { | |
color cyan = color(0, 255, 255); | |
pixels[x+y*width] = color(cyan); | |
} | |
} else if (abs(level - flowValue) < 24) { | |
if (flowDirection < 0) { | |
color red = color(255, 0, 0); | |
pixels[x+y*width] = color(red); | |
} else { | |
//color blue = color(0, 0, 255); | |
//pixels[x+y*width] = color(blue); | |
color gray = color(255/2); | |
pixels[x+y*width] = color(gray); | |
} | |
} else if (level < flowValue) { | |
pixels[x+y*width] = source.get(x, y); | |
} | |
} | |
} | |
updatePixels(); | |
flowValue += 1*flowDirection; | |
//change effect direction when above 255 + time or below 0 + time | |
if (flowValue > 355 || flowValue < -55) { | |
flowDirection*=-1; | |
flowMap = buildFlowMapFrom2DNoise(source, false); | |
//flowMap = buildFlowMapFromImage(source, false); | |
} | |
} | |
/* | |
* Creates a 2D noise map of brightness the same size as the image (also creates a image flowMap2Dnoise.jpg) | |
* @param PImage source | |
* @param boolean saveImage | |
* @return float[][] flowMapFrom2DNoise, whose values are 0~255 | |
*/ | |
float[][] buildFlowMapFrom2DNoise(PImage source, boolean saveImage) { | |
PImage flowMap2Dnoise = createImage(source.width, source.height, RGB); | |
float[][] flowMapFrom2DNoise = new float[source.width][source.height]; | |
float detail = random(0.4, 0.6); | |
float noiseStep = random(0.01, 0.03); | |
noiseDetail(8, detail); | |
if (saveImage) flowMap2Dnoise.loadPixels(); | |
// For every x,y coordinate, calculate a noise value as a brightness value | |
float xoff = 0;//noise x offset coordinate | |
for (int x = 0; x < source.width; x++) { | |
xoff += noiseStep; | |
float yoff = 0;//noise y offset coordinate | |
for (int y = 0; y < source.height; y++) { | |
yoff += noiseStep; | |
// Calculate the noise and scale by 255 | |
float bright = noise(xoff, yoff) * 255; | |
// Set each pixel as a grayscale value | |
if (saveImage) flowMap2Dnoise.pixels[x+y*source.width] = color(bright); | |
flowMapFrom2DNoise[x][y] = color(bright); | |
} | |
} | |
if (saveImage) { | |
flowMap2Dnoise.updatePixels(); | |
image(flowMap2Dnoise, 0, 0); | |
save("flowMap2Dnoise.jpg"); | |
clear(); | |
} | |
return flowMapFrom2DNoise; | |
} | |
/* | |
* Creates a brightness map from the image (also creates a image flowMap2Dnoise.jpg) | |
* @param PImage source | |
* @param boolean saveImage | |
* @return float[][] flowMapFrom2DNoise, whose values are 0~255 | |
*/ | |
float[][] buildFlowMapFromImage(PImage source, boolean saveImage) { | |
PImage flowMapFromImage = createImage(source.width, source.height, RGB); | |
float[][] flowMapFrom2DNoise = new float[source.width][source.height]; | |
if (saveImage) flowMapFromImage.loadPixels(); | |
// For every x,y coordinate, calculate a noise value as a brightness value | |
for (int x = 0; x < source.width; x++) { | |
for (int y = 0; y < source.height; y++) { | |
color pixel = source.pixels[x+y*source.width]; | |
float bright = brightness(pixel); | |
// Set each pixel as a grayscale value | |
if (saveImage) flowMapFromImage.pixels[x+y*source.width] = color(bright); | |
flowMapFrom2DNoise[x][y] = color(bright); | |
} | |
} | |
if (saveImage) { | |
flowMapFromImage.updatePixels(); | |
image(flowMapFromImage, 0, 0); | |
save("flowMapFromImage.jpg"); | |
clear(); | |
} | |
return flowMapFrom2DNoise; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment