从两个位图混合像素 [英] Blending pixels from Two Bitmaps

查看:167
本文介绍了从两个位图混合像素的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我打我的头撞墙在这里,我相当肯定我做一些愚蠢的,让时间来让我的愚蠢公开。

我试图把两个图像,使用标准混合算法(HARDLIGHT,柔光,叠加,繁衍,等)。

混合在一起成为第三图像

由于机器人不具备这样的共混物性质构建,我已经向下取各像素和使用算法将它们结合起来的路径。然而,结果是垃圾。下面是一个简单的乘法混合(使用的图像,和预期结果)。

的结果

BASE:

混纺:

预期的结果:

垃圾结果:

任何帮助将是AP preciated。下面是code,我一直试图去掉所有的垃圾,但有些人可能已经过关的。我将它清理干净,如果事情是不明确的。

 的ImageView ImageView的=(ImageView的)findViewById(R.id.ImageView01);
    位图的基础= BitmapFactory.de codeResource(getResources(),R.drawable.base);
    位图的结果= base.copy(Bitmap.Config.RGB_565,真正的);
    位图混合= BitmapFactory.de codeResource(getResources(),R.drawable.blend);

    IntBuffer buffB​​ase = IntBuffer.allocate(base.getWidth()* base.getHeight());
    base.copyPixelsToBuffer(buffB​​ase);
    buffB​​ase.rewind();

    IntBuffer buffB​​lend = IntBuffer.allocate(blend.getWidth()* blend.getHeight());
    blend.copyPixelsToBuffer(buffB​​lend);
    buffB​​lend.rewind();

    IntBuffer buffOut = IntBuffer.allocate(base.getWidth()* base.getHeight());
    buffOut.rewind();

    而(buffOut.position()&其中; buffOut.limit()){
        INT filterInt = buffB​​lend.get();
        INT srcInt = buffB​​ase.get();

        INT redValueFilter = Color.red(filterInt);
        INT greenValueFilter = Color.green(filterInt);
        INT blueValueFilter = Color.blue(filterInt);

        INT redValueSrc = Color.red(srcInt);
        INT greenValueSrc = Color.green(srcInt);
        INT blueValueSrc = Color.blue(srcInt);

        INT redValueFinal =乘(redValueFilter,redValueSrc);
        INT greenValueFinal =乘(greenValueFilter,greenValueSrc);
        INT blueValueFinal =乘(blueValueFilter,blueValueSrc);

        INT像素= Color.argb(255,redValueFinal,greenValueFinal,blueValueFinal);

        buffOut.put(象素);
    }

    buffOut.rewind();

    result.copyPixelsFromBuffer(buffOut);

    BitmapDrawable绘制=新BitmapDrawable(getResources(),结果);
    imageView.setImageDrawable(绘制);
}

诠释乘(INT IN1,IN2 INT){
    回报IN1 * IN2 / 255;
}
 

解决方案

复制之后,我觉得你的问题,是因为有操纵图像RGB565模式。正如讨论过这个帖子,位图显然需要在ARGB8888模式来操作正常。我第一次对一个乘法混合的预期结果通过执行以下操作:

 资源资源= getResources();
BitmapFactory.Options选项=新BitmapFactory.Options();
options.in preferredConfig = Bitmap.Config.ARGB_8888;
位图的基础= BitmapFactory.de codeResource(RES,R.drawable.base,期权);
位图混合= BitmapFactory.de codeResource(RES,R.drawable.blend,期权);

//现在基地和融合是ARGB8888模式,这是你想要的

位图的结果= base.copy(Config.ARGB_8888,真正的);
//像以前一样与IntBuffers继续...
 

将转换为位图模式ARGB8888似乎为我工作,至少与梯度测试模式。但是,你只需要做屏幕或乘,你可以试试这个还有:

  //同一图像创建/如上读书,则:
涂料P =新的油漆();
p.setXfermode(新PorterDuffXfermode(Mode.MULTIPLY));
p.setShader(新BitmapShader(混合,TileMode.CLAMP,TileMode.CLAMP));

帆布C =新的Canvas();
c.setBitmap(结果);
c.drawBitmap(碱,0,0,NULL);
c.drawRect(0,0,base.getWidth(),base.getHeight()中,p);
 

通过了,你是不是在做每个像素的计算,但仅限于preSET PorterDuff.Mode 秒。在我快(和肮脏)的测试,这是我能得到的混合工作在非梯度图像的唯一方式。

I'm beating my head against a wall here, and I'm fairly certain I'm doing something stupid, so time to make my stupidity public.

I'm trying to take two images, blend them together into a third image using standard blending algorithms (Hardlight, softlight, overlay, multiply, etc).

Because Android does not have such blend properties build in, I've gone down the path of taking each pixel and combine them using an algorithm. However, the results are garbage. Below is the results of a simple multiply blend (images used, and expected result).

BASE:

BLEND:

EXPECTED RESULT:

GARBAGE RESULT:

Any help would be appreciated. Below is the code, which I've tried to strip out all the "junk", but some may have made it through. I'll clean it up if something isn't clear.

    ImageView imageView = (ImageView) findViewById(R.id.ImageView01);
    Bitmap base = BitmapFactory.decodeResource(getResources(), R.drawable.base);
    Bitmap result = base.copy(Bitmap.Config.RGB_565, true);
    Bitmap blend = BitmapFactory.decodeResource(getResources(), R.drawable.blend);

    IntBuffer buffBase = IntBuffer.allocate(base.getWidth() * base.getHeight());
    base.copyPixelsToBuffer(buffBase);
    buffBase.rewind();

    IntBuffer buffBlend = IntBuffer.allocate(blend.getWidth() * blend.getHeight());
    blend.copyPixelsToBuffer(buffBlend);
    buffBlend.rewind();

    IntBuffer buffOut = IntBuffer.allocate(base.getWidth() * base.getHeight());
    buffOut.rewind();

    while (buffOut.position() < buffOut.limit()) {
        int filterInt = buffBlend.get();
        int srcInt = buffBase.get();

        int redValueFilter = Color.red(filterInt);
        int greenValueFilter = Color.green(filterInt);
        int blueValueFilter = Color.blue(filterInt);

        int redValueSrc = Color.red(srcInt);
        int greenValueSrc = Color.green(srcInt);
        int blueValueSrc = Color.blue(srcInt);

        int redValueFinal = multiply(redValueFilter, redValueSrc);
        int greenValueFinal = multiply(greenValueFilter, greenValueSrc);
        int blueValueFinal = multiply(blueValueFilter, blueValueSrc);

        int pixel = Color.argb(255, redValueFinal, greenValueFinal, blueValueFinal);

        buffOut.put(pixel);
    }

    buffOut.rewind();

    result.copyPixelsFromBuffer(buffOut);   

    BitmapDrawable drawable = new BitmapDrawable(getResources(), result);
    imageView.setImageDrawable(drawable);
}

int multiply(int in1, int in2) {
    return in1 * in2 / 255;
}

解决方案

After reproducing, I think your issue has to do with manipulating the images in RGB565 mode. As discussed in this post, Bitmaps apparently need to be in ARGB8888 mode to manipulate properly. I first got the expected result on a multiply blend by doing the following:

Resources res = getResources();
BitmapFactory.Options options = new BitmapFactory.Options();
options.inPreferredConfig = Bitmap.Config.ARGB_8888;
Bitmap base = BitmapFactory.decodeResource(res, R.drawable.base, options);
Bitmap blend = BitmapFactory.decodeResource(res, R.drawable.blend, options);

// now base and blend are in ARGB8888 mode, which is what you want

Bitmap result = base.copy(Config.ARGB_8888, true);
// Continue with IntBuffers as before...

Converting the Bitmaps to ARGB8888 mode did seem to work for me, at least with the gradient test patterns. However, it you only need to do Screen or Multiply, you might try this as well:

// Same image creation/reading as above, then:
Paint p = new Paint();
p.setXfermode(new PorterDuffXfermode(Mode.MULTIPLY));
p.setShader(new BitmapShader(blend, TileMode.CLAMP, TileMode.CLAMP));

Canvas c = new Canvas();
c.setBitmap(result);
c.drawBitmap(base, 0, 0, null);
c.drawRect(0, 0, base.getWidth(), base.getHeight(), p);

With that, you aren't doing the per-pixel calculations, but you are limited to the preset PorterDuff.Modes. In my quick (and dirty) testing, this was the only way I was able to get the blending to work on non-gradient images.

这篇关于从两个位图混合像素的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆