Domanda

Come posso modificare il valore alfa globale di una BufferedImage in Java? (I.E. rende ogni pixel nell'immagine che ha un valore alfa di 100 un valore alfa di 80)

È stato utile?

Soluzione

Non credo ci sia un singolo semplice comando per farlo. Alcune opzioni:

Il primo è il più semplice da implementare, IMO.

Altri suggerimenti

@Neil Coffey: Grazie, ho cercato anche questo; tuttavia, il tuo codice non ha funzionato molto bene per me (lo sfondo bianco è diventato nero).

Ho codificato qualcosa del genere e funziona perfettamente:

public void setAlpha(byte alpha) {       
    alpha %= 0xff; 
    for (int cx=0;cx<obj_img.getWidth();cx++) {          
        for (int cy=0;cy<obj_img.getHeight();cy++) {
            int color = obj_img.getRGB(cx, cy);

            int mc = (alpha << 24) | 0x00ffffff;
            int newcolor = color & mc;
            obj_img.setRGB(cx, cy, newcolor);            

        }

    }
}

Dove obj_img è BufferedImage.TYPE_INT_ARGB.

Cambio alpha con setAlpha ((byte) 125); l'intervallo alfa ora è 0-255.

Spero che qualcuno lo trovi utile.

Questa è una vecchia domanda, quindi non sto rispondendo per il bene del PO, ma per quelli come me che troveranno questa domanda in seguito.

AlphaComposite

Come menzionato l'eccellente schema di @ Michael, un'operazione AlphaComposite può modificare il canale alfa. Ma solo in certi modi, che per me sono in qualche modo difficili da capire:

inserisci qui la descrizione dell'immagine

è la formula per come il " oltre " l'operazione influisce sul canale alfa. Inoltre, ciò influisce anche sui canali RGB, quindi se hai dati cromatici che devono essere invariati, AlphaComposite non è la risposta.

BufferedImageOps

LookupOp

Esistono diverse varietà di BufferedImageOp (vedi 4.10.6 qui ). Nel caso più generale, l'attività dell'OP potrebbe essere soddisfatta da un LookupOp , che richiede la creazione di array di ricerca. Per modificare solo il canale alfa, fornire un array di identità (un array in cui la tabella [i] = i) per i canali RGB e un array separato per il canale alfa. Popolare l'ultimo array con table[i] = f(i), dove f() è la funzione con cui si desidera eseguire il mapping dal vecchio valore alfa al nuovo. Per esempio. se vuoi " fai in modo che ogni pixel nell'immagine che abbia un valore alfa di 100 abbia un valore alfa di 80 " ;, imposta table[100] = 80. (L'intera gamma va da 0 a 255.) Vedi come aumentare l'opacità nella sfocatura gaussiana per un esempio di codice.

RescaleOp

Ma per un sottoinsieme di questi casi, esiste un modo più semplice per farlo, che non richiede l'impostazione di una tabella di ricerca. Se newAlpha = oldAlpha - 20 è una funzione semplice e lineare, utilizzare un RescaleOp . Ad esempio, se si desidera impostare newAlpha = oldAlpha * 0.8, utilizzare un RescaleOp con un fattore di scala 1 e un offset di -20. Se si desidera impostare <=>, utilizzare un fattore di scala di 0,8 e un offset di 0. In entrambi i casi, è necessario fornire nuovamente fattori di scala fittizi e offset per i canali RGB:

new RescaleOp({1.0f, 1.0f, 1.0f, /* alpha scaleFactor */ 0.8f},
              {0f, 0f, 0f, /* alpha offset */ -20f}, null)

Ancora una volta 4.10.6 qui per alcuni esempi che illustrano bene i principi, ma non sono specifici del canale alfa.

Entrambi RescaleOp e LookupOp consentire modifica di un'immagine bufferizzata sul posto.

per un effetto di cambio alfa dall'aspetto più gradevole, puoi usare il cambio alfa relativo per pixel (piuttosto che un set statico o un ritaglio lineare)

public static void 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_ARGB
            int 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);            
        }
    }
}

Sono sicuro al 99% dei metodi che affermano di trattare un " RGB " valore racchiuso in un int realmente trattare con ARGB. Quindi dovresti essere in grado di fare qualcosa del tipo:

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);
  }
}

Per velocità, potresti forse usare i metodi per recuperare blocchi di valori di pixel.

Potrebbe essere necessario copiare prima l'immagine bufferizzata in un'immagine di tipo BufferedImage.TYPE_INT_ARGB. Se l'immagine è di tipo, ad esempio BufferedImage.TYPE_INT_RGB, il componente alfa non verrà impostato correttamente. Se BufferedImage è di tipo /** * 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; } , il codice seguente funziona. <=>

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top