62

I am using jna.jar, jna-3.2.5.jar and jna-3.3.0-platform.jar in my Java Project.

This is the Winapi function I want to replicate.

BOOL WINAPI MagImageScalingCallback(
  _In_  HWND           hwnd,
  _In_  void           *srcdata,
  _In_  MAGIMAGEHEADER srcheader,
  _Out_ void           *destdata,
  _In_  MAGIMAGEHEADER destheader,
  _In_  RECT           unclipped,
  _In_  RECT           clipped,
  _In_  HRGN           dirty
);

This is my Java code

public interface MagImageScalingCallback extends StdCallLibrary.StdCallCallback{
    public boolean MagImageScalingCallback(HWND hwnd,
            Pointer srcdata,
            MAGIMAGEHEADER.ByValue srcheader,
            Pointer destdata,
            MAGIMAGEHEADER.ByValue destheader,
            RectByValue source,
            RectByValue clipped,
            HRGN dirty);
}

When I get into this method of the callback, I get unexpected results:

    public boolean MagImageScalingCallback(HWND hwnd, Pointer srcdata,
            MAGIMAGEHEADER.ByValue srcheader, Pointer destdata,
            MAGIMAGEHEADER.ByValue destheader, RectByValue source, RectByValue clipped, HRGN dirty) {
        image.setRGB(0, 0, srcheader.width, srcheader.height, srcdata.getIntArray(0, srcheader.width * srcheader.height ), 0, srcheader.width);
        return true;
    }

This table explains What works and what doesn't work in 32 bit and 64 bit system when I change the data type of the variables.

+--------------+--------------+-------------+-------------+
| Parameter    | Data type    |   64 bit    |   32 bit    |
+--------------+--------------+-------------+-------------+
| source       | WinDef.RECT  |   Working   | Not Working |
| clipped      | WinDef.RECT  |   Working   | Not Working |
| source       | RectByValue  |   Working   |   Working   |
| source       | RectByValue  |   Working   |   Working   |
| srcdata      | Pointer      |   Working   | Not Working |
| destdata     | Pointer      |   Working   | Not Working |
+--------------+--------------+-------------+-------------+

Not working means a totally black image in the result

If I use the above code in a 64 bit system, I can capture the desktop(I can access the data from the Pointer variable). If I use the same code in 32 bit system, I am not getting any image. You can see my whole code

Why is the error in my code? How can I fix that?

For your Information. As you see in the screenSkip.java, Whenever MagSetWindowSource function is called. MagImageScalingCallback(in line 80) is called.

Problems in this section of code

If I run this code on a 64 bit system srcdata and destdata will hold the array of integer pixels of the Desktop(If I save this as image, it captures the desktop). But if I run the same code on 32 bit system these both variable array pixel value is always zero(If I save the image, it is always black)

64 bit system enter image description here

32 bit system enter image description here

@david-heffernan I am running this code on a 32-bit system. I know The Magnification API is not supported under WOW64;. Which means 32-bit magnification application works on a 32-bit system and 64-bit magnification application works on a 64-bit system. Please stop commenting that magnification API doesn't work on WOW64 and try to execute this code on a 32-bit system.

As for your request the below image shows the configuration of my System.

enter image description here

Vishnu
  • 11,614
  • 6
  • 51
  • 90
  • What is the `C` idiom you are trying to replicate? `struct` handling is by reference (`struct *`) for parameters and by value (`struct`) in aggregate fields. The Java `Structure` tagging interfaces (`ByValue`, `ByReference`) are there to force the complementary convention. All other values are passed by value and there exists a range of `ByReference` implementations in the `com.sun.jna.ptr` package to facilitate passing "the address of" a value. – technomage Sep 12 '15 at 10:44
  • @technomage I have updated the question. Please ping me if you didn't understand. – Vishnu Sep 12 '15 at 11:19
  • `Pointer` is always passed by value. Whether 64- or 32-bit, if the native signature asks for a struct by value, you need to pass it by value (it's only by chance that passing a `struct*` happened to work in your 64-bit case, due to how the compiler handles passing small `struct` values). – technomage Sep 12 '15 at 13:10
  • @technomage how can I fix the issue? – Vishnu Sep 13 '15 at 07:56
  • Please clarify (in your question) what works and what doesn't work, on both 32- and 64-bit versions. Indicate the expected and actual outcomes. – technomage Sep 13 '15 at 13:44
  • @technomage I have updated the question. Hope that is the data you required. – Vishnu Sep 14 '15 at 09:06
  • You definitely need to use `ByValue` variants of all `Structure` types passed in to the callback. You should also avoid initializing any `ByValue` variant from an existing `Pointer`, or you may get unexpected results. Please be more descriptive about the problems you're having with [this section of code](https://github.com/petesh/jna-magnification/blob/master/screenSkip.java#L80-L85). – technomage Sep 14 '15 at 15:16
  • @technomage Updated the problem – Vishnu Sep 15 '15 at 07:17
  • Have you compared the contents of the [`MAGIMAGEHEADER`](https://msdn.microsoft.com/en-us/library/windows/desktop/ms692384(v=vs.85).aspx) (which describes the layout of the data you're receiving) between the 32- and 64-bit versions? Examine the bytes per row ("stride"), offset, and total size. – technomage Sep 15 '15 at 13:55
  • All the values are same for 32 bit and 64 bit system. – Vishnu Sep 15 '15 at 14:13
  • Run the tests on the same system, installing a 32-bit JVM on the 64-bit system if necessary. You'll get the black desktop if, for instance, the code is running as a service but does not have desktop access enabled. – technomage Sep 15 '15 at 14:53
  • @technomage I have tried that too(installing 32-bit JVM), I got the same result(black desktop). – Vishnu Sep 15 '15 at 15:07
  • http://stackoverflow.com/questions/32044727/jna-pointer-in-32-bit-jre – kervin Sep 15 '15 at 17:29
  • @technomage 'srcdata.SIZE' in 64 bit system is '8' where as in 32 bit system is '4'. Does that affect the data? – Vishnu Sep 18 '15 at 05:59
  • 2
    If you're using the `SIZE_T` type JNA should take care of the size difference (assuming you mean the cbSize field in `MAGIMAGEHEADER`). From the [SO link above](http://stackoverflow.com/questions/32044727/jna-pointer-in-32-bit-jre), I wouldn't expect this to work in 32-bit mode on 64-bit windows. – technomage Sep 18 '15 at 11:50
  • Yes, That doesn't work on WOW64 but it should work on 32 bit system. I have tried the cpp code in visual Studio it is working fine on a 32 bit system. – Vishnu Sep 18 '15 at 13:30

1 Answers1

1

The callback is proper - there is no flaw in your code, besides you are using deprecated functions.

Consider using this:

try {
    Rectangle screenRect = new Rectangle(Toolkit.getDefaultToolkit().getScreenSize());
    BufferedImage  capture = new Robot().createScreenCapture(screenRect);
    ImageIO.write(capture, "JPEG", new File("printed1.jpg"));
} catch (Exception e) {
    e.printStackTrace();
}
mkl
  • 90,588
  • 15
  • 125
  • 265
bebbo
  • 2,830
  • 1
  • 32
  • 37