5

我正在编写一些代码来为 Java 中的图像着色。基本上我想做的是与 GIMP 的 colorize 命令类似的东西,所以如果我有一个 BufferedImage 和一个颜色,我可以用给定的颜色为图像着色。有人有什么想法吗?我目前对做这样的事情的最佳猜测是获取 BufferedImage 中每个像素的 rgb 值,并使用一些缩放因子将 Color 的 RGB 值添加到其中。

4

4 回答 4

7

Y = 0.3*R + 0.59*G + 0.11*B图像中的每个像素,然后将它们设置为

((R1+Y)/2,(G1+Y)/2,(B1+Y)/2)

如果(R1,G1,B1)是你正在着色的东西。

于 2008-08-23T00:32:58.317 回答
4

我从未使用过 GIMP 的 colorize 命令。但是,如果您获取每个像素的 RGB 值并向其添加 RGB 值,则您应该真正使用LookupOp这是我编写的一些代码,用于将 BufferedImageOp 应用于 BufferedImage。

使用上面的尼克斯示例,我将如何做到这一点。

让每个像素的 Y = 0.3*R + 0.59*G + 0.11*B

(R1,G1,B1) 是你用来着色的

protected LookupOp createColorizeOp(short R1, short G1, short B1) {
    short[] alpha = new short[256];
    short[] red = new short[256];
    short[] green = new short[256];
    short[] blue = new short[256];

    int Y = 0.3*R + 0.59*G + 0.11*B

    for (short i = 0; i < 256; i++) {
        alpha[i] = i;
        red[i] = (R1 + i*.3)/2;
        green[i] = (G1 + i*.59)/2;
        blue[i] = (B1 + i*.11)/2;
    }

    short[][] data = new short[][] {
            red, green, blue, alpha
    };

    LookupTable lookupTable = new ShortLookupTable(0, data);
    return new LookupOp(lookupTable, null);
}

它创建一个BufferedImageOp,如果掩码布尔值为真,它将屏蔽每种颜色。

调用也很简单。

BufferedImageOp colorizeFilter = createColorizeOp(R1, G1, B1);
BufferedImage targetImage = colorizeFilter.filter(sourceImage, null);

如果这不是您要寻找的东西,我建议您更多地研究 BufferedImageOp。

这也会更有效,因为您不需要对不同的图像进行多次计算。或者只要 R1、G1、B1 值不变,就对不同的 BufferedImage 重新计算。

于 2008-08-26T01:02:32.793 回答
2

这与 GIMP 中的着色功能完全一样,它保留了透明度。我还添加了一些东西,例如对比度和亮度、色相、饱和度和亮度 - 0circle0 Google Me --> 'Sprite Creator 3'

import java.awt.Color;
import java.awt.image.BufferedImage;

public class Colorizer
{
    public static final int MAX_COLOR = 256;

    public static final float LUMINANCE_RED = 0.2126f;
    public static final float LUMINANCE_GREEN = 0.7152f;
    public static final float LUMINANCE_BLUE = 0.0722f;

    double hue = 180;
    double saturation = 50;
    double lightness = 0;

    int[] lum_red_lookup;
    int[] lum_green_lookup;
    int[] lum_blue_lookup;

    int[] final_red_lookup;
    int[] final_green_lookup;
    int[] final_blue_lookup;

    public Colorizer()
    {
        doInit();
    }

    public void doHSB(double t_hue, double t_sat, double t_bri, BufferedImage image)
    {
        hue = t_hue;
        saturation = t_sat;
        lightness = t_bri;
        doInit();
        doColorize(image);
    }

    private void doInit()
    {
        lum_red_lookup = new int[MAX_COLOR];
        lum_green_lookup = new int[MAX_COLOR];
        lum_blue_lookup = new int[MAX_COLOR];

        double temp_hue = hue / 360f;
        double temp_sat = saturation / 100f;

        final_red_lookup = new int[MAX_COLOR];
        final_green_lookup = new int[MAX_COLOR];
        final_blue_lookup = new int[MAX_COLOR];

        for (int i = 0; i < MAX_COLOR; ++i)
        {
            lum_red_lookup[i] = (int) (i * LUMINANCE_RED);
            lum_green_lookup[i] = (int) (i * LUMINANCE_GREEN);
            lum_blue_lookup[i] = (int) (i * LUMINANCE_BLUE);

            double temp_light = (double) i / 255f;

            Color color = new Color(Color.HSBtoRGB((float) temp_hue, (float) temp_sat, (float) temp_light));

            final_red_lookup[i] = (int) (color.getRed());
            final_green_lookup[i] = (int) (color.getGreen());
            final_blue_lookup[i] = (int) (color.getBlue());
        }
    }

    public void doColorize(BufferedImage image)
    {
        int height = image.getHeight();
        int width;

        while (height-- != 0)
        {
            width = image.getWidth();

            while (width-- != 0)
            {
                Color color = new Color(image.getRGB(width, height), true);

                int lum = lum_red_lookup[color.getRed()] + lum_green_lookup[color.getGreen()] + lum_blue_lookup[color.getBlue()];

                if (lightness > 0)
                {
                    lum = (int) ((double) lum * (100f - lightness) / 100f);
                    lum += 255f - (100f - lightness) * 255f / 100f;
                }
                else if (lightness < 0)
                {
                    lum = (int) (((double) lum * (lightness + 100f)) / 100f);
                }
                Color final_color = new Color(final_red_lookup[lum], final_green_lookup[lum], final_blue_lookup[lum], color.getAlpha());
                image.setRGB(width, height, final_color.getRGB());
            }
        }
    }

    public BufferedImage changeContrast(BufferedImage inImage, float increasingFactor)
    {
        int w = inImage.getWidth();
        int h = inImage.getHeight();

        BufferedImage outImage = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
        for (int i = 0; i < w; i++)
        {
            for (int j = 0; j < h; j++)
            {
                Color color = new Color(inImage.getRGB(i, j), true);
                int r, g, b, a;
                float fr, fg, fb;

                r = color.getRed();
                fr = (r - 128) * increasingFactor + 128;
                r = (int) fr;
                r = keep256(r);

                g = color.getGreen();
                fg = (g - 128) * increasingFactor + 128;
                g = (int) fg;
                g = keep256(g);

                b = color.getBlue();
                fb = (b - 128) * increasingFactor + 128;
                b = (int) fb;
                b = keep256(b);

                a = color.getAlpha();

                outImage.setRGB(i, j, new Color(r, g, b, a).getRGB());
            }
        }
        return outImage;
    }

    public BufferedImage changeGreen(BufferedImage inImage, int increasingFactor)
    {
        int w = inImage.getWidth();
        int h = inImage.getHeight();

        BufferedImage outImage = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);

        for (int i = 0; i < w; i++)
        {
            for (int j = 0; j < h; j++)
            {
                Color color = new Color(inImage.getRGB(i, j), true);
                int r, g, b, a;
                r = color.getRed();
                g = keep256(color.getGreen() + increasingFactor);
                b = color.getBlue();
                a = color.getAlpha();

                outImage.setRGB(i, j, new Color(r, g, b, a).getRGB());
            }
        }
        return outImage;
    }

    public BufferedImage changeBlue(BufferedImage inImage, int increasingFactor)
    {
        int w = inImage.getWidth();
        int h = inImage.getHeight();

        BufferedImage outImage = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);

        for (int i = 0; i < w; i++)
        {
            for (int j = 0; j < h; j++)
            {
                Color color = new Color(inImage.getRGB(i, j), true);
                int r, g, b, a;
                r = color.getRed();
                g = color.getGreen();
                b = keep256(color.getBlue() + increasingFactor);
                a = color.getAlpha();

                outImage.setRGB(i, j, new Color(r, g, b, a).getRGB());
            }
        }
        return outImage;
    }

    public BufferedImage changeRed(BufferedImage inImage, int increasingFactor)
    {
        int w = inImage.getWidth();
        int h = inImage.getHeight();

        BufferedImage outImage = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);

        for (int i = 0; i < w; i++)
        {
            for (int j = 0; j < h; j++)
            {
                Color color = new Color(inImage.getRGB(i, j), true);
                int r, g, b, a;
                r = keep256(color.getRed() + increasingFactor);
                g = color.getGreen();
                b = color.getBlue();
                a = color.getAlpha();

                outImage.setRGB(i, j, new Color(r, g, b, a).getRGB());
            }
        }
        return outImage;
    }

    public BufferedImage changeBrightness(BufferedImage inImage, int increasingFactor)
    {
        int w = inImage.getWidth();
        int h = inImage.getHeight();

        BufferedImage outImage = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);

        for (int i = 0; i < w; i++)
        {
            for (int j = 0; j < h; j++)
            {
                Color color = new Color(inImage.getRGB(i, j), true);

                int r, g, b, a;

                r = keep256(color.getRed() + increasingFactor);
                g = keep256(color.getGreen() + increasingFactor);
                b = keep256(color.getBlue() + increasingFactor);
                a = color.getAlpha();

                outImage.setRGB(i, j, new Color(r, g, b, a).getRGB());
            }
        }
        return outImage;
    }

    public int keep256(int i)
    {
        if (i <= 255 && i >= 0)
            return i;
        if (i > 255)
            return 255;
        return 0;
    }
}
于 2013-12-05T21:42:05.703 回答
1

我想做与问题发布者想做的完全相同的事情,但上面的转换并没有像 GIMP 那样去除颜色(即绿色和红色覆盖层会产生令人不快的棕色等)。所以我下载了 GIMP 的源代码并将 c 代码转换为 Java。

将其发布在此线程中,以防万一其他人也想做同样的事情(因为它是 Google 中出现的第一个线程)。转换在不应该的时候仍然会改变白色,这可能是从 double 到 int 的转换问题。该类就地转换 BufferedImage。

public class Colorize {

public static final int MAX_COLOR = 256;

public static final float LUMINANCE_RED   = 0.2126f;
public static final float LUMINANCE_GREEN = 0.7152f;
public static final float LUMINANCE_BLUE  = 0.0722f;

double hue        = 180;
double saturation =  50;
double lightness  =   0;

int [] lum_red_lookup;
int [] lum_green_lookup;
int [] lum_blue_lookup;

int [] final_red_lookup;
int [] final_green_lookup;
int [] final_blue_lookup;

public Colorize( int red, int green, int blue )
{
   doInit();
}

public Colorize( double t_hue, double t_sat, double t_bri )
{
   hue = t_hue;
   saturation = t_sat;
   lightness = t_bri;
   doInit();
}

public Colorize( double t_hue, double t_sat )
{
   hue = t_hue;
   saturation = t_sat;
   doInit();
}

public Colorize( double t_hue )
{
   hue = t_hue;
   doInit();
}

public Colorize()
{
   doInit();
}

private void doInit()
{
   lum_red_lookup   = new int [MAX_COLOR];
   lum_green_lookup = new int [MAX_COLOR];
   lum_blue_lookup  = new int [MAX_COLOR];

   double temp_hue = hue / 360f;
   double temp_sat = saturation / 100f;

   final_red_lookup   = new int [MAX_COLOR];
   final_green_lookup = new int [MAX_COLOR];
   final_blue_lookup  = new int [MAX_COLOR];

   for( int i = 0; i < MAX_COLOR; ++i )
   {
      lum_red_lookup  [i] = ( int )( i * LUMINANCE_RED );
      lum_green_lookup[i] = ( int )( i * LUMINANCE_GREEN );
      lum_blue_lookup [i] = ( int )( i * LUMINANCE_BLUE );

      double temp_light = (double)i / 255f;

      Color color = new Color( Color.HSBtoRGB( (float)temp_hue, 
                                               (float)temp_sat, 
                                               (float)temp_light ) );

      final_red_lookup  [i] = ( int )( color.getRed() );
      final_green_lookup[i] = ( int )( color.getGreen() );
      final_blue_lookup [i] = ( int )( color.getBlue() );
   }
}

public void doColorize( BufferedImage image )
{
   int height = image.getHeight();
   int width;

   while( height-- != 0 )
   {
      width = image.getWidth();

      while( width-- != 0 )
      {
         Color color = new Color( image.getRGB( width, height ) );

         int lum = lum_red_lookup  [color.getRed  ()] +
                   lum_green_lookup[color.getGreen()] +
                   lum_blue_lookup [color.getBlue ()];

         if( lightness > 0 )
         {
            lum = (int)((double)lum * (100f - lightness) / 100f);
            lum += 255f - (100f - lightness) * 255f / 100f;
         }
         else if( lightness < 0 )
         {
            lum = (int)(((double)lum * lightness + 100f) / 100f);
         }

         Color final_color = new Color( final_red_lookup[lum],
                                        final_green_lookup[lum],
                                        final_blue_lookup[lum],
                                        color.getAlpha() );

         image.setRGB( width, height, final_color.getRGB() );

      }
   }
}
于 2011-01-18T05:51:33.227 回答