100字范文,内容丰富有趣,生活中的好帮手!
100字范文 > 图像压缩编码码matlab实现——JSjpeg

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

时间:2022-09-17 01:51:06

相关推荐

图像压缩编码码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);%进行位移

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。