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

Für allgemeine Fragen zur Programmierung mit PureBasic.
FlowPX2
Beiträge: 42
Registriert: 05.05.2008 14:08

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

Beitrag 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
Zuletzt geändert von FlowPX2 am 09.05.2008 01:39, insgesamt 1-mal geändert.
Rokur
Beiträge: 167
Registriert: 29.12.2005 09:58
Computerausstattung: Intel Core2 Quad (4x2,4 GHz), 4096 MB RAM, GForce 8800GTX 786 MB
Windows XP 32 Bit, PureBasic 4.40 (x86)

Beitrag von Rokur »

Schau dir mal die Shift-Operatoren (<< und >>) an, damit kannst du Werte bitweise verschieben.
FlowPX2
Beiträge: 42
Registriert: 05.05.2008 14:08

Beitrag 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
Benutzeravatar
NicknameFJ
Beiträge: 324
Registriert: 03.06.2007 14:36
Wohnort: Von der Sonne aus gesehen der dritte Planet

Beitrag 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
PS: Alle im Text enthaltenen Schreibfehler sind beabsichtigt und dienen der Belustigung aller

Bild
FlowPX2
Beiträge: 42
Registriert: 05.05.2008 14:08

Beitrag 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
Benutzeravatar
Helle
Beiträge: 566
Registriert: 11.11.2004 16:13
Wohnort: Magdeburg

Beitrag 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
Zuletzt geändert von Helle am 08.05.2008 22:23, insgesamt 1-mal geändert.
FlowPX2
Beiträge: 42
Registriert: 05.05.2008 14:08

Beitrag von FlowPX2 »

Das ist nicht nur ein Vorschlag... Das ist super ^^ Funktioniert Prima... danke ^^
FlowPX2
Beiträge: 42
Registriert: 05.05.2008 14:08

Beitrag 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
Benutzeravatar
Helle
Beiträge: 566
Registriert: 11.11.2004 16:13
Wohnort: Magdeburg

Beitrag 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
FlowPX2
Beiträge: 42
Registriert: 05.05.2008 14:08

Beitrag 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
Antworten