android - Rotate the image as per the passed orientation to the functions using Native Code -
i want rotate image per passing orientation function in rotatebitmap() funcation.
i have taken reference method this awesome library.
what want ::
i want rotate image per passing orientation in function after want apply gray scaling effect image , if want downnsample image , return thumbnail of image calling activity.
here below have pasted native code ..
what have tried far ::
#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 stored. returning null..."); return null; } // //creating new bitmap put pixels - 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 pixels 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 new bitmap"); return newbitmap; } /**store java bitmap 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 not rgba_8888!"); return null; } // //read pixels of bitmap 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 ... (int x = 0; x < newwidth; ++x) (int y = newheight - 1; y >= 0; --y) { //take each row (up bottom), left 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; (int y = height - 1; y >= 0; --y) (int x = width - 1; x >= 0; --x) { //take each row (up bottom), left 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; (int x = newwidth - 1; x >= 0; --x) (int y = 0; y < newheight; ++y) { //take each row (up bottom), left 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 d:/workspace/ndksampleproject/jni/photophun.cpp:2:0: d:/android-ndk-r8b/platforms/android-14/arch-arm/usr/include/jni.h:592:13: note: 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 no value, in function returning 'jobject {aka _jobject*}' [-fpermissive] d:/workspace/ndksampleproject/jni/photophun.cpp:179:4: error: return-statement no value, in function returning 'jobject {aka _jobject*}' [-fpermissive] d:/workspace/ndksampleproject/jni/photophun.cpp:204:4: error: return-statement no value, in function returning 'jobject {aka _jobject*}' [-fpermissive] d:/workspace/ndksampleproject/jni/photophun.cpp:226:9: error: cannot convert 'jnibitmap*' 'jobject {aka _jobject*}' in return /cygdrive/d/android-ndk-r8b/build/core/build-binary.mk:255: recipe 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 need side. please me in great need complete thing resolve oom issue. many 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 ... (int x = 0; x < newwidth; ++x) (int y = newheight - 1; y >= 0; --y) { //take each row (up bottom), left 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; (int y = height - 1; y >= 0; --y) (int x = width - 1; x >= 0; --x) { //take each row (up bottom), left 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; (int x = newwidth - 1; x >= 0; --x) (int y = 0; y < newheight; ++y) { //take each row (up bottom), left right uint32_t pixel = previousdata[wheretoget++]; newbitmappixels[newwidth * y + x] = pixel; } delete[] previousdata; //jnibitmap->_storedbitmappixels = newbitmappixels; } //return jnibitmap; }
i called native method 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 @ com.example.ndksampleproject.mainactivity.rotatebitmap(native method) @ 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)
the code i've made supports rotation. @ sample project see how call it.
also, gray scaling shouldn't hard operation implement on c++ code i've made. i'm sure there examples of on internet.
about downsampling, didn't make it's lot of work, have added scaling of images decoded (meaning stored bitmap objects). however, can downscale using normal google's way , or my way (the bottom code).
Comments
Post a Comment