SHARE
TWEET

Encoding arbitrary files in PNG's

a guest Nov 12th, 2013 174 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. package com.ignatieff.tepng;
  2.  
  3. import java.awt.image.BufferedImage;
  4. import java.io.File;
  5. import java.io.FileInputStream;
  6. import java.io.FileNotFoundException;
  7. import java.io.FileOutputStream;
  8. import java.io.IOException;
  9.  
  10. import javax.imageio.ImageIO;
  11.  
  12. public class Encoder {
  13.        
  14.         BufferedImage img;
  15.        
  16.         private static byte[] empty = { 0x00, 0x00, 0x00, 0x00, 0x00 };
  17.        
  18.         public Encoder(BufferedImage image){
  19.                 img = image;
  20.         }
  21.        
  22.         public Encoder(String path) throws IOException{
  23.                 this(loadImage(path));
  24.         }
  25.        
  26.         private static BufferedImage loadImage(String path) throws IOException{
  27.                 File f = new File(path);
  28.                 BufferedImage i = ImageIO.read(f);
  29.                 return i;
  30.         }
  31.        
  32.         public void saveImage(String path) throws IOException{
  33.                 File f = new File(path);
  34.                 ImageIO.write(img, "png", f);
  35.         }
  36.        
  37.         public static int getBit(int input, int bit){
  38.                 if((input & (1 << bit)) != 0)return 1;
  39.                 return 0;
  40.         }
  41.        
  42.         private boolean writeChar(char c, int x, int y){
  43.                 int i = translateChar(c);
  44.                 if(i==-1)return false;
  45.                 encodeData(i, x, y);
  46.                 return true;
  47.         }
  48.        
  49.         private char readChar(int x, int y){
  50.                 return translateInt(decodeData(x,y));
  51.         }
  52.        
  53.         public void encodeMessage(String message){
  54.                 encodeMessage(message, 1);
  55.         }
  56.        
  57.         public void encodeMessage(String message, String key){
  58.                 encodeMessage(message, key.hashCode());
  59.         }
  60.        
  61.         public String getMessage(){
  62.                 return getMessage(1);
  63.         }
  64.        
  65.         public String getMessage(String key){
  66.                 return getMessage(key.hashCode());
  67.         }
  68.        
  69.         public void encodeMessage(String message, int key){
  70.                 int max = img.getHeight() * img.getWidth();
  71.                 if(message.length()+5 >= max){return;}
  72.                 Group g = new Group(max, key);
  73.                 char[] c = (message+"'.!.'").toCharArray();
  74.                 int x = 0, y = 0;
  75.                 for(int i=0;i<c.length;i++){
  76.                         if(writeChar(c[i],x,y)){
  77.                                 x+=g.PRIME;
  78.                                 while(x>=img.getWidth()){x-=img.getWidth();y++;}
  79.                                 if(y>=img.getHeight()){y%=img.getHeight();}
  80.                         }
  81.                 }
  82.         }
  83.        
  84.         public String getMessage(int key){
  85.                 String r = "";
  86.                 Group g = new Group(img.getHeight() * img.getWidth(), key);
  87.                 int x=0, y=0;
  88.                 while(!r.contains("'.!.'")){
  89.                         while(x>=img.getWidth()){x-=img.getWidth();y++;}
  90.                         if(y>=img.getHeight()){y%=img.getHeight();}
  91.                         r+=readChar(x,y);
  92.                         x+=g.PRIME;
  93.                 }
  94.                 return r.substring(0,r.length()-5);
  95.         }
  96.        
  97.         private int decodeData(int x, int y){
  98.                 int argb = img.getRGB(x, y);
  99.                
  100.                 int r = (argb)&0xFF;
  101.                 int g = (argb>>8)&0xFF;
  102.                 int b = (argb>>16)&0xFF;
  103.                
  104.                 int rDec = (getBit(r, 1) << 1) | getBit(r, 0);
  105.                 int gDec = getBit(g, 0);
  106.                 int bDec = (getBit(b, 1) << 1) | getBit(b, 0);
  107.                
  108.                 int data = (bDec << 3)|(gDec << 2)|rDec;
  109.                
  110.                 return data;
  111.         }
  112.        
  113.         private int getBit(byte b, int bit){
  114.                 if((b & (1 << bit))!=0)return 1;return 0;
  115.         }
  116.        
  117.         private int[] convertToBits(byte[] bytes){
  118.                 int a = bytes.length*8;
  119.                 int[] r = new int[a];
  120.                 for(int i=0; i<bytes.length; i++){
  121.                         for(int j=0; j<8; j++){
  122.                                 r[a-((bytes.length-1-i)*8+j)-1] = getBit(bytes[i], j);
  123.                         }
  124.                 }
  125.                 return r;
  126.         }
  127.        
  128.         public byte[] readBytes(int x, int y){
  129.                 int[] bits = new int[40];
  130.                 for(int i=0; i<8; i++){
  131.                         int a;
  132.                         if(x+i<img.getWidth()){
  133.                                 a = decodeData(x+i, y);
  134.                         }else{
  135.                                 a = decodeData((x+i)-img.getWidth(), y+1);
  136.                         }
  137.                         for(int j=0; j<5; j++){
  138.                                 bits[i*5+j]=getBit(a, 4-j);
  139.                         }
  140.                 }
  141.                 return convertToBytes(bits);
  142.         }
  143.        
  144.         private byte[] convertToBytes(int[] bits){
  145.                 if(bits.length%8!=0)return null;
  146.                 int p = bits.length/8;
  147.                 byte[] r = new byte[p];
  148.                 for(int i=0; i<p; i++){
  149.                         int a = 0;
  150.                         for(int j=0; j<8; j++){
  151.                                 a |= bits[i*8+j];
  152.                                 if(j!=7)a<<=1;
  153.                         }
  154.                         r[i] = (byte)a;
  155.                 }
  156.                 return r;
  157.         }
  158.        
  159.         private byte[] appendBytes(byte[] b){
  160.                 byte[] r = b;
  161.                 while(b.length%5!=0){
  162.                         byte[] q = new byte[r.length+1];
  163.                         for(int i=0; i<r.length; i++){
  164.                                 q[i] = r[i];
  165.                         }
  166.                         q[r.length] = 0x00;
  167.                         r=q;
  168.                 }
  169.                 return r;
  170.         }
  171.        
  172.         private byte[] appendBytes(byte[] b, byte[] c){
  173.                 byte[] newArray = new byte[b.length+c.length];
  174.                 for(int i=0; i<b.length; i++){
  175.                         newArray[i] = b[i];
  176.                 }
  177.                 for(int i=0; i<c.length; i++){
  178.                         newArray[b.length+i] = c[i];
  179.                 }
  180.                 return newArray;
  181.         }
  182.        
  183.         private boolean isNull(byte[] b){
  184.                 for(int i=0; i<b.length; i++){
  185.                         if(b[i] != 0)return false;
  186.                 }
  187.                 return true;
  188.         }
  189.        
  190.         public void encodeFile(String path, String key) throws IOException{
  191.                 encodeFile(path, key.hashCode());
  192.         }
  193.        
  194.         public void encodeFile(String path, int key) throws IOException{
  195.                 encodeFile(readFile(path), key);
  196.         }
  197.        
  198.         public void saveContentFile(String path, String key) throws IOException{
  199.                 saveContentFile(path, key.hashCode());
  200.         }
  201.        
  202.         public void saveContentFile(String path, int key) throws IOException{
  203.                 File f = new File(path);
  204.                 byte[] data = readFile(key);
  205.                 FileOutputStream fos = new FileOutputStream(f);
  206.                 fos.write(data);
  207.                 fos.close();
  208.         }
  209.        
  210.         private byte[] readFile(String path) throws IOException{
  211.                 File f = new File(path);
  212.                 FileInputStream fin = new FileInputStream(f);
  213.                 byte fileContent[] = new byte[(int)f.length()];
  214.             fin.read(fileContent);
  215.             fin.close();
  216.             return fileContent;
  217.         }
  218.        
  219.         private void printByte(byte[] b){
  220.                 String s = "{ '";
  221.                 for(int i=0; i<b.length; i++){
  222.                         s+=(int)b[i] + "', '";
  223.                 }
  224.                 System.out.println( s.substring(0, s.length()-3) + " }" );
  225.         }
  226.        
  227.         public byte[] readFile(int key){
  228.                 byte[] bytes = new byte[0];
  229.                 Group g = new Group((img.getWidth()*img.getHeight())/8, key);
  230.                 boolean isDone = false;
  231.                 int x = 0, y = 0;
  232.                 while(!isDone){
  233.                         //System.out.println("reading from ("+x+", "+y+")");
  234.                         byte[] next = readBytes(x*8,y*8);
  235.                         //printByte(next);
  236.                         bytes = appendBytes(bytes, next);
  237.                         if(isNull(next)){isDone=true;}
  238.                         x+=g.PRIME;
  239.  
  240.                         while(x>=img.getWidth()/8){x-=img.getWidth()/8;y++;}
  241.                         if(y>=img.getHeight()/8){y%=img.getHeight()/8;}
  242.                 }
  243.                 return bytes;
  244.         }
  245.        
  246.         public void encodeFile(byte[] bytes, String key){
  247.                 encodeFile(bytes, key.hashCode());
  248.         }
  249.        
  250.         public void encodeFile(byte[] bytes, int key){
  251.                 if(bytes.length >= (img.getWidth() * img.getHeight())/5)return;
  252.                 byte[] e = appendBytes(appendBytes(bytes, empty));
  253.                 int max  = e.length/5;
  254.                 int size = (img.getWidth()*img.getHeight())/8; 
  255.                 Group g = new Group(size, key);
  256.                 int x=0, y=0;
  257.                 for(int i=0; i<max; i++){
  258.                         encodeBytes(subarray(e,i*5,5),x*8,y*8);
  259.                         x+=g.PRIME;
  260.                         while(x>=img.getWidth()/8){x-=img.getWidth()/8;y++;}
  261.                         if(y>=img.getHeight()/8){y%=img.getHeight()/8;}
  262.                 }
  263.         }
  264.        
  265.         private byte[] subarray(byte[] array, int start, int len){
  266.                 byte[] newArray = new byte[len];
  267.                 for(int i=0; i<len; i++){
  268.                         newArray[i] = array[start+i];
  269.                 }
  270.                 return newArray;
  271.         }
  272.        
  273.         private void encodeBytes(byte[] bytes, int x, int y){
  274.                 if(bytes.length!=5){return;}
  275.                 int[] bits = convertToBits(bytes);
  276.                 for(int i=0; i<8; i++){
  277.                         int a = 0;
  278.                         for(int j=0; j<5; j++){
  279.                                 a |= bits[i*5+j];
  280.                                 if(j!=4)a<<=1;
  281.                         }
  282.                         if(x+i<img.getWidth()){
  283.                                 encodeData(a, x+i, y);
  284.                         }else{
  285.                                 encodeData(a, (x+i)-img.getWidth(), y+1);
  286.                         }
  287.                 }
  288.         }
  289.        
  290.         private void encodeData(int data, int x, int y){
  291.                
  292.                 if(data>=32){return;}
  293.                
  294.                 int rEnc = (getBit(data, 1) << 1)|getBit(data, 0);
  295.                 int gEnc = getBit(data, 2);
  296.                 int bEnc = (getBit(data, 4) << 1)|getBit(data, 3);
  297.                 int argb = img.getRGB(x, y);
  298.  
  299.                 int r = (((argb)&0xFF) >> 2) << 2;
  300.                 int g = (((argb>>8)&0xFF) >> 1) << 1;
  301.                 int b = (((argb>>16)&0xFF) >> 2) << 2;
  302.                
  303.                 int newR = r | rEnc;
  304.                 int newG = g | gEnc;
  305.                 int newB = b | bEnc;
  306.                
  307.                 int newARGB = (newB << 16)|(newG << 8)|newR;
  308.                
  309.                 img.setRGB(x, y, newARGB);
  310.         }
  311.        
  312.         public static char translateInt(int i){
  313.                 if(i <= 25)return (char)(i+65);
  314.                 switch(i){
  315.                         case 26:
  316.                                 return ' ';
  317.                         case 27:
  318.                                 return '.';
  319.                         case 28:
  320.                                 return ',';
  321.                         case 29:
  322.                                 return '!';
  323.                         case 30:
  324.                                 return '?';
  325.                         case 31:
  326.                                 return '\'';
  327.                 }
  328.                 return '#';
  329.         }
  330.        
  331.         public static int translateChar(char c){
  332.                 if((int)c >= 65 && (int)c <=90){
  333.                         return (int)c-65;
  334.                 }
  335.                 if((int)c >= 97 && (int)c <=122){
  336.                         return (int)c-97;
  337.                 }
  338.                 switch(c){
  339.                         case ' ':
  340.                                 return 26;
  341.                         case '.':
  342.                                 return 27;
  343.                         case ',':
  344.                                 return 28;
  345.                         case '!':
  346.                                 return 29;
  347.                         case '?':
  348.                                 return 30;
  349.                         case '\'':
  350.                                 return 31;
  351.                 }
  352.                 return -1;
  353.         }
  354.        
  355. }
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
Not a member of Pastebin yet?
Sign Up, it unlocks many cool features!
 
Top