2011-10-12 16 views
8

Sto provando a fondere due immagini con Android, utilizzando una modalità di fusione di tipo Moltiplica.Miscelazione di due immagini insieme a moltiplicare e% opacità

// Prepare ------------------------------- 

// Create source images 
Bitmap img1 = ... 
Bitmap img2 = ... 

// Create result image 
Bitmap result = ... 
Canvas canvas = new Canvas(); 
canvas.setBitmap(result); 

// Get proper display reference 
BitmapDrawable drawable = new BitmapDrawable(getResources(), result); 
ImageView imageView = (ImageView)findViewById(R.id.imageBlend1); 
imageView.setImageDrawable(drawable); 


// Apply ------------------------------- 

// Draw base 
canvas.drawBitmap(img1, 0, 0, null); 

// Draw overlay 
Paint paint = new Paint(); 
paint.setXfermode(new PorterDuffXfermode(Mode.MULTIPLY)); 
paint.setShader(new BitmapShader(img2, TileMode.CLAMP, TileMode.CLAMP)); 

canvas.drawRect(0, 0, img2.getWidth(), img2.getHeight(), paint); 

questo funziona, ma non ho il controllo sulla "quantità" di moltiplicare che viene fatto - è sempre un trasferimento moltiplicano completa. Idealmente, un multiplo dello 0% sarebbe uguale all'immagine di base (img1) senza alcuna variazione, ma una moltiplicazione del 100% sarebbe il risultato che ottengo con il codice sopra.

paint.setAlpha() non sembra funzionare per questo.

Qualsiasi altro modo per impostare l'opacità% del nuovo 'livello'?

P.S. Ci sono alcuni metodi per far funzionare il multiplo con questo immagino (usando uno LightingColorFilter) pre-moltiplicando e sfalsando il colore in bianco, ma è molto specifico per la modalità multipla .. Sto cercando di trovare un modo per applicare l'opacità/% cosa a tutte le altre modalità di trasferimento.

risposta

2

Avevo bisogno di fare qualcosa del genere un po 'di tempo fa, e ho trovato lo this post about Color Channels molto illuminante. (ma temo che ciò sia correlato a ciò che hai descritto nel tuo "PS")

+1

Valeu rapaz. Ma sì, l'articolo è fantastico, ma si tratta solo di aggiungere layer con diverse modalità piuttosto che avere un modo per cambiare la% dei valori di input per ciascuna modalità. Mostra alcune manipolazioni dirette dei pixel dopo averli letti dall'immagine, quindi forse è un'alternativa. Dovrò indagare su questo. Per ora, grazie! – zeh

+1

Link NON trovato, bro. Per favore aggiornare! –

2

Stavo implementando i filtri fotografici in modo simile a quello che fa l'app iOS. Lo fanno qualcosa come source bitmap + mask bitmap + blend mode + alpha value. Per ottenere un comportamento identico ho appena aumentato l'alfa della maschera. Ecco ciò che il mio codice è finalmente:

public static Bitmap blend(Bitmap back, Bitmap front, BlendMethod method, float alpha) { 
    if (alpha != 1.0F) { 
     front = makeTransparent(front, Math.round(alpha * 255)); 
    } 

    Bitmap.Config config = back.getConfig(); 
    int width = back.getWidth(); 
    int height = back.getHeight(); 

    if (width != front.getWidth() || height != front.getHeight()) { 
     Log.e(TAG, "Arrays must be of identical size! Do bitmap scaling prior to blending."); 
     return null; 
    } 

    int[] frontArr = new int[height * width], backArr = new int[height * width], resultArr; 

    back.getPixels(backArr, 0, width, 0, 0, width, height); 
    front.getPixels(frontArr, 0, width, 0, 0, width, height); 

    resultArr = jniBlend(frontArr, backArr, alpha, method.toInt()); 
    return Bitmap.createBitmap(resultArr, width, height, config); 
} 

public static Bitmap blend(Bitmap back, Bitmap front, BlendMethod method) { 
    return blend(back, front, method, 1F); 
} 

public static Bitmap makeTransparent(Bitmap src, int value) { 
    int width = src.getWidth(); 
    int height = src.getHeight(); 
    Bitmap transBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); 
    Canvas canvas = new Canvas(transBitmap); 
    canvas.drawARGB(0, 0, 0, 0); 
    // config paint 
    final Paint paint = new Paint(); 
    paint.setAlpha(value); 
    canvas.drawBitmap(src, 0, 0, paint); 
    return transBitmap; 
} 

Nota che jniBlend è un metodo che ho scritto da solo, si comporta come modalità magazzino PorterDuff in Java.

Metodo makeTransparent non è mia - trovato here: (risposta da Ruban)

0

Il codice non è completa. è solo per darti un'idea in modo da poter usare lo script di rendering per fondere un'immagine

public Bitmap blend(Bitmap image) 
{ 
    final float BLUR_RADIUS = 25f; 
    Bitmap outbitmap = Bitmap.createBitmap(image); 
    final RenderScript renderScript = RenderScript.create(this); 

    Allocation tmpin = Allocation.createFromBitmap(renderScript,image); 
    Allocation tmpout = Allocation.createFromBitmap(renderScript,outbitmap); 
    ScriptIntrinsicBlend blend = ScriptIntrinsicBlend.create(renderScript, 
    Element.U8_4(renderScript)); 

    blend.forEachMultiply(tmpin,tmpout); 
    return outbitmap; 
}