Hallo,
derzeit versuche ich, eine im Maker berechnete Pseudo-Tiefenunschärfe (DOF) zu realisieren. Den Algorithmus, eine einfache Variante des Box blur, habe ich mir nach etwas Recherche selbst zusammengeschustert, mit dem Ergebnis bin ich auch absolut glücklich, allerdings – Maker-Veteranen werden es schon ahnen – frisst das ganze eine knackige Menge CPU-Zeit. Ein Ansatz meinerseits war, die ursprüngliche Bitmap erst einmal auf ein Viertel (halbe Breite, halbe Höhe) mittels stretch_blt zu schrumpfen, dann dort blur anzuwenden und das Ergebnis wieder auf die Ausgangsgröße zu ziehen. Auch hier ist das Ergebnis zufriedenstellend, aber ein Geschmäckle durch die doppelt großen Pixel bleibt – blur auf der vollen Auflösung schaut doch ein wenig feiner aus.
Es geht in meinem Fall im Wesentlichen um Pictures mit meist üppigem transparenten Rand (wie angehängt), hier habe ich schon selbst versucht anzusetzen und mit einem Überspringen der gänzlich transparenten Pixel experimentiert (siehe die auskommentierten "speedhacks"); es geht damit deutlich flotter, aber bei meinem, zugegeben simplen Ansatz werden die Kanten der Bilder nicht sauber in die Transparenz verblendet.
[ruby]class Bitmap
# usage: RPG::Cache.picture("filename").blur
def blur
# create a colormap of the bitmap for faster access
colormap = Hash.new
for x in 0..width
for y in 0..height
colormap[[x,y]] = get_pixel(x,y)
end
end
# actual box blur
for x in 0..width
for y in 0..height
# sum of colors around position [x,y]
# speedhack
#next if colormap[[x,y]].alpha.zero?
clr = [0,0,0,0]
for i in -1..1
for j in -1..1
pxl = colormap[[x-i,y-j]]
# compensate for areas outside the image
pxl = Color.new(0,0,0,0) if pxl.nil?
# speedhack
#next if pxl.alpha.zero?
# squaring each RGB value to approximate linear color space
clr[0] += pxl.red**2
clr[1] += pxl.green**2
clr[2] += pxl.blue**2
clr[3] += pxl.alpha
end
end
# averaging and applying square root to return to sRGB
fill_rect(x, y, 1, 1, Color.new(
Math.sqrt(clr[0]/9),Math.sqrt(clr[1]/9),Math.sqrt(clr[2]/9),clr[3]/9))
end
end
end
end[/ruby]
Das ganze ist, natürlich, nicht als Echtzeit-Effekt gedacht, sonders soll beispielsweise während eines Mapwechsels stattfinden, quasi als Ladezeit; im Projekt selbst benutze ich nicht die ursprüngliche Game.exe, sondern mkxp, ein mittlerweile eingestelltes Projekt, das die Engine des RMXP zeitgenössisch nachbildet und sie dabei, unbeabsichtigt, deutlich flotter macht.
Für Vorschläge, wie man den ursprünglichen Code optimieren könnte, Anregungen oder gar einen ganz anderen, besseren Code, wäre ich ausgesprochen dankbar.
Gruß, dorsch