Derry
Derry

Reputation: 371

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. this what the sprite looks like

Upvotes: 0

Views: 80

Answers (3)

Erwin Bolwidt
Erwin Bolwidt

Reputation: 31279

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

Upvotes: 3

Andrew Thompson
Andrew Thompson

Reputation: 168825

This works:

enter image description here

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;
}

Upvotes: 1

Martin Frank
Martin Frank

Reputation: 3454

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 ^^

Upvotes: 1

Related Questions