2011-01-12 11 views
5

Ich versuche, Mischfilter auf zwei Bilder (in diesem Fall HardLight) anzuwenden. HardLight wird in der Basis-Android-Bibliothek nicht unterstützt, also mache ich es manuell mit jedem Pixel. Der erste Lauf funktioniert, aber die Geschwindigkeit ist weniger als stellar. Die Erstellung eines 500x500-Bildes aus einem 500x500-Basisbild und einem 500x500-Filter dauert viel zu lange. Dieser Codeabschnitt wird auch zum Generieren von Thumbnails (72 x 72) verwendet und ist integraler Bestandteil des Kerns der Anwendung. Ich hätte gerne Ratschläge und/oder Hinweise, wie Sie das beschleunigen können.Optimierung pro Pixel Mischen auf Android Bitmaps

Wenn große Gewinne erzielt werden können, indem die Annahme gemacht wird, dass keines der Bilder Alpha haben wird, ist das in Ordnung. HINWEIS: BlendMode und Alpha sind Werte, die im Beispiel nicht verwendet werden (BlendMode wählt den Blendentyp aus, in diesem Fall habe ich HardLight programmiert).

public Bitmap blendedBitmap(Bitmap source, Bitmap layer, BlendMode blendMode, float alpha) { 
    Bitmap base = source.copy(Config.ARGB_8888, true); 
    Bitmap blend = layer.copy(Config.ARGB_8888, false); 

    IntBuffer buffBase = IntBuffer.allocate(base.getWidth() * base.getHeight()); 
    base.copyPixelsToBuffer(buffBase); 
    buffBase.rewind(); 

    IntBuffer buffBlend = IntBuffer.allocate(blend.getWidth() * blend.getHeight()); 
    blend.copyPixelsToBuffer(buffBlend); 
    buffBlend.rewind(); 

    IntBuffer buffOut = IntBuffer.allocate(base.getWidth() * base.getHeight()); 
    buffOut.rewind(); 

    while (buffOut.position() < buffOut.limit()) { 
     int filterInt = buffBlend.get(); 
     int srcInt = buffBase.get(); 

     int redValueFilter = Color.red(filterInt); 
     int greenValueFilter = Color.green(filterInt); 
     int blueValueFilter = Color.blue(filterInt); 

     int redValueSrc = Color.red(srcInt); 
     int greenValueSrc = Color.green(srcInt); 
     int blueValueSrc = Color.blue(srcInt); 

     int redValueFinal = hardlight(redValueFilter, redValueSrc); 
     int greenValueFinal = hardlight(greenValueFilter, greenValueSrc); 
     int blueValueFinal = hardlight(blueValueFilter, blueValueSrc); 

     int pixel = Color.argb(255, redValueFinal, greenValueFinal, blueValueFinal); 

     buffOut.put(pixel); 
    } 

    buffOut.rewind(); 

    base.copyPixelsFromBuffer(buffOut); 
    blend.recycle(); 

    return base; 
} 

private int hardlight(int in1, int in2) { 
    float image = (float)in2; 
    float mask = (float)in1; 
    return ((int)((image < 128) ? (2 * mask * image/255):(255 - 2 * (255 - mask) * (255 - image)/255))); 

} 
+0

Hallo, kannst du mir helfen, Alpha in dieser Funktion zu verwenden? –

Antwort

0

Es war eine Frage wie diese eine Weile zurück (Link). Ich bin mir nicht sicher, ob das OP jemals sein Problem gelöst hat.

Was ich in meinem Fall getan habe, um eine "Photoshop-Mischung" zu erzielen, war die Anwendung einer transparenten Schattenüberlagerung auf eine einzige Farbe. Es war einfach eine Frage meines Grafikdesigners herauszufinden, wie man das Schatten-Overlay macht. Es funktionierte großartig und ich ignorierte das Problem, dass ich Pixel in einer Bitmap durchlaufen musste (ich benutzte getPixels() und setPixels()). Der schwierige Teil war wirklich am Ende meiner Designer, aber sobald er es herausgefunden hat, hat er eine Reihe von großartig aussehenden Bildern erzeugt.

Ich verwendete grundsätzlich eine Alpha-Maske (um dynamische Farben zu erzeugen) mit der Schattenüberlagerung. Ich würde gerne über eine Lösung via Code lernen, also viel Glück für Sie!

Edit: Ich bin auch nicht vertraut mit BlendMode. Du hast es nie in deiner Methode benutzt. Was ist das, eine benutzerdefinierte Klasse?

+0

Leider funktioniert diese Lösung in meinem Fall nicht. – MarkPowell

2

Fließkommaoperationen sind im Allgemeinen langsamer als ganze Zahlen, obwohl ich speziell über Android nichts sagen kann. Ich frage mich, warum Sie die Eingabe in hardlight in Fließkomma konvertieren, wenn die Operationen so aussehen, als würden sie perfekt als Ganzzahlen funktionieren?

Sie können auch eine Beschleunigung erhalten, indem Sie die Formel inline in die Schleife einfügen, anstatt eine Funktion aufzurufen. Oder vielleicht auch nicht, aber es lohnt sich, es zu versuchen und zu bewerten.

+0

Ausprobieren verschiedener Dinge, ich konnte eine Leistungssteigerung um 40% erzielen, indem ich int Arrays anstelle von Buffers benutze (mit 'getPixels()' und 'setPixels()') und die Werte nicht in floats in 'hardlight' umwandelte . Abgesehen davon denke ich, dass die beste Leistung, die Sie erzielen werden, darin besteht, diese Berechnung auf die native Ebene zu bringen und vielleicht einen benutzerdefinierten Xermode zu implementieren. –

+0

hmm, Wechsel zu getPixels()/setPixels() Ich sah eine doppelte Rechenzeit, es sei denn, ich missverstehe, was Sie sagen? – MarkPowell

+0

@MarkPowell, ich glaube @Kevin hat sich für int-Arrays ausgesprochen und streitet * gegen * getPixels/setPixels. Sie müssen Ihren Kommentar an ihn richten, indem Sie mit @Kevin beginnen, wenn Sie weitere Fragen haben. –

1

Auch wenn Sie 3 Bit/Pixel der endgültigen Bildqualität/Präzision opfern können, - können wir über 25% Leistungsgewinn in Funktion hardlight() gewinnen indem sie sie mit bitweise Operatoren Umschreiben:

int hardlight(int image, int mask) { 
    return (((image < 128) ? 
      ((((mask << 1) * image) >> 8)): 
      (255^((((255^mask) << 1) * (255^image)) >> 8)))); 
} 
+0

Danke, wir sehen hier eine Verbesserung der Gesamtgeschwindigkeit um 10%. Allerdings muss man sehen, ob das 3 Bit/Pixel Opfer machbar ist. – MarkPowell

+0

Ok. Es ist schade, dass der Leistungszuwachs nur 10% statt 25% beträgt wie bei meiner Windows-Maschine.Ich vermute, dass Android bitweise Operatoren weniger optimiert sind als im Vergleich zu Windows-Plattform/MS VS C/C++ - Compiler. Oder vielleicht liegt der Hauptleistungsengpass nicht in der Hardlight-Funktion, sondern woanders. –