2022-05-24 游程编码与位图压缩(C++)
游程编码与位图压缩
- 游程编码
- 位图
- 具体算法
游程编码
如果一个二进制数据是大量重复的 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++)相关推荐
- 利用游程编码实现二值图像压缩
编码方案设计: 按位进行压缩,对二进制流进行超前扫描,判断是否值得压缩,如果压缩有意义,则压缩:否则保持原始数据. 系统实现方案: 总体思想:将图像文件以二进制方式读入缓冲区,把二进制位转制为整数,对 ...
- c++读取8位和24位BMP位图数据 俺的作业
家人萌 我因为这个作业爆炸了好多天...所以我想发一下 菜鸡一个 别骂别骂 欢迎指正 关于这个作业要先了解一下这些登西... 1)BMP 位图的结构 1.BMP文件头(14字节) ,文件的第0字节到 ...
- H5在线CAD,网页CAD,MxDraw云图平台2022.08.24更新
SDK开发包下载地址: MxDraw云图平台 2022.08.24更新_梦想CAD控件 1. 增加对像扩展数据功能 2. 增加CAD结合GIS使用功能 https://www.mxdraw3d.com ...
- http://www.cnblogs.com/tornadomeet/archive/2012/05/24/2515980.html
转载: Deep Learning(深度学习): ufldl的2个教程(这个没得说,入门绝对的好教程,Ng的,逻辑清晰有练习):一 ufldl的2个教程(这个没得说,入门绝对的好教程,Ng的,逻辑清晰 ...
- 【2022.1.3】手脱压缩壳练习(含练习exe)
[2022.1.3]手脱压缩壳练习(含练习exe) 文章目录 [2022.1.3]手脱压缩壳练习(含练习exe) 0.简介 1.单步跟踪法 (#)方法介绍 (0)练习exe下载 (1).查看源程序 ( ...
- 【2022.05.31】大学本科毕业总结,再见北理工
[2022.05.31]大学本科毕业总结,再见北理工 今天顺利完成答辩,成功毕业成为无业游民(doge) 一时思绪万千,感觉前几天才刚入学,今天四年已结束就已经毕业 答辩完身上的包袱感觉少很多,但是也 ...
- Steema.TeeChart.NET Pro 4.2022.11.24 Crack
Steema.TeeChart.NET --version 4.2022.11.24 许多数学指标.统计函数等 .NET 图表控件具有生成高级金融图表应用程序的功能.功能和指标包括:开盘-高-低-收盘 ...
- 2022.3.24 图论——拓扑排序算法
文章目录 一.拓扑排序简介 二.例题 1.题目 2.分析 3.代码 一.拓扑排序简介 1.Topological Sorting,指的是一个DAG(Directed Acyclic Graph)即有向 ...
- JavaWeb 2022.9.24
JavaWeb 2022.9.24 Java web 1.基本概念 1.1.前言 web开发 web,网页的意思 静态web heml.css 提供给所有人看的数据始终不会发生变化! 动态web 淘宝 ...
- 每日总结(2022/05/17-)
2022/05/17- 线程配置 实验设备 实现2个矩阵(Width=2048, Height=1024)的相加,输入的矩阵A,B按照以下要求初始化,矩阵A的初始值全为本人学号的最后1位数字,矩阵B的 ...
最新文章
- Docker 入门系列(5)- Docker 端口映射(映射所有IP地址、映射到指定地址和指定端口、映射指定地址任意端口、查看映射端口配置)
- 全球及中国语音拾音耳机行主要产品及营销模式分析报告业2022-2028年版
- liferay如何在struts2中調用ajax
- 前端学习(3320):undefine和null 2
- keep公众号就“借鉴”原创文章致歉:将停更一周
- 问题 E: 求1+2+...+n=?
- mysql merge事务_mysql菜鸟手迹11--mysql存储引擎之Merge
- shell脚本中一些日期的定义
- java集中常见的算法讲解
- ccc计算机比赛如何报名,2020年加拿大计算机竞赛报名即将截止!
- 大数据在智慧城市建设中的应用
- Ring buffer streaming in general - how to imple...
- UltraEdit编辑器无法使用快捷键全选ctrl+a功能失效解决办法
- 前端程序员福利 利用node写接口
- CSharp 常用函数
- java二维数组的长度问题
- 音频基础知识-PCM、AAC
- OC中声明变量的几种方式
- 轻松上手Manjaro之Manjaro系统配置
- 第一章、华软代码生成器简单模板调制教程