Seite 3 von 6

Re: SetBits / GetBits gut genug?

Verfasst: 27.10.2018 09:56
von #NULL
Sicro hat geschrieben:Bei Macros werden Formeln nochmal in Klammern gesetzt, damit die Macros auch innerhalb von Formeln unproblematisch verwendet werden können (die Operatoren-Priorität bleibt erhalten).
Ich würde bei Macros aus dem selben Grund auch die Verwendung der Parameter immer einklammern, falls dort Ausdrücke angebenen werden.

Code: Alles auswählen

Macro GetBits(_variable_, _offset_)
  (((_variable_) >> (_offset_)) & %111)
EndMacro

Re: SetBits / GetBits gut genug?

Verfasst: 27.10.2018 16:16
von Mijikai
STARGÅTE hat geschrieben:...
Vielleicht kannst du ja einfach mal die gesamte Bearbeitungsschleife posten, damit wie da mal drüber gucken können.
Wie ich das mitbekommen habe geht es um Grauwerte (3 Bit), was schon mal n fürchterliche Anzahl ist.

Was muss denn genau getan werden bei der Verarbeitung ...
Hallo @STARGÅTE 8)

hier mal meine Hauptschleife:

Code: Alles auswählen

Procedure.i Encode(*img.IMAGE_STRUCT)
  Protected ImageX.i
  Protected ImageY.i
  Protected *ScanLine
  Protected *Pixel.COLOR_STRUCT
  Protected Offset.i
  With *img
    \Image\Pixel\BufferSize = \Bitmap\bmWidth * \Bitmap\bmHeight
    \Image\Pixel\Buffer = AllocateMemory(\Image\Pixel\BufferSize)
    If \Image\Pixel\Buffer
      If \Bitmap\bmBitsPixel = 32
        ;//ALPHA IMG
      Else
        For ImageY = 0 To \Bitmap\bmHeight - 1
          *ScanLine = \Bitmap\bmBits + (ImageY * \Bitmap\bmWidthBytes)
          For ImageX = 0 To \Bitmap\bmWidth - 1
            *Pixel = *ScanLine + (ImageX * \Bitmap\PixelSize)  
            SetBits(\Image\Pixel\Buffer,Offset,GrayScale(*Pixel));RGBA -> GrayScaleIndex (0 - 7) -> SetBits GrayscaleIndex 
            Offset + 3;BitOffset
          Next
        Next
        \Image\Pixel\BufferSize = (Offset + 8) / 8
        ProcedureReturn #True
      EndIf
      FreeMemory(\Image\Pixel\Buffer)
      \Image\Pixel\Buffer = #Null
    EndIf
  EndWith
EndProcedure

Re: SetBits / GetBits gut genug?

Verfasst: 27.10.2018 18:36
von STARGÅTE
Was macht denn GrayScale(*Pixel)?
Ich vermute RGB zu Gray umwandeln, was vermutlich um Welten länger dauert als deine SetBits-Prozedur/Makro.
Dort sollte man also auch Ansetzen!

Des weiteren könnte man immer 8 Pixel mit ein Rutsch umwandelt, weil man dann 24Bit gleichzeitig schreibt, was etwas angenehmer ist als immer nur 3 einzel Bits.

Re: SetBits / GetBits gut genug?

Verfasst: 27.10.2018 18:49
von Mijikai
STARGÅTE hat geschrieben:Was macht denn GrayScale(*Pixel)?
Ich vermute RGB zu Gray umwandeln, was vermutlich um Welten länger dauert als deine SetBits-Prozedur/Makro.
Dort sollte man also auch Ansetzen!

Des weiteren könnte man immer 8 Pixel mit ein Rutsch umwandelt, weil man dann 24Bit gleichzeitig schreibt, was etwas angenehmer ist als immer nur 3 einzel Bits.
Macht Sinn, aber wie kann ich 6 RGBA Werte gleichzeitig bearbeiten?

Hier ist meine Grayscale Funktion:

Code: Alles auswählen

Procedure.i GrayScale(*Color.COLOR_STRUCT)
  Protected Diffusion.i
  Protected GrayScale.i
  Diffusion = Int(Round(#COLOR_FAC * *Color\RGBA[0] / #COLOR_SEG,#PB_Round_Nearest) * #COLOR_DIV)
  Diffusion + Int(Round(#COLOR_FAC * *Color\RGBA[1] / #COLOR_SEG,#PB_Round_Nearest) * #COLOR_DIV)
  Diffusion + Int(Round(#COLOR_FAC * *Color\RGBA[2] / #COLOR_SEG,#PB_Round_Nearest) * #COLOR_DIV)
  Diffusion = Diffusion / 3   ;get grayscale
  Diffusion / 32              ;get index (0 - 7) bits 
  GrayScale = Diffusion * 32  ;set the grayscale to the current image (map it to the actual grayscale table)
  *Color\RGBA[0] = GrayScale
  *Color\RGBA[1] = GrayScale
  *Color\RGBA[2] = GrayScale
  ProcedureReturn Diffusion   ;return index bits
EndProcedure

Re: SetBits / GetBits gut genug?

Verfasst: 27.10.2018 20:29
von juergenkulow
Hallo Mijikai,

Code: Alles auswählen

; Register r8..r13 mit Daten laden, Shift the Bits, Gebe 2. Byte r8 Register aus.   
CompilerIf #PB_Processor_x64<>#PB_Compiler_Processor : CompilerError: "X64 Code" : CompilerEndIf
EnableASM : DisableDebugger
Define RegR8L.a=$42
RegRAX=?mydata
mov rax,RegRAX
Mov r8, [rax]
mov r9, [rax+3]
mov r10,[rax+6]
mov r11,[rax+9]
mov r12,[rax+$c]
mov r13,[rax+$f]
SAR r8,8  ; Shift the Bits Right - in PureBasic Reg8=RegR8>>8 
Mov RegR8L,r8l
EnableDebugger
Debug Hex(RegR8L,#PB_Byte)
DataSection : mydata:
  Data.a $FF,$EE,$DD,$CC,$BB,$AA,$99,$88,$77,$66,$55,$44,$33,$22,$11,$00,$FE,$ED : EndDataSection
Gruß

Re: SetBits / GetBits gut genug?

Verfasst: 27.10.2018 21:09
von Mijikai
juergenkulow hat geschrieben: ; Register r8..r13 mit Daten laden, Shift the Bits, Gebe 2. Byte r8 Register aus.
...
:? ...was macht der Code?

Re: SetBits / GetBits gut genug?

Verfasst: 28.10.2018 00:07
von juergenkulow
Der Code schreibt 6 RGB Werte aus dem Speicher, hier der Datasection, in die Prozessorregister r8 bis r13. Auf die Register kann dann quasi gleichzeitig zugegriffen werden.
Ablauf: Die Adresse von mydata: wird in die Variable RegRAX geschrieben.
Die Variable RegRAX wird in das Register rax geschrieben.
Der Inhalt von der Adresse rax wird in das Register r8 geschrieben.
Der Inhalt von der Adresse rax+3 wird in das Register r9 geschreiben.
...
Inhalt Register ist:
R8 : 8899AABBCCDDEEFF
R9 : 5566778899AABBCC
R10 : 2233445566778899
R11 : FE00112233445566
R12 : 0000EDFE00112233
R13 : 0030500000EDFE00
Nur die letzten 3 Byte sind wichtig.
Um an das 2. Byte von R8 zu kommen mache ich SAR r8,8 und hole das unterste Byte von R8 mit dem R8L-Register heraus zur weiteren Verarbeitung, hier Ausgabe mit Debug.

Mit Zeigern kann man einfach auf Daten zugreifen:

Code: Alles auswählen

Structure DreiByteTyp : Dreier.a[3] :EndStructure
Structure SechsMalDreiByteTyp : z18.a[18] : EndStructure
*Zeiger.DreiByteTyp=?mydata
*z.SechsMalDreiByteTyp=*Zeiger
Debug Hex(*Zeiger\Dreier[1],#PB_Byte)
Debug Hex(*z\z18[1],#PB_Byte)
*Zeiger+3
Debug Hex(*Zeiger\Dreier[0],#PB_Byte)+" "+Hex(*Zeiger\Dreier[1],#PB_Byte)+" "+Hex(*Zeiger\Dreier[2],#PB_Byte)
*Zeiger+$C
Debug Hex(*Zeiger\Dreier[0],#PB_Byte)+" "+Hex(*Zeiger\Dreier[1],#PB_Byte)+" "+Hex(*Zeiger\Dreier[2],#PB_Byte)
Debug Hex(*z\z18[15],#PB_Byte)+" "+Hex(*z\z18[16],#PB_Byte)+" "+Hex(*z\z18[17],#PB_Byte)
DataSection : mydata:
  Data.a $FF,$EE,$DD,$CC,$BB,$AA,$99,$88,$77,$66,$55,$44,$33,$22,$11,$00,$FE,$ED : EndDataSection

Re: SetBits / GetBits gut genug?

Verfasst: 28.10.2018 13:05
von Mijikai
juergenkulow hat geschrieben:Der Code schreibt 6 RGB Werte aus dem Speicher, hier der Datasection, in die Prozessorregister r8 bis r13. Auf die Register kann dann quasi gleichzeitig zugegriffen werden.
Ablauf: Die Adresse von mydata: wird in die Variable RegRAX geschrieben.
Die Variable RegRAX wird in das Register rax geschrieben.
Der Inhalt von der Adresse rax wird in das Register r8 geschrieben.
Der Inhalt von der Adresse rax+3 wird in das Register r9 geschreiben.
...
Ich steh aufm Schlauch... :?
Was für Vorteile hat das?
Alle Berechnungen werden nach wie vor nacheinander abgearbeitet.
Da brauch ich nicht erst noch alles in Register schreiben?

Re: SetBits / GetBits gut genug?

Verfasst: 28.10.2018 17:13
von juergenkulow
Hallo Mijikai,
der Vorteil von Operationen die direkt auf dem Prozessor ohne Speicherzugriffe ausgeführt werden ist Geschwindigkeit. Für vier Setbits mit Grayscale liegt die bei mir gemessene Geschwindigkeit bei etwa 11.000 Takten. Das wäre bei einem 4k-Bild etwa 10 Sekunden.

Noch eine Frage: Warum sind die Farben gleich gewichted? (#COLOR_DIV, #COLOR_FAC,#COLOR_SEG) Das ist irgentwie ungewöhnlich.

Gruß

Re: SetBits / GetBits gut genug?

Verfasst: 28.10.2018 17:28
von ccode_new
Hallo,
mich interessiert das Thema mit den Grafikfiltern (z.B. Graustufen) auch.
Aber in fast Echtzeit! Also werde ich kaum um Shader herumkommen.
(Das hier ist für den Einstieg ganz interessant.)
Für Game/Video-Filter.

Das mit Gewichtung würde mich hier auch mal interessieren.

Normal sollte man bei einer Graustufenumwandlung eine Gewichtung vornehmen und nicht nur eine einfache Entsättigung.

(Z.B. Rot 30%, Grün 59%, Blau 11%) - Grün sollte den höchsten Prozentanteil haben.

(Für ein "Warum" hilft die Suchmaschine des Vertrauens.)