I am working on a program where I take RGB values from a portion of an image. I want to remove the darkness in the color and make it bright. What I do is I use Color.RGBtoHSB I then take the brightness channel and set it to the highest value it can be in range then convert the HSB back to RGB. However, when I do this the color changes completely. Here is an example with dark red and it turning to purple and the code I use to do this.
System.out.println("Before Conversion:");
System.out.println("R: " + rAvg + "\nG :" + gAvg + "\nB :" + bAvg);
Color.RGBtoHSB(rAvg, gAvg, bAvg, hsv);
hsv[2] = 100; //Set to max value
System.out.println("H: " + hsv[0] * 360 + "\nS: " + hsv[1] * 100 + "\nV :" + hsv[2]);
int rgb = Color.HSBtoRGB(hsv[0], hsv[1], hsv[2]);
System.out.println("After conversion");
Color color = new Color(rgb);
System.out.println("R: " + color.getRed());
System.out.println("G: " + color.getGreen());
System.out.println("B: " + color.getBlue());
Output:
Before Conversion:
R: 128
G :39
B :50
H: 352.58426
S: 69.53125
V :100.0
After conversion
R: 158
G: 126
B: 233
The brightness, hsv[2], needs to be a value between 0 and 1. Try these two lines of code:
hsv[2] = 1; //Set to max value
System.out.println("H: " + hsv[0] * 360 + "\nS: " + hsv[1] * 100 + "\nV :" + hsv[2] * 100);
Related
I'm extracting images from the PDF page using the PDFBox. In the example I used as a basis (PrintImageLocations), the value of 72 dpi is used for calculation. My question is, where does this value 72 come from?
// position in user space units. 1 unit = 1/72 inch at 72 dpi
System.out.println("position in PDF = " + ctmNew.getTranslateX() + ", " + ctmNew.getTranslateY() + " in user space units");
// raw size in pixels
System.out.println("raw image size = " + imageWidth + ", " + imageHeight + " in pixels");
// displayed size in user space units
System.out.println("displayed size = " + imageXScale + ", " + imageYScale + " in user space units");
// displayed size in inches at 72 dpi rendering
imageXScale /= 72;
imageYScale /= 72;
System.out.println("displayed size = " + imageXScale + ", " + imageYScale + " in inches at 72 dpi rendering");
// displayed size in millimeters at 72 dpi rendering
imageXScale *= 25.4;
imageYScale *= 25.4;
System.out.println("displayed size = " + imageXScale + ", " + imageYScale + " in millimeters at 72 dpi rendering");
Not the most technical of answers... but its been a "standard" for some time... one that is arbitrary and rather silly... Here's a random article that talks about its silliness.
https://petapixel.com/2020/02/13/why-wont-the-72dpi-myth-die/
PDF is closer to being a collection of pixels like a bitmap, than it is to being a token based document like a text file. So for sizing elements on the screen/page it has to assume certain resolution... Because 72dpi was so prevalent for images for so long it makes sense that pdf followed suit.
I am working on a 3D LibGDX project, and am trying to manipulate the vertices of a 3D model. I have the model loading, and I have this as my code:
Model plain = assets.get("plain.g3db", Model.class);
for(Mesh m : plain.meshes){
float[] t = m.getVertices(new float[m.getMaxVertices()]);
float[] newVerticies = new float[m.getMaxVertices()];
for(int i = 0; i < t.length-1; i++){
newVerticies[i] = t[i];
System.out.println("X: " + t[i] + " " + i);
newVerticies[i] = t[i];
System.out.println("Y: " + t[i++] + " " + i);
newVerticies[i] = random.nextInt(1-0) + 0;
System.out.println("Z: " + t[i++] + " " + i);
newVerticies[i] = t[i];
System.out.println("R: " + t[i++]);
newVerticies[i] = t[i];
System.out.println("G: " + t[i++]);
newVerticies[i] = t[i];
System.out.println("B: " + t[i++]);
newVerticies[i] = t[i];
System.out.println("A: " + t[i++]);
}
m.setVertices(newVerticies);
}
That does not work how I want it to, but I can at least see the model. If I comment out these lines:
newVerticies[i] = t[i];
System.out.println("R: " + t[i++]);
newVerticies[i] = t[i];
System.out.println("G: " + t[i++]);
newVerticies[i] = t[i];
System.out.println("B: " + t[i++]);
newVerticies[i] = t[i];
System.out.println("A: " + t[i++]);
I just get a black screen. Even if I move around, I see nothing. What I want to know, is what exactly float[] t = m.getVertices(new float[m.getMaxVertices()]); outputs. How does the output correspond to the model? How can I make the Y value random within a range?
Mesh data is organized into VertexAttributes. These always include position, but can also include color, texture coordinates, normals, etc. For example, a mesh with a texture might have the following:
A Position VertexAttribute of size 3 for X, Y, and Z (it's possible to have a 2D mesh where the position attribute has only 2)
A TextureCooridantes VertexAttribute of size 2 for U and V
A Normal VertexAttribute with size 3 for X, Y, and Z
So the float array you get with mesh.getVertices() would be this set of 8 floats for each vertex, one after the other.
If you loaded your Mesh from a model file rather than constructing it manually, you might not be sure of what VertexAttribute setup it has, so you need to inspect it to find out what the offset of the attribute you want is:
int positionOffset = mesh.getVertexAttributes().getOffset(Usage.Position);
int yOffset = positionOffset + 1; //skip X
int vertexSize = mesh.getVertexSize() / 4; //divide to convert bytes to floats
Now if you wanted to change Y, you would loop through the vertices something like this:
//this is how to get the properly sized mesh:
float[] vertices = new float[mesh.getNumVertices() * mesh.getVertexSize() / 4];
mesh.getVertices(vertices);
for (int i = yOffset; i < vertices.length; i += vertexSize){
vertices[i] += someValue;
}
mesh.setVertices(vertices);
The indices indicate groups of three vertices that make up the triangles of the mesh. If there are vertices on your mesh that are the same on multiple triangles, they might appear in the vertices list only once. This typically happens on soft-shaded vertices of a mesh, since the UV and normal will be the same for all the adjacent triangles touching that vertex.
I'm currently developing a little android game. It is about shooting down enemy aircraft. I'm drawing the content of the actual game with the build in Android Canvas. To tell the user his score and other information, I use
canvas.drawText(...);
My problem is that, after a short time, the text is drawed at a wrong x-coordinate. I checked the affected variables and they have the correct values stored.
This is the sourcecode:
c.drawText(this.you + ": " + this.activity.getLocalScore(), GameActivitySinglePlayer.SCREEN_WIDTH * 0.02f, GameActivitySinglePlayer.SCREEN_HEIGHT * 0.07f, this.smallText);//works
c.drawText(this.enemy + ": " + this.activity.getAndroidScore(), GameActivitySinglePlayer.SCREEN_WIDTH * 0.8f, GameActivitySinglePlayer.SCREEN_HEIGHT * 0.07f, this.smallText);//works
c.drawText(this.oldFps + " FPS", GameActivitySinglePlayer.SCREEN_WIDTH * 0.45f, GameActivitySinglePlayer.SCREEN_HEIGHT * 0.05f, this.smallText);//works sometime
c.drawText(this.activity.lives + " " + this.lives, GameActivitySinglePlayer.SCREEN_WIDTH * 0.45f, GameActivitySinglePlayer.SCREEN_HEIGHT * 0.091f, this.smallText);//works sometime
c.drawText("Level " + this.activity.level, GameActivitySinglePlayer.SCREEN_WIDTH * 0.45f, GameActivitySinglePlayer.SCREEN_HEIGHT * 0.132f, this.smallText);//works sometime
System.out.println("width: " + GameActivitySinglePlayer.SCREEN_WIDTH + " height " + GameActivitySinglePlayer.SCREEN_HEIGHT); //Prints correct values (1280 and 720)
Here is a combined image of the fail
Please note that I added the red rectangles afterwards to improve visibility of the error.
Thank you for any help and improvement proposals.
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 7 years ago.
Improve this question
I'm doing a Java exercise, and I need to display a persons height in both inches and cm, as well as their weight in both pounds and kg.. Here's what I came up with, but I'm getting tons of errors.
Height = 74; // inches
Weight = 180; // pounds
System.out.println( "He's " + Height + " inches or + (Height * 2.54) cm tall "." );
I got the 2.54 by just googling what the conversion was for inches to cm. I basically did the same thing for the weight (see below)
System.out.println( "He's " + Weight + " pounds or + (Weight * 2.20) kg heavy "." );
My goal is to get it to display:
He's 74 inches (or 187.96 cm) tall.
He's 180 pounds (or 81.6466266 kg) heavy.
Any help would be great, and sorry for such a basic question!
There are a couple of glaring syntax errors here:
System.out.println( "He's " + Height + " inches or + (Height * 2.54) cm tall "." );
Notice how the syntax highlighting on this page points them out. (Your IDE really should be doing that too.) You close a string at the end, then have a random . character and open another string which you never close.
You can fix the syntax errors by removing a quote:
System.out.println( "He's " + Height + " inches or + (Height * 2.54) cm tall ." );
However, this doesn't yet give you the output you want. Because this is just a string:
" inches or + (Height * 2.54) cm tall ."
Java isn't going to perform that calculation, as far as Java is concerned this is just text. You need to separate the string just like you already are for your other use of the variable:
System.out.println( "He's " + Height + " inches or " + (Height * 2.54) + " cm tall." );
System.out.println( "He's " + Height + " inches or ("+ (Height * 2.54)+" ) cm tall." );
Remember that you must do the conversion (without Strings quotes) before concatenate with text. The final dot is not needed.
First off, you need to define what datatype your variables are. You can't have "Height", you need to have "int Height".
It's also easier if you set variables for both height and weight in their respective units. So you should have a variable for height in inches, and then a variable for height in centimeters.
Here's my solution:
public static void main(String[] args) {
int inHeight = 74;
double cmHeight = inHeight * 2.54;
int lbWeight = 180;
double kgWeight = lbWeight / 2.2;
System.out.println("He's " + inHeight + " inches (or " + cmHeight + " cm) tall.");
System.out.println("He's " + lbWeight + " pounds (or " + kgWeight + " kg) heavy.");
}
Note: two of the variables are doubles, so if you want to correctly format those to two decimal places, you'll have to use "printf" instead of "println".
You're writing text instead of a variable's value:
System.out.println( "He's " + Height + " inches or + (Height * 2.54) cm tall "." );
Change it to:
System.out.println( "He's " + Height + " inches or (" + (Height * 2.54) + " cm) tall.");
The same goes for the weight line:
System.out.println( "He's " + Weight + " pounds or + (Weight * 2.20) kg heavy "." );
Should be:
System.out.println( "He's " + Weight + " pounds or (" + (Weight * 2.20) + " kg) heavy.");
And please follow Java naming conventions:
Except for variables, all instance, class, and class constants are in mixed case with a lowercase first letter. Internal words start with capital letters. Variable names should not start with underscore _ or dollar sign $ characters, even though both are allowed.
From the above: variable names should start with a lower case
You should also read How to concatenate characters in Java
This might answer your question, it is a bit vague, so I am mostly guessing.
System.out.println( "He's " + Height + " inches or (" + Height * 2.54 + ") cm tall." );
You had formatted your println pretty badly. It is the same for the later one, I suggest having a look at it and figuring that one out by yourself.
Also I have no clue of what unit of measurement you are using for your Weight and Height, I recommend a double for this scenario. If you want more precision you have to look up on BigDecimal.
Normally variables and fields are written in lowerCamelCase in Java.
try this:
System.out.println( "He's " + Height + " inches or " + (Height * 2.54) + " cm tall "." );
Double Height = 74D; // inches
Double Weight = 180D; // pounds
System.out.println( "He's " + Height + " inches or " + (Height * 2.54) + " cm tall "." );
System.out.println( "He's " + Weight + " pounds or " + (Weight * 2.20) + " kg heavy "." );
I've created a huge list of colours with names and RGB values (Took a very long time) now I've created an algorithm that gets the corresponding colour to the closest values.
It seems to work very well BUT sometimes when there's an odd value that's completely out it gets the wrong colour.
Example output
Log: InputRGB: R:7.1009636 | G:83.84344 | B:2.5013387
Log: ColorToCompare: Ball Blue (R13.0,G67.0,B80.0) CLOSE:0.4588677 | CurrentColor: Acid Green CLOSE: 0.41585693
Log: ColorToCompare: Bitter Lemon (R79.0,G88.0,B5.0) CLOSE:0.5143066 | CurrentColor: Ball Blue CLOSE: 0.4588677
Log: ColorToCompare: Citrine (R89.0,G82.0,B4.0) CLOSE:0.5610447 | CurrentColor: Bitter Lemon CLOSE: 0.5143066
Log: ColorToCompare: Smoky Black (R6.0,G5.0,B3.0) CLOSE:0.57945675 | CurrentColor: Citrine CLOSE: 0.5610447
Log: ColorName:Smoky Black
Log: End Color: R:6.0 G:5.0 B:3.0
Log: InputRGB: R:7.1009636 | G:83.84344 | B:2.5013387
The code I've created to calculate this:
public String getClosetColor(float red, float green, float blue){
Functions.log("InputRGB: R:" + red + " | G:" + green + " | B:" + blue);
Color lastColor = null;
for(Color eachColor : this.colors)
{
if(lastColor == null){
lastColor = eachColor;
}
float lastColorCloseness = (getClose(red, lastColor.red) + getClose(green, lastColor.green) + getClose(blue, lastColor.blue)) / 3f;
float thisColorCloseness = (getClose(red, eachColor.red) + getClose(green, eachColor.green) + getClose(blue, eachColor.blue)) / 3f;
if(Float.isFinite(thisColorCloseness) && Float.isFinite(lastColorCloseness))
{
//If they are the same, choose a random one.
if(lastColorCloseness == thisColorCloseness){
if(MathUtils.random() > 0.5f){
lastColor = eachColor;
}
}
//If this one is greater then set it.
else if(thisColorCloseness > lastColorCloseness){
Functions.log(
"ColorToCompare: " + eachColor.nameOfColor + " (R" + eachColor.red + ",G" + eachColor.green + ",B" + eachColor.blue + ") CLOSE:" + thisColorCloseness +
" | CurrentColor: " + lastColor.nameOfColor + " CLOSE: " + lastColorCloseness
);
lastColor = eachColor;
}
}
}
Functions.log("ColorName:" + lastColor.nameOfColor);
Functions.log("End Color: R:" + lastColor.red + " G:" + lastColor.green + " B:" + lastColor.blue);
Functions.log("InputRGB: R:" + red + " | G:" + green + " | B:" + blue);
return "";
}
//Basically if one is higher than the other then devide by it.
private float getClose(float firstNumber, float secondNumber){
if(firstNumber < secondNumber){
return firstNumber / secondNumber;
}
else{
return secondNumber / firstNumber;
}
}
I don't know how you came up with your distance function but it's a bit awkward. Let me explain:
You use the ratio of colors instead of the difference like:
float lastColorCloseness = (getClose(red, lastColor.red) + getClose(green, lastColor.green) + getClose(blue, lastColor.blue)) / 3f;
This has the strange effect of not applying equally to equally distanced colors. For example compare
col1(100, 50, 200) with col2(50, 100, 150) and col3(150, 100, 250).
Well, assuming that col2 and col3 have distance from col1 equals:
abs(100-50)+abs(50-100)+abs(200-150)=150
abs(100-150)+abs(50-100)+abs(200-250)=150
your distance function is giving different results:
(50/100+50/100+150/250)/3=0.53
(50/100+50/100+200/250)/3=0.6
And as #David Wallace mentioned it's not the most exaggerated results.
Use a distance function like Euclidean instead.
This is happening because your getClose method isn't doing a good job. If two numbers are both very small, the gap between them is greatly exaggerated.
You'd be much better off doing something like
1 / ( 1 + ( firstNumber - secondNumber ) * ( firstNumber - secondNumber ))
in getClose.
For defining a measure of "closeness", you would need to adjust for human eyes color perception plus possibly the display device.
First, a distance of X in one channel is worse than a distance of X/2 in two channels (a change in tone is more apparent than a comparable change in brightness). The larger a single channel distance the less "similar" the color is. Simply adding differences doesn't accout for that.
A simple to implement measure of distance is the difference between channels squared:
int deltaR = red1 - red2;
int deltaG = green1 - green2;
int deltaB = blue1 - blue2;
int distance = (deltaR * deltaR) + (deltaG * deltaG) + (deltaB * deltaB);
The human eye is not equally sensitive to each color channel. So you might want to adjust weighting color channels for that. A simple weighting can be derived from RGB to grayscale weigthing (Converting RGB to grayscale/intensity)
Modifying distance function for the weights gives:
float distance = (deltaR * deltaR) * 0.2989F
+ (deltaG * deltaG) * 0.5870F
+ (deltaB * deltaB) * 0.1140F;
That should provide a reasonable closeness function. Simply chose the color with smallest color distance.