I want to crop an image using its x,y coordiates using BufferedImage.getSubimage(x,y,width,height) function in java. But i only have bounding box of an image to crop some part of it.
How can i get x,y coordinates from bounding box using java? Is there any calculation available?
I am giving bounding box values (xMin,yMin,xMax,yMax)(0.46476197,0.46967554,0.8502463,0.67080903 )
How can i get x,y coordinates from bounding box using java? Is there
any calculation available?
If your calculated bounding box coordinates correspond to the image fractions you will first have to calculate the pixel values for xMin, xMax, yMin and yMax.
Using those it is easy to calculate the necessary parameters for the functionBufferedImage.getSubimage(x,y,width,height).
x and y correspond to the upper left corner of the bounding box, therefore:
x = xMin and y = yMin
The width of the box can be calculated using the image width and substracting the left space length leading to the box as well as the right space length where the box ends, therefore you can calculate it using the formula:
width = imageWidth - xMin - (imageWidth - xMax)
Same goes for the height, just use the y-coordinates instead:
height = imageHeight - yMin - (imageHeight - yMax)
I am multiplying bounding box values with image width and height respectively to get its pixel values.
int y1 = yMin * ImageHeight;
int x1 = xMin * ImageWidth;
int y2 = yMax * ImageHeight;
int x2 = xMax * ImageWidth;
And applied the values to below given formula
BufferedImage.getSubimage((int)x1, (int)y1, (x2-x1), (y2-y1));
Thanks gilbert for giving solution to get pixel values.
Related
I am creating a Cartesian Coordinate graph using NumberAxis to create an x and y axis in a LineChart, and use getDisplayPosition to find the distance between two points along the x axis and two points along the y axis. The differences do not equal each other.
I set upper/lower bounds of the x and y axis to be the same with the same tickUnit setting. Visually, the grid looks square and equal on all sides but I cannot seem to make them exactly equal.
Here is how I set NumberAxis for x and y within my linechart:
xAxis.setLowerBound(-2.4);
xAxis.setUpperBound(2.4);
xAxis.setTickUnit(.1);
xAxis.setSide(Side.BOTTOM);
xAxis.setAutoRanging(false);
yAxis.setLowerBound(-2.4);
yAxis.setUpperBound(2.4);
yAxis.setTickUnit(.1);
yAxis.setSide(Side.LEFT);
yAxis.setAutoRanging(false);
LineChart linechart = new LineChart<Number,Number>(xAxis, yAxis);
Here is how I convert inputs for a rectangle to be displayed properly
private Rectangle calcRectangle(SectionRectangle rectangle){
double xPosition = xAxis.getDisplayPosition(rectangle.getXorigin());
double yPosition = yAxis.getDisplayPosition(rectangle.getYorigin());
double xCoord = xPosition + chartZeroX;//x origin of rectangle
double yCoord = yPosition + chartZeroY;//y origin of rectangle
double width = rectangle.getXorigin() + rectangle.getWidth();
double widthPosition = xAxis.getDisplayPosition(width);
double heightPosition = yAxis.getDisplayPosition(rectangle.getYorigin() + rectangle.getHeight());
Rectangle calculatedRectangle = new Rectangle(xCoord, yCoord - (yPosition - heightPosition), widthPosition - xPosition, yPosition - heightPosition);
calculatedRectangle.setFill(Color.TRANSPARENT);
Rotate rotate = new Rotate();
rotate.setAngle(360 - rectangle.getRotation());
rotate.setPivotX(xPosition + chartZeroX);
rotate.setPivotY(yPosition + chartZeroY);
calculatedRectangle.getTransforms().add(rotate);
calculatedRectangle.setStroke(Color.BLACK);
return calculatedRectangle;
And here is how I add the shape onto the graph
Pane chartContent = (Pane) linechart.lookup(".chart-content");
Rectangle rectangle = calcRectangle(rectangleData);
chartContent.getChildren().add(rectangle);
Without rotating, the rectangle will be displayed to scale as expected, but because of the slight variance in pixel width vs pixel height, rotating 90 degrees causes the rectangle to measure taller than it had measured wide.
Here is a more precise example of the issue
double xdiff = xAxis.getDisplayPosition(1) - xAxis.getDisplayPosition(0);
double ydiff = yAxis.getDisplayPosition(0) - yAxis.getDisplayPosition(1);
here xdiff = 195.208 and ydiff = 191.041
Hoping for some way to force the x and y axis to maintain exact equal distance.
I solved my own problem by controlling the height and width of the linechart:
linegraph.setPrefHeight(850);
linegraph.setMinHeight(850);
linegraph.setMaxHeight(850);
linegraph.setMinWidth(853);
linegraph.setMaxWidth(853);
linegraph.setPrefWidth(853);
linegraph.setPrefSize(853, 850);
linegraph.setMinSize(853, 850);
linegraph.setMaxSize(853, 850);
I did a check of the distance between x=0, x=1 and y=0, y=1 using:
double xlength = xAxis.getDisplayPosition(1) - xAxis.getDisplayPosition(0);
double ylength = yAxis.getDisplayPosition(0) - yAxis.getDisplayPosition(1);
I slowly incremented my width until both lengths were equal.
When I set the image with actual size onto a panel and cropping using mouse it's working fine but when I resize image onto panel and cropping it's getting wrong cropping image. How to crop resize image using mouse?
int x = Math.min(p1.x, p2.x);
int y = Math.min(p1.y, p2.y);
int w = Math.abs(p1.x - p2.x);
int h = Math.abs(p1.y - p2.y);
BufferedImage dest = image.getSubimage(x,y,w,h)
If you want to crop from the original image then you will need to calculate the x/y scale factors of the two images. Then you will need to adjust the x/y/width/height values by these scale factors.
So if your original image is 400 x 100 and the resized image is 100 x 100 you would do something like:
double xScale = originalImageWidth / resizeImageWidth = 400 / 100 = 4.
So now if the cropping rectangle on the resized image is (10, 10, 20, 30);
Then you need to calculate your values something like:
int x = rectangle.x * xScale;
int width = rectangle.width * xScale;
image.getSubImage(x, y, width, height);
You would obviously need to calculate the y / height values using the y scaling factor.
I need to draw a simple histogram for a project I'm working on that needs to look this...
I know there is got to be some simple for loop to run on my H[] array which consists of how many pixels belong to each gray scale value... so in H[] we have lets say "10 pixels in gray scale value 1" so at 1 there would be a line of length 10 going vertically next to my image...
if anyone could offer their help, I would greatly appreciate it!
Thanks.
wrote this but its too big and upside down and angled for some reason.
if (H != null) {
int width = getWidth();
int height = getHeight();
int HhPos = (width - (width/2));
int HvPos = (height - (height));
for(int i = 0 ; i <255 ; i++){
g.drawRect(i+HhPos, i+HvPos, 1, H[i]);
}
As Gilbert said, you need to normalize you values, to determine the maximum range or ceiling.
From this you can then determine the percentage of a given value compared to the maximum and then plot it on the graph, based on the available height.
(Taken from the previous answer to this question)
// Determine the maximum vertical value...
int maxValue = 0;
for (Integer key : mapHistory.keySet()) {
int value = mapHistory.get(key);
maxValue = Math.max(maxValue, value);
}
int xPos = xOffset;
for (Integer key : mapHistory.keySet()) {
int value = mapHistory.get(key);
// Calculate the percentage that the given value uses compared to that of the
// maximum value
float percentage = (float)value / (float)maxValue;
// Calculate the line height based on the available vertical space...
int barHeight = Math.round(percentage * height);
g2d.setColor(new Color(key, key, key));
int yPos = height + yOffset - barHeight;
Rectangle2D bar = new Rectangle2D.Float(xPos, yPos, barWidth, barHeight);
g2d.fill(bar);
g2d.setColor(Color.DARK_GRAY);
g2d.draw(bar);
xPos += barWidth;
}
Now in the previous example, I used a Map to to store the values, but it should relativly easy to replace that with your data array...
for (Integer key : mapHistory.keySet()) would become for (int key : H)
Also, with Graphics.drawLine, it is drawing a line from one point to another, not one point to a width/height value (like say Graphics.drawRectangle)
You're plotting points that have an x and y value. You're drawing a histogram that has a width and height in pixels.
For example, let's say your histogram is 500 pixels in width, and 300 pixels in height.
You go through your data points once, looking for the minimum x, minimum y, maximum x, and maximum y.
Assuming we're plotting Y points (the X axis is the width), you subtract the minimum x from the maximum x. Divide 500 pixels (the width) by the difference, and you get the number of pixels per x value. This number can be greater than one, so you have more than one pixel per x value. This number can be less than one, so you have more data values than pixels.
width pixels per value = width of histogram in pixels / difference in X points
You do the same for the Y axis. Calculate the pixels per y value.
height pixels per value = height of histogram in pixels / difference in y points
Now, you go through your data points a second time. For each data point, you calculate the width and height in pixels from the x and y value of the data point. You use the number of pixels per value for both the width and the height to make the conversion.
width = x value * width pixels per value
height = y value * height pixels per value
You use the Java Graphics drawLine or drawRect method to draw the line or bar in your histogram. Just remember that the Y dimension in Java graphics goes down, rather than up like in your histograph. You'll have to take this into account when you're drawing.
I've created a graph using java and swing but it is only good for showing positive numbers and some negative numbers less than -14 the idea that I've used was :
create a box
add my X and Y axis label
get an array of numbers
get max number for indicating the max number in the array
create an scale using following code :
double scale = (double)(height - 2*borderSpace)/getMax();
and then plot my line graph , above solutions is perfect for positive values for negative values I did a trick
int height2 = getHeight() - getHeight()/2;
double scale = (double)(height2 - 2*borderSpace)/getMax();
which is only works till -14 not less than that.
for drawing lines I use this code
//borderspace = 20
double xInc = (double)(width - 2*borderSpace)/(data.length-1);
double scale = (double)(height - 2*borderSpace)/getMax();
g2.setPaint(Color.green.darker());
for(int i = 0 ; i < data.length-1; i++) {
double x1 = borderSpace + i*xInc;
double y1 = height - borderSpace - scale*data[i];
double x2 = borderSpace + (i+1)*xInc;
double y2 = height - borderSpace - scale*data[i+1];
g2.draw(new Line2D.Double(x1, y1, x2, y2));
}
I want to have the box but Y axis should be on the left side( I don't want to change the Y axis place) and I just want to change the place X axis in case of having negative numbers
for making it more clarify you can have a look at this picture :
You might want to take a look at JFreeChart to create your graphs rather than trying to brew your own solution from scratch.
I have two points of circle and center of this circle. I want to draw an arc between these points. Method drawArc is to simple and doesn't fit my purpose.
Anybody help?
You can use Canvas.drawArc, but you must compute the arguments it needs:
Lets say that the center of the circle is (x0, y0) and that the arc contains your two points (x1, y1) and (x2, y2). Then the radius is: r=sqrt((x1-x0)(x1-x0) + (y1-y0)(y1-y0)). So:
int r = (int)Math.sqrt((x1-x0)*(x1-x0) + (y1-y0)*(y1-y0));
int x = x0-r;
int y = y0-r;
int width = 2*r;
int height = 2*r;
int startAngle = (int) (180/Math.PI*atan2(y1-y0, x1-x0));
int endAngle = (int) (180/Math.PI*atan2(y2-y0, x2-x0));
canvas.drawArc(x, y, width, height, startAngle, endAngle);
Good luck!
Graphics.drawArc expects the following parameters:
x
y
width
height
startAngle
arcAngle
Given your arc start and end points it is possible to compute a bounding box where the arc will be drawn. This gives you enough information to provide parameters: x, y, width and height.
You haven't specified the desired angle so I guess you could choose one arbitrarily.