Seite 1 von 4

Bytes zu 12 Bits und anders herum. (Fehlerhafter LZW Source)

Verfasst: 08.05.2008 14:31
von FlowPX2
Hallo,
unter C# oder so würd ich jetzt eine schnelle Methode wissen, doch in PureBasic fällt mir gerade keine ein.

Folgendes:
Ich lese aus einer Datei ein Byte von 0 bis 255
dann lese ich ein zweites Byte wieder 0 bis 255

jetzt möchte ich diese 2 Bytes welche eigentlich 16bits benötigt in 24bits schreiben. Also 12bits pro Byte das wären 0 bis 4096 Möglichkeiten.

Zum Beispiel:
Erstes Byte zu bits = 00000001
Zweites Byte zu bits = 00000111

eigentlich sieht es so aus: 0000000100000111
jetzt möchte ich es aber so in die Datei schreiben: 000000000001000000000111

Vorher 2bytes groß jetzt 3bytes groß.
Und da dannach möchte ich wieder die 3bytes auslesen können aus der Datei und von diesen 3bytes jeweils wieder 12bits lesen und zu einem Longwert convertieren.


Da würd mich jetzt halt die schnellste Methode unter PureBasic interessieren, weil es ja bei der Komprimierung auch um Geschwindigkeit geht. Falls jemand da eine gute Lösung wüsste wäre super, ansonsten würde ich mich auch freuen wenn jemand vll. andere hilfreiche tipps zu bits zu bytes und bytes zu bits geben könnte.

mfg.
FlowPX2

Verfasst: 08.05.2008 14:37
von Rokur
Schau dir mal die Shift-Operatoren (<< und >>) an, damit kannst du Werte bitweise verschieben.

Verfasst: 08.05.2008 15:09
von FlowPX2
Hab was interessantes hier im Forum gefunden... Das mit den Shift Operatoren arbeitet. werd damit mal herum Spielen.

Der Code ist:

Code: Alles auswählen

Macro TestBit(value,bit)
  (value>>bit&1)
EndMacro

Macro SetBit(value,bit)
  (1 << bit | value)
EndMacro

Macro ClrBit(value,bit)
  (~(1 << bit) & value)
EndMacro

Debug "Die Zahl 5 - Bit für Bit"
Debug "Das 1. Bit:     "+Str(TestBit(5,0))
Debug "Das 2. Bit:     "+Str(TestBit(5,1))
Debug "Das 3. Bit:     "+Str(TestBit(5,2))
Debug "Und hier in einer Zeile: "+Bin(5)

Value = 0

Debug "Setze Bit 0"
Value = SetBit(Value,0)
Debug "Setze Bit 2"
Value = SetBit(Value,2)
Debug "Ergebis= " + Str(Value)

Debug "Lösche Bit 0"
Value = ClrBit(Value, 0)
Debug "Ergebis= " + Str(Value)

lVal.l = 0

Debug "Setze Bit 31"
lVal = SetBit(lVal,31)
Debug "Ergebis= " + Str(lVal)
Debug "Ergebis= " + Bin(lVal)

llVal.q = 0

Debug "Setze Bit 63"
llVal = SetBit(llVal,63)
Debug "Ergebis= " + StrQ(llVal)
Debug "Ergebis= " + BinQ(llVal) 
mfg.
FlowPX2

Verfasst: 08.05.2008 19:28
von NicknameFJ
Hallo !

Mit Assembler dürfte es am schnellsten sein

etwa so

Code: Alles auswählen

result = 0
Wert1.b = %00000001 
Wert2.b = %00000111


! Xor Eax,Eax
! mov ah,[v_Wert1]
! shl Eax,4
! mov al,[v_Wert2]
! mov [v_result],Eax

Debug result

Debug "Nur zur Kontrolle:      " 
Debug % 000000000001000000000111 


Grüße

Joachim

Verfasst: 08.05.2008 20:35
von FlowPX2
Ahh das ist gut... Nur leider kann ich da wirklich nur Maximal 255 bei den Bytes angeben... doch ich müsste Maximal die Zahl 4095 zweimal angeben können... Daher möchte ich das jede zahl 12bit nutzt statt 8bit

Ich hab mir eine sehr umständliche funktion in PureBasic geschrieben...

Code: Alles auswählen

Macro TestBit(value,bit)
  (value>>bit&1)
EndMacro

Macro SetBit(value,bit)
  (1 << bit | value)
EndMacro

Macro ClrBit(value,bit)
  (~(1 << bit) & value)
EndMacro

Global Dim BitBytes(2)

Procedure IntToBit(byteA, byteB)

For A = 0 To 11

  If A < 4
    Index = 1
    Pos = A+4
  Else
    Index = 0
    Pos = A-4
  EndIf
  
  If TestBit(byteA,A) = 1
    BitBytes(Index) = SetBit(BitBytes(Index),Pos)
  Else
    BitBytes(Index) = ClrBit(BitBytes(Index),Pos)
  EndIf
Next 

For B = 0 To 11

  If B < 8
    Index = 2
    Pos = B
  Else
    Index = 1
    Pos = B-8
  EndIf
  
  If TestBit(byteB,B) = 1
    BitBytes(Index) = SetBit(BitBytes(Index),Pos)
  Else
    BitBytes(Index) = ClrBit(BitBytes(Index),Pos)
  EndIf
Next 
Der Code ist so schlecht, dass er doch wieder interessant ist xD

In Assembler wäre das bestimmt um einiges schneller und kleiner ^^
Nur keine ahnung wie ^^

Hab folgendes Probiert

Code: Alles auswählen

Wert1.b = 255
Wert2 = 4095


! Xor Eax,Eax
! mov ah,[v_Wert1]
! shl Eax,4
! mov ax,[v_Wert2]
! mov [v_result],Eax
Ohje Sinnlos ist das aber ^^ keine ahnung wie das funktionieren soll.

mfg.
FlowPX2

Verfasst: 08.05.2008 21:11
von Helle
Nicht weiter getestet; nur ein Vorschlag:

Code: Alles auswählen

Global Wert1.w = %101000000001    ;irgendweiche 12 Bits 
Global Wert2.w = %111100000111 

!movzx eax,[v_Wert1] 
!shl eax,4 
!mov dx,[v_Wert2] 
!shl edx,12+4 
!or eax,edx 
!shr eax,4 

!mov [v_Result],eax 

Debug RSet(Bin(Result), 24, "0") 
Debug "Kontrolle :" 
Debug RSet(Bin(Wert2), 12, "0") + RSet(Bin(Wert1), 12, "0")
Gruß
Helle

Verfasst: 08.05.2008 21:23
von FlowPX2
Das ist nicht nur ein Vorschlag... Das ist super ^^ Funktioniert Prima... danke ^^

Verfasst: 08.05.2008 22:22
von FlowPX2
Irgendwie will das nicht...
Es sollte 2 Zahlen Werte von 0 bis 4095 in 24bit unter bekommen... das klappt dank Helle..

Jetzt wollte ich diese 2 Zahlen also diese 24bit in 8bit aufteilen damit ich Bytes bekomme welche ich in eine Datei schreiben kann... Leider funktioniert es nur halb!?

Das erste Beispiel funktioniert ohne Probleme... Doch bei Beispiel 2, wenn bei einem byte das erste bit 1 ist werden die anderen 7bits auch mit 1 gefüllt... Kommt mir irgendwie seltsam vor!?

Code: Alles auswählen

Wert1.w = %000001100000    ;irgendwelche 12 Bits
Wert2.w = %011000000110

Byte1.b = 0
Byte2.b = 0
Byte3.b = 0
Result = 0

!mov ax,[v_Wert1]
!shl eax,4
!mov dx,[v_Wert2]
!shl edx,12+4
!or eax,edx
!shr eax,4
!mov [v_Result],eax
!mov [v_Byte2],ah
!mov [v_Byte3],al
!shr eax,8
!mov [v_Byte1],ah

Debug "##### Richtig! #####"
Debug "Alles  :  "+RSet(Bin(Result), 24, "0")
Debug "Byte 1:  "+RSet(Bin(Byte1.b), 8, "0")
Debug "Byte 2:  "+RSet(Bin(Byte2.b), 8, "0")
Debug "Byte 3:  "+RSet(Bin(Byte3.b), 8, "0")


; Hier werden alle Bits total mit 1 gefüllt
Wert1.w = %000011100000    ;irgendwelche 12 Bits
Wert2.w = %111000001110

Byte1.b = 0
Byte2.b = 0
Byte3.b = 0
Result = 0

!mov ax,[v_Wert1]
!shl eax,4
!mov dx,[v_Wert2]
!shl edx,12+4
!or eax,edx
!shr eax,4
!mov [v_Result],eax
!mov [v_Byte2],ah
!mov [v_Byte3],al
!shr eax,8
!mov [v_Byte1],ah
Debug ""
Debug "##### Falsch! #####"
Debug "Alles  :  "+RSet(Bin(Result), 24, "0")
Debug "Byte 1:  "+RSet(Bin(Byte1.b), 8, "0")
Debug "Byte 2:  "+RSet(Bin(Byte2.b), 8, "0")
Debug "Byte 3:  "+RSet(Bin(Byte3.b), 8, "0")
mfg.
FlowPX2

Verfasst: 08.05.2008 22:39
von Helle
Fußball-Gucken lenkt doch immer ab (Eisern Union)... Habe obigen Code korrigiert, High-Word von eax muß natürlich auf Null gesetzt werden.
Unsigned Byte (c) anstatt signed Byte (b) verwenden!

Code: Alles auswählen


Wert1.w = %000001100000    ;irgendwelche 12 Bits 
Wert2.w = %011000000110 

Byte1.c = 0 
Byte2.c = 0 
Byte3.c = 0 
Result.l = 0 

!movzx eax,[v_Wert1] 
!shl eax,4 
!mov dx,[v_Wert2] 
!shl edx,12+4 
!or eax,edx 
!shr eax,4 
!mov [v_Result],eax 
!mov [v_Byte2],ah 
!mov [v_Byte3],al 
!shr eax,8 
!mov [v_Byte1],ah 

Debug "##### Richtig! #####" 
Debug "Alles  :  "+RSet(Bin(Result), 24, "0") 
Debug "Byte 1:  "+RSet(Bin(Byte1), 8, "0") 
Debug "Byte 2:  "+RSet(Bin(Byte2), 8, "0") 
Debug "Byte 3:  "+RSet(Bin(Byte3), 8, "0") 


; Hier werden alle Bits total mit 1 gefüllt 
Wert1.w = %000011100000    ;irgendwelche 12 Bits 
Wert2.w = %111000001110 

Byte1 = 0 
Byte2 = 0 
Byte3 = 0 
Result = 0 

!movzx eax,[v_Wert1] 
!shl eax,4 
!mov dx,[v_Wert2] 
!shl edx,12+4 
!or eax,edx 
!shr eax,4 
!mov [v_Result],eax 
!mov [v_Byte2],ah 
!mov [v_Byte3],al 
!shr eax,8 
!mov [v_Byte1],ah 
Debug "" 
Debug "##### Falsch! #####" 
Debug "Alles  :  "+RSet(Bin(Result), 24, "0") 
Debug "Byte 1:  "+RSet(Bin(Byte1), 8, "0") 
Debug "Byte 2:  "+RSet(Bin(Byte2), 8, "0") 
Debug "Byte 3:  "+RSet(Bin(Byte3), 8, "0") 
Gruß
Helle

Verfasst: 08.05.2008 22:53
von FlowPX2
Hmm mit c klappt es bei mir nicht da meint der hier ist ein Fehler
PureBasic.asm[112]:
mov [v_Byte2], ah
error; operand sizes do not match.

Hab es jetzt aber so gelöst...Mit &$FF... Hab ganz vergessen das b signed ist in PureBasic. Sowas passiert wenn man zuviel C# programmiert ^^
Danke nochmal für den tipp.

Code: Alles auswählen

Wert1.w = %000001100000    ;irgendwelche 12 Bits
Wert2.w = %011000000110

Byte1.b = 0
Byte2.b = 0
Byte3.b = 0
Result.l = 0

!movzx eax,[v_Wert1]
!shl eax,4
!mov dx,[v_Wert2]
!shl edx,12+4
!or eax,edx
!shr eax,4
!mov [v_Result],eax
!mov [v_Byte2],ah
!mov [v_Byte3],al
!shr eax,8
!mov [v_Byte1],ah

Debug "##### Richtig! #####"
Debug "Alles  :  "+RSet(Bin(Result), 24, "0")
Debug "Byte 1:  "+RSet(Bin(Byte1&$FF), 8, "0")
Debug "Byte 2:  "+RSet(Bin(Byte2&$FF), 8, "0")
Debug "Byte 3:  "+RSet(Bin(Byte3&$FF), 8, "0")
mfg.
FlowPX2