5.Java实现LSB(最低有效位)算法--隐藏图片

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;

/**
 * @author ArtemisKhryso
 * @time 2021/4/28
 */
public class LSB {
    //图片宽高
    private static int imgHight = 1;
    private static int imgWidth = 1;
    private static int imgHight2= 1;
    private static int imgWidth2 = 1;
    //像素矩阵集合
    private static ArrayList<String[][]> resList = new ArrayList<>();
    //原像素矩阵
    public static void main(String[] args) throws IOException {

//加密
        encryption("img/zui10/载体图像.png","img/zui10/秘密图像预处理6.png");
        //解密
        Decrypt("img/zui10/已伪装图像.png");


    }

    /**
     * 初始化并加密
     * @param src 载体图像路径
     * @param src2 秘密图像路径
     * @throws IOException
     */
    public static void encryption(String src, String src2) throws IOException {

        System.out.println("载体图像路径:"+src+" 秘密图像路径:"+src2);
        System.out.println("开始加密....");

        //图像操纵对象
        BufferedImage imgSrc = ImageIO.read(new File(src));
        BufferedImage imgSrc2 = ImageIO.read(new File(src2));
        //图片类型
        int imgType = 5;
        imgHight = imgSrc.getHeight();
        imgWidth = imgSrc.getWidth();
        imgHight2 = imgSrc2.getHeight();
        imgWidth2 = imgSrc2.getWidth();

        //创建存储像素信息的三个矩阵
        resList.clear();
        resList.add(ru(imgWidth,imgHight));
        resList.add(ru(imgWidth2,imgHight2));
        resList.add(ru(imgWidth,imgHight));

        //记录载体图像像素信息到第一个矩阵里
        for (int i = 0; i < imgWidth; i++) {
            for (int j = 0; j < imgHight; j++) {
                resList.get(0)[i][j] = Integer.toBinaryString(imgSrc.getRGB(i, j));
            }
        }
        //记录秘密图像像素信息到第二个矩阵里
        for (int i = 0; i < imgWidth2; i++) {
            for (int j = 0; j < imgHight2; j++) {
                resList.get(1)[i][j] = Integer.toBinaryString(imgSrc2.getRGB(i, j));
            }
        }
        //默认从左上角开始隐藏
        for (int i = 0; i < imgWidth; i++) {
            //如果小于隐藏图像的宽度,列号
            if (i<imgWidth2){
                for (int j = 0; j < imgHight; j++) {
                    //且小于隐藏图像的高度,行号
                    //则为秘密图像的宽高范围,应发生置换
                    if (j<imgHight2){
                        char[] chars1 = resList.get(0)[i][j].toCharArray();
                        char[] chars3 = chars1;
                        char[] chars2 = resList.get(1)[i][j].toCharArray();
                        //就将对应的位置信息放置在对应像素的透明度、红、绿、蓝通道的低4bit位
                        //采用U型替换规则,加密顺时针替换,解密逆时针替换

                        //蓝通道
                        chars3[31] = chars2[24];
                        chars3[30] = chars2[25];
                        chars3[29] = chars2[26];
                        chars3[28] = chars2[27];
                        //绿通道
                        chars3[23] = chars2[16];
                        chars3[22] = chars2[17];
                        chars3[21] = chars2[18];
                        chars3[20] = chars2[19];
                        //红通道
                        chars3[15] = chars2[8];
                        chars3[14] = chars2[9];
                        chars3[13] = chars2[10];
                        chars3[12] = chars2[11];
                        //透明度通道
                        chars3[7] = chars2[0];
                        chars3[6] = chars2[1];
                        chars3[5] = chars2[2];
                        chars3[4] = chars2[3];
                        //保存置换后的像素信息至第三个矩阵中
                        resList.get(2)[i][j] = String.valueOf(chars3);
                    }else {
                        //保存没有置换的像素信息至第三个矩阵中
                        resList.get(2)[i][j] = String.valueOf(resList.get(0)[i][j].toCharArray());
                    }
                }
            }else {
                for (int j = 0; j < imgHight; j++) {
                    resList.get(2)[i][j] = String.valueOf(resList.get(0)[i][j].toCharArray());
                }
            }
        }


        //输出加密结果
        oimg(resList.get(2),"已伪装图像",imgWidth,imgHight);


        System.out.println("加密完成....");
    }

    public static void Decrypt(String src) throws IOException {
        //图像操纵对象
        BufferedImage imgSrc = ImageIO.read(new File(src));
        //图片类型
        int imgType = 5;
        imgWidth = imgSrc.getWidth();
        imgHight = imgSrc.getHeight();
        System.out.println(imgWidth2);
        System.out.println(imgHight2);

        resList.clear();
        resList.add(ru(imgWidth,imgHight));
        resList.add(ru(imgWidth2,imgHight2));

        for (int i = 0; i < imgWidth; i++) {
            if (i<imgWidth2){
                for (int j = 0; j < imgHight; j++) {
                    if (j<imgHight2){
                        char[] chars1 = Integer.toBinaryString(imgSrc.getRGB(i, j)).toCharArray();

                        char[] chars2 = new char[32];
                        char[] chars3 = new char[32];
                        for (int h = 0; h < 32; h++){
                            chars2[h] = '0';
                            chars3[h] = '0';
                        }
                        chars2[24] = chars1[24];
                        chars2[25] = chars1[25];
                        chars2[26] = chars1[26];
                        chars2[27] = chars1[27];
                        chars3[24] = chars1[31];
                        chars3[25] = chars1[30];
                        chars3[26] = chars1[29];
                        chars3[27] = chars1[28];

                        chars2[16] = chars1[16];
                        chars2[17] = chars1[17];
                        chars2[18] = chars1[18];
                        chars2[19] = chars1[19];
                        chars3[16] = chars1[23];
                        chars3[17] = chars1[22];
                        chars3[18] = chars1[21];
                        chars3[19] = chars1[20];

                        chars2[8] = chars1[8];
                        chars2[9] = chars1[9];
                        chars2[10] = chars1[10];
                        chars2[11] = chars1[11];
                        chars3[8] = chars1[15];
                        chars3[9] = chars1[14];
                        chars3[10] = chars1[13];
                        chars3[11] = chars1[12];

                        chars2[0] = chars1[0];
                        chars2[1] = chars1[1];
                        chars2[2] = chars1[2];
                        chars2[3] = chars1[3];
                        chars3[0] = chars1[7];
                        chars3[1] = chars1[6];
                        chars3[2] = chars1[5];
                        chars3[3] = chars1[4];
                        resList.get(0)[i][j] = String.valueOf(chars2);
                        resList.get(1)[i][j] = String.valueOf(chars3);
                    }else {
                        resList.get(0)[i][j] = Integer.toBinaryString(imgSrc.getRGB(i, j));
                    }
                }
            }else {
                for (int j = 0; j < imgHight; j++) {
                    resList.get(0)[i][j] = Integer.toBinaryString(imgSrc.getRGB(i, j));
                }
            }

        }

        oimg(resList.get(0),"解密后载体图像",imgWidth,imgHight);
        oimg(resList.get(1),"解密后秘密图像",imgWidth2,imgHight2);

        System.out.println("解密完成....");
    }

    /**
     * 生产像素矩阵
     * @param width
     * @param hight
     * @return
     */
    public static String[][] ru(int width,int hight){
        return new String[width][hight];
    }

    /**
     * 图片输出方法
     * @param matrix
     * @param name
     * @param imgWidth
     * @param imgHight
     */
    public static void oimg(String[][] matrix, String name,int imgWidth, int imgHight){
        BufferedImage imgRes = new BufferedImage(imgWidth, imgHight, 5);
        for (int i = 0; i < imgWidth; i++) {
            for (int j = 0; j < imgHight; j++) {
//                System.out.println("第"+name+"个  i:"+i+"  j:"+j+"  值:"+Integer.parseUnsignedInt(r[i][j],2));
                imgRes.setRGB(i,j,Integer.parseUnsignedInt(matrix[i][j],2));
            }
        }
        File imgOut = new File("img/zui10/"+name+".png");
        //输出文件
        try {
            ImageIO.write(imgRes, "png", imgOut);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}


在这里插入图片描述

通道是什么?

一个像素占一个int(32bit)
从左往右00000000 00000000 00000000 00000000
第一个八位是决定像素蓝光的
第二个绿
第三个红
第四个透明度
每个八位对其颜色的影响也是从左往右降低 越低位影响越大 越能保持像素的原始信息 所以把低八位隐藏在高八位里

  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
没有积分的私聊我 看到消息百分百发给你 1、算法核心: 1、读取图片A,获得其RGB三个通道数据并转换成三个矩阵a1,a2,a3。 2、读取文件B,将其转换成比特流b。 3、遍历b,得到比特b1,b2,b3,b4,b5,b6等等,将b1代替a1第一个元素的最低位,将b2代替a2第一个元素的最低位,将b3代替a3第一个元素的最低位,将b4代替a1第二个元素的最低位,以此类推。 2、具体实现: 1、隐写: 1、使用java ImageIO读取图片,获取其RGB通道信息。 2、使用java NIO读取被嵌入的文件,将其转换为byte数组,需要特别指出的是原生方法得到是byte类型的数组,但是算法实现需要更加精细的操作,所以还需要对得到的byte数组进行进一步的转换封装,将其转换成形如10101的数组。例如,读取文件得到byte数组的第一个元素为63,需将63转换为00111111数组。并且保存好文件的长度。 3、按照算法,遍历形如10101的数组 1、如果遍历到的值为0,将矩阵对应的矩阵元素与0xfe进行与运算,将最低位置为0 2、如果遍历到的值为1,将矩阵对应的矩阵元素与0x01进行或运算,将最低位置为1 4、将步骤3得到的经过经过隐写的矩阵写为一张新的图片。 3、读取 1、使用java ImageIO读取图片,获取其RGB通道信息。 2、使用隐写步骤3得到的文件长度,遍历图片的像素矩阵,需要特别指出的是因为后续步骤还需要进行进一步的转化,所以这一步是将得到的“100100......”序列每八位封装为一个数组,最终得到一些数组集合,每个数组包含八位二进制序列。 3、将步骤2得到的数组进行转换,例如00111111应该转换为byte类型数值为63的数字,10111111转换为-63。这一步会得到一个byte类型的数组。 4、将步骤3得到的byte类型数组写入文件,需要指出的是写入的文件形式应该和隐写模块步骤二中读入的文件形式一致。 3、程序使用方法 1、安装Java8 2、使用命令行进入jar文件所在目录下,使用命令 java -jar 2016115130.jar 3、安装提示输入嵌入和被嵌入的文件名字,注意路径问题

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值