Matlab实现简单的GifShuffle算法隐藏信息

GifShuffle算法:

隐藏的对象是索引图像,通过改变调色板的顺序来隐藏信息,这是Gifshuffle算法的基本思想,排序的方式有很多种。对于256色的调色板矩阵来说,最多可以容纳1684个bit信息。
这里我只实现最简单的版本,即将调色板分为一对一对的,一对当中,若前面的颜色值大于后面的则代表1,否则代表0。

索引图像是一种把像素值直接作为RGB调色板下标的图像。索引图像可把像素值“直接映射”为调色板数值。
一幅索引图包含一个数据索引矩阵data和一个调色板矩阵map,数据矩阵可以是uint8,uint16或双精度类型的,而调色板矩阵则总是一个m×3的双精度矩阵。

关于数据索引是如何对应调色板矩阵的:

我们看到图像索引矩阵的(1,1)单元的内容为124,也就是说这一点像素的颜色就是调色板矩阵的第125行所定义的颜色。

具体代码

隐藏函数

function [ newdata, newmap ] = SortPalletHiding( data,map, msg )
%通过改变调色板的顺序来隐藏信息
%data:原始的索引矩阵;
%map: 原始的调色板矩阵;
%msg: 需要隐藏的信息
newmap = map;
newdata = data;
size_data = prod(size(data));
len = length(msg);  %信息的长度
msgasc = double(msg);
msgstr = de2bi(msgasc,7,2); %将信息转为一维的二进制串
msgstr = msgstr';
lenstr = de2bi(len,7,2);
%把消息的长度存入前面14个调色板点上去
for i = 1:2:13
    info = Judgement(map(i,:), map(i+1,:));
    lenstr_i = uint8(i/2);
    if info ~= lenstr(lenstr_i)        %如果调色板的顺序代表的信息不同,则调换顺序
        newmap(i,:) = map(i+1,:);
        newmap(i+1,:) = map(i,:);
        newdata = SwapData(newdata,i,size_data);
    end
    %Judgement(newmap(i,:), newmap(i+1,:))测试取消注释
end
%把信息存入剩下的调色板中去,这里考虑256色
len_msg = (14*(len+1)-1);
for j = 15:2:len_msg
    info = Judgement(map(j,:), map(j+1,:));
    msg_i = uint8((j-14)/2);
    if info ~= msgstr(msg_i)        %如果调色板的顺序代表的信息不同,则调换顺序
        newmap(j,:) = map(j+1,:);
        newmap(j+1,:) = map(j,:);
        newdata = SwapData(newdata,j,size_data);
    end
end
end

function info = Judgement(row1, row2)
%判断传入的参数(两行)的大小,确定代表的是1还是0;这里定义row1小于row2代表1,否则代表2
%row1、row2均为调色板的一行数据,一个3维行向量
if row1(1)>row2(1)
    info = 0;
elseif row1(1)<row2(1)
    info = 1;
else
    if row1(2)>row2(2)
        info = 0;
    elseif row1(2)<row2(2)
        info = 1;
    else
        if row1(3)>row2(3)
            info = 0;
        elseif row1(3)<row2(3)
            info = 1;
        else
            info = 0;%如果两个点的颜色值完全相等,返回0.
        end
    end
end
end

function [newdata] = SwapData(data,index,size)
%交换索引矩阵中的值
%data:原始索引矩阵
%index:调色板中颜色的索引值
%size:data的大小,包含多少个索引
for i = 1:size
    if data(i)+1 == index    %这里的data(i)1的原因是因为数据索引矩阵的值是从0开始的,而调色板矩阵的值是从1开始的
        data(i) = data(i) + 1;
    elseif data(i)+1 == index + 1
        data(i) = data(i) - 1;
    end
end
newdata = data;
end

提取函数

function info = ExtractFromSortPallet( newmap )
%提取隐藏信息
%newmap:改变之后的调色板
lenstr = zeros(1,7);
%提取消息长度
for i = 1:2:13
    len_i = uint8(i/2);
    lenstr(len_i) = Judgement(newmap(i,:), newmap(i+1,:));
end
%提取消息
len = bi2de(lenstr);
msg = zeros(7,len); %初始化消息矩阵7行n列,代表有n个字符,最大为18个字符
len_msg = (14*(len+1)-1);
for j = 15:2:len_msg
    msg_i = uint8((j-14)/2);
    msg(msg_i) = Judgement(newmap(j,:),newmap(j+1,:));
end
msgasc = bi2de(msg');   %提取得到的为二进制数据,转化为char字符
message = char(msgasc);
message = message';
info = message;
end

function info = Judgement(row1, row2)
%判断传入的参数(两行)的大小,确定代表的是1还是0;这里定义row1小于row2代表1,否则代表2
%row1、row2均为调色板的一行数据,一个3维行向量
if row1(1)>row2(1)
    info = 0;
elseif row1(1)<row2(1)
    info = 1;
else
    if row1(2)>row2(2)
        info = 0;
    elseif row1(2)<row2(2)
        info = 1;
    else
        if row1(3)>row2(3)
            info = 0;
        elseif row1(3)<row2(3)
            info = 1;
        else
            info = 0;%如果两个点的颜色值完全相等,返回0.
        end
    end
end
end

测试脚本

im = imread('comic.png');
[data, map] = rgb2ind(im, 256);
[newdata, newmap] = SortPalletHiding(data, map, 'I love Sherry!');
imshow(data, map);title('origin');
figure;imshow(newdata, newmap);title('stegano');
info = ExtractFromSortPallet(newmap);
fprintf('The secret info is:%s\n', info);

测试结果

运行后得到以下效果,基本完成。
Matlab实现简单的GifShuffle算法隐藏信息
Matlab实现简单的GifShuffle算法隐藏信息
注:哈哈哈,小哀是我的~