jni 写一个简单的photoshop
第一步创建 ui
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#ffffffff"
>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="center" > <Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/btnReset"
android:text="Reset"
android:visibility="visible"
android:onClick="onResetImage"
/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/btnConvert"
android:text="Convert Image"
android:visibility="visible"
android:onClick="onConvertToGray"
/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/btnFindEdges"
android:text="Find Edges"
android:visibility="visible"
android:onClick="onFindEdges"
/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/btnDimmer"
android:text="- "
android:visibility="visible"
android:onClick="onDimmer"
/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/btnBrighter"
android:text=" +"
android:visibility="visible"
android:onClick="onBrighter"
/>
</LinearLayout>
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:scaleType="centerCrop"
android:layout_gravity="center_vertical|center_horizontal"
android:id="@+id/ivDisplay"
/>
</LinearLayout>
第二步,写activity MainActivity
import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.graphics.BitmapFactory;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.view.View;
import android.widget.ImageView; public class IBMPhotoPhun extends Activity {
private String tag = "IBMPhotoPhun";
private Bitmap bitmapOrig = null;
private Bitmap bitmapGray = null;
private Bitmap bitmapWip = null;
private ImageView ivDisplay = null; // NDK STUFF
static {
System.loadLibrary("ibmphotophun");
}
public native void convertToGray(Bitmap bitmapIn,Bitmap bitmapOut);
public native void changeBrightness(int direction,Bitmap bitmap);
public native void findEdges(Bitmap bitmapIn,Bitmap bitmapOut);
// END NDK STUFF /** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Log.i(tag,"before image stuff");
ivDisplay = (ImageView) findViewById(R.id.ivDisplay); // load bitmap from resources
BitmapFactory.Options options = new BitmapFactory.Options();
// Make sure it is 24 bit color as our image processing algorithm
// expects this format
options.inPreferredConfig = Config.ARGB_8888;
bitmapOrig = BitmapFactory.decodeResource(this.getResources(),
R.drawable.sampleimage,options);
if (bitmapOrig != null)
ivDisplay.setImageBitmap(bitmapOrig); } public void onResetImage(View v) {
Log.i(tag,"onResetImage"); ivDisplay.setImageBitmap(bitmapOrig); } public void onFindEdges(View v) {
Log.i(tag,"onFindEdges"); // make sure our target bitmaps are happy
bitmapGray = Bitmap.createBitmap(bitmapOrig.getWidth(),bitmapOrig.getHeight(),
Config.ALPHA_8);
bitmapWip = Bitmap.createBitmap(bitmapOrig.getWidth(),bitmapOrig.getHeight(),
Config.ALPHA_8);
// before finding edges, we need to convert this image to gray
convertToGray(bitmapOrig,bitmapGray);
// find edges in the image
findEdges(bitmapGray,bitmapWip);
ivDisplay.setImageBitmap(bitmapWip); }
public void onConvertToGray(View v) {
Log.i(tag,"onConvertToGray"); bitmapWip = Bitmap.createBitmap(bitmapOrig.getWidth(),bitmapOrig.getHeight(),
Config.ALPHA_8);
convertToGray(bitmapOrig,bitmapWip);
ivDisplay.setImageBitmap(bitmapWip);
} public void onDimmer(View v) {
Log.i(tag,"onDimmer"); changeBrightness(2,bitmapWip);
ivDisplay.setImageBitmap(bitmapWip);
}
public void onBrighter(View v) {
Log.i(tag,"onBrighter"); changeBrightness(1,bitmapWip);
ivDisplay.setImageBitmap(bitmapWip);
}
}
Android.mk
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := ibmphotophun
LOCAL_SRC_FILES := ibmphotophun.c
LOCAL_LDLIBS := -llog -ljnigraphics
include $(BUILD_SHARED_LIBRARY)
增加宏
/*
* ibmphotophun.c
*
* Author: Frank Ableson
* Contact Info: fableson@msiservices.com
*/ #include <jni.h>
#include <android/log.h>
#include <android/bitmap.h> #define LOG_TAG "libibmphotophun"
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__)
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__) typedef struct
{
uint8_t alpha;
uint8_t red;
uint8_t green;
uint8_t blue;
} argb; /*
convertToGray
Pixel operation
*/
JNIEXPORT void JNICALL Java_com_msi_ibm_ndk_IBMPhotoPhun_convertToGray(JNIEnv
* env, jobject obj, jobject bitmapcolor,jobject bitmapgray)
{
AndroidBitmapInfo infocolor;
void* pixelscolor;
AndroidBitmapInfo infogray;
void* pixelsgray;
int ret;
int y;
int x; LOGI("convertToGray");
if ((ret = AndroidBitmap_getInfo(env, bitmapcolor, &infocolor)) < 0) {
LOGE("AndroidBitmap_getInfo() failed ! error=%d", ret);
return;
} if ((ret = AndroidBitmap_getInfo(env, bitmapgray, &infogray)) < 0) {
LOGE("AndroidBitmap_getInfo() failed ! error=%d", ret);
return;
} LOGI("color image :: width is %d; height is %d; stride is %d; format is %d;flags is
%d",infocolor.width,infocolor.height,infocolor.stride,infocolor.format,infocolor.flags);
if (infocolor.format != ANDROID_BITMAP_FORMAT_RGBA_8888) {
LOGE("Bitmap format is not RGBA_8888 !");
return;
} LOGI("gray image :: width is %d; height is %d; stride is %d; format is %d;flags is
%d",infogray.width,infogray.height,infogray.stride,infogray.format,infogray.flags);
if (infogray.format != ANDROID_BITMAP_FORMAT_A_8) {
LOGE("Bitmap format is not A_8 !");
return;
} if ((ret = AndroidBitmap_lockPixels(env, bitmapcolor, &pixelscolor)) < 0) {
LOGE("AndroidBitmap_lockPixels() failed ! error=%d", ret);
} if ((ret = AndroidBitmap_lockPixels(env, bitmapgray, &pixelsgray)) < 0) {
LOGE("AndroidBitmap_lockPixels() failed ! error=%d", ret);
} // modify pixels with image processing algorithm for (y=0;y<infocolor.height;y++) {
argb * line = (argb *) pixelscolor;
uint8_t * grayline = (uint8_t *) pixelsgray;
for (x=0;x<infocolor.width;x++) {
grayline[x] = 0.3 * line[x].red + 0.59 * line[x].green + 0.11*line[x].blue;
} pixelscolor = (char *)pixelscolor + infocolor.stride;
pixelsgray = (char *) pixelsgray + infogray.stride;
} LOGI("unlocking pixels");
AndroidBitmap_unlockPixels(env, bitmapcolor);
AndroidBitmap_unlockPixels(env, bitmapgray); } /*
changeBrightness
Pixel Operation
*/
JNIEXPORT void JNICALL Java_com_msi_ibm_ndk_IBMPhotoPhun_changeBrightness(JNIEnv
* env, jobject obj, int direction,jobject bitmap)
{
AndroidBitmapInfo infogray;
void* pixelsgray;
int ret;
int y;
int x;
uint8_t save; if ((ret = AndroidBitmap_getInfo(env, bitmap, &infogray)) < 0) {
LOGE("AndroidBitmap_getInfo() failed ! error=%d", ret);
return;
} LOGI("gray image :: width is %d; height is %d; stride is %d; format is %d;flags is
%d",infogray.width,infogray.height,infogray.stride,infogray.format,infogray.flags);
if (infogray.format != ANDROID_BITMAP_FORMAT_A_8) {
LOGE("Bitmap format is not A_8 !");
return;
} if ((ret = AndroidBitmap_lockPixels(env, bitmap, &pixelsgray)) < 0) {
LOGE("AndroidBitmap_lockPixels() failed ! error=%d", ret);
} // modify pixels with image processing algorithm LOGI("time to modify pixels....");
for (y=0;y<infogray.height;y++) {
uint8_t * grayline = (uint8_t *) pixelsgray;
int v;
for (x=0;x<infogray.width;x++) {
v = (int) grayline[x]; if (direction == 1)
v -=5;
else
v += 5;
if (v >= 255) {
grayline[x] = 255;
} else if (v <= 0) {
grayline[x] = 0;
} else {
grayline[x] = (uint8_t) v;
}
} pixelsgray = (char *) pixelsgray + infogray.stride;
} AndroidBitmap_unlockPixels(env, bitmap); } /*
findEdges
Matrix operation
*/
JNIEXPORT void JNICALL Java_com_msi_ibm_ndk_IBMPhotoPhun_findEdges(JNIEnv
* env, jobject obj, jobject bitmapgray,jobject bitmapedges)
{
AndroidBitmapInfo infogray;
void* pixelsgray;
AndroidBitmapInfo infoedges;
void* pixelsedge;
int ret;
int y;
int x;
int sumX,sumY,sum;
int i,j;
int Gx[3][3];
int Gy[3][3];
uint8_t *graydata;
uint8_t *edgedata; LOGI("findEdges running"); Gx[0][0] = -1;Gx[0][1] = 0;Gx[0][2] = 1;
Gx[1][0] = -2;Gx[1][1] = 0;Gx[1][2] = 2;
Gx[2][0] = -1;Gx[2][1] = 0;Gx[2][2] = 1; Gy[0][0] = 1;Gy[0][1] = 2;Gy[0][2] = 1;
Gy[1][0] = 0;Gy[1][1] = 0;Gy[1][2] = 0;
Gy[2][0] = -1;Gy[2][1] = -2;Gy[2][2] = -1; if ((ret = AndroidBitmap_getInfo(env, bitmapgray, &infogray)) < 0) {
LOGE("AndroidBitmap_getInfo() failed ! error=%d", ret);
return;
} if ((ret = AndroidBitmap_getInfo(env, bitmapedges, &infoedges)) < 0) {
LOGE("AndroidBitmap_getInfo() failed ! error=%d", ret);
return;
} LOGI("gray image :: width is %d; height is %d; stride is %d; format is %d;flags is
%d",infogray.width,infogray.height,infogray.stride,infogray.format,infogray.flags);
if (infogray.format != ANDROID_BITMAP_FORMAT_A_8) {
LOGE("Bitmap format is not A_8 !");
return;
} LOGI("color image :: width is %d; height is %d; stride is %d; format is %d;flags is
%d",infoedges.width,infoedges.height,infoedges.stride,infoedges.format,infoedges.flags);
if (infoedges.format != ANDROID_BITMAP_FORMAT_A_8) {
LOGE("Bitmap format is not A_8 !");
return;
} if ((ret = AndroidBitmap_lockPixels(env, bitmapgray, &pixelsgray)) < 0) {
LOGE("AndroidBitmap_lockPixels() failed ! error=%d", ret);
} if ((ret = AndroidBitmap_lockPixels(env, bitmapedges, &pixelsedge)) < 0) {
LOGE("AndroidBitmap_lockPixels() failed ! error=%d", ret);
} // modify pixels with image processing algorithm LOGI("time to modify pixels...."); graydata = (uint8_t *) pixelsgray;
edgedata = (uint8_t *) pixelsedge; for (y=0;y<=infogray.height - 1;y++) {
for (x=0;x<infogray.width -1;x++) {
sumX = 0;
sumY = 0;
// check boundaries
if (y==0 || y == infogray.height-1) {
sum = 0;
} else if (x == 0 || x == infogray.width -1) {
sum = 0;
} else {
// calc X gradient
for (i=-1;i<=1;i++) {
for (j=-1;j<=1;j++) {
sumX += (int) ( (*(graydata + x + i + (y + j)
* infogray.stride)) * Gx[i+1][j+1]);
}
} // calc Y gradient
for (i=-1;i<=1;i++) {
for (j=-1;j<=1;j++) {
sumY += (int) ( (*(graydata + x + i + (y + j)
* infogray.stride)) * Gy[i+1][j+1]);
}
} sum = abs(sumX) + abs(sumY); } if (sum>255) sum = 255;
if (sum<0) sum = 0; *(edgedata + x + y*infogray.width) = 255 - (uint8_t) sum; }
} AndroidBitmap_unlockPixels(env, bitmapgray);
AndroidBitmap_unlockPixels(env, bitmapedges); }
jni 写一个简单的photoshop的更多相关文章
- 用Python写一个简单的Web框架
一.概述 二.从demo_app开始 三.WSGI中的application 四.区分URL 五.重构 1.正则匹配URL 2.DRY 3.抽象出框架 六.参考 一.概述 在Python中,WSGI( ...
- 如何写一个简单的http服务器
最近几天用C++写了一个简单的HTTP服务器,作为学习网络编程和Linux环境编程的练手项目,这篇文章记录我在写一个HTTP服务器过程中遇到的问题和学习到的知识. 服务器的源代码放在Github. H ...
- 如何写一个简单的shell
如何写一个简单的shell 看完<UNIX环境高级编程>后我就一直想写一个简单的shell来作为练习,因为有事断断续续的写了好几个月,如今写了差不多来总结一下. 源代码放在了Github: ...
- 分享:计算机图形学期末作业!!利用WebGL的第三方库three.js写一个简单的网页版“我的世界小游戏”
这几天一直在忙着期末考试,所以一直没有更新我的博客,今天刚把我的期末作业完成了,心情澎湃,所以晚上不管怎么样,我也要写一篇博客纪念一下我上课都没有听,还是通过强大的度娘完成了我的作业的经历.(当然作业 ...
- 一步一步写一个简单通用的makefile(三)
上一篇一步一步写一个简单通用的makefile(二) 里面的makefile 实现对通用的代码进行编译,这一章我将会对上一次的makefile 进行进一步的优化. 优化后的makefile: #Hel ...
- Java写一个简单学生管理系统
其实作为一名Java的程序猿,无论你是初学也好,大神也罢,学生管理系统一直都是一个非常好的例子,初学者主要是用数组.List等等来写出一个简易的学生管理系统,二.牛逼一点的大神则用数据库+swing来 ...
- (2)自己写一个简单的servle容器
自己写一个简单的servlet,能够跑一个简单的servlet,说明一下逻辑. 首先是写一个简单的servlet,这就关联到javax.servlet和javax.servlet.http这两个包的类 ...
- express 写一个简单的web app
之前写过一个简单的web app, 能够完成注册登录,展示列表,CURD 但是版本好像旧了,今天想写一个简单的API 供移动端调用 1.下载最新的node https://nodejs.org/zh- ...
- 写一个简单的C词法分析器
写一个简单的C词法分析器 在写本文过程中,我参考了<词法分析器的实现>中的一些内容.这里我们主要讨论写一个C语言的词法分析器. 一.关键字 首先,C语言中关键字有: auto.break. ...
随机推荐
- Oracle sql中的正则表达式
SELECT first_name, last_nameFROM employeesWHERE REGEXP_LIKE (first_name, '^Ste(v|ph)en$'); FIRST_NAM ...
- PHP在变量前面加&是什么意思
比如: <? php $a = 'c' ; $b = & $a ; //表示$b 和 $a 引用了同一个变量 $a = 'abc' ; //这里重置了$a echo $b ; //将输出 ...
- django给视图添加缓存功能
在开发过程中,有些视图只是查询数据,而且查询的数据一般不会变化.例如,做地址模块时,省市县都是不会变的.如果用户每次请求地址视图时,都要执行视图返回数据,会给服务端带来不必要的压力.这时候可以用到缓存 ...
- mac下安装golang
1.安装homebrew ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/in ...
- LeetCode解题报告—— Unique Binary Search Trees & Binary Tree Level Order Traversal & Binary Tree Zigzag Level Order Traversal
1. Unique Binary Search Trees Given n, how many structurally unique BST's (binary search trees) that ...
- python字符编码与解码 unicode,str
解释以下几个问题: (1)python2中str和unicode是两种字符串类型,与字符编码方式是什么关系? (2)str和unicode是怎么相互转换的? (3)'\x...':'\u...', ' ...
- “无法在web服务器上启动调试,不是Debugger User组成员..."
在使用VS.net2003开发asp.net项目时,有时候在你调试项目时,会提示”无法在web服务器上启动调试,不是Debugger User组成员..."这样一个错误信息.很是让人头疼,一 ...
- [BZOJ4824][Cqoi2017]老C的键盘 树形dp+组合数
4824: [Cqoi2017]老C的键盘 Time Limit: 10 Sec Memory Limit: 512 MBSubmit: 218 Solved: 171[Submit][Statu ...
- CentOS7.3安装electronic-wechat
方法一.简单粗暴 1.到https://github.com/geeeeeeeeek/electronic-wechat/找到最新的安装包linux-x64.tar.gz 2.解压tar -zxvf ...
- hdu多校第三场
Problem D. Euler Function 思路:打表找找规律. #include<bits/stdc++.h> #define LL long long #define fi f ...