2016-12-04 11 views
1

私は以下の問題があります。LSBにメッセージをコーディングして簡単なステガノグラフィ「プログラム」を作成します。ImageWriterは小さな画像を作成します(KBサイズで)

青い色の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のために代わりにRGBのARGBを使用しようとしました。

は、これは私が

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キロバイトを持っているメインクラス内の関数を呼び出し、再作成画像のみ24,3キロバイトを持っているかです。

答えて

0

解決策が見つかりました。私と将来的に解決策を探して可能な限り同じ問題を抱えて誰のための

このアルゴリズムは、.jpgの拡張子は生き残ることができません。ピクチャをbmpに変更しましたが、少し時間がかかりますが、すべて正常に動作します。

jpgでステガノグラフィーを使用する場合は、LSB以外のものを使用する必要があります。

関連する問題