Javaの画像に色合いを適用します
-
27-09-2019 - |
質問
私は自分のプログラムにいくつかの同様の視覚スタイルを作成しようとしています。それぞれが異なる色のテーマを持っています。これを行うために、私はアイコンの使用を実装して、 JCheckBox
砂 JRadioButton
s。すべての可能な色に1つの完全なアイコンを作成する代わりに、1つのセットを取得して、画像の色相/彩度/光度/アルファを表示する前に変更する方法はありますか?
解決
方法がありますが、いくつかの緩衝距離変換を利用する必要があります。作成したら、キャッシュするか、後で簡単に再利用できるようにします。基本的に、アルファ層のみを使用してピクセルをオフにするブラック画像(ソースカラー#000000)から始めたいと思います(また、スムーズなアンチエイリアスを提供します)。たとえば、ソース画像では、すべてのピクセルが黒ですが、アルファチャネルはピクセルからピクセルまで異なります。
まず、いくつかの背景情報については、この記事を読んでください。 http://www.javalobby.org/articles/ultimate-image/
そのプライマーが完了したら、画像をBufferedImageにロードする必要があります。
BufferedImage loadImg = ImageUtil.loadImage("C:/Images/myimg.png");
次に、次のように変換するために新しいbufferedimageを作成する必要があります。
public BufferedImage colorImage(BufferedImage loadImg, int red, int green, int blue) {
BufferedImage img = new BufferedImage(loadImg.getWidth(), loadImg.getHeight(),
BufferedImage.TRANSLUCENT);
Graphics2D graphics = img.createGraphics();
Color newColor = new Color(red, green, blue, 0 /* alpha needs to be zero */);
graphics.setXORMode(newColor);
graphics.drawImage(loadImg, null, 0, 0);
graphics.dispose();
return img;
}
基本的に、SetXormodeは、ソース画像の色で提供する色をXorします。ソースイメージが黒い場合、指定したときに提供する色が書かれます。アルファチャネルに「0」を使用する新しい色では、元のアルファチャネル値が尊重されます。最終結果は、あなたが探している複合です。
編集:
2つの方法のいずれかで最初の緩衝液をロードできます。最も簡単なのは、Javaの新しいImageio APIを使用することです。 http://download.oracle.com/javase/6/docs/api/javax/imageio/imageio.html ファイルをBufferEdImageに直接ロードします。呼び出しは次のようになります:
BufferedImage img = ImageIO.read(url);
または、Toolkitを使用して画像を読み取る方法を作成することもできます。
public BufferedImage loadImage(String url) {
ImageIcon icon = new ImageIcon(url);
Image image = icon.getImage();
// Create empty BufferedImage, sized to Image
BufferedImage buffImage =
new BufferedImage(
image.getWidth(null),
image.getHeight(null),
BufferedImage.TYPE_INT_ARGB);
// Draw Image into BufferedImage
Graphics g = buffImage.getGraphics();
g.drawImage(image, 0, 0, null);
return buffImage;
}
もちろん、あなたが注意を払うなら、私たちはまったく同じことをして、私たちがそれを色にするのと同じように、バッファーされた画像に画像を読む必要があります。要するに、の署名を変更した場合 colorImage
受け入れる方法 Image
オブジェクトgetWidth()およびgetheight()メソッドにいくつかの変更を加えるだけで、それを動作させる必要があります。
他のヒント
public static void tint(BufferedImage img) {
for (int x = 0; x < img.getWidth(); x++) {
for (int y = 0; y < img.getHeight(); y++) {
Color color = new Color(img.getRGB(x, y));
// do something with the color :) (change the hue, saturation and/or brightness)
// float[] hsb = new float[3];
// Color.RGBtoHSB(color.getRed(), old.getGreen(), old.getBlue(), hsb);
// or just call brighter to just tint it
Color brighter = color.brighter();
img.setRGB(x, y, brighter.getRGB());
}
}
}
これを行う最も簡単な方法は、 JHラボによる画像フィルター. 。呼び出してHSBを調整するだけで、
public BufferedImage setHSB(BufferedImage source, float hValue, float sValue, float bValue) {
com.jhlabs.image.HSBAdjustFilter hsb hsb = new HSBAdjustFilter();
BufferedImage destination = hsb.createCompatibleDestImage(source, null);
hsb.setHFactor(hValue);
hsb.setSFactor(sValue);
hsb.setBFactor(bValue);
BufferedImage result = hsb.filter(bi, destination);
return result;
}
各色コンポーネントの平均を計算し、元のアルファを保持するには:
public static void tint(BufferedImage image, Color color) {
for (int x = 0; x < image.getWidth(); x++) {
for (int y = 0; y < image.getHeight(); y++) {
Color pixelColor = new Color(image.getRGB(x, y), true);
int r = (pixelColor.getRed() + color.getRed()) / 2;
int g = (pixelColor.getGreen() + color.getGreen()) / 2;
int b = (pixelColor.getBlue() + color.getBlue()) / 2;
int a = pixelColor.getAlpha();
int rgba = (a << 24) | (r << 16) | (g << 8) | b;
image.setRGB(x, y, rgba);
}
}
}
これは私の場合に最適です。
私はこのページですべてのソリューションを試しましたが、運がありませんでした。 Xor One(受け入れられた答え)は私にとってはうまくいきませんでした - 私が議論として何を議論として与えていた色の代わりに奇妙な黄色の色を着色しました。少し乱雑ですが、私はついに私のために働くアプローチを見つけました。他の誰かが他のソリューションで私と同じ問題を抱えている場合に備えて、私はそれを追加しました。乾杯!
/** Tints the given image with the given color.
* @param loadImg - the image to paint and tint
* @param color - the color to tint. Alpha value of input color isn't used.
* @return A tinted version of loadImg */
public static BufferedImage tint(BufferedImage loadImg, Color color) {
BufferedImage img = new BufferedImage(loadImg.getWidth(), loadImg.getHeight(),
BufferedImage.TRANSLUCENT);
final float tintOpacity = 0.45f;
Graphics2D g2d = img.createGraphics();
//Draw the base image
g2d.drawImage(loadImg, null, 0, 0);
//Set the color to a transparent version of the input color
g2d.setColor(new Color(color.getRed() / 255f, color.getGreen() / 255f,
color.getBlue() / 255f, tintOpacity));
//Iterate over every pixel, if it isn't transparent paint over it
Raster data = loadImg.getData();
for(int x = data.getMinX(); x < data.getWidth(); x++){
for(int y = data.getMinY(); y < data.getHeight(); y++){
int[] pixel = data.getPixel(x, y, new int[4]);
if(pixel[3] > 0){ //If pixel isn't full alpha. Could also be pixel[3]==255
g2d.fillRect(x, y, 1, 1);
}
}
}
g2d.dispose();
return img;
}
これはまさに色合いではなく、別のレイヤーを適用するようなものですが、私には機能します。
public static BufferedImage colorImage(BufferedImage loadImg, int red, int green, int blue, int alpha /*Also the intesity*/) {
Graphics g = loadImg.getGraphics();
g.setColor(new Color(red, green, blue, alpha));
g.fillRect(0, 0, loadImg.getWidth(), loadImg.getHeight());
g.dispose();
return loadImg;
}
何らかの理由で私が見つけたすべての方法が私にはうまくいかなかったので、これにこれにアプローチする簡単な方法があります(余分なLIBSは必要ありません):
/**
* Colors an image with specified color.
* @param r Red value. Between 0 and 1
* @param g Green value. Between 0 and 1
* @param b Blue value. Between 0 and 1
* @param src The image to color
* @return The colored image
*/
protected BufferedImage color(float r, float g, float b, BufferedImage src) {
// Copy image ( who made that so complicated :< )
BufferedImage newImage = new BufferedImage(src.getWidth(), src.getHeight(), BufferedImage.TRANSLUCENT);
Graphics2D graphics = newImage.createGraphics();
graphics.drawImage(src, 0, 0, null);
graphics.dispose();
// Color image
for (int i = 0; i < newImage.getWidth(); i++) {
for (int j = 0; j < newImage.getHeight(); j++) {
int ax = newImage.getColorModel().getAlpha(newImage.getRaster().getDataElements(i, j, null));
int rx = newImage.getColorModel().getRed(newImage.getRaster().getDataElements(i, j, null));
int gx = newImage.getColorModel().getGreen(newImage.getRaster().getDataElements(i, j, null));
int bx = newImage.getColorModel().getBlue(newImage.getRaster().getDataElements(i, j, null));
rx *= r;
gx *= g;
bx *= b;
newImage.setRGB(i, j, (ax << 24) | (rx << 16) | (gx << 8) | (bx << 0));
}
}
return newImage;
}
黒い画像がそうなるでしょう いつも 黒を維持しますが、白い画像はあなたが指定する色になります。この方法は、すべてのピクセルを通過し、画像の赤い緑と青の値にパラメーターを掛けます。これは、OpenGLの正確な動作です glcolor3f() 方法。 r、gおよびb paramsは0.0fから1.0fでなければなりません。
この方法は、アルファ値に問題はありません。