iterate-ch / rococoa

Rococoa allows you to call Objective-C code through Java classes and interfaces that you define.
GNU Lesser General Public License v3.0
72 stars 18 forks source link

Getting error while capturing screenshot of specific window. #25

Open sumit33 opened 2 years ago

sumit33 commented 2 years ago

I want to capture screenshot of specific application on Mac. I find a piece of code on net and used it and got this error.

2022-06-01 13:11:27.327 java[38630:745393] *** Assertion failure in -[NSBitmapImageRep initWithCGImage:],NSBitmapImageRep.m:1254
2022-06-01 13:11:27.327 java[38630:745393] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Invalid parameter not satisfying: cgImage != NULL'
*** First throw call stack:
(
    0   CoreFoundation                      0x00007fff20494beb __exceptionPreprocess + 242
    1   libobjc.A.dylib                     0x00007fff201cdd92 objc_exception_throw + 48
    2   CoreFoundation                      0x00007fff204bdd82 +[NSException raise:format:arguments:] + 88
    3   Foundation                          0x00007fff2127d4e2 -[NSAssertionHandler handleFailureInMethod:object:file:lineNumber:description:] + 191
    4   AppKit                              0x00007fff22ec04df -[NSBitmapImageRep initWithCGImage:] + 214
    5   jna1422728435769209689.tmp          0x0000000124a95fda ffi_prep_go_closure + 1370
    6   ???                                 0x00007000010f5188 0x0 + 123145320092040
)
libc++abi: terminating with uncaught exception of type NSException

This is the method.

private BufferedImage getWindowImage(int windowId) {

    CoreGraphicsLibrary.CGRect bounds = new CoreGraphicsLibrary.CGRect.CGRectByValue();
    bounds.origin = new CoreGraphicsLibrary.CGPoint();
    bounds.origin.x = 0;
    bounds.origin.y = 0;
    bounds.size = new CoreGraphicsLibrary.CGSize();
    bounds.size.width = 0;
    bounds.size.height = 0;
    ID imageRef = CoreGraphicsLibrary.INSTANCE.CGWindowListCreateImage(bounds, CoreGraphicsLibrary.kCGWindowListOptionIncludingWindow | CoreGraphicsLibrary.kCGWindowListExcludeDesktopElements, windowId, CoreGraphicsLibrary.kCGWindowImageBoundsIgnoreFraming | CoreGraphicsLibrary.kCGWindowImageNominalResolution);

    NSBitmapImageRep imageRep = NSBitmapImageRep.CLASS.alloc().initWithCGImage(imageRef);
    imageRep.retain();

    int width = imageRep.pixelsWide();
    int height = imageRep.pixelsHigh();

    int windowTitleHeight = determineWindowTitleHeight(height, width);

    int heightWithoutTitle = height - windowTitleHeight;

    Pointer bitmapPointer = imageRep.bitmapData();
    if (bitmapPointer == null || bitmapPointer == Pointer.NULL) {
        imageRep.release();
        return null;

    } else {
        int[] data = bitmapPointer.getIntArray(0, width * height);

        if (heightWithoutTitle > 512) {
            BufferedImage image = new BufferedImage(width, heightWithoutTitle, BufferedImage.TYPE_INT_RGB);

            // Start on row windowTitleHeight to exclude the window titlebar
            int idx = windowTitleHeight * width;

            // Manually write each pixel to the raster because OS X generates ARGB screenshots but BufferedImage expects RGB data.
            WritableRaster raster = image.getRaster();
            for (int y = 0; y < heightWithoutTitle; y++) {

                for (int x = 0; x < width; x++) {
                    int pixel = data[idx++];
                    raster.setSample(x, y, 0, pixel >> 8 & 0xFF);   // Red is the second byte
                    raster.setSample(x, y, 1, pixel >> 16 & 0xFF);  // Green is the third byte
                    raster.setSample(x, y, 2, pixel >> 24 & 0xFF);  // Blue is the fourth byte
                }
            }

            // Now that we have a copy of the image in a Java object it's safe to release the native pointers
            Foundation.cfRelease(imageRef);
            imageRep.release();

            return image;

        } else {
            // The window is too small to generate an image
            return null;
        }
    }

}