- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我有以下问题,我想通过在 LSB 中编码消息来创建简单的隐写术“程序”。
我从图片中提取 ARGB(每个都在它自己的数组中),以蓝色的 LSB 编码消息,并尝试使用这些新值创建新图像(我将 ARGB 数组加入到 int 数组中)。
我遇到的明显问题是,当我更改 LSB 并尝试将它们写入图片时,我可以看到 ImageWriter 正在创建以 kb 为单位的小得多的图片,并且我无法再提取我的消息。
这是代码:
import javax.imageio.ImageWriteParam;
import javax.imageio.ImageWriter;
import javax.imageio.stream.ImageOutputStream;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
public class Steganography {
int [][] alpha;
int [][] red;
int [][] green;
int [][] blue;
public int [][] readPixels (String image) throws IOException {
//load image into img buffer
BufferedImage img = ImageIO.read(new File(image));
//make matrix according to picture height and width
int [][] pixels = new int[img.getHeight()][img.getWidth()];
// load matrix with image pixels
for(int i=0;i<pixels.length;i++) {
for (int j = 0; j < pixels[0].length; j++) {
pixels[i][j]=(img.getRGB(j, i));
}
}
/* reminder to myself
values will be negative because of packing the 4 byte values into a 4-byte
The getRGB method returns an int whose 4 bytes are the alpha, red, green, and blue components in that order.
Assuming that the pixel is not transparent, the alpha is 255 (0xFF).
It's the most significant byte in the int, and the first bit is set in that value.
Because in Java int values are signed according to Two's Complement,
the value is actually negative because that first bit is on.
*/
return pixels ;
}
// extracts colors and alpha into their own matrix so we can reconstruct image later
public void extractColors(int [][] pixel){
this.alpha = new int[pixel.length][pixel[0].length];
this.red = new int[pixel.length][pixel[0].length];
this.green = new int[pixel.length][pixel[0].length];
this.blue = new int[pixel.length][pixel[0].length];
for(int i=0;i<pixel.length;i++) {
for(int j=0;j<pixel[i].length;j++){
int clr = pixel[i][j];
alpha[i][j] = (clr & 0xff000000) >> 24;
red[i][j] = (clr & 0x00ff0000) >> 16;
green[i][j] = (clr & 0x0000ff00) >> 8;
blue [i][j] = clr & 0x000000ff;
}
}
} // closed method
//reconstruct image
// need to make 32 bit integer again in correct order
public void reconstructImage () throws IOException{
int height = alpha.length;
int width= alpha[0].length;
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
for (int y = 0; y < width; y++) {
for (int x = 0; x < height; x++) {
int rgb= red[x][y];
rgb = (rgb << 8) + green[x][y];
rgb = (rgb << 8) + blue[x][y];
image.setRGB(y, x, rgb);
}
}
ImageWriter writer = ImageIO.getImageWritersByFormatName("jpeg").next();
ImageWriteParam param = writer.getDefaultWriteParam();
param.setCompressionMode(ImageWriteParam.MODE_EXPLICIT); // Needed see javadoc
param.setCompressionQuality(1.0F); // Highest quality
File file = new File("output.jpg");
ImageOutputStream ios = ImageIO.createImageOutputStream(file);
writer.setOutput(ios);
writer.write(image);
}
public void codeMessage (String message){
//first turn string into binary representation
// each character should have 7 bits
// ASCII uses 7 bit
message="START"+message.length()+message+"STOP";
String binaryMessage ="";
for(int i =0;i<message.length();i++){
//adding zeros if string has less than 8 characters
String binaryString= Integer.toBinaryString(message.charAt(i));
while (binaryString.length() !=7)
binaryString = "0"+binaryString;
binaryMessage+=binaryString;
}
//binaryMessage is binary representation of string
// change value of LSB in blue color according to binaryMessage
//actually coding message into LSB is done here
int k=0;
for (int i = 0; i < blue.length; i++) {
for (int j = 0; j < blue[i].length; j++) {
if(k>=binaryMessage.length())
break;
else if (binaryMessage.charAt(k) == '0') {
blue[i][j] = blue[i][j] & 0b1111110;
k++;
}
else {
blue[i][j] = blue[i][j] | 0b0000001;
k++;
}
}
}
} //closed codeMessage
public void readMessage(){
String LSB ="";
char charLSB;
String messageBinary ="";
for(int i=0;i<blue.length;i++){
for(int j=0;j<blue[i].length;j++){
LSB = Integer.toBinaryString(blue[i][j]);
charLSB = LSB.charAt(LSB.length()-1);
messageBinary+=charLSB;
}
}
char ArrayOfChars [] = new char [blue[0].length*blue.length];
int k =0;
for(int i=0;i<messageBinary.length()-7;i+=7){
String letter=(messageBinary.substring(i,i+7));
int valueOfASCIIcharacter = Integer.parseInt(letter,2);
char c = (char)(valueOfASCIIcharacter);
System.out.println(c);
ArrayOfChars[k]=c;
k++;
}
}
}
我也尝试过对 BufferedImage 使用 ARGB 而不是 RGB,但没有运气(只会弄乱颜色,图片变得有点粉红色)。
这就是我在主类中调用函数的方式
import java.io.IOException;
public class Main {
public static void main(String[] args) throws IOException{
Steganography img = new Steganography();
int pixels [][] =img.readPixels("image.jpg");
img.extractColors(pixels);
img.codeMessage("Some message");
img.reconstructImage();
/*reading message from here on */
int pixels2 [][] = img.readPixels("output.jpg");
img.extractColors(pixels2);
img.readMessage();
}
}
原始图片有 83,3 kb,重新创建的图片只有 24,3 kb。
最佳答案
我找到了解决方案。
对于任何与我有同样问题并可能在未来寻找解决方案的人:
该算法无法在 .jpg 扩展名中幸存。将图片更改为 bmp,需要更长的时间,但一切都按预期进行。
如果你想在 jpg 上使用隐写术,你必须使用 LSB 以外的东西。
关于java - ImageWriter 创建较小的图片(以 kb 大小为单位),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40963756/
我将文件读入字符串,更改第一行,然后将此字符串写入新文件。我通过以下代码(稍微缩短了一点)来做到这一点: while(jspIterator.hasNext()){
adb shell dumsys meminfo返回的内存是kB还是KB? 哪里: kB = 1000 bytes KB = 1024 bytes 最佳答案 它是 KB(1024 字节)或 ki
我能够解析 xml 文件,并且我想下载 xml 给出的 url 的文件。我有以下代码: try{ /* Create a URL we want to load some xm
这个问题在这里已经有了答案: Android, Compressing an image (2 个答案) 关闭 10 个月前。 我正在 android 中开发一个应用程序,它将捕获照片并存储在 sq
我将文件保存在我的 MySQL 数据库中的 LONGBLOB 列上,当我在我的 IDE 中执行选择时,我注意到一些 base64 文件内容有消息 206.2 kB (204.8 kB loaded)放
使用 Indy 的 TIdTCPServer 组件,一个包被分两部分接收,但客户端发送了一个 64 KB 的包。 如何在服务器 OnExecute 事件中接收完整的包? 现在我放了一个原型(proto
我正在编写一个正则表达式,它可以捕获一个值及其后面的任何 mb、kb、gb、字节正则表达式是: (?\p{N}+)(?:\s*)(?[mb|kb|gb|b|bytes]) 但是当给定输入“40
我刚刚创建了 range(1,100000) 的 python 列表. 使用 SparkContext 完成以下步骤: a = sc.parallelize([i for i in range(1,
我的要求是将相机捕获的图像上传到服务器,但它应该小于 500 KB。如果大于 500 KB,则需要减小到小于 500 KB (但稍微接近) 为此,我使用以下代码 - @Override pub
我有以两种不同方式加载和保存图像的代码-第一种使用openCV,第二种使用PIL。 import cv2 from PIL import Image img = cv2.imread("/home/m
我有一个 android 视频播放器,它显示 SD 卡上的所有视频名称和文件大小,但大小以字节显示,我无法将它转换为 KB、MB、GB 等。我尝试除以 int值增加 1024 但它不起作用。它打印出错
任何人都可以向我解释一下摘要报告中如何测量吞吐量、Kb/秒和平均字节数吗? 我得到了以下登录操作的总结报告。 Label : Login Action(sampler) Sample# : 1 ave
我需要将上传图片的大小调整为最大 100 kB。可能吗? 例如:尺寸为 1200x600 的 image1.jpg 有 280kB,我需要将其调整为 <100kB。 最佳答案 ImageMagick
我需要将上传图片的大小调整为最大 100 kB。可能吗? 例如:尺寸为 1200x600 的 image1.jpg 有 280kB,我需要将其调整为 <100kB。 最佳答案 ImageMagick
我有例如: Document doc = Jsoup.connect("http://example.com/").get(); String title = doc.title(); Documen
我正忙于Android通话录音机,当我调用电话时录音机显示它正在录音,在我挂断电话后,它保存文件,但保存的文件是0 KB 有没有人遇到同样的问题,请帮我解决一下。 这是我的录制代码 recorder
我正在以 KB 为单位将文件存储在数据库中。我尝试将文件信息返回的文件长度转换为 KB,如下所示。 FileInfo FileVol = new FileInfo(DownloadPath); int
在我的应用程序中,显示照片中的所有视频。选择视频后,将使用 avplayer 播放该视频。但是当我尝试获取所选视频文件的大小(kb)时,它显示错误。当我尝试复制视频文件时出现同样的错误。 我已获取这些
我正在尝试在 firebase 存储中上传图像,我希望图像不应大于 50 kb 我正在尝试获取位图的大小,以便我可以知道位图的大小是否超过 50 kb这图片不会显示在画廊中 我已经尝试了许多人建议的代
在我的 android 应用程序中,它收集了一些数据和照片扔手机。 之后它将所有这些东西插入到一个对象中,然后将这个对象发送到服务器。 在将此对象发送到服务器之前,我想向用户显示数据的大小以及将此数据
我是一名优秀的程序员,十分优秀!