java - Steganography, only jpg as input works, when using png the resulting image looks strange -


i built little java program hides messages in image using least significant bit method. works fine when inputting jpg file. output may png or jpg. when inputting png though, result looks stange.

here original , result images respectively:

original image

output image

public abstract class builder{  public static void leastsignificantbitencryption(string imagesource, string message, string newpath) {     bufferedimage image = returnimage(imagesource);     //prepare variables     string[] messagebinstring = null;     string[] pixelbinstring = null;     final byte[] messagebin = message.getbytes(standardcharsets.utf_8);     final byte[] pixelsbin = ((databufferbyte) image.getraster().getdatabuffer()).getdata();     //convert message , image binary string array     try {         messagebinstring = stringtobinarystrings(messagebin);         pixelbinstring = stringtobinarystrings(pixelsbin);     } catch (unsupportedencodingexception e) {         e.printstacktrace();     }     string[] messagebinstringcut = splitin2bit(messagebinstring);   //split message binary 2 bit strings     string[] pixelbinstringnew = pixelbinstring.clone();    //insert 2 bit strings in last 2 bits of bytes bitmap     insert2bit(messagebinstringcut, pixelbinstringnew);     byte[] pixelsbinnew = stringarraytobytearray(pixelbinstringnew);    //convert string array byte array     try {   //create new image out of bitmap         int w = image.getwidth();         int h = image.getheight();         bufferedimage imagenew = new bufferedimage(w, h, bufferedimage.type_3byte_bgr);         imagenew.setdata(raster.createraster(imagenew.getsamplemodel(), new databufferbyte(pixelsbinnew, pixelsbinnew.length), new point()));         file imagefile = new file(newpath);         imageio.write(imagenew, "png", imagefile);     } catch (ioexception e) {         e.printstacktrace();     } }  private static string[] stringtobinarystrings(byte[] messagebin) throws unsupportedencodingexception{     string[] bytes = new string[messagebin.length];     int = 0;     for(byte b : messagebin) {         bytes[i] = string.format("%8s", integer.tobinarystring(b & 0xff)).replace(' ', '0');         i++;     }     return bytes; }  private static string binarystringstostring(string[] messagebin) throws unsupportedencodingexception{     stringbuilder stringbuilder = new stringbuilder();     int = 0;     while(messagebin[i] != null) {         stringbuilder.append((char) integer.parseint(messagebin[i], 2));         i++;     }     return stringbuilder.tostring(); }  private static bufferedimage returnimage(string imagesource) {     try{         try {             return imageio.read(new url(imagesource));         } catch (malformedurlexception e) {             return imageio.read(new file(imagesource));         }     } catch (ioexception ioe) {         ioe.printstacktrace();         return null;     } }  private static byte[] stringarraytobytearray(string[] stringarray) {     byte[] bytearray = new byte[stringarray.length];     for(int = 0; < stringarray.length; i++) {         bytearray[i] = (byte) integer.parseint(stringarray[i], 2);     }     return bytearray; }  private static string[] splitin2bit(string[] inputarray) {     string[] outputarray = new string[inputarray.length * 4];     for(int = 0; < outputarray.length; += 4) {         string[] splitbyte = inputarray[i / 4].split("(?<=\\g..)");         outputarray[i] = splitbyte[0];         outputarray[i + 1] = splitbyte[1];         outputarray[i + 2] = splitbyte[2];         outputarray[i + 3] = splitbyte[3];     }     return outputarray; }  private static string[] insert2bit(string[] twobitarray, string[] insertarray) {     for(int = 0; < twobitarray.length; i++) {         insertarray[i] = insertarray[i].substring(0, 6) + twobitarray[i];     }     return insertarray; }  } 

also, testclass:

public class test {      public static void main(string[] args) {         builder.leastsignificantbitencryption("imagepath or url", "message", "path image containing message");         builder.leastsignificantbitdecryption("path of image containing message", "path txt containing output");     } } 

the error originates fact png image has channel transparency. system.out.println(pixelsbin.length); returns 338355 bytes jpg , 451140 bytes png.

the simplest solution create appropriate imagenew depending on format file. example,

int w = image.getwidth(); int h = image.getheight(); bufferedimage imagenew = null; if (imagesource.matches(".*jpg$")) {     imagenew = new bufferedimage(w, h, bufferedimage.type_3byte_bgr); } else if (imagesource.matches(".*png$")) {     imagenew = new bufferedimage(w, h, bufferedimage.type_4byte_abgr); } else {     // whatever } imagenew.setdata(raster.createraster(imagenew.getsamplemodel(), new databufferbyte(pixelsbinnew, pixelsbinnew.length), new point())); 

however, have aware message not embedded in both types in same pixels. byte array of 3-channel image (no transparency) goes this

first-pixel-blue, first-pixel-green, first-pixel-red, second-pixel-blue, etc 

while 4-channel image

first-pixel-alpha, first-pixel-blue, first-pixel-green, first-pixel-red, second-pixel-alpha, etc 

if care detail, might interested in removing alpha channel png first, you're working 3-channel images.


Comments

Popular posts from this blog

sql server - Cannot query correctly (MSSQL - PHP - JSON) -

php - trouble displaying mysqli database results in correct order -

C++ Linked List -