更改 BufferedImage 的 alpha 值? (Change the alpha value of a BufferedImage?)


問題描述

更改 BufferedImage 的 alpha 值? (Change the alpha value of a BufferedImage?)

How do I change the global alpha value of a BufferedImage in Java? (I.E. make every pixel in the image that has a alpha value of 100 have a alpha value of 80)

‑‑‑‑‑

參考解法

方法 1:

<p>@Neil Coffey:
Thanks, I've been looking for this too; however, Your code didn't work very well for me (white background became black).</p>

I coded something like this and it works perfectly:

public void setAlpha(byte alpha) {       
    alpha %= 0xff; 
    for (int cx=0;cx<obj_img.getWidth();cx++) {          
        for (int cy=0;cy<obj_img.getHeight();cy++) {
            int color = obj_img.getRGB(cx, cy);

            int mc = (alpha << 24) | 0x00ffffff;
            int newcolor = color & mc;
            obj_img.setRGB(cx, cy, newcolor);            

        }

    }
}

Where obj_img is BufferedImage.TYPE_INT_ARGB.

I change alpha with setAlpha((byte)125); alpha range is now 0‑255.

Hope someone finds this useful. 

方法 2:

I don't believe there's a single simple command to do this.  A few options:

  • copy into another image with an AlphaComposite specified (downside: not converted in place)
  • directly manipulate the raster (downside: can lead to unmanaged images)
  • use a filter or BufferedImageOp

The first is the simplest to implement, IMO.

方法 3:

This is an old question, so I'm not answering for the sake of the OP, but for those like me who find this question later.

AlphaComposite

As @Michael's excellent outline mentioned, an AlphaComposite operation can modify the alpha channel. But only in certain ways, which to me are somewhat difficult to understand:

is the formula for how the "over" operation affects the alpha channel. Moreover, this affects the RGB channels too, so if you have color data that needs to be unchanged, AlphaComposite is not the answer.

BufferedImageOps

LookupOp

There are several varieties of BufferedImageOp (see 4.10.6 here). In the more general case, the OP's task could be met by a LookupOp, which requires building lookup arrays. To modify only the alpha channel, supply an identity array (an array where table[i] = i) for the RGB channels, and a separate array for the alpha channel. Populate the latter array with table[i] = f(i), where f() is the function by which you want to map from old alpha value to new. E.g. if you want to "make every pixel in the image that has a alpha value of 100 have a alpha value of 80", set table[100] = 80. (The full range is 0 to 255.) See how to increase opacity in gaussian blur for a code sample.

RescaleOp

But for a subset of these cases, there is a simpler way to do it, that doesn't require setting up a lookup table. If f() is a simple, linear function, use a RescaleOp. For example, if you want to set newAlpha = oldAlpha ‑ 20, use a RescaleOp with a scaleFactor of 1 and an offset of ‑20. If you want to set newAlpha = oldAlpha * 0.8, use a scaleFactor of 0.8 and an offset of 0. In either case, you again have to provide dummy scaleFactors and offsets for the RGB channels:

new RescaleOp({1.0f, 1.0f, 1.0f, /* alpha scaleFactor */ 0.8f},
              {0f, 0f, 0f, /* alpha offset */ ‑20f}, null)

Again see 4.10.6 here for some examples that illustrate the principles well, but are not specific to the alpha channel.

Both RescaleOp and LookupOp allow modifying a BufferedImage in‑place.

方法 4:

for a nicer looking alpha change effect, you can use relative alpha change per pixel (rather than static set, or clipping linear)

public static void modAlpha(BufferedImage modMe, double modAmount) {
        //
    for (int x = 0; x < modMe.getWidth(); x++) {          
        for (int y = 0; y < modMe.getHeight(); y++) {
                //
            int argb = modMe.getRGB(x, y); //always returns TYPE_INT_ARGB
            int alpha = (argb >> 24) & 0xff;  //isolate alpha

            alpha *= modAmount; //similar distortion to tape saturation (has scrunching effect, eliminates clipping)
            alpha &= 0xff;      //keeps alpha in 0‑255 range

            argb &= 0x00ffffff; //remove old alpha info
            argb |= (alpha << 24);  //add new alpha info
            modMe.setRGB(x, y, argb);            
        }
    }
}

方法 5:

I'm 99% sure the methods that claim to deal with an "RGB" value packed into an int actually deal with ARGB. So you ought to be able to do something like:

for (all x,y values of image) {
  int argb = img.getRGB(x, y);
  int oldAlpha = (argb >>> 24);
  if (oldAlpha == 100) {
    argb = (80 << 24) | (argb & 0xffffff);
    img.setRGB(x, y, argb);
  }
}

For speed, you could maybe use the methods to retrieve blocks of pixel values.

(by WilliamFelixMichael Brewer‑DavisLarsHThumbzNeil Coffey)

參考文件

  1. Change the alpha value of a BufferedImage? (CC BY‑SA 3.0/4.0)

#java #graphics #bufferedimage






相關問題

電子郵件地址中帶有 + 字符的 Java 郵件 (Java mail with + character in email address)

如何快速原型化 Java 代碼? (How to quickly prototype Java code?)

如何使用 Maven 在目標(SVN-)服務器上創建 Javadoc? (How to create Javadoc on the target (SVN-) server using Maven?)

為什麼檢查二叉樹有效性的解決方案不起作用? (Why the solution for checking the validity of binary tree is not working?)

Selenium webdriver通過第一個數字找到texy (Selenium webdriver find texy by first digits)

setOnClickListener 沒有在圖像視圖上被調用 (setOnClickListener is not getting called on image view)

繪製多邊形:找不到錯誤 (Drawing Polygon : unable to find error)

半透明 JButton:對像出現在背景中 (Semi-Transparent JButton: Objects appear in Background)

比較同一數組的元素 (Compare elements of the same array)

Java 屏幕截圖小程序 (Java screen capture applet)

Minecraft 1.8.9 Forge Modding 的Java 開發工具包,需要什麼JDK/JRE,代碼是否正確? (Java Development Kit with Minecraft 1.8.9 Forge Modding, What JDK/JRE Is Needed, Is Code Correct?)

java while (resultset.next()) 不返回同一列中的所有數據 (java while (resultset.next()) does not return all data in the same column)







留言討論