Marshalling Java image bytes to C++ BITMAP in JNI technology

Hello everybody

I want to send Java image bytes to c++ with JNI technology and then change the byte array to BITMAP in c++.

How can I do that?

Please tell me your guides

Sam

If you just want to write a BMP from java, doesn’t ImageIO work for you?

First ask yourself if you just can’t do the same thing you want to do with C++ in Java. If you still need to send data to C++, you send the int[] of the raster of a BufferedImage, or use a PixelGrabber to get a copy of the image data. You’ll get it as an int[] where each int contains all the color data of a single pixel.

Thanks Cylab and Theagentd for your response

It’s not important to Java part how image has been read, because it’s a buffered image and I want to send it like a stream data to lower layer(C++ wrapper). Maybe it can be an array of image bits or an Object.

The goal in this project is making a C++ BITMAP to sending to a printer with Java wrapper.
I’m trying to find a way to marshalling between Java image class to C++ BITMAP to transfer image bytes for printing.

If you have knowladge about JNI marshalling, I’ll happey to hear your guide.

So your printer can only handle BITMAPs sent from C++ and there is no other way to communicate with it, like the JavaTM Print Service?

You could try using a java.nio.ByteBuffer, which should give you shared memory between Java and Native, and use the JNI methods for native access to the shared memory area.

Yes. If it can be implement from Java language I followed it. But it’s a specific printer that we bought and it has a driver(.DLL file) which handle our functionalities. I have to making a JAVA wrapper to work with this printer with JNI technology.

Hello Zendar

You have a good solution for me. Thank you very much. I want to arrive like your solution

Could you guide me to have a reference or sample code to do it

I’m looking forward to help you
Sam

Take a look at http://java.sun.com/developer/onlineTraining/Programming/JDCBook/jni.html and Google: jni in c++.

Probably also see http://download.oracle.com/javase/1.4.2/docs/guide/jni/jni-14.html.

For code, you can peek at LWJGL glTexImage2D() bindings:

Declaration in java:
http://www.google.com/codesearch#3855oKWYJUU/trunk/Jiggles/lib/lwjgl-2.4.2/src/generated/org/lwjgl/opengl/GL11.java&q="package%20org.lwjgl.opengl"%20"class%20GL11"%20glTexImage2D&type=cs&l=2843

JNI implementation:
http://www.google.com/codesearch#3855oKWYJUU/trunk/Jiggles/lib/lwjgl-2.4.2/src/native/generated/org_lwjgl_opengl_GL11.c&type=cs&l=1420

safeGetBufferAdress implementation:
http://www.google.com/codesearch#3855oKWYJUU/trunk/Jiggles/lib/lwjgl-2.4.2/src/native/common/common_tools.h&type=cs&l=67

Cylab Thanks for your advises

All address were general but my issues is really special. Of course I didn’t understand Google sample codes.
I want send an Image of Java to C++ side. I saw a post in your site about sending image from C++ to Java2D side.
If you saw similar solution which it’s helpful to me, Please guide me to see some example to understand what I have to do. I’m almost being familiar with JNI concept but I didn’t face to such problem to sending image bytes of Java to C++ wrapper and I don’t know how I Can make a share memory between Java part and Native codes. But I know Java Image is an object and C++ BITMAP has some structures to making a Bitmap and I think they aren’t related. I think Mr. Theagentd in this post said true because we have to send colors array not Image object address in memory because they’re incompatible. If I made mistake please tell me.

Friends, I’m looking forward to your replies

You might want to look at https://github.com/twall/jna
Then you don’t need JNI and you can use your DLL “directly”. With com.sun.jna.Memory you should be able to submit the Bitmap bytes to your DLL. Just write the BufferedImage with ImageIO with “bmp” as format into a ByteArrayOutputStream and pass the resulting byte array written into a Memory-object to your java interface of the DLL.

It’s as simple as this (mapping the system’s C runtime library’s printf function):

package com.sun.jna.examples;

import com.sun.jna.Library;
import com.sun.jna.Native;
import com.sun.jna.Platform;

/** Simple example of JNA interface mapping and usage. */
public class HelloWorld {

    // This is the standard, stable way of mapping, which supports extensive
    // customization and mapping of Java to native types.

    public interface CLibrary extends Library {
        CLibrary INSTANCE = (CLibrary)
            Native.loadLibrary((Platform.isWindows() ? "msvcrt" : "c"),
                               CLibrary.class);

        void printf(String format, Object... args);
    }

    public static void main(String[] args) {
        CLibrary.INSTANCE.printf("Hello, World\n");
        for (int i=0;i < args.length;i++) {
            CLibrary.INSTANCE.printf("Argument %d: %s\n", i, args[i]);
        }
    }
}

Hello Chromanoid
Thanks for your guide.

Unfortunately the base of our project is JNI technology and migration from JNI to JNA consume a lot of cost and time.
I think the JNA do not call Clibrary directly and maybe it use JNI on background to do JNA functionalities. Of course I don’t have good knowladge about JNA but I think with logical reasons it maybe using JNI. If you know an Ebook or an useful reference to JNA, I’ll happy if you’ll introduce it to read.

Friends : I’m waiting to your another helps(Transfer Image from Java to C++)
Sam

Actually you have all the bits and pieces together now. You can convert a bitmap to a byte array with ImageIO and a ByteArrayOutputStream and you have a guide at hand how to use Jni.

So I guess you may have to try something for yourself now :stuck_out_tongue:

Thanks for everybody

Please look at me. I find a logical solution for my problem. I just want to say someone that can’t help, don’t write message. because if everyone can help us, they’ve forgotten base question with your messages.Thanks

Theagentd and Zendar had good suggetions, but my solution is near to Theagentd advice.

First things that we have to do is change Java Image object to send to JNI wrapper. You can understand the reason of it in below address:

http://www.jguru.com/faq/view.jsp?EID=31065

Also in below link you can understand how to use PixelGrabber in Java framework:

http://download.oracle.com/javase/1.4.2/docs/api/java/awt/image/PixelGrabber.html

After prepare Java Image as int[] you can send this parameter to JNI wrapper and make a C++ BITMAP from that . For understand way to make BITMAP you can see below like too:

http://www.codeguru.com/forum/showthread.php?t=453758

Also in the following, you can see my codes in tow parts(Java and JNI wrapper)

Java code: change Java Image to int[] for JNI warpper

Image image = null;
try {
File file = new File(“c:/image.jpg”);
image = ImageIO.read(file);
}
catch (MalformedURLException ex) {
Logger.getLogger(SmartTest.class.getName()).log(Level.SEVERE, ex.getMessage());
} catch (IOException ex) {
Logger.getLogger(SmartTest.class.getName()).log(Level.SEVERE, ex.getMessage());
}

// Image grabbing
int[] pixels = new int[w * h];
PixelGrabber pg = new PixelGrabber(image, x, y, w, h, pixels, 0, w);
try {
pg.grabPixels();
}catch (InterruptedException e) {
System.err.println(“interrupted waiting for pixels!”);
return;
}
if ((pg.getStatus() & ImageObserver.ABORT) != 0) {
System.err.println(“image fetch aborted or errored”);
return;
}

JNI wrapper code(C++): change int[] of Java Image to C++ BITMAP

HBITMAP CreateBitmapFromPixel( HDC hDC, UINT uWidth, UINT uHeight, UINT uBitsPerPixel, LPVOID pBits )
{
HBITMAP m_HBitmap = NULL;
if ( !uWidth || !uHeight || !uBitsPerPixel )
{
return m_HBitmap;//hBitmap;
}
LONG lBmpSize = uWidth * uHeight * uBitsPerPixel / 8;
BITMAPINFO bmpInfo = { 0 };
bmpInfo.bmiHeader.biBitCount = uBitsPerPixel;
bmpInfo.bmiHeader.biHeight = uHeight;
bmpInfo.bmiHeader.biWidth = uWidth;
bmpInfo.bmiHeader.biPlanes = 1;
bmpInfo.bmiHeader.biSizeImage = uWidth * uHeight * uBitsPerPixel / 8;
bmpInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
// Pointer to access the pixels of bitmap
UINT * pPixels = 0;
/hBitmap/m_HBitmap = CreateDIBSection( hDC, (BITMAPINFO *)&bmpInfo, DIB_RGB_COLORS, (void **)& pPixels , NULL, 0);
if ( !m_HBitmap )
return m_HBitmap;//hBitmap; // return if invalid bitmaps
SetBitmapBits( m_HBitmap, lBmpSize,pBits);
return m_HBitmap;
}

sample code to change Java Image to BITMAP in JNIwrapper :

int len = env->GetArrayLength(pixels); //pixels is jintArray and get from input parameter
jint* jarr;
jarr = env->GetIntArrayElements(pixels,FALSE);
HBITMAP hImg = CreateBitmapFromPixel(pFront->bmp.hdcColor,(DWORD)cx,(DWORD)cy,32,jarr);
if( hImg != NULL )
{
DIBSECTION dib;
BITMAPINFO bi;
::GetObject( hImg, sizeof(dib), &dib );
bi.bmiHeader = dib.dsBmih;

 // HDC is Hardware Device context. For understand how to set it please read Microsoft MSDN
 // w and h in here are belongs to BITMAP buffer based on you HDC
 ::SetDIBitsToDevice(HDC, 0, 0,w,h,0, 0, 0,dib.dsBm.bmHeight,dib.dsBm.bmBits,&bi,DIB_RGB_COLORS);

 DeleteObject( hImg );

}

Cheer up…
Sam