位图图像未正确呈现

时间:2014-10-03 14:29:37

标签: java

我有这个图片

enter image description here

这只是一个圆圈,对边缘变得更加透明。如果我将此图像blit到屏幕上,我会看到以下内容:

enter image description here

有没有人知道为什么我的图像会像这样被吸引到屏幕上?以下是我的相关功能:

public void blit(Bitmap bitmap, int x, int y) {
    int x0 = x;
    int x1 = x + bitmap.width;
    int y0 = y;
    int y1 = y + bitmap.height;
    if (x0 < 0)
        x0 = 0;
    if (y0 < 0)
        y0 = 0;
    if (x1 > width)
        x1 = width;
    if (y1 > height)
        y1 = height;
    int ww = x1 - x0;

    for (int yy = y0; yy < y1; yy++) {
        int tp = yy * width + x0;
        int sp = (yy - y) * bitmap.width + (x0 - x);
        tp -= sp;
        for (int xx = sp; xx < sp + ww; xx++) {
            int col = bitmap.pixels[xx];
            if (col < 0 && (tp+xx) < pixels.length){
                pixels[tp + xx] = normal(col, pixels[tp + xx]);
            }
        }
    }
}
    public static int normal(int a, int b) {
        int aA = (a >> 24) & 0xff;
        int aR = ((a & 0xff0000) >> 16);
        int aG = ((a & 0xff00) >> 8);
        int aB = (a & 0xff);

        int bA = (b >> 24) & 0xff;
        int bR = ((b & 0xff0000) >> 16);
        int bG = ((b & 0xff00) >> 8);
        int bB = (b & 0xff);

        float alpha = aA / 255f;

        if (aA == 255 || bA == 0){
            return a;
        }

        float srcAlpha = aA * (1 / 255f);
        float dstAlpha = bA * (1 / 255f);
        int A = (int) (aA+bA*(1-srcAlpha));
        int R = (int) (aR*srcAlpha+bR*dstAlpha*(1-srcAlpha));
        int G = (int) (aG*srcAlpha+bG*dstAlpha*(1-srcAlpha));
        int B = (int) (aB*srcAlpha+bB*dstAlpha*(1-srcAlpha));

        return A << 24 | R << 16 | G << 8 | B;
}
//code for importing image
public static Bitmap getBitmap(String location){
    try{
        BufferedImage image = ImageIO.read(ImageHandler.class.getResource(location));

        Bitmap bitmap = new Bitmap(image.getWidth(), image.getHeight());

        for(int i = 0; i < image.getWidth(); i++){
            for(int j = 0; j < image.getHeight(); j++){
                int rgb = image.getRGB(i, j);
                if(rgb != 0xFFFF00FF && rgb != 0xFF990099){
                    bitmap.setPixel(rgb, i, j);
                }
            }
        }

        return bitmap;
    }catch(Exception e){
        e.printStackTrace();
        return null;
    }
}

如果这个问题看起来模糊不清,我真的很抱歉,我真的迷失了这个问题!提前致谢。我个人认为答案就在于我实际上是如何对像素进行模糊以及它们如何重叠。

更新

我一直在玩代码,如果我传入

,那就是某个值无法正确计算
int colour = 0x80FF0000;

然后程序读取alpha为128,但是,如果我传入:

int colour = 0x79FF0000;

alpha突然被读为254,因此会使图像被切断。

float aA = (a >> 24) & 0x000000FF;

是我如何提取alpha

float srcAlpha = aA / 255F;

是我如何提取源alpha

编辑2

问题不在于四舍五入,而在于缓冲。

buffer.renderTest(); //buffer is of type Bitmap

将完美呈现屏幕上的渐变

Bitmap b = new Bitmap(buffer.width, buffer.height);
b.renderTest();
buffer.blit(b, 0, 0);
然而,一旦透明度低于0x79000000,

将被切断 这是否意味着发行是我的blit功能?

2 个答案:

答案 0 :(得分:1)

在你的blit函数中:

if (col < 0 && (tp+xx) < pixels.length){
        pixels[tp + xx] = normal(col, pixels[tp + xx]);
}

这不会处理透明度,因为col可能大于0。

if ((tp+xx) < pixels.length){
    pixels[tp + xx] = normal(col, pixels[tp + xx]);
}

只需要......

答案 1 :(得分:0)

根据Wikipedia article,您添加两个像素的公式是错误的。

修改(2)

  • normal运算符不可交换。背景和前景之间有明显的区别。你需要交换参数:

    正常(像素[tp + xx],col);

而不是:

正常(col,pixels [tp + xx]);

  • 第一个错误是在alpha值提取中,您使用:

    int aA =(a&gt;&gt;&amp; 0xff); //由编译器读取(a&gt;&gt;(24&amp; 0xff))

使用

int aA = (a >> 24) & 0xff;

代替。

  • 您应该使用:

int A = (int) (aA+bA*(1-srcAlpha)); int R = (int) (aR*srcAlpha+bR*dstAlpha*(1-srcAlpha)); //...

为什么要添加0.5

效果优化

为了优化性能,您可以通过移回结果来绕过使用浮点运算:

int cA = 0xff-aA;
int A = aA+bA*cA/0xff;
int R = (aR*aA+bR*bA*cA)/0xff;
//...