Updated some files, fixed #1, added mimetype recognition for the depth map

This commit is contained in:
VanitasVitae 2015-07-17 20:09:06 +02:00
parent 18f6e4e13f
commit 34f16eb4f9
8 changed files with 60 additions and 28 deletions

1
src/ArrayUtils.java Normal file → Executable file
View File

@ -89,6 +89,7 @@ public class ArrayUtils
*/ */
public static byte[] unsign(byte[] b) public static byte[] unsign(byte[] b)
{ {
if(b == null) return null;
byte[] u = new byte[b.length]; byte[] u = new byte[b.length];
for (int i = 0; i < b.length; i++) for (int i = 0; i < b.length; i++)
u[i] = (byte) (b[i] & 0xFF); u[i] = (byte) (b[i] & 0xFF);

0
src/Base64Wrapper.java Normal file → Executable file
View File

11
src/Const.java Normal file → Executable file
View File

@ -13,6 +13,7 @@ public class Const
public static final String EXIF = "EXIF"; public static final String EXIF = "EXIF";
public static final String STANDARDXMP = "StandardXMP"; public static final String STANDARDXMP = "StandardXMP";
public static final String EXTENDEDXMP = "ExtendedXMP"; public static final String EXTENDEDXMP = "ExtendedXMP";
public static final String mimeJPG = "image/jpeg";
/** /**
* Magical bytes that identify the file as JPG (FF D8) (length: 2) * Magical bytes that identify the file as JPG (FF D8) (length: 2)
@ -81,6 +82,16 @@ public class Const
(byte) 0x68, (byte) 0x3a, (byte) 0x44, (byte) 0x61, (byte) 0x74, (byte) 0x68, (byte) 0x3a, (byte) 0x44, (byte) 0x61, (byte) 0x74,
(byte) 0x61 (byte) 0x61
}; };
/**
* Key for the MIME type of the depth map
* (GDepth:Mime) (length: 11)
*/
public static byte[] keyGDepthMIME = {
(byte) 0x47, (byte) 0x44, (byte) 0x65, (byte) 0x70, (byte) 0x74,
(byte) 0x68, (byte) 0x3a, (byte) 0x4D, (byte) 0x69, (byte) 0x6D,
(byte) 0x65
};
/** /**
* Key for the Base64 encoded unblurred jpg source image (Google camera will combine this with the depth information to render the blurred image) * Key for the Base64 encoded unblurred jpg source image (Google camera will combine this with the depth information to render the blurred image)

26
src/DepthMapNeedle.java Normal file → Executable file
View File

@ -14,13 +14,19 @@ public class DepthMapNeedle
@Override @Override
public byte[] decode(byte[] data) public byte[] decode(byte[] data)
{ {
return Base64.getDecoder().decode(data); if(data != null)
return Base64.getDecoder().decode(data);
else
return null;
} }
@Override @Override
public byte[] encode(byte[] data) public byte[] encode(byte[] data)
{ {
return Base64.getEncoder().encode(data); if(data != null)
return Base64.getEncoder().encode(data);
else
return null;
} }
}; };
//No arguments given or '-h' as first argument -> show help text //No arguments given or '-h' as first argument -> show help text
@ -33,8 +39,8 @@ public class DepthMapNeedle
{ {
JPEG image = new JPEG(args[i], wrapper); JPEG image = new JPEG(args[i], wrapper);
if (image.exportDepthMap()) if (image.exportDepthMap())
System.out.println("Depthmap extracted for file "+args[i]+"."); System.out.println("Info: Depthmap extracted for file "+args[i]+".");
else System.err.println("There is no Depthmap in file "+args[i]); else System.out.println("Warning: There is no Depthmap in file "+args[i]+".");
} }
} }
@ -45,9 +51,9 @@ public class DepthMapNeedle
{ {
JPEG image = new JPEG(args[i], wrapper); JPEG image = new JPEG(args[i], wrapper);
if (image.exportSourceImage()) if (image.exportSourceImage())
System.out.println("Unblurred source image extracted for file "+args[i]+"."); System.out.println("Info: Unblurred source image extracted for file "+args[i]+".");
else else
System.err.println("There is no unblurred source image in file "+args[i]+". Maybe this photo has not been taken with the blur function?"); System.out.println("Warning: There is no unblurred source image in file "+args[i]+". Maybe this photo has not been taken with Google Camera\'s blur function?");
} }
} }
@ -59,9 +65,9 @@ public class DepthMapNeedle
{ {
JPEG image = new JPEG(args[i], wrapper); JPEG image = new JPEG(args[i], wrapper);
if (image.injectDepthMap(depthmap)) if (image.injectDepthMap(depthmap))
System.out.println("Depthmap injected into file "+args[i]+"."); System.out.println("Info: Depthmap injected into file "+args[i]+".");
else else
System.err.println("Something went wrong while injecting "+depthmap+" into "+args[i]+".\nRemember: The first argument has to be a png and the following arguments must be jpgs shot with the blur function."); System.out.println("Warning: Something went wrong while injecting "+depthmap+" into "+args[i]+".\nRemember: The first argument has to be a png and the following arguments must be jpgs shot with the blur function.");
image.save(); image.save();
} }
} }
@ -73,9 +79,9 @@ public class DepthMapNeedle
{ {
JPEG image = new JPEG(args[i], wrapper); JPEG image = new JPEG(args[i], wrapper);
if (image.injectSourceImage(source)) if (image.injectSourceImage(source))
System.out.println("Source image injected into file "+args[i]+"."); System.out.println("Info: Source image injected into file "+args[i]+".");
else 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."); System.out.println("Warning: 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(); image.save();
} }
} }

0
src/HexUtil.java Normal file → Executable file
View File

0
src/IO.java Normal file → Executable file
View File

18
src/JPEG.java Normal file → Executable file
View File

@ -1,5 +1,6 @@
import java.io.File; import java.io.File;
import java.util.Arrays;
public class JPEG extends Const public class JPEG extends Const
{ {
@ -74,14 +75,19 @@ public class JPEG extends Const
} }
/** /**
* extract the depth map from the jpeg and store it in the same location as the jpeg itself but with the suffix _d.png * extract the depth map from the jpeg and store it in the same location as the jpeg itself
* but with the suffix '_d' and filetype suffix (jpg or png)
* *
* @return * @return
*/ */
public boolean exportDepthMap() public boolean exportDepthMap()
{ {
String out = m_Filename; String out = m_Filename;
if (out.endsWith(".jpg") || out.endsWith(".JPG")) out = out.substring(0, out.length()-4); if (out.endsWith(".jpg") || out.endsWith(".JPG"))
out = out.substring(0, out.length()-4);
String mime = extractDepthMapMIMEType();
if(mime != null && mime.equals(Const.mimeJPG))
return this.exportDepthMap(out+"_d.jpg");
return this.exportDepthMap(out+"_d.png"); return this.exportDepthMap(out+"_d.png");
} }
@ -140,6 +146,14 @@ public class JPEG extends Const
{ {
return JPEGUtils.extractDepthMap(m_RawData); return JPEGUtils.extractDepthMap(m_RawData);
} }
public String extractDepthMapMIMEType()
{
byte[] mime = JPEGUtils.extract(m_RawData, Const.keyGDepthMIME);
if (mime != null) return new String(mime);
else
return null;
}
/** /**
* Extract and return the unblurred source image * Extract and return the unblurred source image

32
src/JPEGUtils.java Normal file → Executable file
View File

@ -16,7 +16,7 @@ public class JPEGUtils extends Const
//Check whether entered position is APP1 Marker //Check whether entered position is APP1 Marker
if (!JPEGUtils.isAPP1Marker(data, boundaryPos)) if (!JPEGUtils.isAPP1Marker(data, boundaryPos))
{ {
System.err.println("JPEGUtils blockLength: Block is no APP1 Block!"); System.err.println("JPEGUtils.blockLength(): Block is no APP1 Block!");
return -1; return -1;
} }
int o; int o;
@ -26,7 +26,7 @@ public class JPEGUtils extends Const
o = 256 * (data[boundaryPos+2] & 0xFF)+(data[boundaryPos+3] & 0xFF); o = 256 * (data[boundaryPos+2] & 0xFF)+(data[boundaryPos+3] & 0xFF);
} catch (ArrayIndexOutOfBoundsException e) } catch (ArrayIndexOutOfBoundsException e)
{ {
System.err.println("JPEGUtils blockLength threw ArrayIndexOutOfBoundsException. Maybe the block is cut after APP1 Marker?"); System.err.println("JPEGUtils.blockLength() threw ArrayIndexOutOfBoundsException. Maybe the block is cut after APP1 Marker?");
e.printStackTrace(); e.printStackTrace();
return -1; return -1;
} }
@ -93,7 +93,7 @@ public class JPEGUtils extends Const
out = ArrayUtils.concatenate(out, part); out = ArrayUtils.concatenate(out, part);
return out; return out;
} }
System.err.println("JPEGUtils decorateBlock no valid type entered."); System.err.println("JPEGUtils.decorateBlock(): No valid type entered.");
return null; return null;
} }
@ -124,10 +124,10 @@ public class JPEGUtils extends Const
} }
} }
System.err.println("JPEGUtils extract found end for \""+new String(key)+"\": false"); System.err.println("JPEGUtils.extract() found end of key \""+new String(key)+"\": false");
} }
} }
System.err.println("JPEGUtils extract found start for \""+new String(key)+"\": false"); System.err.println("JPEGUtils.extract() found key \""+new String(key)+"\": false");
return null; return null;
} }
@ -141,7 +141,7 @@ public class JPEGUtils extends Const
{ {
byte[] meta = getXMPBlocksContent(data); byte[] meta = getXMPBlocksContent(data);
byte[] depth = extract(meta, keyGDepthData); byte[] depth = extract(meta, keyGDepthData);
if (depth == null) System.err.println("JPEGUtils extractDepthMap is null"); if (depth == null) System.err.println("JPEGUtils.extractDepthMap() is null!");
return depth; return depth;
} }
@ -155,7 +155,7 @@ public class JPEGUtils extends Const
{ {
byte[] meta = getXMPBlocksContent(data); byte[] meta = getXMPBlocksContent(data);
byte[] src = extract(meta, keyGImageData); byte[] src = extract(meta, keyGImageData);
if (src == null) System.err.println("JPEGUtils extractSourceImage is null"); if (src == null) System.err.println("JPEGUtils.extractSourceImage() is null!");
return src; return src;
} }
@ -184,7 +184,7 @@ public class JPEGUtils extends Const
{ {
if (!JPEGUtils.isAPP1Marker(data, boundary)) if (!JPEGUtils.isAPP1Marker(data, boundary))
{ {
System.err.println("JPEGUtils getBlock: Block is no APP1-block"); System.err.println("JPEGUtils.getBlock(): Block is no APP1-block!");
return data; return data;
} else } else
{ {
@ -203,7 +203,7 @@ public class JPEGUtils extends Const
{ {
if (!JPEGUtils.isAPP1Marker(data, boundary)) if (!JPEGUtils.isAPP1Marker(data, boundary))
{ {
System.err.println("JPEGUtils getBlockWithoutAPP1: Block is no APP1-block"); System.err.println("JPEGUtils.getBlockWithoutAPP1(): Block is no APP1-block!");
return null; return null;
} else } else
return Arrays.copyOfRange(data, boundary+4, boundary+JPEGUtils.readBlockLength(boundary, data)+2); return Arrays.copyOfRange(data, boundary+4, boundary+JPEGUtils.readBlockLength(boundary, data)+2);
@ -221,7 +221,7 @@ public class JPEGUtils extends Const
{ {
if (!JPEGUtils.isAPP1Marker(data, boundary)) if (!JPEGUtils.isAPP1Marker(data, boundary))
{ {
System.err.println("JPEGUtils getBlockWithoutHeader: Block is no APP1-block"); System.err.println("JPEGUtils.getBlockWithoutHeader(): Block is no APP1-block!");
return null; return null;
} else } else
{ {
@ -276,7 +276,7 @@ public class JPEGUtils extends Const
byte[] block = getBlock(data, e); byte[] block = getBlock(data, e);
if (isEXIFBlock(block)) return getBlockWithoutHeader(data, e); if (isEXIFBlock(block)) return getBlockWithoutHeader(data, e);
} }
System.err.println("JPEGUtils getEXIFBlock: No EXIF-block found"); System.err.println("JPEGUtils.getEXIFBlock(): No EXIF-block found!");
return null; return null;
} }
@ -297,7 +297,7 @@ public class JPEGUtils extends Const
{ {
byte[] part = JPEGUtils.getBlockWithoutHeader(block, 0); byte[] part = JPEGUtils.getBlockWithoutHeader(block, 0);
if (part == null) if (part == null)
System.err.println("JPEGUtils getExtendedXMPBlockContent part is null"); System.err.println("JPEGUtils.getExtendedXMPBlockContent(): Part "+e+" is null!");
cont = ArrayUtils.concatenate(cont, part); cont = ArrayUtils.concatenate(cont, part);
} }
} }
@ -355,7 +355,7 @@ public class JPEGUtils extends Const
byte[] block = JPEGUtils.getBlock(data, e); byte[] block = JPEGUtils.getBlock(data, e);
if (JPEGUtils.isStandardXMP(block)) return JPEGUtils.getBlockWithoutHeader(data, e); if (JPEGUtils.isStandardXMP(block)) return JPEGUtils.getBlockWithoutHeader(data, e);
} }
System.err.println("JPEGUtils getStandardXMPBlockContent is null"); System.err.println("JPEGUtils.getStandardXMPBlockContent() is null!");
return null; return null;
} }
@ -371,7 +371,7 @@ public class JPEGUtils extends Const
byte[] ext = getExtendedXMPBlockContent(data); byte[] ext = getExtendedXMPBlockContent(data);
byte[] out = ArrayUtils.concatenate(stand, ext); byte[] out = ArrayUtils.concatenate(stand, ext);
if (out == null) System.err.println("JPEGUtils getXMPBlocksContent is null"); if (out == null) System.err.println("JPEGUtils.getXMPBlocksContent() is null!");
return out; return out;
} }
@ -503,8 +503,8 @@ public class JPEGUtils extends Const
byte[] out = ArrayUtils.concatenate(pre, value); byte[] out = ArrayUtils.concatenate(pre, value);
out = ArrayUtils.concatenate(out, post); out = ArrayUtils.concatenate(out, post);
return out; return out;
} else System.err.println("JPEGUtils replace: No closing \" found in data"); } else System.err.println("JPEGUtils.replace(): No closing \" found in data!");
} else System.err.println("JPEGUtils replace: key not found in data"); } else System.err.println("JPEGUtils.replace(): Key not found in data!");
return null; return null;
} }
} }