Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to convert int[] to ByteBuffer in Java?

as the title already says, I need to convert an int[] to a ByteBuffer in Java. Is there a recommended way to do this ?

I want to pass the ByteBuffer over JNI to C++. What do I have to look out for regarding any specific endian conversions in this case ?

Edit: Sorry, I mistakenly wrote ByteArray but meant the type ByteBuffer.

Edit: Sample code:

I stripped out the unnecessary parts. I call a Java function over JNI from c++ to load a resource and pass it back to c++ as bytebuffer. It works with various other resources. Now I have an "int []" and would like to know if there is an elegant way to convert it to a bytebuffer or if I have to go the oldfashioned way and fill it in a for loop.

ByteBuffer  resource= null;
resource = ByteBuffer.allocateDirect((x*y+2)*4).order(ByteOrder.nativeOrder());
.
.
ByteBuffer GetResourcePNG(String text)
{
    .
    .
    int []  pix;
    map.getPixels(pix,0,x,0,0,x,y);

    return resource;
}
like image 898
HardCoder Avatar asked Feb 21 '23 08:02

HardCoder


2 Answers

You have to use ByteBuffer.allocateDirect if you want to be able to use JNI's GetDirectBufferAddress.

Use ByteBuffer.order(ByteOrder.nativeOrder()) to adjust the ByteBuffer instance's endianness to match the current platform.

After the ByteBuffer's endianness is properly configured, use ByteBuffer.asIntBuffer() to get a view of it as a java.nio.IntBuffer and fill it with your data.

Full Example:

import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.nio.IntBuffer;

public class Test {
    static final int bytes_per_datum = 4;

    public static void main(String args[]) {
        main2("Native Endian", ByteOrder.nativeOrder());
        main2("Big Endian", ByteOrder.BIG_ENDIAN);
        main2("Little Endian", ByteOrder.LITTLE_ENDIAN);
    }

    static void main2(String comment, ByteOrder endian) {
        int[] data = { 1, 0xF, 0xFF, 0xFFF, 0xFFFF, 0xFFFFF, 0xFFFFFF, 0xFFFFFFF, 0xFFFFFFFF };
        ByteBuffer bb = ByteBuffer.allocateDirect(data.length * bytes_per_datum);
        bb.order(endian); // endian must be set before putting ints into the buffer
        put_ints(bb, data);

        System.out.println(comment + ": ");
        print(bb);
    }

    static void put_ints(ByteBuffer bb, int[] data) {
        IntBuffer b = bb.asIntBuffer(); // created IntBuffer starts only from the ByteBuffer's relative position
                                        // if you plan to reuse this IntBuffer, be mindful of its position
        b.put(data); // position of this IntBuffer changes by +data.length;
    } // this IntBuffer goes out of scope

    static void print(ByteBuffer bb) { // prints from start to limit
        ByteBuffer bb_2 = bb.duplicate(); // shares backing content, but has its own capacity/limit/position/mark (equivalent to original buffer at initialization)
        bb_2.rewind();
        for (int x = 0, xx = bb_2.limit(); x < xx; ++x) {
            System.out.print((bb_2.get() & 0xFF) + " "); // 0xFF for display, since java bytes are signed
            if ((x + 1) % bytes_per_datum == 0) {
                System.out.print(System.lineSeparator());
            }
        }
    }
}
like image 173
Gregory Pakosz Avatar answered Mar 05 '23 02:03

Gregory Pakosz


you could convert to matrix in this way:

public static final byte[] intToByteArray(int value) {
    return new byte[] {
            (byte)(value >>> 24),
            (byte)(value >>> 16),
            (byte)(value >>> 8),
            (byte)value};
}

int[] arrayOfInt = {1,2,3,4,5,6};
byte[][] matrix = new byte[arrayOfInt.length][size];
for(int i=0;i<arrayOfInt.length;i++)
   byte[i] = intToByteArray(arrayOfInt[i]);
like image 45
Jayyrus Avatar answered Mar 05 '23 02:03

Jayyrus