Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Documentation: add example code for using jna #23

Open
beethoven2493 opened this issue Oct 20, 2018 · 0 comments
Open

Documentation: add example code for using jna #23

beethoven2493 opened this issue Oct 20, 2018 · 0 comments

Comments

@beethoven2493
Copy link

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);
    }
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant