Java에서 이미지 색상화
-
09-06-2019 - |
문제
Java에서 이미지를 색칠하기 위한 일부 코드를 작업 중입니다.기본적으로 제가 하고 싶은 것은 김프의 colorize 명령을 따르는 것입니다. 따라서 BufferedImage와 Color가 있으면 주어진 색상으로 이미지를 색칠할 수 있습니다.누구든지 아이디어가 있나요?이와 같은 작업을 수행하는 현재 최선의 추측은 BufferedImage의 각 픽셀의 rgb 값을 가져오고 일부 배율 인수를 사용하여 Color의 RGB 값을 추가하는 것입니다.
해결책
나는 김프의 colorize 명령을 사용한 적이 없습니다.그러나 각 픽셀의 RGB 값을 가져와서 여기에 RGB 값을 추가하는 경우에는 실제로 조회작업. 다음은 BufferedImageOp를 BufferedImage에 적용하기 위해 작성한 코드입니다.
위의 Nicks 예제를 사용하여 수행하는 방법은 다음과 같습니다.
각 픽셀에 대해 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 colorizeFilter = createColorizeOp(R1, G1, B1);
BufferedImage targetImage = colorizeFilter.filter(sourceImage, null);
이것이 당신이 찾고 있는 것이 아니라면 BufferedImageOp를 더 자세히 살펴보는 것이 좋습니다.
이는 또한 다른 이미지에 대해 여러 번 계산을 수행할 필요가 없기 때문에 더 효율적입니다.또는 R1,G1,B1 값이 변경되지 않는 한 다른 BufferedImages에서 계산을 다시 수행하십시오.
다른 팁
허락하다 Y = 0.3*R + 0.59*G + 0.11*B
이미지의 각 픽셀에 대해 다음과 같이 설정합니다.
((R1+Y)/2,(G1+Y)/2,(B1+Y)/2)
만약에 (R1,G1,B1)
당신이 색칠하고 있는 것입니다.
이는 김프의 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;
}
}
나는 질문 포스터가 하고 싶었던 것과 똑같은 일을 하고 싶었지만 위의 변환은 김프처럼 색상을 제거하지 못했습니다(예: 빨간색 오버레이가 있는 녹색이 불쾌한 갈색 색상을 만드는 등).그래서 김프의 소스 코드를 다운로드하고 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() );
}
}
}