Updated some files, fixed #1, added mimetype recognition for the depth map
This commit is contained in:
parent
18f6e4e13f
commit
34f16eb4f9
8 changed files with 60 additions and 28 deletions
1
src/ArrayUtils.java
Normal file → Executable file
1
src/ArrayUtils.java
Normal file → Executable 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
0
src/Base64Wrapper.java
Normal file → Executable file
11
src/Const.java
Normal file → Executable file
11
src/Const.java
Normal file → Executable 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)
|
||||||
|
@ -82,6 +83,16 @@ public class Const
|
||||||
(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)
|
||||||
* (GImage:Data) (length: 11)
|
* (GImage:Data) (length: 11)
|
||||||
|
|
26
src/DepthMapNeedle.java
Normal file → Executable file
26
src/DepthMapNeedle.java
Normal file → Executable 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
0
src/HexUtil.java
Normal file → Executable file
0
src/IO.java
Normal file → Executable file
0
src/IO.java
Normal file → Executable file
18
src/JPEG.java
Normal file → Executable file
18
src/JPEG.java
Normal file → Executable 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");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -141,6 +147,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
32
src/JPEGUtils.java
Normal file → Executable 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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue