How to take screenshots fast in Java?

后端 未结 5 1261
温柔的废话
温柔的废话 2020-11-27 05:36

I am implementing a simple eye tracker, which requires fast screenshoting of what is happening on the screen simultaneously with capturing the video from webcam.

The

相关标签:
5条回答
  • 2020-11-27 06:05

    u should definitely give a shot to OpenCV

    0 讨论(0)
  • 2020-11-27 06:10

    Here's a Windows-specific version using JNA that I am using in one of my projects.

    I have found it to be an order-of-magnitude faster than Robot, even with the native call overhead.

    import java.awt.Rectangle;
    import java.awt.image.BufferedImage;
    import java.awt.image.ColorModel;
    import java.awt.image.DataBuffer;
    import java.awt.image.DataBufferInt;
    import java.awt.image.DataBufferUShort;
    import java.awt.image.DirectColorModel;
    import java.awt.image.Raster;
    import java.awt.image.WritableRaster;
    
    import com.sun.jna.Native;
    import com.sun.jna.platform.win32.W32API;
    import com.sun.jna.win32.W32APIOptions;
    
    public class JNAScreenShot {
    
        public static BufferedImage getScreenshot(Rectangle bounds) {
            W32API.HDC windowDC = GDI.GetDC(USER.GetDesktopWindow());
            W32API.HBITMAP outputBitmap =
                GDI.CreateCompatibleBitmap(windowDC,
                                           bounds.width, bounds.height);
            try {
                W32API.HDC blitDC = GDI.CreateCompatibleDC(windowDC);
                try {
                    W32API.HANDLE oldBitmap =
                        GDI.SelectObject(blitDC, outputBitmap);
                    try {
                        GDI.BitBlt(blitDC,
                                   0, 0, bounds.width, bounds.height,
                                   windowDC,
                                   bounds.x, bounds.y,
                                   GDI32.SRCCOPY);
                    } finally {
                        GDI.SelectObject(blitDC, oldBitmap);
                    }
                    GDI32.BITMAPINFO bi = new GDI32.BITMAPINFO(40);
                    bi.bmiHeader.biSize = 40;
                    boolean ok =
                        GDI.GetDIBits(blitDC, outputBitmap, 0, bounds.height,
                                      (byte[]) null, bi, GDI32.DIB_RGB_COLORS);
                    if (ok) {
                        GDI32.BITMAPINFOHEADER bih = bi.bmiHeader;
                        bih.biHeight = - Math.abs(bih.biHeight);
                        bi.bmiHeader.biCompression = 0;
                        return bufferedImageFromBitmap(blitDC, outputBitmap, bi);
                    } else {
                        return null;
                    }
                } finally {
                    GDI.DeleteObject(blitDC);
                }
            } finally {
                GDI.DeleteObject(outputBitmap);
            }
        }
    
        private static BufferedImage
        bufferedImageFromBitmap(GDI32.HDC        blitDC,
                                GDI32.HBITMAP    outputBitmap,
                                GDI32.BITMAPINFO bi) {
            GDI32.BITMAPINFOHEADER bih = bi.bmiHeader;
            int height = Math.abs(bih.biHeight);
            final ColorModel cm;
            final DataBuffer buffer;
            final WritableRaster raster;
            int strideBits =
                (bih.biWidth * bih.biBitCount);
            int strideBytesAligned =
                (((strideBits - 1) | 0x1F) + 1) >> 3;
            final int strideElementsAligned;
            switch (bih.biBitCount) {
            case 16:
                strideElementsAligned = strideBytesAligned / 2;
                cm = new DirectColorModel(16, 0x7C00, 0x3E0, 0x1F);
                buffer =
                    new DataBufferUShort(strideElementsAligned * height);
                raster =
                    Raster.createPackedRaster(buffer,
                                              bih.biWidth, height,
                                              strideElementsAligned,
                                              ((DirectColorModel) cm).getMasks(),
                                              null);
                break;
            case 32:
                strideElementsAligned = strideBytesAligned / 4;
                cm = new DirectColorModel(32, 0xFF0000, 0xFF00, 0xFF);
                buffer =
                    new DataBufferInt(strideElementsAligned * height);
                raster =
                    Raster.createPackedRaster(buffer,
                                              bih.biWidth, height,
                                              strideElementsAligned,
                                              ((DirectColorModel) cm).getMasks(),
                                              null);
                break;
            default:
                throw new IllegalArgumentException("Unsupported bit count: " + bih.biBitCount);
            }
            final boolean ok;
            switch (buffer.getDataType()) {
                case DataBuffer.TYPE_INT:
                    {
                        int[] pixels = ((DataBufferInt) buffer).getData();
                        ok = GDI.GetDIBits(blitDC, outputBitmap, 0, raster.getHeight(), pixels, bi, 0);
                    }
                    break;
                case DataBuffer.TYPE_USHORT:
                    {
                        short[] pixels = ((DataBufferUShort) buffer).getData();
                        ok = GDI.GetDIBits(blitDC, outputBitmap, 0, raster.getHeight(), pixels, bi, 0);
                    }
                    break;
                default:
                    throw new AssertionError("Unexpected buffer element type: " + buffer.getDataType());
            }
            if (ok) {
                return new BufferedImage(cm, raster, false, null);
            } else {
                return null;
            }
        }
    
        private static final User32 USER = User32.INSTANCE;
    
        private static final GDI32 GDI = GDI32.INSTANCE;
    
    }
    
    interface GDI32 extends com.sun.jna.platform.win32.GDI32 {
        GDI32 INSTANCE =
            (GDI32) Native.loadLibrary(GDI32.class);
        boolean BitBlt(HDC hdcDest,
                       int nXDest,
                       int nYDest,
                       int nWidth,
                       int nHeight,
                       HDC hdcSrc,
                       int nXSrc,
                       int nYSrc,
                       int dwRop);
        HDC GetDC(HWND hWnd);
        boolean GetDIBits(HDC dc, HBITMAP bmp, int startScan, int scanLines,
                          byte[] pixels, BITMAPINFO bi, int usage);
        boolean GetDIBits(HDC dc, HBITMAP bmp, int startScan, int scanLines,
                          short[] pixels, BITMAPINFO bi, int usage);
        boolean GetDIBits(HDC dc, HBITMAP bmp, int startScan, int scanLines,
                          int[] pixels, BITMAPINFO bi, int usage);
        int SRCCOPY = 0xCC0020;
    }
    
    interface User32 extends com.sun.jna.platform.win32.User32 {
        User32 INSTANCE =
            (User32) Native.loadLibrary(User32.class,
                                        W32APIOptions.UNICODE_OPTIONS);
        HWND GetDesktopWindow();
    }
    
    0 讨论(0)
  • 2020-11-27 06:11

    The robot.createScreenCapture(captureSize); call takes about 20ms for me.

    0 讨论(0)
  • 2020-11-27 06:12

    May be you can make use of JMF.. Checkout the Screen Grabber code @ Oracle's site. I think it will help you solve your problem.

    0 讨论(0)
  • 2020-11-27 06:28

    To capture full screen.

    Robot robot = new Robot();
    Rectangle screenRect = new Rectangle(Toolkit.getDefaultToolkit().getScreenSize());
    BufferedImage screenFullImage = robot.createScreenCapture(screenRect);
    ImageIO.write(screenFullImage, format, new File(destination));
    

    To capture partial screen.

    Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
    Rectangle rect = new Rectangle(0, 0, screenSize.width / 2, screenSize.height / 2);
    Robot robot = new Robot();
    BufferedImage screenFullImage = robot.createScreenCapture(rect);
    ImageIO.write(screenFullImage, format, new File(destination));
    

    Reference : link

    0 讨论(0)
提交回复
热议问题