< prev index next >

src/java.desktop/share/classes/java/awt/Robot.java

Print this page

        

@@ -25,10 +25,12 @@
 
 package java.awt;
 
 import java.awt.event.InputEvent;
 import java.awt.event.KeyEvent;
+import java.awt.geom.AffineTransform;
+import java.awt.image.BaseMultiResolutionImage;
 import java.awt.image.BufferedImage;
 import java.awt.image.DataBufferInt;
 import java.awt.image.DirectColorModel;
 import java.awt.image.Raster;
 import java.awt.image.WritableRaster;

@@ -392,10 +394,171 @@
     public synchronized Color getPixelColor(int x, int y) {
         Color color = new Color(peer.getRGBPixel(x, y));
         return color;
     }
 
+    private static int interp(int pixels[], int x, int y, int w, int h,
+            int fractx1, int fracty1) {
+        int fractx0 = 256 - fractx1;
+        int fracty0 = 256 - fracty1;
+        int i = y * w + x;
+        int rgb00 = (x < 0 || y < 0 || x >= w || y >= h) ? 0 : pixels[i];
+        if (fracty1 == 0) {
+            // No interplation with pixels[y+1]
+            if (fractx1 == 0) {
+                // No interpolation with any neighbors
+                return rgb00;
+            }
+            int rgb10 = (y < 0 || x + 1 >= w || y >= h) ? 0 : pixels[i + 1];
+            return interp(rgb00, rgb10, fractx0, fractx1);
+        } else if (fractx1 == 0) {
+            // No interpolation with pixels[x+1]
+            int rgb01 = (x < 0 || x >= w || y + 1 >= h) ? 0 : pixels[i + w];
+            return interp(rgb00, rgb01, fracty0, fracty1);
+        } else {
+            // All 4 neighbors must be interpolated
+            int rgb10 = (y < 0 || x + 1 >= w || y >= h) ? 0 : pixels[i + 1];
+            int rgb01 = (x < 0 || x >= w || y + 1 >= h) ? 0 : pixels[i + w];
+            int rgb11 = (x + 1 >= w || y + 1 >= h) ? 0 : pixels[i + w + 1];
+            return interp(interp(rgb00, rgb10, fractx0, fractx1),
+                    interp(rgb01, rgb11, fractx0, fractx1),
+                    fracty0, fracty1);
+        }
+    }
+
+    private static int interp(int rgb0, int rgb1, int fract0, int fract1) {
+        int a0 = (rgb0 >> 24) & 0xff;
+        int r0 = (rgb0 >> 16) & 0xff;
+        int g0 = (rgb0 >> 8) & 0xff;
+        int b0 = (rgb0) & 0xff;
+        int a1 = (rgb1 >> 24) & 0xff;
+        int r1 = (rgb1 >> 16) & 0xff;
+        int g1 = (rgb1 >> 8) & 0xff;
+        int b1 = (rgb1) & 0xff;
+        int a = (a0 * fract0 + a1 * fract1) >> 8;
+        int r = (r0 * fract0 + r1 * fract1) >> 8;
+        int g = (g0 * fract0 + g1 * fract1) >> 8;
+        int b = (b0 * fract0 + b1 * fract1) >> 8;
+        return (a << 24) | (r << 16) | (g << 8) | b;
+    }
+
+    /**
+     * Creates an image containing pixels read from the screen.
+     * This image does not include the mouse cursor.
+     * Returns BufferedImage for Non-HiDPI display and MultiResolutionImage 
+     * for HiDPI display with two resolution variants.
+     * @param   screenRect     Rect to capture in screen coordinates
+     * @return  The captured image
+     * @throws  IllegalArgumentException if {@code screenRect} width and height are not greater than zero
+     * @throws  SecurityException if {@code readDisplayPixels} permission is not granted
+     * @see     SecurityManager#checkPermission
+     * @see     AWTPermission
+     */
+    
+    public synchronized Image createHiDPIScreenCapture(Rectangle screenRect) {
+        checkScreenCaptureAllowed();
+
+        checkValidRect(screenRect);
+ 
+        BufferedImage lowResolutionImage;
+        BufferedImage highResolutionImage;
+        DataBufferInt buffer;
+        WritableRaster raster;
+
+        if (screenCapCM == null) {
+            /*
+             * Fix for 4285201
+             * Create a DirectColorModel equivalent to the default RGB ColorModel,
+             * except with no Alpha component.
+             */
+
+            screenCapCM = new DirectColorModel(24,
+                    /* red mask */ 0x00FF0000,
+                    /* green mask */ 0x0000FF00,
+                    /* blue mask */ 0x000000FF);
+        }
+
+        int[] bandmasks = new int[3];
+        bandmasks[0] = screenCapCM.getRedMask();
+        bandmasks[1] = screenCapCM.getGreenMask();
+        bandmasks[2] = screenCapCM.getBlueMask();
+        
+        // need to sync the toolkit prior to grabbing the pixels since in some
+        // cases rendering to the screen may be delayed
+        Toolkit.getDefaultToolkit().sync();
+        AffineTransform tx = GraphicsEnvironment.
+                getLocalGraphicsEnvironment().getDefaultScreenDevice().
+                getDefaultConfiguration().getDefaultTransform();
+        double uiScaleX = tx.getScaleX();
+        double uiScaleY = tx.getScaleY();
+        int pixels[];
+     
+        // Return normal screenCapture for Non-HiDPI Display
+        if(uiScaleX ==1 && uiScaleY==1){
+            return createScreenCapture(screenRect);
+        }
+
+        int x = screenRect.x;
+        int y = screenRect.y;
+        int width = screenRect.width;
+        int height = screenRect.height;
+        int pminx = (int) Math.floor(x * uiScaleX);
+        int pminy = (int) Math.floor(y * uiScaleY);
+        int pmaxx = (int) Math.ceil((x + width) * uiScaleX);
+        int pmaxy = (int) Math.ceil((y + height) * uiScaleY);
+        int pwidth = pmaxx - pminx;
+        int pheight = pmaxy - pminy;
+        int temppixels[];
+        Rectangle rect = new Rectangle(pminx, pminy, pwidth, pheight);
+        temppixels = peer.getRGBPixels(rect);
+
+        // HighResolutionImage
+        pixels = temppixels;
+        screenRect = rect;
+  
+        buffer = new DataBufferInt(pixels, pixels.length);
+        raster = Raster.createPackedRaster(buffer, screenRect.width,
+                screenRect.height, screenRect.width, bandmasks, null);
+        SunWritableRaster.makeTrackable(buffer);
+
+        highResolutionImage = new BufferedImage(screenCapCM, raster, false, null);
+
+        // LowResolutionImage
+        pixels = new int[width * height];
+        int index = 0;
+        for (int iy = 0; iy < height; iy++) {
+            float rely = (float) (((y + iy + 0.5f) * uiScaleY)
+                    - (pminy + 0.5f));
+            int irely = (int) Math.floor(rely);
+            int fracty = (int) ((rely - irely) * 256);
+            for (int ix = 0; ix < width; ix++) {
+                float relx = (float) (((x + ix + 0.5f) * uiScaleX)
+                        - (pminx + 0.5f));
+                int irelx = (int) Math.floor(relx);
+                int fractx = (int) ((relx - irelx) * 256);
+                pixels[index++]
+                        = interp(temppixels, irelx, irely, pwidth,
+                                pheight, fractx, fracty);
+            }
+        }
+        screenRect.width = width;
+        screenRect.height = height;
+       
+        buffer = new DataBufferInt(pixels, pixels.length);
+        raster = Raster.createPackedRaster(buffer, screenRect.width,
+                screenRect.height, screenRect.width, bandmasks, null);
+        SunWritableRaster.makeTrackable(buffer);
+
+        lowResolutionImage = new BufferedImage(screenCapCM, raster, false, null);
+
+        // MultiResoltuionImage
+        BaseMultiResolutionImage image = new BaseMultiResolutionImage(
+                lowResolutionImage,highResolutionImage);
+   
+        return image;
+    }
+    
     /**
      * Creates an image containing pixels read from the screen.  This image does
      * not include the mouse cursor.
      * @param   screenRect      Rect to capture in screen coordinates
      * @return  The captured image
< prev index next >