【问题标题】:ImageWriter creates smaller picture ( in kb size ) [duplicate]ImageWriter 创建更小的图片(以 kb 为单位)[重复]
【发布时间】:2017-04-19 05:26:03
【问题描述】:

我有以下问题,我想通过在 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++;
    }

  }
}

我也尝试使用 ARGB 而不是 RGB 作为 BufferedImage,但没有运气(只会弄乱颜色,图片有点粉红色)。

这就是我在主类中调用函数的方式

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。

【问题讨论】:

    标签: java bufferedimage steganography


    【解决方案1】:

    我找到了解决办法。

    对于和我有同样问题并可能在未来寻找解决方案的人:

    此算法无法在 .jpg 扩展名中存活。将图片更改为 bmp,需要更长的时间,但一切正常。

    如果你想在 jpg 上使用隐写术,你必须使用 LSB 以外的东西。

    【讨论】:

      猜你喜欢
      • 2014-02-19
      • 2020-04-20
      • 1970-01-01
      • 2014-06-12
      • 1970-01-01
      • 1970-01-01
      • 2011-09-10
      • 1970-01-01
      • 2010-11-27
      相关资源
      最近更新 更多