如何将区域从画布复制到图像中

时间:2014-12-29 15:23:22

标签: java canvas swt composite

我正在尝试使用Canvas方法将鼠标光标周围的区域从Image复制到gc.copyarea。之后我想将该图像绘制到按下鼠标1秒后出现的复合图像上。

以下是我的代码: 在我的画布的paintControl方法中,我将区域复制到图像:

    img = new Image(display, 40, 40);
    gc.copyArea(img, mousePosition.x-20, mousePosition.y-20);

在我的复合的paintControl方法中,我绘制了该图像:

    if (img != null) {
        gc.drawImage(img, 0, 0);
    }

我遇到的问题是,实际上只有很小一部分区域被复制并涂在复合材料上。在40x40像素区域中,复合材料中只能看到左下角10x20像素区域的区域。

实施例:

光标位于compisite左上角的旁边。只有光标周围区域的一小部分被涂在compisite上

问题:如何从画布复制区域并将其正确地绘制到另一个复合材料上?我的代码中我做错了什么?

2 个答案:

答案 0 :(得分:1)

经过一些反复试验,我设法得到了一些可以接近你想要的东西。

public class CopyArea {

  public static void main( String[] args ) {
    CopyArea copyArea = new CopyArea();
    copyArea.create();
    copyArea.run();
  }

  private Display display;
  private Image sourceImage;
  private Point canvasSize;
  private Shell shell;
  private Canvas source;
  private Canvas destination;
  private Point snippetOrigin;
  private Image snippet;

  CopyArea() {
    display = new Display();
    sourceImage = new Image( display, getClass().getResourceAsStream( "mona-lisa.jpeg" ) );
    canvasSize = new Point( sourceImage.getBounds().width, sourceImage.getBounds().height );
    shell = new Shell( display );
    source = new Canvas( shell, SWT.NONE );
    destination = new Canvas( shell, SWT.NONE );
  }

  void create() {
    shell.setLayout( new RowLayout() );
    source.setLayoutData( new RowData( canvasSize ) );
    source.addPaintListener( new PaintListener() {
      @Override
      public void paintControl( PaintEvent event ) {
        event.gc.drawImage( sourceImage, 0, 0 );
        if( snippetOrigin != null ) {
          snippet = new Image( display, 40, 40 );
          event.gc.copyArea( snippet, snippetOrigin.x, snippetOrigin.y );
          destination.redraw();
          snippetOrigin = null;
        }
      }
    } );
    source.addMouseListener( new MouseAdapter() {
      @Override
      public void mouseDown( MouseEvent event ) {
        snippetOrigin = new Point( event.x, event.y );
        source.redraw();
      }
    } );
    destination.setLayoutData( new RowData( canvasSize ) );
    destination.addPaintListener( new PaintListener() {
      @Override
      public void paintControl( PaintEvent event ) {
        event.gc.setBackground( display.getSystemColor( SWT.COLOR_WHITE ) );
        event.gc.fillRectangle( event.gc.getClipping() );
        if( snippet != null ) {
          event.gc.drawImage( snippet, 0, 0 );
        }
      }
    } );
  }

  void run() {
    shell.pack();
    shell.open();
    while( !shell.isDisposed() ) {
      if( !display.readAndDispatch() )
        display.sleep();
    }
    display.dispose();
  }
}

sourceImage只是绘图代码的占位符。 source Canvas侦听鼠标按下事件,然后将其客户端的40x40片段绘制到destination Canvas。请注意,我在两种情况下都使用Canvas,但Canvas和Composite也应该可以使用。

以下是它的工作原理:鼠标监听器将鼠标位置存储到snippetOrigin并触发source的重绘。 source的绘画听众会根据请求(snippetOrigin != null)对其刚刚绘制的内容进行部分屏幕截图,然后强制destination重新绘制自己。 destination简单的绘画监听器会绘制snippet图像(如果有)。

代码deos尚未正确剪辑复制的图像。如果您在source画布的右下角按下鼠标,也会复制一些shell修剪。

为简洁起见,代码在重用之前不会丢弃snippet图像(并且可能有其他泄漏)。

如果您拥有绘制相当于source Canvas的绘图代码,我宁愿重构它以便可以绘制任意部分,然后使用适当的参数调用代码以在{{1}上绘制小部件。

答案 1 :(得分:0)

试试这个代码,示例获取画布区域的副本并粘贴到对象中

var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
ctx.fillStyle = "red";
ctx.fillRect(10, 10, 50, 50);

function copy() {
    var imgData = ctx.getImageData(10, 10, 50, 50);
    ctx.putImageData(imgData, 10, 70);
}

在这种情况下,副本被粘贴到画布目的地作为原点

试试这个参考

https://www.w3schools.com/tags/canvas_getimagedata.asp

这是 API 参考

https://developer.mozilla.org/es/docs/Web/API/CanvasRenderingContext2D/getImageData