游程编码与位图压缩

  • 游程编码
  • 位图
  • 具体算法

游程编码

如果一个二进制数据是大量重复的 0000… 连接大量的 1111… ,我们就可以用每段数字的长度进行描述,压缩数据。

比如 00000000 11111111 00000000 00000000 00000000 00000000 可以被描述为 8 8 32.

代表8个0,连接8个1,连接32个0.

对于一些杂乱的信息,可能没有太多的压缩能力,但对于位图这种比较特殊的结构数据,则可能存在较为适应的压缩。

位图

我们所见的黑白位图,最朴素的描述方法是 长 * 宽 bool 矩阵,比如:
4 * 4 矩阵:

0000
1010
0101
1111

而位图,通常要大很多,如果连续的重复序列非常多,就可以用游程编码进行压缩了。

具体算法

我们通常用一个固定位数的数值,比如char的8位表示长度,通过二进制读取原文件,一个个数重复的序列的长度,将长度用char表示,但由于位数原因,char最多表示255的长度,更长的情况,则用中间插0的方式解决。

比如我有265个连续的0,此时就用 255 0 10 表示,255个连续的0,0个连续的1,10个连续的0.

代码:还是二进制读写,略改动,这个玩具类设计很不C++,使用中还是有陷阱,仅供参考。

#ifndef BINSTDIO
#define BINSTDIO#include <bitset>
#include <cassert>
#include <iostream>
#include <string>namespace BIO
{struct cbin
{//单例模式,不可实体化cbin() = delete;//比特流是否为空static auto isEmpty() -> bool{return std::cin.eof();}//读取1位数据并返回一个bool值static auto readBool() -> bool{if (isEmpty()){std::cerr << "EOF" << std::endl;buffer = -1;N = -1;}if (N == 0){fillBuffer();}N--;bool bit = buffer[N];return bit;}//读取8位数据并返回一个char值static auto readChar() -> unsigned char{if (isEmpty()){std::cerr << "EOF" << std::endl;buffer = -1;N = -1;}if (N == buffersize){auto x = buffer;fillBuffer();return x.to_ulong() & bufferfill;}auto x = buffer;x <<= (buffersize - N);int oldN = N;fillBuffer();if (isEmpty()){std::cerr << "EOF" << std::endl;buffer = -1;N = -1;}N = oldN;x |= (buffer >> N);return x.to_ulong() & bufferfill;}//读取r(1~16)位数据并返回一个char值static auto readChar(int r) -> unsigned char{if (r < 1 || r > 2 * buffersize){throw std::string("Illegal value for r = ") + std::to_string(r);}if (r == buffersize){return readChar();}unsigned char x = 0;for (int i = 0; i != r; ++i){x <<= 1;bool bit = readBool();if (bit){x |= 1;}}return x;}static auto readInt() -> int{int x = 0;for (int i = 0; i < 4; i++){unsigned char c = readChar();x <<= buffersize;x |= c;}return x;}//关闭比特流static void close(){std::cin.setstate(std::ios::eofbit);}//静态初始化static void begin(){fillBuffer();}private://读流到缓冲区static void fillBuffer(){if (std::cin.read(reinterpret_cast<char *>(&buffer),sizeof(unsigned char))){N = buffersize;}else{std::cerr << "EOF" << std::endl;buffer = -1;N = -1;}}static constexpr int buffersize = 8;static constexpr unsigned int bufferfill = 0xff;//缓冲区static std::bitset<buffersize> buffer;//缓冲区比特指针static int N;
};
constexpr int buffersize = 8;
std::bitset<buffersize> cbin::buffer;
int cbin::N;struct cbout
{cbout() = delete;//刷新缓冲流static void flush(){clearBuffer();std::cout.flush();}//写入指定的比特static void write(bool bit){writeBit(bit);}//写入指定的8位字符static void write(unsigned char c){writeByte(c);}static void write(unsigned int x){writeByte((x >> 3 * buffersize) & bufferfill);writeByte((x >> 2 * buffersize) & bufferfill);writeByte((x >> buffersize) & bufferfill);writeByte((x >> 0) & bufferfill);}//写入指定字符的第r(1~16)位static void write(unsigned char c, int r){if (r == buffersize){write(c);}if (r < 1 || r > 2 * buffersize){throw std::string("Illegal value for r = ") + std::to_string(r);}for (int i = 0; i != r; ++i){bool bit = ((c >> (r - i - 1)) & 1) == 1;writeBit(bit);}}//关闭比特流static void close(){clearBuffer();std::cout.flush();}private:static void writeBit(bool bit){buffer <<= 1;if (bit){buffer |= 1;}N++;if (N == buffersize){clearBuffer();}}static void writeByte(unsigned int x){assert(x >= 0 && x < 256);unsigned char c = static_cast<unsigned char>(x);if (N == 0){std::cout.write(reinterpret_cast<char *>(&c),sizeof(unsigned char));return;}for (int i = 0; i != buffersize; ++i){bool bit = ((c >> (buffersize - i - 1)) & 1) == 1;writeBit(bit);}}static void clearBuffer(){if (N <= 0){return;}if (N > 0){buffer <<= (buffersize - N);}std::cout.write(reinterpret_cast<char *>(&buffer),sizeof(unsigned char));N = 0;buffer = 0;}static constexpr unsigned int bufferfill = 0xff;static constexpr unsigned int buffersize = 8;//缓冲区static std::bitset<buffersize> buffer;//缓冲区比特指针static int N;
};std::bitset<buffersize> cbout::buffer;
int cbout::N;inline void BinaryDump(char *argv[])
{cbin::begin();int width = std::stoi(argv[1]);int cnt = 0;for (cnt = 0; !cbin::isEmpty();){if (width == 0){continue;}if (cnt != 0 && cnt % width == 0){std::cout << '\n';}if (cbin::readBool() && !cbin::isEmpty()){std::cout << '1';++cnt;}else if (!cbin::isEmpty()){std::cout << '0';++cnt;}}std::cout << std::endl;std::cout << cnt << " bits" << std::endl;
}
} // namespace BIO
#endif

游程编码代码:

#include "BinStdio_2.h"
#include <iostream>
#include <string>
#include <vector>void expand()
{bool b = false;while (true){unsigned char cnt = BIO::cbin::readChar();if (!BIO::cbin::isEmpty()){for (int i = 0; i != cnt; ++i){BIO::cbout::write(b);}b = !b;}else{break;}}BIO::cbout::close();
}void compress()
{unsigned char cnt = 0;bool b = false;bool old = false;while (true){b = BIO::cbin::readBool();if (!BIO::cbin::isEmpty()){if (b != old){BIO::cbout::write(cnt);cnt = 0;old = !old;}else{if (cnt == 255){BIO::cbout::write(cnt);cnt = 0;BIO::cbout::write(cnt);}}cnt++;}else{break;}}BIO::cbout::write(cnt);BIO::cbout::close();
}auto main(int /*argc*/, char *argv[]) -> int
{//    BIO::BinaryDump(argv);if (argv[1][0] == '-'){compress();}if (argv[1][0] == '+'){expand();}return 0;
}

2022-05-24 游程编码与位图压缩(C++)相关推荐

  1. 利用游程编码实现二值图像压缩

    编码方案设计: 按位进行压缩,对二进制流进行超前扫描,判断是否值得压缩,如果压缩有意义,则压缩:否则保持原始数据. 系统实现方案: 总体思想:将图像文件以二进制方式读入缓冲区,把二进制位转制为整数,对 ...

  2. c++读取8位和24位BMP位图数据 俺的作业

    家人萌 我因为这个作业爆炸了好多天...所以我想发一下 菜鸡一个 别骂别骂 欢迎指正  关于这个作业要先了解一下这些登西... 1)BMP 位图的结构 1.BMP文件头(14字节) ,文件的第0字节到 ...

  3. H5在线CAD,网页CAD,MxDraw云图平台2022.08.24更新

    SDK开发包下载地址: MxDraw云图平台 2022.08.24更新_梦想CAD控件 1. 增加对像扩展数据功能 2. 增加CAD结合GIS使用功能 https://www.mxdraw3d.com ...

  4. http://www.cnblogs.com/tornadomeet/archive/2012/05/24/2515980.html

    转载: Deep Learning(深度学习): ufldl的2个教程(这个没得说,入门绝对的好教程,Ng的,逻辑清晰有练习):一 ufldl的2个教程(这个没得说,入门绝对的好教程,Ng的,逻辑清晰 ...

  5. 【2022.1.3】手脱压缩壳练习(含练习exe)

    [2022.1.3]手脱压缩壳练习(含练习exe) 文章目录 [2022.1.3]手脱压缩壳练习(含练习exe) 0.简介 1.单步跟踪法 (#)方法介绍 (0)练习exe下载 (1).查看源程序 ( ...

  6. 【2022.05.31】大学本科毕业总结,再见北理工

    [2022.05.31]大学本科毕业总结,再见北理工 今天顺利完成答辩,成功毕业成为无业游民(doge) 一时思绪万千,感觉前几天才刚入学,今天四年已结束就已经毕业 答辩完身上的包袱感觉少很多,但是也 ...

  7. Steema.TeeChart.NET Pro 4.2022.11.24 Crack

    Steema.TeeChart.NET --version 4.2022.11.24 许多数学指标.统计函数等 .NET 图表控件具有生成高级金融图表应用程序的功能.功能和指标包括:开盘-高-低-收盘 ...

  8. 2022.3.24 图论——拓扑排序算法

    文章目录 一.拓扑排序简介 二.例题 1.题目 2.分析 3.代码 一.拓扑排序简介 1.Topological Sorting,指的是一个DAG(Directed Acyclic Graph)即有向 ...

  9. JavaWeb 2022.9.24

    JavaWeb 2022.9.24 Java web 1.基本概念 1.1.前言 web开发 web,网页的意思 静态web heml.css 提供给所有人看的数据始终不会发生变化! 动态web 淘宝 ...

  10. 每日总结(2022/05/17-)

    2022/05/17- 线程配置 实验设备 实现2个矩阵(Width=2048, Height=1024)的相加,输入的矩阵A,B按照以下要求初始化,矩阵A的初始值全为本人学号的最后1位数字,矩阵B的 ...

最新文章

  1. Docker 入门系列(5)- Docker 端口映射(映射所有IP地址、映射到指定地址和指定端口、映射指定地址任意端口、查看映射端口配置)
  2. 全球及中国语音拾音耳机行主要产品及营销模式分析报告业2022-2028年版
  3. liferay如何在struts2中調用ajax
  4. 前端学习(3320):undefine和null 2
  5. keep公众号就“借鉴”原创文章致歉:将停更一周
  6. 问题 E: 求1+2+...+n=?
  7. mysql merge事务_mysql菜鸟手迹11--mysql存储引擎之Merge
  8. shell脚本中一些日期的定义
  9. java集中常见的算法讲解
  10. ccc计算机比赛如何报名,2020年加拿大计算机竞赛报名即将截止!
  11. 大数据在智慧城市建设中的应用
  12. Ring buffer streaming in general - how to imple...
  13. UltraEdit编辑器无法使用快捷键全选ctrl+a功能失效解决办法
  14. 前端程序员福利 利用node写接口
  15. CSharp 常用函数
  16. java二维数组的长度问题
  17. 音频基础知识-PCM、AAC
  18. OC中声明变量的几种方式
  19. 轻松上手Manjaro之Manjaro系统配置
  20. 第一章、华软代码生成器简单模板调制教程

热门文章

  1. aliez歌词_aLIEz (中文版)歌词
  2. 网页设计中常用的20个Web安全字体
  3. 你该不会不知道,web自动化测试中的八大定位方法吧!
  4. 【前端】【HTML+CSS+JavaScript(JS)】简易工资计算器的实现
  5. 暗黑破坏神不朽怎么在电脑上玩 暗黑破坏神不朽模拟器教程
  6. 智慧城市智慧路灯解决方案
  7. 如何快速调整图片亮度和对比度?
  8. Workflow 规则大全 最新版
  9. 吝啬SAT问题是NP完全问题的证明
  10. 银行家算法C语言代码