Issue
I am trying to convert this Android code in C. I want to do this part in C NDK. Here is what I have tried so far. I am not able to convert getPixel()
and setPixel()
method of android. Please see the code below.
JNIEXPORT jobject JNICALL
Java_com_test_mypic_StylePreviewActivity_mergeBitmaps(JNIEnv *env, jobject instance,
jobject bm, jobject filter) {
AndroidBitmapInfo bm1;
AndroidBitmap_getInfo(env, bm, &bm1);
AndroidBitmapInfo filter1;
AndroidBitmap_getInfo(env, filter, &filter1);
int width = bm1.width;
int height = bm1.height;
int w2 = filter1.width;
int h2 = filter1.height;
float scaleX = (float) w2 / (float) width;
Bitmap result = Bitmap.createBitmap(w2, h2, ANDROID_BITMAP_FORMAT_RGB_565);
void* bitmapPixels;
AndroidBitmap_lockPixels(env, bm, &bitmapPixels);
for (int x = 0; x < w2; x++) {
for (int y = 0; y < h2 && y < height; y++) {
int xx =(int) ((float) x / scaleX);
int yy = (int) ((float) y / scaleX);
int pixel = bm1.getPixel(xx, yy);
int fp = filter1.getPixel(x, y);
int alpha = (fp & 0xFF000000) >> 24;
if (alpha == 0) {
result.setPixel(x, y, pixel);
}
}
}
result = Bitmap.createBitmap(result, 0, 0, width, height);
return result;
}
With the help of @Serhio I wrote this method. But it seems something wrong in here.
JNIEXPORT jobject JNICALL
Java_com_test_mypic_StylePreviewActivity_mergeBitmaps(JNIEnv *env, jobject instance,
jobject bm, jobject filter, jobject result) {
AndroidBitmapInfo bm1;
AndroidBitmap_getInfo(env, bm, &bm1);
AndroidBitmapInfo filter1;
AndroidBitmap_getInfo(env, filter, &filter1);
// AndroidBitmapInfo result1;
// AndroidBitmap_getInfo(env, result, &result1);
int width = bm1.width;
int height = bm1.height;
int w2 = filter1.width;
int h2 = filter1.height;
float scaleX = (float) w2 / (float) width;
for (int x = 0; x < w2; x++) {
for (int y = 0; y < h2 && y < height; y++) {
int xx =(int) ((float) x / scaleX);
int yy = (int) ((float) y / scaleX);
int pixel = getPixel(env,bm, xx, yy);
int fp = getPixel(env,filter,x, y);
int alpha = (fp & 0xFF000000) >> 24;
if (alpha == 0) {
setPixel(env, result, x, y, pixel);
}
}
}
return result;
}
Solution
There is no straight analogue for getPixel()/setPixel()
in native code. Instead of this, you obtain raw pointer to pixel buffer via AndroidBitmap_lockPixels()
, and then you can freely modify data in this buffer. To get/set single pixel you can use next functions:
#include <stdint.h>
#include <assert.h>
#include <jni.h>
#include <android/bitmap.h>
uint32_t getPixel(JNIEnv *env, jobject bm, int x, int y)
{
AndroidBitmapInfo bi = {0};
uint8_t *pixelBuf;
uint8_t a, r, g, b;
AndroidBitmap_getInfo(env, bm, &bi);
/* ensure that we fit into bounds */
assert(x >= 0 && x < bi.width
&& y >= 0 && y < bi.height);
/* we support only one format at the moment */
assert(ANDROID_BITMAP_FORMAT_RGBA_8888 == bi.format);
/* read pixel components */
AndroidBitmap_lockPixels(env, bm, (void **)&pixelBuf);
r = pixelBuf[y * bi.stride + x * 4 + 0];
g = pixelBuf[y * bi.stride + x * 4 + 1];
b = pixelBuf[y * bi.stride + x * 4 + 2];
a = pixelBuf[y * bi.stride + x * 4 + 3];
AndroidBitmap_unlockPixels(env, bm);
return a << 24 | r << 16 | g << 8 | b;
}
void setPixel(JNIEnv *env, jobject bm, int x, int y, uint32_t val)
{
AndroidBitmapInfo bi = {0};
uint8_t *pixelBuf;
AndroidBitmap_getInfo(env, bm, &bi);
/* ensure that we fit into bounds */
assert(x >= 0 && x < bi.width
&& y >= 0 && y < bi.height);
/* we support only one format at the moment */
assert(ANDROID_BITMAP_FORMAT_RGBA_8888 == bi.format);
/* read pixel components */
AndroidBitmap_lockPixels(env, bm, (void **)&pixelBuf);
pixelBuf[y * bi.stride + x * 4 + 0] = (val >> 16) & 0xff;
pixelBuf[y * bi.stride + x * 4 + 1] = (val >> 8) & 0xff;
pixelBuf[y * bi.stride + x * 4 + 2] = (val >> 0) & 0xff;
pixelBuf[y * bi.stride + x * 4 + 3] = (val >> 24) & 0xff;
AndroidBitmap_unlockPixels(env, bm);
}
Of course you can lock buffer just once and iterate through pixels in a loop.
Nonetheless, seems like your code should perform mask applying to bitmap. Probably it is possible to do in java code only via drawing on bitmap-powered canvas with proper PorterDuffXfermode
. See here. It will be done in native code, so performance will be nice.
Answered By - Sergio
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.