Java实现LSB隐写术将图片藏入另一图片提取后像素损坏求助
问题排查与修复方案
你的代码核心错误出在二进制字符串转整数的逻辑上,错误将二进制字符串以十进制规则解析,导致分量数值完全错乱,以下是具体问题和修复方案:
一、核心错误点
- 二进制转换逻辑错误
现有转换逻辑完全错误:
RHString[n] = Integer.toBinaryString(RData[n]); // 得到分量的二进制字符串,比如分量值12得到"1100" RData[n]= Integer.parseInt(RHString[n]); // 这里会把二进制字符串"1100"当做十进制数解析,直接变成1100,数值完全错乱 RHString[n] = String.format("%08d",RData[n]); // 最后得到的是十进制1100补零后的"00001100",和原来分量的8位二进制完全不相关
这一步直接导致后续拼接的二进制内容全错,只是因为载体图片的高4位偏差不大,肉眼看不出异常,但隐藏的秘密数据已经错乱。
2. 次要问题
- 隐藏代码中
Color c = new Color(orImage.getRGB(x,y), true);是冗余代码,没有实际作用 - 提取代码中
n++缺少分号,会导致编译报错
二、修复方案
方案1:修正字符串处理逻辑
正确的8位二进制补零逻辑应该直接对二进制字符串补前导零,不需要中间转int:
// 正确的8位二进制转换示例,所有分量的转换都替换成这个写法,删掉中间转int的错误代码 RHString[n] = String.format("%8s", Integer.toBinaryString(RData[n])).replace(' ', '0');
方案2:改用位运算实现(更高效稳定,推荐)
完全不用字符串操作,直接用位运算处理,避免字符串操作的各种问题:
修正后的隐藏代码核心逻辑
for(int y=0 ; y<orHeight ; y++) { for(int x=0 ; x<orWidth ; x++) { // 保留载体分量高4位,清空低4位 int r = (RData[n] & 0xF0); int g = (GData[n] & 0xF0); int b = (BData[n] & 0xF0); // 取秘密图片分量高4位,放到载体的低4位 r |= (oRData[n] >> 4) & 0x0F; g |= (oGData[n] >> 4) & 0x0F; b |= (oBData[n] >> 4) & 0x0F; // 保存处理后的分量 RData[n] = r; GData[n] = g; BData[n] = b; n++; } } // 写入图片逻辑保留,删掉冗余的读Color那行代码 n=0; for(int y=0 ; y<orHeight ; y++) { for(int x=0 ; x<orWidth ; x++) { Color newC = new Color(RData[n], GData[n],BData[n]); orImage.setRGB(x,y,newC.getRGB()); n++; } }
修正后的提取代码核心逻辑
int n = 0; for(int y=0 ; y<hiHeight ; y++) { for(int x=0 ; x<hiWidth ; x++) { // 取隐写图片分量的低4位,左移4位补零得到秘密图片的分量 int r = (RData[n] & 0x0F) << 4; int g = (GData[n] & 0x0F) << 4; int b = (BData[n] & 0x0F) << 4; RData[n] = r; GData[n] = g; BData[n] = b; n++; } } // 写入提取后的图片逻辑不变 n=0; for(int y=0 ; y<hiHeight ; y++) { for(int x=0 ; x<hiWidth ; x++) { Color newC = new Color(RData[n], GData[n],BData[n]); hidImage.setRGB(x,y,newC.getRGB()); n++; } }
三、额外注意事项
- 确保秘密图片的分辨率和载体图片的分辨率完全一致,否则也会出现像素错位
- 确保读取图片的时候没有丢失alpha通道,如果是带透明通道的png图片,需要额外处理alpha分量的隐写,否则透明通道数据会被覆盖导致异常
内容的提问来源于stack exchange,提问作者IKS
相关产品推荐
相关产品推荐

