图片LSB隐写(java)

article/2025/11/6 22:31:38

一、隐写原理

        LSB隐写原理就是图片中的像素一般是由三种颜色组成,即三原色(红绿蓝)。由这三种原色可以组成其他各种颜色,在png图片的存储中,每个颜色占有8bit,即有256种颜色,一共包含256的三次方颜色,即16777216中颜色。人类的眼睛可以区分约1,000万种不同的颜色,剩下无法区分的颜色就有6777216。

        LSB隐写就是修改了像素中的最低位,把一些信息隐藏起来。png图片是一种无损压缩,也只有在无损压缩或无压缩的图片(bmp图片是一种无压缩)上实现LSB隐写,

        举例:观察图一、图二,没有发现区别,图二是经过图一加特定的信息(测试123aaa)生成新的图片,使用解密函数,可以重新恢复图片中的信息。

  

                            图一 

                          图二 

二、实现代码

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;/*** 图像掩蔽 RGB依次取Bit*/
public class ImageMasker {public boolean[] content = null;private BufferedImage image = null;private void setContent(Color color, int start) {content[start] = (1 == color.getRed() % 2);content[start + 1] = (1 == color.getGreen() % 2);content[start + 2] = (1 == color.getBlue() % 2);}private int changeToColor(int rgb, int start) {if (content[start]) rgb = rgb | 0x00010000;else rgb = rgb & 0xFFFEFFFF;if (content[start + 1]) rgb = rgb | 0x00000100;else rgb = rgb & 0xFFFFFEFF;if (content[start + 2]) rgb = rgb | 0x00000001;else rgb = rgb & 0xFFFFFFFE;return rgb;}/*** 读取文件* @param file* @return*/public boolean read(String file) {try {image = ImageIO.read(new File(file));} catch (IOException e) {e.printStackTrace();return false;}int height = image.getHeight();int width = image.getWidth();content = new boolean[height * width * 3];for (int h = 0; h < height; h++) {for (int w = 0; w < width; w++) {int color = image.getRGB(w, h);Color c = new Color(color);setContent(c, (h * width + w) * 3);}}return true;}public boolean write(String file) {if (null == image) return false;int height = image.getHeight();int width = image.getWidth();for (int h = 0; h < height; h++)for (int w = 0; w < width; w++)image.setRGB(w, h, changeToColor(image.getRGB(w, h), (h * width + w) * 3));try {String format = file.substring(file.lastIndexOf(".") + 1);ImageIO.write(image, format, new File(file));} catch (IOException e) {e.printStackTrace();return false;}return true;}}

public class StringEncoder {public static boolean[] encodeString(String s) {try {byte[] b = s.getBytes("GBK");boolean[] bl = new boolean[b.length * 8];for (int i = 0; i < b.length; i++) {bl[8 * i] = (((b[i]) & 0x1) == 1);bl[8 * i + 1] = (((b[i] >> 1) & 0x1) == 1);bl[8 * i + 2] = (((b[i] >> 2) & 0x1) == 1);bl[8 * i + 3] = (((b[i] >> 3) & 0x1) == 1);bl[8 * i + 4] = (((b[i] >> 4) & 0x1) == 1);bl[8 * i + 5] = (((b[i] >> 5) & 0x1) == 1);bl[8 * i + 6] = (((b[i] >> 6) & 0x1) == 1);bl[8 * i + 7] = (((b[i] >> 7) & 0x1) == 1);}return bl;} catch (Exception e) {e.printStackTrace();}return null;}/*** 根据隐写的图片,还原写入的数据* @param bl* @return*/public static String decodeString( boolean[] bl) {try {byte[] b = new byte[bl.length / 8];for (int i = 0; i < b.length; i++) {b[i] = 0;if (bl[8 * i]) b[i] = (byte) (b[i] | 0x1);if (bl[8 * i + 1]) b[i] = (byte) (b[i] | 0x2);if (bl[8 * i + 2]) b[i] = (byte) (b[i] | 0x4);if (bl[8 * i + 3]) b[i] = (byte) (b[i] | 0x8);if (bl[8 * i + 4]) b[i] = (byte) (b[i] | 0x10);if (bl[8 * i + 5]) b[i] = (byte) (b[i] | 0x20);if (bl[8 * i + 6]) b[i] = (byte) (b[i] | 0x40);if (bl[8 * i + 7]) b[i] = (byte) (b[i] | 0x80);}return new String(b, "GBK");} catch (Exception e) {e.printStackTrace();}return "Failed to decode string!";}}

 三、测试

 public static void main(String[] args) {BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));ImageMasker imageMasker = new ImageMasker();try {System.out.print("请输入文件路径:");String s = bufferedReader.readLine();imageMasker.read(s);System.out.print("写入内容还是读取(r/w):");s = bufferedReader.readLine();if (s.equals("r")) {System.out.print(StringEncoder.decodeString(imageMasker.content).trim());} else if (s.equals("w")) {System.out.print("输入数据(<=" + imageMasker.content.length / 8 + "):");s = bufferedReader.readLine();boolean[] value = StringEncoder.encodeString(s);for (int i = 0; i < value.length; i++)imageMasker.content[i] = value[i];for (int i = value.length; i < imageMasker.content.length; i++) {imageMasker.content[i] = false;}System.out.print("输出文件路径:");s = bufferedReader.readLine();imageMasker.write(s);}} catch (IOException e) {e.printStackTrace();}}

图一:C:\Users\Administrator\Desktop\sorce.png

图二:C:\Users\Administrator\Desktop\sorce1.png 

 中文乱码,大家帮我看看原因。

来自网络,可以试试

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Scanner;public class LSB {public static void main(String[] args) throws IOException {Scanner scan = new Scanner(System.in);System.out.println("***************LSB图像隐写编码程序****************");System.out.println("*********请选择想要使用的功能(输入数字)*************");System.out.println();System.out.println("******************1.LSB编码********************");System.out.println("******************2.LSB解码********************");System.out.println();System.out.print("请输入你想选择的功能:");String choice = scan.next();switch (choice) {case "1":System.out.print("请输入需要加密的文件的路径:");String textPath = scan.next();System.out.print("请输入png图像辅助文件的路径:");String imagePath = scan.next();System.out.print("最后再输入一下生成的png图片的保存路径:");String imageOutputPath = scan.next();LSBEncoder(textPath, imagePath, imageOutputPath);scan.close();break;case "2":System.out.print("请输入待解码的png图片的路径:");String imageInputPath = scan.next();System.out.print("请输入解码后,存放数据的文件名称");String textFilePath = scan.next();LSBDecoder(imageInputPath, textFilePath);scan.close();break;default:System.out.print("谁叫你乱按键盘的啊!!!活该不能执行,哼?!");scan.close();break;}}public static void LSBEncoder(String textPath, String imagePath, String imageOutputPath) throws IOException {//读取png图像BufferedImage image = ImageIO.read(new File(imagePath));int width = image.getWidth();int height = image.getHeight();int[][][] rgb = new int[width][height][3];//将图像每个点的像素(R,G,B)存储在数组中for (int w = 0; w < width; w++) {for (int h = 0; h < height; h++) {int pixel = image.getRGB(w, h);//读取的是一个24位的数据//数据三个字节分别代表R、B、Grgb[w][h][0] = (pixel & 0xff0000) >> 16;//Rrgb[w][h][1] = (pixel & 0xff00) >> 8;//Brgb[w][h][2] = (pixel & 0xff);//G}}//导入待加密机密文件FileInputStream fis = new FileInputStream(textPath);int byteLen = fis.available();byte[] buf = new byte[byteLen];fis.read(buf);//我用两个字节(16位)表示数据部分的长度,也就是说,图像转像素点后,前16个像素点的R对应的字节的最低有效位都是默认表示数据字节数组的长度//规定,数据的长度最大为2^16-1int[] bufLen = new int[2];bufLen[0] = (byteLen & 0xff00) >> 8;bufLen[1] = (byteLen & 0xff);for (int i = 0; i < 2; i++) {for (int j = 7; j >= 0; j--) {int h = (i * 8 + (7 - j)) / width;int w = (i * 8 + (7 - j)) % width;//只取每个像素点的R,的字节的最低位if ((bufLen[i] >> j & 1) == 1) {rgb[w][h][0] = rgb[w][h][0] | 1;} else {rgb[w][h][0] = rgb[w][h][0] & 0xe;}}}//按照规则将数据的二进制序列全部放到每一个像素点的第一个字节的最后一位上for (int i = 2; i < byteLen + 2; i++) {for (int j = 7; j >= 0; j--) {//高int h = (i * 8 + (7 - j)) / width;//宽int w = (i * 8 + (7 - j)) % width;if ((buf[i - 2] >> j & 1) == 1) {rgb[w][h][0] = rgb[w][h][0] | 1;//变1} else {rgb[w][h][0] = rgb[w][h][0] & 0xe;}}}//        构建通过编码生成的png图片的类型BufferedImage imageOutput = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);for (int w = 0; w < width; w++) {for (int h = 0; h < height; h++) {int[] color = new int[3];color[0] = rgb[w][h][0] << 16;color[1] = rgb[w][h][1] << 8;color[2] = rgb[w][h][2];int pixel = 0xff000000 | color[0] | color[1] | color[2];imageOutput.setRGB(w, h, pixel);}}ImageIO.write(imageOutput, "png", new File(imageOutputPath));}public static void LSBDecoder(String imageInputPath, String textFilePath) throws IOException {BufferedImage imageInput = ImageIO.read(new File(imageInputPath));int width = imageInput.getWidth();int height = imageInput.getHeight();int[] bufLen = new int[2];//将图像每个点的像素(R,G,B)存储在数组中for (int i = 0; i < 2; i++) {int[] bits = new int[8];for (int j = 7; j >= 0; j--) {int h = (i * 8 + (7 - j)) / width;int w = (i * 8 + (7 - j)) % width;int pixel = imageInput.getRGB(w, h);int r = (pixel & 0xff0000) >> 16;bits[j] = (r & 1) << j;}bufLen[i] = bits[7] | bits[6] | bits[5] | bits[4] | bits[3] | bits[2] | bits[1] | bits[0];}int byteLen = ((bufLen[0] << 7) | bufLen[1]);byte[] buf = new byte[byteLen];for (int i = 2; i < byteLen + 2; i++) {int[] bits = new int[8];for (int j = 7; j >= 0; j--) {int h = (i * 8 + (7 - j)) / width;int w = (i * 8 + (7 - j)) % width;int pixel = imageInput.getRGB(w, h);int r = (pixel & 0xff0000) >> 16;bits[j] = (r & 0x1) << j;}buf[i - 2] = (byte) (bits[7] | bits[6] | bits[5] | bits[4] | bits[3] | bits[2] | bits[1] | bits[0]);}FileOutputStream fos = new FileOutputStream(textFilePath);fos.write(buf);fos.close();}
}


http://chatgpt.dhexx.cn/article/q6DKqT2e.shtml

相关文章

LSB隐写术

前言 LSB全称为 least significant bit&#xff0c;是最低有效位的意思。Lsb图片隐写是基于lsb算法的一种图片隐写术&#xff0c;以下统称为lsb隐写&#xff0c;这是一种常见的信息隐藏方法。当然关于图像的隐写的方法有很多&#xff0c;统称为隐写术&#xff0c; lsb隐写很实…

Linux开发标准LSB简介:Linux Standard Base

目录 Unix/Linux 标准化历史 POSIX Open Group Austin Group LSB LSB 简介 组织架构 工作组 LSB 的标准化流程 认证 认证问题报告 LSB 的历史、现状和将来 实例&#xff1a;lsb_release 的规范定义和实现 结束语 Unix/Linux 标准化历史 标准化目前已经成为 Linu…

LSB 简介

Unix/Linux 标准化历史 标准化目前已经成为 Linux 系统上的一个热门话题。实际上&#xff0c;在 Linux 诞生之初&#xff0c;这个问题就得到了重视。当 Linus 在开发 0.01 版本的 Linux 内核时&#xff0c;就开始关注 POSIX 标准的发展&#xff0c;他在 /include/unistd.h 文件…

图片隐写之LSB(Least Significant Bit)原理及其代码实现

1. 什么是隐写&#xff1f; 隐写术是一门关于信息隐藏的技巧与科学&#xff0c;所谓信息隐藏指的是不让除预期的接收者之外的任何人知晓信息的传递事件或者信息的内容。隐写术的英文叫做Steganography&#xff0c;来源于特里特米乌斯的一本讲述密码学与隐写术的著作Steganogra…

MetaPhlAn2:宏基因组物种组成分析

简介 MetaPhlAn2是分析微生物群落(细菌、古菌、真核生物和病毒)组成的工具&#xff0c;它在宏基因组研究中非常有用&#xff0c;只需一条完命令即可获得微生物的物种丰度信息(扩增子物种组成需要质控、拼接、拆样本、切除引物、比对等步骤&#xff0c;此软件居然分析宏基因组这…

你想要的宏基因组-微生物组知识全在这(2023.4)

欢迎点击上方蓝色”宏基因组”关注我们&#xff01; 宏基因组/微生物组是当今世界科研最热门的研究领域之一&#xff0c;为加强宏基因组学技术和成果交流传播&#xff0c;推动全球华人微生物组领域发展&#xff0c;中科院青年科研人员创立“宏基因组”公众号&#xff0c;联合海…

Kraken2:宏基因组快速物种注释神器

简介 kraken是基于k-mer精确比对&#xff0c;并采用最LCA投票结果快速宏基因组DNA序列进行物种注释的软件。 图. Kraken2分类基本原理 该文章于2014年发表于Genome Biology&#xff0c;目前引用过两千次[1]。详见《Kraken&#xff1a;使用精确比对的超快速宏基因组序列分类软件…

Nature综述: 宏基因组关联分析-深入研究微生物组

本文由谢忠杰编译&#xff0c;董小橙、江舜尧编辑&#xff0c;本文较长&#xff0c;建议用电脑阅读。 “微生太”原创微文&#xff0c;转载已获授权。 导读 问题1&#xff1a;哪些疾病与人体微生物明确相关&#xff1f; 问题2&#xff1a;如何研究人体微生物与健康的关系&#…

Nature子刊:HUMAnN2实现宏基因组和宏转录组种水平功能组成分析

HUMAnN2实现宏基因组和宏转录组种水平功能组成分析 Species-level functional profiling of metagenomes and metatranscriptomes Nature Methods, [IF 26.919], Article, 2018-10-30 DOI: http://dx.doi.org/10.1038/s41592-018-0176-y 第一作者&#xff1a;Eric A. Franzosa…

从测序到宏基因组:聚焦菌群生信分析方法最前沿

今天是第2439期日报。 Nature子刊&#xff1a;基于三代测序的宏基因组分析助力完整微生物进化研究 Nature Methods[IF:47.99] ① 基于Pacific Biosciences或Oxford Nanopore的三代测序技术已成为获得闭环微生物基因组的常规手段&#xff0c;即使对特殊大量数据的读取&#xff0…

Protein Cell:扩增子和宏基因组数据分析实用指南

扩增子和宏基因组数据分析实用指南 A practical guide to amplicon and metagenomic analysis of microbiome data Protein Cell [IF: 10.164] DOI: https://doi.org/10.1007/s13238-020-00724-8 Review: 2020-5-11 第一作者&#xff1a;刘永鑫1,2,3, 秦媛1,2,3,4, 陈同5 通讯作…

凌恩生物文献分享|颠覆性的宏基因组新思路,速来get!

非人灵长类动物&#xff08;NHP&#xff09;是人类的近亲&#xff0c;为宿主-微生物互作的研究提供了一个很好的例子。近年来研究主要集中在野生灵长类动物的肠道微生物群&#xff0c;这将有助于了解灵长类及其肠道微生物群的进化&#xff0c;但仍然缺乏关于野生种群肠道微生物…

Nature综述:宏基因组测序研究耐药基因的方法和资源

本文转自红皇后学术&#xff0c;链接 https://mp.weixin.qq.com/s/2QMrq6hwr4mIPSpe_rfXJg 论文信息 论文题目&#xff1a;Sequencing-based methods and resources to study antimicrobial resistance 期刊&#xff1a;Nature Reviews Genetics IF&#xff1a;35.898 发表时间…

Nature综述:鸟枪法宏基因组-从取样到数据分析——2万字带你系统入门宏基因组实验和分析

文章目录 NBT&#xff1a;鸟枪法宏基因组-从取样到数据分析热心肠日报摘要正文图1. 宏基因组分析流程概述附图1. 用于规划宏基因组学研究的示例工作流程附框1. 实验设计中的问题和解决方案鸟枪法宏基因组学研究方案设计样本采集和DNA提取表1. 在测序之前富集微生物细胞和DNA方法…

宏基因组TPM定量

在RNA-Seq分析中&#xff0c;为了获取基因表达量差异&#xff0c;于是产生了RPKM、FPKM、TPM定量方法&#xff0c;去除测序深度和基因长度的影响。RPKM用于单端测序&#xff1b;FPKM用于双端测序。而TPM计算方法类似于RPKM&#xff0c;但更具有优势&#xff0c;是目前使用的较多…

你想要的宏基因组-微生物组知识全在这(2023.01)

欢迎点击上方蓝色”宏基因组”关注我们&#xff01; 宏基因组/微生物组是当今世界科研最热门的研究领域之一&#xff0c;为加强宏基因组学技术和成果交流传播&#xff0c;推动全球华人微生物组领域发展&#xff0c;中科院青年科研人员创立“宏基因组”公众号&#xff0c;联合海…

你想要的宏基因组-微生物组知识全在这(2022.10)

欢迎点击上方蓝色”宏基因组”关注我们&#xff01; 宏基因组/微生物组是当今世界科研最热门的研究领域之一&#xff0c;为加强宏基因组学技术和成果交流传播&#xff0c;推动全球华人微生物组领域发展&#xff0c;中科院青年科研人员创立“宏基因组”公众号&#xff0c;联合海…

你想要的宏基因组-微生物组知识全在这(2022.12)

欢迎点击上方蓝色”宏基因组”关注我们&#xff01; 宏基因组/微生物组是当今世界科研最热门的研究领域之一&#xff0c;为加强宏基因组学技术和成果交流传播&#xff0c;推动全球华人微生物组领域发展&#xff0c;中科院青年科研人员创立“宏基因组”公众号&#xff0c;联合海…

Nature子刊:宏基因组中挖掘原核基因组的分析流程

宏基因组中挖掘原核基因组的分析流程 从宿主相关的短读长鸟枪宏基因组测序数据中恢复原核基因组 Recovering prokaryotic genomes from host-associated, short-read shotgun metagenomic sequencing data Nature Protocols [IF:10.419] 2021-04-16 Articles DOI: https://doi…

宏基因组测序实验分析方法

宏基因组测序实验分析方法-功能分析基于reads 1 使用ctab法或相应试剂盒提取样本中的总 DNA&#xff1b; 2 DNA样品检测合格后&#xff0c;使用Covaris超声波破碎仪随机打断&#xff0c;再经末端修复、加A尾、加测序接头、纯化、PCR扩增等步骤完成整个文库制备工作&#xff1…