【问题标题】:Change the alpha value of a BufferedImage?更改 BufferedImage 的 alpha 值?
【发布时间】:2009-03-19 00:07:45
【问题描述】:

如何在 Java 中更改 BufferedImage 的全局 alpha 值? (即让图像中每个 alpha 值为 100 的像素的 alpha 值为 80)

【问题讨论】:

    标签: java graphics bufferedimage


    【解决方案1】:

    @尼尔·科菲: 谢谢,我也在找这个;但是,您的代码对我来说效果不佳(白色背景变成了黑色)。

    我编写了这样的代码,并且效果很好:

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

    其中 obj_img 是 BufferedImage.TYPE_INT_ARGB。

    我用 setAlpha((byte)125); alpha 范围现在是 0-255。

    希望有人觉得这很有用。

    【讨论】:

    • 看起来不错。它的便携性如何?例如。 RGB 值是否保证保存在 color int 的最低 3 个字节中?
    【解决方案2】:

    我不相信有一个简单的命令可以做到这一点。几个选项:

    第一个是最容易实现的,IMO。

    【讨论】:

      【解决方案3】:

      这是一个老问题,所以我不是为了OP而回答,而是为了像我这样后来发现这个问题的人。

      AlphaComposite

      正如@Michael 出色的大纲所述,AlphaComposite 操作可以修改 Alpha 通道。但只是在某些方面,对我来说有点难以理解:

      是the formula,了解“over”操作如何影响 Alpha 通道。此外,这也会影响 RGB 通道,因此如果您有需要更改的颜色数据,AlphaComposite 不是答案。

      BufferedImageOps

      查找操作

      BufferedImageOp 有多种变体(请参阅4.10.6 here)。在更一般的情况下,LookupOp 可以满足 OP 的任务,这需要构建查找数组。要仅修改 Alpha 通道,请为 RGB 通道提供一个标识数组(其中 table[i] = i 的数组),并为 Alpha 通道提供一个单独的数组。用table[i] = f(i) 填充后一个数组,其中f() 是您想要从旧alpha 值映射到新alpha 值的函数。例如。如果您想“使图像中 alpha 值为 100 的每个像素的 alpha 值为 80”,请设置 table[100] = 80。 (完整范围为 0 到 255。)有关代码示例,请参阅 how to increase opacity in gaussian blur。

      重新缩放操作

      但是对于这些情况的一个子集,有一种更简单的方法可以做到这一点,不需要设置查找表。如果f() 是一个简单的线性函数,请使用RescaleOp。例如,如果要设置newAlpha = oldAlpha - 20,请使用比例因子为 1 且偏移量为 -20 的 RescaleOp。如果您想设置newAlpha = oldAlpha * 0.8,请使用 0.8 的 scaleFactor 和 0 的偏移量。无论哪种情况,您都必须再次为 RGB 通道提供虚拟的 scaleFactors 和偏移量:

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

      请再次参阅4.10.6 here 中的一些示例,这些示例很好地说明了原理,但并不特定于 Alpha 通道。

      RescaleOp 和 LookupOp 都允许就地修改 BufferedImage。

      【讨论】:

        【解决方案4】:

        为了获得更好看的 alpha 变化效果,您可以使用每个像素的相对 alpha 变化(而不是静态设置或线性剪裁)

        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】:

          我 99% 确定声称处理打包到 int 中的“RGB”值的方法实际上处理的是 ARGB。因此,您应该能够执行以下操作:

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

          为了速度,您可以使用这些方法来检索像素值块。

          【讨论】:

            【解决方案6】:

            您可能需要先将 BufferedImage 复制到 BufferedImage.TYPE_INT_ARGB 类型的图像。如果您的图像类型为BufferedImage.TYPE_INT_RGB,则不会正确设置 alpha 组件。如果您的 BufferedImage 是 BufferedImage.TYPE_INT_ARGB 类型,则下面的代码有效。 /** * Modifies each pixel of the BufferedImage so that the selected component (R, G, B, or A) * is adjusted by delta. Note: the BufferedImage must be of type BufferedImage.TYPE_INT_ARGB. * @param src BufferedImage of type BufferedImage.TYPE_INT_ARGB. * @param colorIndex 0=red, 1=green, 2=blue, 3= alpha * @param delta amount to change component * @return */ public static BufferedImage adjustAColor(BufferedImage src,int colorIndex, int delta) { int w = src.getWidth(); int h = src.getHeight(); assert(src.getType()==BufferedImage.TYPE_INT_ARGB); for (int y = 0; y < h; y++) for (int x = 0; x < w; x++) { int rgb = src.getRGB(x,y); java.awt.Color color= new java.awt.Color(rgb,true); int red=color.getRed(); int green=color.getGreen(); int blue=color.getBlue(); int alpha=color.getAlpha(); switch (colorIndex) { case 0: red=adjustColor(red,delta); break; case 1: green=adjustColor(green,delta); break; case 2: blue=adjustColor(blue,delta); break; case 3: alpha=adjustColor(alpha,delta); break; default: throw new IllegalStateException(); } java.awt.Color adjustedColor=new java.awt.Color(red,green,blue,alpha); src.setRGB(x,y,adjustedColor.getRGB()); int gottenColorInt=src.getRGB(x,y); java.awt.Color gottenColor=new java.awt.Color(gottenColorInt,true); assert(gottenColor.getRed()== red); assert(gottenColor.getGreen()== green); assert(gottenColor.getBlue()== blue); assert(gottenColor.getAlpha()== alpha); } return src; } private static int adjustColor(int value255, int delta) { value255+= delta; if (value255<0) { value255=0; } else if (value255>255) { value255=255; } return value255; }

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 2014-02-16
              • 2017-06-03
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2021-08-05
              • 1970-01-01
              相关资源
              最近更新 更多