如何使用jpeglib-turbo与android ndk?

时间:2018-03-07 15:16:16

标签: android android-ndk libjpeg-turbo

我正在尝试使用jpeglib-turbo和android ndk来获取jpeg图像的像素rgb值,我是C ++,C和android NDK的新手,直到现在我已尝试使用提供的解决方案在Examples or tutorials of using libjpeg-turbo's TurboJPEG,但我无法解决手头的问题,目前使用https://github.com/openstf/android-libjpeg-turbo构建libjpeg-turbo。

目前的代码是

#include <turbojpeg.h>
#include <jni.h>
#include <android/log.h>
#include <syslog.h>



JNIEXPORT jbyteArray
Java_com_serelay_jpegturbo_MainActivity_getImagePixelData( JNIEnv*  env,
                                jobject  this,
                                jbyteArray data)
{
long unsigned int _jpegSize=2464742; //!< _jpegSize from above
unsigned char *_compressedImage; //!< _compressedImage from above

_compressedImage = data;

int width, height, jpegSubSamp;
// int jpegSubSamp = TJSAMP_444;


tjhandle _jpegDecompressor = tjInitDecompress();

tjDecompressHeader2(_jpegDecompressor, _compressedImage, _jpegSize, &width, 
&height, &jpegSubSamp);

unsigned long len = width * height * 4;
unsigned long pitch = width * 4;
syslog(LOG_CRIT, "====================");
syslog(LOG_CRIT, "jpegSize %lu", _jpegSize);

syslog(LOG_CRIT, "width %d", width);
syslog(LOG_CRIT, "height %d", height);
syslog(LOG_CRIT, "total length %lu", len);

syslog(LOG_CRIT, "====================");



unsigned char buffer[len]; //!< will contain the decompressed image

tjDecompress2(_jpegDecompressor, _compressedImage, _jpegSize, buffer, width, pitch, height, TJPF_RGBA, 0);

tjDestroy(_jpegDecompressor);


// char array to byte array 

jbyteArray jbytes = buffer;
//jbyteArray jbytes = _compressedImage;

return jbytes;
}

从我正在使用的java中调用它     公共类MainActivity扩展了AppCompatActivity {

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    // Example of a call to a native method
    TextView tv = (TextView) findViewById(R.id.sample_text);
    System.loadLibrary("twolib-second");
    InputStream inputStream= getResources().openRawResource(R.raw.image1);
    byte[] bytes;
    try {
        bytes = new byte[inputStream.available()];
        inputStream.read(bytes);

        byte[] array = getImagePixelData(bytes);
        tv.setText(String.valueOf(getImagePixelData(bytes).length));

    } catch (IOException e) {
        e.printStackTrace();
    }

//        tv.setText(getImagePixelData(5));
}

/**
 * A native method that is implemented by the 'native-lib' native library,
 * which is packaged with this application.
 */
public native byte[] getImagePixelData(byte[] x);
}

我已经在ndk生成的文件的帮助下成功调用了java中的代码,但我遇到的问题是代码中的例外情况,     信号11(SIGSEGV),代码1(SEGV_MAPERR),故障地址0xeaa6cc30

在进一步检查时我记录了一些变量的值,考虑到传递的图像大小为3840 * 2160,在记录变量时我感觉有点不好

03-07 20:26:05.180 13613-13613/com.serelay.jpegturbo E/com.serelay.jpegturbo: 
====================
03-07 20:26:05.180 13613-13613/com.serelay.jpegturbo E/com.serelay.jpegturbo: 
jpegSize 2464742
03-07 20:26:05.180 13613-13613/com.serelay.jpegturbo E/com.serelay.jpegturbo: 
width 4
03-07 20:26:05.180 13613-13613/com.serelay.jpegturbo E/com.serelay.jpegturbo: 
height -1386946560
03-07 20:26:05.180 13613-13613/com.serelay.jpegturbo E/com.serelay.jpegturbo: 
total length 3578658816
03-07 20:26:05.180 13613-13613/com.serelay.jpegturbo E/com.serelay.jpegturbo: 
====================

我可以看到宽度和高度值非常错误,但我无法弄清楚为什么以及如何解决它。 如果可以提供任何帮助或方向来解决这个问题,那将是很好的,自从过去2天以来我一直坚持:)谢谢。

1 个答案:

答案 0 :(得分:0)

在tjDecompressHeader2中需要进行更改,我们需要在库版本中使用tjDecompressHeader3,我们还需要将jbyteArray转换为unsigned char *然后返回jbyteArray以便将字节数组返回给java,这两者都可以被观察到在下面的代码中。

#include <turbojpeg.h>
#include <jni.h>
#include <android/log.h>
#include <syslog.h>



JNIEXPORT jbyteArray
Java_com_serelay_jpegturbo_MainActivity_getImagePixelData( JNIEnv*  env,
                                jobject  this,
                                jbyteArray data,
                                jint dataLength)
{
long unsigned int _jpegSize=dataLength; //!< _jpegSize from above
unsigned char *_compressedImage; //!< _compressedImage from above
jboolean isCopy;

_compressedImage = (unsigned char*)(*env)->GetByteArrayElements(env, data, 
&isCopy);
int width, height, jpegSubSamp, jpegColorSpace;
// int jpegSubSamp = TJSAMP_444;


tjhandle _jpegDecompressor = tjInitDecompress();

tjDecompressHeader3(_jpegDecompressor, _compressedImage, _jpegSize, &width, 
&height, &jpegSubSamp, &jpegColorSpace);

long len = width * height * 4;
long pitch = width * 4;
syslog(LOG_CRIT, "====================");
syslog(LOG_CRIT, "jpegSize %lu", _jpegSize);

syslog(LOG_CRIT, "width %d", width);
syslog(LOG_CRIT, "height %d", height);
syslog(LOG_CRIT, "subsampl %d", jpegSubSamp);
syslog(LOG_CRIT, "colorSpace %d", jpegColorSpace);
    syslog(LOG_CRIT, "len %lu", len);
    syslog(LOG_CRIT, "pitch %lu", pitch);


syslog(LOG_CRIT, "====================");
syslog(LOG_CRIT, "===================0");



unsigned char* mumfer = (unsigned char*)malloc(len); //!< will contain the 
decompressed image
syslog(LOG_CRIT, "===================1");

tjDecompress2(_jpegDecompressor, _compressedImage, _jpegSize, mumfer, width, 
0, height, TJPF_RGBA, TJFLAG_FASTDCT);
syslog(LOG_CRIT, "===================2");

tjDestroy(_jpegDecompressor);
syslog(LOG_CRIT, "===================3");


// char array to byte array 

jbyteArray array = (*env)->NewByteArray(env, len);
syslog(LOG_CRIT, "===================4");

//HERE I GET THE ERROR, I HAVE BEEN TRYING WITH len/2 and WORKS , PROBABLY 
SOME BYTS ARE GETTING LOST.
(*env)->SetByteArrayRegion (env, array, 0, len, (jbyte*)(mumfer));
syslog(LOG_CRIT, "===================5");
return array;
}

同样在java中我们需要将byte []转换为int []以获得精确的像素颜色值,这可以通过以下函数来完成

public static int byteToColorInt(byte b) {
    return b & 0xFF;
}