Java での画像の色付け
-
09-06-2019 - |
質問
Javaで画像に色を付けるコードを作成しています。基本的に私がやりたいことは、GIMP の colorize コマンドに沿ったもので、BufferedImage と Color があれば、指定された色で画像を色付けできます。何かアイデアがある人はいますか?このようなことを行うための私の現時点での最善の推測は、BufferedImage の各ピクセルの RGB 値を取得し、それに何らかのスケーリング係数を使用して Color の RGB 値を追加することです。
解決
GIMPのcolorizeコマンドを使ったことはありません。ただし、各ピクセルの RGB 値を取得し、それに RGB 値を追加する場合は、実際には ルックアップ操作. 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 マスクブール値が true の場合、各色がマスクされます。
呼び出すのも簡単です。
BufferedImageOp colorizeFilter = createColorizeOp(R1, G1, B1);
BufferedImage targetImage = colorizeFilter.filter(sourceImage, null);
これが探しているものではない場合は、BufferedImageOp について詳しく調べることをお勧めします。
これは、異なる画像に対して何度も計算を行う必要がないため、より効率的です。または、R1、G1、B1 の値が変わらない限り、別の BufferedImage に対して計算を再度実行します。
他のヒント
させて Y = 0.3*R + 0.59*G + 0.11*B
画像内の各ピクセルに対して、次のように設定します。
((R1+Y)/2,(G1+Y)/2,(B1+Y)/2)
もし (R1,G1,B1)
色付けしているものです。
これは GIMP の Colorize 機能とまったく同じように機能し、透明度が維持されます。コントラストと明るさ、色相、土、明度なども追加しました - 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;
}
}
質問投稿者がやりたかったこととまったく同じことをやりたかったのですが、上記の変換では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() );
}
}
}