?? huffcompress.c
字號:
MOV DX,wTreeSize
// Compute the Tree Storage Requirements
SHL EDX,2
MOV dwStorage,EDX
}
// Copy the Byte Tree
memblast(pByteTree,&dwByteTree[0],dwStorage);
// Build the Code List
HuffmanBuildCodes();
// Copy the Codes
memblast(pCodes,&dwCodes[0],2048);
// Return the Tree Size
return wTreeSize;
}
// Compute the Compression Size of the Input Data
DWORD HuffmanCountCompress(BYTE *pInput,DWORD dwCount,WORD iTreeSize,DWORD *pCodes)
{
// Variables Used for Code Shifting
BOOL fOutput = FALSE;
// Compressed Size with Initial Space for Codes
DWORD dwNewCount;
// Loop Variable
DWORD dwLoop;
// Get the Tree Size and Table Storage Requirement
__asm
{
// Get the Tree Size
MOV EAX,0
MOV AX,iTreeSize
// Get the Table Storage
SHL EAX,2
MOV dwStorage,EAX
// Add 6 for the DWORD and WORD that Stores the UnCompressed Count and Number of Tree Entries
ADD EAX,6
// Initialize the Base Storage Requirement
MOV dwNewCount,EAX
}
// Encode the Input Data
__asm
{
// Point to the Source Data
MOV ESI,pInput
// Set the Loop Count
MOV EDX,dwCount
MOV dwLoop,EDX
// Point to the Codes Array
MOV EDX,pCodes
// Clear the Count of Used Bits
MOV EDI,0
// Main Loop for Reading Bytes
_LoopInput:
// Clear the EAX Register for the Input Character
MOV EAX,0
// Read the Input Byte and Increment the Input Pointer
LODSB
// Get the Compression Code (Bytes 0 - 255 in Array)
MOV EBX,[EDX + EAX * 4]
// Get the Compression Code Bit Count (Bytes 256 - 511 in Array)
MOV ECX,[EDX + 1024 + EAX * 4]
// See How Many Bits Can be Shifted to the Output DWORD
ADD EDI,ECX
CMP EDI,32
JLE _ShiftBits
// See How Many Bits of the Last Code Can't Be Used
SUB EDI,32
// Adjust ECX to Handle only the Bits that Can Be Used
SUB ECX,EDI
// Set the Output Flag
MOV fOutput,TRUE
// Start the Bit Shifting
_ShiftBits:
// Check for Outputting a full DWORD
CMP fOutput,FALSE
JE _Continue
// Increment the Compression Count
ADD dwNewCount,4
// Remove the Bits we Used
MOV EAX,32
SUB EAX,EDI
MOV ECX,EAX
// Reset the Output Flag
MOV fOutput,FALSE
// Decrement the Main Loop Counter
_Continue:
DEC dwLoop
JNZ _LoopInput
// Update Any Remaining Compression data in the Buffer
CMP EDI,0
JE _Exit
// Left Shift the Remaining Bits
MOV EAX,32
SUB EAX,EDI
MOV ECX,EAX
// Increment the Compression Count
ADD dwNewCount,4
// Finished Compressing the Input Data
_Exit:
}
// Return the Compression Count
return dwNewCount;
}
// Compress the Count of Input Data to Output Data returning the new Count
DWORD HuffmanCompress(BYTE *pInput,DWORD dwCount,WORD iTreeSize,DWORD *pByteTree,DWORD *pCodes,BYTE *pOutput)
{
// Allocation Variables
BYTE *pStartInput = pInput;
BYTE *pStartOutput = pOutput;
// Variables Used for Code Shifting
DWORD dwUnusedByte = 0;
BOOL fOutput = FALSE;
// Compressed Size with Initial Space for Codes
DWORD dwNewCount = 0;
// Loop Variable
DWORD dwLoop;
// Get the Tree Size and Table Storage Requirement
__asm
{
// Get the Table Storage
MOV EAX,0
MOV AX,iTreeSize
MOV wTreeSize,AX
SHL EAX,2
MOV dwStorage,EAX
}
// Encode the Input Data
__asm
{
// Point to the Destination Data
MOV EDI,pOutput
// Store the UnCompressed Count
MOV EAX,dwCount
MOV [EDI],EAX
// Move Past the UnCompressed Count
ADD EDI,4
// Move in the Number of Codes to the Output
MOV ECX,0
MOV CX,wTreeSize
MOV [EDI],CX
// Move Past the Number of Codes
ADD EDI,2
// Initialize the Base Storage Requirement
MOV EDX,dwStorage
MOV dwNewCount,EDX
// Add 6 for the DWORD and WORD that Stores the UnCompressed Count and Number of Tree Entries
ADD dwNewCount,6
// Adjust the Start of the Output Compressed Data, Skipping Byte Tree
SHR EDX,1
ADD EDI,EDX
// Store the Pointer to the Output
MOV pOutput,EDI
// Set the Loop Count
MOV EDX,dwCount
MOV dwLoop,EDX
// Point to the Codes Array
MOV EDX,pCodes
// Clear the Count of Used Bits
MOV EDI,0
// Initialize the Storage DWORD
XOR ESI,ESI
// Main Loop for Reading Bytes
_LoopInput:
// Clear the EAX Register for the Input Character
MOV EAX,0
// Save the ESI Register
PUSH ESI
// Point to the Source Data
MOV ESI,pInput
// Read an Input Byte
MOV AL,[ESI]
// Increment the Pointer to the Source Data
INC ESI
// Store the Pointer to the Source Data
MOV pInput,ESI
// Restore the ESI Register
POP ESI
// Get the Compression Code (Bytes 0 - 255 in Array)
MOV EBX,[EDX + EAX * 4]
// Get the Compression Code Bit Count (Bytes 256 - 511 in Array)
MOV ECX,[EDX + 1024 + EAX * 4]
// See How Many Bits Can be Shifted to the Output DWORD
ADD EDI,ECX
CMP EDI,32
JLE _ShiftBits
// See How Many Bits of the Last Code Can't Be Used
SUB EDI,32
// Adjust ECX to Handle only the Bits that Can Be Used
SUB ECX,EDI
// Save the Code
MOV dwUnusedByte,EBX
// Shift the Input Symbol to the Right
PUSH ECX
MOV ECX,EDI
SHR EBX,CL
POP ECX
// Set the Output Flag
MOV fOutput,TRUE
// Start the Bit Shifting
_ShiftBits:
// Shift the Output Symbol to Handle a New Symbol
SHL ESI,CL
// OR the Output Symbol with New Symbol
OR ESI,EBX
// Check for Outputting a full DWORD
CMP fOutput,FALSE
JE _Continue
// Output an Encoded Symbol
MOV EAX,ESI
PUSH EDI
MOV EDI,pOutput
MOV [EDI],EAX
POP EDI
ADD pOutput,4
// Increment the Compression Count
ADD dwNewCount,4
// Remove the Bits we Used
MOV EAX,32
SUB EAX,EDI
MOV ECX,EAX
// Restore the Unused Portion of the Code
MOV EAX,dwUnusedByte
SHL EAX,CL
SHR EAX,CL
// Update the Code to Have the Left Over Bits
MOV ESI,EAX
// Initialize the Left Over Bits
MOV dwUnusedByte,0
// Reset the Output Flag
MOV fOutput,FALSE
// Decrement the Main Loop Counter
_Continue:
DEC dwLoop
JNZ _LoopInput
// Update Any Remaining Compression data in the Buffer
CMP EDI,0
JE _Exit
// Left Shift the Remaining Bits
MOV EAX,32
SUB EAX,EDI
MOV ECX,EAX
SHL ESI,CL
// Output the Final Encoded Symbol
MOV EAX,ESI
MOV EDI,pOutput
MOV [EDI],EAX
// Increment the Compression Count
ADD dwNewCount,4
// Finished Compressing the Input Data
_Exit:
}
// Set the Start of the Byte Tree
pOutput = pStartOutput + 6;
// Copy the DWORD Byte Tree to a WORD Byte Tree
D2W(&wByteTree[0],pByteTree,dwStorage/4);
// Copy the Byte Tree
memblast(pOutput,&wByteTree[0],dwStorage/2);
// Restore the Pointer to the Start of the Input
pInput = pStartInput;
// Restore the Pointer to the Start of the Output
pOutput = pStartOutput;
// Return the Compression Count
return dwNewCount;
}
// Get the UnCompressed Count of Output Data
DWORD HuffmanGetSize(BYTE *pInput)
{
DWORD dwUnCount;
__asm
{
// Point to the Source Data
MOV ESI,pInput
// Get the UnCompressed Count
MOV EAX,[ESI]
MOV dwUnCount,EAX
}
// Return the UnCompressed Count
return dwUnCount;
}
// UnCompress the Compressed Count of Input Data to Output Data returning the UnCompressed Count
DWORD HuffmanUnCompress(BYTE *pInput,BYTE *pOutput)
{
// UnCompressed Count
DWORD dwUnCount;
// Allocation Variables
BYTE *pStartInput = pInput;
BYTE *pStartOutput = pOutput;
// UnCompressed Variables
DWORD dwLoop;
// Initialize the Weights Array
HuffmanInitArrays();
// Copy the Decoding Dictionary
__asm
{
// Point to the Source Data
MOV ESI,pInput
// Get the UnCompressed Count
MOV EAX,[ESI]
MOV dwUnCount,EAX
// Move Past the Uncompressed Count
ADD ESI,4
// Get the Tree Size
MOV EAX,0
MOV AX,[ESI]
MOV wTreeSize,AX
// Increment the Pointer to the Encoded Data
ADD ESI,2
// Store the Start of the Compressed Data
MOV pInput,ESI
// Compute the Root Index
MOV dwRootIndex,EAX
SUB dwRootIndex,3
// Compute the Table Storage Requirement
SHL EAX,2
MOV dwStorage,EAX
}
// Copy the Decoding Byte Tree
memblast(&wByteTree[0],pInput,dwStorage/2);
// Convert the WORD Byte Tree to a DWORD Byte Tree
W2D(&dwByteTree[0],&wByteTree[0],dwStorage/4);
// Decode the Input Data
__asm
{
// Increment the Pointer to the Data
MOV EAX,dwStorage
SHR EAX,1
ADD pInput,EAX
// Point to the Byte Code Tree
MOV ESI,OFFSET dwByteTree[0]
// Set the Loop Count for Amount of Bytes to Uncompress
MOV EDX,dwUnCount
MOV dwLoop,EDX
// Calculate the Index of the Root
MOV EBX,dwRootIndex
// Main Loop for Reading Bytes
_LoopInput:
// Point to the Source Data
MOV EDI,pInput
// Read a DWORD of Encoded Data
MOV ECX,[EDI]
// Increment the Source Data Pointer by a DWORD
ADD pInput,4
// Initialize the Number of Bits to Process
MOV EAX,32
// Left Shift the Encoded Data 1 Bit at a Time
_LeftShift:
// Initialize the Decode Storage
MOV EDX,0
// Left Shift the Code into the Decode Storage
SHL ECX,1
// Bit + 1 = Number of Children, ie The Direction in Tree to Move
ADC EDX,1
// Index the Child of the Parent
ADD EBX,EDX
// Decrement the Bits Processed
DEC EAX
// Check for a Leaf Node
MOV EDI,[ESI + EBX * 4]
CMP EDI,256
JLE _LeafNode
// Index the Child's Parent
MOV EDI,EBX
SUB EDI,EDX
// Match the Child to a Parent
_TestParent:
// Index the Previous Parent in the Tree
SUB EDI,3
// Get the Child's Parent
MOV EDX,[ESI + EDI * 4]
// Compare the Parent with the Child
CMP EDX,[ESI + EBX * 4]
JNE _TestParent
// Update the Parent Index
MOV EBX,EDI
// Check the Bits Processed upto this Point
CMP EAX,0
// Check for More Bits to Process
JNZ _LeftShift
// Read in another DWORD
JMP _LoopInput
// Output a Decoded Symbol
_LeafNode:
// Point to the Destination Data
MOV EDI,pOutput
// Output the Code
MOV EDX,[ESI + EBX * 4]
MOV [EDI],DL
// Increment the Destination Data by 1 Byte
INC pOutput
// Calculate the Index of the Root
MOV EBX,dwRootIndex
// Decrement the Loop Counter
DEC dwLoop
JZ _Exit
// Check for More Bits to Process
CMP EAX,0
JNZ _LeftShift
// Read a New DWORD
JMP _LoopInput
// Finished Decompressing
_Exit:
}
// Restore the Pointer to the Start of the Input
pInput = pStartInput;
// Restore the Pointer to the Start of the Output
pOutput = pStartOutput;
// Return the Count of UnCompressed Data
return dwUnCount;
}
// Copy a DWORD Array to a WORD Array
void D2W(void* dest,void* src,DWORD count)
{
__asm
{
MOV ESI,src // Copy the Source Address to the Register
MOV EDI,dest // Copy the Destination to the Register
MOV ECX,count // Copy the Count to the Register
_CopyD2W:
MOV EAX,[ESI]
MOV [EDI],AX
ADD ESI,4
ADD EDI,2
DEC ECX
JNZ _CopyD2W
}
}
// Copy a WORD Array to a DWORD Array
void W2D(void* dest,void* src,DWORD count)
{
__asm
{
MOV ESI,src // Copy the Source Address to the Register
MOV EDI,dest // Copy the Destination to the Register
MOV ECX,count // Copy the Count to the Register
XOR EAX,EAX
_CopyW2D:
MOV AX,[ESI]
MOV [EDI],EAX
ADD ESI,2
ADD EDI,4
DEC ECX
JNZ _CopyW2D
}
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -