Поверните изображение в соответствии с переданной ориентацией на функции, используя собственный код

Я хочу повернуть изображение в соответствии с передачей ориентации функции в моей функции rotateBitmap().

Я взял ссылку на этот метод из этой удивительной библиотеки.

Что я хочу сделать:

Я хочу повернуть изображение в соответствии с передачей ориентации в функции после этого, я хочу  примените эффект серого масштабирования к изображению, а затем, если хотите уменьшить изображение и вернуть эскиз изображения к вызывающей активности.

Здесь ниже я вставил свой собственный код.

Что я пробовал до сих пор:

#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;
}

Лог 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

Пожалуйста, дайте мне знать, если вам нужно что-нибудь с моей стороны. Пожалуйста, помогите мне, поскольку мне очень нужна эта задача, чтобы решить проблему OOM. Большое спасибо заранее....

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;
    }

Я вызвал собственный метод 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)

Ответ 1

Код, который я сделал, уже поддерживает вращение. просто посмотрите пример проекта, чтобы узнать, как его назвать.

Кроме того, серое масштабирование не должно быть слишком сложной операцией для реализации кода С++, который я сделал. Я уверен, что есть примеры этого в Интернете.

Что касается понижающей дискретизации, я не делал этого так, как это было много работы, но я добавил масштабирование изображений, которые уже декодированы (что означает, что они хранятся в виде растровых объектов). Тем не менее, вы всегда можете уменьшить масштаб, используя обычный способ Google или мой путь (нижний код).