PDA

View Full Version : [JAVA]Variazione di colore


MEMon
01-10-2006, 11:34
Esiste un modo semplice per far variare un colore da un azzuro "cielo di giorno" a un blu "notte"?
Lavorare sui canali RGB non è semplicissimo in quanto in una variazione del genere cambiano tutti e 3 e in modo differente(uno cambia più velocemente dell'altro).

andbin
01-10-2006, 13:26
Esiste un modo semplice per far variare un colore da un azzuro "cielo di giorno" a un blu "notte"?
Lavorare sui canali RGB non è semplicissimo in quanto in una variazione del genere cambiano tutti e 3 e in modo differente(uno cambia più velocemente dell'altro).Ma vuoi ottenere un gradiente di N colori ottenuti "interpolando" i due colori? O vuoi cambiare tinta e luminosità ad un colore?

MEMon
01-10-2006, 13:29
Vorrei cambare tinta e luminosità allo stesso colore!C'è qaulche modo veloce?

mastoo
01-10-2006, 13:29
ma non puoi partire da un colore tipo
r=0
g=255
b=255
che è l'azzurro
poi diminuisci gradatamente il verde fino a 0
e dopo fai lo stesso con il blu fino al valore che vuoi tu fino ad arrivare al nero

MEMon
01-10-2006, 13:30
Si ma così facendo incontro dei colori non desiderati!

mastoo
01-10-2006, 13:37
potresti crearti una tabella dei colori che deve assumere il tuo cielo

MEMon
01-10-2006, 13:38
Si infatti se nn trovo un metodo migliore mi sa che farò così

MEMon
01-10-2006, 13:59
Ho risolto con l'AlphaCompiste!

MEMon
01-10-2006, 14:31
Azz no non va bene! mi calano le prestazioni in modo incredibile!
uff...

PGI-Bis
01-10-2006, 15:39
La tabella dei colori suggerita da mastoo è la soluzione che mi sconfiffera di più perchè ti consente di generare i colori in un momento della vita dell'applicazione in cui puoi non considerare di primaria importanza il tempo di risposta.

Il problema è quello esposto da andbin: che colori ti servono?

Adesso però abbiamo l'indizio di un indizio: AlphaComposite andava bene.

Supponendo che la regola di composizione fosse SRC_OVER (predefinita) e che la variazione di colore sia stata ottenuta attraverso la variazione dell'attributo di trasparenza e che lo sfondo della proiezione fosse nero (quante supposizioni... :D) allora sospetto che ciò che hai ottenuto sia il prodotto di un'interpolazione lineare di due colori HSB1(h, s, 0) e HSB2(h, s, 1).

In questo caso non devi fare altro che pre-calcolare tale variazione e infilarla in una bella mappona da cui poi prelevi a mani basse il colore che, di volta in volta, vorrai usare.

Siccome non ho voglia di fare quello che dovrei fare (:D) ho scritto un esempio di possibili interpolazioni tra due colori che potrebbero anche esserti utili. C'è un gradiente (interpolazione lineare tra i valori RGB di due colori), un illuminazione (interpolazione lineare tra due colori HS(B= 0) e HS(B=1)) e un'interpolazione lineare tra i valori H e B di due colori HSB.

package it.tukano.bandsample;

import java.awt.*;
import java.awt.image.*;
import javax.imageio.*;
import javax.swing.*;

public class BandSample {

public static void main(String[] args) {
gradienteriziorizza(new Color(0, 0, 98), new Color(217, 252, 255));
illuminazionalizza(new Color(0, 0, 1)); //blu scurissimo
mescolizza(new Color(0, 0, 98), new Color(232, 251, 255));
}

private static void gradienteriziorizza(Color start, Color end) {
final int IMAGE_WIDTH = 128;
final int IMAGE_HEIGHT = 128;
float[] rgbStart = start.getRGBComponents(null);
float[] rgbEnd = end.getRGBComponents(null);
final float redOne = rgbStart[0];
final float greenOne = rgbStart[1];
final float blueOne = rgbStart[2];
final float redTwo = rgbEnd[0];
final float greenTwo = rgbEnd[1];
final float blueTwo = rgbEnd[2];
final float redStep = (redTwo - redOne) / (IMAGE_HEIGHT - 1);
final float greenStep = (greenTwo - greenOne) / (IMAGE_HEIGHT - 1);
final float blueStep = (blueTwo - blueOne) / (IMAGE_HEIGHT - 1);
BufferedImage canvas = new BufferedImage(IMAGE_WIDTH, IMAGE_HEIGHT,
BufferedImage.TYPE_INT_RGB);
Graphics g = canvas.getGraphics();
for(int i = 0; i < canvas.getHeight(); i++) {
Color c = new Color(
redOne + i * redStep,
greenOne + i * greenStep,
blueOne + i * blueStep,
1f);
g.setColor(c);
g.drawLine(0, i, IMAGE_WIDTH, i);
}
projectWindow(canvas, "Interpola");
}

private static void mescolizza(Color start, Color end) {
final int IMAGE_WIDTH = 128;
final int IMAGE_HEIGHT = 128;
BufferedImage canvas = new BufferedImage(IMAGE_WIDTH, IMAGE_HEIGHT,
BufferedImage.TYPE_INT_RGB);
float[] startHSB = Color.RGBtoHSB(start.getRed(), start.getGreen(),
start.getBlue(), null);
float[] endHSB = Color.RGBtoHSB(end.getRed(), end.getGreen(),
end.getBlue(), null);
final float SATURATION = Math.max(startHSB[1], endHSB[1]);
final float HUE_STEP = (endHSB[0] - startHSB[0]) / (IMAGE_HEIGHT - 1);
final float BRIGHTNESS_STEP = 1f / (IMAGE_HEIGHT - 1);
final float HUE_START = startHSB[0];
final float BRIGHTNESS_START = 0f;
Graphics g = canvas.getGraphics();
for(int i = 0; i < canvas.getHeight(); i++) {
float brightness = BRIGHTNESS_START + i * BRIGHTNESS_STEP;
float hue = HUE_START + i * HUE_STEP;
g.setColor(Color.getHSBColor(hue, SATURATION, brightness));
g.drawLine(0, i, IMAGE_WIDTH - 1, i);
}
projectWindow(canvas, "Combina");
}

private static void illuminazionalizza(Color base) {
float[] baseHSB = Color.RGBtoHSB(base.getRed(), base.getGreen(),
base.getBlue(), null);
final int IMAGE_WIDTH = 128;
final int IMAGE_HEIGHT = 128;
final float HUE = baseHSB[0];
final float SATURATION = baseHSB[1];
final float BRIGHTNESS = baseHSB[2];
BufferedImage canvas = new BufferedImage(IMAGE_WIDTH, IMAGE_HEIGHT,
BufferedImage.TYPE_INT_RGB);
//luminosità da 0 (prima linea) a 1 (ultima linea)
float brightStep = (1f - BRIGHTNESS) / (canvas.getHeight() - 1);
Graphics g = canvas.getGraphics();
for(int i = 0; i < canvas.getHeight(); i++) {
float brightness = BRIGHTNESS + i * brightStep;
g.setColor(Color.getHSBColor(HUE, SATURATION, brightness));
g.drawLine(0, i, IMAGE_WIDTH - 1, i);
}
projectWindow(canvas, "Illumina");
}

private static void projectWindow(BufferedImage canvas, String title) {
//rifila l'immagine ad un'etichetta propinata a una finestra
JLabel screen = new JLabel(new ImageIcon(canvas));
JFrame window = new JFrame();
window.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
window.add(screen);
window.setTitle(title);
//apre la finestra
final JFrame windowRef = window;
SwingUtilities.invokeLater(new Runnable() {
public void run() {
windowRef.pack();
windowRef.setResizable(false);
windowRef.setVisible(true);
}
});
}
}

Chi riesce a pronunciare i nomi dei tre metodi statici tutto d'un fiato vince :D.

MEMon
01-10-2006, 15:42
heheh grande pgi come al solito!!!Grazie mille.

Ormai ho una versione semi giocabile del mio giochino, penso che entro sera riesco a farvi vedere qualcosa se vi interessa! :)

andbin
01-10-2006, 15:48
Se può essere utile, per effettuare il "blending" di due colori, si può fare così:
public static Color blendColors (Color color1, Color color2, float perc)
{
float[] rgb1 = color1.getRGBColorComponents (null);
float[] rgb2 = color2.getRGBColorComponents (null);

float percInv;

if (perc < 0.0f)
perc = 0.0f;
else if (perc > 1.0f)
perc = 1.0f;

percInv = 1.0f - perc;

return new Color (percInv * rgb1[0] + perc * rgb2[0],
percInv * rgb1[1] + perc * rgb2[1],
percInv * rgb1[2] + perc * rgb2[2]);
}

MEMon
01-10-2006, 15:52
sisisisi grazie!