Comment puis-je changer le global alpha de la valeur d'un BufferedImage en Java? (I. E. faire de chaque pixel de l'image a une valeur alpha de 100 ont une valeur alpha de 80)
C'est une vieille question, donc je ne suis pas de réponse pour le bien de l'OP, mais pour ceux comme moi qui trouvent que cette question plus tard.
AlphaComposite
@Michael excellent aperçu mentionné, un AlphaComposite opération peut modifier le canal alpha. Mais d'une certaine façon, qui pour moi, sont un peu difficiles à comprendre:
est la formule de la façon dont les "plus" de l'opération affecte le canal alpha. En outre, cela affecte les canaux RVB trop, donc si vous avez des données de couleur qui doit être inchangée, AlphaComposite n'est pas la réponse.
BufferedImageOps
LookupOp
Il existe plusieurs variétés de BufferedImageOp (voir 4.10.6 ici). Dans le cas plus général, l'OP de la tâche pourrait être satisfaite par un LookupOp, ce qui nécessite la mise en place de recherche de tableaux. Pour modifier uniquement le canal alpha, la fourniture d'une identité matrice (un tableau où le tableau[i] = i) pour les canaux RVB, et un tableau séparé pour le canal alpha. Remplir le dernier tableau avec table[i] = f(i), où f() est la fonction par laquelle vous voulez la carte de la vieille valeur alpha à nouveau. E. g. si vous voulez "faire de chaque pixel de l'image a une valeur alpha de 100 ont une valeur alpha de 80",table[100] = 80. (Toute la gamme de 0 à 255.) Voir comment faire pour augmenter l'opacité dans le flou gaussien pour un exemple de code.
RescaleOp
Mais pour un sous-ensemble de ces cas, il y a un moyen plus simple de le faire, que ne pas exiger la mise en place d'une table de recherche. Si f() est une simple fonction linéaire, l'utilisation d'un RescaleOp. Par exemple, si vous souhaitez définir newAlpha = oldAlpha - 20, utiliser un RescaleOp avec un scaleFactor de 1 et un décalage de -20. Si vous souhaitez définir newAlpha = oldAlpha * 0.8, utiliser un scaleFactor de 0,8 et un offset de 0. Dans les deux cas, vous avez à fournir mannequin scaleFactors et les décalages pour les canaux RVB:
pour un plus agréable à la recherche d'alpha effet de changement, vous pouvez utiliser par rapport alpha changement par pixel (plutôt que de l'ensemble statique, ou d'écrêtage linéaire)
publicstaticvoid modAlpha(BufferedImage modMe,double modAmount){//for(int x =0; x < modMe.getWidth(); x++){for(int y =0; y < modMe.getHeight(); y++){//int argb = modMe.getRGB(x, y);//always returns TYPE_INT_ARGBint alpha =(argb >>24)&0xff;//isolate alpha
alpha *= modAmount;//similar distortion to tape saturation (has scrunching effect, eliminates clipping)
alpha &=0xff;//keeps alpha in 0-255 range
argb &=0x00ffffff;//remove old alpha info
argb |=(alpha <<24);//add new alpha info
modMe.setRGB(x, y, argb);}}}
Je suis sûr à 99% que les méthodes qui prétendent traiter avec un "RVB" valeur emballé dans un int fait affaire avec ARGB. Donc, vous devriez être en mesure de faire quelque chose comme:
for(all x,y values of image){int argb = img.getRGB(x, y);int oldAlpha =(argb >>>24);if(oldAlpha ==100){
argb =(80<<24)|(argb &0xffffff);
img.setRGB(x, y, argb);}}
Pour la vitesse, vous pourriez peut-être utiliser les méthodes pour récupérer des blocs de valeurs de pixel.
Vous devrez peut-être de la première copie de votre BufferedImage à une image de type BufferedImage.TYPE_INT_ARGB. Si votre image est de type, disons, BufferedImage.TYPE_INT_RGB, alors la composante alpha ne sera pas réglé correctement. Si votre BufferedImage est de type BufferedImage.TYPE_INT_ARGB, puis le code ci-dessous fonctionne.
/**
* Modifies each pixel of the BufferedImage so that the selected component (R, G, B, or A)
* is adjusted by delta. Note: the BufferedImage must be of type BufferedImage.TYPE_INT_ARGB.
* @param src BufferedImage of type BufferedImage.TYPE_INT_ARGB.
* @param colorIndex 0=red, 1=green, 2=blue, 3= alpha
* @param delta amount to change component
* @return
*/
public static BufferedImage adjustAColor(BufferedImage src,int colorIndex, int delta) {
int w = src.getWidth();
int h = src.getHeight();
assert(src.getType()==BufferedImage.TYPE_INT_ARGB);
for (int y = 0; y < h; y++)
for (int x = 0; x < w; x++) {
int rgb = src.getRGB(x,y);
java.awt.Color color= new java.awt.Color(rgb,true);
int red=color.getRed();
int green=color.getGreen();
int blue=color.getBlue();
int alpha=color.getAlpha();
switch (colorIndex) {
case 0: red=adjustColor(red,delta); break;
case 1: green=adjustColor(green,delta); break;
case 2: blue=adjustColor(blue,delta); break;
case 3: alpha=adjustColor(alpha,delta); break;
default: throw new IllegalStateException();
}
java.awt.Color adjustedColor=new java.awt.Color(red,green,blue,alpha);
src.setRGB(x,y,adjustedColor.getRGB());
int gottenColorInt=src.getRGB(x,y);
java.awt.Color gottenColor=new java.awt.Color(gottenColorInt,true);
assert(gottenColor.getRed()== red);
assert(gottenColor.getGreen()== green);
assert(gottenColor.getBlue()== blue);
assert(gottenColor.getAlpha()== alpha);
}
return src;
}
private static int adjustColor(int value255, int delta) {
value255+= delta;
if (value255<0) {
value255=0;
} else if (value255>255) {
value255=255;
}
return value255;
}
Je ne crois pas qu'il y a un simple et unique commande pour le faire. Quelques options:
La première est la plus simple à mettre en œuvre, de l'OMI.
OriginalL'auteur Michael Brewer-Davis
@Neil Coffey:
Merci, j'ai été la recherche de ce trop; cependant, Votre code ne fonctionne pas très bien pour moi (fond blanc est devenu noir).
J'ai codé quelque chose comme ça et ça fonctionne parfaitement:
Où obj_img est BufferedImage.TYPE_INT_ARGB.
- Je changer alpha avec setAlpha((byte)125); gamme alpha est maintenant de 0 à 255.
Espère que quelqu'un trouve cela utile.
color
int?OriginalL'auteur
C'est une vieille question, donc je ne suis pas de réponse pour le bien de l'OP, mais pour ceux comme moi qui trouvent que cette question plus tard.
AlphaComposite
@Michael excellent aperçu mentionné, un AlphaComposite opération peut modifier le canal alpha. Mais d'une certaine façon, qui pour moi, sont un peu difficiles à comprendre:
est la formule de la façon dont les "plus" de l'opération affecte le canal alpha. En outre, cela affecte les canaux RVB trop, donc si vous avez des données de couleur qui doit être inchangée, AlphaComposite n'est pas la réponse.
BufferedImageOps
LookupOp
Il existe plusieurs variétés de BufferedImageOp (voir 4.10.6 ici). Dans le cas plus général, l'OP de la tâche pourrait être satisfaite par un LookupOp, ce qui nécessite la mise en place de recherche de tableaux. Pour modifier uniquement le canal alpha, la fourniture d'une identité matrice (un tableau où le tableau[i] = i) pour les canaux RVB, et un tableau séparé pour le canal alpha. Remplir le dernier tableau avec
table[i] = f(i)
, oùf()
est la fonction par laquelle vous voulez la carte de la vieille valeur alpha à nouveau. E. g. si vous voulez "faire de chaque pixel de l'image a une valeur alpha de 100 ont une valeur alpha de 80",table[100] = 80
. (Toute la gamme de 0 à 255.) Voir comment faire pour augmenter l'opacité dans le flou gaussien pour un exemple de code.RescaleOp
Mais pour un sous-ensemble de ces cas, il y a un moyen plus simple de le faire, que ne pas exiger la mise en place d'une table de recherche. Si
f()
est une simple fonction linéaire, l'utilisation d'un RescaleOp. Par exemple, si vous souhaitez définirnewAlpha = oldAlpha - 20
, utiliser un RescaleOp avec un scaleFactor de 1 et un décalage de -20. Si vous souhaitez définirnewAlpha = oldAlpha * 0.8
, utiliser un scaleFactor de 0,8 et un offset de 0. Dans les deux cas, vous avez à fournir mannequin scaleFactors et les décalages pour les canaux RVB:De nouveau voir 4.10.6 ici de quelques exemples qui illustrent les principes bien, mais ne sont pas spécifiques à un canal alpha.
Les deux RescaleOp et LookupOp permettre de modifier un BufferedImage en place.
OriginalL'auteur LarsH
pour un plus agréable à la recherche d'alpha effet de changement, vous pouvez utiliser par rapport alpha changement par pixel (plutôt que de l'ensemble statique, ou d'écrêtage linéaire)
OriginalL'auteur Thumbz
Je suis sûr à 99% que les méthodes qui prétendent traiter avec un "RVB" valeur emballé dans un int fait affaire avec ARGB. Donc, vous devriez être en mesure de faire quelque chose comme:
Pour la vitesse, vous pourriez peut-être utiliser les méthodes pour récupérer des blocs de valeurs de pixel.
OriginalL'auteur Neil Coffey
Vous devrez peut-être de la première copie de votre BufferedImage à une image de type
BufferedImage.TYPE_INT_ARGB
. Si votre image est de type, disons,BufferedImage.TYPE_INT_RGB
, alors la composante alpha ne sera pas réglé correctement. Si votre BufferedImage est de typeBufferedImage.TYPE_INT_ARGB
, puis le code ci-dessous fonctionne./**
* Modifies each pixel of the BufferedImage so that the selected component (R, G, B, or A)
* is adjusted by delta. Note: the BufferedImage must be of type BufferedImage.TYPE_INT_ARGB.
* @param src BufferedImage of type BufferedImage.TYPE_INT_ARGB.
* @param colorIndex 0=red, 1=green, 2=blue, 3= alpha
* @param delta amount to change component
* @return
*/
public static BufferedImage adjustAColor(BufferedImage src,int colorIndex, int delta) {
int w = src.getWidth();
int h = src.getHeight();
assert(src.getType()==BufferedImage.TYPE_INT_ARGB);
for (int y = 0; y < h; y++)
for (int x = 0; x < w; x++) {
int rgb = src.getRGB(x,y);
java.awt.Color color= new java.awt.Color(rgb,true);
int red=color.getRed();
int green=color.getGreen();
int blue=color.getBlue();
int alpha=color.getAlpha();
switch (colorIndex) {
case 0: red=adjustColor(red,delta); break;
case 1: green=adjustColor(green,delta); break;
case 2: blue=adjustColor(blue,delta); break;
case 3: alpha=adjustColor(alpha,delta); break;
default: throw new IllegalStateException();
}
java.awt.Color adjustedColor=new java.awt.Color(red,green,blue,alpha);
src.setRGB(x,y,adjustedColor.getRGB());
int gottenColorInt=src.getRGB(x,y);
java.awt.Color gottenColor=new java.awt.Color(gottenColorInt,true);
assert(gottenColor.getRed()== red);
assert(gottenColor.getGreen()== green);
assert(gottenColor.getBlue()== blue);
assert(gottenColor.getAlpha()== alpha);
}
return src;
}
private static int adjustColor(int value255, int delta) {
value255+= delta;
if (value255<0) {
value255=0;
} else if (value255>255) {
value255=255;
}
return value255;
}
OriginalL'auteur Don Smith