简体   繁体   中英

Why isn't my method for removing this color working?

I'm trying to make a Mario game clone, and right now, in my constructor, I have a method that is supposed to make a certain color transparent instead of the current pinkish (R: 255, G: 0, B: 254). According to Photoshop, the hex value is ff00fe. My method is:

public Mario(){
    this.state = MarioState.SMALL;
    this.x = 54;
    this.y = 806;
    URL spriteAtLoc = getClass().getResource("sprites/Mario/SmallStandFaceRight.bmp");

    try{
      sprite = ImageIO.read(spriteAtLoc);
      int width = sprite.getWidth();
      int height = sprite.getHeight();
      int[] pixels = new int[width * height];
      sprite.getRGB(0, 0, width, height, pixels, 0, width);

      for (int i = 0; i < pixels.length; i++) {

        if (pixels[i] == 0xFFff00fe) {

          pixels[i] = 0x00ff00fe; //this is supposed to set alpha value to 0 and make the target color transparent
        }

      }
    } catch(IOException e){
      System.out.println("sprite not found");
      e.printStackTrace();
    }
  }

it runs and compiles, but sprite comes out exactly the same when I render it. (edit: perhaps of note I do not have super.paintComponent(g) in my paintComponent(g) method. The sprites are .bmps. 这就是精灵的样子

You are only retrieving the pixels using BufferedImage.getRGB . That returns a copy of the data in a certain area of the BufferedImage.

Any change you make to the int[] returned is not automatically reflected back into the image.

To update the image, you need to call BufferedImage.setRGB after you change the int[] :

sprite.setRGB(0, 0, width, height, pixels, 0, width);

Another change you should probably make (and this involves a little guesswork as I don't have your bmp to test with) - the BufferedImage returned by ImageIO.read may have type BufferedImage.TYPE_INT_RGB - meaning that it doesn't have an alpha channel. You can verify by printing sprite.getType() , if that prints 1 it's TYPE_INT_RGB without an alpha channel.

To get an alpha channel, create a new BufferedImage of the right size and then set the converted int[] on that image, then use the new image from then on:

BufferedImage newSprite = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
newSprite.setRGB(0, 0, width, height, pixels, 0, width);
sprite = newSprite; // Swap the old sprite for the new one with an alpha channel

BMP images don't provide an alpha channel, you have to set it manually (as you do in your code)...

when you check your pixel to have a certain color you have to check without alpha (BMP has no alpha it's always 0x0).

if (pixels[i] == 0x00ff00fe) { //THIS is the color WITHOUT alpha
    pixels[i] = 0xFFff00fe; //set alpha to 0xFF to make this pixel transparent
}

so in short: you did all right but mixed it up a bit ^^

This works:

在此处输入图片说明

private BufferedImage switchColors(BufferedImage img) {
    int w = img.getWidth();
    int h = img.getHeight();
    BufferedImage bi = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
    // top left pixel is presumed to be BG color
    int rgb = img.getRGB(0, 0); 
    for (int xx=0; xx<w; xx++) {
        for (int yy=0; yy<h; yy++) {
            int rgb2 = img.getRGB(xx, yy);
            if (rgb2!=rgb) {
                bi.setRGB(xx, yy, rgb2);
            }
        }
    }

    return bi;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM