android jni bitmap,android – 如何使用JNI位图操作来帮助避免...

注意:这是一个有点旧的代码.对于最新的,请查看github上的项目页面.

JNI / Android.mk

LOCAL_PATH := $(call my-dir)

#bitmap operations module

include $(CLEAR_VARS)

LOCAL_MODULE := JniBitmapOperations

LOCAL_SRC_FILES := JniBitmapOperations.cpp

LOCAL_LDLIBS := -llog

LOCAL_LDFLAGS += -ljnigraphics

include $(BUILD_SHARED_LIBRARY)

APP_OPTIM := debug

LOCAL_CFLAGS := -g

#if you need to add more module, do the same as the one we started with (the one with the CLEAR_VARS)

JNI / JniBitmapOperations.cpp

#include

#include

#include

#include

#include

#include

#include

#define LOG_TAG "DEBUG"

#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG,LOG_TAG,__VA_ARGS__)

#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__)

extern "C"

{

JNIEXPORT jobject JNICALL Java_com_jni_bitmap_1operations_JniBitmapHolder_jniStoreBitmapData(JNIEnv * env, jobject obj, jobject bitmap);

JNIEXPORT jobject JNICALL Java_com_jni_bitmap_1operations_JniBitmapHolder_jniGetBitmapFromStoredBitmapData(JNIEnv * env, jobject obj, jobject handle);

JNIEXPORT void JNICALL Java_com_jni_bitmap_1operations_JniBitmapHolder_jniFreeBitmapData(JNIEnv * env, jobject obj, jobject handle);

JNIEXPORT void JNICALL Java_com_jni_bitmap_1operations_JniBitmapHolder_jniRotateBitmapCcw90(JNIEnv * env, jobject obj, jobject handle);

JNIEXPORT void JNICALL Java_com_jni_bitmap_1operations_JniBitmapHolder_jniCropBitmap(JNIEnv * env, jobject obj, jobject handle, uint32_t left, uint32_t top, uint32_t right, uint32_t bottom);

}

class JniBitmap

{

public:

uint32_t* _storedBitmapPixels;

AndroidBitmapInfo _bitmapInfo;

JniBitmap()

{

_storedBitmapPixels = NULL;

}

};

/**crops the bitmap within to be smaller. note that no validations are done*/ //

JNIEXPORT void JNICALL Java_com_jni_bitmap_1operations_JniBitmapHolder_jniCropBitmap(JNIEnv * env, jobject obj, jobject handle, uint32_t left, uint32_t top, uint32_t right, uint32_t bottom)

{

JniBitmap* jniBitmap = (JniBitmap*) env->GetDirectBufferAddress(handle);

if (jniBitmap->_storedBitmapPixels == NULL)

return;

uint32_t* previousData = jniBitmap->_storedBitmapPixels;

uint32_t oldWidth = jniBitmap->_bitmapInfo.width;

uint32_t newWidth = right - left, newHeight = bottom - top;

uint32_t* newBitmapPixels = new uint32_t[newWidth * newHeight];

uint32_t* whereToGet = previousData + left + top * oldWidth;

uint32_t* whereToPut = newBitmapPixels;

for (int y = top; y < bottom; ++y)

{

memcpy(whereToPut, whereToGet, sizeof(uint32_t) * newWidth);

whereToGet += oldWidth;

whereToPut += newWidth;

}

//done copying , so replace old data with new one

delete[] previousData;

jniBitmap->_storedBitmapPixels = newBitmapPixels;

jniBitmap->_bitmapInfo.width = newWidth;

jniBitmap->_bitmapInfo.height = newHeight;

}

/**rotates the inner bitmap data by 90 degress counter clock wise*/ //

JNIEXPORT void JNICALL Java_com_jni_bitmap_1operations_JniBitmapHolder_jniRotateBitmapCcw90(JNIEnv * env, jobject obj, jobject handle)

{

JniBitmap* jniBitmap = (JniBitmap*) env->GetDirectBufferAddress(handle);

if (jniBitmap->_storedBitmapPixels == NULL)

return;

uint32_t* previousData = jniBitmap->_storedBitmapPixels;

AndroidBitmapInfo bitmapInfo = jniBitmap->_bitmapInfo;

uint32_t* newBitmapPixels = new uint32_t[bitmapInfo.height * bitmapInfo.width];

int whereToPut = 0;

// A.D D.C

// ...>...

// B.C A.B

for (int x = bitmapInfo.width - 1; x >= 0; --x)

for (int y = 0; y < bitmapInfo.height; ++y)

{

uint32_t pixel = previousData[bitmapInfo.width * y + x];

newBitmapPixels[whereToPut++] = pixel;

}

delete[] previousData;

jniBitmap->_storedBitmapPixels = newBitmapPixels;

uint32_t temp = bitmapInfo.width;

bitmapInfo.width = bitmapInfo.height;

bitmapInfo.height = temp;

}

/**free bitmap*/ //

JNIEXPORT void JNICALL Java_com_jni_bitmap_1operations_JniBitmapHolder_jniFreeBitmapData(JNIEnv * env, jobject obj, jobject handle)

{

JniBitmap* jniBitmap = (JniBitmap*) env->GetDirectBufferAddress(handle);

if (jniBitmap->_storedBitmapPixels == NULL)

return;

delete[] jniBitmap->_storedBitmapPixels;

jniBitmap->_storedBitmapPixels = NULL;

delete jniBitmap;

}

/**restore java bitmap (from JNI data)*/ //

JNIEXPORT jobject JNICALL Java_com_jni_bitmap_1operations_JniBitmapHolder_jniGetBitmapFromStoredBitmapData(JNIEnv * env, jobject obj, jobject handle)

{

JniBitmap* jniBitmap = (JniBitmap*) env->GetDirectBufferAddress(handle);

if (jniBitmap->_storedBitmapPixels == NULL)

{

LOGD("no bitmap data was stored. returning null...");

return NULL;

}

//

//creating a new bitmap to put the pixels into it - using Bitmap Bitmap.createBitmap (int width, int height, Bitmap.Config config) :

//

//LOGD("creating new bitmap...");

jclass bitmapCls = env->FindClass("android/graphics/Bitmap");

jmethodID createBitmapFunction = env->GetStaticMethodID(bitmapCls, "createBitmap", "(IILandroid/graphics/Bitmap$Config;)Landroid/graphics/Bitmap;");

jstring configName = env->NewStringUTF("ARGB_8888");

jclass bitmapConfigClass = env->FindClass("android/graphics/Bitmap$Config");

jmethodID valueOfBitmapConfigFunction = env->GetStaticMethodID(bitmapConfigClass, "valueOf", "(Ljava/lang/String;)Landroid/graphics/Bitmap$Config;");

jobject bitmapConfig = env->CallStaticObjectMethod(bitmapConfigClass, valueOfBitmapConfigFunction, configName);

jobject newBitmap = env->CallStaticObjectMethod(bitmapCls, createBitmapFunction, jniBitmap->_bitmapInfo.width, jniBitmap->_bitmapInfo.height, bitmapConfig);

//

// putting the pixels into the new bitmap:

//

int ret;

void* bitmapPixels;

if ((ret = AndroidBitmap_lockPixels(env, newBitmap, &bitmapPixels)) < 0)

{

LOGE("AndroidBitmap_lockPixels() failed ! error=%d", ret);

return NULL;

}

uint32_t* newBitmapPixels = (uint32_t*) bitmapPixels;

int pixelsCount = jniBitmap->_bitmapInfo.height * jniBitmap->_bitmapInfo.width;

memcpy(newBitmapPixels, jniBitmap->_storedBitmapPixels, sizeof(uint32_t) * pixelsCount);

AndroidBitmap_unlockPixels(env, newBitmap);

//LOGD("returning the new bitmap");

return newBitmap;

}

/**store java bitmap as JNI data*/ //

JNIEXPORT jobject JNICALL Java_com_jni_bitmap_1operations_JniBitmapHolder_jniStoreBitmapData(JNIEnv * env, jobject obj, jobject bitmap)

{

AndroidBitmapInfo bitmapInfo;

uint32_t* storedBitmapPixels = NULL;

//LOGD("reading bitmap info...");

int ret;

if ((ret = AndroidBitmap_getInfo(env, bitmap, &bitmapInfo)) < 0)

{

LOGE("AndroidBitmap_getInfo() failed ! error=%d", ret);

return NULL;

}

LOGD("width:%d height:%d stride:%d", bitmapInfo.width, bitmapInfo.height, bitmapInfo.stride);

if (bitmapInfo.format != ANDROID_BITMAP_FORMAT_RGBA_8888)

{

LOGE("Bitmap format is not RGBA_8888!");

return NULL;

}

//

//read pixels of bitmap into native memory :

//

//LOGD("reading bitmap pixels...");

void* bitmapPixels;

if ((ret = AndroidBitmap_lockPixels(env, bitmap, &bitmapPixels)) < 0)

{

LOGE("AndroidBitmap_lockPixels() failed ! error=%d", ret);

return NULL;

}

uint32_t* src = (uint32_t*) bitmapPixels;

storedBitmapPixels = new uint32_t[bitmapInfo.height * bitmapInfo.width];

int pixelsCount = bitmapInfo.height * bitmapInfo.width;

memcpy(storedBitmapPixels, src, sizeof(uint32_t) * pixelsCount);

AndroidBitmap_unlockPixels(env, bitmap);

JniBitmap *jniBitmap = new JniBitmap();

jniBitmap->_bitmapInfo = bitmapInfo;

jniBitmap->_storedBitmapPixels = storedBitmapPixels;

return env->NewDirectByteBuffer(jniBitmap, 0);

}

SRC/C++OM / JNI / bitmap_operations / JniBitmapHolder.java

package com.jni.bitmap_operations;

import java.nio.ByteBuffer;

import android.graphics.Bitmap;

import android.util.Log;

public class JniBitmapHolder

{

ByteBuffer _handler =null;

static

{

System.loadLibrary("JniBitmapOperations");

}

private native ByteBuffer jniStoreBitmapData(Bitmap bitmap);

private native Bitmap jniGetBitmapFromStoredBitmapData(ByteBuffer handler);

private native void jniFreeBitmapData(ByteBuffer handler);

private native void jniRotateBitmapCcw90(ByteBuffer handler);

private native void jniCropBitmap(ByteBuffer handler,final int left,final int top,final int right,final int bottom);

public JniBitmapHolder()

{}

public JniBitmapHolder(final Bitmap bitmap)

{

storeBitmap(bitmap);

}

public void storeBitmap(final Bitmap bitmap)

{

if(_handler!=null)

freeBitmap();

_handler=jniStoreBitmapData(bitmap);

}

public void rotateBitmapCcw90()

{

if(_handler==null)

return;

jniRotateBitmapCcw90(_handler);

}

public void cropBitmap(final int left,final int top,final int right,final int bottom)

{

if(_handler==null)

return;

jniCropBitmap(_handler,left,top,right,bottom);

}

public Bitmap getBitmap()

{

if(_handler==null)

return null;

return jniGetBitmapFromStoredBitmapData(_handler);

}

public Bitmap getBitmapAndFree()

{

final Bitmap bitmap=getBitmap();

freeBitmap();

return bitmap;

}

public void freeBitmap()

{

if(_handler==null)

return;

jniFreeBitmapData(_handler);

_handler=null;

}

@Override

protected void finalize() throws Throwable

{

super.finalize();

if(_handler==null)

return;

Log.w("DEBUG","JNI bitmap wasn't freed nicely.please rememeber to free the bitmap as soon as you can");

freeBitmap();

}

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值