BPS #16: Schwarzweiß ist das neue Bunt - Auswertung

Übersicht BlitzBasic Beginners-Corner

Neue Antwort erstellen

Xeres

Moderator

Betreff: BPS #16: Schwarzweiß ist das neue Bunt - Auswertung

BeitragSo, Jan 22, 2012 15:33
Antworten mit Zitat
Benutzer-Profile anzeigen
So! Wer konnte die Transformation umsetzen?

Das war die Aufgabe

Postet hier eure Ergebnisse, Codes, Gedanken. Lernt von den anderen, seht euch deren Quelltext an und versucht euren eigenen zu verbessern.

Diskussion
Postet zu euren Codes stets eine kurze Erklärung mit euren Gedanken in denen ihr simpel gesagt die Frage "Wieso habe ich XY auf diese Art gelöst?" beantwortet. Beiträge, die nur den Code enthalten werden wir aus dem Thread entfernen.

Nächste Aufgabe
In einer Woche wird die Musterlösung nach editiert und in 2 die nächste Aufgabe eingestellt.

Viel Spaß & viel Erfolg!

Musterlösung:
BlitzBasic: [AUSKLAPPEN]

Graphics(512,256,32,2)

;* Bild Laden:
Local img = LoadImage("ToSW.png")

;* Schwarzweiß Version erzeugen:
Local img_sw = KonvertiereZuSW(img)

;* Bilder zum Vergleich anzeigen:
DrawImage(img,0,0)
DrawImage(img_sw,256,0)

WaitKey()
End

Function KonvertiereZuSW(img)
Local breit = ImageWidth(img)
Local hoch = ImageHeight(img)
;* Bild Kopieren um das Ursprungsbild nicht zu verändern:
Local New_img = CopyImage(img)

;* X,Y Koordinaten für das Bild
;* Alpha, Rot, Grün, Blau Farbbestandteile
;* ARGB Farb-Summe
Local x,y, a,r,g,b, argb

;* Den Buffer des Bildes zum Bearbeiten auswählen:
SetBuffer(ImageBuffer(New_img))
;* Buffer Sichern um schnellen Zugriff mittels Read/Write-PixelFast zu haben
LockBuffer(ImageBuffer(New_img))

;* alle Pixel des Bildes durchgehen:
For y = 0 To hoch-1
For x = 0 To breit-1
;* Einlesen der Pixelfarbe:
argb = ReadPixelFast(x,y)

;* Zerlegen der Farbe in ihre Bestandteile:
a = (argb And $FF000000)/$1000000
r = (argb And $FF0000)/$10000
g = (argb And $FF00)/$100
b = argb And $FF

;* Mittelwert der Farbe:
Local sw = (r+g+b)/3

;* Farbe wieder zusammensetzen, Alpha-Kanal bleibt unverändert
argb = a*$1000000 + sw*$10000 + sw*$100 + sw

;* Pixelfarbe Schreiben:
WritePixelFast(x,y,argb)
Next
Next
;* Buffer wieder Freigeben:
UnlockBuffer(ImageBuffer(New_img))
;* Buffer wieder zurückschalten, damit es keine Probleme mit den
;* Folgenden Zeichenbefehlen gibt.
SetBuffer(FrontBuffer())

;* Das Fertig bearbeitete Bild zurückliefern:
Return New_img
End Function

Wie DerHase so richtig im Chat bemerkte (und einige wussten oder nach schlugen) ist der Grauton hier nur ein Mittelwert. Um ein Bild in Grausstufen mit der richtigen Luminanz (d.h. die Helligkeit der Farben bleibt erhalten) zu konvertieren, muss man die Farben in einem Verhältnis von 30% Rot, 59% Grün, und 11% Blau mischen.
Wieder was gelernt!
Win10 Prof.(x64)/Ubuntu 16.04|CPU 4x3Ghz (Intel i5-4590S)|RAM 8 GB|GeForce GTX 960
Wie man Fragen richtig stellt || "Es geht nicht" || Video-Tutorial: Sinus & Cosinus
T
HERE IS NO FAIR. THERE IS NO JUSTICE. THERE IS JUST ME. (Death, Discworld)
  • Zuletzt bearbeitet von Xeres am Mo, Feb 06, 2012 0:52, insgesamt 2-mal bearbeitet

darth

BeitragSo, Jan 22, 2012 16:20
Antworten mit Zitat
Benutzer-Profile anzeigen
Hallo,

hier ist erstmal meien Funktion:

Input: Image
Output: Image

BlitzBasic: [AUSKLAPPEN]
Function greyFilter( src )
Local width = ImageWidth(src)
Local height = ImageHeight(src)

Local out = CreateImage(width, height)

Local col
Local r
Local g
Local b
Local grey

Local srcBuffer = ImageBuffer(src)
Local outBuffer = ImageBuffer(out)

LockBuffer( srcBuffer )
LockBuffer( outBuffer )

For x = 0 To width -1
For y = 0 To height -1
col = ReadPixelFast( x, y, srcBuffer )

r = (col And $FF0000)/$10000
g = (col And $FF00 )/$100
b = (col And $FF )

grey = (r + g + b) /3.

col = grey *$10000 + grey *$100 + grey

WritePixelFast( x, y, col, outBuffer )
Next
Next

UnlockBuffer( srcBuffer )
UnlockBuffer( outBuffer )

Return out
End Function


Vom Prinzip her ist es ganz einfach: Man liest jeden Pixel ein, berechnet die RGB-Werte (die "Funktion" dazu findet sich im ReadPixel - Hilfefile) und nimmt dann den Durchschnitt der drei Werte ((R+G+B)/3). Der errechnete Pixel wird dann wieder reingeschrieben (errechnen des Farb-Integers sollte sich im Writepixel - Hilfefile finden).

Anmerkung: Für ReadPixelFast und WritePixelFast braucht man LockBuffer und der Bereich geht von 0 - (width -1) (wie generell bei C-artigen Arrays).

MfG,
Darth
Diese Signatur ist leer.
  • Zuletzt bearbeitet von darth am So, Jan 22, 2012 17:47, insgesamt einmal bearbeitet

ozzi789

BeitragSo, Jan 22, 2012 16:47
Antworten mit Zitat
Benutzer-Profile anzeigen
Wiedermal viel zu viel gemacht, sorry Sad
Code: [AUSKLAPPEN]
; Beginner's Practice Series #16 - Schwarzweiss ist das neue Bunt |
;-----------------------------------------------------------------|
; ozz789 - 05.01.2012                                             |
;-----------------------------------------------------------------|
; Do whatever you want licence                                    |
;-----------------------------------------------------------------|


;Commandline von Hochkommas säubern
filepath$=Replace(CommandLine(),Chr(34),"")

;Falls keine Commandline da, also "bloss" doppelgeklickt wurde
If filepath$=""
   ;Dies dem User mitteilen
   Color 255,0,0
   Print "Es wurde kein Bild per Drag&Drop"
   Print "auf die Exe gezogen!"
   Color 255,255,255
   Print ""
   Print "Versuche Standardbild "+Chr(34)+"tosw.png"+Chr(34)+" zu laden"
   Print ""
   Print "Auf Tastendruck gehts weiter!"
   filepath$="tosw.png"
   ;Versuchen das Standardbild zu laden
   image=LoadImage(filepath$)
   ;Falls es nicht gefunden/geladen worden konnte mit Fehlermeldung abbrechen
   If image=0 RuntimeError "tosw.png konnte nicht gefunden/geladen werden...!"
   WaitKey
Else
;Falls die Commandline einen Pfad enthält, diesen versuchen zu laden
   image=LoadImage(filepath$)
   If image=0 RuntimeError "Bild konnte nicht gefunden/geladen werden...!"
EndIf

;Die Breite&Höhe des Bildes auslesen und speichern
img_width=ImageWidth(image)
img_height=ImageHeight(image)

;Falls das Bild doch etwas grösser ist den Windowscaled Modus setzen
If img_width>1280 Then
   graphics_flag=3
Else
   graphics_flag=2
EndIf


;Das Graphicsfenster doppelt so breit machen wie das Bild plus 20 pixel in der Höhe (siehe unten)
Graphics img_width*2,img_height+20,32,graphics_flag
SetBuffer BackBuffer()

;Durch das erneute Graphics setzen müssen wir unser Bild erneut laden :(
image=LoadImage(filepath$)
;Geladenes Bild anzeigen
DrawImage image,0,0
Text img_width,img_height/2,"Bin am Arbeiten ;)"
AppTitle "Bin am Arbeiten ;)"
Flip


;Buffer locken für Read/Writepixelfast
LockBuffer BackBuffer()
;Startzeit speichern, wird später benutzt
start#=MilliSecs()
;Eine Schleife erstellen die sooft durchläuft wie die Breite des Bildes (von Null beginnend)
For x=0 To img_width-1
   ;Eine Schleife erstellen die sooft durchläuft wie die Höhe des Bildes (von Null beginnend)
   For y=0 To img_height-1
      ;Den Pixel an der X/Y Koordinate auslesen (siehe Schleifenwerte von X/Y)
      rgb=ReadPixelFast(x,y,BackBuffer())
      ;Den zurückgelieferten HEX Code in R/G/B Werte aufteilen
      r = (rgb And $FF0000) / $10000
      g = (rgb And $FF00) / $100
      b = rgb And $FF
      ;Den totalen Wert aus dem R/G/B Werten zusammenaddieren und durch 3 teilen (Transformation zu S/W)
      tot=r+g+b
      tot=tot/3
      ;Den totalen Wert wieder zueinem HEX Wert zusammensetzen
      sw_rgb= tot*$10000 + tot*$100 + tot
      ;Den neuen Pixel um die Bildbreite versetzt (also rechts davon) zeichnen
      WritePixelFast x+img_width,y,sw_rgb
   Next
Next
;Endzeit speichern
finish#=MilliSecs()
;Buffer wieder unlocken
UnlockBuffer BackBuffer()
;Totale Zeit berechnen (als Float da Kommastellen benötigt werden)
total#=Float((finish#-start#)/1000)
;String präparieren
it_took$="Es dauerte "+total#+" Sekunden um das Bild in S/W umzuwandeln!"
;Diesen String nun als Apptitle setzen und ausgeben
AppTitle it_took$
Text 1,ImageHeight(image),it_took$
Flip
;Eingaben während diesem ganzen Vorgang vergessen
FlushKeys()
;Auf Keyhit warten
WaitKey
;Und tschüss
End
0x2B || ! 0x2B
C# | C++13 | Java 7 | PHP 5

joshmami

BeitragSo, Jan 22, 2012 17:16
Antworten mit Zitat
Benutzer-Profile anzeigen
Ich habe nicht wie alle anderen (bis jetzt) einfach den RGB-Durchschnitt genommen,was auch eine gute Lösung ist, sondern die sogenannte Leuchtkraft-Graustufenumwandlungsformel genommen. Diese wird unter anderem auch bei GIMP eingesetzt, glaube ich. Cool

BlitzBasic: [AUSKLAPPEN]
Graphics 1024,768,0,2 ;Fenster erstellen
AppTitle "Graustufenumwandler" ;Anwedungsname
Local Colored = LoadImage("tosw.png") ; Laden des Bildes
Local Greyscaled = GreyscaleImg(Colored) ;Bild durch Aufruf der Funktion in Graustufen umwandeln

DrawImage Colored,192,256 ;Ursprüngliches, farbiges Bild zeichnen
DrawImage Greyscaled,576,256 ;"Schwarz-Weißes" Bild zeichen

WaitKey()
End

Function GreyscaleImg(Img)
Local Image = CopyImage(Img) ;Kopieren des ursprünglichen Bilds
Local TempAlpha ;
Local TempRed ;
Local TempGreen ;
Local TempBlue ; Variablen deklarieren
Local GreyColor ;
Local TempRGBValue;
LockBuffer ImageBuffer(Image)
For x = 0 To ImageWidth(Image) - 1 ;Jede Zeile durchgehen
For y = 0 To ImageHeight(Image) - 1 ; Für die jeweilige Zeile alle Y-Werte durchgehen
TempRGBValue = ReadPixelFast(x,y,ImageBuffer(Image)) ;Auslesen jedes Pixels
TempAlpha = (TempRGBValue And $FF000000)/$1000000 ; ':
TempRed = (TempRGBValue And $FF0000)/$10000 ; :.Umwandeln der Werte in RGB bzw Alpha
TempGreen = (TempRGBValue And $FF00)/$100 ; :'
TempBlue = TempRGBValue And $FF ;,:
GreyColor = TempRed*0.3 + TempGreen*0.59 + TempBlue*0.11 ; Bilden des Einzel-Werts für jeden Pixel mit der Leuchtkraftformel für Graustufen.Alternativ könnte man auch einfach den Durchschnittswert bilden
TempRed = GreyColor ;
TempGreen = GreyColor :; RGB-Werte mit dem Einzel-Wert belegen
TempBlue = GreyColor ;
TempRGBValue = TempAlpha * $1000000 + TempRed * $10000 + TempGreen * $100 + TempBlue ;Wieder zu einem Wert zusammenfügen
WritePixelFast x,y,TempRGBValue,ImageBuffer(Image) ;Pixel wieder einfärben
Next
Next
UnlockBuffer ImageBuffer(Image)
Return Image ;Bild wird zurückgegeben
End Function
Mfg Joshmami

Tennisball

BeitragSo, Jan 22, 2012 17:19
Antworten mit Zitat
Benutzer-Profile anzeigen
Hi,

meine Formel ist die gleiche wie Darths
und ich hab als kleines Gimmick noch einen Übergang reingebastelt.

BlitzBasic: [AUSKLAPPEN]
Graphics3D 800, 600, 0, 2


image = LoadImage("tosw.png")


tex1 = CreateTexture( ImageWidth( image ), ImageHeight( image ) )
tex2 = CreateTexture( ImageWidth( image ), ImageHeight( image ) )


SetBuffer( TextureBuffer( tex2 ) )

DrawImage image, 0, 0

LockBuffer()

For x = 0 To 255
For y = 0 To 255
rgb = ReadPixelFast( x, y )
r = (rgb And $FF0000)/$10000
g = (rgb And $FF00)/$100
b = rgb And $FF
asdf = ( r + g + b ) / 3
rgb2 = 256*$1000000 + asdf*$10000 + asdf*$100 + asdf
WritePixelFast( x, y, rgb2 )
Next
Next

UnlockBuffer()


SetBuffer( TextureBuffer( tex1 ) )

DrawImage image, 0, 0


SetBuffer BackBuffer()



timer = CreateTimer( 60 )



alpha# = 0.9


camera = CreateCamera()
PositionEntity camera, 0, 0, -4

cube1 = CreateCube()
EntityTexture cube1, tex1
cube2 = CreateCube()
EntityTexture cube2, tex2



Repeat

If alpha > 0 Then alpha = alpha - 0.005
EntityAlpha cube1, alpha

RenderWorld
UpdateWorld

WaitTimer timer
Flip 0
Cls

Until KeyHit( 1 )


End


mfg,
Tennisball

Blitzcraft

BeitragSo, Jan 22, 2012 22:58
Antworten mit Zitat
Benutzer-Profile anzeigen
MASTEREDIT( Cool ):
Danke für die kleine Bemerkung Holzchopf Wink
Mein Beitrag(BMax)
  • Zuletzt bearbeitet von Blitzcraft am So, Jan 22, 2012 23:21, insgesamt 2-mal bearbeitet

Holzchopf

Meisterpacker

BeitragSo, Jan 22, 2012 23:11
Antworten mit Zitat
Benutzer-Profile anzeigen
@Blitzcraft: Die anderen posten BMax-Codes wohl im BMax-Pendant Wink
Erledige alles Schritt um Schritt - erledige alles. - Holzchopf
CC BYBinaryBorn - Yogurt ♫ (31.10.2018)
Im Kopf da knackt's und knistert's sturm - 's ist kein Gedanke, nur ein Wurm
 

Bamboo

BeitragDo, Jan 26, 2012 18:11
Antworten mit Zitat
Benutzer-Profile anzeigen
BlitzBasic: [AUSKLAPPEN]
image = LoadImage("sample.png")


imgHeight = ImageHeight(image)
imgWidth = ImageWidth(image)

Graphics imgWidth*2, imgHeight, 32, 2
SetBuffer BackBuffer()

DrawImage image, 0, 0

LockBuffer BackBuffer()

For y = 0 To imgHeight - 1
For x = 0 To imgWidth - 1
rgbValue = ReadPixelFast(x, y)

rValue = (rgbValue And $FF0000) / $10000
gValue = (rgbValue And $FF00) / $100
bValue = (rgbValue And $FF)

bwValue = (rValue + gValue + bValue) / 3

newValue = 255 * $1000000 + bwValue * $10000 + bwValue * $100 + bwValue

WritePixelFast(x + imgWidth, y, newValue)

Next
Next

UnlockBuffer BackBuffer()
Flip

WaitKey:End


Dasselbe System wie bei allen anderen auch...

count-doku

BeitragDo, Jan 26, 2012 18:16
Antworten mit Zitat
Benutzer-Profile anzeigen
Hallo,

etwas länger und mehr "objekt orientiert" aber vom Kern her das Gleiche. Very Happy
BlitzBasic: [AUSKLAPPEN]
Graphics 600,300,0,2
SetBuffer BackBuffer()


Local infile.TImage=LoadMyImage("tosw.png")
Local outfile.TImage=Color2SW(infile,Null)
SaveMyImage(outfile,"bnw.bmp")
DrawImage infile\hwnd,0,0
DrawImage outfile\hwnd,258,0

Flip
WaitKey
End


Type TImage
Field width%,height%
Field hwnd%,buff%
End Type


Function CreateMyImage.TImage(width%,height%)
Local image.TImage=New TImage
image\hwnd=CreateImage(width,height)
If image\hwnd=0 Then RuntimeError "Bild nicht gefunden!"
image\buff=ImageBuffer(image\hwnd)
image\width=width
image\height=height
Return image.TImage
End Function
Function LoadMyImage.TImage(filename$)
Local image.TImage=New TImage
image\hwnd=LoadImage(filename)
If image\hwnd=0 Then RuntimeError "Bild nicht gefunden!"
image\buff=ImageBuffer(image\hwnd)
image\width=ImageWidth(image\hwnd)
image\height=ImageHeight(image\hwnd)
Return image.TImage
End Function
Function Color2SW.TImage(src.TImage,dst.TImage)
If src.TImage=Null Then RuntimeError "Bild nicht gefunden!"
If dst.TImage=Null Then dst.TImage=CreateMyImage(src\width,src\height)
LockBuffer src\buff
LockBuffer dst\buff
For y=0 To src\height-1
For x=0 To src\width-1
Local argb=ReadPixelFast(x,y,src\buff)
Local a = (argb And $FF000000)/$1000000
Local r = (argb And $FF0000)/$10000
Local g = (argb And $FF00)/$100
Local b = argb And $FF
Local rgb=(r+g+b)/3
argb = a*$1000000 + rgb*$10000 + rgb*$100 + rgb
WritePixelFast(x,y,argb,dst\buff)
Next
Next

UnlockBuffer src\buff
UnlockBuffer dst\buff
Return dst.TImage

End Function
Function SaveMyImage(src.TImage,filename$)
If src.TImage=Null Then RuntimeError "Bild nicht gefunden!"
SaveImage(src\hwnd,filename)
End Function


lg,
count-doku

Neue Antwort erstellen


Übersicht BlitzBasic Beginners-Corner

Gehe zu:

Powered by phpBB © 2001 - 2006, phpBB Group