May 14

Combining Java's BufferedImage and OpenCV's IplImage


I recently did a small project combining a Java web service with a OpenCV processing. I tried to transfer the picture from Java environment (as BufferedImage) to OpenCV (IplImage) as seamlessly as possible. This proved a but tricky, especially the Java part where you need to create your own buffer for the image, but it worked out nicely.

Let me show you how I did it

First up was creating a 3-component RGB BufferedImage in Java, with a custom memory buffer that will fit nicely with IplImages:

private BufferedImage createOpenCVCompatibleBufferedImage(int w, int h)
ComponentColorModel cm = new ComponentColorModel(
false,  //no alpha channel
false,  //not premultiplied
DataBuffer.TYPE_BYTE); //important - data in the buffer is saved by the byte

SampleModel sm = cm.createCompatibleSampleModel(w, h);
DataBufferByte db = new DataBufferByte(w*h*3); //3 channels buffer
WritableRaster r = WritableRaster.createWritableRaster(sm, db, new Point(0,0));
BufferedImage bm = new BufferedImage(cm,r,false,null);
return bm;

This took some trial and error, but I ended up with a working thing.

Now, the C++/OpenCV side of things - a JNI function to read the buffer and do some OpenCV stuff:

JNIEXPORT jint JNICALL Java_test_OpenCVShowImage
(JNIEnv *env, jobject jo, jbyteArray pic, jint w, jint h, jint bpp, jint bpr) {
IplImage* img;
jint len;
unsigned char* result;
int n1;

img = cvCreateImageHeader(cvSize(w,h),8,bpp/8); //create the "shell"

len = (*env)->GetArrayLength(env, pic);
result = (unsigned char *)malloc(len + 1);
if (result == 0) {
fatal_error("out of memory");
(*env)->DeleteLocalRef(env, pic);
return 0;
(*env)->GetByteArrayRegion(env, pic, 0, len,(jbyte *)result);

cvSetData(img,result,bpr);    //set the buffer


return 1;

One last thing -the Java call to the JNI function:

BufferedImage tmp = ImageIO.read(new File("bird.png"));

BufferedImage bi1 = createOpenCVCompatibleBufferedImage(tmp.getWidth(), tmp.getHeight());

//paint the image with a little transform...
Graphics2D biDestG2D = bi1.createGraphics();
biDestG2D.fillRect(0, 0, w, h);
AffineTransform transform = AffineTransform.getShearInstance(0.2, 0.1);
transform.scale(0.5, 0.5);

byte[] bytes = ((DataBufferByte)bi1.getRaster().getDataBuffer()).getData();

OpenCVShowImage(bytes, w, h, 24, w*3);

That's all folks!

  • Pingback: OpenCV/Java/MacOSX and libjpeg framework for OSX 10.5 « tech-tips.estudass.es()

  • http://www.avc-cvut.cz quentar

    I do use use opencv-java-processin.org library ( http://ubaa.net/shared/processing/opencv/ + processing.org libraries ) that can create Processing Image (PImage) and convert this into opencv image ...

  • AraZZ

    Hello, nice work. Can you send instructions how to compile it. (Preferably Mac os)
    I'm struggling to do so, but no success. Any help is appreciated..

  • http://www.tut-all.com Martin

    Exactly what I was looking for! Thanks a lot!!! :-)

  • Horst


    tnx, for that solution. with playing a little bit around I got it also working with that code:

    Java Code:

    final BufferedImage img = ImageIO.read(new File("test.jpeg"));
    openCv.showImage(img.getWidth(), img.getHeight(), img.getRGB(0, 0, img.getWidth(), img.getHeight(), null, 0, img.getWidth()));

    C++ Code:

    JNIEXPORT void JNICALL Java_at_test_opencv2java_OpenCV2Java_showImage
    (JNIEnv* env, jobject, jint width, jint height, jintArray rgbArray)
    jint *carr;
    carr = env->GetIntArrayElements(rgbArray, NULL);
    if (carr == NULL) {
    return; /* TODO: exception occurred */
    Mat img(height, width, CV_8UC4, carr);
    cv::imshow( "result", img);

    env->ReleaseIntArrayElements(rgbArray, carr, 0);