Java 写入JPEG文件后,像素数据会发生更改

Java 写入JPEG文件后,像素数据会发生更改,java,javax.imageio,steganography,dct,density-independent-pixel,Java,Javax.imageio,Steganography,Dct,Density Independent Pixel,我正在对JPEG图像执行隐写术。我正在使用DCT系数来隐藏数据。我执行以下步骤: 将输入图像读入buffereImage 从buffereImage 应用前向DCT得到DCT系数 在DCT系数中嵌入消息位 应用逆DCT并将块写回buffereImage 重复步骤2-5,直到没有消息位剩余,此时我将buffereImage写入名为output.jpg的JPEG文件。值得一提的是,我没有对整个图像应用DCT,而是只对嵌入消息位的块应用。我使用源代码进行DCT和隐写术 问题:我在output.jpg上

我正在对JPEG图像执行隐写术。我正在使用
DCT
系数来隐藏数据。我执行以下步骤:

  • 将输入图像读入
    buffereImage
  • buffereImage
  • 应用前向DCT得到DCT系数
  • 在DCT系数中嵌入消息位
  • 应用逆DCT并将块写回
    buffereImage
  • 重复步骤2-5,直到没有消息位剩余,此时我将
    buffereImage
    写入名为
    output.jpg
    的JPEG文件。值得一提的是,我没有对整个图像应用
    DCT
    ,而是只对嵌入消息位的块应用。我使用源代码进行DCT和隐写术

    问题:我在
    output.jpg
    上出现了随机行,这意味着像素数据发生了巨大的变化。以下是用于图像写入的代码:

    static int[][] DCT_coefficients = new int[8][8];
    static double[][] DCT_matrix = new double[8][8];
    static int[][] Dequantized_m = new int[8][8];
    static int[][] YBlock = new int[8][8];
    static double[][] resultant = new double[8][8];
    static int[][] red = new int[8][8];
    static int[][] green = new int[8][8];
    static int[][] blue = new int[8][8];
    static int[][] Y = new int[8][8];
    static int[][] Cb = new int[8][8];
    static int[][] Cr = new int[8][8];
    static int x = 0, y = 0;
    
    public static void main(String args[]) {
      //I retrieve a pixel block from **BufferedImage** and convert it to YCbCr
      double temp1, temp2, temp3, temp4;
      for (int i = 0; i < 8; i++) {
        for (int j = 0; j < 8; j++) {
          Color c = new Color(input_image.getRGB(y, x));
          red = c.getRed();
          green = c.getGreen();
          blue = c.getBlue();
          YCbCr = YCrCb_conversion(red, green, blue);
          YBlock[i][j] = YCbCr[0];
          Cb[i][j] = YCbCr[1];
          Cr[i][j] = YCbCr[2];
          y++;
        }
        x++;
      }
      //calculating DCT matrix
      for (int i = 0; i < 8; i++) {
        for (int j = 0; j < 8; j++) {
          if (i == 0) {
            DCT_matrix[i][j] = 1 / Math.sqrt(8.0);
          }
          if (i > 0) {
            temp1 = 0.5;
            Apfloat Atemp1 = new Apfloat(temp1, 15);
            temp3 = ((2 * j) + 1) * i * java.lang.Math.PI;
            temp2 = temp3 / 16;
            Apfloat Atemp2 = new Apfloat(temp2, 15);
            temp4 = Math.cos(java.lang.Math.toRadians(temp2));
            Apfloat Atemp4 = ApfloatMath.cos(Atemp2);
            Apfloat Atemp = Atemp4.multiply(Atemp1);
            DCT_matrix[i][j] = Atemp.doubleValue();
          }
        }
      }
      //Leveling off Yblock
      for (int i = 0; i < 8; i++) {
        for (int j = 0; j < 8; j++) {
          leveledoff[i][j] = pixel_block[i][j] - 128;
        }
      }
      // multiplying DCT matrix and leveled off YBlock
      resultant = matrix_multiply(DCT_matrix, leveledoff);
      // taking transpose of DCT matrix
      transpose = obj.transpose(DCT_matrix);
      //multiplying transpose with resultant to get DCT coefficient block
      DCT_Coefficients = matrix_multiply(resultant, trans);
      //quantizing DCT coefficients using 50 % quantization matrix
      for (int i = 0; i < 8; i++) {
        for (int j = 0; j < 8; j++) {
          quantized_matrix[i][j] = (int) Math.round(DCT_Coefficients[i][j] / quantzation_matrix[i][j]);
        }
      }
      //Applying zigzag encoding
      ZigZag_encoded = zigzag.ZigzagEncode(quantised_m);
      //Encode data
      ZigZag_encoded = embed_data(ZigZag_encoded, data_buffer);
      //start IDCT
      IDCT(ZigZag_Encoded);
      //end main
    }
    
    //Method definitions
    //Method to change LSB of integer value
    public static int changeBit(int pixel, char bit) {
      String s = Integer.toBinaryString(pixel);
      char[] c = s.toCharArray();
      c[c.length - 1] = bit;
      // converting binary to integer
      String n = "";
      for (int y = 0; y < c.length; y++) {
        n += "" + c[y];
      }
      int j = 0;
      for (int i = 0; i < n.length(); i++) {
        if (n.charAt(i) == '1') {
          j = j + pow(2, n.length() - 1 - i);
        }
      }
      return j;
    }
    
    // method to embed data
    public static int[] embed_data(int encoded[], char buffer[]) {
      for (int i = 0; i < buffer.length; i++) {
        int newVal = changeBit(encoded[i], buffer[i]);
        encoded[i] = newVal;
      }
      return encoded;
    }
    
    // Method to perform IDCT
    public static void IDCT(ZigZag_encoded) {
      //converting 1D zigzag array to 2D array
      quantised_matrix = Zigzag_Decode(ZigZag_encoded);
      //Dequantizing 
      for (int i = 0; i < 8; i++) {
        for (int j = 0; j < 8; j++) {
          Dequantized[i][j] = quantised_matrix[i][j] * quantzation_matrix[i][j];
        }
      }
      // multiplying transpose of DCT matrix with Dequantized matrix
      resultant = matrix_multiply(transpose, Dequantized);
      //multiplying resultant with DCT matrix
      resultant = matrix_multiply(resultant, dct_mat);
      //adding 128 to each resultant entry and rounding off
      for (int i = 0; i < 8; i++) {
        for (int j = 0; j < 8; j++) {
          block[i][j] = (int) Math.round(resultant[i][j] + 128);
        }
      }
      //Converting Yblock to RGB block
      YCrCbToRGB(block, Cb, Cr);
      //writing RGB block to BufferedImage
      for (int i = 0; i < 8; i++) {
        for (int j = 0; j < 8; j++) {
          newcolor = new Color(red[i][j], green[i][j], blue[i][j]);
          input_image.setRGB(y, x, newcolor.getRGB());
          y++;
        }
        x++;
      }
    }
    
    //method to convert RGB block to YCbCr
    public int[] YCrCb_conversion(int red, int green, int blue) {
      int[] YCbCr = new int[3];
      //Y = 0.257R+ 0.504G + 0.098B + 16
      YCbCr[0] = (int)(0.257 * red + 0.504 * green + 0.098 * blue) + 16;
      //Cb=–0.148R – 0.291G+ 0.439B + 128
      YCbCr[1] = (int)((-0.148 * red - 0.291 * green + 0.439 * blue) + 128);
      //Cr = 0.439R – 0.368G – 0.071B + 128
      YCbCr[2] = (int)((0.539 * red - 0.368 * green - 0.071 * blue) + 128);
      return value
      // index 0 holds values of Y 1 holds Cb values and 2 holds Cr vlaues
      return YCbCr;
    }
    
    //Method to convert YCbCr block to RGB block
    public static void YCrCbToRGB(int y[][], int Cb[][], int Cr[][]) {
      for (int i = 0; i < 8; i++) {
        for (int j = 0; j < 8; j++) {
          //R = 1.164(Y – 16) + 1.596(Cr – 128)
          red[i][j] = (int)(1.164 * (y[i][j] - 16) + (1.596 * (Cr[i][j] - 128)));
          //G = 1.164(Y – 16) – 0.813(Cr – 128) – 0.391(Cb – 128)
          green[i][j] = (int)(1.164 * (y[i][j] - 16) - (0.813 * (Cr[i][j] - 128)) - (0.391 * (Cb[i][j] - 128)));
          //B = 1.164(Y – 16) + 2.018(Cb – 128)
          blue[i][j] = (int)(1.164 * (y[i][j] - 16) + (2.018 * (Cb[i][j] - 128)));
        }
      }
    }
    
    量化后嵌入数据前的DCT系数矩阵:

     51  -1  0  0  0  0  0  0 
     -1  0  0  0  0  0  0  0 
     0  0  0  0  0  0  0  0 
     0  0  0  0  0  0  0  0 
     0  0  0  0  0  0  0  0 
     0  0  0  0  0  0  0  0 
     0  0  0  0  0  0  0  0 
     0  0  0  0  0  0  0  0 
    
    50  -1  0  1  0  0  0  0 
     -1  0  1  0  0  0  0  0 
     1  0  0  0  0  0  0  0 
     0  0  0  0  0  0  0  0 
     0  0  0  0  0  0  0  0 
     0  0  0  0  0  0  0  0 
     0  0  0  0  0  0  0  0 
     0  0  0  0  0  0  0  0 
    
    嵌入数据后的量化DCT系数:

     51  -1  0  0  0  0  0  0 
     -1  0  0  0  0  0  0  0 
     0  0  0  0  0  0  0  0 
     0  0  0  0  0  0  0  0 
     0  0  0  0  0  0  0  0 
     0  0  0  0  0  0  0  0 
     0  0  0  0  0  0  0  0 
     0  0  0  0  0  0  0  0 
    
    50  -1  0  1  0  0  0  0 
     -1  0  1  0  0  0  0  0 
     1  0  0  0  0  0  0  0 
     0  0  0  0  0  0  0  0 
     0  0  0  0  0  0  0  0 
     0  0  0  0  0  0  0  0 
     0  0  0  0  0  0  0  0 
     0  0  0  0  0  0  0  0 
    
    嵌入数据并应用IDCT后Y空间中的像素块:

     232  227  223  223  227  231  232  231 
     230  226  222  223  226  230  230  229 
     228  224  221  222  226  229  229  227 
     226  223  221  223  227  229  228  225 
     226  224  223  225  229  230  228  225 
     227  225  225  228  232  233  230  226 
     228  227  228  231  235  236  232  228 
     230  229  230  234  237  238  233  229 
    


    我认为这是由于JPEG的有损特性,所以我尝试了PNG,但仍然遇到同样的问题。

    您可能误解了JPEG隐写术是什么。它不是DCT->embed secret->IDCT,而是遵循整个jpeg编码过程,并在中间步骤修改系数,如和。至于输出图像中的点,这可能是您如何应用步骤2-5的结果,您没有向我们展示代码。我没有执行在中提到的步骤4和步骤8。我认为哈夫曼编码不是必需的,所以我在第7步嵌入数据后直接转到IDCT。我对像素值重新居中的代码很长也不清楚,这就是我没有分享的原因。每个步骤的代码片段是否有效。向我们展示复制您的问题所需的代码。在您的例子中,应该从64个硬编码像素开始,DCT,手动修改一些系数和IDCT。如果您是基于出版物或其他内容的算法,请与我们共享源代码。您可能误解了jpeg隐写术是什么。它不是DCT->embed secret->IDCT,而是遵循整个jpeg编码过程,并在中间步骤修改系数,如和。至于输出图像中的点,这可能是您如何应用步骤2-5的结果,您没有向我们展示代码。我没有执行在中提到的步骤4和步骤8。我认为哈夫曼编码不是必需的,所以我在第7步嵌入数据后直接转到IDCT。我对像素值重新居中的代码很长也不清楚,这就是我没有分享的原因。每个步骤的代码片段是否有效。向我们展示复制您的问题所需的代码。在您的例子中,应该从64个硬编码像素开始,DCT,手动修改一些系数和IDCT。如果您是基于出版物或其他内容的算法,请与我们共享源代码。