diff --git a/DepthMapNeedle.jar b/DepthMapNeedle.jar index e85e0d7..e15fc24 100644 Binary files a/DepthMapNeedle.jar and b/DepthMapNeedle.jar differ diff --git a/src/ArrayUtils.java b/src/ArrayUtils.java index 17a8682..8612959 100644 --- a/src/ArrayUtils.java +++ b/src/ArrayUtils.java @@ -1,59 +1,63 @@ - public class ArrayUtils { /** * Return true, if the array part is sub array of src from offset - * @param src array - * @param part array + * + * @param src array + * @param part array * @param offset int * @return true, if part is completely a subarray of src on offset offset, else false */ public static boolean arrayIsPartOfOtherArrayOnOffset(byte[] src, byte[] part, int offset) { - if(offset<0 || part.length+offset > src.length) return false; - for(int i=0; i src.length) return false; + for (int i = 0; i < part.length; i++) { - if(part[i] != src[i+offset]) return false; + if (part[i] != src[i+offset]) return false; } return true; } /** * converts the byte array b into a char array by casting all the bytes into chars + * * @param b byte array * @return char array */ public static char[] bytesToChars(byte[] b) { char[] c = new char[b.length]; - for(int i=0; i>> 24), - (byte)(value >>> 16), - (byte)(value >>> 8), - (byte)value}; + public static final byte[] intToByteArray(int value) + { + return new byte[]{ + (byte) (value >>> 24), + (byte) (value >>> 16), + (byte) (value >>> 8), + (byte) value}; } /** * convert a signed byte array into an unsigned byte array (sort of) + * * @param b byte array of signed bytes * @return byte array of unsigned bytes */ public static byte[] unsign(byte[] b) { byte[] u = new byte[b.length]; - for(int i=0; i show help text - if(args.length==0 || args[0].equals("-h")) help(); - - //export depthmap - if(args.length >= 2 && args[0].equals("-e")) - { - for(int i=1; i show help text + if (args.length == 0 || args[0].equals("-h")) help(); + + //export depthmap + if (args.length >= 2 && args[0].equals("-d")) + { + for (int i = 1; i < args.length; i++) + { + JPEG image = new JPEG(args[i], wrapper); + if (image.exportDepthMap()) + System.out.println("Depthmap extracted for file "+args[i]+"."); else System.err.println("There is no Depthmap in file "+args[i]); } } - + //export source image - else if(args.length >=2 && args[0].equals("-s")) + else if (args.length >= 2 && args[0].equals("-s")) { - for(int i=1; i= 3 && args[0].equals("-i")) + else if (args.length >= 3 && args[0].equals("-D")) { String depthmap = args[1]; - for(int i=2; i= 3 && args[0].equals("-S")) + { + String source = args[1]; + for (int i = 2; i < args.length; i++) + { + JPEG image = new JPEG(args[i], wrapper); + if (image.injectSourceImage(source)) + System.out.println("Source image injected into file "+args[i]+"."); + else + System.err.println("Something went wrong while injecting "+source+" into "+args[i]+".\nRemember: The first argument has to be a jpg and the following arguments must be jpgs shot with the blur function."); image.save(); } } } - + /** * Show help text */ public static void help() { System.out.println("Welcome to DepthMapNeedle!" - + "\nDepthMapNeedle is a tool to inject or extract depth information in form of depthmaps from photos shot using Google Cameras Blur function." - + "\n" - + "\nAvailable Options:" - + "\n'-e .jpg ... .jpg':" - + "\n Extract the depthmap from the specified photo(s). The depthmaps will be stored with the suffix \"_d.png\"." - + "\n'-s .jpg ... .jpg':" - + "\n Extract the unblurred source image from the photo(s). These files will be stored with the suffix \"_s.jpg\"." - + "\n'-i .png .jpg .jpg':" - + "\n Inject a png file as Depthmap into the following specified jpg files." - + "\n'-h':" - + "\n Show this help text."); + +"\nDepthMapNeedle is a tool to inject or extract depth information in form of depthmaps from photos shot using Google Cameras Blur function." + +"\n" + +"\nAvailable Options:" + +"\n'-d .jpg ... .jpg':" + +"\n Extract the depthmap from the specified photo(s). The depthmaps will be stored with the suffix \"_d.png\"." + +"\n'-s .jpg ... .jpg':" + +"\n Extract the unblurred source image from the photo(s). These files will be stored with the suffix \"_s.jpg\"." + +"\n'-D .png .jpg ... .jpg':" + +"\n Inject a png file as Depthmap into the following specified jpg files." + +"\n'-S .jpg .jpg ... .jpg':" + +"\n Inject an unblurred source image into the following specified jpg files. " + +"\n Note: The unblurred source image is a simple jpg file of the same dimensions as the photos." + +"\n'-h':" + +"\n Show this help text."); } } diff --git a/src/HexUtil.java b/src/HexUtil.java index f7dc06e..dd25e3e 100644 --- a/src/HexUtil.java +++ b/src/HexUtil.java @@ -1,5 +1,4 @@ - import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; @@ -7,19 +6,22 @@ public class HexUtil { /** * Print out a byte array in hexadecimal + * * @param bytes array */ public static void printHex(byte[] bytes) { - for(byte b : bytes) System.out.print(byteToHexString(b)); + for (byte b : bytes) System.out.print(byteToHexString(b)); } /** * convert a byte to a hex string + * * @param data array * @return String representation in hex */ - public static String byteToHexString(byte data) { + public static String byteToHexString(byte data) + { StringBuffer buf = new StringBuffer(); buf.append(toHexChar((data >>> 4) & 0x0F)); @@ -27,22 +29,27 @@ public class HexUtil return buf.toString(); } - + /** * convert a integer into a hexadecimal character + * * @param i integer * @return hex char */ - public static char toHexChar(int i) { - if ((0 <= i) && (i <= 9)) { - return (char) ('0' + i); - } else { - return (char) ('a' + (i - 10)); + public static char toHexChar(int i) + { + if ((0 <= i) && (i <= 9)) + { + return (char) ('0'+i); + } else + { + return (char) ('a'+(i-10)); } } - + /** * Generate the md5 digest of the byte array data in hexadecimal + * * @param data array * @return byte array of the md5 digest in hex */ @@ -51,10 +58,10 @@ public class HexUtil try { byte[] md5 = MessageDigest.getInstance("MD5").digest(data); - String m=""; - for(int i=0; i CHUNKSIZE multiple ExtendedXMPBlocks will be generated and concatenated. * Available types: * Const.EXIF, Const.STANDARDXMP, Const.EXTENDEDXMP + * * @param data byte array of data that will be decorated * @param type String declaring the type of header for the block. * @return decorated block @@ -46,49 +46,49 @@ public class JPEGUtils extends Const public static byte[] decorateBlock(byte[] data, String type) { //EXIF Block: 'APP1 + BLOCKLENGTH + EXIF\0\0 + data' - if(type.equals(EXIF)) + if (type.equals(EXIF)) { data = ArrayUtils.concatenate(markEXIF, data); byte[] pre = ArrayUtils.concatenate(markAPP1, genLen(data.length+2)); return ArrayUtils.concatenate(pre, data); } //StandardXMP: 'APP1 + BLOCKLENGTH + http://ns.adobe.com/xap/1.0/\0 + data' - else if(type.equals(STANDARDXMP)) + else if (type.equals(STANDARDXMP)) { data = ArrayUtils.concatenate(markStandardXMP, data); byte[] pre = ArrayUtils.concatenate(markAPP1, genLen(data.length+2)); - return ArrayUtils.concatenate(pre,data); + return ArrayUtils.concatenate(pre, data); } //ExtendedXMP: 'APP1 + BLOCKLENGTH + http://ns.adobe.com/xmp/extension/\0 + MD5 + EXTENDEDLENGTH + EXTENDEDOFFSET + DATAPORTION - else if(type.equals(EXTENDEDXMP)) + else if (type.equals(EXTENDEDXMP)) { byte[] out = new byte[0]; //MD5 checksum is digest of the datacontent byte[] md5 = HexUtil.generateMD5(data); - int i=0; - int blockCount = data.length/CHUNKSIZE; + int i = 0; + int blockCount = data.length / CHUNKSIZE; //decorate blockportions of size CHUNKSIZE - while (i b = new Vector(); - for(int i=0; i