机器人如何通过JNI的例子使用的libjpeg涡轮增压库 [英] Android how to use libjpeg-turbo library through JNi example

查看:678
本文介绍了机器人如何通过JNI的例子使用的libjpeg涡轮增压库的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我成功打造的libjpeg-turbo跟NDK建造感谢这篇文章: 的libjpeg涡轮增压为Android

I successfully build libjpeg-turbo with ndk-build thanks to this post: libjpeg-turbo for android

我想获得像read_JPEG_file本机功能的libjpeg涡轮增压的将example.c从Java code调用使用它的Andr​​oid应用程序。

I would like to get a native function like read_JPEG_file in the example.c of libjpeg-turbo to call from the Java code to use it for Android app.

可能有人给我一个例子,如何做到这一点?如何写一个本地方法的Java它们使用的libjpeg涡轮增压NDK建库?

Could someone give me an example how to do it? How to write a native method for Java which use libjpeg-turbo ndk built library?

我可以通过

System.loadLibrary("libjpeg");

但接下来呢?本库没有任何本地方法从Java调用。

But what next? The library doesn't have any native methods to call from Java.

我想写根据JNI documentarion但没有成功JNI的C类。 样品code将是巨大的,以了解如何做到这一点。

I was trying to write a JNI c class according JNI documentarion but with no success. Sample code would be great to learn how to do it.

编辑:

我创建了一个测试类NativeMethods:

I created a test class NativeMethods:

package com.test.app;

public class NativeMethods {

    private String filename = null;

    static {
        System.loadLibrary("jpeg"); // this represents compiled libjpeg-turbo under ndk
    }

    public NativeMethods(String jpegFilename) {
        this.filename = jpegFilename;
    }

    public native int computeNumberOfDCTS(String filename);
}

然后我用javah的生成本地方法的C头,结果是 com_test_app_NativeMethods.h 包含文件:

/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_test_app_NativeMethods */

#ifndef _Included_com_test_app_NativeMethods
#define _Included_com_test_app_NativeMethods
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     com_test_app_NativeMethods
 * Method:    computeNumberOfDCTS
 * Signature: (Ljava/lang/String;)I
 */
JNIEXPORT jint JNICALL Java_com_test_app_NativeMethods_computeNumberOfDCTS
  (JNIEnv *, jobject, jstring);

#ifdef __cplusplus
}
#endif
#endif

然后,我创建了一个名为 JPEGProcessing.c 在这里我把本机函数的C实现文件,如下所示:

Then I created file named JPEGProcessing.c where I put the c implementation of the native function as follows:

#include "com_test_app_NativeMethods.h"

//that came from jpeglib example
struct my_error_mgr
{
    struct jpeg_error_mgr pub;
    jmp_buf setjmp_buffer;
};
typedef struct my_error_mgr * my_error_ptr;

//routine that will replace the standard error_exit method
static void
my_error_exit (j_common_ptr cinfo)
{
    /* cinfo->err really points to a my_error_mgr struct, so coerce pointer */
    my_error_ptr myerr = (my_error_ptr) cinfo->err;

    (*cinfo->err->output_message) (cinfo);

    /* Return control to the setjmp point */
    longjmp(myerr->setjmp_buffer, 1);
}

JNIEXPORT jint JNICALL Java_com_test_app_NativeMethods_computeNumberOfDCTS
    (JNIEnv *env, jobject obj, jstring javaString)
{
    jint toReturn = 0;
    // struct representing jpeg image
    struct jpeg_decompress_struct  cinfo;
    // struct representing error manager; defined above
    struct my_error_mgr jerr;

    const char *filename = (*env)->GetStringUTFChars(env, javaString, 0);

    FILE * infile;

    if ((infile = fopen(filename, "rb")) == NULL) {
        fprintf(stderr, "can't open %s\n", filename);
        return -1;
    }

    cinfo.err = jpeg_std_error(&jerr.pub);
    jerr.pub.error_exit = my_error_exit;

    if (setjmp(jerr.setjmp_buffer)) {
        jpeg_destroy_decompress(&cinfo);
        fclose(infile);
        return -1;
    }

    jpeg_create_decompress(&cinfo);

    jpeg_stdio_src(&cinfo, infile);

    (void) jpeg_read_header(&cinfo, TRUE);

    // declare virtual arrays for DCT coefficients
    jvirt_barray_ptr* coeffs_array;
    // read DCT coefficients from jpeg
    coeffs_array = jpeg_read_coefficients(&cinfo);

    // fill virtual arrays.
    // ci represents component color
    // this cycle prints all dct coefficient of the jpeg in 8x8 blocks
    for (int ci = 0; ci < 3; ci++)
    {
        JBLOCKARRAY buffer_one;
        JCOEFPTR blockptr_one;
        jpeg_component_info* compptr_one;
        compptr_one = cinfo.comp_info + ci;

        for (int by = 1; by < (compptr_one->height_in_blocks - 1); by++) // we don't want to use the edges of the images
        {
            buffer_one = (cinfo.mem->access_virt_barray)((j_common_ptr)&cinfo, coeffs_array[ci], by, (JDIMENSION)1, FALSE);

            for (int bx = 1; bx < (compptr_one->width_in_blocks - 1); bx++) // we don't want to use the edges of the images
            {
                blockptr_one = buffer_one[0][bx];

                for (int bi = 1; bi < 64; bi++) // we don't want to use AC
                {
                    toReturn++;
                }
            }
        }
    }

    jpeg_destroy_decompress(&cinfo);
    fclose(infile);

    return toReturn;
}

文件 JPEGProcessing.c com_test_app_NativeMethods.h 项目/ JNI / 文件夹。在同一JNI的文件夹,我创建 Android.mk 文件,其中我把这些行:

Files JPEGProcessing.c and com_test_app_NativeMethods.h are in the project/jni/ folder. In the same jni folder I created Android.mk file where I put these lines:

LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)

LOCAL_MODULE    := JPEGProcessing
LOCAL_CFLAGS    := -Werror
LOCAL_SRC_FILES := JPEGProcessing.c

LOCAL_C_INCLUDES := $(LOCAL_PATH)
LOCAL_LDLIBS    := -lm -llog -landroid
LOCAL_STATIC_LIBRARIES := libjpeg
include $(BUILD_SHARED_LIBRARY)

在从我的项目目录中运行NDK建造有一些错误的:

After running ndk-build from my project directory there was a number of errors:

jni/JPEGProcessing.c:7:27: error: field 'pub' has incomplete type
jni/JPEGProcessing.c:8:5: error: unknown type name 'jmp_buf'
jni/JPEGProcessing.c:14:16: error: unknown type name 'j_common_ptr'
jni/JPEGProcessing.c: In function 'Java_com_test_app_NativeMethods_computeNumberOfDCTS':
jni/JPEGProcessing.c:30:36: error: storage size of 'cinfo' isn't known
jni/JPEGProcessing.c:36:5: error: unknown type name 'FILE'
jni/JPEGProcessing.c:38:17: error: assignment makes pointer from integer without a cast [-Werror]
jni/JPEGProcessing.c:38:45: error: 'NULL' undeclared (first use in this function)
...

我不明白这一点。如何使用的libjpeg涡轮增压功能结合起来,code,以获得工作库,并用它在Java?

I don't get it. How to combine the code with the libjpeg-turbo functions to get working library and use it in java?

我看了NDK的说明和示例,但仍然不明白这一点。

I read NDK instructions and Examples but still don't get it.

编辑:

NDK和JNI简单的本地方法工作得很好。作为测试我用下面简单的方法效果很好:

NDK and JNI with simple native method works just fine. As a test I used the following simple method which works well:

#include "com_test_app_NativeMethods.h"

JNIEXPORT jint JNICALL Java_com_test_app_NativeMethods_computeNumberOfDCTS
    (JNIEnv *env, jobject obj, jstring javaString)
{
    jint toReturn = 0;

    const char *filename = (*env)->GetStringUTFChars(env, javaString, 0);
    const char *test = "test";

    if ( filename == test )
    {
        toReturn++;
    }

    return toReturn;
}

我试了一下用的libjpeg涡轮增压的东西如下:

I tried it with the libjpeg-turbo stuff as following:

#include "com_test_app_NativeMethods.h"
#include <stdio.h>
#include <setjmp.h>
#include <libjpeg-turbo/jpeglib.h>
#include <libjpeg-turbo/turbojpeg.h>
#include <libjpeg-turbo/jconfig.h>
#include <libjpeg-turbo/jmorecfg.h>
#include <libjpeg-turbo/jerror.h>

//that came from jpeglib example
struct my_error_mgr
{
    struct jpeg_error_mgr pub;
    jmp_buf setjmp_buffer;
};
typedef struct my_error_mgr * my_error_ptr;

//routine that will replace the standard error_exit method
static void
my_error_exit (j_common_ptr cinfo)
{
    /* cinfo->err really points to a my_error_mgr struct, so coerce pointer */
    my_error_ptr myerr = (my_error_ptr) cinfo->err;

    (*cinfo->err->output_message) (cinfo);

    /* Return control to the setjmp point */
    longjmp(myerr->setjmp_buffer, 1);
}

JNIEXPORT jint JNICALL Java_com_test_app_NativeMethods_computeNumberOfDCTS
    (JNIEnv *env, jobject obj, jstring javaString)
{
    jint toReturn = 0;
    // struct representing jpeg image
    struct jpeg_decompress_struct  cinfo;
    // struct representing error manager; defined above
    struct my_error_mgr jerr;

    const char *filename = (*env)->GetStringUTFChars(env, javaString, 0);

    FILE * infile;

    if ((infile = fopen(filename, "rb")) == NULL) {
        // cannot open file
        return -1;
    }

    cinfo.err = jpeg_std_error(&jerr.pub);
    jerr.pub.error_exit = my_error_exit;

    if (setjmp(jerr.setjmp_buffer)) {
        jpeg_destroy_decompress(&cinfo);
        fclose(infile);
        return -1;
    }

    jpeg_create_decompress(&cinfo);

    jpeg_destroy_decompress(&cinfo);
    fclose(infile);

    return toReturn;
}

和我得到的错误...

And I get the errors...:

Compile thumb  : JPEGProcessing <= JPEGProcessing.c
SharedLibrary  : libJPEGProcessing.so
/usr/android-ndk-r8c/toolchains/arm-linux-androideabi-4.6/prebuilt/darwin-x86/bin/../lib/gcc/arm-linux-androideabi/4.6/../../../../arm-linux-androideabi/bin/ld: ./obj/local/armeabi/objs/JPEGProcessing/JPEGProcessing.o: in function Java_com_test_app_NativeMethods_computeNumberOfDCTS:jni/JPEGProcessing.c:50: error: undefined reference to 'jpeg_std_error'
/usr/android-ndk-r8c/toolchains/arm-linux-androideabi-4.6/prebuilt/darwin-x86/bin/../lib/gcc/arm-linux-androideabi/4.6/../../../../arm-linux-androideabi/bin/ld: ./obj/local/armeabi/objs/JPEGProcessing/JPEGProcessing.o: in function Java_com_test_app_NativeMethods_computeNumberOfDCTS:jni/JPEGProcessing.c:59: error: undefined reference to 'jpeg_CreateDecompress'
/usr/android-ndk-r8c/toolchains/arm-linux-androideabi-4.6/prebuilt/darwin-x86/bin/../lib/gcc/arm-linux-androideabi/4.6/../../../../arm-linux-androideabi/bin/ld: ./obj/local/armeabi/objs/JPEGProcessing/JPEGProcessing.o: in function Java_com_test_app_NativeMethods_computeNumberOfDCTS:jni/JPEGProcessing.c:61: error: undefined reference to 'jpeg_destroy_decompress'
/usr/android-ndk-r8c/toolchains/arm-linux-androideabi-4.6/prebuilt/darwin-x86/bin/../lib/gcc/arm-linux-androideabi/4.6/../../../../arm-linux-androideabi/bin/ld: ./obj/local/armeabi/objs/JPEGProcessing/JPEGProcessing.o: in function Java_com_test_app_NativeMethods_computeNumberOfDCTS:jni/JPEGProcessing.c:54: error: undefined reference to 'jpeg_destroy_decompress'
collect2: ld returned 1 exit status
make: *** [obj/local/armeabi/libJPEGProcessing.so] Error 1

那么如何使用本机code与NDK内置的libjpeg涡轮增压库?

So how to use the native code with ndk-built libjpeg-turbo library?

推荐答案

如果你需要从本地code完成这一切,您可以创建自己的包装在本机端的库。 这些步骤大致这些的:

You could create your own wrapper for the library in the native side if you need to perform it all from native code. The steps are roughly these ones:

  • 在那里你调用类的:

  • In the class where you call:

的System.loadLibrary(的libjpeg);

System.loadLibrary("libjpeg");

您声明您需要在Java端调用本地方法,但不提供任何的实现:

You declare the native methods you need to call in the Java side, without providing any implementation:

public static native readJPEGFile();

  • 然后就可以使用javah的命令来创建你的原生funcions在本机端的实现C文件。当你调用Java端本机的功能,将被调用。注意函数和参数,将由javah的命令来自动产生,而不应被改变的全路径,否则将无法正常工作。其结果应该是这样的:

    • Then you can use the javah command to create a C file with the implementation of your native funcions in the native side. That will be called when you call the native function in Java side. Notice the full path of the function and the parameters, that will be automatically generated by the javah command and should not be changed, otherwise it won't work. The result should be something like that:

       extern "C" {
           JNIEXPORT void JNICALL Java_com_android_packagename_GL2JNILib_readJPEGFile(JNIEnv * env, jobject obj);
       };
      
      JNIEXPORT void JNICALL Java_com_android_packagename_GL2JNILib_readJPEGFile(JNIEnv * env, jobject obj) {
          // Call your library's function
       }
      

    • 之后,你需要创建在JNI文件夹的共享库(创建它,如果它不存在),包含你的包装函数。你可以做到这一点创建一个Android.mk文件,并运行NDK建造以生成共享库(.so文件)。一个可能的Andr​​oid.mk也能像这一个,你应该检查虽然名称和依赖关系:

    • After that you need to create a shared library in the jni folder (create it if it doesn't exist) containing your wrapper functions. You can do that creating an Android.mk file and running ndk-build to generate the shared library (.so file). A possible Android.mk could be like this one, you should check the names and dependencies though:

        LOCAL_PATH := $(call my-dir)
        include $(CLEAR_VARS)
        LOCAL_MODULE    := jpgturbo-wrapper
        LOCAL_CFLAGS    := -Werror
        LOCAL_SRC_FILES := jpgturboWrapper.cpp
        LOCAL_C_INCLUDES := $(LOCAL_PATH)
        LOCAL_LDLIBS    := -lm -llog -landroid
        LOCAL_STATIC_LIBRARIES := jpegturbo # write all the libraries your project depend on here, separated by white spaces
        include $(BUILD_SHARED_LIBRARY)
      

    • 现在可以运行NDK建造和.so文件将生成并复制到相应的文件夹。

    • Now you can run ndk-build and the .so file will be generated and copied to its correspondent folder.

      您可以检查NDK文件,以启动与,特别是样品他们提供: http://developer.android.com/tool​​s/sdk/ndk/index.html

      You can check the NDK documentation to start with that, and especially the samples they provide: http://developer.android.com/tools/sdk/ndk/index.html

      有时候也是一个不错的主意,使在GitHub上快速搜索,看看别人拿着疼痛之前,你做的工作同一个库,或者只是看到一些更高级的例子比官方的样本。

      Sometimes is also a good idea to make a quick search on github to see if someone else took the pain before you to make work the same library, or just to see some more advanced examples than the official samples.

      这篇关于机器人如何通过JNI的例子使用的libjpeg涡轮增压库的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆