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:
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
Post a Comment