Advertisement
Guest User

Untitled

a guest
May 27th, 2015
219
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 10.54 KB | None | 0 0
  1. import java.awt.image.BufferedImage;
  2. import java.util.Arrays;
  3.  
  4. import org.apache.commons.lang3.math.NumberUtils;
  5. import org.apache.commons.math3.analysis.interpolation.SplineInterpolator;
  6. import org.apache.commons.math3.analysis.polynomials.PolynomialSplineFunction;
  7.  
  8.  
  9. public class ImageHandler
  10. {
  11.     public static final int N = 8;
  12.     private final int T1 = 6, T2 = 3, E=35;
  13.    
  14.     final int xn=24;
  15.    
  16.     private BufferedImage input;
  17.     private int height, width, blocksNum;
  18.     private byte[] dataToHide;
  19.     private int[][] blocks;
  20.     private int[][] blueBlocks;
  21.     private int[][] delta;
  22.     private int[][] zones;
  23.     private int[][] masks;
  24.    
  25.     public ImageHandler(BufferedImage img)
  26.     {
  27.         input = img;
  28.         height = input.getHeight();
  29.         width = input.getWidth();
  30.         blocksNum = height*width/(N*N);
  31.     }
  32.    
  33.        
  34.    
  35.    
  36.     public BufferedImage encrypt(String str) throws Exception
  37.     {
  38.         //convert input string to binary sequence
  39.         dataToHide = this.stringToBinary(str);
  40.         if (dataToHide.length > blocksNum)
  41.             throw new Exception("There is not enough space in the image to hide the message");
  42.                
  43.         //System.out.println( Arrays.toString(dataToHide) );
  44.        
  45.         blocks = new int[blocksNum][N*N];
  46.         blueBlocks = new int[blocksNum][N*N];
  47.         zones = new int[blocksNum][N*N];
  48.         masks = new int[blocksNum][N*N];
  49.         delta = new int[blocksNum][4];
  50.        
  51.        
  52.         //splitting image to 64-pixels blocks, picking out blue components
  53.         splitInput();
  54.        
  55.        
  56.        
  57.         //splitting every block to zones according to intensity of its blue component
  58.         splitToZones();
  59.        
  60.         //System.out.println( Arrays.toString(zones[0]) );
  61.                
  62.                    
  63.         //generating mask for each block
  64.         generateMasks();
  65.        
  66.         //System.out.println( Arrays.toString(masks[0]) );
  67.                
  68.        
  69.         //computing intensity shifts based on masks and zones
  70.         computeDelta();
  71.        
  72.        
  73.        
  74.         //data integration into blue blocks
  75.         shiftData();
  76.        
  77.        
  78.         //normalizing blue blocks
  79.         normalizeData();
  80.        
  81.        
  82.         //integrating blue blocks back to the pixels blocks
  83.         integrateData();
  84.        
  85.        
  86.        
  87.         BufferedImage output = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
  88.                
  89.         return uniteOutput(output);
  90.     }
  91.  
  92.    
  93.     public String decrypt()
  94.     {
  95.         blocks = new int[blocksNum][N*N];
  96.         blueBlocks = new int[blocksNum][N*N];
  97.         zones = new int[blocksNum][N*N];
  98.         masks = new int[blocksNum][N*N];
  99.        
  100.         //splitting image to 64-pixels blocks, picking out blue components
  101.         splitInput();
  102.                
  103.                                
  104.         //splitting every block to zones according to intensity of its blue component
  105.         splitToZones();
  106.        
  107.         //System.out.println( Arrays.toString(zones[0]) );
  108.  
  109.         //generating mask for each block
  110.         generateMasks();
  111.                        
  112.        
  113.         return extract();  
  114.     }
  115.    
  116.    
  117.    
  118.    
  119.    
  120.    
  121.    
  122.    
  123.     private void splitInput()
  124.     {
  125.         int startX = 0, startY = 0;
  126.         for (int i=0; i<blocksNum; i++)
  127.         {
  128.             if (startX>=width)
  129.             {
  130.                 startX = 0;
  131.                 startY += N;
  132.             }
  133.                        
  134.             blocks[i] = input.getRGB(startX, startY, N, N, null, 0, N);
  135.             for(int j=0; j<N*N; j++)
  136.                 blueBlocks[i][j] = getBlue(blocks[i][j]);
  137.            
  138.             startX += N;
  139.         }
  140.     }
  141.    
  142.    
  143.    
  144.     private void splitToZones()
  145.     {
  146.         for (int i=0; i<xn; i++)
  147.         {
  148.             int[] currentBlock = Arrays.copyOf(blueBlocks[i], N*N);
  149.            
  150.             //sorting the block
  151.             Arrays.sort(currentBlock);
  152.            
  153.             //System.out.println( Arrays.toString(currentBlock) );
  154.            
  155.             //splining function
  156.             int r = 10;
  157.             double[] hi = new double[r];
  158.             double[] fi = new double[r];
  159.             for (int j=0; j<r; j++)
  160.             {
  161.                 hi[j] = j*Math.round(N*N/(r-1));
  162.                 fi[j] = currentBlock[(int) hi[j]];
  163.             }
  164.            
  165.             SplineInterpolator interpolator = new SplineInterpolator();
  166.             PolynomialSplineFunction spline = interpolator.interpolate(hi,fi);
  167.            
  168.             double sMax = 0, alpha = -1;
  169.             for (int x = 0; x<N*N; x++)
  170.             {
  171.                 if (spline.derivative().value(x) > sMax)
  172.                 {
  173.                     sMax = spline.derivative().value(x);
  174.                     alpha = x;
  175.                 }
  176.             }
  177.            
  178.            
  179.             if (alpha == -1)
  180.                 alpha = N*N/2;
  181.             else if (alpha == 0)
  182.                 alpha = 1;
  183.             else if(alpha == N*N-1)
  184.                 alpha = N*N-2;
  185.            
  186.            
  187.             int bminus=0, bplus=0;
  188.            
  189.             if (sMax < T1) // noise contrast
  190.             {
  191.                 int k=0;
  192.                 for (int j=0; j<zones[i].length; j++)
  193.                 {
  194.                    
  195.                     zones[i][j] = (j+k)%2 + 1;
  196.                     if ( (j+1) % 8 == 0)
  197.                         ++k;
  198.                 }
  199.             }
  200.             else // sharp contrast
  201.             {
  202.                
  203.                 //bminus
  204.                 for (int j=(int)alpha; j>=0; j--)
  205.                 {
  206.                     if (j==0)
  207.                         bminus = (int)alpha;
  208.                     if (currentBlock[(int)alpha] - currentBlock[j] > T2)
  209.                     {
  210.                         bminus = j;
  211.                         break;
  212.                     }
  213.                 }
  214.                 //bplus
  215.                 for (int j=(int)alpha; j<N*N; j++)
  216.                 {
  217.                     if (j==N*N-1)
  218.                         bplus = (int)alpha;
  219.                     if (currentBlock[j] - currentBlock[(int)alpha] > T2)
  220.                     {
  221.                         bplus = j;
  222.                         break;
  223.                     }
  224.                 }
  225.                 // split pixels to zones
  226.                 for  (int j=0; j<currentBlock.length; j++)
  227.                 {
  228.                     if ( getBlue(blocks[i][j]) < currentBlock[bminus] )
  229.                         zones[i][j] = 1;
  230.                     else if ( getBlue(blocks[i][j]) > currentBlock[bplus] )
  231.                         zones[i][j] = 2;
  232.                     else
  233.                         zones[i][j] = 0;
  234.                 }
  235.             }
  236.         }
  237.     }
  238.    
  239.    
  240.    
  241.     private void generateMasks()
  242.     {
  243.         int k0=123;
  244.         for (int i=0; i<xn; i++)
  245.         {
  246.             Arrays.fill(masks[i], 0);
  247.             for (int j=0; j<N*N/2; j++)
  248.                 masks[i][ ( i+j*k0 ) % (N*N) ] = 1;
  249.             for (int j=0; j<N*N; j++)
  250.                 if (masks[i][j] != 1)
  251.                     masks[i][j] = 2;
  252.         }
  253.     }
  254.    
  255.    
  256.    
  257.     private void computeDelta()
  258.     {
  259.         for (int i=0; i<xn; i++)
  260.         {
  261.             byte b = dataToHide[i];
  262.             int[] B = blueBlocks[i];
  263.             int[] Z = zones[i];
  264.             int[] M = masks[i];
  265.             int[] n = new int[4];
  266.             double[] sl = new double[4];
  267.             double[] sl_star = new double[4];
  268.            
  269.             for (int j=0; j<N*N; j++)
  270.             {
  271.                 if (Z[j]==1 && M[j]==1) { ++n[0]; sl[0] += B[j]; }
  272.                 else if (Z[j]==1 && M[j]==2) { ++n[1]; sl[1] += B[j]; }                
  273.                 else if (Z[j]==2 && M[j]==1) { ++n[2]; sl[2] += B[j]; }                
  274.                 else if (Z[j]==2 && M[j]==2) { ++n[3]; sl[3] += B[j]; }
  275.             }
  276.                    
  277.             sl[0] = sl[0]==0 ? 0 : sl[0]/n[0];
  278.             sl[1] = sl[1]==0 ? 0 : sl[1]/n[1];
  279.             sl[2] = sl[2]==0 ? 0 : sl[2]/n[2];
  280.             sl[3] = sl[3]==0 ? 0 : sl[3]/n[3];
  281.                                    
  282.             for (int x=0; x<2; x++)
  283.             {
  284.                 double lx = (sl[2*x]*n[2*x] + sl[2*x+1]*n[2*x+1]);
  285.                 if (b == 1)
  286.                 {
  287.                     sl_star[2*x] = ( - lx - n[2*x+1]*E )/( - n[2*x] - n[2*x+1] );
  288.                     sl_star[2*x+1] = ( n[2*x]*E - lx )/( - n[2*x] - n[2*x+1] );
  289.                 } else
  290.                 {
  291.                     sl_star[2*x] = ( lx - n[2*x+1]*E )/( n[2*x] + n[2*x+1] );
  292.                     sl_star[2*x+1] = ( n[2*x]*E + lx )/( n[2*x] + n[2*x+1] );
  293.                 }
  294.             }
  295.            
  296.             //with transposition
  297.             delta[i][0] = (int) Math.round( sl_star[0] - sl[0] );
  298.             delta[i][1] = (int) Math.round( sl_star[1] - sl[1] );
  299.             delta[i][2] = (int) Math.round( sl_star[2] - sl[2] );
  300.             delta[i][3] = (int) Math.round( sl_star[3] - sl[3] );
  301.            
  302.  
  303.             //System.out.println( (sl_star[0] - sl[0]) + " " + (sl_star[1] - sl[1]) );
  304.             //System.out.println( (sl_star[2] - sl[2]) + " " + (sl_star[3] - sl[3]) );
  305.             //System.out.println(delta[i][0] + " " + delta[i][1]);
  306.             //System.out.println(delta[i][2] + " " + delta[i][3]);
  307.                        
  308.         }
  309.     }
  310.    
  311.    
  312.    
  313.     private void shiftData()
  314.     {
  315.         for (int i=0; i<xn; i++)
  316.         {
  317.             int[] Z = zones[i];
  318.             int[] M = masks[i];
  319.            
  320.             for (int j=0; j<xn; j++)
  321.             {
  322.                 if (Z[j]==1 && M[j]==1) { blueBlocks[i][j] += delta[i][0]; }
  323.                 else if (Z[j]==1 && M[j]==2) { blueBlocks[i][j] += delta[i][1]; }                  
  324.                 else if (Z[j]==2 && M[j]==1) { blueBlocks[i][j] += delta[i][2]; }                  
  325.                 else if (Z[j]==2 && M[j]==2) { blueBlocks[i][j] += delta[i][3]; }
  326.             }
  327.            
  328.         }
  329.        
  330.        
  331.     }
  332.    
  333.    
  334.    
  335.     private void normalizeData()
  336.     {
  337.         int min = 256;
  338.         int max = 0;
  339.         for (int i=0; i<blueBlocks.length; i++)
  340.         {          
  341.             if ( NumberUtils.min(blueBlocks[i]) < min)
  342.                 min = NumberUtils.min(blueBlocks[i]);
  343.             if ( NumberUtils.max(blueBlocks[i]) > max)
  344.                 max = NumberUtils.max(blueBlocks[i]);
  345.            
  346.         }
  347.                
  348.         for (int i=0; i<blueBlocks.length; i++)
  349.             for (int j=0; j<blueBlocks[i].length; j++)
  350.                 blueBlocks[i][j] = Math.round( (blueBlocks[i][j] + Math.abs(min))*255/(max + Math.abs(min)) );
  351.                
  352.     }
  353.    
  354.    
  355.     private String extract()
  356.     {
  357.         StringBuilder res = new StringBuilder();       
  358.        
  359.         for (int i=0; i<xn; i++)
  360.         {
  361.             int[] B = blueBlocks[i];
  362.             int[] Z = zones[i];
  363.             int[] M = masks[i];
  364.             int[] n = new int[4];
  365.             double[] sl = new double[4];
  366.                        
  367.             for (int j=0; j<N*N; j++)
  368.             {
  369.                 if (Z[j]==1 && M[j]==1) { ++n[0]; sl[0] += B[j]; }
  370.                 else if (Z[j]==1 && M[j]==2) { ++n[1]; sl[1] += B[j]; }                
  371.                 else if (Z[j]==2 && M[j]==1) { ++n[2]; sl[2] += B[j]; }                
  372.                 else if (Z[j]==2 && M[j]==2) { ++n[3]; sl[3] += B[j]; }
  373.             }
  374.                    
  375.             sl[0] = sl[0]==0 ? 0 : sl[0]/n[0];
  376.             sl[1] = sl[1]==0 ? 0 : sl[1]/n[1];
  377.             sl[2] = sl[2]==0 ? 0 : sl[2]/n[2];
  378.             sl[3] = sl[3]==0 ? 0 : sl[3]/n[3];
  379.            
  380.             double E1 = sl[0] - sl[1];
  381.             double E2 = sl[2] - sl[3];
  382.            
  383.             if ( E1*E2 > 0.05 )
  384.             {
  385.                 if (E1 > 0)
  386.                     res.append('1');
  387.                 else
  388.                     res.append('0');
  389.             } else if ( E1*E2 < -0.05 )
  390.             {
  391.                 double Estar = E1*(n[0]+n[1]) + E2*(n[2]+n[3]);
  392.                 if (Estar > 0)
  393.                     res.append('1');
  394.                 else
  395.                     res.append('0');
  396.             } else
  397.             {
  398.                 double Estar = Math.max(E1, E2);
  399.                 if (Estar > 0)
  400.                     res.append('1');
  401.                 else
  402.                     res.append('0');
  403.             }
  404.         }
  405.        
  406.         return res.toString();
  407.     }
  408.    
  409.    
  410.    
  411.    
  412.    
  413.    
  414.     private void integrateData()
  415.     {
  416.         for (int i=0; i<xn; i++)
  417.         {
  418.             for (int j=0; j<blueBlocks[i].length; j++)
  419.                 blocks[i][j] = (int) changeBlue(blocks[i][j], blueBlocks[i][j]);
  420.         }
  421.     }
  422.    
  423.    
  424.     private BufferedImage uniteOutput(BufferedImage img)
  425.     {
  426.         int startX = 0, startY = 0;
  427.         for (int i=0; i<blocksNum; i++)
  428.         {
  429.             if (startX>=width)
  430.             {
  431.                 startX = 0;
  432.                 startY += N;
  433.             }
  434.             img.setRGB(startX, startY, N, N, blocks[i], 0, N);
  435.             startX += N;
  436.         }
  437.        
  438.        
  439.         return img;
  440.     }
  441.    
  442.    
  443.    
  444.    
  445.    
  446.    
  447.    
  448.    
  449.    
  450.    
  451.        
  452.     private byte[] stringToBinary(String str)
  453.     {
  454.         byte[] bytes = str.getBytes();
  455.         byte[] binary = new byte[bytes.length*8];
  456.        
  457.         for (int i=0; i<bytes.length; i++)
  458.         {
  459.            int val = bytes[i];
  460.            for (int j = 0; j < 8; j++)
  461.            {
  462.               binary[i*8+j] = (byte) ((val & 128) == 0 ? 0 : 1);
  463.               val <<= 1;
  464.            }
  465.         }
  466.         return binary;
  467.     }
  468.        
  469.     private int getBlue(int z) { return Integer.parseInt( String.format("%32s", Integer.toBinaryString( z ) ).replace(' ', '0').substring(24, 32), 2); }
  470.    
  471.     private long changeBlue(int b, int bb)
  472.     {
  473.         String sb = String.format("%32s", Integer.toBinaryString( b ) ).replace(' ', '0');
  474.         String sbb = String.format("%8s", Integer.toBinaryString( bb ) ).replace(' ', '0');
  475.            
  476.         StringBuilder sBuilder = new StringBuilder(sb);
  477.        
  478.        
  479.         sBuilder = sBuilder.replace(24, 32, sbb);
  480.        
  481.         return Long.parseLong(sBuilder.toString(),2);
  482.     }
  483.    
  484.    
  485. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement