1 /*
2 * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 package java.awt;
27
28 import java.awt.event.InputEvent;
29 import java.awt.event.KeyEvent;
30 import java.awt.image.BufferedImage;
31 import java.awt.image.DataBufferInt;
32 import java.awt.image.DirectColorModel;
33 import java.awt.image.Raster;
34 import java.awt.image.WritableRaster;
35 import java.awt.peer.RobotPeer;
36
37 import sun.awt.AWTPermissions;
38 import sun.awt.ComponentFactory;
39 import sun.awt.SunToolkit;
40 import sun.awt.image.SunWritableRaster;
41
42 /**
43 * This class is used to generate native system input events
44 * for the purposes of test automation, self-running demos, and
45 * other applications where control of the mouse and keyboard
46 * is needed. The primary purpose of Robot is to facilitate
47 * automated testing of Java platform implementations.
48 * <p>
49 * Using the class to generate input events differs from posting
377 // rather than build a big table or switch statement here, we'll
378 // just check that the key isn't VK_UNDEFINED and assume that the
379 // peer implementations will throw an exception for other bogus
380 // values e.g. -1, 999999
381 if (keycode == KeyEvent.VK_UNDEFINED) {
382 throw new IllegalArgumentException("Invalid key code");
383 }
384 }
385
386 /**
387 * Returns the color of a pixel at the given screen coordinates.
388 * @param x X position of pixel
389 * @param y Y position of pixel
390 * @return Color of the pixel
391 */
392 public synchronized Color getPixelColor(int x, int y) {
393 Color color = new Color(peer.getRGBPixel(x, y));
394 return color;
395 }
396
397 /**
398 * Creates an image containing pixels read from the screen. This image does
399 * not include the mouse cursor.
400 * @param screenRect Rect to capture in screen coordinates
401 * @return The captured image
402 * @throws IllegalArgumentException if {@code screenRect} width and height are not greater than zero
403 * @throws SecurityException if {@code readDisplayPixels} permission is not granted
404 * @see SecurityManager#checkPermission
405 * @see AWTPermission
406 */
407 public synchronized BufferedImage createScreenCapture(Rectangle screenRect) {
408 checkScreenCaptureAllowed();
409
410 checkValidRect(screenRect);
411
412 BufferedImage image;
413 DataBufferInt buffer;
414 WritableRaster raster;
415
416 if (screenCapCM == null) {
417 /*
418 * Fix for 4285201
419 * Create a DirectColorModel equivalent to the default RGB ColorModel,
420 * except with no Alpha component.
421 */
422
423 screenCapCM = new DirectColorModel(24,
424 /* red mask */ 0x00FF0000,
425 /* green mask */ 0x0000FF00,
426 /* blue mask */ 0x000000FF);
427 }
428
429 // need to sync the toolkit prior to grabbing the pixels since in some
430 // cases rendering to the screen may be delayed
431 Toolkit.getDefaultToolkit().sync();
432
433 int pixels[];
434 int[] bandmasks = new int[3];
435
436 pixels = peer.getRGBPixels(screenRect);
437 buffer = new DataBufferInt(pixels, pixels.length);
438
439 bandmasks[0] = screenCapCM.getRedMask();
440 bandmasks[1] = screenCapCM.getGreenMask();
441 bandmasks[2] = screenCapCM.getBlueMask();
442
443 raster = Raster.createPackedRaster(buffer, screenRect.width, screenRect.height, screenRect.width, bandmasks, null);
444 SunWritableRaster.makeTrackable(buffer);
445
446 image = new BufferedImage(screenCapCM, raster, false, null);
447
448 return image;
449 }
450
451 private static void checkValidRect(Rectangle rect) {
452 if (rect.width <= 0 || rect.height <= 0) {
453 throw new IllegalArgumentException("Rectangle width and height must be > 0");
454 }
455 }
456
|
1 /*
2 * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 package java.awt;
27
28 import java.awt.event.InputEvent;
29 import java.awt.event.KeyEvent;
30 import java.awt.geom.AffineTransform;
31 import java.awt.image.BufferedImage;
32 import java.awt.image.DataBufferInt;
33 import java.awt.image.DirectColorModel;
34 import java.awt.image.Raster;
35 import java.awt.image.WritableRaster;
36 import java.awt.peer.RobotPeer;
37
38 import sun.awt.AWTPermissions;
39 import sun.awt.ComponentFactory;
40 import sun.awt.SunToolkit;
41 import sun.awt.image.SunWritableRaster;
42
43 /**
44 * This class is used to generate native system input events
45 * for the purposes of test automation, self-running demos, and
46 * other applications where control of the mouse and keyboard
47 * is needed. The primary purpose of Robot is to facilitate
48 * automated testing of Java platform implementations.
49 * <p>
50 * Using the class to generate input events differs from posting
378 // rather than build a big table or switch statement here, we'll
379 // just check that the key isn't VK_UNDEFINED and assume that the
380 // peer implementations will throw an exception for other bogus
381 // values e.g. -1, 999999
382 if (keycode == KeyEvent.VK_UNDEFINED) {
383 throw new IllegalArgumentException("Invalid key code");
384 }
385 }
386
387 /**
388 * Returns the color of a pixel at the given screen coordinates.
389 * @param x X position of pixel
390 * @param y Y position of pixel
391 * @return Color of the pixel
392 */
393 public synchronized Color getPixelColor(int x, int y) {
394 Color color = new Color(peer.getRGBPixel(x, y));
395 return color;
396 }
397
398 private static int interp(int pixels[], int x, int y, int w, int h, int fractx1, int fracty1) {
399 int fractx0 = 256 - fractx1;
400 int fracty0 = 256 - fracty1;
401 int i = y * w + x;
402 int rgb00 = (x < 0 || y < 0 || x >= w || y >= h) ? 0 : pixels[i];
403 if (fracty1 == 0) {
404 // No interplation with pixels[y+1]
405 if (fractx1 == 0) {
406 // No interpolation with any neighbors
407 return rgb00;
408 }
409 int rgb10 = (y < 0 || x + 1 >= w || y >= h) ? 0 : pixels[i + 1];
410 return interp(rgb00, rgb10, fractx0, fractx1);
411 } else if (fractx1 == 0) {
412 // No interpolation with pixels[x+1]
413 int rgb01 = (x < 0 || x >= w || y + 1 >= h) ? 0 : pixels[i + w];
414 return interp(rgb00, rgb01, fracty0, fracty1);
415 } else {
416 // All 4 neighbors must be interpolated
417 int rgb10 = (y < 0 || x + 1 >= w || y >= h) ? 0 : pixels[i + 1];
418 int rgb01 = (x < 0 || x >= w || y + 1 >= h) ? 0 : pixels[i + w];
419 int rgb11 = (x + 1 >= w || y + 1 >= h) ? 0 : pixels[i + w + 1];
420 return interp(interp(rgb00, rgb10, fractx0, fractx1),
421 interp(rgb01, rgb11, fractx0, fractx1),
422 fracty0, fracty1);
423 }
424 }
425
426 private static int interp(int rgb0, int rgb1, int fract0, int fract1) {
427 int a0 = (rgb0 >> 24) & 0xff;
428 int r0 = (rgb0 >> 16) & 0xff;
429 int g0 = (rgb0 >> 8) & 0xff;
430 int b0 = (rgb0) & 0xff;
431 int a1 = (rgb1 >> 24) & 0xff;
432 int r1 = (rgb1 >> 16) & 0xff;
433 int g1 = (rgb1 >> 8) & 0xff;
434 int b1 = (rgb1) & 0xff;
435 int a = (a0 * fract0 + a1 * fract1) >> 8;
436 int r = (r0 * fract0 + r1 * fract1) >> 8;
437 int g = (g0 * fract0 + g1 * fract1) >> 8;
438 int b = (b0 * fract0 + b1 * fract1) >> 8;
439 return (a << 24) | (r << 16) | (g << 8) | b;
440 }
441
442 /**
443 * Creates an image containing pixels read from the screen. This image does
444 * not include the mouse cursor.
445 * @param screenRect Rect to capture in screen coordinates
446 * @return The captured image
447 * @throws IllegalArgumentException if {@code screenRect} width and height are not greater than zero
448 * @throws SecurityException if {@code readDisplayPixels} permission is not granted
449 * @see SecurityManager#checkPermission
450 * @see AWTPermission
451 */
452 public synchronized BufferedImage createScreenCapture(Rectangle screenRect) {
453 return createScreenCapture(screenRect, false);
454 }
455
456 /**
457 * Creates an image containing pixels read from the screen. This image does
458 * not include the mouse cursor.
459 * @param screenRect Rect to capture in screen coordinates
460 * @param isHiDPI Specifies if HiDPI
461 * @return The captured image
462 * @throws IllegalArgumentException if {@code screenRect} width and height are not greater than zero
463 * @throws SecurityException if {@code readDisplayPixels} permission is not granted
464 * @see SecurityManager#checkPermission
465 * @see AWTPermission
466 */
467 public synchronized BufferedImage createScreenCapture(Rectangle screenRect,
468 boolean isHiDPI) {
469 checkScreenCaptureAllowed();
470
471 checkValidRect(screenRect);
472
473 BufferedImage image;
474 DataBufferInt buffer;
475 WritableRaster raster;
476
477 if (screenCapCM == null) {
478 /*
479 * Fix for 4285201
480 * Create a DirectColorModel equivalent to the default RGB ColorModel,
481 * except with no Alpha component.
482 */
483
484 screenCapCM = new DirectColorModel(24,
485 /* red mask */ 0x00FF0000,
486 /* green mask */ 0x0000FF00,
487 /* blue mask */ 0x000000FF);
488 }
489
490 // need to sync the toolkit prior to grabbing the pixels since in some
491 // cases rendering to the screen may be delayed
492 Toolkit.getDefaultToolkit().sync();
493 AffineTransform tx = GraphicsEnvironment.
494 getLocalGraphicsEnvironment().getDefaultScreenDevice().
495 getDefaultConfiguration().getDefaultTransform();
496 double uiScaleX = tx.getScaleX();
497 double uiScaleY = tx.getScaleY();
498 int pixels[];
499 int[] bandmasks = new int[3];
500
501 if (uiScaleX == 1 && uiScaleY == 1) {
502 pixels = peer.getRGBPixels(screenRect);
503 } else {
504 int x = screenRect.x;
505 int y = screenRect.y;
506 int width = screenRect.width;
507 int height = screenRect.height;
508 int pminx = (int) Math.floor(x * uiScaleX);
509 int pminy = (int) Math.floor(y * uiScaleY);
510 int pmaxx = (int) Math.ceil((x + width) * uiScaleX);
511 int pmaxy = (int) Math.ceil((y + height) * uiScaleY);
512 int pwidth = pmaxx - pminx;
513 int pheight = pmaxy - pminy;
514 int temppixels[];
515 Rectangle rect = new Rectangle(pminx, pminy, pwidth, pheight);
516 temppixels = peer.getRGBPixels(rect);
517 if (isHiDPI) {
518 pixels = temppixels;
519 screenRect.width = pwidth;
520 screenRect.height = pheight;
521 } else {
522 pixels = new int[width * height];
523 int index = 0;
524 for (int iy = 0; iy < height; iy++) {
525 float rely = (float) (((y + iy + 0.5f) * uiScaleY)
526 - (pminy + 0.5f));
527 int irely = (int) Math.floor(rely);
528 int fracty = (int) ((rely - irely) * 256);
529 for (int ix = 0; ix < width; ix++) {
530 float relx = (float) (((x + ix + 0.5f) * uiScaleX)
531 - (pminx + 0.5f));
532 int irelx = (int) Math.floor(relx);
533 int fractx = (int) ((relx - irelx) * 256);
534 pixels[index++]
535 = interp(temppixels, irelx, irely, pwidth,
536 pheight, fractx, fracty);
537 }
538 }
539 screenRect.width = width;
540 screenRect.height = height;
541 }
542 }
543
544 buffer = new DataBufferInt(pixels, pixels.length);
545
546 bandmasks[0] = screenCapCM.getRedMask();
547 bandmasks[1] = screenCapCM.getGreenMask();
548 bandmasks[2] = screenCapCM.getBlueMask();
549
550 raster = Raster.createPackedRaster(buffer, screenRect.width, screenRect.height, screenRect.width, bandmasks, null);
551 SunWritableRaster.makeTrackable(buffer);
552
553 image = new BufferedImage(screenCapCM, raster, false, null);
554
555 return image;
556 }
557
558 private static void checkValidRect(Rectangle rect) {
559 if (rect.width <= 0 || rect.height <= 0) {
560 throw new IllegalArgumentException("Rectangle width and height must be > 0");
561 }
562 }
563
|