动脑学院 - Java 和 JNI方式处理图片比较
2016-08-29 02:24
351 查看
MainAcitivty:
JavaImageUtils:
NdkImageUtils:
生成的JNI头文件,club_younge_ndk_NdkImageUtils.h:
实现类,编辑实现类时,右键,Android tools -> add Native support, 然后右键Properties -> c/c++ general -> paths and symbols 若为添加包含的头文件路径,需要添加包含的头文件路径,这样在CPP文件中才会出现代码提示,确保不那么容易出现错误。club_younge_ndk_NdkImageUtils.cpp:
测试结果:java:1579ms, jni:470ms, 性能提升3倍多一点。若用大图超过1M,JNI调用直接崩溃退出,报Fatal signal 11 (SIGSEGV) at 0x00000000 (code=1)。
Github:源码
/** * @projectName:JavaNdkComp * @fileName:MainActivity.java * @packageName:club.younge.demo * @date:2016年8月28日下午11:10:29 * @copyright (c) 2016, heqy@finansir.nt All Rights Reserved. * */ package club.younge.demo; import android.app.Activity; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Bitmap.Config; import android.media.Image; import android.os.Bundle; import android.view.View; import android.widget.ImageView; import android.widget.Toast; import club.younge.java.JavaImageUtils; import club.younge.ndk.NdkImageUtils; /** * @className:MainActivity * @function: TODO ADD FUNCTION. * @reason: TODO ADD REASON. * @date: 2016年8月28日 下午11:10:29 * @author Younge * @version * @since JDK 1.8 * @see */ public class MainActivity extends Activity { private ImageView imageView; private Bitmap mBitmap; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); imageView = (ImageView) findViewById(R.id.imageView); mBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.xy); } public void srcImage(View view) { imageView.setImageBitmap(mBitmap); } public void javaImage(View view) { long start = System.currentTimeMillis(); Bitmap bitmap = JavaImageUtils.getBitMap(mBitmap); imageView.setImageBitmap(bitmap); long end = System.currentTimeMillis(); Toast.makeText(this, "耗时:"+ (end -start) +"ms", Toast.LENGTH_SHORT).show(); } public void ndkImage(View view) { int width = mBitmap.getWidth(); int height = mBitmap.getHeight(); int[] buffer = new int[width*height]; mBitmap.getPixels(buffer, 0, width, 0, 0, width, height); long start = System.currentTimeMillis(); int[] result = NdkImageUtils.getImage(buffer, width, height); Bitmap bitmap = Bitmap.createBitmap(result, 0, width, width, height, Config.ARGB_8888); imageView.setImageBitmap(bitmap); long end = System.currentTimeMillis(); Toast.makeText(this, "耗时:"+ (end -start) +"ms", Toast.LENGTH_SHORT).show(); } }
JavaImageUtils:
/** * @projectName:JavaNdkComp * @fileName:JavaImageUtils.java * @packageName:club.younge.java * @date:2016年8月28日下午11:12:57 * @copyright (c) 2016, heqy@finansir.nt All Rights Reserved. * */ package club.younge.java; import android.graphics.Bitmap; import android.graphics.Bitmap.Config; import android.graphics.Color; /** * @className:JavaImageUtils * @function: TODO ADD FUNCTION. * @reason: TODO ADD REASON. * @date: 2016年8月28日 下午11:12:57 * @author Younge * @version * @since JDK 1.8 * @see */ public class JavaImageUtils { public static Bitmap getBitMap(Bitmap bitmap){ if(bitmap == null) return null; int width = bitmap.getWidth(); int height = bitmap.getHeight(); Bitmap result = Bitmap.createBitmap(width, height, Config.ARGB_8888); int color, a, r, g, b, rt, gt, bt; float bright = 0.2f; float contrast = 0.2f; int bri = (int)(256*bright); for (int x = 0; x < width; x++) { for (int y = 0; y < height; y++) { color = bitmap.getPixel(x, y); a = Color.alpha(color); r = Color.red(color); g = Color.green(color); b = Color.blue(color); //更改亮度,统一增加一个值,变得更白更亮 rt = r + bri; gt = g + bri; bt = b + bri; r = rt > 255 ? 255:(rt < 0 ? 0: rt); //事实在目前情况下,不会出现rt小于0的情况,此处这么写是为了统一后边 g = gt > 255 ? 255:(gt < 0 ? 0: gt); b = bt > 255 ? 255:(bt < 0 ? 0: bt); //更改对比度, 以128中间值为分界点,白的更白,黑的更黑,增加对比度 r = r - 128; g = g - 128; b = b - 128; rt = (int) (r*(1 + contrast)) + 128; gt = (int) (g*(1 + contrast)) + 128; bt = (int) (b*(1 + contrast)) + 128; r = rt > 255 ? 255:(rt < 0 ? 0: rt); g = gt > 255 ? 255:(gt < 0 ? 0: gt); b = bt > 255 ? 255:(bt < 0 ? 0: bt); color = Color.argb(a, r, g, b); result.setPixel(x, y, color); } } return result; } }
NdkImageUtils:
/** * @projectName:JavaNdkComp * @fileName:NdkImageUtils.java * @packageName:club.younge.ndk * @date:2016年8月28日下午11:13:12 * @copyright (c) 2016, heqy@finansir.nt All Rights Reserved. * */ package club.younge.ndk; /** * @className:NdkImageUtils * @function: TODO ADD FUNCTION. * @reason: TODO ADD REASON. * @date: 2016年8月28日 下午11:13:12 * @author Younge * @version * @since JDK 1.8 * @see */ public class NdkImageUtils { static{ System.loadLibrary("Image"); } public static native int[] getImage(int[] buffer, int width, int height); }
生成的JNI头文件,club_younge_ndk_NdkImageUtils.h:
/* DO NOT EDIT THIS FILE - it is machine generated */ #include <jni.h> /* Header for class club_younge_ndk_NdkImageUtils */ #ifndef _Included_club_younge_ndk_NdkImageUtils #define _Included_club_younge_ndk_NdkImageUtils #ifdef __cplusplus extern "C" { #endif /* * Class: club_younge_ndk_NdkImageUtils * Method: getImage * Signature: ([III)[I */ JNIEXPORT jintArray JNICALL Java_club_younge_ndk_NdkImageUtils_getImage (JNIEnv *, jclass, jintArray, jint, jint); #ifdef __cplusplus } #endif #endif
实现类,编辑实现类时,右键,Android tools -> add Native support, 然后右键Properties -> c/c++ general -> paths and symbols 若为添加包含的头文件路径,需要添加包含的头文件路径,这样在CPP文件中才会出现代码提示,确保不那么容易出现错误。club_younge_ndk_NdkImageUtils.cpp:
/* DO NOT EDIT THIS FILE - it is machine generated */ #include <stdlib.h> #include <jni.h> #include "club_younge_ndk_NdkImageUtils.h" /* Header for class club_younge_ndk_NdkImageUtils */ /* * Class: club_younge_ndk_NdkImageUtils * Method: getImage * Signature: ([III)[I */ JNIEXPORT jintArray JNICALL Java_club_younge_ndk_NdkImageUtils_getImage (JNIEnv *env, jclass clazz, jintArray buffer, jint width, jint height){ jint *buf = (jint*)env->GetIntArrayElements(buffer, 0); jsize len = env->GetArrayLength(buffer); jint resultBuf[len]; jintArray result = env->NewIntArray(len); int color, a, r, g, b, rt, gt, bt; int bright = (int)(0.2f*256); float contrast = 0.2f; for(int x = 0; x < width; x++){ for(int y = 0; y < height; y++){ color = buf[y*width + x]; a = color >> 24; r = (color >> 16) & 0xFF; g = (color >> 8) & 0xFF; b = color & 0xFF; //改变亮度 rt = r + bright; gt = g + bright; bt = b + bright; r = rt > 255 ? 255 : rt; g = gt > 255 ? 255 : gt; b = bt > 255 ? 255 : bt; //改变对比度 r = r - 128; g = g - 128; b = b - 128; rt = (int) (r*(1 + contrast)) + 128; gt = (int) (g*(1 + contrast)) + 128; bt = (int) (b*(1 + contrast)) + 128; r = rt > 255 ? 255 : (rt < 0 ? 0 : rt); g = gt > 255 ? 255 : (gt < 0 ? 0 : gt); b = bt > 255 ? 255 : (bt < 0 ? 0 : bt); color = a << 24 | r << 16 | g << 8 | b; resultBuf[y*width + x] = color; } } env->ReleaseIntArrayElements(buffer,buf,0); env->SetIntArrayRegion(result, 0, len, resultBuf); return result; }
测试结果:java:1579ms, jni:470ms, 性能提升3倍多一点。若用大图超过1M,JNI调用直接崩溃退出,报Fatal signal 11 (SIGSEGV) at 0x00000000 (code=1)。
Github:源码
相关文章推荐
- [Android]-图片JNI(C++\Java)高斯模糊的实现与比较
- 从url下载图片--java与python实现方式比较
- [Android]-图片JNI(C++\Java)高斯模糊的实现与比较
- [Android]-图片JNI(C++\Java)高斯模糊的实现与比较
- java中如何判断一个数是否为正整数(多种种方式比较有意思)对时间处理也可以
- jQuery使用Base64 生成图片预览和java后台不同的接收处理方式
- java---access文件(accdb\mdb)文件处理方式比较jackcess 和 Access_JDBC30
- [Android]-图片JNI(C++\Java)高斯模糊的实现与比较
- java中 使用ImageMagick处理图片(对图片处理要求比较高的解决方案)
- java处理XML三种解析方式比较
- java中四种操作xml方式的比较
- java中四种操作xml方式的比较(摘抄)
- java中四种操作xml方式的比较
- Java对特殊编码方式的处理
- java中对于initializer的处理方式
- java图片处理(转)
- java中四种操作xml方式的比较
- Java的图片处理
- 趣说java处理异常的方式
- java中四种操作xml方式的比较(转载)