Android NDK方向,android – 使用JNI和NDK旋转位图

背景:

我已经决定,由于位图会占用大量内存,而这些内存很容易导致内存不足错误,因此我会对C/C++代码进行大量内存消耗.

我用来旋转位图的步骤是:

>读取位图信息(宽度,高度)

>将位图像素存储到数组中.

>回收位图.

>创建一个相反大小的新位图.

>将像素放入新位图.

>释放像素并返回位图.

问题:

即使一切似乎都没有任何错误,输出图像也不是原始的旋转.事实上,它完全毁了它.

旋转应该是逆时针方向,90度.

我获得的示例(屏幕截图放大):

所以你可以看到,不仅颜色变得怪异,而且尺寸与我设定的颜色不一致.这里真的很奇怪.

也许我没有正确读取/放置数据?

当然这只是一个例子.代码应该可以在任何位图上正常工作,只要设备有足够的内存来容纳它.另外,我可能想在位图上执行其他操作而不是旋转它.

我创建的代码:

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE := JniTest

LOCAL_SRC_FILES := JniTest.cpp

LOCAL_LDLIBS := -llog

LOCAL_LDFLAGS += -ljnigraphics

include $(BUILD_SHARED_LIBRARY)

APP_OPTIM := debug

LOCAL_CFLAGS := -g

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_example_jnitest_MainActivity_rotateBitmapCcw90(JNIEnv * env, jobject obj, jobject bitmap);

}

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

{

//

//getting bitmap info:

//

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

AndroidBitmapInfo info;

int ret;

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

{

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

return NULL;

}

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

if (info.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;

uint32_t* tempPixels = new uint32_t[info.height * info.width];

int stride = info.stride;

int pixelsCount = info.height * info.width;

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

AndroidBitmap_unlockPixels(env, bitmap);

//

//recycle bitmap - using bitmap.recycle()

//

LOGD("recycling bitmap...");

jclass bitmapCls = env->GetObjectClass(bitmap);

jmethodID recycleFunction = env->GetMethodID(bitmapCls, "recycle", "()V");

if (recycleFunction == 0)

{

LOGE("error recycling!");

return NULL;

}

env->CallVoidMethod(bitmap, recycleFunction);

//

//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...");

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, info.height, info.width, bitmapConfig);

//

// putting the pixels into the new bitmap:

//

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

{

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

return NULL;

}

uint32_t* newBitmapPixels = (uint32_t*) bitmapPixels;

int whereToPut = 0;

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

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

{

uint32_t pixel = tempPixels[info.width * y + x];

newBitmapPixels[whereToPut++] = pixel;

}

AndroidBitmap_unlockPixels(env, newBitmap);

//

// freeing the native memory used to store the pixels

//

delete[] tempPixels;

return newBitmap;

}

java文件:

static

{

System.loadLibrary("JniTest");

}

/**

* rotates a bitmap by 90 degrees counter-clockwise .

* notes:

* -the input bitmap will be recycled and shouldn't be used anymore

* -returns the rotated bitmap .

* -could take some time , so do the operation in a new thread

*/

public native Bitmap rotateBitmapCcw90(Bitmap bitmap);

...

Bitmap rotatedImage=rotateBitmapCcw90(bitmapToRotate);

编辑:在得到我的答案之后,我希望与大家分享这些代码和说明:

>为了使它工作,我在代码中用“uint32_t”替换了每个“uint16_t”的实例(这就是我所询问的代码中的错误).

>输入和输出位图必须是8888配置(这是ARGB)

>输入位图将在此过程中回收.

>代码以逆时针方向旋转图像90度.当然,您可以根据需要进行更改.

更好的解决

我做了一个很好的帖子,有这个功能和其他人,here.

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值