32bitTGA的rle压缩以及解压算法(二)

来源:互联网 发布:云计算 国家政策 2014 编辑:程序博客网 时间:2024/05/12 10:26

闲话少说,直接先看代码

void CompressData(void * pSrc, void * pDst, int srcSize, DWORD & dstSize)
{
 if( (pSrc == NULL) || (pDst == NULL) )
 {
  return ;
 }
 
 int totalCompress = 0;
 int repCount = 1;
 DWORD blockHead = 0;
 
 DWORD * pComData = (DWORD *)pDst;
 DWORD * pRawData = (DWORD *)pSrc;
 
 //////////////////////////////////////////////////////////////////////////
 /// DWORD Size = BYTE Size / 4
 int len = srcSize >> 2;
 dstSize = 0;
 
 while(totalCompress < len)
 {
  if( !(*(pRawData+repCount-1)&0xff000000) && !(*(pRawData+repCount)&0xff000000) )
  {
   while( !(*(pRawData+repCount-1)&0xff000000) && !(*(pRawData+repCount)&0xff000000)
     && ((totalCompress+repCount)<len) )
   {
    ++repCount;
   }
   
   blockHead = 0x11000000 | repCount;
   *pComData++ = blockHead;
   *pComData++ = 0;
   dstSize += 2;
   
  }
  /// 看是否是0x10@@@@@@的情况
  else if( *pRawData == *(pRawData+repCount) )
  {
   while( *pRawData == *(pRawData+repCount)
    && ((totalCompress+repCount)<len))
   {
    ++repCount;
   }
   blockHead = 0x10000000 | repCount;
   *pComData++ = blockHead;
   *pComData++ = *pRawData;
   
   dstSize += 2;
  }
  /// 看是否为0x00@@@@@@的情况
  else //if( (*(pRawData+repCount-1) != *(pRawData+repCount)) && (*(pRawData+repCount)&0xff000000) )
  {
   while( *(pRawData+repCount-1) != *(pRawData+repCount)
    && ((totalCompress+repCount)<len) )
   {
    if( !(*(pRawData+repCount-1)&0xff000000) &&
     !(*(pRawData+repCount)&0xff000000) )
    {
     break;
    }
    ++repCount;
   }
   
   blockHead = 0x00000000 | repCount;
   *pComData++ = blockHead;
   memcpy(pComData, pRawData, sizeof(DWORD)*repCount);
   pComData += repCount;
   
   dstSize += repCount+1;
  }
  pRawData += repCount;
  totalCompress += repCount;
  repCount = 1;
 }
 
 dstSize *= 4;
}

稍显繁琐,代码写的不够整齐,不过基本意思就是这样了

解压代码:

void DeCompress(void * pSrc, void * pDst, DWORD srcSize, DWORD & dstSize)
{
 DWORD nowSize = 0;
 DWORD tSize = srcSize;// >> 2;
 DWORD * pDSrc = (DWORD *)pSrc;
 DWORD * pDstData = (DWORD *)pDst;

 dstSize = 0;

 DWORD dSize = 0;
 
 // C++版本
// while(nowSize < tSize)
// {
//  DWORD blockData = 0;  
//  blockData = *pDSrc++;
//  if( !(blockData & 0xff000000) )
//  {
//   int len = blockData & 0x00ffffff;
//   //fread(pDstData, sizeof(DWORD), len, m_pANMFile);
//   memcpy(pDstData, pDSrc, sizeof(DWORD)*len);
//   pDstData += len;
//   pDSrc += len;
//   nowSize += len+1;
//
//   dstSize += len;
//  }
//  else
//  {
//   int len = blockData & 0x00ffffff;
//   DWORD CompData;
//   CompData = *pDSrc++;
//   for(int i=0; i<len; ++i)
//   {
//    *pDstData++ = CompData;
//   }
//   nowSize += 2;
//
//   dstSize += len;
//  }
// }
// dstSize *= 4;


 // asm 版本
 __asm
 {
   mov  esi, pDSrc
   mov  edi, pDstData
loop_start: 
   lodsd     ; 将block读取到eax中
   mov  ebx, eax
   and  ebx, 0x00ffffff ; ebx 存放数据的长度信息
   and  eax, 0xff000000
   jnz  compress
   
   ; 原始数据
   mov  ecx, ebx
   
   cld
   rep  movsd
   
   mov  edx, ebx  ; 获取length + 1
   inc  edx    
   jmp  new_block
   
compress: 
         ; 压缩数据
   mov  ecx, ebx
   mov  edx, 0x02
   lodsd
   cld
   rep  stosd
new_block: 
   add  ebx, dSize  ; 计算总的长度信息
   lea  ecx, dSize
   mov  [ecx], ebx
   
   add  edx, nowSize ; 计算当前已经解压的长度
   lea  ecx, nowSize
   mov  [ecx], edx
   
   mov  eax, tSize
   cmp  edx, eax
   jnz  loop_start
 };  
 dstSize = 4 * dSize;

}

原理见另外一篇文章