Android 实现图片加水印或logo

我们常常会遇到为图像加水印或logo的需求,一般可以通过三方库或者软件实现,但其实加水印非常简单,仅用一个函数即可实现。
实现思路,逐一计算水印和原图重叠部分的像素点的RGBA分量:
  float percent = watermarkA / 255.0f
  dstR = srcR * (1 - percent) + watermarkR * percent;
  dstG = srcG * (1 - percent) + watermarkG * percent;
  dstB = srcB * (1 - percent) + watermarkB * percent;
  dstA = srcA * (1 - percent) + watermarkA * percent;

JNI实现:

extern "C" JNIEXPORT void JNICALL
Java_com_qxt_watermark_WatermarkUtils_add(JNIEnv *env, jclass clazz, jbyteArray src, jint srcWidth,
                   jint srcHeight, jbyteArray watermark, jint watermarkWidth, jint watermarkHeight,
                   jint x, jint y) {
    uint8_t *_src = (uint8_t *) env->GetByteArrayElements(src, nullptr);
    uint8_t *_watermark = (uint8_t *) env->GetByteArrayElements(watermark, nullptr);

    int positionX;
    if (x < 0) {
        positionX = 0;
    } else if (x > srcWidth - watermarkWidth) {
        positionX = srcWidth - watermarkWidth;
    } else {
        positionX = x;
    }
    int positionY;
    if (y < 0) {
        positionY = 0;
    } else if (y > srcHeight - watermarkHeight) {
        positionY = srcHeight - watermarkHeight;
    } else {
        positionY = y;
    }

    for (int h = 0; h < watermarkHeight; h++) {
        for (int w = 0; w < watermarkWidth; w++) {
            /*int srcPosition = ((srcHeight - watermarkHeight + y) * srcWidth
                               + srcWidth - watermarkWidth + x) * 4;*/
            int srcPosition = ((positionY + h) * srcWidth
                               + positionX + w) * 4;
            int position = (h * watermarkWidth + w) * 4;

            float watermarkAlpha = _watermark[position + 3] / 255.0f;
            float dstR = _src[srcPosition] * (1.0f - watermarkAlpha)
                         + _watermark[position] * watermarkAlpha;
            _src[srcPosition] = (uint8_t) dstR;
            float dstG = _src[srcPosition + 1] * (1.0f - watermarkAlpha)
                         + _watermark[position + 1] * watermarkAlpha;
            _src[srcPosition + 1] = (uint8_t) dstG;
            float dstB = _src[srcPosition + 2] * (1.0f - watermarkAlpha)
                         + _watermark[position + 2] * watermarkAlpha;
            _src[srcPosition + 2] = (uint8_t) dstB;
            float dstA = _src[srcPosition + 3] * (1.0f - watermarkAlpha)
                         + _watermark[position + 3] * watermarkAlpha;
            _src[srcPosition + 3] = (uint8_t) dstA;
        }
    }
    env->ReleaseByteArrayElements(watermark, (jbyte *) _watermark, JNI_ABORT);
    env->ReleaseByteArrayElements(src, (jbyte *) _src, 0);
}

java函数及参数说明:

    /**
     *
     * @param image, src image byte array
     * @param imageWidth, src image width
     * @param imageHeight, src image height
     * @param watermark, watermark image byte array
     * @param watermarkWidth, watermark image width
     * @param watermarkHeight, watermark image height
     * @param x, watermark coordinate x,  x >= 0 && x <= imageWidth - watermarkWidth
     * @param y, watermark coordinate y,  y >= 0 && y <= imageHeight - watermarkHeight
     */
    public static native void add(byte[] image, int imageWidth, int imageHeight,
                                  byte[] watermark, int watermarkWidth, int watermarkHeight,
                                  int x, int y);

可以通过x, y坐标控制水印或者logo图片的位置,最终实现效果:


Android 实现图片加水印或logo_第1张图片
watermark.png

以上仅是一个demo,在实际项目中,我们可以结合人脸检测,用类似的方法轻松地实现在相机的预览帧中加个兔子耳朵、络腮胡子之类的效果。
最后,本文demo代码已上传至github:https://github.com/qiuxintai/Watermark

你可能感兴趣的:(Android 实现图片加水印或logo)