【问题标题】:PNG blending modePNG混合模式
【发布时间】:2012-11-26 08:59:47
【问题描述】:

在 Photoshop 中有几种混合模式,例如:

  • 颜色加深
  • 相乘
  • 变暗
  • 变亮
  • 叠加层

(更多信息在这里:http://help.adobe.com/en_US/photoshop/cs/using/WSfd1234e1c4b69f30ea53e41001031ab64-77eba.html

例如,对于模式Color Burn“查看每个通道中的颜色信息并将基础颜色变暗以通过增加两者之间的对比度来反映混合颜色。与白色混合不会产生任何变化”。

这是我的代码:

Bitmap blendBitmap = BitmapFactory.decodeStream(ctx.getAssets().open(filename));
Canvas canvas = new Canvas(srcBitmap);
canvas.drawBitmap(blendBitmap, 0, 0, null); // ?
p.recycle();
p = null;

是否可以应用,例如,颜色加深混合模式,而不是简单地在其他图像上方绘制图像(就像在这个小代码中一样)?

【问题讨论】:

  • 你的意思是要在你的图片上写一个滤镜效果吗?
  • 这不完全是滤镜效果,它是某种方式两层相互混合。

标签: android image-processing android-image


【解决方案1】:

这并不难。

我使用 NDK(因为性能)来处理像素。这个混合模式的信息非常有用:How does photoshop blend two images together?

我的最终解决方案是:

#define ChannelBlend_ColorBurn(A, B)  ((uint8_t) ((B == 0) ? B : max(0, (255 - ((255 -  
#define ChannelBlend_Alpha(A, B, O)    ((uint8_t) (O * A + (1 - O) * B))
#define ChannelBlend_AlphaF(A, B, F, O) (ChannelBlend_Alpha(F(A, B), A, O))

typedef struct {
    uint8_t red;
    uint8_t green;
    uint8_t blue;
    uint8_t alpha;
} rgba;

// Blend
JNIEXPORT void 
JNICALL Java_com_package_Filter_jniBlend(JNIEnv* env, jobject obj, jobject bitmapA,
    jobject bitmapB, jobject bitmapOut, jint mode) {

    // Properties
    AndroidBitmapInfo   infoA;
    void*               pixelsA;
    AndroidBitmapInfo   infoB;
    void*               pixelsB;
    AndroidBitmapInfo   infoOut;
    void*               pixelsOut;

    int ret;

    // Get image info
    if ((ret = AndroidBitmap_getInfo(env, bitmapA, &infoA)) < 0 ||
        (ret = AndroidBitmap_getInfo(env, bitmapB, &infoB)) < 0 ||
        (ret = AndroidBitmap_getInfo(env, bitmapOut, &infoOut)) < 0) {
        return;
    }
    // Check image
    if (infoA.format != ANDROID_BITMAP_FORMAT_RGBA_8888 ||
        infoB.format != ANDROID_BITMAP_FORMAT_RGBA_8888 ||
        infoOut.format != ANDROID_BITMAP_FORMAT_RGBA_8888) {
        return;
    }
    // Lock all images
    if ((ret = AndroidBitmap_lockPixels(env, bitmapA, &pixelsA)) < 0 ||
        (ret = AndroidBitmap_lockPixels(env, bitmapB, &pixelsB)) < 0 ||
        (ret = AndroidBitmap_lockPixels(env, bitmapOut, &pixelsOut)) < 0) {
        LOGE("Error! %d", ret);
    }

    int h = infoA.height;
    int w = infoA.width;
    int wh = w * h;

    int n;
    rgba* inputA = (rgba*) pixelsA;
    rgba* inputB = (rgba*) pixelsB;
    rgba* output = (rgba*) pixelsOut;

    rgba pA, pB;

    int x, y;
    for (y = 0; y < h; y++) {
        for (x = 0; x < w; x++) {
            n = y * w + x;

            pA = inputA[n];
            pB = inputB[n];

            float alpha = (float) pB.alpha / 255.0;

            output[n].red = ChannelBlend_AlphaF(pA.red, pB.red, ChannelBlend_ColorBurn, alpha);
            output[n].green = ChannelBlend_AlphaF(pA.green, pB.green, ChannelBlend_ColorBurn, alpha);
            output[n].blue = ChannelBlend_AlphaF(pA.blue, pB.blue, ChannelBlend_ColorBurn, alpha);
        }
    }

    // Unlocks everything
    AndroidBitmap_unlockPixels(env, bitmapA);
    AndroidBitmap_unlockPixels(env, bitmapB);
    AndroidBitmap_unlockPixels(env, bitmapOut);
}

提高性能的小评论:在我为单个像素制作方程式之后,将值存储在某种缓存中以便下次无需方程式更快地访问它会很好。

【讨论】:

  • 成功了!当然,有一些拼写错误,例如 ChannelBlend_ColorBurn 的声明,但仍然非常感谢!您实际上保存了我的应用程序!我终于可以放弃 ImageMagick,谢谢!
猜你喜欢
  • 2018-04-22
  • 2013-12-01
  • 1970-01-01
  • 2021-05-08
  • 1970-01-01
  • 2012-08-04
  • 2011-04-13
  • 2020-06-11
  • 1970-01-01
相关资源
最近更新 更多