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)
{
if(b == null) return null;
byte[] u = new byte[b.length];
for (int i = 0; i < b.length; i++)
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 STANDARDXMP = "StandardXMP";
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)
@ -81,6 +82,16 @@ public class Const
(byte) 0x68, (byte) 0x3a, (byte) 0x44, (byte) 0x61, (byte) 0x74,
(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)

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

@ -14,13 +14,19 @@ public class DepthMapNeedle
@Override
public byte[] decode(byte[] data)
{
return Base64.getDecoder().decode(data);
if(data != null)
return Base64.getDecoder().decode(data);
else
return null;
}
@Override
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
@ -33,8 +39,8 @@ public class DepthMapNeedle
{
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]);
System.out.println("Info: Depthmap extracted for 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);
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
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);
if (image.injectDepthMap(depthmap))
System.out.println("Depthmap injected into file "+args[i]+".");
System.out.println("Info: Depthmap injected into file "+args[i]+".");
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();
}
}
@ -73,9 +79,9 @@ public class DepthMapNeedle
{
JPEG image = new JPEG(args[i], wrapper);
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
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();
}
}

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.util.Arrays;
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
*/
public boolean exportDepthMap()
{
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");
}
@ -140,6 +146,14 @@ public class JPEG extends Const
{
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

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
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;
}
int o;
@ -26,7 +26,7 @@ public class JPEGUtils extends Const
o = 256 * (data[boundaryPos+2] & 0xFF)+(data[boundaryPos+3] & 0xFF);
} 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();
return -1;
}
@ -93,7 +93,7 @@ public class JPEGUtils extends Const
out = ArrayUtils.concatenate(out, part);
return out;
}
System.err.println("JPEGUtils decorateBlock no valid type entered.");
System.err.println("JPEGUtils.decorateBlock(): No valid type entered.");
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;
}
@ -141,7 +141,7 @@ public class JPEGUtils extends Const
{
byte[] meta = getXMPBlocksContent(data);
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;
}
@ -155,7 +155,7 @@ public class JPEGUtils extends Const
{
byte[] meta = getXMPBlocksContent(data);
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;
}
@ -184,7 +184,7 @@ public class JPEGUtils extends Const
{
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;
} else
{
@ -203,7 +203,7 @@ public class JPEGUtils extends Const
{
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;
} else
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))
{
System.err.println("JPEGUtils getBlockWithoutHeader: Block is no APP1-block");
System.err.println("JPEGUtils.getBlockWithoutHeader(): Block is no APP1-block!");
return null;
} else
{
@ -276,7 +276,7 @@ public class JPEGUtils extends Const
byte[] block = getBlock(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;
}
@ -297,7 +297,7 @@ public class JPEGUtils extends Const
{
byte[] part = JPEGUtils.getBlockWithoutHeader(block, 0);
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);
}
}
@ -355,7 +355,7 @@ public class JPEGUtils extends Const
byte[] block = JPEGUtils.getBlock(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;
}
@ -371,7 +371,7 @@ public class JPEGUtils extends Const
byte[] ext = getExtendedXMPBlockContent(data);
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;
}
@ -503,8 +503,8 @@ public class JPEGUtils extends Const
byte[] out = ArrayUtils.concatenate(pre, value);
out = ArrayUtils.concatenate(out, post);
return out;
} 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(): No closing \" found in data!");
} else System.err.println("JPEGUtils.replace(): Key not found in data!");
return null;
}
}