【3D技术宅公社】XR数字艺术论坛  XR技术讨论 XR互动电影 定格动画

 找回密码
 立即注册

QQ登录

只需一步,快速开始

调查问卷
论坛即将给大家带来全新的技术服务,面向三围图形学、游戏、动画的全新服务论坛升级为UTF8版本后,中文用户名和用户密码中有中文的都无法登陆,请发邮件到324007255(at)QQ.com联系手动修改密码

3D技术论坛将以计算机图形学为核心,面向教育 推出国内的三维教育引擎该项目在持续研发当中,感谢大家的关注。

查看: 3600|回复: 7

[求助]RLE压缩方法

[复制链接]
发表于 2006-12-12 20:55:46 | 显示全部楼层 |阅读模式

网上找了不少资料,但都没看懂,

比如说

01 01 01 01 05 06 06 00 1F 2A 2A

压缩后为

84 01 05 82 06 00 1F 82 2A

解压时将01还原成84&0x7F个

我的疑惑是如果原数据中个84这个个值那不是就乱了吗?

发表于 2006-12-13 15:58:25 | 显示全部楼层
真不好意思,我也不是很懂RLE,看看会不会出现高人吧
 楼主| 发表于 2006-12-13 17:36:19 | 显示全部楼层

呵呵 昨天花了一晚上研究出来了。

发表于 2006-12-13 22:08:28 | 显示全部楼层
那就告诉我们呀~
 楼主| 发表于 2006-12-15 04:33:34 | 显示全部楼层

说什么都不如代码来得直接。

#include "RLECompression.h"

int RLE8Compress(BYTE*in, int Count, BYTE*out)
{
BYTE L;
int f_size = 0;
while (Count)
{
L = 0;
while((Count>1)&&(in[0]==in[1])&&(L<=0x7E)) //如果相等,可压缩
{
Count--; in++; L++;
}
if (L)
{
out[0] = L|0x80;
out[1] = in[0];
out += 2;
f_size += 2;
in++; Count--;
L = 0;
}
  while ((Count>1)&&(in[0]!=in[1])&&(L<=0x7E))//不可压缩 记录原数据长度
{
out[1] = in[0];
L++; Count--; in++; out++;
}
if (L)
{
out -= L;
out[0] = L;
out += L+1;
f_size += L+1;
}
  if (Count==1)        //最后的一个数据
{
out[0] = 1;
out[1] = in[0];
Count--;
f_size += 2;
}
}
return f_size;
}
int RLE8UnCompress(BYTE*in, int Count, BYTE*out)
{
BYTE L;
int f_size = 0;
while (Count)
{
//if (in[0]&0x7F)
if (in[0]&0x80) //已压缩
{
L = (in[0]&0x7F) + 1;
memset(out, in[1], L);
out += L;
f_size += L;
in += 2;
Count-=2;
}
else //未压缩
{
L = in[0]&0x7F;
in++;
memcpy(out, in, L);
in += L;
out += L;
f_size += L;
Count -= L+1;
}
}
return f_size;
}
int RLE16Compress(WORD*in, int Count, WORD*out)
{
WORD L;
int f_size = 0;
while (Count)
{
L = 0;
while((Count>1)&&(in[0]==in[1])&&(L<=0x7FFE)) //如果相等,可压缩
{
Count--; in++; L++;
}
if (L)
{
out[0] = L|0x8000;
out[1] = in[0];
out += 2;
f_size += 2;
in++; Count--;
L = 0;
}
  while ((Count>1)&&(in[0]!=in[1])&&(L<=0x7FFE)) //不可压缩 记录原数据长度
{
out[1] = in[0];
L++; Count--; in++; out++;
}
if (L)
{
out -= L;
out[0] = L;
out += L+1;
f_size += L+1;
}
  if (Count==1)        //最后的一个数据
{
out[0] = 1;
out[1] = in[0];
Count--;
f_size += 2;
}
}
return f_size * sizeof(WORD);
}
int RLE16UnCompress(WORD*in, int Count, WORD*out)
{
WORD L;
int f_size = 0;
while (Count)
{
//if (in[0]&0x7F)
if (in[0]&0x8000) //已压缩
{
L = (in[0]&0x7FFF) + 1;
for (int I=0;I<L;++I)
{
out[0] = in[1];
out++;
f_size++;
}
//memset(out, in[1], L);
//out += L;
//f_size += L;
in += 2;
Count-=2;
}
else //未压缩
{
L = in[0]&0x7FFF;
in++;
memcpy(out, in, L * sizeof(WORD));
in += L;
out += L;
f_size += L;
Count -= L+1;
}
}
return f_size * sizeof(WORD);
}
int RLE32Compress(DWORD*in, int Count, DWORD*out)
{
DWORD L;
int f_size = 0;
while (Count)
{
L = 0;
while((Count>1)&&(in[0]==in[1])&&(L<=0x7FFFFFFE)) //如果相等,可压缩
{
Count--; in++; L++;
}
if (L)
{
out[0] = L|0x80000000;
out[1] = in[0];
out += 2;
f_size += 2;
in++; Count--;
L = 0;
}
  while ((Count>1)&&(in[0]!=in[1])&&(L<=0x7FFFFFFE)) //不可压缩 记录原数据长度
{
out[1] = in[0];
L++; Count--; in++; out++;
}
if (L)
{
out -= L;
out[0] = L;
out += L+1;
f_size += L+1;
}
  if (Count==1)        //最后的一个数据
{
out[0] = 1;
out[1] = in[0];
Count--;
f_size += 2;
}
}
return f_size * sizeof(DWORD);
}
int RLE32UnCompress(DWORD*in, int Count, DWORD*out)
{
DWORD L;
int f_size = 0;
while (Count)
{
//if (in[0]&0x7F)
if (in[0]&0x80000000) //已压缩
{
L = (in[0]&0x7FFFFFFF) + 1;
for (int I=0;I<L;++I)
{
out[0] = in[1];
out++;
f_size++;
}
//memset(out, in[1], L);
//out += L;
//f_size += L;
in += 2;
Count-=2;
}
else //未压缩
{
L = in[0]&0x7FFFFFFF;
in++;
memcpy(out, in, L * sizeof(DWORD));
in += L;
out += L;
f_size += L;
Count -= L+1;
}
}
return f_size * sizeof(DWORD);
}
 
 楼主| 发表于 2006-12-15 04:40:03 | 显示全部楼层

压缩率并不是很高,但是如果将R, G, B, A分开压缩压缩率会好很多

B G R A

FF 7F 0F 00

FF 46 0F 00

FF 43 0F 00

F0 2E 10 00

将 R, G, B, A 分别压缩(很多情况下几个相临像素的R, G, B, A重复的情况会很多

^_^)

发表于 2006-12-15 21:16:26 | 显示全部楼层
我就喜欢这样的~!哈哈哈[em01][em06]
发表于 2007-1-27 17:54:22 | 显示全部楼层

以前写过pcx的解压,印象中应该是这样的:以一个数(好像是192,也可能是128吧,都是可以的)为分界点,超过的为表示后面有n个重复的数字,以楼主的案例,分界点为128.0x84 - 128 = 4,然后后面的01就表示有4个01,解压缩出来就是01010101.若是超过该值,那么若只有1个也要用两个值表示,就会发生更大的情况,所以一般会用192,会降低这种可能性.

这个一般都是为了八位的图片压缩而设置的,若是32位,可以根据这个算法改一下就可以了
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|3D数字艺术论坛 ( 沪ICP备14023054号 )

GMT+8, 2025-2-6 04:08

Powered by Discuz! X3.4

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表