旋转图像按所传递的方向,使用原生code的功能 [英] Rotate the image as per the passed orientation to the functions using Native Code

查看:244
本文介绍了旋转图像按所传递的方向,使用原生code的功能的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想图像按传递方向的功能在我rotateBitmap()funcation旋转。

我从的真棒库。

我想要做的是:

我要的影像按旋转传递函数的方向之后,我想
 应用灰度缩放效果的图像,然后,如果想要downnsample图像和图像的缩略图返回到调用活动

下面下面我粘贴在我的家乡code ..

是我迄今为止尝试过的:

 的#include< jni.h>
#包括LT&;机器人/ log.h>
#包括LT&;机器人/ bitmap.h>
#包括LT&;&stdio.h中GT;
#包括LT&; CString的GT;
#包括LT&;&unistd.h中GT;#定义LOG_TAGlibphotophun
#定义LOGI(...)__android_log_print(ANDROID_LOG_INFO,LOG_TAG,__ VA_ARGS__)
#定义LOGE(...)__android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__ VA_ARGS__)
#定义LOGD(...)__android_log_print(ANDROID_LOG_DEBUG,LOG_TAG,__ VA_ARGS__)
typedef结构
{
    uint8_t有字母;
    uint8_t有红色;
    uint8_t有绿色;
    uint8_t有蓝色;
} ARGB;类JniBitmap
{
上市:
    uint32_t的* _storedBitmapPixels;
    AndroidBitmapInfo _bitmapInfo;
    JniBitmap()
    {
        _storedBitmapPixels = NULL;
    }
};为externC
{
        //商店
        JNIEXPORT jobject JNICALL Java_com_example_ndksampleproject_MainActivity_jniStoreBitmapData(
                JNIEnv的* ENV,jobject OBJ,jobject位);
        //得到
        JNIEXPORT jobject JNICALL Java_com_example_ndksampleproject_MainActivity_jniG​​etBitmapFromStoredBitmapData(
                JNIEnv的* ENV,jobject OBJ,jobject手柄);
        //自由
        JNIEXPORT无效JNICALL Java_com_example_ndksampleproject_MainActivity_jniFreeBitmapData(
                JNIEnv的* ENV,jobject OBJ,jobject手柄);        JNIEXPORT jobject JNICALL Java_com_example_ndksampleproject_MainActivity_rotateBitmap(
                JNIEnv的* ENV,jobject OBJ,jobject位,INT旋转);}/ **无位* / //
JNIEXPORT无效JNICALL Java_com_example_ndksampleproject_MainActivity_jniFreeBitmapData(
        JNIEnv的* ENV,jobject OBJ,jobject手柄)
{
    JniBitmap * jniBitmap =(JniBitmap *)env-> GetDirectBufferAddress(句柄);
    如果(jniBitmap-> _storedBitmapPixels == NULL)
        返回;
    删除[] jniBitmap-> _storedBitmapPixels;
    jniBitmap-> _storedBitmapPixels = NULL;
    删除jniBitmap;
}/ **恢复java的位图(从JNI数据)* / //
JNIEXPORT jobject JNICALL Java_com_example_ndksampleproject_MainActivity_jniG​​etBitmapFromStoredBitmapData(
        JNIEnv的* ENV,jobject OBJ,jobject手柄)
{
    JniBitmap * jniBitmap =(JniBitmap *)env-> GetDirectBufferAddress(句柄);
    如果(jniBitmap-> _storedBitmapPixels == NULL)
    {
        LOGD(无位图数据储存返回null ......。);
        返回NULL;
    }
    //
    //创建一个新位图把像素进去 - 使用位图Bitmap.createBitmap(INT宽度,高度INT,Bitmap.Config配置):
    //
    JCLASS bitmapCls = env->的findClass(机器人/图形/位图);
    jmethodID createBitmapFunction = env-> GetStaticMethodID(bitmapCls,
            createBitmap
            (IILandroid /图形/位图$配置;)Landroid /图形/位图;);
    CONFIGNAME的jstring = env-> NewStringUTF(ARGB_8888);
    JCLASS bitmapConfigClass = env->的findClass(机器人/图形/位图$配置);
    jmethodID valueOfBitmapConfigFunction = env-> GetStaticMethodID(
            bitmapConfigClass的valueOf
            (Ljava /朗/字符串;)Landroid /图形/位图$配置;);
    jobject bitmapConfig = env-> CallStaticObjectMethod(bitmapConfigClass,
            valueOfBitmapConfigFunction,配置名称);
    jobject newBitmap = env-> CallStaticObjectMethod(bitmapCls,
            createBitmapFunction,jniBitmap-> _bitmapInfo.width,
            jniBitmap-> _bitmapInfo.height,bitmapConfig);
    //
    //把像素到新位图:
    //
    INT RET;
    无效* bitmapPixels;
    如果((RET = AndroidBitmap_lockPixels(ENV,newBitmap,&安培; bitmapPixels))小于0)
    {
        LOGE(AndroidBitmap_lockPixels()失败,错误=%d个!,RET);
        返回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(返回新的位图);
    返回newBitmap;
}/ **存储Java位图作为JNI数据* / //
JNIEXPORT jobject JNICALL Java_com_example_ndksampleproject_MainActivity_jniStoreBitmapData(
        JNIEnv的* ENV,jobject OBJ,jobject位图)
{
    AndroidBitmapInfo BITMAPINFO;
    uint32_t的* storedBitmapPixels = NULL;
    // LOGD(读书位图信息...);
    INT RET;
    如果((保留= AndroidBitmap_getInfo(ENV,位图&放大器; BITMAPINFO))小于0)
    {
        LOGE(AndroidBitmap_getInfo()失败,错误=%d个!,RET);
        返回NULL;
    }
    // LOGD(宽:%d个身高:%d个步幅数:%d,bitmapInfo.width,bitmapInfo.height,bitmapInfo.stride);
    如果(bitmapInfo.format!= ANDROID_BITMAP_FORMAT_RGBA_8888)
    {
        LOGE(位图格式不RGBA_8888!);
        返回NULL;
    }
    //
    //读取位图到本机内存像素:
    //
    // LOGD(读书位图像素...);
    无效* bitmapPixels;
    如果((保留= AndroidBitmap_lockPixels(ENV,位图&放大器; bitmapPixels))小于0)
    {
        LOGE(AndroidBitmap_lockPixels()失败,错误=%d个!,RET);
        返回NULL;
    }
    uint32_t的* SRC =(uint32_t的*)bitmapPixels;
    storedBitmapPixels =新uint32_t的[bitmapInfo.height * bitmapInfo.width]。
    INT pixelsCount = bitmapInfo.height * bitmapInfo.width;
    的memcpy(storedBitmapPixels,SRC,sizeof的(uint32_t的)* pixelsCount);
    AndroidBitmap_unlockPixels(ENV,位图);
    JniBitmap * jniBitmap =新JniBitmap();
    jniBitmap-> _bitmapInfo = BITMAPINFO;
    jniBitmap-> _storedBitmapPixels = storedBitmapPixels;
    返回env-> NewDirectByteBuffer(jniBitmap,0);
}
JNIEXPORT jobject JNICALL Java_com_example_ndksampleproject_MainActivity_rotateBitmap(JNIEnv的* ENV,jobject OBJ,jobject位,INT旋转,jobject手柄)
{
    JniBitmap * jniBitmap = jniBitmap =(JniBitmap *)env-> GetDirectBufferAddress(句柄);
    如果(旋转== 90)
    {
        // jniBitmap =(JniBitmap *)env-> GetDirectBufferAddress(句柄);
        如果(jniBitmap-> _storedBitmapPixels == NULL)
            返回;
        uint32_t的* previousData = jniBitmap-> _storedBitmapPixels;
        uint32_t的newWidth = jniBitmap-> _bitmapInfo.height;
        uint32_t的newHeight = jniBitmap-> _bitmapInfo.width;
        jniBitmap-> _bitmapInfo.width = newWidth;
        jniBitmap-> _bitmapInfo.height = newHeight;
        uint32_t的* newBitmapPixels =新uint32_t的[newWidth * newHeight]。
        INT whereToGet = 0;
        // XY。 ... ... ..X
        // ...> Y ..> ...> ..ÿ
        // ... X .. .YX ...
        为(中间体X = 0; X&下; newWidth ++ x)的
            为(中间体Y = newHeight - 1 y与其所连接; = 0; --y)
            {
                //取从各行(最多底部),从左至右
                uint32_t的像素= previousData [whereToGet ++];
                newBitmapPixels [newWidth * Y + X] =像素;
            }
        //删除[] previousData;
        jniBitmap-> _storedBitmapPixels = newBitmapPixels;
    }
    否则,如果(旋转== 180)
    {
        // jniBitmap =(JniBitmap *)env-> GetDirectBufferAddress(句柄);
        如果(jniBitmap-> _storedBitmapPixels == NULL)
            返回;
        uint32_t的* previousData = jniBitmap-> _storedBitmapPixels;
        uint32_t的宽度= jniBitmap-> _bitmapInfo.width;
        uint32_t的高度= jniBitmap-> _bitmapInfo.height;
        uint32_t的* newBitmapPixels =新uint32_t的[宽*高]。
        INT whereToGet = 0;
        // XY。 ...
        // ...> ...
        // ... .YX
        jniBitmap-> _storedBitmapPixels = newBitmapPixels;
        对于(INT Y =高 - 1; Y> = 0; --Y)
            对于(INT X =宽度 - 1; X> = 0; --x)
            {
                //取从各行(最多底部),从左至右
                uint32_t的像素= previousData [whereToGet ++];
                newBitmapPixels [宽* Y + X] =像素;
            }
        //删除[] previousData;
        jniBitmap-> _storedBitmapPixels = newBitmapPixels;
    }    否则,如果(旋转== 270)
    {
        // jniBitmap =(JniBitmap *)env-> GetDirectBufferAddress(句柄);
        如果(jniBitmap-> _storedBitmapPixels == NULL)
            返回;
        uint32_t的* previousData = jniBitmap-> _storedBitmapPixels;
        uint32_t的newWidth = jniBitmap-> _bitmapInfo.height;
        uint32_t的newHeight = jniBitmap-> _bitmapInfo.width;
        jniBitmap-> _bitmapInfo.width = newWidth;
        jniBitmap-> _bitmapInfo.height = newHeight;
        uint32_t的* newBitmapPixels =新uint32_t的[newWidth * newHeight]。
        INT whereToGet = 0;
        // XY。 ..X ... ...
        // ...> .. Y'GT; ...> Y ..
        // ...... .YX X ..
        jniBitmap-> _storedBitmapPixels = newBitmapPixels;
        为(中间体X = newWidth - 1; X> = 0; --x)
            对于(INT Y = 0; Y< newHeight ++ Y)
            {
                //取从各行(最多底部),从左至右
                uint32_t的像素= previousData [whereToGet ++];
                newBitmapPixels [newWidth * Y + X] =像素;
            }
        //删除[] previousData;
        jniBitmap-> _storedBitmapPixels = newBitmapPixels;
    }
    返回jniBitmap;
}

登录猫::

  ++编译大拇指:photophun< = photophun.cpp
/Workspace/NDKSampleProject/jni/photophun.cpp:2:0文件由D包括:
D:/android-ndk-r8b/platforms/android-14/arch-arm/usr/include/jni.h:592:13:一张字条:va_list的的是混淆在GCC 4.4已经改变
D:/Workspace/NDKSampleProject/jni/photophun.cpp:在函数'_jobject * Java_com_example_ndksampleproject_MainActivity_rotateBitmap(JNIEnv的*,jobject,jobject,INT,jobject):
D:/Workspace/NDKSampleProject/jni/photophun.cpp:154:4:错误:返回语句没有任何价值,在函数返回jobject {又名_jobject *}'[-fpermissive]
D:/Workspace/NDKSampleProject/jni/photophun.cpp:179:4:错误:返回语句没有任何价值,在函数返回jobject {又名_jobject *}'[-fpermissive]
D:/Workspace/NDKSampleProject/jni/photophun.cpp:204:4:错误:返回语句没有任何价值,在函数返回jobject {又名_jobject *}'[-fpermissive]
D:/Workspace/NDKSampleProject/jni/photophun.cpp:226:9:错误:无法转换'JniBitmap *'到'jobject {又名_jobject *}'回报
/cygdrive/d/android-ndk-r8b/build/core/build-binary.mk:255:配方目标`/cygdrive/d/Workspace/NDKSampleProject/obj/local/armeabi/objs/photophun/photophun.o失败
使:*** [/cygdrive/d/Workspace/NDKSampleProject/obj/local/armeabi/objs/photophun/photophun.o]错误1

请让我知道如果你需要从我身边任何东西。
请帮助我,我十分需要完成这件事情来解决OOM问题。
提前许多感谢....

编辑:

 的externC
{        JNIEXPORT无效JNICALL com_example_ndksampleproject_MainActivity_rotateBitmap(
                JNIEnv的* ENV,jobject OBJ,jobject位,INT旋转);}
    JNIEXPORT无效JNICALL com_example_ndksampleproject_MainActivity_rotateBitmap(JNIEnv的* ENV,jobject OBJ,jobject位图,uint32_t的旋转,jobject手柄)
    {
        JniBitmap * jniBitmap = jniBitmap =(JniBitmap *)env-> GetDirectBufferAddress(句柄);
        如果(旋转== 90)
        {
            jniBitmap =(JniBitmap *)env-> GetDirectBufferAddress(句柄);            如果(jniBitmap-> _storedBitmapPixels == NULL)
                返回;
            uint32_t的* previousData = jniBitmap-> _storedBitmapPixels;
            uint32_t的newWidth = jniBitmap-> _bitmapInfo.height;
            uint32_t的newHeight = jniBitmap-> _bitmapInfo.width;
            jniBitmap-> _bitmapInfo.width = newWidth;
            jniBitmap-> _bitmapInfo.height = newHeight;
            uint32_t的* newBitmapPixels =新uint32_t的[newWidth * newHeight]。
            INT whereToGet = 0;
            // XY。 ... ... ..X
            // ...> Y ..> ...> ..ÿ
            // ... X .. .YX ...
            为(中间体X = 0; X&下; newWidth ++ x)的
                为(中间体Y = newHeight - 1 y与其所连接; = 0; --y)
                {
                    //取从各行(最多底部),从左至右
                    uint32_t的像素= previousData [whereToGet ++];
                    newBitmapPixels [newWidth * Y + X] =像素;
                }
            删除[] previousData;
            // jniBitmap-> _storedBitmapPixels = newBitmapPixels;
        }
        否则,如果(旋转== 180)
        {
            jniBitmap =(JniBitmap *)env-> GetDirectBufferAddress(句柄);
            如果(jniBitmap-> _storedBitmapPixels == NULL)
                返回;
            uint32_t的* previousData = jniBitmap-> _storedBitmapPixels;
            uint32_t的宽度= jniBitmap-> _bitmapInfo.width;
            uint32_t的高度= jniBitmap-> _bitmapInfo.height;
            uint32_t的* newBitmapPixels =新uint32_t的[宽*高]。
            INT whereToGet = 0;
            // XY。 ...
            // ...> ...
            // ... .YX
            jniBitmap-> _storedBitmapPixels = newBitmapPixels;
            对于(INT Y =高 - 1; Y> = 0; --Y)
                对于(INT X =宽度 - 1; X> = 0; --x)
                {
                    //取从各行(最多底部),从左至右
                    uint32_t的像素= previousData [whereToGet ++];
                    newBitmapPixels [宽* Y + X] =像素;
                }
            删除[] previousData;
            // jniBitmap-> _storedBitmapPixels = newBitmapPixels;
        }        否则,如果(旋转== 270)
        {
            jniBitmap =(JniBitmap *)env-> GetDirectBufferAddress(句柄);
            如果(jniBitmap-> _storedBitmapPixels == NULL)
                返回;
            uint32_t的* previousData = jniBitmap-> _storedBitmapPixels;
            uint32_t的newWidth = jniBitmap-> _bitmapInfo.height;
            uint32_t的newHeight = jniBitmap-> _bitmapInfo.width;
            jniBitmap-> _bitmapInfo.width = newWidth;
            jniBitmap-> _bitmapInfo.height = newHeight;
            uint32_t的* newBitmapPixels =新uint32_t的[newWidth * newHeight]。
            INT whereToGet = 0;
            // XY。 ..X ... ...
            // ...> .. Y'GT; ...> Y ..
            // ...... .YX X ..
            jniBitmap-> _storedBitmapPixels = newBitmapPixels;
            为(中间体X = newWidth - 1; X> = 0; --x)
                对于(INT Y = 0; Y< newHeight ++ Y)
                {
                    //取从各行(最多底部),从左至右
                    uint32_t的像素= previousData [whereToGet ++];
                    newBitmapPixels [newWidth * Y + X] =像素;
                }
            删除[] previousData;
            // jniBitmap-> _storedBitmapPixels = newBitmapPixels;
        }
        //返回jniBitmap;
    }

我所谓的本地方法这种方式:

  BitmapFactory.Options选项=新BitmapFactory.Options();
    位图tempBmp = NULL;
    ByteBuffer的_handler = NULL;
    @覆盖
    公共布尔onOptionsItemSelected(菜单项项){        开关(item.getItemId())
        {
        案例R.id.item_rotate_90:
            options.in preferredConfig = Config.ARGB_8888;
            bitmapOrig = BitmapFactory.de codeResource(this.getResources(),R.drawable.sampleimage,期权);
            rotateBitmap(bitmapOrig,90,_handler);
            tempBmp = getBitmapAndFree();
            如果(tempBmp!= NULL)
            {
                ivDisplay.setImageBitmap(tempBmp);
            }
            打破;

LogCat中::

 致命异常:主要
java.lang.UnsatisfiedLinkError中:本机方法未找到: com.example.ndksampleproject.MainActivity.rotateBitmap:(Landroid/graphics/Bitmap;ILjava/nio/ByteBuffer;)V
在com.example.ndksampleproject.MainActivity.rotateBitmap(本机方法)
在com.example.ndksampleproject.MainActivity.onOptionsItemSelected(MainActivity.java:113)
在android.app.Activity.onMenuItemSelected(Activity.java:2612)
在com.android.internal.policy.impl.PhoneWindow.onMenuItemSelected(PhoneWindow.java:1061)
在com.android.internal.view.menu.MenuBuilder.dispatchMenuItemSelected(MenuBuilder.java:735)


解决方案

在code我做已经支持旋转。只要看看示例项目,以了解如何调用它。

此外,灰阶不应该实施的C ++ code我做了一个太难操作。我敢肯定有这样的例子在互联网上。

关于下采样,我没有做它,因为它是一个大量的工作,但我补充说,已经去codeD(这意味着它们被存储为位图对象)的图像缩放。
但是,你可以随时使用低档次的 普通谷歌的方式 ,或 我的方式 (底部code)。

i want to rotate the image as per passing the orientation to the function in my rotateBitmap() funcation.

i have taken the reference about this method from this awesome library.

What i want to do is ::

I want to rotate the image as per the passing the orientation in function after that i want to apply the gray scaling effect to the image and then if want to downnsample the image and return the thumbnail of the image to the calling activity.

Here below i have pasted the my native code ..

What i have tried so far is ::

#include <jni.h>
#include <android/log.h>
#include <android/bitmap.h>
#include <stdio.h>
#include <cstring>
#include <unistd.h>

#define  LOG_TAG    "libphotophun"
#define  LOGI(...)  __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__)
#define  LOGE(...)  __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__)
#define  LOGD(...)  __android_log_print(ANDROID_LOG_DEBUG,LOG_TAG,__VA_ARGS__)
typedef struct 
{
    uint8_t alpha;
    uint8_t red;
    uint8_t green;
    uint8_t blue;
} argb;

class JniBitmap
{
public:
    uint32_t* _storedBitmapPixels;
    AndroidBitmapInfo _bitmapInfo;
    JniBitmap()
    {
        _storedBitmapPixels = NULL;
    }
};

extern "C"
{
        //store
        JNIEXPORT jobject JNICALL Java_com_example_ndksampleproject_MainActivity_jniStoreBitmapData(
                JNIEnv * env, jobject obj, jobject bitmap);
        //get
        JNIEXPORT jobject JNICALL Java_com_example_ndksampleproject_MainActivity_jniGetBitmapFromStoredBitmapData(
                JNIEnv * env, jobject obj, jobject handle);
        //free
        JNIEXPORT void JNICALL Java_com_example_ndksampleproject_MainActivity_jniFreeBitmapData(
                JNIEnv * env, jobject obj, jobject handle);

        JNIEXPORT jobject JNICALL Java_com_example_ndksampleproject_MainActivity_rotateBitmap(
                JNIEnv * env, jobject obj, jobject bitmap,int rotation);

}

/**free bitmap*/  //
JNIEXPORT void JNICALL Java_com_example_ndksampleproject_MainActivity_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_example_ndksampleproject_MainActivity_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) :
    //
    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_example_ndksampleproject_MainActivity_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);
}
JNIEXPORT jobject JNICALL Java_com_example_ndksampleproject_MainActivity_rotateBitmap(JNIEnv * env, jobject obj, jobject bitmap,int rotation,jobject handle)
{
    JniBitmap* jniBitmap =jniBitmap = (JniBitmap*) env->GetDirectBufferAddress(handle);
    if(rotation==90)
    {
        //jniBitmap = (JniBitmap*) env->GetDirectBufferAddress(handle);
        if (jniBitmap->_storedBitmapPixels == NULL)
            return;
        uint32_t* previousData = jniBitmap->_storedBitmapPixels;
        uint32_t newWidth = jniBitmap->_bitmapInfo.height;
        uint32_t newHeight = jniBitmap->_bitmapInfo.width;
        jniBitmap->_bitmapInfo.width = newWidth;
        jniBitmap->_bitmapInfo.height = newHeight;
        uint32_t* newBitmapPixels = new uint32_t[newWidth * newHeight];
        int whereToGet = 0;
        // XY. ... ... ..X
        // ...>Y..>...>..Y
        // ... X.. .YX ...
        for (int x = 0; x < newWidth; ++x)
            for (int y = newHeight - 1; y >= 0; --y)
            {
                //take from each row (up to bottom), from left to right
                uint32_t pixel = previousData[whereToGet++];
                newBitmapPixels[newWidth * y + x] = pixel;
            }
        //delete[] previousData;
        jniBitmap->_storedBitmapPixels = newBitmapPixels;
    }
    else if(rotation==180)
    {
        //jniBitmap = (JniBitmap*) env->GetDirectBufferAddress(handle);
        if (jniBitmap->_storedBitmapPixels == NULL)
            return;
        uint32_t* previousData = jniBitmap->_storedBitmapPixels;
        uint32_t width = jniBitmap->_bitmapInfo.width;
        uint32_t height = jniBitmap->_bitmapInfo.height;
        uint32_t* newBitmapPixels = new uint32_t[width * height];
        int whereToGet = 0;
        // XY. ...
        // ...>...
        // ... .YX
        jniBitmap->_storedBitmapPixels = newBitmapPixels;
        for (int y = height - 1; y >= 0; --y)
            for (int x = width - 1; x >= 0; --x)
            {
                //take from each row (up to bottom), from left to right
                uint32_t pixel = previousData[whereToGet++];
                newBitmapPixels[width * y + x] = pixel;
            }
        //delete[] previousData;
        jniBitmap->_storedBitmapPixels = newBitmapPixels;
    }

    else if(rotation==270)
    {
        //jniBitmap = (JniBitmap*) env->GetDirectBufferAddress(handle);
        if (jniBitmap->_storedBitmapPixels == NULL)
            return;
        uint32_t* previousData = jniBitmap->_storedBitmapPixels;
        uint32_t newWidth = jniBitmap->_bitmapInfo.height;
        uint32_t newHeight = jniBitmap->_bitmapInfo.width;
        jniBitmap->_bitmapInfo.width = newWidth;
        jniBitmap->_bitmapInfo.height = newHeight;
        uint32_t* newBitmapPixels = new uint32_t[newWidth * newHeight];
        int whereToGet = 0;
        // XY. ..X ... ...
        // ...>..Y>...>Y..
        // ... ... .YX X..
        jniBitmap->_storedBitmapPixels = newBitmapPixels;
        for (int x = newWidth - 1; x >= 0; --x)
            for (int y = 0; y < newHeight; ++y)
            {
                //take from each row (up to bottom), from left to right
                uint32_t pixel = previousData[whereToGet++];
                newBitmapPixels[newWidth * y + x] = pixel;
            }
        //delete[] previousData;
        jniBitmap->_storedBitmapPixels = newBitmapPixels;
    }
    return jniBitmap;
}

Log cat ::

Compile++ thumb  : photophun <= photophun.cpp
In file included from D:/Workspace/NDKSampleProject/jni/photophun.cpp:2:0:
D:/android-ndk-r8b/platforms/android-14/arch-arm/usr/include/jni.h:592:13: note: the mangling of 'va_list' has changed in GCC 4.4
D:/Workspace/NDKSampleProject/jni/photophun.cpp: In function '_jobject* Java_com_example_ndksampleproject_MainActivity_rotateBitmap(JNIEnv*, jobject, jobject, int, jobject)':
D:/Workspace/NDKSampleProject/jni/photophun.cpp:154:4: error: return-statement with no value, in function returning 'jobject {aka _jobject*}' [-fpermissive]
D:/Workspace/NDKSampleProject/jni/photophun.cpp:179:4: error: return-statement with no value, in function returning 'jobject {aka _jobject*}' [-fpermissive]
D:/Workspace/NDKSampleProject/jni/photophun.cpp:204:4: error: return-statement with no value, in function returning 'jobject {aka _jobject*}' [-fpermissive]
D:/Workspace/NDKSampleProject/jni/photophun.cpp:226:9: error: cannot convert 'JniBitmap*' to 'jobject {aka _jobject*}' in return
/cygdrive/d/android-ndk-r8b/build/core/build-binary.mk:255: recipe for target `/cygdrive/d/Workspace/NDKSampleProject/obj/local/armeabi/objs/photophun/photophun.o' failed
make: *** [/cygdrive/d/Workspace/NDKSampleProject/obj/local/armeabi/objs/photophun/photophun.o] Error 1

Please let me know if you need anything from my side. Please help me as i am in great need to complete this thing to resolve the OOM issue. Many thanks in advance....

EDIT ::

extern "C"
{

        JNIEXPORT void JNICALL com_example_ndksampleproject_MainActivity_rotateBitmap(
                JNIEnv * env, jobject obj, jobject bitmap,int rotation);

}


    JNIEXPORT void JNICALL com_example_ndksampleproject_MainActivity_rotateBitmap(JNIEnv * env, jobject obj, jobject bitmap,uint32_t rotation,jobject handle)
    {
        JniBitmap* jniBitmap =jniBitmap = (JniBitmap*) env->GetDirectBufferAddress(handle);
        if(rotation==90)
        {
            jniBitmap = (JniBitmap*) env->GetDirectBufferAddress(handle);

            if (jniBitmap->_storedBitmapPixels == NULL)
                return;
            uint32_t* previousData = jniBitmap->_storedBitmapPixels;
            uint32_t newWidth = jniBitmap->_bitmapInfo.height;
            uint32_t newHeight = jniBitmap->_bitmapInfo.width;
            jniBitmap->_bitmapInfo.width = newWidth;
            jniBitmap->_bitmapInfo.height = newHeight;
            uint32_t* newBitmapPixels = new uint32_t[newWidth * newHeight];
            int whereToGet = 0;
            // XY. ... ... ..X
            // ...>Y..>...>..Y
            // ... X.. .YX ...
            for (int x = 0; x < newWidth; ++x)
                for (int y = newHeight - 1; y >= 0; --y)
                {
                    //take from each row (up to bottom), from left to right
                    uint32_t pixel = previousData[whereToGet++];
                    newBitmapPixels[newWidth * y + x] = pixel;
                }
            delete[] previousData;
            //jniBitmap->_storedBitmapPixels = newBitmapPixels;
        }
        else if(rotation==180)
        {
            jniBitmap = (JniBitmap*) env->GetDirectBufferAddress(handle);
            if (jniBitmap->_storedBitmapPixels == NULL)
                return;
            uint32_t* previousData = jniBitmap->_storedBitmapPixels;
            uint32_t width = jniBitmap->_bitmapInfo.width;
            uint32_t height = jniBitmap->_bitmapInfo.height;
            uint32_t* newBitmapPixels = new uint32_t[width * height];
            int whereToGet = 0;
            // XY. ...
            // ...>...
            // ... .YX
            jniBitmap->_storedBitmapPixels = newBitmapPixels;
            for (int y = height - 1; y >= 0; --y)
                for (int x = width - 1; x >= 0; --x)
                {
                    //take from each row (up to bottom), from left to right
                    uint32_t pixel = previousData[whereToGet++];
                    newBitmapPixels[width * y + x] = pixel;
                }
            delete[] previousData;
            //jniBitmap->_storedBitmapPixels = newBitmapPixels;
        }

        else if(rotation==270)
        {
            jniBitmap = (JniBitmap*) env->GetDirectBufferAddress(handle);
            if (jniBitmap->_storedBitmapPixels == NULL)
                return;
            uint32_t* previousData = jniBitmap->_storedBitmapPixels;
            uint32_t newWidth = jniBitmap->_bitmapInfo.height;
            uint32_t newHeight = jniBitmap->_bitmapInfo.width;
            jniBitmap->_bitmapInfo.width = newWidth;
            jniBitmap->_bitmapInfo.height = newHeight;
            uint32_t* newBitmapPixels = new uint32_t[newWidth * newHeight];
            int whereToGet = 0;
            // XY. ..X ... ...
            // ...>..Y>...>Y..
            // ... ... .YX X..
            jniBitmap->_storedBitmapPixels = newBitmapPixels;
            for (int x = newWidth - 1; x >= 0; --x)
                for (int y = 0; y < newHeight; ++y)
                {
                    //take from each row (up to bottom), from left to right
                    uint32_t pixel = previousData[whereToGet++];
                    newBitmapPixels[newWidth * y + x] = pixel;
                }
            delete[] previousData;
            //jniBitmap->_storedBitmapPixels = newBitmapPixels;
        }
        //return jniBitmap;
    }

I called the native method this Way ::

BitmapFactory.Options options = new BitmapFactory.Options();
    Bitmap tempBmp=null;
    ByteBuffer _handler =null;
    @Override
    public boolean onOptionsItemSelected(MenuItem item) {

        switch (item.getItemId())
        {
        case R.id.item_rotate_90:
            options.inPreferredConfig = Config.ARGB_8888;
            bitmapOrig = BitmapFactory.decodeResource(this.getResources(), R.drawable.sampleimage,options);
            rotateBitmap(bitmapOrig,90,_handler);
            tempBmp=getBitmapAndFree();
            if(tempBmp!=null)
            {
                ivDisplay.setImageBitmap(tempBmp);
            }
            break;

LogCat ::

FATAL EXCEPTION: main
java.lang.UnsatisfiedLinkError: Native method not found: com.example.ndksampleproject.MainActivity.rotateBitmap:(Landroid/graphics/Bitmap;ILjava/nio/ByteBuffer;)V
at com.example.ndksampleproject.MainActivity.rotateBitmap(Native Method)
at com.example.ndksampleproject.MainActivity.onOptionsItemSelected(MainActivity.java:113)
at android.app.Activity.onMenuItemSelected(Activity.java:2612)
at com.android.internal.policy.impl.PhoneWindow.onMenuItemSelected(PhoneWindow.java:1061)
at com.android.internal.view.menu.MenuBuilder.dispatchMenuItemSelected(MenuBuilder.java:735)

解决方案

The code I've made already supports rotation. just look at the sample project to see how to call it.

Also, gray scaling shouldn't be a too hard operation to implement on the C++ code I've made. I'm sure there are examples of it on the Internet.

About downsampling, I didn't make it as it's a lot of work, but I have added scaling of images that are already decoded (meaning they are stored as bitmap objects). However, you can always downscale using the normal Google's way , or my way (the bottom code).

这篇关于旋转图像按所传递的方向,使用原生code的功能的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆