I'm trying to convert an image into a picture that only has a certain amount of colors in p5.js. I am doing this by picking num
random colors. Then, I'm going through every pixel in the image with loadPixels()
and giving it a score. This score is determined by how close the color is to one of the random colors. I do this by adding the difference individually from the rgb values and then choosing the lowest score. For example, if I had num = [color(100, 100, 100), color(200, 200, 200)]
and I was looking at a pixel that has color(100, 150, 110)
then the score would be not 240 (the difference between the image pixel and the 200 color) but instead 60. This all works fine. Next, what I'm trying to do is make sure that every pixel has a score under scoreBoundary
. Originally, this variable is set to 0. If the score of a pixel is more than scoreBoundary
, I alter the closest random color to bring the pixel's score under scoreBoundary
. This all should work fine. After a few loops (I haven't decided how many yet, maybe it has to do with the average pixel score or something), if there is still a pixel over scoreBoundary
, I increase scoreBoundary
. Eventually, I should have the best picture I can have with num
colors. (If you want to know, I'm trying to make a sort of Cross-Stitch Clone.)
Now for my problem. I want to make a temporary progress bar, because this method is very slow. Originally, I tried putting text that said pixelNum " out of " pixels.length
. However, since this process was in a for loop, this didn't show up. So, I tried putting this process in the draw loop. Now the text shows up, but it's unbearably slow. After about a minute, I was maybe 1% done with the first loop (and remember, there will be thousands) because it was only performing one calculation per frame. Now I ask you two things, and either solution helps.
One, is there a way to have a process that works as fast as it can away from the draw loop? For example, can I have this process run multiple times per frame (without just adding i < previousBoundary * howMuchFasterIWantItToBe
) while still being linked to draw for the progress bar?
Two, is there another way to go about this? Another library or method that reduces the number of colors in an image to num
?
CodePudding user response:
You don't really show any code that is reproducible to explain what issue you are having.
In any case, what you are looking for (for your first question) is an async function.
SEIZURE WARNING FOR PHOTOSENSITIVITY Seriously, this example sketch will wreck your eyes but you can see two ellipses working on different schedules because of the async function
Importantly, I had to append the start of the sketch with /*jshint esversion: 9 */
for the editor to allow async to be used:
/*jshint esversion: 9 */
let thing = 10;
let thing2 = 10;
function setup() {
createCanvas(400, 400);
}
function draw() {
background(220);
drawOther();
for(let i = 0; i < 1000; i ){
if(thing <= 400){
thing = 2;
}else{
thing = 10;
}
fill(255)
stroke(0);
ellipse(width, height, thing, thing);
}
}
const drawOther = async () => {
for(let i = 0; i < 100; i ){
if(thing2 <= 400){
thing2 = 2;
}else{
thing2 = 10;
}
fill(0);
stroke(255)
ellipse(0, 0, thing2, thing2);
}
}
You can read more about async functions here but basically, it does what you want - to launch a separate thread of activity that won't block your main loop.
If you want to return anything from an async function you would need to read about await
and promises
as well.