我在这里撞墙撞墙,我很确定我做了些蠢事,所以有时间把我的愚蠢公之于众。
我正在尝试拍摄两张图像,使用标准混合算法(Hardlight,softlight,叠加,乘法等)将它们混合成第三张图像。
因为Android没有内置这样的混合属性,所以我已经走下了获取每个像素并使用算法组合它们的道路。但是,结果是垃圾。下面是简单乘法混合的结果(使用的图像和预期结果)。
BASE:
BLEND:
预期结果:
垃圾结果:
任何帮助将不胜感激。下面是代码,我试图删除所有“垃圾”,但有些可能已经完成了。如果不清楚,我会清理它。
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;
}
答案 0 :(得分:14)
复制后,我认为您的问题与在RGB565模式下操作图像有关。正如this post中所讨论的,Bitmaps显然需要处于ARGB8888模式才能正常操作。我首先通过执行以下操作获得了乘法混合的预期结果:
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...
将位图转换为ARGB8888模式似乎对我有用,至少对于渐变测试模式。但是,你只需要做Screen或Multiply,你也可以试试这个:
// 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);
有了这个,你没有进行每像素计算,但是你只能使用预设的PorterDuff.Mode
s。在我的快速(和肮脏)测试中,这是我能够使混合处理非渐变图像的唯一方法。
答案 1 :(得分:5)
简单叠加你可以这样做(为简单起见,假设bmp1等于或大于bmp2):
private Bitmap bitmapOverlay(Bitmap bmp1, Bitmap bmp2)
{
Bitmap bmOverlay = Bitmap.createBitmap(bmp1.getWidth(), bmp1.getHeight(), bmp1.getConfig());
Canvas canvas = new Canvas(bmOverlay);
canvas.drawBitmap(bmp1, 0, 0, null);
canvas.drawBitmap(bmp2, 0, 0, null);
return bmOverlay;
}
对于更复杂的混合算法,也许您可以使用一些可用的Bitmap / Canvas函数来帮助自己。