【问题标题】:Construct ellipse from rectangle从矩形构造椭圆
【发布时间】:2017-02-01 15:00:31
【问题描述】:

我正在制作一个有点像Paint light 的程序,并且我已经到了希望用户能够选择椭圆区域的地步。我最初的想法是,一定有某种方程可以让我根据矩形的宽度和高度构造一个椭圆。但是,到目前为止,我还没有发现任何如此直接的东西。

这是我在用户拖动鼠标时选择矩形区域的代码(位于 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 是扩展JPanel 的自定义类的实例。这个想法是我想从所选区域绘制一个填充的椭圆,以便用户可以看到他们选择的内容。

这个程序的第二部分也是我遇到一些困惑的地方。在用户做出他或她的选择后,我想使用所选区域作为指导对图像位应用掩码。所以我也在使用字节数组。如何根据子图像的宽度、高度和原点找出计算椭圆中包含哪些字节?下面是我根据矩形选择获取子图像的代码(供参考):

        @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);
                }
            }
        }

如果有什么方法可以让我的问题更清楚,请告诉我。

【问题讨论】:

    标签: java image-processing shapes ellipse


    【解决方案1】:

    你可以从矩形中得到椭圆如下:

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

    那么你就可以将椭圆下覆盖的位置屏蔽如下:

    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
    

    --

    对于像素 r.x+i、r.y+j,您可以获取 RGB 并从中获取各个字节:

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

    【讨论】:

    • 看起来这个解决方案可能是最简单的,但由于我正在处理图像的字节数组,有没有办法从矩形中的每个像素中提取字节?我没有看到这个的内置功能。
    • 我只是想到了一些事情。这可能有点奇怪,但是如果我取那个像素位置(r.x+i,r.y+j),并从中制作一个小的子 BufferedImage,然后从那个小小的 BufferedImage 中提取图像字节呢?这行得通吗?
    • 这可以用作极端尺寸的 1x1 图像 - 我不知道你会怎么做 - 但它可能是不必要的 - 我会尝试在上面提出一个解决方案
    【解决方案2】:

    对于轴对齐的椭圆,使用参数方程(中心)

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


    x0,y0 是椭圆中心
    rx,ry 是半轴尺寸(矩形边的一半)
    a 是你要获取的点的角度

    区域通常通过角度间隔来选择。角度通常由从中心 (x0,y0) 到实际鼠标位置 (mx,my) 或某个控制点的线确定

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

    所以a = &lt; a0,a1 &gt; 其中ai = { a0,a1 } 是您的区间角。对于全椭圆a =&lt; 0,2*M_PI&gt; [rad]

    这只是角度的圆形近似,所以如果您想获得更精确的角度,请寻找

    或应用圆形/椭圆校正缩放...

    【讨论】:

      猜你喜欢
      • 2013-10-09
      • 1970-01-01
      • 2012-03-19
      • 2020-04-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-01-31
      相关资源
      最近更新 更多