jni操作图片


先拍一个照片①
指定文字生成半透明图片②
指定信息生成二维码③
②和③拼接成④
④再印在①上
原功能的拼接是上下拼接,得改

extern "C"
JNIEXPORT jintArray JNICALL
Java_com_xxx_xxx_pic_WaterMake_jointPicture(JNIEnv *env, jclass clazz,jintArray pixels, jint width, jint height,jintArray add_pixel, jint add_width,jint add_height) {
  
    //像素数组拷贝到native层
    jint *pixel = env->GetIntArrayElements(pixels, JNI_FALSE);
    jint *addPixel = env->GetIntArrayElements(add_pixel, JNI_FALSE);
    //这里假定图片宽度相同
    // 并不是,其实是高度相同
    //int size = width * (height+add_height);
    int size =  (width+add_width) * height;
    jint *newPixel = new jint[size];
    int x, y;
    // 修改这里
    for(x = 0 ; x < height ;x ++){
        for ( y = 0; y < width; y ++) {
            newPixel[x*(width + add_width) + y] = pixel[x*width + y];
        }
    }

    for (x = 0; x < height; x ++) {
        for (y = 0; y < add_width; ++y) {
            newPixel[x*(width + add_width)+ y + width] = addPixel[x*add_width + y];
        }
    }
    
    jintArray newPixels = env->NewIntArray(size);
    env->SetIntArrayRegion(newPixels, 0, size, newPixel);
    env->ReleaseIntArrayElements(pixels, pixel, 0);
    env->ReleaseIntArrayElements(add_pixel, addPixel, 0);
    return newPixels;
}



copy来的代码,也改一下

/**
     * 使用NDK拼接图片
     * @param bitmap bitmap
     * @param addBitmap addBitmap
     */
    public static Bitmap ndkJointPicture(Bitmap bitmap,  Bitmap addBitmap){
        if (bitmap == null || addBitmap == null){
            return null;
        }
        int width = bitmap.getWidth();
        int height = bitmap.getHeight();
        int[] pixels = new int[width * height];
        //获取bitmap的所有pixel像素点
        bitmap.getPixels(pixels, 0, width, 0, 0, width, height);

        int addWidth = addBitmap.getWidth();
        int addHeight = addBitmap.getHeight();
        int[] addPixel = new int[addWidth * addHeight];
        addBitmap.getPixels(addPixel, 0, addWidth, 0, 0, addWidth, addHeight);

        //ndk处理像素点数组
        int[] newPixels = jointPicture(pixels, width, height, addPixel, addWidth, addHeight);
        // 使用 Bitmap.Config.ARGB_8888 模式 更改为需要的尺寸
        Bitmap ndkBitmap = Bitmap.createBitmap(width + addWidth, height, Bitmap.Config.ARGB_8888);
        //重新设置bitmap的所有pixel像素点
        ndkBitmap.setPixels(newPixels, 0, width + addWidth, 0, 0, width + addWidth, height);
        return ndkBitmap;
    }



然后是水印,原功能是直接将图片印上去,替换掉原来的像素,单这个不符合需求,需要保留④的部分是透明的,需要保留①的信息,动手改一下。

/**
 *  图片水印
 */
extern "C"
JNIEXPORT jintArray JNICALL
Java_com_xxx_xxx_pic_WaterMake_picWaterMark(JNIEnv *env, jclass clazz,jintArray pixels, jint width, jint height,jintArray overlay_pixels,jint overlay_width, jint overlay_height,jint offset_x, jint offset_y) {
    // TODO: implement picWaterMark()
    //像素数组拷贝到native层
    jint *pixel = env->GetIntArrayElements(pixels, JNI_FALSE);
    jint *overlayPixel = env->GetIntArrayElements(overlay_pixels, JNI_FALSE);
    
    int size = width * height;
    int alpha;
    int red;
    int green ;
    int blue;

    // 添加了变量
    int alphaadd  ;
    int redadd ;
    int greenadd;
    int blueadd ;
    
    int x, y;
    for(x=0; x<width; x++){
        for(y=0; y< height; y++){
            //获取每一个像素点
            int color = pixel[y*width + x];
            alpha = (color >> 24) & 0xFF;
            red = (color >> 16) & 0xFF;
            green = (color >> 8) & 0xFF;
            blue = color & 0xFF;


            //获取覆盖层图片的像素点
            if(x > offset_x && x < width && y > offset_y && y < height){
                int addColor = overlayPixel[(y-offset_y)*overlay_width + (x-offset_x)];
                //混合像素的RGBA
                alphaadd = (addColor >> 24)  & 0xFF ;
                redadd = (addColor  >> 16) & 0xFF ;
                greenadd = (addColor  >> 8) & 0xFF ;
                blueadd = (addColor ) & 0xFF ;
                
                // 在这里进行计算
                red = (redadd * alphaadd +(red * (255-alphaadd)))/255;
                green = (greenadd * alphaadd +(green * (255-alphaadd)))/255;
                blue = (blueadd * alphaadd +(blue * (255-alphaadd)))/255;
            }

            //重新赋值给每个像素点
            pixel[y*width + x] = (alpha << 24) |  (red << 16)  |  (green << 8)  |  blue  ;
        }
    }
    jintArray newPixel = env->NewIntArray(size);
    env->SetIntArrayRegion(newPixel, 0, size, pixel);
    env->ReleaseIntArrayElements(pixels, pixel, 0);
    env->ReleaseIntArrayElements(overlay_pixels, overlayPixel, 0);
    return newPixel;
}



更改的主要点在这里:

        red = (redadd * alphaadd +(red * (255-alphaadd)))/255;
        green = (greenadd * alphaadd +(green * (255-alphaadd)))/255;
        blue = (blueadd * alphaadd +(blue * (255-alphaadd)))/255;

根据获取到的alphaadd(④的透明度)计算叠加后的像素值。
举个栗子:
④的红色通道值为240,透明度为200;①的红色通道值为100;
那算一下,最后的值为:

(240x200 + 100x(255-200))/255≈209.8
取整:209,这就是像素叠加后的红色通道值。

印上去的java代码

 public static Bitmap picWaterMarks(Bitmap bitmap,  Bitmap addBitmap){
        if (bitmap == null || addBitmap == null){
            return null;
        }
        int width = bitmap.getWidth();
        int height = bitmap.getHeight();
        int[] pixels = new int[width * height];
        //获取bitmap的所有pixel像素点
        bitmap.getPixels(pixels, 0, width, 0, 0, width, height);
        int addWidth = addBitmap.getWidth();
        int addHeight = addBitmap.getHeight();
        int[] addPixel = new int[addWidth * addHeight];
        addBitmap.getPixels(addPixel, 0, addWidth, 0, 0, addWidth, addHeight);

        //ndk处理像素点数组
        int[] newPixels = picWaterMark(pixels, width, height, addPixel, addWidth, addHeight,0,height-addHeight);
        Bitmap ndkBitmap = Bitmap.createBitmap(width , height, Bitmap.Config.ARGB_8888);
        //重新设置bitmap的所有pixel像素点
        ndkBitmap.setPixels(newPixels, 0, width , 0, 0, width , height);
        return ndkBitmap;
    }



再来看看这个native方法的参数:

 int[] newPixels = picWaterMark(pixels, width, height, addPixel, addWidth, addHeight,0,height-addHeight);
1
pixels 底图的像素组
width 底图的宽
height 底图的高
addPixel 水印图片的像素组
addWidth 水印图片的宽
addHeight 水印图片的高
0 水印x坐标起点
height-addHeight 水印y坐标起点
需要注意的是,图像的坐标和数学坐标有差异:

左上角为(0,0)
左下角为(0,hight)
右上角为(width,0)
右下角为(width,hight)
取像素的顺序是横向的,即:

pixels [0]=(0,0);
pixels [1]=(1,0);
pixels [2]=(2,0);
 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

AI算法网奇

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值