Sarah
Sarah

Reputation: 145

Construct ellipse from rectangle

I'm making a program that's a bit like Paint light, and I've gotten to the point where I want the user to be able to select elliptical regions. My initial thought is that there must be some kind of equation that allows me to construct an ellipse based on the width and height of a rectangle. However, I've thus far not found anything quite so straight forward.

Here is my code for selecting a rectangular region when the user drags the mouse (this is located inside a MouseAdapter):

        @Override
        public void mouseDragged(MouseEvent e) {
               dragPoint = e.getPoint();
               if (selectionType.equalsIgnoreCase("Rectangle")) {
                int width = dragPoint.x - mouseAnchor.x;
                int height = dragPoint.y - mouseAnchor.y;
                subHeight = height;
                subWidth = width;
                int x = mouseAnchor.x;
                int y = mouseAnchor.y;

                if (width < 0) {
                    x = dragPoint.x;
                    width *= -1;
                }
                if (height < 0) {
                    y = dragPoint.y;
                    height *= -1;
                }
                selectionPane.setBounds(x, y, width, height);
                selectionPane.revalidate();
                repaint();
            }
  }

SelectionPane is an instance of a custom class that extends JPanel. The idea is that I want to draw a filled ellipse from the selected region, so the user can see what they've selected.

The second part of this program is where I'm also hitting some confusion. After the user makes his or her selection, I want to apply a mask to the image bits using the selected region as a guide. So I'm also working with byte arrays. How do I find which bytes are encompassed in a calculated oval based on the width, height, and origin of the sub image? Below is the code where I get the sub image based on a rectangular selection (for reference):

        @Override
        public void mouseReleased(MouseEvent e) {
            if (subWidth != 0 && subHeight != 0) {
                try {
                    //numCols * (numRows - 1) + xPos
                    int startPos = img.getWidth() * (img.getHeight() - 1) + mouseAnchor.x;//the starting position for the total byte array of the original image. The mask will start here.
                    Main.setStartingPos(startPos);
                    Main.setSubImage(img.getSubimage(mouseAnchor.x, mouseAnchor.y, Math.abs(subWidth), Math.abs(subHeight)));
                    ByteArrayOutputStream baos = new ByteArrayOutputStream();
                    ImageIO.write(Main.getSubImage(), "bmp", baos);
                    Main.setImageRegion(baos.toByteArray()); //sets the region bytes in the Main class

                    Main.generateImageMask();//generates the mask after everything's been calculated. 
                } catch (IOException ex) {
                    Logger.getLogger(SelectionRectangle.class.getName()).log(Level.SEVERE, null, ex);
                }
            }
        }

Let me know if there's any way I can make my question more clear.

Upvotes: 0

Views: 491

Answers (2)

gpasch
gpasch

Reputation: 2682

You can get the ellipse from the rectangle as follows:

Ellispe2D.Double el=new Ellispe2D.Double(x, y, width, height);

Then you can mask the positions covered under the ellipse as follows:

Rectangle r=el.getBounds();
for(i=0; i<r.width; i++)
  for(j=0; j<r.height; j++)
    if(el.contains(r.x+i, r.y+j)) ... do whatever with this pixel add it to a list etc

--

For pixel r.x+i, r.y+j you can get the RGB and from this the individual bytes:

int pixel=image.getRGB(r.x+i, r.y+j);
int red=(pixel&0x00ff0000)>>16, green=(pixel&0x0000ff00)>>8, blue=pixel&0x000000ff; 

Upvotes: 1

Spektre
Spektre

Reputation: 51845

for axis alligned ellipse use parametric equation (centric)

x = x0 + rx*cos(a)
y = y0 + ry*sin(a)


x0,y0 is ellipse center
rx,ry are semi axises sizes (half size of your rectangle sides)
a is angle of point you want to obtain

the region is usually selected by angle interval. The angles are usually determined by a line from center (x0,y0) to actual mouse position (mx,my) or some control point as

ai = atan2(my-y0,mx-x0)

so a = < a0,a1 > where ai = { a0,a1 } are your interval angles. for full ellipse a =< 0,2*M_PI> [rad]

That is just circle approximation of angle so if you want to get more precise angle look for

Or apply circle/ellipse correction scaling ...

Upvotes: 1

Related Questions