Android canvas color milchglas effekt

Jaiel

Jaiel

Dauergast
235
hey

ihr kennt ja milchglas(glas das mit säure behandelt wurde) und wie das aussieht

gibt es eine möglichkeit diesen effekt in android umzusetzen

der hintergrund ist, dass ich eine farbe über dem canvas legen will wenn ich bestimmte bilder anzeige die nur einen teil der view einnehmen und den hintergrund verschwommen aussehen lassen will mit diesem effekt.

gibt es da eine möglichkeit?
kann man irgendwas mit filtern machen quasi die view vor dem anzeigen des bildes einlesen und verändern mit einer matrix oder ähnlichem?

Der ursprüngliche Beitrag von 19:04 Uhr wurde um 19:28 Uhr ergänzt:

also andere stichworte wären : "blureffect" und "frosteffect"
 
Hi,

das geht mit den OpenGL-Shadern. Ich weiß nicht, ob es welche dafür schon gibt, aber man kann auch selber welche dafür schreiben.

Es gibt eine Art Library dafür:
https://github.com/CyberAgent/android-gpuimage

Damit kannst du aus Bildern welche mit Effekten erstellen. Diese kann man dann einbinden.
 
hi danke für den tipp werde mir das anschauen

Ich habe gerade foglende Methode versucht:

bevor ich zeichne erstelle ich ein neuen Canvas mit

PHP:
new Canvas(Bitmap bmp)

das bmp hat die maße des screens
dieses canvas benutze ich für meine zeichenmethoden

damit wird alles in das bitmap gezeichnet
anschließend skaliere ich das bitmap auf eine größe von 256x256 pixeln und skaliere sofort wieder zurück dabei stelle ich den filter auf false in
Bitmap.createScaledBitmap(bmp,screenWidth,screenHeight,false);

zum schluss zeichne ich einfach den übergebenen canvas des Bildschirmes mit diesem Bitmap

PHP:
screenCanvas.drawBitmap(bmp,0,0,null);


Resultat: verpixeltes Bild und eine Framerate die von 57-60 auf 12 absinkt :(


beides sehr ungewünschte Effekte, ersteres ist auch interessant aber ich möchte kein Minecraft artigen style einführen

wenn ich jetzt opengl ES benutzen muss dafür wird es wohl etwas schreibarbeit


Es gibt noch die Möglichkeit Renderscript zu verwenden jedoch ist das erst ab einer höheren API (ich glaube 18) möglich dadurch schränke ich wiederum meinen Benutzerkreis ein was auch sehr unerwünscht ist


Gibt es keine anderen Alternativen?


XML mäßig vllt

Die Entwickler der App Etsy amchen da irgendwie sowas in der Art


Das wirklich letzte Mittel das ich anwenden würde ist es meine bitmaps per Hand in Gimp mit diesem Effekt zu versehen und es so wie die Yahoo Weather app macht ->http://nicolaspomepuy.fr/blur-effect-for-android-design/

Der ursprüngliche Beitrag von 09:01 Uhr wurde um 09:31 Uhr ergänzt:

Hab grad noch ein Versuch gewagt und einfach ein etwas transparentes Weiß über die view gelegt...

Das geht schon in die richtige Richtung nur sind die bilder hinter dem weiß leider scharf

Sieht aber schonmal nicht so schlecht aus
 
Zuletzt bearbeitet:
  • Danke
Reaktionen: Railwanderer
jaiel ich bin einfach ein fan von dir :) klasse dass du deine eigenen frahen auch ausfuehrlich beantwortest dass andere das nachlesen koennen!
Mein erster gedanke war auch einfach transparent weiss, oder eben
hoch skalieren, dann wird unscharf und so ubernommen wieder runter scalieren.

Merci nochmal, einfach interessant zu lesen!
 
  • Danke
Reaktionen: Jaiel
oh freut mich dass dir meine Monologe gefallen :D
 
Warum zeichnest du nicht ein bild in dem jeder pixel einzeln
mit einem transparent weiss wert zwischen zb 50-80% scheankt.
nach bedarf die werte smooth steigen bzw fallen lassen statt
zufaellig zu waehlen, dann duerfte ersteres ein koerniges
milchglas und zweiteres ein poliertes milchglas mit evtl spotlight
entstehen, oder aehnliches ;)

Um rechenzeit zu sparen koennte man dieses bild einmal berechnen
und speichern und dann immer drueberlegen.

ich denke mit zufallswerten fuer jeden pixel wuerde ein leicht koerniger
effekt entstehen. Hm scharf siehts evtl immernoch aus, vll davor manche
pixelwerte des ursprungsbildes speichern u mit einem nachbar
oder zwei vertauschen?


Apropos: wie spricht man einen einzelnen pixel an und speichert seine farbe?

Graphics g // g.getGtaphics() ? Und fuer einen bestimmten pixel?
Haette lust es mal selbst auszuprobieren ;)
 
Railwanderer schrieb:
Apropos: wie spricht man einen einzelnen pixel an und speichert seine farbe?

Graphics g // g.getGtaphics() ? Und fuer einen bestimmten pixel?
Haette lust es mal selbst auszuprobieren ;)

ich würde einfach

canvas.drawPixel(x,y,...);

verwenden dafür.

Der ursprüngliche Beitrag von 14:15 Uhr wurde um 14:27 Uhr ergänzt:

ich hatte ja erwähnt dass Renderscript nciht in Erwägung kommt aber jetzt hab ich rausgefunden dass es eine Support library gibt ab API 8

Jetzt nur noch RenderScript lernen und los gehts ...wenn ich mal zeit habe :p

versuche gerade shader programmierung in open gl es


mal gucken welche schneller sein wird....stelle die ergebnisse dann hier vor



für das Projekt was ich zur zeit habe wird wohl sowas nciht mehr genutzt deswegen wird es wohl ein bisschen dauern werde es wahrscheinlich in meinem nächsten spiel umsetzen da ich eh geplant habe es als open gl spiel zu schreiben vllt sogar 3D wenn ich matrizen und so draufhab (endlich mal)
 
  • Danke
Reaktionen: Railwanderer
Und wie bekommt man die farbe eines pixels eines bildes?
Sowas wie canvas.getGraphics.getPixel? :D :D leider grad nicht am laptop
 
ich glaube geht nciht habe ncihts gefunden dazu jedenfalls


wenn du auf dem canvas malst mit hilfe eines bitmaps(wenn du ein Canvas mit new Canvas(Bitmap bmp); erstellt hast zum beispiel) dann geht das indem du das bitmap fragst welche Farbe es an der und der Stelle hat

oder das bitmap des Screens ansteuern mjit getDrawingCache();(der drawing cache muss aber bevor die view existiert enabled werden...setDrawingCacheEnabled(true) oder im manifest auf true stellen)

Möchtest du damit etwa Collision Detection machen?
Das wäre performance-technisch zu kostspielig jedenfalls!
 
  • Danke
Reaktionen: Railwanderer
Japp so wollte ich das ein pixel eines bitmaps abfragen.
wie saehe der code dazu aus?

Ich hatte in erster linie gedacht damit einen eigenen blur
effekt zu erreichen, wie oben beschrieben einfach benachbarte
pixel tauschen um so ein wischfinger aehnlichen effekt zu erreichen
dann transparent weiss drueber fuer milchglas look.

Collison detection laeuft bei mir ueber die tiles, meine figur ist auch
in der bewegung an ein tile raster gebunden und kann immer
nur in 32 pixel schritten forwaerts bewegt werden. Also er haelt
erst an wenn er auf dem naechsten tile angekommen ist.

aber mir fallen weitere anwendungen dafuer ein, die zum teil
auch so schon genutzt werden, zb:

Eine mini map zeichnen, wege in gruen, boden in weiss,
blocked tiles in schwarz usw. Und dann den algorithmus diese
minimap grafik durchlaufen lassen und fuer die jeweilige
pixelfarbe ein bestimmten tile eben auf die tilemap zeichnen.
dann kann man seine map mit stift und fuellwerkzeug in gimp o.a.
zeichnen. Allerdings habe ich schon meinen eigenen tileeditor
Und werde, auch wenn er bei weitem nicht perfekt ist, beibehalten und
dran feilen.

eine andere einsatzmoeglichkeit: aimbots, klickbots etc.
Dazu soll der algorithmus ein bild eines programmes checken
und wenn gegner spawnt wieder angreifen
(Z.b. fuer das spiel warspear auf android)
Natuerlich trau ich mir das noch nicht zu und bin sowieso
mit meinem zweiten spiel bzw erstem eigenen komplett
Bedient, aber aus interese immer gut gleich zu verstehen wie was
funktionier ;) irgendwann will ich ja mal ein pro im coden sein xD

Der ursprüngliche Beitrag von 23:17 Uhr wurde um 23:33 Uhr ergänzt:



Mein spiel stelle ich natuerlich hierrein, ist mein erste komplett eigen geschaffenes incl grafik ;)

Momentan schleife ich am letzen stueck des mapengine, bisher kann man die map
an den kartenraendern verlassen um auf der naechsten zu landen, es gibt
eine minimap und eine insel map, und unterstuetzt werden verschiedene layer,
Man kann hinter baeume hauser waende gehen und diese koennen sich gegenseitig ueberlagern.
fehlt noch: spritetiles (zb wasser, laternenleuchten) und eine untergrund bzw hausebene.

danach gehts endlich an interaktion und inventar :)


Ps sorry fuer die masse an tippfehlern. Schreibe grad v handy -.-
 
Zuletzt bearbeitet:
Railwanderer schrieb:
Japp so wollte ich das ein pixel eines bitmaps abfragen.
wie saehe der code dazu aus?
Etwa so:
PHP:
public void drawOnBitmap (Canvas screenCanvas )
{
    Bitmap tempBitmap=new Bitmap (screenWidth, screenHeight, Config.ARGB_8888);
    Canvas tempCanvas=new Canvas (tempBitmap);

    tempCanvas.drawBitmap (...);

    (...)

    pixelOperationOnBitmap (tempBitmap);

    screenCanvas.drawBitmap (tempBitmap,0,0,paint);
}

Sehr spannend ist das was in pixelOperationOnBitmap () passiert

Vielleicht geht man da von Pixel zu Pixel und verändert die 8 umliegenden je nach farbwert quasi wie anti aliasing

Gibt bestimmt viele hochgezüchtete Algorithmen dafür

Vllt schafft man es ja so zu impementieren dass man wenigstens 10 fps hat

Wäre für games ungeeignet aber normale Anwendungen brauchen ja nicht so viel fps wie spiele


Natürlich ist die Manipulation der grafikpipeline schneller
hier schlägt Hardware die Software um Längen

Der ursprüngliche Beitrag von 04:10 Uhr wurde um 05:07 Uhr ergänzt:

Mir kam gerade noch eine Idee werden ich auf jeden Fall testen

Man malt dasselbe Bild 9 mal
1 mal ganz normal und 8 mal transparent immer um die Pixel verschoben
 
Habe das jetzt so gemacht:


PHP:
Paint alphaPaint=new Paint(),paint=new Paint();
	int x=10;
	Rect rect=new Rect();
	

	alphaPaint.setColor(Color.argb(100,255,255,255));
	
	paint.setColor(Color.RED);
	paint.setTextSize(50);
	

	bmp=Bitmap.createScaledBitmap(BitmapFactory.decodeResource(getResources(),R.drawable.bitmap),
			getWidth(),getHeight(),true);
	rect.set((int)(getWidth()*0.2f),(int)(getWidth()*0.2f),(int)(getWidth()*0.8f),(int)(getHeight()-getWidth()*0.2f));
	
	/*
	 * Method for the drawing operations.
	 */
	public void doDraw()
	{
		try
		{
			synchronized(sHolder)
			{
				if(click)
				{
					canvas = sHolder.lockCanvas(rect);
					canvas.drawBitmap(bmp,-x-x,-x-x,alphaPaint);
					canvas.drawBitmap(bmp, 0-x,-x-x,alphaPaint);
					canvas.drawBitmap(bmp, x-x,-x-x,alphaPaint);
					canvas.drawBitmap(bmp,-x-x, 0-x,alphaPaint);
					canvas.drawBitmap(bmp, 0-x, 0-x,null);
					canvas.drawBitmap(bmp, x-x, 0-x,alphaPaint);
					canvas.drawBitmap(bmp,-x-x, x-x,alphaPaint);
					canvas.drawBitmap(bmp, 0-x, x-x,alphaPaint);
					canvas.drawBitmap(bmp, x-x, x-x,alphaPaint);
					canvas.drawRect(getWidth()*0.2f,getWidth()*0.2f,getWidth()*0.8f,getHeight()-getWidth()*0.2f,alphaPaint);
//					canvas.drawColor(Color.argb(100, 255, 255, 255));
				}
				else 
				{
					canvas = sHolder.lockCanvas();
					canvas.drawBitmap(bmp, 0, 0,null);
				}
				canvas.drawText("FPS:" + mMThread.FPS, 100, 100, paint);

			}
		}
		catch(Throwable t)
		{
			canvas=null;
		}
		finally
		{
			if(canvas!= null)
			{
				sHolder.unlockCanvasAndPost(canvas);
			}
		}
	}


x gibt dabei an wie weit er weg ist

Im Anhang sind die daraus entstandenen Bilder (in der Reihenfolge : ungeblurrt,x=5,x=10,x=15,x=20)

Die Framerate hängt davon ab wie groß das Rect ist was ich benutze.

Im vollbild bekomme ich ca. 12-14 FPS bei x=10 mit einem Bild.


Man könnte jetzt viele Tricks einsetzen wie z.B. Vorrendern wenn man weiß dass man statische Bilder hat.
Dann kann man ja einfach nur ein Bildabschnitt nehmen und muss nciht das ganze Bild rendern und dieses immer wieder drüberzueichnen(zum Beispiel falls ihr ein Menü habt das aufploppt dann malt ihr unter die Menüoberfläche einfach den geblurrten Bildabschnitt und dann das transparente Menü darüber

dann sind 50-60 FPS auch wieder drin


Das Ergebnis von der Optik her ist finde ich gut gelungen

Man könnte einen feineren Effekt erzielen ind em man alle pixel zwischen 0 punkt und x durchgeht dann malt man mehr bilder und ich echtzeit würde die FPS rate ncih weiter absinken....vorgerendert wäre ein längerer ladeprozess nötig

Also für einfach Anwendungen sind 15-19 FPS vollkommen in Ordnung

(Anmerkungen: in meinem Code habe ich einen Fehler gemacht deswegen sehen die Bilder je höher x ist verschoben aus...überall wo ein x-x steht muss das x mit 2*x vertauscht werden zu 2*x-x und 0-x muss einfach nur 0 sein...sorry)


Aber seht selbst!
 

Anhänge

  • Ungeblurrt.png
    Ungeblurrt.png
    51,2 KB · Aufrufe: 137
  • x=5.png
    x=5.png
    75,4 KB · Aufrufe: 134
  • x=10.png
    x=10.png
    91,2 KB · Aufrufe: 148
  • x=15.png
    x=15.png
    111,1 KB · Aufrufe: 148
  • x=20.png
    x=20.png
    114,8 KB · Aufrufe: 173
Zuletzt bearbeitet:
und hier das vorgerenderte
x=8


Ich versuche es ncohmal vorzurendern indem ich das Bitmap erstmal hochskaliere und dann schrittweise auf die Ursprungsgröße zurücksklaiere und bei jedem sklaierungsschritt auf den canvas male der Effekt wäre glaube ich dann viel geschmeidiger
 

Anhänge

  • vorgerendert x=8.png
    vorgerendert x=8.png
    83,1 KB · Aufrufe: 159
So jetzt hab ich vorgerendert indem ich die bitmaps schrittweise runter skaliert habe

x steht diesmal für die maximale skalierung in pixel heißt beio 30 habe ich das bild um 30 pixel vergrößert also original größe +x

schrittweite für die skalierung war -2 ausser in dem einen mit x=30 und 58 FPS(das andere hatte 60)

dort war die schrittweite -4

skaliert habe ich bis (original größe-x+1)

hier die grafiken (diesmal ohne weiße tranzparenz schicht)


Fazit:
1.das echtzeit rendern mit meiner methode macht eine FPS von 10-20 und das ist eig. ok für normale anwendungen(am besten zeichnet man auch nur wenn sich was verändert hat) mit opengl geht das bestimmt schneller da der Renderer so gesetzt werden kann das nur gezeichnet wird wenn sich daten verändern

Das Vorrendern kann man sich unter Umständen sparen und ein bitmap von vorherein mit bildbearbeitungsprogrrammen blurren.
Mit hilfe der Skalierungsmethode hat es gefühlt eine Stunde kürzer gedauert bis er fertig war mit vorrendern und ein bild auf den screen geschmissen hatte(ca. 1 sekunde und beim malalgorithmus hat es ca. 5-6 sekunden gebraucht)


Aber ansonsten ist für wirklich performante lösungen opengl shader oder renderscript unser Freund
 

Anhänge

  • Screenshot_2015-04-09-07-43-01.png
    Screenshot_2015-04-09-07-43-01.png
    103,9 KB · Aufrufe: 147
  • Screenshot_2015-04-09-07-41-07.png
    Screenshot_2015-04-09-07-41-07.png
    77,7 KB · Aufrufe: 158
  • Screenshot_2015-04-09-07-40-45.png
    Screenshot_2015-04-09-07-40-45.png
    95,9 KB · Aufrufe: 155
  • Screenshot_2015-04-09-07-40-26.png
    Screenshot_2015-04-09-07-40-26.png
    107,5 KB · Aufrufe: 182
Zuletzt bearbeitet:
Haja kann sich doch sehen lassen! Grad das obere, letzte beispiel mit milchglas effekt
sieht top aus :)

PixelOperationOnBitmap versteh ich jetzt noch nicht ganz, wie kann ich nun zum beispiel
pixel bei 10,10 speichern? Ich werd am wochenende selbst nochmal nachschlagen,
Hatte schonmal iwo ein tutorial gesehen bei dem man einzelne pixel farben abfragen kann.

aber der rest ist top u gut beschrieben, setze mich morgen abend(nacht) nach feierabend defintiv auch nochmal damit ausseinander :)
 
Railwanderer schrieb:
PixelOperationOnBitmap versteh ich jetzt noch nicht ganz, wie kann ich nun zum beispiel
pixel bei 10,10 speichern?

freut mich das es dir gefällt

ich bin etwas verwirrt was du meinst...den namen hab ich mir nur ausgedacht...

Der ursprüngliche Beitrag von 20:08 Uhr wurde um 20:31 Uhr ergänzt:

Railwanderer schrieb:
pixel bei 10,10 speichern?


die abfrage geht so

PHP:
    int pxl, red, blue, green, alpha;

    pxl = bitmap.getPixel(x,y);

    red = Color.red(pxl);
    blue = Color.blue(pxl);
    green = Color.green(pxl);
    alpha = Color.alpha(pxl);

die kannst du dann nach belieben verändern
das setzen eines pixels in einem bitmap geht so:
PHP:
    paint.setColor(Color.argb(alpha,red,green,blue));
    bitmap.setPixel(x,y,paint);


ABER ich habe es jetzt nciht in betracht gezogen sowas zu implementieren da ich mir nicht vorstellen aknn bei solch einen algo eine FPS über 1 zu kriegen muss ich ehrlich zugeben

alleine schon wenn ich bei meinem screen alle pixel durch gehen muss sind das 1440x2560=3.686.400 schleifendurchgänge x die 8 operationen x (im geringsten fall wenn man NUR in Abhängigkeit von den umliegenden pixeln die neue farbe setzen will) 8 pixel x 5 anweisungen pro pixelabfrage x 4 werte die zwischengespeichert werden müssen x 6-8 operationen die neuen werte aus den daten zu ermitteln wären wir bei 28.311.552.000 operationsschritten

selbst wenn jede operation nur 1 takt braucht sind das ca bei 28 Gigs und einer modernen handy CPU mindestens 3-4 sekunden für ein bild
könnten genauso gut 20 sek sein wer weiß das schon genau

nur zur groben Übersicht wenn man nicht irgendeine geheime sauce benutzt die das ganz flutschen lässt

Ich wäre trotzdem gespannt auf das Ergebnis
 
  • Danke
Reaktionen: Railwanderer
Yes das wollte ich! Manchmal sollte ich mich vor dem fragen selbst dran setzen :D waere
bestimmt als auswahlmoeglichkeit bei bitmap. angezeigt worden, danke! :)

Aber du hast recht, es ist schlauer statische bilder vorher zu bearbeiten als es durch das programm
im loading screen machen zu lassen. Andererseits koennte es spaeter interessant sein wenn
Server client beziehungen eintreten, bei einem spiel mit vielen grafiken koennte man manche so von
der app selbst bearbeiten lassen und der user muesste weniger inhalt runterladen (gedrosseltes inet)

Ich hatte schon vermutet dass es fuer jeden pixel im laufenden programm nichtmehr
hinterherkommt. Trotzdem danke! Fuer die idee mit einer minimap eine tilemap von
20x20 tiles zeichnen zu lassen wuerde die abfrage sinn ergeben, das muss ja nur einmal ausgefuehrt werden.

woher weiss man eigendlich welche operatoren viel aufwand brauchen? Also deine rechnung
kommt ja wahrscheinlich an einen guten annaeherungswert der spaeter tatsaechlich gebrauchten
zeit. Ich hab ja noch lange nicht so ein umfassendes java wissen und befuerchte schon eine weile
das meine vielen for schleifen und if abfragen frueher zum problem werden.
leider kann ich gar nicht einschaetzen was wie lange dauert oder ob zb ein
if(x>10) schneller geht als ein if (x>=11)...
 
Ich weiß das auch nicht so genau was da intern passiert
hatte früher etwas Assembler gelernt

Zum Beispiel 2 zahlen addieren erfordert folgende Schritte

Zahl 1 in Speicher holen
zahl 2 in Speicher holen
addieren Und Ergebnis speichern

Bei einem 64 Bit Prozessor wären das 1.5 takte glaube ich bin aber nicht sicher

Bei 64 Bit kann der Prozessor ja 64 Bit pro Takt auswerten ein integer hat 32 bit also kann er die beiden parallel pro takt laden das addieren ist sehr schnell durch die Verknüpfungen in der Hardware aber lässt sich auch nicht genau sagen wie lange es dauert üblicherweise Zw. 0.25 und 1er clock rate

So genau kenne ich mich auch nicht aus aber es kommt so ungefähr hin
vllt braucht es alles bei Java etwas länger k.a. wie das bei anderen Operation ist aber die sind bestimmt langsamer als Addition von 2 ints
 

Ähnliche Themen

M
Antworten
4
Aufrufe
1.173
swa00
swa00
5
Antworten
0
Aufrufe
1.151
586920
5
B
Antworten
4
Aufrufe
496
bb321
B
Zurück
Oben Unten