Archived

This topic is now archived and is closed to further replies.

darrinps

[java] OK, I'll try it another way. Again, how to draw a line.

Recommended Posts

I think that I have been asking the wrong question over the past week and a half with respect to drawing a line on a zoomed image. Here is the question I THINK I need to ask. We have an image which has been zoomed. No lines are yet drawn on it. A line is added. The image is then zoomed in or out one more time. How do we get the line to remap to the newly zoomed image? What I am doing is: 0) Load up an image from a file. 1) Create a zoomed image by using the Image.getScaledInstance() method. 2) Create a BufferedImage with the width and height of the image AFTER the zoom has taken place. 3) Create a Graphics2D object by the createGraphics from this BufferedImage. 4) Place the image into the BufferedImage by doing a BufferedImage.drawImage 5) Select two points to be the start and end of the line. 6) Draw the line using Graphics2D.drawLine(start.x, start.y, end.x, end.y). 7) Zoom the image again (using the Image.getScaledInstance() method. 8) Create a new ImageIcon using the image from above and override its paintIcon method like this:
ImageIcon newIcon = new ImageIcon(newImage)
                     {
                        public void paintIcon(Component c, Graphics g, int x, int y)
                        {
                           super.paintIcon(c, g, x, y);
//********************************
                           zoom(); //<---- ZOOM call
//********************************
                        }
                      };
   
Now in the zoom routine, what do I need to do to get the lines to draw at the proper location and size? Remember, the points of the lines (stored in a list as home grown line objects) are in screen coordinates, not image coordinates since they are just click points Note that when I use these points to draw a line, all is well (the line gets drawn where it should), but I have problems when I zoom the image. Thanks! [edited by - darrinps on August 13, 2003 10:38:21 AM]

Share this post


Link to post
Share on other sites
You already have the concepts to get it working, just need the details. There are two sets or coordinate systems, the image coordinates and the screen (or window) coordinates.

When you draw a line on the image, it is probably recorded in screen coordinates like you said. You need to convert these to image coordinates and save them like this. Then every time you draw the line, convert the image coordinates back into screen coordinates. This way, no matter how you are viewing your image; rotated, scaled, shifted, whatever, the line will appear in the correct place.

The transformation from image to screen and viceversa is just a set of 2D matrix operation sthat should be easily reversible.

Share this post


Link to post
Share on other sites
Thanks for a response!!!!!!!!!!!!!

Ok, I need to put everything in image coordinates instead of screen.

How can I convert from screen to image and back again? You mentioned a 2D matrix, are you talking about using the AffineTransform class?

Here is what I have now in my code that does the draw. It has access to anOraImage which holds the image being used and the modifications (the lines) that need to be applied to it. The GraphicsTransformInfo object holds everything I need (the view's size, the Grapchics2D object, etc.


public BufferedImage applyModifications(GraphicTransformInfo gti, boolean apply)
{
ImageIcon icon = oraImage.getImageIcon();
BufferedImage bi = new BufferedImage(oraImage.getOriginalImageWidth(),
oraImage.getOriginalImageHeight(),
BufferedImage.TYPE_INT_ARGB);

ImageModHolder mods = oraImage.getImageModHolder();

Graphics2D g2D = gti.getGraphics2D();

Iterator shapeIter = mods.getShapeList().iterator();

while(shapeIter.hasNext())
{
OraShape shape = (OraShape)shapeIter.next();
shape.draw(gti);
}
}

//Draw is found in a shape derived line class
public void draw(GraphicTransformInfo gti)
{
Graphics2D g2D = gti.getGraphics2D();
g2D.setColor(color);
g2D.setStroke(new BasicStroke(shapeSize));

g2D.drawLine(begin.x, begin.y, end.x, end.y);

}


So, I take it that I need to do adjust the begin and end points from screen to image before I get to the draw method, and then inside of this method, adjust from image to screen.

That's where I'm lost. Say I have the following where begin and end are in screen coordinates.


private void convertClickedPoints(Point begin, Point end)
{
//What goes here
}


What do I put in this to convert the points to image coordinates?

Also, in the draw above, how to I convert the points which are now (once you tell me how) in image coordinates back to the screen?

Thanks!

That should do it!


[edited by - darrinps on August 13, 2003 12:35:39 PM]

Share this post


Link to post
Share on other sites
quote:
Original post by darrinps
private void convertClickedPoints(Point begin, Point end)
{
//What goes here

//these should be global to the class

Point imageBegin=new Point();
Point imageEnd=new Point();

imageBegin.x=originalWidth/scaledWidth*begin.x;
imageBegin.y=originalHeight/scaledHeight*begin.y;
imageEnd.x=originalWidth/scaledWidth*end.x;
imageEnd.y=originalHeight/scaledHeight*end.y;
//or you could convert them and overwrite the points passed in


}

Share this post


Link to post
Share on other sites
Ok,

I did this:


private void convertFromScreenToImage()
{
//Go through every point and convert it from screen coordinates to the image
JScrollPane jsp = (JScrollPane) m_tabbedPane.getSelectedComponent();
JViewport port = jsp.getViewport();
GrabAndScrollLabel gnsLabel = (GrabAndScrollLabel) m_port.getView();

for(int n = 0; n < m_clickPointCount; n++)
{
System.out.println("Point was " + m_clickPointArray[n].x + ", " +
m_clickPointArray[n].y);

Point newPoint = new Point();

newPoint.x = gnsLabel.getOraImage().getOriginalImageWidth() /
gnsLabel.getOraImage().getImageIcon().getIconWidth() *
m_clickPointArray[n].x;

newPoint.y = gnsLabel.getOraImage().getOriginalImageHeight() /
gnsLabel.getOraImage().getImageIcon().getIconHeight() *
m_clickPointArray[n].y;

m_clickPointArray[n] = newPoint;

System.out.println("Point is now " + m_clickPointArray[n].x + ", " +
m_clickPointArray[n].y);

}

}


Now, what about the draw method? Don't I need to convert back from image to screen there? These converted points (really just two points for now, index 0, and index 1) create a home grown line object. So...


//Inside home grown line object
public void draw(GraphicTransformInfo gti)
{
Graphics2D g2D = gti.getGraphics2D();
g2D.setColor(color);
g2D.setStroke(new BasicStroke(shapeSize));

int offsetX = ?????
int offsetY = ?????

g2D.drawLine(begin.x + offsetW,
begin.y + offsetH,
end.x + offsetW,
end.y + offsetH);
}



What goes where the ?????? are?

That will finally do it I HOPE.

Thanks.

[edited by - darrinps on August 13, 2003 2:08:18 PM]

Share this post


Link to post
Share on other sites
Here is what I tried (didn''t quite work).


public void draw(GraphicTransformInfo gti)
{
Graphics2D g2D = gti.getGraphics2D();
g2D.setColor(color);
g2D.setStroke(new BasicStroke(shapeSize));

double zoom = gti.getZoom();

Point begin2 = new Point();
Point end2 = new Point();

begin2.x = begin.x * gti.getOriginalImageWidth() / gti.getImageWidth();
begin2.y = begin.y * gti.getOriginalImageHeight() / gti.getImageHeight();

end2.x = end.x * gti.getOriginalImageWidth() / gti.getImageWidth();
end2.y = end.y * gti.getOriginalImageHeight() / gti.getImageHeight();

g2D.drawLine(begin2.x,
begin2.y,
end2.x,
end2.y);

}



Also note that in my zoom method I scale before the draw gets called like this:


public BufferedImage applyModificationsZoom(GraphicTransformInfo gti, boolean apply)
{
ImageIcon icon = oraImage.getImageIcon();
BufferedImage bi = new BufferedImage(oraImage.getOriginalImageWidth(),
oraImage.getOriginalImageHeight(),
BufferedImage.TYPE_INT_ARGB);

ImageModHolder mods = oraImage.getImageModHolder();
Graphics2D g2D = gti.getGraphics2D();

g2D.scale(mods.getZoomFactor(), mods.getZoomFactor());

Iterator shapeIter = mods.getShapeList().iterator();

while(shapeIter.hasNext())
{
OraShape shape = (OraShape)shapeIter.next();
shape.draw(gti);
}

return bi;
}



That shape.draw is where the draw above gets called.

Note that the other applyModifications call (the one for drawing a line..not zooming) works fine for the line being drawn, but is redraws the old line (if there were any) in the wrong location.

The zoom hoses all of the lines!

So, I''m back to exactly where (maybe a little worse) I was over a week ago. I got the line to draw really quick but since then WASTED time.

Any help is GREATLY appreciated. I''m soon to give up on this and maybe use a 2D package of some sort.

Thanks.

Share this post


Link to post
Share on other sites
Maybe you should try another approach. Use a backbuffer. Draw the image to it, then draw the line to it. Then scale the backbuffer to whatever zoom level you want.



First make it work,
then make it fast.

--Brian Kernighan

"I’m happy to share what I can, because I’m in it for the love of programming. The Ferraris are just gravy, honest!" --John Carmack: Forward to Graphics Programming Black Book

Share this post


Link to post
Share on other sites