位图颜色更改

6

我正在尝试创建一个函数,该函数获取位图和目标颜色,并返回着色的位图(不使用绘画)。 我找到了几种方法来实现它,但没有一种方法能够像我想要的那样正常工作。

我能找到的最接近的解决方案是:

    public static Bitmap changeImageColor(Bitmap srcBmp, int dstColor) {

        int width = srcBmp.getWidth();
        int height = srcBmp.getHeight();

        float srcHSV[] = new float[3];
        float dstHSV[] = new float[3];

        Bitmap dstBitmap = Bitmap.createBitmap(width, height, Config.RGB_565);

        for (int row = 0; row < height; row++) {
            for (int col = 0; col < width; col++) {
                Color.colorToHSV(srcBmp.getPixel(col, row), srcHSV);
                Color.colorToHSV(dstColor, dstHSV);

                // If it area to be painted set only value of original image
                dstHSV[2] = srcHSV[2];  // value
                int color2=Color.HSVToColor(dstHSV);;
                dstBitmap.setPixel(col, row, Color.HSVToColor(dstHSV));
            }
        }

        return dstBitmap;
    }

但是在透明图片上它的效果并不太好,如下所示(之前和之后):enter image description here 有没有其他解决方案(不再使用画图工具)?

我在这里回答了一个类似的问题:https://dev59.com/moDba4cB1Zd3GeqPC1MW 它使用 yourImageView.setColorFilter(yourColor, PorterDuff.Mode.MULTIPLY); - Phantômaxx
我只使用位图,我需要一个返回彩色位图的函数。 - SpoocyCrep
3个回答

5

你只需要提取alpha通道,然后在变换后重新应用它,并使用ARGB_8888;

编辑你的代码以包含alpha:

public Bitmap colorize(Bitmap srcBmp, int dstColor) {

        int width = srcBmp.getWidth();
        int height = srcBmp.getHeight();

        float srcHSV[] = new float[3];
        float dstHSV[] = new float[3];

        Bitmap dstBitmap = Bitmap.createBitmap(width, height, Config.ARGB_8888);

        for (int row = 0; row < height; row++) {
            for (int col = 0; col < width; col++) {
                int pixel = srcBmp.getPixel(col, row);
                int alpha = Color.alpha(pixel);
                Color.colorToHSV(pixel, srcHSV);
                Color.colorToHSV(dstColor, dstHSV);

                // If it area to be painted set only value of original image
                dstHSV[2] = srcHSV[2];  // value
                dstBitmap.setPixel(col, row, Color.HSVToColor(alpha, dstHSV));
            }
        }

        return dstBitmap;
}

我不知道什么是光栅,而且在安卓系统中只有HSV,没有HSL。 - SpoocyCrep
我会修复你的代码,使着色保持不透明。 - SGal
感谢上苍给出的答案!完美地解决了问题! - Michael
实际上...它可以工作,但是当使用相同的可绘制资源时会产生奇怪的效果。 - Michael
@Mike Milla 在更改 drawable 资源之前,您应该先使用 mutate() 方法。 - SGal
显示剩余3条评论

2

以下是一个示例代码,用于改变位图的颜色:

private BitmapDrawable getColoredBitmap(int color, Context context,
            int drawableId) {
        Bitmap source = BitmapFactory.decodeResource(context.getResources(),
                drawableId);
        final Bitmap bitmap = Bitmap.createBitmap(source.getWidth(),
                source.getHeight(), Bitmap.Config.ARGB_8888);
        for (int i = 0; i < source.getWidth(); i++) {
            for (int j = 0; j < source.getHeight(); j++) {
                int pixel = source.getPixel(i, j);

                // if (pixel == Color.TRANSPARENT) {
                //
                // } else
                if (pixel == Color.WHITE) {
                    pixel = Color.argb(Color.alpha(pixel),
                            Color.red(Color.WHITE), Color.green(Color.WHITE),
                            Color.blue(Color.WHITE));
                } else {
                    pixel = Color.argb(Color.alpha(pixel), Color.red(color),
                            Color.green(color), Color.blue(color));
                }
                bitmap.setPixel(i, j, pixel);
            }
        }
        return new BitmapDrawable(context.getResources(), bitmap);
    }

结果是:http://puu.sh/eJqS9/7275c317e2.png,我并不是想将它完全改为一种颜色,只是给它上色。 - SpoocyCrep
它将会把透明颜色改为给定的颜色。 - balaji koduri
你需要的是源图像,请提供。 - balaji koduri
我希望它能够被着色,有一点颜色的色调,但仍然能够看到方块。这是源图像:http://puu.sh/eJrBr/0b807796a3.png - SpoocyCrep
你想要改变哪个颜色? - balaji koduri
显示剩余6条评论

0
你需要这样做:
int alpha=srcBmp.getPixel(col, row);
dstBitmap.setPixel(col, row, Color.HSVToColor(dstHSV));

在这段代码中,你计算了一个 alpha 值(看起来可能是错误的),但是却没有使用它。你可能需要使用 HSVToColor 创建一个带有 alpha 值的 Color 对象,然后在 setPixel 中使用它。同时,你可能也需要以类似的方式获取 alpha 值,因为我很难相信 getPixel 函数只返回 alpha 值 :p


我忘了去掉 alpha,实际上是不正确的。我尝试了你说的方法,但结果没有改变。 - SpoocyCrep
作为一种调试哲学,您是否能够完全忽略源位图,并将目标像素设置为全部透明?因为如果您不能这样做,至少可以在这里提出一个更简单的问题,简单的问题会得到更好的答案 :) - Andy Newman
我认为我能行,我会尝试,虽然我更希望有人能提出更好的着色方案,这个不是最好的,颜色太高和强烈了。 - SpoocyCrep

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接