Advertisement
Guest User

Untitled

a guest
May 27th, 2015
205
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 10.02 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=2;
  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.         StringBuilder res = new StringBuilder();
  113.        
  114.        
  115.         for (int i=0; i<xn; i++)
  116.         {
  117.             int[] B = blueBlocks[i];
  118.             int[] Z = zones[i];
  119.             int[] M = masks[i];
  120.             int[] n = new int[4];
  121.             double[] sl = new double[4];
  122.                        
  123.             for (int j=0; j<N*N; j++)
  124.             {
  125.                 if (Z[j]==1 && M[j]==1) { ++n[0]; sl[0] += B[j]; }
  126.                 else if (Z[j]==1 && M[j]==2) { ++n[1]; sl[1] += B[j]; }                
  127.                 else if (Z[j]==2 && M[j]==1) { ++n[2]; sl[2] += B[j]; }                
  128.                 else if (Z[j]==2 && M[j]==2) { ++n[3]; sl[3] += B[j]; }
  129.             }
  130.                    
  131.             sl[0] = sl[0]==0 ? 0 : sl[0]/n[0];
  132.             sl[1] = sl[1]==0 ? 0 : sl[1]/n[1];
  133.             sl[2] = sl[2]==0 ? 0 : sl[2]/n[2];
  134.             sl[3] = sl[3]==0 ? 0 : sl[3]/n[3];
  135.            
  136.             i
  137.            
  138.         }
  139.        
  140.        
  141.        
  142.        
  143.        
  144.        
  145.        
  146.         return res.toString(); 
  147.     }
  148.    
  149.    
  150.    
  151.    
  152.    
  153.    
  154.    
  155.    
  156.     private void splitInput()
  157.     {
  158.         int startX = 0, startY = 0;
  159.         for (int i=0; i<blocksNum; i++)
  160.         {
  161.             if (startX>=width)
  162.             {
  163.                 startX = 0;
  164.                 startY += N;
  165.             }
  166.                        
  167.             blocks[i] = input.getRGB(startX, startY, N, N, null, 0, N);
  168.             for(int j=0; j<N*N; j++)
  169.                 blueBlocks[i][j] = getBlue(blocks[i][j]);
  170.            
  171.             startX += N;
  172.         }
  173.     }
  174.    
  175.    
  176.    
  177.     private void splitToZones()
  178.     {
  179.         for (int i=0; i<xn; i++)
  180.         {
  181.             int[] currentBlock = Arrays.copyOf(blueBlocks[i], N*N);
  182.            
  183.             //sorting the block
  184.             Arrays.sort(currentBlock);
  185.            
  186.             //System.out.println( Arrays.toString(currentBlock) );
  187.            
  188.             //splining function
  189.             int r = 10;
  190.             double[] hi = new double[r];
  191.             double[] fi = new double[r];
  192.             for (int j=0; j<r; j++)
  193.             {
  194.                 hi[j] = j*Math.round(N*N/(r-1));
  195.                 fi[j] = currentBlock[(int) hi[j]];
  196.             }
  197.            
  198.             SplineInterpolator interpolator = new SplineInterpolator();
  199.             PolynomialSplineFunction spline = interpolator.interpolate(hi,fi);
  200.            
  201.             double sMax = 0, alpha = -1;
  202.             for (int x = 0; x<N*N; x++)
  203.             {
  204.                 if (spline.derivative().value(x) > sMax)
  205.                 {
  206.                     sMax = spline.derivative().value(x);
  207.                     alpha = x;
  208.                 }
  209.             }
  210.            
  211.            
  212.             if (alpha == -1)
  213.                 alpha = N*N/2;
  214.             else if (alpha == 0)
  215.                 alpha = 1;
  216.             else if(alpha == N*N-1)
  217.                 alpha = N*N-2;
  218.            
  219.            
  220.             int bminus=0, bplus=0;
  221.            
  222.             if (sMax < T1) // noise contrast
  223.             {
  224.                 int k=0;
  225.                 for (int j=0; j<zones[i].length; j++)
  226.                 {
  227.                    
  228.                     zones[i][j] = (j+k)%2 + 1;
  229.                     if ( (j+1) % 8 == 0)
  230.                         ++k;
  231.                 }
  232.             }
  233.             else // sharp contrast
  234.             {
  235.                
  236.                 //bminus
  237.                 for (int j=(int)alpha; j>=0; j--)
  238.                 {
  239.                     if (j==0)
  240.                         bminus = (int)alpha;
  241.                     if (currentBlock[(int)alpha] - currentBlock[j] > T2)
  242.                     {
  243.                         bminus = j;
  244.                         break;
  245.                     }
  246.                 }
  247.                 //bplus
  248.                 for (int j=(int)alpha; j<N*N; j++)
  249.                 {
  250.                     if (j==N*N-1)
  251.                         bplus = (int)alpha;
  252.                     if (currentBlock[j] - currentBlock[(int)alpha] > T2)
  253.                     {
  254.                         bplus = j;
  255.                         break;
  256.                     }
  257.                 }
  258.                 // split pixels to zones
  259.                 for  (int j=0; j<currentBlock.length; j++)
  260.                 {
  261.                     if ( getBlue(blocks[i][j]) < currentBlock[bminus] )
  262.                         zones[i][j] = 1;
  263.                     else if ( getBlue(blocks[i][j]) > currentBlock[bplus] )
  264.                         zones[i][j] = 2;
  265.                     else
  266.                         zones[i][j] = 0;
  267.                 }
  268.             }
  269.         }
  270.     }
  271.    
  272.    
  273.    
  274.     private void generateMasks()
  275.     {
  276.         int k0=123;
  277.         for (int i=0; i<xn; i++)
  278.         {
  279.             Arrays.fill(masks[i], 0);
  280.             for (int j=0; j<N*N/2; j++)
  281.                 masks[i][ ( i+j*k0 ) % (N*N) ] = 1;
  282.             for (int j=0; j<N*N; j++)
  283.                 if (masks[i][j] != 1)
  284.                     masks[i][j] = 2;
  285.         }
  286.     }
  287.    
  288.    
  289.    
  290.     private void computeDelta()
  291.     {
  292.         for (int i=0; i<xn; i++)
  293.         {
  294.             byte b = dataToHide[i];
  295.             int[] B = blueBlocks[i];
  296.             int[] Z = zones[i];
  297.             int[] M = masks[i];
  298.             int[] n = new int[4];
  299.             double[] sl = new double[4];
  300.             double[] sl_star = new double[4];
  301.            
  302.             for (int j=0; j<N*N; j++)
  303.             {
  304.                 if (Z[j]==1 && M[j]==1) { ++n[0]; sl[0] += B[j]; }
  305.                 else if (Z[j]==1 && M[j]==2) { ++n[1]; sl[1] += B[j]; }                
  306.                 else if (Z[j]==2 && M[j]==1) { ++n[2]; sl[2] += B[j]; }                
  307.                 else if (Z[j]==2 && M[j]==2) { ++n[3]; sl[3] += B[j]; }
  308.             }
  309.                    
  310.             sl[0] = sl[0]==0 ? 0 : sl[0]/n[0];
  311.             sl[1] = sl[1]==0 ? 0 : sl[1]/n[1];
  312.             sl[2] = sl[2]==0 ? 0 : sl[2]/n[2];
  313.             sl[3] = sl[3]==0 ? 0 : sl[3]/n[3];
  314.                                    
  315.             for (int x=0; x<2; x++)
  316.             {
  317.                 double lx = (sl[2*x]*n[2*x] + sl[2*x+1]*n[2*x+1]);
  318.                 if (b == 1)
  319.                 {
  320.                     sl_star[2*x] = ( - lx - n[2*x+1]*E )/( - n[2*x] - n[2*x+1] );
  321.                     sl_star[2*x+1] = ( n[2*x]*E - lx )/( - n[2*x] - n[2*x+1] );
  322.                 } else
  323.                 {
  324.                     sl_star[2*x] = ( lx - n[2*x+1]*E )/( n[2*x] + n[2*x+1] );
  325.                     sl_star[2*x+1] = ( n[2*x]*E + lx )/( n[2*x] + n[2*x+1] );
  326.                 }
  327.             }
  328.            
  329.             //with transposition
  330.             delta[i][0] =  Math.round( sl_star[0] - sl[0] );
  331.             delta[i][1] =  Math.round( sl_star[1] - sl[1] );
  332.             delta[i][2] =  Math.round( sl_star[2] - sl[2] );
  333.             delta[i][3] =  Math.round( sl_star[3] - sl[3] );
  334.            
  335.  
  336.             //System.out.println( (sl_star[0] - sl[0]) + " " + (sl_star[1] - sl[1]) );
  337.             //System.out.println( (sl_star[2] - sl[2]) + " " + (sl_star[3] - sl[3]) );
  338.             //System.out.println(delta[i][0] + " " + delta[i][1]);
  339.             //System.out.println(delta[i][2] + " " + delta[i][3]);
  340.                        
  341.         }
  342.     }
  343.    
  344.    
  345.    
  346.     private void shiftData()
  347.     {
  348.         for (int i=0; i<xn; i++)
  349.         {
  350.             int[] Z = zones[i];
  351.             int[] M = masks[i];
  352.            
  353.             for (int j=0; j<xn; j++)
  354.             {
  355.                 if (Z[j]==1 && M[j]==1) { blueBlocks[i][j] += delta[i][0]; }
  356.                 else if (Z[j]==1 && M[j]==2) { blueBlocks[i][j] += delta[i][1]; }                  
  357.                 else if (Z[j]==2 && M[j]==1) { blueBlocks[i][j] += delta[i][2]; }                  
  358.                 else if (Z[j]==2 && M[j]==2) { blueBlocks[i][j] += delta[i][3]; }
  359.             }
  360.            
  361.         }
  362.        
  363.        
  364.     }
  365.    
  366.    
  367.    
  368.     private void normalizeData()
  369.     {
  370.         int min = 256;
  371.         int max = 0;
  372.         for (int i=0; i<blueBlocks.length; i++)
  373.         {          
  374.             if ( NumberUtils.min(blueBlocks[i]) < min)
  375.                 min = NumberUtils.min(blueBlocks[i]);
  376.             if ( NumberUtils.max(blueBlocks[i]) > max)
  377.                 max = NumberUtils.max(blueBlocks[i]);
  378.            
  379.         }
  380.                
  381.         for (int i=0; i<blueBlocks.length; i++)
  382.             for (int j=0; j<blueBlocks[i].length; j++)
  383.                 blueBlocks[i][j] = Math.round( (blueBlocks[i][j] + Math.abs(min))*255/(max + Math.abs(min)) );
  384.                
  385.     }
  386.    
  387.    
  388.    
  389.    
  390.    
  391.     private void integrateData()
  392.     {
  393.         for (int i=0; i<xn; i++)
  394.         {
  395.             for (int j=0; j<blueBlocks[i].length; j++)
  396.                 blocks[i][j] = (int) changeBlue(blocks[i][j], blueBlocks[i][j]);
  397.         }
  398.     }
  399.    
  400.    
  401.     private BufferedImage uniteOutput(BufferedImage img)
  402.     {
  403.         int startX = 0, startY = 0;
  404.         for (int i=0; i<blocksNum; i++)
  405.         {
  406.             if (startX>=width)
  407.             {
  408.                 startX = 0;
  409.                 startY += N;
  410.             }
  411.             img.setRGB(startX, startY, N, N, blocks[i], 0, N);
  412.             startX += N;
  413.         }
  414.        
  415.        
  416.         return img;
  417.     }
  418.    
  419.    
  420.    
  421.    
  422.    
  423.    
  424.    
  425.    
  426.    
  427.    
  428.        
  429.     private byte[] stringToBinary(String str)
  430.     {
  431.         byte[] bytes = str.getBytes();
  432.         byte[] binary = new byte[bytes.length*8];
  433.        
  434.         for (int i=0; i<bytes.length; i++)
  435.         {
  436.            int val = bytes[i];
  437.            for (int j = 0; j < 8; j++)
  438.            {
  439.               binary[i*8+j] = (byte) ((val & 128) == 0 ? 0 : 1);
  440.               val <<= 1;
  441.            }
  442.         }
  443.         return binary;
  444.     }
  445.        
  446.     private int getBlue(int z) { return Integer.parseInt( String.format("%32s", Integer.toBinaryString( z ) ).replace(' ', '0').substring(24, 32), 2); }
  447.    
  448.     private long changeBlue(int b, int bb)
  449.     {
  450.         String sb = String.format("%32s", Integer.toBinaryString( b ) ).replace(' ', '0');
  451.         String sbb = String.format("%8s", Integer.toBinaryString( bb ) ).replace(' ', '0');
  452.            
  453.         StringBuilder sBuilder = new StringBuilder(sb);
  454.        
  455.        
  456.         sBuilder = sBuilder.replace(24, 32, sbb);
  457.        
  458.         return Long.parseLong(sBuilder.toString(),2);
  459.     }
  460.    
  461.    
  462. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement