#include <iostream>
using namespace std;
const int N =11;//数组元素个数-1
int length(int i); //二进制数的位数
void Compress(int n,int p[],int s[],int l[],int b[]); //压缩
void Tracebace(int n,int& i,int s[],int l[]);//递归构造最优解
void Output(int s[],int l[],int b[],int n); //输出
int main()
{
//图像灰度数组 下标从1开始计数
int p[] = {0,6, 5, 7, 245, 180, 28,28,19, 22, 25,20};
//int p[]={4,6,5,7,129,138};
//s[N]为像素序列最优分段所需的存储位数
//l[N]为最优分段的有最高位数的像素个数
//b[N]为最优分段的二进制数最高位数
int s[N],l[N],b[N];
cout<<"图像的灰度序列为:"<<endl;
for(int i=1;i<=N;i++)
{
cout<<p[i]<<" ";
}
cout<<endl;
Compress(N,p,s,l,b); //压缩过程
Output(s,l,b,N); //回溯输出
return 0;
}
void Compress(int n,int p[],int s[],int l[],int b[])
{
//灰度值的范围为0~255,header=l[i]+b[i]=8+3=11
int Lmax = 256,header = 11;
//从第一位开始,所以S[0]=0;
s[0] = 0;
for(int i=1; i<=n; i++)
{
b[i] = length(p[i]);//计算像素点p需要的存储位数
int bmax = b[i];//b[i]为最优分段的二进制数值的位数
s[i] = s[i-1] + bmax; //每次加对应的位数
l[i] = 1;//第一段像素个数
//p[] = {0,6, 5, 7, 245, 180, 28,28,19, 22, 25,20}
//从{0,6}开始进行计算
for(int j=2; j<=i && j<=Lmax;j++)
{
//p[i]的位数比较,谁的位数大要谁
if(bmax<b[i-j+1])
{
bmax = b[i-j+1];
}
if(s[i]>s[i-j]+j*bmax)
{
s[i] = s[i-j] + j*bmax;
l[i] = j;
}
}
s[i] += header; //最优分段消耗位数
}
}
//十进制数转换为二进制数时二进制数的位数
int length(int i)
{
int k=1; //初始化时位数的数值
i = i/2;
//当i大于0时循环
while(i>0)
{
k++;
i=i/2;
}
return k;
}
//递归构造最优解
void Traceback(int n,int& i,int s[],int l[])
{
if(n==0)
return;
Traceback(n-l[n],i,s,l);//当n-l[n]的值为0时返回
s[i++]=n-l[n];//重新为s[]数组赋值,用来存储分段位置
}
void Output(int s[],int l[],int b[],int n)
{
//在输出s[n]存储位数后,s[]数组则被重新赋值,用来存储分段的位置
cout<<"图像压缩后的最小空间为:"<<s[n]<<endl;
int m = 0;
Traceback(n,m,s,l);
s[m] = n;
cout<<"将原灰度序列分成"<<m<<"段序列段"<<endl;
//求最优分段的像素个数l[i]以及最高位数b[i]
for(int j=1; j<=m; j++)
{
l[j] = l[s[j]];
b[j] = b[s[j]];
}
//输出最优分段像素个数l[j]以及最高位数b[j]的值
for(int j=1; j<=m; j++)
{
cout<<"段长度(最优分段的像素个数):"<<l[j]<<",所需存储位数:"<<b[j]<<endl;
}
}
图片 压缩
于 2023-05-22 12:44:24 首次发布