Colorizing images in Java

前端 未结 4 1775
隐瞒了意图╮
隐瞒了意图╮ 2020-12-03 23:52

I\'m working on some code to colorize an image in Java. Basically what I\'d like to do is something along the lines of GIMP\'s colorize command, so that if I have a Buffered

相关标签:
4条回答
  • 2020-12-04 00:28

    This works exactly like the Colorize function in GIMP and it preserves the transparency. I've also added a few things like Contrast and Brightness, Hue, Sat, and Luminosity - 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;
        }
    }
    
    0 讨论(0)
  • 2020-12-04 00:32

    I have never used GIMP's colorize command. However, if your getting the RGB value of each pixel and adding RGB value to it you should really use a LookupOp. Here is some code that I wrote to apply a BufferedImageOp to a BufferedImage.

    Using Nicks example from above heres how I would do it.

    Let Y = 0.3*R + 0.59*G + 0.11*B for each pixel

    (R1,G1,B1) is what you are colorizing with

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

    It creates a BufferedImageOp that will mask out each color if the mask boolean is true.

    Its simple to call too.

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

    If this is not what your looking for I suggest you look more into BufferedImageOp's.

    This is would also be more efficient since you would not need to do the calculations multiple times on different images. Or do the calculations over again on different BufferedImages as long as the R1,G1,B1 values don't change.

    0 讨论(0)
  • 2020-12-04 00:34

    Let Y = 0.3*R + 0.59*G + 0.11*B for each pixel in the image, then set them to be

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

    if (R1,G1,B1) is what you are colorizing with.

    0 讨论(0)
  • 2020-12-04 00:43

    I wanted to do the exact same thing as the question poster wanted to do but the above conversion did not remove colors like the GIMP does (ie green with a red overlay made an unpleasant brown color etc). So I downloaded the source code for GIMP and converted the c code over to Java.

    Posting it in this thread just in case anyone else wants to do the same (since it is the first thread that comes up in Google). The conversion still changes the white color when it should not, it's probably a casting issue from double to int. The class converts a BufferedImage in-place.

    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() );
    
          }
       }
    }
    
    0 讨论(0)
提交回复
热议问题