JAVA层和JNI层实现Bitmap图镜像功能。
写在前面:
经过几天查阅资料,终于完成镜像功能,其中加载位图时需对位图进行处理,主要原因是因为超过8M的位图加载进进程会出现内存溢出,图片处理包含两个部分:缩放处理和质量处理。
我这里选择的是质量处理。Java层代码很简单,网上资料很多,JNI层使用C++实现,传三个参数,即存像素的Int数组,图片宽和图片高,其实这里传进来二维数组会更好处理。
JAVA代码:
public class MainActivity extends Activity {
/** Called when the activity is first created. */
Button btnJAVA,btnJNI;
Button btn;
ImageView imgView;
int quality=1000;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btn=(Button)this.findViewById(R.id.btn);
btn.setOnClickListener(new ClickEvent());
btnJAVA=(Button)this.findViewById(R.id.btnJAVA);
btnJAVA.setOnClickListener(new ClickEvent());
btnJNI=(Button)this.findViewById(R.id.btnJNI);
btnJNI.setOnClickListener(new ClickEvent());
imgView=(ImageView)this.findViewById(R.id.ImageView01);
}
class ClickEvent implements View.OnClickListener{
@Override
public void onClick(View v) {
if(v==btnJAVA)
{
Bitmap mBitmap;
try {
mBitmap = revitionImageSize("bg.jpg", quality);
Bitmap mmBitmap=convertBmp(mBitmap);
imgView.setImageBitmap(mmBitmap);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
else if(v==btnJNI)
{
//先打开图像并读取像素
Bitmap img1;
try {
img1 = revitionImageSize("bg.jpg", quality);
int w=img1.getWidth(),h=img1.getHeight();
int[] pix = new int[w * h];
img1.getPixels(pix, 0, w, 0, 0, w, h);
int[] resultInt=Convert.Convert(pix, w, h);
Bitmap resultImg=Bitmap.createBitmap(w, h, Config.RGB_565);
resultImg.setPixels(resultInt, 0, w, 0, 0,w, h);
imgView.setImageBitmap(resultImg);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
else if(v==btn)
{
Bitmap mBitmap;
try {
mBitmap = revitionImageSize("bg.jpg", quality);
imgView.setImageBitmap(mBitmap);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
/*缩小位图处理*/
private Bitmap revitionImageSize(String path, int size) throws IOException {
InputStream temp = this.getAssets().open(path);
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeStream(temp, null, options);
temp.close();
int i = 0;
Bitmap bitmap = null;
while (true) {
if ((options.outWidth >> i <= size)
&& (options.outHeight >> i <= size)) {
temp = this.getAssets().open(path);
options.inSampleSize = (int) Math.pow(2.0D, i);
options.inJustDecodeBounds = false;
bitmap = BitmapFactory.decodeStream(temp, null, options);
break;
}
i += 1;
}
return bitmap;
}
/*Java层实现镜像功能*/
public Bitmap convertBmp(Bitmap bmp){
int w = bmp.getWidth();
int h = bmp.getHeight();
Bitmap convertBmp = Bitmap.createBitmap(w, h, Config.ARGB_8888);
Canvas cv = new Canvas(convertBmp);
Matrix matrix = new Matrix();
matrix.postScale(-1, 1);
Bitmap newBmp = Bitmap.createBitmap(bmp, 0, 0, w, h, matrix, true);
cv.drawBitmap(newBmp, new Rect(0, 0,newBmp.getWidth(), newBmp.getHeight()),new Rect(0, 0, w, h), null);
return convertBmp;
}
}
JNI层C++代码:
#include <jni.h>
#include <stdio.h>
#include <stdlib.h>
using namespace std;
extern "C" {
JNIEXPORT jintArray JNICALL Java_com_example_convertbitmap_Convert_Convert(
JNIEnv* env, jobject obj, jintArray buf, int w, int h);
}
;
JNIEXPORT jintArray JNICALL Java_com_example_convertbitmap_Convert_Convert(
JNIEnv* env, jobject obj, jintArray buf, int w, int h) {
jint *cbuf;
cbuf = env->GetIntArrayElements(buf, false);
if (cbuf == NULL) {
return 0; /* exception occurred */
}
int alpha = 0xFF << 24;
for (int i = 0; i < h; i++) {
for (int j = 0; j < w/2; j++) {
//像素交换
int tmp=cbuf[i*w+j];
cbuf[i*w+j]=cbuf[(i+1)*w-j-1];
cbuf[(i+1)*w-j-1]=tmp;
}
}
int size=w * h;
jintArray result = env->NewIntArray(size);
env->SetIntArrayRegion(result, 0, size, cbuf);
env->ReleaseIntArrayElements(buf, cbuf, 0);
return result;
}
github代码链接:https://github.com/mgstone/mygit/tree/master/ConvertBitmap