I'm trying to create a sorting algorithm visualiser in greenfoot java, with an array shown as a column graph. I want it to be colourful, so I'm using a colour gradient like shown in this video https://www.youtube.com/watch?v=qlvBsYyGIDo
This is the non-working code:
Pseudocode{
int[50] arr={1,2,3...}
for(int i:arr)
rect.color=getColor(i,arr.length)
}
private static Color getColor(int value, int length){
float h=((float)value/(float)length);//goes from 0-1
System.out.println(value+" "+length+" "+h);
java.awt.Color rgb=java.awt.Color.getHSBColor(h,255,255);
int r=rgb.getRed();
int g=rgb.getGreen();
int b=rgb.getBlue();
System.out.println(rgb+" "+r+" "+g+" "+b);
return new Color(r,g,b);//greenfoot.Color, not java.awt.Color
}
But the colours it produces look like this:
How can I create a smoth gradient, from red->yellow->green->cyan->blue->magenta?
Thanks #Thomas. Turns out all three of the values for Color.getHSBColor() range from 0-1, and values higher than that produce ~undefined behaviour~.
Related
I have a Collection of Integers of Processing colors (it contains colors of images rescaled to 1x1 to get the "average" color).
I have this thing that must retrieve me the nearest color of the array :
public static int getNearestColor(Collection<Integer> colors, int color) {
return colors.stream()
.min(Comparator.comparingInt(i -> Math.abs(i - color)))
.orElseThrow(() -> new NoSuchElementException("No value present"));
}
But when I do this, it returns me a color that is way far than the input, but the array contains some colors that are nearest than the input, this is my problem that I don't understand ?
The RGB color channels of a color() are encoded in an int. You can extract the red, green and blue component of the color, by red(), green() and blue().
Treat the color channels as a 3 dimensional vector (PVector) and compute the Euclidean distance of 2 color vectors, by dist(). The color with the shortest "distance" is the "nearest" color:
In the following function the arguments c1 and c2 are colors of type int:
float ColorDistance(int c1, int c2) {
return PVector.dist(
new PVector(red(c1), green(c1), blue(c1)),
new PVector(red(c2), green(c2), blue(c2)));
}
Find the "nearest" color, in a collection of colors, by finding the minimum floating point "distance" (ColorDistance(i, color)).
arrays in java don't have a stream method; perhaps you meant Arrays.stream(colors). IntStream has no way to do a comparison other than on natural order. You can map to the difference (abs(i - color)) first, but now you've deleted the information you were looking for (the original color), so that won't work either. Let's box it. This results in the following code, which is exactly like your code, except this compiles and runs. I'll then also add a test case to make it a self-contained example:
int[] colors = {1,4,5,9,12};
int target = 6;
int a = Arrays.stream(colors).boxed()
.min(Comparator.comparingInt(i -> Math.abs(i - target)))
.orElseThrow(() -> new NoSuchElementException());
System.out.println(a);
and, whoa nelly, '5' falls out, which is exactly what you want.
In other words, the intent of your code is fine, if it's not giving the right answer your inputs are not what you thought they are, or something else is wrong that cannot be gleaned from your paste.
May I suggest that if it is at all possible to put the question in a simple, self contained form (as this question clearly was, see the code snippet in this answer), that you do so? Often you'll answer your own questions that way :)
public static int getNearestColor(int[] colors, int color) {
int minDiff = IntStream.of(colors)
.map(val -> Math.abs(val - color))
.min()
.getAsInt();
OptionalInt num = IntStream.of(colors)
.filter(val-> val==(color + minDiff))
.findFirst();
if(num.isPresent()){
return color + minDiff;
} else {
return color - minDiff;
}
}
So my ultimate goal is to draw 50 circles(with processing.core.PApplet) structured around a ring that transitions colors like a neon sign so that it would look like Psychadelics
The circles have to be random sizes and with a diameter of under 210 pixels the circles have to have 8 bars with each "shells" changing colors in order, and at the center, there must be an empty circle with the same color as the background.
Right now I am trying to break this problem into lots of small problems, and currently, I am struggling to make the spaces between the bars to be equally spaced.
Culprit:
(I found the problem to be the ratio between the bar size and the circle size, due to the undefined range random sizing it made seemingly empty circles)
Here is my next problem, The circles seem to be vibrating instead of remaining static, I want the 50 circles to be static while the colors on each shell change each frame.
Here is the part where I tell it to draw smaller and smaller circles
This is the "Drawing component"
public Donut(float x, float y , float d) { //constructor
this.x =x;
this.y =y;
diameter=d;
}
public void draw(PApplet p) {
p.circle(x, y, diameter);
float bar=(float)(Math.random()*(1-10)-1)+1;
for(int i =0; i<8; i++) {
bar+=10;
p.fill(REDS[i],GREENS[i],BLUES[i]);
p.circle(x, y, diameter-bar);
}
}
And here is the part where I tell it to have random sizes and positions(still haven't told it to be placed around a ring yet) //This is the Main Class
public class Psychadelics extends PApplet{
Donut [] DonutList = new Donut [50];
public static void main(String[] args) {
PApplet.main("test.Psychadelics");
}
public void settings() {
size(SCR_W, SCR_H);
}
public void setup() {
for(int i =0; i<DonutList.length;i++) {
float x = (float)(Math.random()*600);
float y = (float)(Math.random()*400);
float diameter = (float)(Math.random()*210);
DonutList [i]= new Donut(x,y,diameter);
}
I have another drawing method inside the main class to tell the Donut class to keep drawing and to keep updating it.
I expect each circle to remain static and to transition colors, each frame but my actual results were the circles each with different colors on each shell vibrating on their specified coordinates
The vibration is caused by float bar=(float)(Math.random()*(1-10)-1)+1;. Because bar is determined inside the draw function, the exact diameter will be slightly different on each frame. Instead, you should create an array of these random floats in the constructor and use random_diameter[i] in the draw loop, so the sizes of the inner circles are created random, but remain constant.
The color remaining constant is caused by p.fill(REDS[i],GREENS[i],BLUES[i]);. You assign specific colors, based on the index, to a circle that is also based on the index. This is where you should use random. For red, green and blue use int(Math.random(0,255));. That way, on each frame, a random color is generated for each circle. If you want more gradual color changes, you'll need to store the color for each circle and add/subtract a small random number. If you want to limit the number of colors, you can use the function you have now, but instead of i, use a random number with the size of the array.
I hope you see that, interestingly, the problems/solutions are each others inverse :)
I'm working on a image manipulation. I have a problem I'm dealing with it, I didn't get any results. I need an algorithm to detect inverted colors.
As in the example photo below, I need to find and fix the inverted colors:
Currently I'm trying to find solution with using Java and C# .
I get the best closest result with this method. I convert the image to invert and two image compare with pixel-by-pixel. 70% success.
public static Color getTrueColor(this Color t, Color m)
{
int[] a = { t.R, t.G, t.B };
int[] b = { m.R, m.G, m.B };
int x = (int)a.Average();
int y = (int)b.Average();
return x < y ? m : t;
}
Thanks in advance for every help and suggestion.
for an assignment I have to display an image using imagej in java. So I used the following code:
FloatProcessor abc=new FloatProcessor(imageSizeX,imageSizeY);
for (int i=0;i<imageSizeX;i++){
for(int j=0;j<imageSizeY;j++){
abc.putPixel(i, j, 100);
}
}
ImagePlus im=new ImagePlus("test",abc);
im.show();
but the Image I get is always completely black. Can you tell me what the mistake is?
It should at least be white if the value was 0 shouldn't it?
(FYI: imageSizeX=imageSizeY=256)
.putPixel uses the conversion Float.intBitsToFloat.
If you want a direct access to the pixels, you can use setf(int x, int y, float value).
Moreover, if you already have the pixels into an array, you can use the constructors to immediately set the pixel values FloatProcessor(int width, int height, int[] pixels).
I was making a Gauroud algorithm and when i had calculated point intensity on the edge I didn't know what to do with it. I tried to decide this problem like:
private int getPointRGB(double intensity)
{
float[] hsb=null;
double newCrRed;
double newCrGr;
double newCrBlue;
int nRGB;
//crRed, crGr, crBlue - primary components of edge RGB
newCrRed = intensity*crRed;
newCrGr = intensity*crGr;
newCrBlue = intensity*crBlue;
hsb = Color.RGBtoHSB((int)newCrRed, (int)newCrGr, (int)newCrBlue, null);
nRGB = Color.HSBtoRGB(hsb[0], hsb[1], hsb[2]);
return(nRGB);
}
am I right?
If none of the default color choosers are satisfactory, you can create your own custom chooser panel, as discussed in How to Use Color Choosers: Creating a Custom Chooser Panel. For example, you could implement the CIE 1976 color space, shown here.