如何将 jpeglib-turbo 与 android ndk 一起使用?
How to use jpeglib-turbo with android ndk?
我正在尝试将 jpeglib-turbo 与 android ndk 一起使用来获取 jpeg 图像的像素 rgb 值,我对 C++、C 和 android NDK 都是新手,直到现在我已经尝试使用 Examples or tutorials of using libjpeg-turbo's TurboJPEG but i am unable to fix the issue at hand, Currently using 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 调用它,我正在使用
public class 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 生成的 so 文件的帮助下,我已经成功地从 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 天以来我一直坚持这个问题 :) 谢谢。
tjDecompressHeader2 需要更改,我们需要在库版本中使用 tjDecompressHeader3,我们还需要将 jbyteArray 转换为 unsigned char * 然后返回到 jbyteArray,以便 return 字节数组到 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;
}
我正在尝试将 jpeglib-turbo 与 android ndk 一起使用来获取 jpeg 图像的像素 rgb 值,我对 C++、C 和 android NDK 都是新手,直到现在我已经尝试使用 Examples or tutorials of using libjpeg-turbo's TurboJPEG but i am unable to fix the issue at hand, Currently using 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 调用它,我正在使用 public class 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 生成的 so 文件的帮助下,我已经成功地从 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 天以来我一直坚持这个问题 :) 谢谢。
tjDecompressHeader2 需要更改,我们需要在库版本中使用 tjDecompressHeader3,我们还需要将 jbyteArray 转换为 unsigned char * 然后返回到 jbyteArray,以便 return 字节数组到 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;
}