Documentation: add example code for using jna
beethoven2493 opened this issue · 0 comments
beethoven2493 commented
com.sun.jna is an excellent library for calling C from java. I've used this with epeg to great success.
For example:
public interface EpegLibrary extends Library {
Pointer epeg_file_open(String fileName);
Pointer epeg_memory_open(Memory memory, int len);
void epeg_size_get(Pointer image, int[] width, int[] height);
void epeg_decode_size_set(Pointer image, int width, int height);
void epeg_quality_set(Pointer image, int quality);
void epeg_memory_output_set(Pointer image, PointerByReference output, LongByReference size);
int epeg_encode(Pointer image);
void epeg_close(Pointer image);
}
private final EpegLibrary epeg = Native.loadLibrary("epeg", EpegLibrary.class);
// this is an unfortunate hack, I hope someone can figure out a better version
private static class ExposingFree extends Memory {
public static void exposedFree(Pointer p) {
free(Pointer.nativeValue(p));
}
}
public byte[] thumb(String fileName, int targetBigDim, int targetLittleDim, int qualityOutOf100) {
Pointer image = epeg.epeg_file_open(fileName);
return thumb(image, targetBigDim, targetLittleDim, qualityOutOf100);
}
public byte[] thumb(byte[] source, int targetBigDim, int targetLittleDim, int qualityOutOf100) {
Memory buf = new Memory(source.length);
buf.write(0, source, 0, source.length);
Pointer image = epeg.epeg_memory_open(buf, source.length);
byte[] result = thumb(image, targetBigDim, targetLittleDim, qualityOutOf100);
// would free memory here, but it apparently just gets GC'd
return result;
}
private byte[] thumb(Pointer image, int targetBigDim, int targetLittleDim, int qualityOutOf100) {
if (image == null)
return null;
int[] width = new int[1];
int[] height = new int[1];
epeg.epeg_size_get(image, width, height);
while ((width[0] >= targetBigDim * 2 && height[0] >= targetBigDim * 2) || (width[0] >= targetLittleDim * 2 || height[0] >= targetLittleDim * 2)) {
width[0] /= 2;
height[0] /= 2;
}
epeg.epeg_decode_size_set(image, width[0], height[0]);
epeg.epeg_quality_set(image, qualityOutOf100);
PointerByReference m = new PointerByReference();
LongByReference sizeMem = new LongByReference();
sizeMem.setValue(0);
epeg.epeg_memory_output_set(image, m, sizeMem);
int encodeStatus = epeg.epeg_encode(image);
try {
if (encodeStatus != 0) {
throw new RuntimeException("epeg_encode: Error encoding, error=" + encodeStatus);
}
long size = sizeMem.getValue();
if (size == 0) {
throw new RuntimeException("epeg: Size was 0");
}
if (size > Integer.MAX_VALUE) {
throw new RuntimeException("epeg: Size was > 2GB");
}
Pointer pointer = m.getValue();
try {
byte[] bytes = pointer.getByteArray(0, (int)size);
return bytes;
} finally {
ExposingFree.exposedFree(pointer);
}
} finally {
epeg.epeg_close(image);
}
}