图像压缩编码码matlab实现——JSjpeg

function y = jpegencode(x, quality)
%jpegencode函数用来压缩图像,x为输入图像
%quality决定了截去的系数和压缩比

error(nargchk(1, 2, nargin));   %检查输入参数
if nargin < 2
    quality = 1;   %默认时 quality为1
end
x = double(x) - 128;   %像素层次移动-128
[xm, xn] = size(x);    %得到像素尺寸
t = dctmtx(8);         %得到8*8DCT矩阵
%将图像分割成8*8子图像,进行DCT,然后进行量化
y = blkproc(x, [8,8], 'P1*x*P2', t, t');
m = [16 11 10 16 24 40 51 61     %JPEG量化步长矩阵
     12 12 14 19 26 58 60 55
     14 13 16 24 40 57 69 56
     14 17 22 29 51 87 80 62
     18 22 37 56 68 109 103 77
     24 35 55 64 81 104 113 92
     49 64 78 87 103 121 120 101
     72 92 95 98 112 110 103 99]*quality;
 %用量化步长矩阵m对变换矩阵进行量化
 yy = blkproc(y, [8, 8], 'round(x./P1)', m);
 y = im2col(yy, [8, 8], 'distinct');   %将图像块排列成向量
 xb = size(y, 2);                      %得到列数,也就是子图像个数
 order = [1 9 2 3 10 17 25 18 11 4 5 12 19 26 33 ...        %变换系数排列次序
       41 34 27 20 13 6 7 14 21 28 35 42 49 57 50 ...
       43 36 29 22 15 8 16 23 30 37 44 51 58 59 52 ...
       45 38 31 24 32 39 46 53 60 61 54 47 40 48 55 62 63 56 64];
 %用Z形扫描方式对变换系数重新排列
 y = y(order, :);
 eob = max(x(:)) + 1;            %创建一个块结束符号
 num = numel(y) + size(y, 2);
 r = zeros(num, 1);
 count = 0;
 %将非零元素重新排列放入r中,-26-3  eob  -25  1   eob
 for j = 1: xb                   %每次对一列(即一块)进行操作
     i = max(find(y(:, j)));     %找最后一个非零元素
     if isempty(i)               %没有非零元素
         i = 0;
     end
     p = count + 1;
     q = p + i;
     r(p: q) = [y(1: i, j); eob];   %截去零并加上结束符号
     count = count + i + 1;
 end
 r((count + 1): end) = [];          %删除r的没有用的部分
 r = r + 128;
 %保存编码信息
 y.size = uint16([xm, xn]);
 y.numblocks = uint16(xb);
 y.quality = uint16(quality*100);
 %对r进行Huffman编码
 [y.huffman, y.info] = huffencode(uint8(r));
 

 

 

 

function vector = huffdecode(zipped, info, image)
% 函数对输入矩阵vector进行Huffman解码,返回解压后的图像数据

if ~isa(zipped, 'uint8')
    error('input argument must be be a uint8 vector');
end

%产生0,1序列,每位占一个字节
len = length(zipped);
string = repmat(uint8(0), 1, len.*8);
bitindex = 1:8;
for index = 1:len
    string(bitindex + 8.*(index-1)) = uint8(bitget(zipped(index), bitindex));
end
string = logical(string(:)');
len = length(string);
string ((len-info.pad+1):end)=[];
len = length(string);

%开始解码
weights = 2.^(0:51);
vector = repmat(uint8(0), 1, info.length);
vectorindex = 1;
codeindex = 1;
code = 0;
for index = 1:len
    code = bitset(code, codeindex, string(index));
    codeindex = codeindex+1;
    byte = decode(bitset(code, codeindex), info);
    if byte > 0
        vector(vectorindex) = byte-1;
        codeindex = 1;
        code = 0;
        vectorindex = vectorindex + 1;
    end
end
vector = reshape(vector, info.rows, info.cols);

%函数decode返回码字对应的符号
function byte = decode(code, info)
byte = info.huffcodes(code);
 

 

function [zipped, info] = huffencode(vector)
% 输入和输出都是 uint8 格式
% info 返回解码需要的结构信息
% info.pad 是添加的比特数
% info.huffcodes 是 Huffman 码字
% info.rows 是原始图像行数
% info.cols 是原始图像列数
% info.length 是原始图像数据长度
% info.maxcodelen 是最大码长

if ~isa(vector, 'uint8')
    error('input argument must be a uint8 vector');
end

[m, n] = size(vector);
vector = vector(:)';
f = frequency(vector);      %计算各符号出现的概率
symbols = find(f~=0);
f = f(symbols);
[f, sortindex] = sort(f);    %将符号按照出现的概率大小排列
symbols = symbols(sortindex);
len = length(symbols);
symbols_index = num2cell(1:len);
codeword_tmp = cell(len, 1);

% 生成 Huffman 树,得到码字编码表
while length(f)>1
    index1 = symbols_index{1};
    index2 = symbols_index{2};
    codeword_tmp(index1) = addnode(codeword_tmp(index1), uint8(0));
    codeword_tmp(index2) = addnode(codeword_tmp(index2), uint8(1));
    f = [sum(f(1:2)),f(3:end)];
    symbols_index = [{[index1, index2]},symbols_index(3:end)];
    [f, sortindex] = sort(f);
    symbols_index = symbols_index(sortindex);
end
codeword = cell(256, 1);
codeword(symbols) = codeword_tmp;
len = 0;
for index = 1:length(vector)       %得到整个图像所有比特数
    len = len + length(codeword{double(vector(index))+1});
end
string = repmat(uint8(0), 1, len);
pointer = 1;
for index = 1:length(vector)       %对输入图像进行编码
    code = codeword{double(vector(index))+1};
    len = length(code);
    string(pointer + (0:len-1))=code;
    pointer = pointer + len;
end
len = length(string);
pad = 8-mod(len, 8);
if pad > 0
    string = [string uint8(zeros(1, pad))];
end
codeword = codeword(symbols);
codelen = zeros(size(codeword));
weights = 2.^(0:23);
maxcodelen = 0;
for index = 1:length(codeword)
    len = length(codeword{index});
    if len > maxcodelen;
        maxcodelen = len;
    end
    if len > 0
        code = sum(weights(codeword{index} == 1));
        code = bitset(code, len + 1);
        codeword{index} = code;
        codelen(index) = len;
    end
end
codeword = [codeword{:}];
    
%计算压缩的向量
cols = length(string)/8;
string = reshape(string, 8, cols);
weights = 2.^(0: 7);
zipped = uint8(weights * double(string));
    
%码表存储到一个希疏矩阵
huffcodes = sparse(1, 1);
for index = 1:nnz(codeword)   % length(codeword)  %numel(codeword)
    huffcodes(codeword(index), 1) = symbols(index);
end
    
%填写解码时所需的结构信息
info.pad = pad;
info.huffcodes = huffcodes;
info.ratio = cols./length(vector);
info.length = length(vector);
info.maxcodelen = maxcodelen;
info.rows = m;
info.cols = n;
    
%函数addnode添加节点
function codeword_new = addnode(codeword_old, item)
codeword_new = cell(size(codeword_old));
for index = 1:length(codeword_old)
    codeword_new{index} = [item codeword_old{index}];
end

%函数frequency计算各符号出现的概率
function f = frequency(vector)
if ~isa(vector, 'uint8')
    error('input argument must be a uint8 vector');
end
f = repmat(0, 1, 256);
len = length(vector);
for index = 0:255
    f(index+1) = sum(vector == uint8(index));
end
f = f./len;   %归一化
    


    

function x = jpegdecode(y)
%jpegdecode函数,jpegencode的解码程序
error(nargchk(1, 1, nargin));      %检查输入参数
m = [16 11 10 16 24 40 51 61       %JPEG量化步长矩阵
     12 12 14 19 26 58 60 55
     14 13 16 24 40 57 69 56
     14 17 22 29 51 87 80 62
     18 22 37 56 68 109 103 77
     24 35 55 64 81 104 113 92
     49 64 78 87 103 121 120 101
     72 92 95 98 112 110 103 99];
 order = [1 9 2 3 10 17 25 18 11 4 5 12 19 26 33 ...        %变换系数排列次序
       41 34 27 20 13 6 7 14 21 28 35 42 49 57 50 ...
       43 36 29 22 15 8 16 23 30 37 44 51 58 59 52 ...
       45 38 31 24 32 39 46 53 60 61 54 47 40 48 55 62 63 56 64];
rev = order;          %计算逆序
for k = 1:length(order)
    rev(k) = find(order == k);
end
% ff = max(rev(:)+1;
m = double(y.quality)/100*m;
xb = double(y.numblocks);          %得到图像块数
sz = double(y.size);
xn = sz(1);
xm = sz(2);
x = huffdecode(y.huffman, y.info);    %huffman1解码
x = double(x) - 128;
eob = max(x(:));
z = zeros(64, xb);
k = 1;
for j = 1: xb
    for i = 1: 64
        if x(k) == eob
            k = k + 1;
            break;
        else
            z(i, j) = x(k);
            k = k + 1;
        end
    end
end
z = z(rev, :);               %恢复次序
x = col2im(z, [8, 8], [xm, xn], 'distinct');       %重新排列成图像
x = blkproc(x, [8, 8], 'x.*P1', m);                %逆量化
t = dctmtx(8);
x = blkproc(x, [8, 8], 'P1*x*P2', t', t);          %DCT逆变换
x = uint8(x + 128);                                %进行位移

 

  • 2
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

fpga和matlab

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值