Advertisement
Guest User

Untitled

a guest
Sep 10th, 2016
88
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. ;https://en.wikipedia.org/wiki/LZW
  2.  
  3. Structure tINFOENTRY
  4.     First.l
  5.     Second.l
  6. EndStructure
  7.  
  8. Structure ByteArray
  9.     Byte.a[0]
  10. EndStructure
  11.  
  12. Structure LongArray
  13.     Long.l[0]
  14. EndStructure
  15.  
  16. Macro __CHECKBITS()
  17. ;   If  CurrentTableEntry+257 >= (1<<CurrentBitSize)
  18. ;       CurrentBitSize+1
  19. ;   EndIf
  20.     CurrentBitSize  +   Bool(CurrentTableEntry+257 >= (1<<CurrentBitSize))
  21. EndMacro
  22.  
  23.  
  24. Global Dim RenderedString.a(1000000)
  25. Global RenderedLength;.l
  26.  
  27. Procedure WriteEntry(*DataPtr.ByteArray,*DataOffset.Long, *BitOffset.Long,Entry.l,EntrySize.l)
  28.    
  29.     Protected LocalValue.a  =   *DataPtr\Byte[*DataOffset\l]
  30.    
  31.     For i   =   1   To  EntrySize
  32.        
  33.         ; Frisches byte immer löschen
  34.         If  *BitOffset\l    =   #NUL
  35.             LocalValue  =   #NUL
  36.         EndIf
  37.        
  38.         TestBit = Entry&1
  39.         Entry>>1
  40.        
  41.         LocalValue | (TestBit<<*BitOffset\l)
  42.        
  43.         *BitOffset\l+1
  44.        
  45.         If  *BitOffset\l    >   7;=8
  46.             *BitOffset\l    =   #NUL
  47.             *DataPtr\Byte[*DataOffset\l] = LocalValue
  48.             *DataOffset\l   +   1
  49.             LocalValue      =   *DataPtr\Byte[*DataOffset\l]
  50.         EndIf
  51.        
  52.     Next
  53.    
  54.     *DataPtr\Byte[*DataOffset\l] = LocalValue
  55.    
  56. EndProcedure
  57.  
  58.  
  59. Procedure ReadEntry(*DataPtr.ByteArray,*DataOffset.Long, *BitOffset.Long,*Entry.Long,EntrySize.l)
  60.    
  61.     Protected TestByte.a    = *DataPtr\Byte[*DataOffset\l] >> *BitOffset\l
  62.    
  63.     For i   =   1   To  EntrySize
  64.        
  65.         TestBit =  TestByte&1
  66.        
  67.         Entry | (TestBit<<BitOffset)
  68.        
  69.         BitOffset   +   1
  70.        
  71.         TestByte    >>  1
  72.         *BitOffset\l    +   1
  73.        
  74.         If  *BitOffset\l    >   7;=8
  75.             *BitOffset\l    =   #NUL
  76.             *DataOffset\l   +   1
  77.             TestByte            =   *DataPtr\Byte[*DataOffset\l]
  78.         EndIf
  79.        
  80.     Next
  81.    
  82.     *Entry\l = Entry
  83.    
  84. EndProcedure
  85.  
  86.  
  87. Procedure AddTable(*Table.tINFOENTRY,Index,First, Second)
  88.     *Table+Index*SizeOf(tINFOENTRY)
  89.     *Table\First = First
  90.     *Table\Second = Second
  91. EndProcedure
  92.  
  93.  
  94. Procedure IsTable(*Table.tINFOENTRY,MaxSize,First,Second)
  95.    
  96.     If  First>256
  97.         Counter + First -   256
  98.         *Table + (First-256)*SizeOf(tINFOENTRY)
  99.     EndIf
  100.    
  101.     If Counter  <   MaxSize
  102.         MaxSize-1
  103.         For i   =   Counter To  MaxSize
  104.             If(*Table\First = First) And (*Table\Second = Second)
  105.                 ProcedureReturn i+256
  106.             EndIf
  107.             *Table+SizeOf(tINFOENTRY)
  108.         Next
  109.     EndIf
  110.    
  111.     ProcedureReturn -1
  112. EndProcedure
  113.  
  114.  
  115. Procedure ComputeString(*Table,Value)
  116.    
  117.     RenderedLength =    #NUL
  118.    
  119.     If  Value   <   256
  120.         RenderedString(RenderedLength) = Value-256
  121.         RenderedLength + 1
  122.         ProcedureReturn
  123.     EndIf
  124.    
  125.     Value-256
  126.     *TablePtr.tINFOENTRY = *Table+Value*SizeOf(tINFOENTRY)
  127.     Value = *TablePtr\First-256
  128.  
  129.     While   Value   >=  0
  130.         RenderedString(RenderedLength) = *TablePtr\Second
  131.         RenderedLength+1
  132.         *TablePtr = *Table + Value*SizeOf(tINFOENTRY)
  133.         Value = *TablePtr\First-256
  134.     Wend
  135.    
  136.     RenderedString(RenderedLength) = *TablePtr\Second
  137.     RenderedLength+1
  138.     RenderedString(RenderedLength) = *TablePtr\First
  139.     RenderedLength+1
  140.    
  141. EndProcedure
  142.  
  143. Procedure CompressData(*DataBlock, DataSize)
  144.  
  145.     Protected *InfoTable.tINFOENTRY = AllocateMemory(SizeOf(tINFOENTRY)*1000000)
  146.  
  147.     Protected *DataPtr.ByteArray = *DataBlock
  148.     Protected *Compressed = AllocateMemory(DataSize*2)
  149.     Protected *CompressedPtr.ByteArray = *Compressed
  150.     Protected CompressedOffset     = 8
  151.     Protected CurrentBitSize       = 9
  152.     Protected *DebugPtr            = *Compressed
  153.     Protected DebugOffset          = 8
  154.    
  155.     First           =   *DataPtr\Byte[DataOffset]
  156.     DataOffset  +   1
  157.     DataEnd     =   DataSize    -   1
  158.    
  159.     For i   =   DataOffset  To  DataEnd
  160.         Second = *DataPtr\Byte[i]
  161.        
  162.         ; Prüfen, ob First/Second schon so in der Tabelle vorkommen.
  163.         Index = IsTable(*InfoTable,CurrentTableEntry,First,Second)
  164.         If  Index   <>  -1
  165.             First = Index
  166.         Else
  167.            
  168.             ; Die neue Kombination in die Liste eintragen.
  169.             AddTable(*InfoTable,CurrentTableEntry,First,Second)
  170.             CurrentTableEntry+1
  171.            
  172.             ; Prüfen, ob die Bitbreite noch stimmt.
  173.             __CHECKBITS()
  174.  
  175.             WriteEntry(*Compressed,@CompressedOffset,@CompressedBitOffset,First,CurrentBitSize)
  176.            
  177.             First = Second
  178.         EndIf
  179.        
  180.     Next
  181.    
  182.     ; Prüfen, ob die Bitbreite noch stimmt.
  183.     __CHECKBITS()
  184.    
  185.     WriteEntry(*Compressed,@CompressedOffset,@CompressedBitOffset,First,CurrentBitSize)
  186.    
  187.     ; Datenblock zusammenstellen:
  188.     If  CompressedBitOffset
  189.         CompressedOffset+1
  190.     EndIf
  191.    
  192.     *Compressed = ReAllocateMemory(*Compressed,CompressedOffset)
  193.    
  194.     PokeL(*Compressed,CompressedOffset-8)
  195.     PokeL(*Compressed+4,DataSize)
  196.    
  197.     FreeMemory(*InfoTable)
  198.    
  199.     ProcedureReturn *Compressed
  200.    
  201. EndProcedure
  202.  
  203.  
  204. Procedure DecompressData(*Compressed)
  205.    
  206.     Protected *InfoTable.tINFOENTRY = AllocateMemory(SizeOf(tINFOENTRY)*1000000)
  207.     Protected *DataPtr.ByteArray
  208.     Protected *CompressedPtr.ByteArray
  209.    
  210.     CompressedSize = PeekL(*Compressed)+8
  211.    
  212.     DataBlockSize = PeekL(*Compressed+4)
  213.     *DataBlock = AllocateMemory(DataBlockSize)
  214.     *DataPtr.ByteArray = *DataBlock
  215.     CompressedOffset = 8
  216.     CurrentBitSize = 9
  217.    
  218.     ReadEntry(*Compressed,@CompressedOffset,@CompressedBitOffset,@First,CurrentBitSize)
  219.     *DataPtr\Byte[DataOffset] = First
  220.     DataOffset+1
  221.    
  222.     While   DataOffset<DataBlockSize
  223.        
  224.         ; Den nächsten Eintrag auslesen.
  225.         ReadEntry(*Compressed,@CompressedOffset,@CompressedBitOffset,@Second,CurrentBitSize)
  226.        
  227.         If Second   <=  CurrentTableEntry+255
  228.             ComputeString(*InfoTable,Second)
  229.         Else
  230.             ComputeString(*InfoTable,First)
  231.         EndIf
  232.        
  233.         AdditionalChar = RenderedLength-1
  234.        
  235.         For i   =   AdditionalChar  To  0   Step    -1
  236.             *DataPtr\Byte[DataOffset] = RenderedString(i)
  237.             DataOffset+1
  238.         Next
  239.        
  240.         If Second   >   CurrentTableEntry+255
  241.             *DataPtr\Byte[DataOffset] = RenderedString(AdditionalChar)
  242.             DataOffset+1
  243.         EndIf
  244.        
  245.         AddTable(*InfoTable,CurrentTableEntry,First,RenderedString(AdditionalChar))
  246.         CurrentTableEntry+1
  247.        
  248.         ; Prüfen, ob die Bitbreite noch stimmt.
  249. ;       n   =   CurrentTableEntry+258
  250. ;       While   n >= (1<<CurrentBitSize)-1
  251. ;           CurrentBitSize+1
  252. ;       Wend
  253.  
  254.             CurrentBitSize  +   Bool(CurrentTableEntry+259  >= (1<<CurrentBitSize))
  255.        
  256.         First = Second
  257.     Wend
  258.    
  259.     FreeMemory(*InfoTable)
  260.    
  261.     ProcedureReturn *DataBlock
  262.    
  263. EndProcedure
  264.  
  265.  
  266. OpenFile(0,"MCEd.pb")
  267. Define.l length = Lof(0)
  268. Define *Buffer = AllocateMemory(length)
  269. ReadData(0,*Buffer,length)
  270. CloseFile(0)
  271.  
  272. OpenConsole()
  273. PrintN("Komprimieren")
  274. t0 = ElapsedMilliseconds()
  275. *Compressed = CompressData(*Buffer,length)
  276. t0  =   ElapsedMilliseconds()-t0
  277.  
  278. PrintN("Originallänge : "+Str(PeekL(*Compressed+4)))
  279. PrintN("Komprimiert   : "+Str(PeekL(*Compressed)))
  280.  
  281. CreateFile(0,"Test.IC7")
  282. WriteData(0,*Compressed,PeekL(*Compressed))
  283. CloseFile(0)
  284.  
  285. ; OpenFile(0,"Test.cpr")
  286. ; Define.l length = Lof(0)
  287. ; Define *Compressed = AllocateMemory(length)
  288. ; ReadData(0,*Compressed,length)
  289. ; CloseFile(0)
  290.  
  291. PrintN("Dekomprimieren")
  292. t1  =   ElapsedMilliseconds()
  293. *Decompressed = DecompressData(*Compressed)
  294. t1 = ElapsedMilliseconds()-t1
  295. CreateFile(0,"TestLZW.txt")
  296. WriteData(0,*Decompressed,PeekL(*Compressed+4))
  297. CloseFile(0)
  298.  
  299.  
  300. MessageRequester("Ergebnis","Komprimieren : "+Str(t0)+#CRLF$+"Dekomprimieren : "+Str(t1),#PB_MessageRequester_Ok)
  301. ; IDE Options = PureBasic 5.31 (Windows - x64)
  302. ; CursorPosition = 245
  303. ; FirstLine = 87
  304. ; Folding = --
  305. ; EnableXP
  306. ; Executable = Lzw2.exe
  307. ; DisableDebugger
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement